clean up vertex/edge deletion

This commit is contained in:
Jordan Liggitt 2018-04-19 16:59:09 -04:00
parent 96a0df6413
commit ad7d5505b9
No known key found for this signature in database
GPG Key ID: 39928704103C7229
2 changed files with 39 additions and 43 deletions

View File

@ -173,28 +173,19 @@ func (g *Graph) deleteVertex_locked(vertexType vertexType, namespace, name strin
return true return true
}) })
g.graph.VisitTo(vertex, func(neighbor graph.Node) bool { g.graph.VisitTo(vertex, func(neighbor graph.Node) bool {
// this upstream neighbor has only one edge (which must be to us), so remove them as well
if g.graph.Degree(neighbor) == 1 { if g.graph.Degree(neighbor) == 1 {
// this upstream neighbor has only one edge (which must be to us), so remove them as well
neighborsToRemove = append(neighborsToRemove, neighbor) neighborsToRemove = append(neighborsToRemove, neighbor)
} }
return true return true
}) })
// remove the vertex // remove the vertex
g.graph.RemoveNode(vertex) g.removeVertex_locked(vertex)
delete(g.vertices[vertexType][namespace], name)
if len(g.vertices[vertexType][namespace]) == 0 {
delete(g.vertices[vertexType], namespace)
}
// remove neighbors that are now edgeless // remove neighbors that are now edgeless
for _, neighbor := range neighborsToRemove { for _, neighbor := range neighborsToRemove {
g.graph.RemoveNode(neighbor) g.removeVertex_locked(neighbor.(*namedVertex))
n := neighbor.(*namedVertex)
delete(g.vertices[n.vertexType][n.namespace], n.name)
if len(g.vertices[n.vertexType][n.namespace]) == 0 {
delete(g.vertices[n.vertexType], n.namespace)
}
} }
} }
@ -208,37 +199,36 @@ func (g *Graph) deleteEdges_locked(fromType, toType vertexType, toNamespace, toN
return return
} }
// get potential "from" verts that match fromType
namespaces, exists := g.vertices[fromType]
if !exists {
return
}
// delete all edges between vertices of fromType and toVert // delete all edges between vertices of fromType and toVert
removeVerts := []*namedVertex{} neighborsToRemove := []*namedVertex{}
for _, vertexMapping := range namespaces { g.graph.VisitTo(toVert, func(from graph.Node) bool {
for _, fromVert := range vertexMapping { fromVert := from.(*namedVertex)
if g.graph.HasEdgeBetween(fromVert, toVert) { if fromVert.vertexType != fromType {
// remove the edge (no-op if edge doesn't exist) return true
g.graph.RemoveEdge(newDestinationEdge(fromVert, toVert, nil))
// remember to clean up the fromVert if we orphaned it
if g.graph.Degree(fromVert) == 0 {
removeVerts = append(removeVerts, fromVert)
}
}
} }
} // remove the edge
g.graph.RemoveEdge(simple.Edge{F: fromVert, T: toVert})
// track vertexes that changed edges
if g.graph.Degree(fromVert) == 0 {
neighborsToRemove = append(neighborsToRemove, fromVert)
}
return true
})
// clean up orphaned verts // clean up orphaned verts
for _, v := range removeVerts { for _, v := range neighborsToRemove {
g.graph.RemoveNode(v) g.removeVertex_locked(v)
delete(g.vertices[v.vertexType][v.namespace], v.name) }
if len(g.vertices[v.vertexType][v.namespace]) == 0 { }
delete(g.vertices[v.vertexType], v.namespace)
} // must be called under write lock
if len(g.vertices[v.vertexType]) == 0 { // removeVertex_locked removes the specified vertex from the graph and from the maintained indices.
delete(g.vertices, v.vertexType) // It does nothing to indexes of neighbor vertices.
} func (g *Graph) removeVertex_locked(v *namedVertex) {
g.graph.RemoveNode(v)
delete(g.vertices[v.vertexType][v.namespace], v.name)
if len(g.vertices[v.vertexType][v.namespace]) == 0 {
delete(g.vertices[v.vertexType], v.namespace)
} }
} }
@ -265,22 +255,26 @@ func (g *Graph) AddPod(pod *api.Pod) {
// //
// ref https://github.com/kubernetes/kubernetes/issues/58790 // ref https://github.com/kubernetes/kubernetes/issues/58790
if len(pod.Spec.ServiceAccountName) > 0 { if len(pod.Spec.ServiceAccountName) > 0 {
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(serviceAccountVertexType, pod.Namespace, pod.Spec.ServiceAccountName), podVertex, nodeVertex)) serviceAccountVertex := g.getOrCreateVertex_locked(serviceAccountVertexType, pod.Namespace, pod.Spec.ServiceAccountName)
g.graph.SetEdge(newDestinationEdge(serviceAccountVertex, podVertex, nodeVertex))
} }
podutil.VisitPodSecretNames(pod, func(secret string) bool { podutil.VisitPodSecretNames(pod, func(secret string) bool {
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(secretVertexType, pod.Namespace, secret), podVertex, nodeVertex)) secretVertex := g.getOrCreateVertex_locked(secretVertexType, pod.Namespace, secret)
g.graph.SetEdge(newDestinationEdge(secretVertex, podVertex, nodeVertex))
return true return true
}) })
podutil.VisitPodConfigmapNames(pod, func(configmap string) bool { podutil.VisitPodConfigmapNames(pod, func(configmap string) bool {
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(configMapVertexType, pod.Namespace, configmap), podVertex, nodeVertex)) configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, pod.Namespace, configmap)
g.graph.SetEdge(newDestinationEdge(configmapVertex, podVertex, nodeVertex))
return true return true
}) })
for _, v := range pod.Spec.Volumes { for _, v := range pod.Spec.Volumes {
if v.PersistentVolumeClaim != nil { if v.PersistentVolumeClaim != nil {
g.graph.SetEdge(newDestinationEdge(g.getOrCreateVertex_locked(pvcVertexType, pod.Namespace, v.PersistentVolumeClaim.ClaimName), podVertex, nodeVertex)) pvcVertex := g.getOrCreateVertex_locked(pvcVertexType, pod.Namespace, v.PersistentVolumeClaim.ClaimName)
g.graph.SetEdge(newDestinationEdge(pvcVertex, podVertex, nodeVertex))
} }
} }
} }

View File

@ -42,6 +42,7 @@ func TestDeleteEdges_locked(t *testing.T) {
toName: "node1", toName: "node1",
start: func() *Graph { start: func() *Graph {
g := NewGraph() g := NewGraph()
g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap2")
nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", "node1") nodeVertex := g.getOrCreateVertex_locked(nodeVertexType, "", "node1")
configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1") configmapVertex := g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap1")
g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex, nodeVertex)) g.graph.SetEdge(newDestinationEdge(configmapVertex, nodeVertex, nodeVertex))
@ -49,6 +50,7 @@ func TestDeleteEdges_locked(t *testing.T) {
}(), }(),
expect: func() *Graph { expect: func() *Graph {
g := NewGraph() g := NewGraph()
g.getOrCreateVertex_locked(configMapVertexType, "namespace1", "configmap2")
g.getOrCreateVertex_locked(nodeVertexType, "", "node1") g.getOrCreateVertex_locked(nodeVertexType, "", "node1")
return g return g
}(), }(),