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:
Satyam Zode
2018-05-03 17:07:51 +05:30
parent d26b2c3805
commit 24741bec2a
13 changed files with 172 additions and 234 deletions

View File

@@ -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 }

View File

@@ -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" {

View File

@@ -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}
}

View File

@@ -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))
}
}

View File

@@ -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,
),
),
))

View File

@@ -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() {