Add kubernetes volume snapshot support

- Add a new client in probe/kubernetes/client.go
  which will be used to fetch details of Snapshot CRD
- Visualize VolumeSnapshot and VolumeSnapshotData
- Add adjacency between PV and VolumeSnapshot
- Add adjacency between VolumeSnapshot and VolumeSnapshotData
- Add snapshot filter to hide and show snapshots

Signed-off-by: Akash Srivastava <akash.srivastava@openebs.io>
This commit is contained in:
Akash Srivastava
2018-10-16 01:04:44 +05:30
parent bcaf0ae4b1
commit 81a682893f
17 changed files with 363 additions and 11 deletions
+10 -1
View File
@@ -10,6 +10,7 @@ import (
"time"
"context"
"github.com/gorilla/mux"
log "github.com/sirupsen/logrus"
@@ -55,6 +56,14 @@ var (
{Value: "hide", Label: "Hide storage", filter: render.IsPodComponent, filterPseudo: false},
},
}
snapshotFilter = APITopologyOptionGroup{
ID: "snapshot",
Default: "hide",
Options: []APITopologyOption{
{Value: "show", Label: "Show snapshots", filter: nil, filterPseudo: false},
{Value: "hide", Label: "Hide snapshots", filter: render.IsNonSnapshotComponent, filterPseudo: false},
},
}
)
// namespaceFilters generates a namespace selector option group based on the given namespaces
@@ -237,7 +246,7 @@ func MakeRegistry() *Registry {
renderer: render.PodRenderer,
Name: "Pods",
Rank: 3,
Options: []APITopologyOptionGroup{storageFilter, unmanagedFilter},
Options: []APITopologyOptionGroup{snapshotFilter, storageFilter, unmanagedFilter},
HideIfEmpty: true,
},
APITopologyDesc{
+2 -4
View File
@@ -6,10 +6,8 @@ import { enterEdge, leaveEdge } from '../actions/app-actions';
import { encodeIdAttribute, decodeIdAttribute } from '../utils/dom-utils';
function isStorageComponent(id) {
if (id === '<persistent_volume>' || id === '<storage_class>' || id === '<persistent_volume_claim>') {
return true;
}
return false;
const storageComponents = ['<persistent_volume>', '<storage_class>', '<persistent_volume_claim>', '<volume_snapshot>', '<volume_snapshot_data>'];
return storageComponents.includes(id);
}
// getAdjacencyClass takes id which contains information about edge as a topology
+41 -2
View File
@@ -8,6 +8,8 @@ import (
"github.com/weaveworks/common/backoff"
snapshotv1 "github.com/openebs/k8s-snapshot-client/snapshot/pkg/apis/volumesnapshot/v1"
snapshot "github.com/openebs/k8s-snapshot-client/snapshot/pkg/client/clientset/versioned"
log "github.com/sirupsen/logrus"
apiappsv1beta1 "k8s.io/api/apps/v1beta1"
apibatchv1 "k8s.io/api/batch/v1"
@@ -41,6 +43,8 @@ type Client interface {
WalkPersistentVolumes(f func(PersistentVolume) error) error
WalkPersistentVolumeClaims(f func(PersistentVolumeClaim) error) error
WalkStorageClasses(f func(StorageClass) error) error
WalkVolumeSnapshots(f func(VolumeSnapshot) error) error
WalkVolumeSnapshotData(f func(VolumeSnapshotData) error) error
WatchPods(f func(Event, Pod))
@@ -53,6 +57,7 @@ type Client interface {
type client struct {
quit chan struct{}
client *kubernetes.Clientset
snapshotClient *snapshot.Clientset
podStore cache.Store
serviceStore cache.Store
deploymentStore cache.Store
@@ -65,6 +70,8 @@ type client struct {
persistentVolumeStore cache.Store
persistentVolumeClaimStore cache.Store
storageClassStore cache.Store
volumeSnapshotStore cache.Store
volumeSnapshotDataStore cache.Store
podWatchesMutex sync.Mutex
podWatches []func(Event, Pod)
@@ -133,9 +140,15 @@ func NewClient(config ClientConfig) (Client, error) {
return nil, err
}
sc, err := snapshot.NewForConfig(restConfig)
if err != nil {
return nil, err
}
result := &client{
quit: make(chan struct{}),
client: c,
quit: make(chan struct{}),
client: c,
snapshotClient: sc,
}
result.podStore = NewEventStore(result.triggerPodWatches, cache.MetaNamespaceKeyFunc)
@@ -152,6 +165,8 @@ func NewClient(config ClientConfig) (Client, error) {
result.persistentVolumeStore = result.setupStore("persistentvolumes")
result.persistentVolumeClaimStore = result.setupStore("persistentvolumeclaims")
result.storageClassStore = result.setupStore("storageclasses")
result.volumeSnapshotStore = result.setupStore("volumesnapshots")
result.volumeSnapshotDataStore = result.setupStore("volumesnapshotdatas")
return result, nil
}
@@ -204,6 +219,10 @@ func (c *client) clientAndType(resource string) (rest.Interface, interface{}, er
return c.client.BatchV1().RESTClient(), &apibatchv1.Job{}, nil
case "statefulsets":
return c.client.AppsV1beta1().RESTClient(), &apiappsv1beta1.StatefulSet{}, nil
case "volumesnapshots":
return c.snapshotClient.VolumesnapshotV1().RESTClient(), &snapshotv1.VolumeSnapshot{}, nil
case "volumesnapshotdatas":
return c.snapshotClient.VolumesnapshotV1().RESTClient(), &snapshotv1.VolumeSnapshotData{}, nil
case "cronjobs":
ok, err := c.isResourceSupported(c.client.BatchV1beta1().RESTClient().APIVersion(), resource)
if err != nil {
@@ -388,6 +407,26 @@ func (c *client) WalkNamespaces(f func(NamespaceResource) error) error {
return nil
}
func (c *client) WalkVolumeSnapshots(f func(VolumeSnapshot) error) error {
for _, m := range c.volumeSnapshotStore.List() {
volumeSnapshot := m.(*snapshotv1.VolumeSnapshot)
if err := f(NewVolumeSnapshot(volumeSnapshot)); err != nil {
return err
}
}
return nil
}
func (c *client) WalkVolumeSnapshotData(f func(VolumeSnapshotData) error) error {
for _, m := range c.volumeSnapshotDataStore.List() {
volumeSnapshotData := m.(*snapshotv1.VolumeSnapshotData)
if err := f(NewVolumeSnapshotData(volumeSnapshotData)); err != nil {
return err
}
}
return nil
}
func (c *client) GetLogs(namespaceID, podID string, containerNames []string) (io.ReadCloser, error) {
readClosersWithLabel := map[io.ReadCloser]string{}
for _, container := range containerNames {
+51
View File
@@ -34,6 +34,8 @@ const (
VolumeName = report.KubernetesVolumeName
Provisioner = report.KubernetesProvisioner
StorageDriver = report.KubernetesStorageDriver
VolumeSnapshotName = report.KubernetesVolumeSnapshotName
SnapshotData = report.KubernetesSnapshotData
)
// Exposed for testing
@@ -130,6 +132,19 @@ var (
Provisioner: {ID: Provisioner, Label: "Provisioner", From: report.FromLatest, Priority: 3},
}
VolumeSnapshotMetadataTemplates = report.MetadataTemplates{
NodeType: {ID: NodeType, Label: "Type", From: report.FromLatest, Priority: 1},
Namespace: {ID: Namespace, Label: "Name", From: report.FromLatest, Priority: 2},
VolumeClaim: {ID: VolumeClaim, Label: "Persistent volume claim", From: report.FromLatest, Priority: 3},
SnapshotData: {ID: SnapshotData, Label: "Volume snapshot data", From: report.FromLatest, Priority: 4},
}
VolumeSnapshotDataMetadataTemplates = report.MetadataTemplates{
NodeType: {ID: NodeType, Label: "Type", From: report.FromLatest, Priority: 1},
VolumeName: {ID: VolumeName, Label: "Persistent volume", From: report.FromLatest, Priority: 2},
VolumeSnapshotName: {ID: VolumeSnapshotName, Label: "Volume snapshot", From: report.FromLatest, Priority: 3},
}
TableTemplates = report.TableTemplates{
LabelPrefix: {
ID: LabelPrefix,
@@ -300,6 +315,14 @@ func (r *Reporter) Report() (report.Report, error) {
if err != nil {
return result, err
}
volumeSnapshotTopology, _, err := r.volumeSnapshotTopology()
if err != nil {
return result, err
}
volumeSnapshotDataTopology, _, err := r.volumeSnapshotDataTopology()
if err != nil {
return result, err
}
result.Pod = result.Pod.Merge(podTopology)
result.Service = result.Service.Merge(serviceTopology)
result.Host = result.Host.Merge(hostTopology)
@@ -311,6 +334,8 @@ func (r *Reporter) Report() (report.Report, error) {
result.PersistentVolume = result.PersistentVolume.Merge(persistentVolumeTopology)
result.PersistentVolumeClaim = result.PersistentVolumeClaim.Merge(persistentVolumeClaimTopology)
result.StorageClass = result.StorageClass.Merge(storageClassTopology)
result.VolumeSnapshot = result.VolumeSnapshot.Merge(volumeSnapshotTopology)
result.VolumeSnapshotData = result.VolumeSnapshotData.Merge(volumeSnapshotDataTopology)
return result, nil
}
@@ -459,6 +484,32 @@ func (r *Reporter) storageClassTopology() (report.Topology, []StorageClass, erro
return result, storageClasses, err
}
func (r *Reporter) volumeSnapshotTopology() (report.Topology, []VolumeSnapshot, error) {
volumeSnapshots := []VolumeSnapshot{}
result := report.MakeTopology().
WithMetadataTemplates(VolumeSnapshotMetadataTemplates).
WithTableTemplates(TableTemplates)
err := r.client.WalkVolumeSnapshots(func(p VolumeSnapshot) error {
result.AddNode(p.GetNode(r.probeID))
volumeSnapshots = append(volumeSnapshots, p)
return nil
})
return result, volumeSnapshots, err
}
func (r *Reporter) volumeSnapshotDataTopology() (report.Topology, []VolumeSnapshotData, error) {
volumeSnapshotData := []VolumeSnapshotData{}
result := report.MakeTopology().
WithMetadataTemplates(VolumeSnapshotDataMetadataTemplates).
WithTableTemplates(TableTemplates)
err := r.client.WalkVolumeSnapshotData(func(p VolumeSnapshotData) error {
result.AddNode(p.GetNode(r.probeID))
volumeSnapshotData = append(volumeSnapshotData, p)
return nil
})
return result, volumeSnapshotData, err
}
type labelledChild interface {
Labels() map[string]string
AddParent(string, string)
+6
View File
@@ -164,6 +164,12 @@ func (c *mockClient) WalkPersistentVolumeClaims(f func(kubernetes.PersistentVolu
func (c *mockClient) WalkStorageClasses(f func(kubernetes.StorageClass) error) error {
return nil
}
func (c *mockClient) WalkVolumeSnapshots(f func(kubernetes.VolumeSnapshot) error) error {
return nil
}
func (c *mockClient) WalkVolumeSnapshotData(f func(kubernetes.VolumeSnapshotData) error) error {
return nil
}
func (*mockClient) WatchPods(func(kubernetes.Event, kubernetes.Pod)) {}
func (c *mockClient) GetLogs(namespaceID, podName string, _ []string) (io.ReadCloser, error) {
r, ok := c.logs[namespaceID+";"+podName]
+39
View File
@@ -0,0 +1,39 @@
package kubernetes
import (
snapshotv1 "github.com/openebs/k8s-snapshot-client/snapshot/pkg/apis/volumesnapshot/v1"
"github.com/weaveworks/scope/report"
)
// SnapshotPVName is the label key which provides PV name
const (
SnapshotPVName = "SnapshotMetadata-PVName"
)
// VolumeSnapshot represent kubernetes VolumeSnapshot interface
type VolumeSnapshot interface {
Meta
GetNode(probeID string) report.Node
}
// volumeSnapshot represents kubernetes volume snapshots
type volumeSnapshot struct {
*snapshotv1.VolumeSnapshot
Meta
}
// NewVolumeSnapshot returns new Volume Snapshot type
func NewVolumeSnapshot(p *snapshotv1.VolumeSnapshot) VolumeSnapshot {
return &volumeSnapshot{VolumeSnapshot: p, Meta: meta{p.ObjectMeta}}
}
// GetNode returns VolumeSnapshot as Node
func (p *volumeSnapshot) GetNode(probeID string) report.Node {
return p.MetaNode(report.MakeVolumeSnapshotNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,
NodeType: "Volume Snapshot",
VolumeClaim: p.Spec.PersistentVolumeClaimName,
SnapshotData: p.Spec.SnapshotDataName,
VolumeName: p.GetLabels()[SnapshotPVName],
})
}
+33
View File
@@ -0,0 +1,33 @@
package kubernetes
import (
snapshotv1 "github.com/openebs/k8s-snapshot-client/snapshot/pkg/apis/volumesnapshot/v1"
"github.com/weaveworks/scope/report"
)
// VolumeSnapshotData represent kubernetes VolumeSnapshotData interface
type VolumeSnapshotData interface {
Meta
GetNode(probeID string) report.Node
}
// volumeSnapshotData represents kubernetes volume snapshot data
type volumeSnapshotData struct {
*snapshotv1.VolumeSnapshotData
Meta
}
// NewVolumeSnapshotData returns new Volume Snapshot Data type
func NewVolumeSnapshotData(p *snapshotv1.VolumeSnapshotData) VolumeSnapshotData {
return &volumeSnapshotData{VolumeSnapshotData: p, Meta: meta{p.ObjectMeta}}
}
// GetNode returns VolumeSnapshotData as Node
func (p *volumeSnapshotData) GetNode(probeID string) report.Node {
return p.MetaNode(report.MakeVolumeSnapshotDataNodeID(p.UID())).WithLatests(map[string]string{
report.ControlProbeID: probeID,
NodeType: "Volume Snapshot Data",
VolumeName: p.Spec.PersistentVolumeRef.Name,
VolumeSnapshotName: p.Spec.VolumeSnapshotRef.Name,
})
}
+14
View File
@@ -206,6 +206,20 @@ var nodeSummaryGroupSpecs = []struct {
Columns: []Column{},
},
},
{
topologyID: report.VolumeSnapshot,
NodeSummaryGroup: NodeSummaryGroup{
Label: "Volume Snapshots",
Columns: []Column{},
},
},
{
topologyID: report.VolumeSnapshotData,
NodeSummaryGroup: NodeSummaryGroup{
Label: "Volume Snapshot Data",
Columns: []Column{},
},
},
}
func children(rc RenderContext, n report.Node) []NodeSummaryGroup {
+14
View File
@@ -84,6 +84,8 @@ var renderers = map[string]func(BasicNodeSummary, report.Node) BasicNodeSummary{
report.PersistentVolume: persistentVolumeNodeSummary,
report.PersistentVolumeClaim: persistentVolumeClaimNodeSummary,
report.StorageClass: storageClassNodeSummary,
report.VolumeSnapshot: volumeSnapshotNodeSummary,
report.VolumeSnapshotData: volumeSnapshotDataNodeSummary,
}
// For each report.Topology, map to a 'primary' API topology. This can then be used in a variety of places.
@@ -104,6 +106,8 @@ var primaryAPITopology = map[string]string{
report.PersistentVolume: "pods",
report.PersistentVolumeClaim: "pods",
report.StorageClass: "pods",
report.VolumeSnapshot: "pods",
report.VolumeSnapshotData: "pods",
}
// MakeBasicNodeSummary returns a basic summary of a node, if
@@ -394,6 +398,16 @@ func storageClassNodeSummary(base BasicNodeSummary, n report.Node) BasicNodeSumm
return base
}
func volumeSnapshotNodeSummary(base BasicNodeSummary, n report.Node) BasicNodeSummary {
base = addKubernetesLabelAndRank(base, n)
return base
}
func volumeSnapshotDataNodeSummary(base BasicNodeSummary, n report.Node) BasicNodeSummary {
base = addKubernetesLabelAndRank(base, n)
return base
}
// groupNodeSummary renders the summary for a group node. n.Topology is
// expected to be of the form: group:container:hostname
func groupNodeSummary(base BasicNodeSummary, r report.Report, n report.Node) BasicNodeSummary {
+20 -2
View File
@@ -44,6 +44,8 @@ var (
persistentVolume = node(report.PersistentVolume)
persistentVolumeClaim = node(report.PersistentVolumeClaim)
StorageClass = node(report.StorageClass)
volumeSnapshot = node(report.VolumeSnapshot)
volumeSnapshotData = node(report.VolumeSnapshotData)
UnknownPseudoNode1ID = render.MakePseudoNodeID(fixture.UnknownClient1IP)
UnknownPseudoNode2ID = render.MakePseudoNodeID(fixture.UnknownClient3IP)
@@ -282,7 +284,7 @@ var (
kubernetes.StorageClassName: "standard",
}).WithChild(report.MakeNode(fixture.PersistentVolumeNodeID).WithTopology(report.PersistentVolume)),
fixture.PersistentVolumeNodeID: persistentVolume(fixture.PersistentVolumeNodeID).
fixture.PersistentVolumeNodeID: persistentVolume(fixture.PersistentVolumeNodeID, fixture.VolumeSnapshotNodeID).
WithLatests(map[string]string{
kubernetes.Name: "pongvolume",
kubernetes.Namespace: "ping",
@@ -291,7 +293,7 @@ var (
kubernetes.AccessModes: "ReadWriteOnce",
kubernetes.StorageClassName: "standard",
kubernetes.StorageDriver: "iSCSI",
}),
}).WithChild(report.MakeNode(fixture.VolumeSnapshotNodeID).WithTopology(report.VolumeSnapshot)),
fixture.StorageClassNodeID: StorageClass(fixture.StorageClassNodeID, fixture.PersistentVolumeClaimNodeID).
WithLatests(map[string]string{
@@ -299,6 +301,22 @@ var (
kubernetes.Provisioner: "pong",
}).WithChild(report.MakeNode(fixture.PersistentVolumeClaimNodeID).WithTopology(report.PersistentVolumeClaim)),
fixture.VolumeSnapshotNodeID: volumeSnapshot(fixture.VolumeSnapshotNodeID, fixture.VolumeSnapshotDataNodeID).
WithLatests(map[string]string{
kubernetes.Name: "vs-1234",
kubernetes.Namespace: "ping",
kubernetes.VolumeClaim: "pvc-6124",
kubernetes.SnapshotData: "vsd-1234",
kubernetes.VolumeName: "pongvolume",
}).WithChild(report.MakeNode(fixture.VolumeSnapshotDataNodeID).WithTopology(report.VolumeSnapshotData)),
fixture.VolumeSnapshotDataNodeID: volumeSnapshotData(fixture.VolumeSnapshotDataNodeID).
WithLatests(map[string]string{
kubernetes.Name: "vsd-1234",
kubernetes.VolumeName: "pongvolume",
kubernetes.VolumeSnapshotName: "vs-1234",
}),
UnmanagedServerID: unmanagedServerNode,
render.IncomingInternetID: theIncomingInternetNode(fixture.ServerPodNodeID),
render.OutgoingInternetID: theOutgoingInternetNode,
+8
View File
@@ -138,6 +138,14 @@ func IsPodComponent(node report.Node) bool {
return ok
}
// IsNonSnapshotComponent checks whether given node is everything but Volume Snapshot, Volume Snapshot Data
func IsNonSnapshotComponent(node report.Node) bool {
if node.Topology == "volume_snapshot" || node.Topology == "volume_snapshot_data" {
return false
}
return true
}
// connected returns the node ids of nodes which have edges to/from
// them, excluding edges to/from themselves.
func connected(nodes report.Nodes) map[string]struct{} {
+51 -2
View File
@@ -11,6 +11,8 @@ var KubernetesVolumesRenderer = MakeReduce(
VolumesRenderer,
PodToVolumeRenderer,
PVCToStorageClassRenderer,
PVToSnapshotRenderer,
VolumeSnapshotRenderer,
)
// VolumesRenderer is a Renderer which produces a renderable kubernetes PV & PVC
@@ -25,13 +27,12 @@ func (v volumesRenderer) Render(rpt report.Report) Nodes {
nodes := make(report.Nodes)
for id, n := range rpt.PersistentVolumeClaim.Nodes {
volume, _ := n.Latest.Lookup(kubernetes.VolumeName)
for pvNodeID, p := range rpt.PersistentVolume.Nodes {
for _, p := range rpt.PersistentVolume.Nodes {
volumeName, _ := p.Latest.Lookup(kubernetes.Name)
if volume == volumeName {
n.Adjacency = n.Adjacency.Add(p.ID)
n.Children = n.Children.Add(p)
}
nodes[pvNodeID] = p
}
nodes[id] = n
}
@@ -86,3 +87,51 @@ func (v pvcToStorageClassRenderer) Render(rpt report.Report) Nodes {
}
return Nodes{Nodes: nodes}
}
//PVToSnapshotRenderer is a Renderer which produces a renderable kubernetes PV
var PVToSnapshotRenderer = pvToSnapshotRenderer{}
//pvToSnapshotRenderer is a Renderer to render PV & Snapshot.
type pvToSnapshotRenderer struct{}
//Render renders the PV & Snapshot nodes with adjacency.
func (v pvToSnapshotRenderer) Render(rpt report.Report) Nodes {
nodes := make(report.Nodes)
for pvNodeID, p := range rpt.PersistentVolume.Nodes {
volumeName, _ := p.Latest.Lookup(kubernetes.Name)
for _, volumeSnapshotNode := range rpt.VolumeSnapshot.Nodes {
snapshotPVName, _ := volumeSnapshotNode.Latest.Lookup(kubernetes.VolumeName)
if volumeName == snapshotPVName {
p.Adjacency = p.Adjacency.Add(volumeSnapshotNode.ID)
p.Children = p.Children.Add(volumeSnapshotNode)
}
}
nodes[pvNodeID] = p
}
return Nodes{Nodes: nodes}
}
// VolumeSnapshotRenderer is a renderer which produces a renderable Kubernetes Volume Snapshot and Volume Snapshot Data
var VolumeSnapshotRenderer = volumeSnapshotRenderer{}
// volumeSnapshotRenderer is a render to volume snapshot & volume snapshot data
type volumeSnapshotRenderer struct{}
// Render renders the volumeSnapshots & volumeSnapshotData with adjacency
// It checks for the volumeSnapshotData name in volumeSnapshot, adjacency is created by matching the volumeSnapshotData name.
func (v volumeSnapshotRenderer) Render(rpt report.Report) Nodes {
nodes := make(report.Nodes)
for volumeSnapshotID, volumeSnapshotNode := range rpt.VolumeSnapshot.Nodes {
snapshotData, _ := volumeSnapshotNode.Latest.Lookup(kubernetes.SnapshotData)
for volumeSnapshotDataID, volumeSnapshotDataNode := range rpt.VolumeSnapshotData.Nodes {
snapshotDataName, _ := volumeSnapshotDataNode.Latest.Lookup(kubernetes.Name)
if snapshotDataName == snapshotData {
volumeSnapshotNode.Adjacency = volumeSnapshotNode.Adjacency.Add(volumeSnapshotDataNode.ID)
volumeSnapshotNode.Children = volumeSnapshotNode.Children.Add(volumeSnapshotDataNode)
}
nodes[volumeSnapshotDataID] = volumeSnapshotDataNode
}
nodes[volumeSnapshotID] = volumeSnapshotNode
}
return Nodes{Nodes: nodes}
}
+2
View File
@@ -35,4 +35,6 @@ var (
SelectPersistentVolume = TopologySelector(report.PersistentVolume)
SelectPersistentVolumeClaim = TopologySelector(report.PersistentVolumeClaim)
SelectStorageClass = TopologySelector(report.StorageClass)
SelectVolumeSnapshot = TopologySelector(report.VolumeSnapshot)
SelectVolumeSnapshotData = TopologySelector(report.VolumeSnapshotData)
)
+12
View File
@@ -175,6 +175,18 @@ var (
// ParseStorageClassNodeID parses a storage class node ID
ParseStorageClassNodeID = parseSingleComponentID("storage_class")
// MakeVolumeSnapshotNodeID produces a volume snapshot node ID from its composite parts.
MakeVolumeSnapshotNodeID = makeSingleComponentID("volume_snapshot")
// ParseVolumeSnapshotNodeID parses a volume snapshot node ID
ParseVolumeSnapshotNodeID = parseSingleComponentID("volume_snapshot")
// MakeVolumeSnapshotDataNodeID produces a volume snapshot data node ID from its composite parts.
MakeVolumeSnapshotDataNodeID = makeSingleComponentID("volume_snapshot_data")
// ParseVolumeSnapshotDataNodeID parses a volume snapshot data node ID
ParseVolumeSnapshotDataNodeID = parseSingleComponentID("volume_snapshot_data")
)
// makeSingleComponentID makes a single-component node id encoder
+4
View File
@@ -81,6 +81,8 @@ const (
KubernetesVolumeName = "kubernetes_volume_name"
KubernetesProvisioner = "kubernetes_provisioner"
KubernetesStorageDriver = "kubernetes_storage_driver"
KubernetesVolumeSnapshotName = "kubernetes_volume_snapshot_name"
KubernetesSnapshotData = "kuberneets_snapshot_data"
// probe/awsecs
ECSCluster = "ecs_cluster"
ECSCreatedAt = "ecs_created_at"
@@ -116,6 +118,8 @@ var commonKeys = map[string]string{
PersistentVolume: PersistentVolume,
PersistentVolumeClaim: PersistentVolumeClaim,
StorageClass: StorageClass,
VolumeSnapshot: VolumeSnapshot,
VolumeSnapshotData: VolumeSnapshotData,
HostNodeID: HostNodeID,
ControlProbeID: ControlProbeID,
+24
View File
@@ -31,6 +31,8 @@ const (
PersistentVolume = "persistent_volume"
PersistentVolumeClaim = "persistent_volume_claim"
StorageClass = "storage_class"
VolumeSnapshot = "volume_snapshot"
VolumeSnapshotData = "volume_snapshot_data"
// Shapes used for different nodes
Circle = "circle"
@@ -72,6 +74,8 @@ var topologyNames = []string{
PersistentVolume,
PersistentVolumeClaim,
StorageClass,
VolumeSnapshot,
VolumeSnapshotData,
}
// Report is the core data type. It's produced by probes, and consumed and
@@ -172,6 +176,12 @@ type Report struct {
// Metadata is limited for now, more to come later.
StorageClass Topology
// VolumeSnapshot represent all Kubernetes Volume Snapshots on hosts running probes.
VolumeSnapshot Topology
// VolumeSnapshotData represent all Kubernetes Volume Snapshot Data on hosts running probes.
VolumeSnapshotData Topology
DNS DNSRecords
// Sampling data for this report.
@@ -277,6 +287,16 @@ func MakeReport() Report {
WithShape(StorageSheet).
WithLabel("storage class", "storage classes"),
VolumeSnapshot: MakeTopology().
WithShape(DottedCylinder).
WithTag(Camera).
WithLabel("volume snapshot", "volume snapshots"),
VolumeSnapshotData: MakeTopology().
WithShape(Cylinder).
WithTag(Camera).
WithLabel("volume snapshot data", "volume snapshot data"),
DNS: DNSRecords{},
Sampling: Sampling{},
@@ -389,6 +409,10 @@ func (r *Report) topology(name string) *Topology {
return &r.PersistentVolumeClaim
case StorageClass:
return &r.StorageClass
case VolumeSnapshot:
return &r.VolumeSnapshot
case VolumeSnapshotData:
return &r.VolumeSnapshotData
}
return nil
}
+32
View File
@@ -107,6 +107,10 @@ var (
PersistentVolumeClaimNodeID = report.MakePersistentVolumeClaimNodeID(PersistentVolumeClaimUID)
StorageClassUID = "sc1234"
StorageClassNodeID = report.MakeStorageClassNodeID(StorageClassUID)
VolumeSnapshotUID = "vs1234"
VolumeSnapshotNodeID = report.MakeVolumeSnapshotNodeID(VolumeSnapshotUID)
VolumeSnapshotDataUID = "vsd1234"
VolumeSnapshotDataNodeID = report.MakeVolumeSnapshotDataNodeID(VolumeSnapshotDataUID)
ClientProcess1CPUMetric = report.MakeSingletonMetric(Now.Add(-1*time.Second), 0.01)
ClientProcess1MemoryMetric = report.MakeSingletonMetric(Now.Add(-2*time.Second), 0.02)
@@ -396,6 +400,34 @@ var (
WithTopology(report.StorageClass),
},
}.WithShape(report.StorageSheet).WithLabel("storage class", "storage classes"),
VolumeSnapshot: report.Topology{
Nodes: report.Nodes{
VolumeSnapshotNodeID: report.MakeNodeWith(
VolumeSnapshotNodeID, map[string]string{
kubernetes.Name: "vs-1234",
kubernetes.Namespace: "ping",
kubernetes.VolumeClaim: "pvc-6124",
kubernetes.SnapshotData: "vsd-1234",
kubernetes.VolumeName: "pongvolume",
}).
WithTopology(report.VolumeSnapshot),
},
}.WithShape(report.DottedCylinder).WithLabel("volume snapshot", "volume snapshots").
WithTag(report.Camera),
VolumeSnapshotData: report.Topology{
Nodes: report.Nodes{
VolumeSnapshotDataNodeID: report.MakeNodeWith(
VolumeSnapshotDataNodeID, map[string]string{
kubernetes.Name: "vsd-1234",
kubernetes.VolumeName: "pongvolume",
kubernetes.VolumeSnapshotName: "vs-1234",
}).
WithTopology(report.VolumeSnapshotData),
},
}.WithShape(report.Cylinder).WithLabel("volume snapshot data", "volume snapshot data").
WithTag(report.Camera),
Sampling: report.Sampling{
Count: 1024,
Total: 4096,