mirror of
https://github.com/weaveworks/scope.git
synced 2026-07-17 04:19:32 +00:00
Simplify volume rendering code in render
- Remove the complex volume rendering code. - Remove volume specific code from Transform. - Rename filtering methods - Remove extra params from PV, PVC nodes to make table view look good. Signed-off-by: Satyam Zode <satyam.zode@openebs.io>
This commit is contained in:
@@ -35,7 +35,6 @@ const (
|
||||
ecsTasksID = "ecs-tasks"
|
||||
ecsServicesID = "ecs-services"
|
||||
swarmServicesID = "swarm-services"
|
||||
persistentVolumesID = "persistent-volumes"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -52,8 +51,8 @@ var (
|
||||
ID: "storage",
|
||||
Default: "hide",
|
||||
Options: []APITopologyOption{
|
||||
{Value: "show", Label: "Show Storage", filter: render.IsStorageComponent, filterPseudo: false},
|
||||
{Value: "hide", Label: "Hide Storage", filter: render.IsNotStorageComponent, filterPseudo: false},
|
||||
{Value: "show", Label: "Show Storage", filter: render.IsVolumesComponent, filterPseudo: false},
|
||||
{Value: "hide", Label: "Hide Storage", filter: render.IsPodComponent, filterPseudo: false},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
@@ -8,7 +8,9 @@ import (
|
||||
// PersistentVolume represent kubernetes PersistentVolume interface
|
||||
type PersistentVolume interface {
|
||||
Meta
|
||||
GetNode(probeID string) report.Node
|
||||
GetNode() report.Node
|
||||
GetAccessMode() string
|
||||
GetVolume() string
|
||||
}
|
||||
|
||||
// persistentVolume represents kubernetes persistent volume
|
||||
@@ -22,16 +24,34 @@ func NewPersistentVolume(p *apiv1.PersistentVolume) PersistentVolume {
|
||||
return &persistentVolume{PersistentVolume: p, Meta: meta{p.ObjectMeta}}
|
||||
}
|
||||
|
||||
// GetAccessMode returns access mode associated with PV
|
||||
func (p *persistentVolume) GetAccessMode() string {
|
||||
var accessMode string
|
||||
|
||||
if len(p.Spec.AccessModes) > 0 {
|
||||
// A volume can only be mounted using one access mode at a time,
|
||||
//even if it supports many.
|
||||
accessMode = string(p.Spec.AccessModes[0])
|
||||
}
|
||||
return accessMode
|
||||
}
|
||||
|
||||
// GetVolume returns volume name
|
||||
func (p *persistentVolume) GetVolume() string {
|
||||
var volume string
|
||||
if p.Spec.ClaimRef != nil {
|
||||
volume = p.Spec.ClaimRef.Name
|
||||
}
|
||||
return volume
|
||||
}
|
||||
|
||||
// GetNode returns Persistent Volume as Node
|
||||
func (p *persistentVolume) GetNode(probeID string) report.Node {
|
||||
func (p *persistentVolume) GetNode() report.Node {
|
||||
return p.MetaNode(report.MakePersistentVolumeNodeID(p.UID())).WithLatests(map[string]string{
|
||||
report.ControlProbeID: probeID,
|
||||
NodeType: "Persistent Volume",
|
||||
VolumeClaim: p.Spec.ClaimRef.Name,
|
||||
StorageClassName: p.Spec.StorageClassName,
|
||||
Status: string(p.Status.Phase),
|
||||
AccessModes: string(p.Spec.AccessModes[0]),
|
||||
ReclaimPolicy: string(p.Spec.PersistentVolumeReclaimPolicy),
|
||||
Message: p.Status.Message,
|
||||
NodeType: "Persistent Volume",
|
||||
VolumeClaim: p.GetVolume(),
|
||||
StorageClassName: p.Spec.StorageClassName,
|
||||
Status: string(p.Status.Phase),
|
||||
AccessModes: p.GetAccessMode(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const (
|
||||
type PersistentVolumeClaim interface {
|
||||
Meta
|
||||
Selector() (labels.Selector, error)
|
||||
GetNode(probeID string) report.Node
|
||||
GetNode() report.Node
|
||||
GetStorageClass() string
|
||||
}
|
||||
|
||||
@@ -48,14 +48,12 @@ func (p *persistentVolumeClaim) GetStorageClass() string {
|
||||
}
|
||||
|
||||
// GetNode returns Persistent Volume Claim as Node
|
||||
func (p *persistentVolumeClaim) GetNode(probeID string) report.Node {
|
||||
func (p *persistentVolumeClaim) GetNode() report.Node {
|
||||
return p.MetaNode(report.MakePersistentVolumeClaimNodeID(p.UID())).WithLatests(map[string]string{
|
||||
report.ControlProbeID: probeID,
|
||||
NodeType: "Persistent Volume Claim",
|
||||
Status: string(p.Status.Phase),
|
||||
VolumeName: p.Spec.VolumeName,
|
||||
AccessModes: string(p.Spec.AccessModes[0]),
|
||||
StorageClassName: p.GetStorageClass(),
|
||||
NodeType: "Persistent Volume Claim",
|
||||
Status: string(p.Status.Phase),
|
||||
VolumeName: p.Spec.VolumeName,
|
||||
StorageClassName: p.GetStorageClass(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func (p *pod) RestartCount() uint {
|
||||
}
|
||||
|
||||
func (p *pod) VolumeClaimName() string {
|
||||
claimName := ""
|
||||
var claimName string
|
||||
for _, volume := range p.Spec.Volumes {
|
||||
if volume.VolumeSource.PersistentVolumeClaim != nil {
|
||||
claimName = volume.VolumeSource.PersistentVolumeClaim.ClaimName
|
||||
@@ -92,7 +92,10 @@ func (p *pod) GetNode(probeID string) report.Node {
|
||||
IP: p.Status.PodIP,
|
||||
report.ControlProbeID: probeID,
|
||||
RestartCount: strconv.FormatUint(uint64(p.RestartCount()), 10),
|
||||
VolumeClaim: p.VolumeClaimName(),
|
||||
}
|
||||
|
||||
if p.VolumeClaimName() != "" {
|
||||
latests[VolumeClaim] = p.VolumeClaimName()
|
||||
}
|
||||
|
||||
if p.Pod.Spec.HostNetwork {
|
||||
|
||||
@@ -429,7 +429,7 @@ func (r *Reporter) persistentVolumeTopology() (report.Topology, []PersistentVolu
|
||||
WithMetadataTemplates(PersistentVolumeMetadataTemplates).
|
||||
WithTableTemplates(TableTemplates)
|
||||
err := r.client.WalkPersistentVolumes(func(p PersistentVolume) error {
|
||||
result.AddNode(p.GetNode(r.probeID))
|
||||
result.AddNode(p.GetNode())
|
||||
persistentVolumes = append(persistentVolumes, p)
|
||||
return nil
|
||||
})
|
||||
@@ -442,7 +442,7 @@ func (r *Reporter) persistentVolumeClaimTopology() (report.Topology, []Persisten
|
||||
WithMetadataTemplates(PersistentVolumeClaimMetadataTemplates).
|
||||
WithTableTemplates(TableTemplates)
|
||||
err := r.client.WalkPersistentVolumeClaims(func(p PersistentVolumeClaim) error {
|
||||
result.AddNode(p.GetNode(r.probeID))
|
||||
result.AddNode(p.GetNode())
|
||||
persistentVolumeClaims = append(persistentVolumeClaims, p)
|
||||
return nil
|
||||
})
|
||||
@@ -455,7 +455,7 @@ func (r *Reporter) storageClassTopology() (report.Topology, []StorageClass, erro
|
||||
WithMetadataTemplates(StorageClassMetadataTemplates).
|
||||
WithTableTemplates(TableTemplates)
|
||||
err := r.client.WalkStorageClasses(func(p StorageClass) error {
|
||||
result.AddNode(p.GetNode(r.probeID))
|
||||
result.AddNode(p.GetNode())
|
||||
storageClasses = append(storageClasses, p)
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
// StorageClass represent kubernetes StorageClass interface
|
||||
type StorageClass interface {
|
||||
Meta
|
||||
GetNode(probeID string) report.Node
|
||||
GetNode() report.Node
|
||||
}
|
||||
|
||||
// storageClass represents kubernetes storage classes
|
||||
@@ -23,11 +23,10 @@ func NewStorageClass(p *storagev1.StorageClass) StorageClass {
|
||||
}
|
||||
|
||||
// GetNode returns StorageClass as Node
|
||||
func (p *storageClass) GetNode(probeID string) report.Node {
|
||||
func (p *storageClass) GetNode() report.Node {
|
||||
return p.MetaNode(report.MakeStorageClassNodeID(p.UID())).WithLatests(map[string]string{
|
||||
report.ControlProbeID: probeID,
|
||||
NodeType: "Storage Class",
|
||||
Name: p.GetName(),
|
||||
Provisioner: p.Provisioner,
|
||||
NodeType: "Storage Class",
|
||||
Name: p.GetName(),
|
||||
Provisioner: p.Provisioner,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@ import (
|
||||
|
||||
// Exported for testing.
|
||||
var (
|
||||
circle = "circle"
|
||||
square = "square"
|
||||
heptagon = "heptagon"
|
||||
hexagon = "hexagon"
|
||||
cloud = "cloud"
|
||||
cylinder = "cylinder"
|
||||
circle = "circle"
|
||||
square = "square"
|
||||
heptagon = "heptagon"
|
||||
hexagon = "hexagon"
|
||||
cloud = "cloud"
|
||||
cylinder = "cylinder"
|
||||
dottedcylinder = "dottedcylinder"
|
||||
storagesheet = "storagesheet"
|
||||
|
||||
// Helper to make a report.node with some common options
|
||||
node = func(topology string) func(id string, adjacent ...string) report.Node {
|
||||
@@ -41,6 +43,7 @@ var (
|
||||
hostNode = node(report.Host)
|
||||
persistentVolume = node(report.PersistentVolume)
|
||||
persistentVolumeClaim = node(report.PersistentVolumeClaim)
|
||||
StorageClass = node(report.StorageClass)
|
||||
|
||||
UnknownPseudoNode1ID = render.MakePseudoNodeID(fixture.UnknownClient1IP)
|
||||
UnknownPseudoNode2ID = render.MakePseudoNodeID(fixture.UnknownClient3IP)
|
||||
@@ -269,6 +272,32 @@ var (
|
||||
RenderedContainers[fixture.ServerContainerNodeID],
|
||||
)),
|
||||
|
||||
fixture.PersistentVolumeClaimNodeID: persistentVolumeClaim(fixture.PersistentVolumeClaimNodeID, fixture.PersistentVolumeNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "pvc-6124",
|
||||
kubernetes.Namespace: "ping",
|
||||
kubernetes.Status: "bound",
|
||||
kubernetes.VolumeName: "pongvolume",
|
||||
kubernetes.AccessModes: "ReadWriteOnce",
|
||||
kubernetes.StorageClassName: "standard",
|
||||
}).WithChild(report.MakeNode(fixture.PersistentVolumeNodeID).WithTopology(report.PersistentVolume)),
|
||||
|
||||
fixture.PersistentVolumeNodeID: persistentVolume(fixture.PersistentVolumeNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "pongvolume",
|
||||
kubernetes.Namespace: "ping",
|
||||
kubernetes.Status: "bound",
|
||||
kubernetes.VolumeClaim: "pvc-6124",
|
||||
kubernetes.AccessModes: "ReadWriteOnce",
|
||||
kubernetes.StorageClassName: "standard",
|
||||
}),
|
||||
|
||||
fixture.StorageClassNodeID: StorageClass(fixture.StorageClassNodeID, fixture.PersistentVolumeClaimNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "standard",
|
||||
kubernetes.Provisioner: "pong",
|
||||
}).WithChild(report.MakeNode(fixture.PersistentVolumeClaimNodeID).WithTopology(report.PersistentVolumeClaim)),
|
||||
|
||||
UnmanagedServerID: unmanagedServerNode,
|
||||
render.IncomingInternetID: theIncomingInternetNode(fixture.ServerPodNodeID),
|
||||
render.OutgoingInternetID: theOutgoingInternetNode,
|
||||
@@ -327,36 +356,6 @@ var (
|
||||
render.IncomingInternetID: theIncomingInternetNode(fixture.ServerHostNodeID),
|
||||
render.OutgoingInternetID: theOutgoingInternetNode,
|
||||
}
|
||||
|
||||
RenderedPersistentVolume = report.Nodes{
|
||||
fixture.ClientPodNodeID: pod(fixture.ClientPodNodeID, fixture.PersistentVolumeClaimNodeID, fixture.ServerPodNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "pong-a",
|
||||
kubernetes.Namespace: "ping",
|
||||
kubernetes.State: "running",
|
||||
kubernetes.VolumeClaim: "pvc-6124",
|
||||
}).WithChild(report.MakeNode(fixture.PersistentVolumeClaimNodeID).WithTopology(report.Pod)),
|
||||
|
||||
fixture.PersistentVolumeClaimNodeID: persistentVolumeClaim(fixture.PersistentVolumeClaimNodeID, fixture.PersistentVolumeNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "pvc-6124",
|
||||
kubernetes.Namespace: "ping",
|
||||
kubernetes.Status: "bound",
|
||||
kubernetes.VolumeName: "pongvolume",
|
||||
kubernetes.AccessModes: "ReadWriteOnce",
|
||||
kubernetes.StorageClassName: "standard",
|
||||
}).WithChild(report.MakeNode(fixture.PersistentVolumeNodeID).WithTopology(report.PersistentVolume)),
|
||||
|
||||
fixture.PersistentVolumeNodeID: persistentVolume(fixture.PersistentVolumeNodeID).
|
||||
WithLatests(map[string]string{
|
||||
kubernetes.Name: "pongvolume",
|
||||
kubernetes.Namespace: "ping",
|
||||
kubernetes.Status: "bound",
|
||||
kubernetes.VolumeClaim: "pvc-6124",
|
||||
kubernetes.AccessModes: "ReadWriteOnce",
|
||||
kubernetes.StorageClassName: "standard",
|
||||
}),
|
||||
}
|
||||
)
|
||||
|
||||
func newu64(value uint64) *uint64 { return &value }
|
||||
|
||||
@@ -80,10 +80,7 @@ func (f FilterFunc) Transform(nodes Nodes) Nodes {
|
||||
newAdjacency = newAdjacency.Add(dstID)
|
||||
}
|
||||
}
|
||||
claimName, ok := node.Latest.Lookup(kubernetes.VolumeClaim)
|
||||
if claimName == "" || !ok {
|
||||
node.Adjacency = newAdjacency
|
||||
}
|
||||
node.Adjacency = newAdjacency
|
||||
output[id] = node
|
||||
}
|
||||
|
||||
@@ -131,8 +128,8 @@ func IsConnected(node report.Node) bool {
|
||||
return ok
|
||||
}
|
||||
|
||||
// IsStorageComponent check whether given node is PV, PVC, SC or not
|
||||
func IsStorageComponent(node report.Node) bool {
|
||||
// IsVolumesComponent check whether given node is PV, PVC, SC or not
|
||||
func IsVolumesComponent(node report.Node) bool {
|
||||
var storageComponent bool
|
||||
if node.Topology == "persistent_volume" || node.Topology == "persistent_volume_claim" || node.Topology == "storage_class" {
|
||||
storageComponent = true
|
||||
@@ -150,8 +147,8 @@ func IsStorageComponent(node report.Node) bool {
|
||||
return storageComponent
|
||||
}
|
||||
|
||||
// IsNotStorageComponent check whether given node is PV, PVC, SC or not
|
||||
func IsNotStorageComponent(node report.Node) bool {
|
||||
// IsPodComponent check whether given node is everything but PV, PVC, SC
|
||||
func IsPodComponent(node report.Node) bool {
|
||||
var ok bool
|
||||
ok = true
|
||||
if node.Topology == "persistent_volume" || node.Topology == "persistent_volume_claim" || node.Topology == "storage_class" {
|
||||
|
||||
@@ -5,116 +5,84 @@ import (
|
||||
"github.com/weaveworks/scope/report"
|
||||
)
|
||||
|
||||
// ConnectionStorageJoin returns connectionStorageJoin object
|
||||
func ConnectionStorageJoin(toPV func(report.Node) []string, topology string) Renderer {
|
||||
return connectionStorageJoin{toPV: toPV, topology: topology}
|
||||
}
|
||||
// KubernetesVolumesRenderer is a Renderer which combines all Kubernetes
|
||||
// volumes components such as stateful Pods, Persistent Volume, Persistent Volume Claim, Storage Class.
|
||||
var KubernetesVolumesRenderer = MakeReduce(
|
||||
VolumesRenderer,
|
||||
PodToVolumeRenderer,
|
||||
PVCToStorageClassRenderer,
|
||||
)
|
||||
|
||||
// connectionStorageJoin holds the information about mapping of storage components
|
||||
// along with TopologySelector
|
||||
type connectionStorageJoin struct {
|
||||
toPV func(report.Node) []string
|
||||
topology string
|
||||
}
|
||||
// VolumesRenderer is a Renderer which produces a renderable kubernetes PV & PVC
|
||||
// graph by merging the pods graph and the Persistent Volume topology.
|
||||
var VolumesRenderer = volumesRenderer{}
|
||||
|
||||
func (c connectionStorageJoin) Render(rpt report.Report) Nodes {
|
||||
inputNodes := TopologySelector(c.topology).Render(rpt).Nodes
|
||||
// volumesRenderer is a Renderer to render PV & PVC nodes.
|
||||
type volumesRenderer struct{}
|
||||
|
||||
var pvcNodes = map[string][]string{}
|
||||
for _, n := range inputNodes {
|
||||
pvName := c.toPV(n)
|
||||
for _, name := range pvName {
|
||||
pvcNodes[name] = append(pvcNodes[name], n.ID)
|
||||
}
|
||||
}
|
||||
|
||||
return MapStorageEndpoints(
|
||||
func(m report.Node) []string {
|
||||
pvName, ok := m.Latest.Lookup(kubernetes.Name)
|
||||
if !ok {
|
||||
return []string{""}
|
||||
// Render renders PV & PVC nodes along with adjacency
|
||||
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 {
|
||||
volumeName, _ := p.Latest.Lookup(kubernetes.Name)
|
||||
if volume == volumeName {
|
||||
n.Adjacency = n.Adjacency.Add(p.ID)
|
||||
n.Children = n.Children.Add(p)
|
||||
}
|
||||
id := pvcNodes[pvName]
|
||||
return id
|
||||
}, c.topology).Render(rpt)
|
||||
nodes[pvNodeID] = p
|
||||
}
|
||||
nodes[id] = n
|
||||
}
|
||||
return Nodes{Nodes: nodes}
|
||||
}
|
||||
|
||||
// Map2PVName accepts PV Node and returns Volume name associated with PV Node.
|
||||
func Map2PVName(m report.Node) []string {
|
||||
pvName, ok := m.Latest.Lookup(kubernetes.VolumeName)
|
||||
scName, ok1 := m.Latest.Lookup(kubernetes.StorageClassName)
|
||||
if !ok {
|
||||
pvName = ""
|
||||
}
|
||||
if !ok1 {
|
||||
scName = ""
|
||||
}
|
||||
return []string{pvName, scName}
|
||||
}
|
||||
// PodToVolumeRenderer is a Renderer which produces a renderable kubernetes Pod
|
||||
// graph by merging the pods graph and the Persistent Volume Claim topology.
|
||||
// Pods having persistent volumes are rendered.
|
||||
var PodToVolumeRenderer = podToVolumesRenderer{}
|
||||
|
||||
// Map2PVCName returns pvc name
|
||||
func Map2PVCName(m report.Node) []string {
|
||||
pvcName, ok := m.Latest.Lookup(kubernetes.VolumeClaim)
|
||||
if !ok {
|
||||
pvcName = ""
|
||||
}
|
||||
return []string{pvcName}
|
||||
}
|
||||
// VolumesRenderer is a Renderer to render Pods & PVCs.
|
||||
type podToVolumesRenderer struct{}
|
||||
|
||||
// Map2PVNode returns pv node ID
|
||||
func Map2PVNode(n report.Node) []string {
|
||||
if pvNodeID, ok := n.Latest.Lookup(report.MakePersistentVolumeNodeID(n.ID)); ok {
|
||||
return []string{pvNodeID}
|
||||
}
|
||||
return []string{""}
|
||||
}
|
||||
|
||||
type storageEndpointMapFunc func(report.Node) []string
|
||||
|
||||
// mapStorageEndpoints is the Renderer for rendering storage components together.
|
||||
type mapStorageEndpoints struct {
|
||||
f storageEndpointMapFunc
|
||||
topology string
|
||||
}
|
||||
|
||||
// MapStorageEndpoints instantiates mapStorageEndpoints and returns same
|
||||
func MapStorageEndpoints(f storageEndpointMapFunc, topology string) Renderer {
|
||||
return mapStorageEndpoints{f: f, topology: topology}
|
||||
}
|
||||
|
||||
func (e mapStorageEndpoints) Render(rpt report.Report) Nodes {
|
||||
var endpoints Nodes
|
||||
if e.topology == report.PersistentVolumeClaim {
|
||||
endpoints = SelectPersistentVolume.Render(rpt)
|
||||
endpoints.Merge(SelectStorageClass.Render(rpt))
|
||||
}
|
||||
if e.topology == report.Pod {
|
||||
endpoints = SelectPersistentVolumeClaim.Render(rpt)
|
||||
}
|
||||
ret := newJoinResults(TopologySelector(e.topology).Render(rpt).Nodes)
|
||||
|
||||
for _, n := range endpoints.Nodes {
|
||||
if id := e.f(n); len(id) > 0 {
|
||||
for _, nodeID := range id {
|
||||
if nodeID != "" {
|
||||
ret.addChild(n, nodeID, e.topology)
|
||||
}
|
||||
// Render renders the Pod nodes having volumes adjacency.
|
||||
func (v podToVolumesRenderer) Render(rpt report.Report) Nodes {
|
||||
nodes := make(report.Nodes)
|
||||
for podID, podNode := range rpt.Pod.Nodes {
|
||||
ClaimName, _ := podNode.Latest.Lookup(kubernetes.VolumeClaim)
|
||||
for _, pvcNode := range rpt.PersistentVolumeClaim.Nodes {
|
||||
pvcName, _ := pvcNode.Latest.Lookup(kubernetes.Name)
|
||||
if pvcName == ClaimName {
|
||||
podNode.Adjacency = podNode.Adjacency.Add(pvcNode.ID)
|
||||
podNode.Children = podNode.Children.Add(pvcNode)
|
||||
}
|
||||
}
|
||||
nodes[podID] = podNode
|
||||
}
|
||||
if e.topology == report.PersistentVolumeClaim {
|
||||
ret.storageResult(endpoints)
|
||||
endpoints = SelectStorageClass.Render(rpt)
|
||||
for _, n := range endpoints.Nodes {
|
||||
if id := e.f(n); len(id) > 0 {
|
||||
for _, nodeID := range id {
|
||||
if nodeID != "" {
|
||||
ret.addChild(n, nodeID, e.topology)
|
||||
}
|
||||
}
|
||||
return Nodes{Nodes: nodes}
|
||||
}
|
||||
|
||||
// PVCToStorageClassRenderer is a Renderer which produces a renderable kubernetes PVC
|
||||
// & Storage class graph.
|
||||
var PVCToStorageClassRenderer = pvcToStorageClassRenderer{}
|
||||
|
||||
// pvcToStorageClassRenderer is a Renderer to render PVC & StorageClass.
|
||||
type pvcToStorageClassRenderer struct{}
|
||||
|
||||
// Render renders the PVC & Storage Class nodes with adjacency.
|
||||
func (v pvcToStorageClassRenderer) Render(rpt report.Report) Nodes {
|
||||
nodes := make(report.Nodes)
|
||||
for scID, scNode := range rpt.StorageClass.Nodes {
|
||||
storageClass, _ := scNode.Latest.Lookup(kubernetes.Name)
|
||||
for _, pvcNode := range rpt.PersistentVolumeClaim.Nodes {
|
||||
storageClassName, _ := pvcNode.Latest.Lookup(kubernetes.StorageClassName)
|
||||
if storageClassName == storageClass {
|
||||
scNode.Adjacency = scNode.Adjacency.Add(pvcNode.ID)
|
||||
scNode.Children = scNode.Children.Add(pvcNode)
|
||||
}
|
||||
}
|
||||
return ret.storageResult(endpoints)
|
||||
nodes[scID] = scNode
|
||||
}
|
||||
return ret.storageResult(endpoints)
|
||||
return Nodes{Nodes: nodes}
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
package render_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/weaveworks/common/test"
|
||||
"github.com/weaveworks/scope/render"
|
||||
"github.com/weaveworks/scope/render/expected"
|
||||
"github.com/weaveworks/scope/test/fixture"
|
||||
"github.com/weaveworks/scope/test/reflect"
|
||||
"github.com/weaveworks/scope/test/utils"
|
||||
)
|
||||
|
||||
func TestPersistentVolumeRenderer(t *testing.T) {
|
||||
have := utils.Prune(render.PersistentVolumeRenderer.Render(fixture.Report).Nodes)
|
||||
want := utils.Prune(expected.RenderedPersistentVolume)
|
||||
if !reflect.DeepEqual(want, have) {
|
||||
t.Error(test.Diff(want, have))
|
||||
}
|
||||
}
|
||||
@@ -65,22 +65,7 @@ var PodRenderer = Memoise(ConditionalRenderer(renderKubernetesTopologies,
|
||||
),
|
||||
),
|
||||
ConnectionJoin(MapPod2IP, report.Pod),
|
||||
ConnectionStorageJoin(
|
||||
Map2PVName,
|
||||
report.PersistentVolumeClaim,
|
||||
),
|
||||
ConnectionStorageJoin(
|
||||
Map2PVCName,
|
||||
report.Pod,
|
||||
),
|
||||
MapStorageEndpoints(
|
||||
Map2PVNode,
|
||||
report.PersistentVolume,
|
||||
),
|
||||
MapStorageEndpoints(
|
||||
Map2PVNode,
|
||||
report.StorageClass,
|
||||
),
|
||||
KubernetesVolumesRenderer,
|
||||
),
|
||||
),
|
||||
))
|
||||
|
||||
@@ -251,29 +251,6 @@ func (ret *joinResults) rewriteAdjacency(outID string, adjacency report.IDList)
|
||||
ret.nodes[outID] = out
|
||||
}
|
||||
|
||||
// storageAdjacency sets adjacency for the given node ID
|
||||
func (ret *joinResults) storageAdjacency(outID string, adjacency string) {
|
||||
out := ret.nodes[outID]
|
||||
out.Adjacency = out.Adjacency.Add(adjacency)
|
||||
ret.nodes[outID] = out
|
||||
}
|
||||
|
||||
// storageResult returns Nodes for after adding adjacencies
|
||||
func (ret *joinResults) storageResult(input Nodes) Nodes {
|
||||
for _, n := range input.Nodes {
|
||||
outID, ok := ret.mapped[n.ID]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Since PV and PVC will have only single adjacency
|
||||
ret.storageAdjacency(outID, n.ID)
|
||||
for _, outID := range ret.multi[n.ID] {
|
||||
ret.storageAdjacency(outID, n.ID)
|
||||
}
|
||||
}
|
||||
return Nodes{Nodes: ret.nodes}
|
||||
}
|
||||
|
||||
// ResetCache blows away the rendered node cache, and known service
|
||||
// cache.
|
||||
func ResetCache() {
|
||||
|
||||
@@ -105,6 +105,8 @@ var (
|
||||
PersistentVolumeNodeID = report.MakePersistentVolumeNodeID(PersistentVolumeUID)
|
||||
PersistentVolumeClaimUID = "pvc1234"
|
||||
PersistentVolumeClaimNodeID = report.MakePersistentVolumeClaimNodeID(PersistentVolumeClaimUID)
|
||||
StorageClassUID = "sc1234"
|
||||
StorageClassNodeID = report.MakeStorageClassNodeID(StorageClassUID)
|
||||
|
||||
ClientProcess1CPUMetric = report.MakeSingletonMetric(Now.Add(-1*time.Second), 0.01)
|
||||
ClientProcess1MemoryMetric = report.MakeSingletonMetric(Now.Add(-2*time.Second), 0.02)
|
||||
@@ -366,7 +368,7 @@ var (
|
||||
}).
|
||||
WithTopology(report.PersistentVolumeClaim),
|
||||
},
|
||||
}.WithShape(report.Cylinder).WithLabel("persistent volume claim", "persistent volume claims"),
|
||||
}.WithShape(report.DottedCylinder).WithLabel("persistent volume claim", "persistent volume claims"),
|
||||
PersistentVolume: report.Topology{
|
||||
Nodes: report.Nodes{
|
||||
PersistentVolumeNodeID: report.MakeNodeWith(
|
||||
@@ -382,6 +384,17 @@ var (
|
||||
WithTopology(report.PersistentVolume),
|
||||
},
|
||||
}.WithShape(report.Cylinder).WithLabel("persistent volume", "persistent volumes"),
|
||||
StorageClass: report.Topology{
|
||||
Nodes: report.Nodes{
|
||||
StorageClassNodeID: report.MakeNodeWith(
|
||||
|
||||
StorageClassNodeID, map[string]string{
|
||||
kubernetes.Name: "standard",
|
||||
kubernetes.Provisioner: "pong",
|
||||
}).
|
||||
WithTopology(report.StorageClass),
|
||||
},
|
||||
}.WithShape(report.StorageSheet).WithLabel("storage class", "storage classes"),
|
||||
Sampling: report.Sampling{
|
||||
Count: 1024,
|
||||
Total: 4096,
|
||||
|
||||
Reference in New Issue
Block a user