...
1
2
3
4
5
6
7 package graph
8
9 import (
10 "sort"
11
12 "sigs.k8s.io/cli-utils/pkg/object"
13 "sigs.k8s.io/cli-utils/pkg/object/validation"
14 "sigs.k8s.io/cli-utils/pkg/ordering"
15 )
16
17
18
19
20 type Graph struct {
21
22 edges map[object.ObjMetadata]object.ObjMetadataSet
23
24 reverseEdges map[object.ObjMetadata]object.ObjMetadataSet
25 }
26
27
28 func New() *Graph {
29 g := &Graph{}
30 g.edges = make(map[object.ObjMetadata]object.ObjMetadataSet)
31 g.reverseEdges = make(map[object.ObjMetadata]object.ObjMetadataSet)
32 return g
33 }
34
35
36
37 func (g *Graph) AddVertex(v object.ObjMetadata) {
38 if _, exists := g.edges[v]; !exists {
39 g.edges[v] = object.ObjMetadataSet{}
40 }
41 if _, exists := g.reverseEdges[v]; !exists {
42 g.reverseEdges[v] = object.ObjMetadataSet{}
43 }
44 }
45
46
47 func edgeMapKeys(edgeMap map[object.ObjMetadata]object.ObjMetadataSet) object.ObjMetadataSet {
48 keys := make(object.ObjMetadataSet, len(edgeMap))
49 i := 0
50 for k := range edgeMap {
51 keys[i] = k
52 i++
53 }
54 sort.Sort(ordering.SortableMetas(keys))
55 return keys
56 }
57
58
59
60 func (g *Graph) AddEdge(from object.ObjMetadata, to object.ObjMetadata) {
61
62 if _, exists := g.edges[from]; !exists {
63 g.edges[from] = object.ObjMetadataSet{}
64 }
65 if _, exists := g.reverseEdges[from]; !exists {
66 g.reverseEdges[from] = object.ObjMetadataSet{}
67 }
68
69 if _, exists := g.edges[to]; !exists {
70 g.edges[to] = object.ObjMetadataSet{}
71 }
72 if _, exists := g.reverseEdges[to]; !exists {
73 g.reverseEdges[to] = object.ObjMetadataSet{}
74 }
75
76
77 if !g.isAdjacent(from, to) {
78 g.edges[from] = append(g.edges[from], to)
79 g.reverseEdges[to] = append(g.reverseEdges[to], from)
80 }
81 }
82
83
84 func edgeMapToList(edgeMap map[object.ObjMetadata]object.ObjMetadataSet) []Edge {
85 edges := []Edge{}
86 for from, toList := range edgeMap {
87 for _, to := range toList {
88 edge := Edge{From: from, To: to}
89 edges = append(edges, edge)
90 }
91 }
92 sort.Sort(SortableEdges(edges))
93 return edges
94 }
95
96
97
98 func (g *Graph) isAdjacent(from object.ObjMetadata, to object.ObjMetadata) bool {
99
100 if _, exists := g.edges[from]; !exists {
101 return false
102 }
103
104 for _, vertex := range g.edges[from] {
105 if vertex == to {
106 return true
107 }
108 }
109 return false
110 }
111
112
113 func (g *Graph) Size() int {
114 return len(g.edges)
115 }
116
117
118 func removeVertex(edges map[object.ObjMetadata]object.ObjMetadataSet, r object.ObjMetadata) {
119
120 for v, adj := range edges {
121 edges[v] = adj.Remove(r)
122 }
123
124 delete(edges, r)
125 }
126
127
128 func (g *Graph) Dependencies(from object.ObjMetadata) object.ObjMetadataSet {
129 edgesFrom, exists := g.edges[from]
130 if !exists {
131 return nil
132 }
133 c := make(object.ObjMetadataSet, len(edgesFrom))
134 copy(c, edgesFrom)
135 return c
136 }
137
138
139 func (g *Graph) Dependents(to object.ObjMetadata) object.ObjMetadataSet {
140 edgesTo, exists := g.reverseEdges[to]
141 if !exists {
142 return nil
143 }
144 c := make(object.ObjMetadataSet, len(edgesTo))
145 copy(c, edgesTo)
146 return c
147 }
148
149
150 func (g *Graph) Sort() ([]object.ObjMetadataSet, error) {
151
152 edges := make(map[object.ObjMetadata]object.ObjMetadataSet, len(g.edges))
153 for vertex, deps := range g.edges {
154 c := make(object.ObjMetadataSet, len(deps))
155 copy(c, deps)
156 edges[vertex] = c
157 }
158
159 sorted := []object.ObjMetadataSet{}
160 for len(edges) > 0 {
161
162 leafVertices := object.ObjMetadataSet{}
163 for v, adj := range edges {
164 if len(adj) == 0 {
165 leafVertices = append(leafVertices, v)
166 }
167 }
168
169
170 if len(leafVertices) == 0 {
171
172 return sorted, validation.NewError(CyclicDependencyError{
173 Edges: edgeMapToList(edges),
174 }, edgeMapKeys(edges)...)
175 }
176
177 for _, v := range leafVertices {
178 removeVertex(edges, v)
179 }
180 sorted = append(sorted, leafVertices)
181 }
182 return sorted, nil
183 }
184
View as plain text