@@ -19,11 +19,15 @@ package tree
19
19
import (
20
20
"context"
21
21
22
+ corev1 "k8s.io/api/core/v1"
22
23
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24
+ unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
23
25
"sigs.k8s.io/controller-runtime/pkg/client"
24
26
25
27
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
26
28
"sigs.k8s.io/cluster-api/controllers/external"
29
+ addonsv1 "sigs.k8s.io/cluster-api/exp/addons/api/v1beta1"
30
+ expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
27
31
"sigs.k8s.io/cluster-api/util"
28
32
)
29
33
@@ -36,8 +40,16 @@ type DiscoverOptions struct {
36
40
// ShowMachineSets instructs the discovery process to include machine sets in the ObjectTree.
37
41
ShowMachineSets bool
38
42
43
+ // ShowClusterResourceSets instructs the discovery process to include cluster resource sets in the ObjectTree.
44
+ ShowClusterResourceSets bool
45
+
46
+ // ShowTemplates instructs the discovery process to include infrastructure and bootstrap config templates in the ObjectTree.
47
+ ShowTemplates bool
48
+
49
+ // AddTemplateVirtualNode instructs the discovery process to group template under a virtual node.
50
+ AddTemplateVirtualNode bool
51
+
39
52
// Echo displays MachineInfrastructure or BootstrapConfig objects if the object's ready condition is true
40
- // or it has the same Status, Severity and Reason of the parent's object ready condition (it is an echo)
41
53
Echo bool
42
54
43
55
// Grouping groups machine objects in case the ready conditions
@@ -75,10 +87,14 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
75
87
tree .Add (cluster , clusterInfra , ObjectMetaName ("ClusterInfrastructure" ))
76
88
}
77
89
90
+ if options .ShowClusterResourceSets {
91
+ addClusterResourceSetsToObjectTree (ctx , c , cluster , tree )
92
+ }
93
+
78
94
// Adds control plane
79
- controlPLane , err := external .Get (ctx , c , cluster .Spec .ControlPlaneRef , cluster .Namespace )
95
+ controlPlane , err := external .Get (ctx , c , cluster .Spec .ControlPlaneRef , cluster .Namespace )
80
96
if err == nil {
81
- tree . Add (cluster , controlPLane , ObjectMetaName ( "ControlPlane" ), GroupingObject ( true ) )
97
+ addControlPlane (cluster , controlPlane , tree , options )
82
98
}
83
99
84
100
// Adds control plane machines.
@@ -105,25 +121,103 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
105
121
controlPlaneMachines := selectControlPlaneMachines (machinesList )
106
122
for i := range controlPlaneMachines {
107
123
cp := controlPlaneMachines [i ]
108
- addMachineFunc (controlPLane , cp )
124
+ addMachineFunc (controlPlane , cp )
109
125
}
110
126
111
- if len (machinesList .Items ) == len (controlPlaneMachines ) {
112
- return tree , nil
127
+ machinePoolList , err := getMachinePoolsInCluster (ctx , c , cluster .Namespace , cluster .Name )
128
+ if err != nil {
129
+ return nil , err
113
130
}
114
131
115
132
workers := VirtualObject (cluster .Namespace , "WorkerGroup" , "Workers" )
116
- tree .Add (cluster , workers )
133
+ // Add WorkerGroup if there are MachineDeployments or MachinePools
134
+ if len (machinesList .Items ) != len (controlPlaneMachines ) || len (machinePoolList .Items ) > 0 {
135
+ tree .Add (cluster , workers )
136
+ }
137
+
138
+ if len (machinesList .Items ) != len (controlPlaneMachines ) { // Add MachineDeployment objects
139
+ tree .Add (cluster , workers )
140
+ err = addMachineDeploymentToObjectTree (ctx , c , cluster , workers , machinesList , tree , options , addMachineFunc )
141
+ if err != nil {
142
+ return nil , err
143
+ }
144
+
145
+ // Handles orphan machines.
146
+ if len (machineMap ) < len (machinesList .Items ) {
147
+ other := VirtualObject (cluster .Namespace , "OtherGroup" , "Other" )
148
+ tree .Add (workers , other )
149
+
150
+ for i := range machinesList .Items {
151
+ m := & machinesList .Items [i ]
152
+ if _ , ok := machineMap [m .Name ]; ok {
153
+ continue
154
+ }
155
+ addMachineFunc (other , m )
156
+ }
157
+ }
158
+ }
159
+
160
+ if len (machinePoolList .Items ) > 0 { // Add MachinePool objects
161
+ tree .Add (cluster , workers )
162
+ addMachinePoolsToObjectTree (ctx , c , cluster .Namespace , workers , machinePoolList , tree )
163
+ }
164
+
165
+ return tree , nil
166
+ }
117
167
168
+ func addClusterResourceSetsToObjectTree (ctx context.Context , c client.Client , cluster * clusterv1.Cluster , tree * ObjectTree ) {
169
+ if resourceSetBinding , err := getResourceSetBindingInCluster (ctx , c , cluster .Namespace , cluster .Name ); err == nil {
170
+ resourceSetGroup := VirtualObject (cluster .Namespace , "ClusterResourceSetGroup" , "ClusterResourceSets" )
171
+ tree .Add (cluster , resourceSetGroup )
172
+
173
+ for _ , binding := range resourceSetBinding .Spec .Bindings {
174
+ resourceSetRefObject := ObjectReferenceObject (& corev1.ObjectReference {
175
+ Kind : "ClusterResourceSet" ,
176
+ Namespace : cluster .Namespace ,
177
+ Name : binding .ClusterResourceSetName ,
178
+ APIVersion : addonsv1 .GroupVersion .String (),
179
+ })
180
+ tree .Add (resourceSetGroup , resourceSetRefObject )
181
+ }
182
+ }
183
+ }
184
+
185
+ func addControlPlane (cluster * clusterv1.Cluster , controlPlane * unstructured.Unstructured , tree * ObjectTree , options DiscoverOptions ) {
186
+ tree .Add (cluster , controlPlane , ObjectMetaName ("ControlPlane" ), GroupingObject (true ))
187
+
188
+ if options .ShowTemplates {
189
+ // Add control plane infrastructure ref using spec fields guaranteed in contract
190
+ infrastructureRef , found , err := unstructured .NestedMap (controlPlane .UnstructuredContent (), "spec" , "machineTemplate" , "infrastructureRef" )
191
+ if err == nil && found {
192
+ infrastructureObjectRef := & corev1.ObjectReference {
193
+ Kind : infrastructureRef ["kind" ].(string ),
194
+ Namespace : infrastructureRef ["namespace" ].(string ),
195
+ Name : infrastructureRef ["name" ].(string ),
196
+ APIVersion : infrastructureRef ["apiVersion" ].(string ),
197
+ }
198
+
199
+ machineTemplateRefObject := ObjectReferenceObject (infrastructureObjectRef )
200
+ var templateParent client.Object
201
+ if options .AddTemplateVirtualNode {
202
+ templateParent = addTemplateVirtualNode (tree , controlPlane , cluster .Namespace )
203
+ } else {
204
+ templateParent = controlPlane
205
+ }
206
+ tree .Add (templateParent , machineTemplateRefObject , ObjectMetaName ("MachineInfrastructureTemplate" ))
207
+ }
208
+ }
209
+ }
210
+
211
+ func addMachineDeploymentToObjectTree (ctx context.Context , c client.Client , cluster * clusterv1.Cluster , workers * unstructured.Unstructured , machinesList * clusterv1.MachineList , tree * ObjectTree , options DiscoverOptions , addMachineFunc func (parent client.Object , m * clusterv1.Machine )) error {
118
212
// Adds worker machines.
119
213
machinesDeploymentList , err := getMachineDeploymentsInCluster (ctx , c , cluster .Namespace , cluster .Name )
120
214
if err != nil {
121
- return nil , err
215
+ return err
122
216
}
123
217
124
218
machineSetList , err := getMachineSetsInCluster (ctx , c , cluster .Namespace , cluster .Name )
125
219
if err != nil {
126
- return nil , err
220
+ return err
127
221
}
128
222
129
223
for i := range machinesDeploymentList .Items {
@@ -134,6 +228,21 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
134
228
}
135
229
tree .Add (workers , md , addOpts ... )
136
230
231
+ if options .ShowTemplates {
232
+ var templateParent client.Object
233
+ if options .AddTemplateVirtualNode {
234
+ templateParent = addTemplateVirtualNode (tree , md , cluster .Namespace )
235
+ } else {
236
+ templateParent = md
237
+ }
238
+
239
+ bootstrapTemplateRefObject := ObjectReferenceObject (md .Spec .Template .Spec .Bootstrap .ConfigRef )
240
+ tree .Add (templateParent , bootstrapTemplateRefObject , ObjectMetaName ("BootstrapConfigTemplate" ))
241
+
242
+ machineTemplateRefObject := ObjectReferenceObject (& md .Spec .Template .Spec .InfrastructureRef )
243
+ tree .Add (templateParent , machineTemplateRefObject , ObjectMetaName ("MachineInfrastructureTemplate" ))
244
+ }
245
+
137
246
machineSets := selectMachinesSetsControlledBy (machineSetList , md )
138
247
for i := range machineSets {
139
248
ms := machineSets [i ]
@@ -151,21 +260,42 @@ func Discovery(ctx context.Context, c client.Client, namespace, name string, opt
151
260
}
152
261
}
153
262
154
- // Handles orphan machines.
155
- if len (machineMap ) < len (machinesList .Items ) {
156
- other := VirtualObject (cluster .Namespace , "OtherGroup" , "Other" )
157
- tree .Add (workers , other )
263
+ return nil
264
+ }
265
+
266
+ func addMachinePoolsToObjectTree (ctx context.Context , c client.Client , namespace string , workers * unstructured.Unstructured , machinePoolList * expv1.MachinePoolList , tree * ObjectTree ) {
267
+ for i := range machinePoolList .Items {
268
+ mp := & machinePoolList .Items [i ]
269
+ _ , visible := tree .Add (workers , mp )
158
270
159
- for i := range machinesList .Items {
160
- m := & machinesList .Items [i ]
161
- if _ , ok := machineMap [m .Name ]; ok {
162
- continue
271
+ if visible {
272
+ if machinePoolBootstrap , err := external .Get (ctx , c , mp .Spec .Template .Spec .Bootstrap .ConfigRef , namespace ); err == nil {
273
+ tree .Add (mp , machinePoolBootstrap , ObjectMetaName ("BootstrapConfig" ), NoEcho (true ))
274
+ }
275
+
276
+ if machinePoolInfra , err := external .Get (ctx , c , & mp .Spec .Template .Spec .InfrastructureRef , namespace ); err == nil {
277
+ tree .Add (mp , machinePoolInfra , ObjectMetaName ("MachineInfrastructure" ), NoEcho (true ))
163
278
}
164
- addMachineFunc (other , m )
165
279
}
166
280
}
281
+ }
167
282
168
- return tree , nil
283
+ func getResourceSetBindingInCluster (ctx context.Context , c client.Client , namespace string , name string ) (* addonsv1.ClusterResourceSetBinding , error ) {
284
+ if name == "" {
285
+ return nil , nil
286
+ }
287
+
288
+ resourceSetBinding := & addonsv1.ClusterResourceSetBinding {}
289
+ resourceSetBindingKey := client.ObjectKey {Namespace : namespace , Name : name }
290
+ if err := c .Get (ctx , resourceSetBindingKey , resourceSetBinding ); err != nil {
291
+ return nil , err
292
+ }
293
+ resourceSetBinding .TypeMeta = metav1.TypeMeta {
294
+ Kind : "ClusterResourceSetBinding" ,
295
+ APIVersion : addonsv1 .GroupVersion .String (),
296
+ }
297
+
298
+ return resourceSetBinding , nil
169
299
}
170
300
171
301
func getMachinesInCluster (ctx context.Context , c client.Client , namespace , name string ) (* clusterv1.MachineList , error ) {
@@ -213,6 +343,21 @@ func getMachineSetsInCluster(ctx context.Context, c client.Client, namespace, na
213
343
return machineSetList , nil
214
344
}
215
345
346
+ func getMachinePoolsInCluster (ctx context.Context , c client.Client , namespace , name string ) (* expv1.MachinePoolList , error ) {
347
+ if name == "" {
348
+ return nil , nil
349
+ }
350
+
351
+ machinePoolList := & expv1.MachinePoolList {}
352
+ labels := map [string ]string {clusterv1 .ClusterLabelName : name }
353
+
354
+ if err := c .List (ctx , machinePoolList , client .InNamespace (namespace ), client .MatchingLabels (labels )); err != nil {
355
+ return nil , err
356
+ }
357
+
358
+ return machinePoolList , nil
359
+ }
360
+
216
361
func selectControlPlaneMachines (machineList * clusterv1.MachineList ) []* clusterv1.Machine {
217
362
machines := []* clusterv1.Machine {}
218
363
for i := range machineList .Items {
@@ -245,3 +390,14 @@ func selectMachinesControlledBy(machineList *clusterv1.MachineList, controller c
245
390
}
246
391
return machines
247
392
}
393
+
394
+ func addTemplateVirtualNode (tree * ObjectTree , parent client.Object , namespace string ) client.Object {
395
+ templateNode := VirtualObject (namespace , "TemplateGroup" , parent .GetName ())
396
+ addOpts := []AddObjectOption {
397
+ ZOrder (1 ),
398
+ ObjectMetaName ("Templates" ),
399
+ }
400
+ tree .Add (parent , templateNode , addOpts ... )
401
+
402
+ return templateNode
403
+ }
0 commit comments