Skip to content

Commit e1370a1

Browse files
author
Maksim Fedotov
committed
propagate labels and annotations from ClusterClass and Cluster topology to KCP and MD
1 parent 0cf4492 commit e1370a1

File tree

5 files changed

+81
-24
lines changed

5 files changed

+81
-24
lines changed

api/v1beta1/cluster_types.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ type Topology struct {
101101

102102
// ControlPlaneTopology specifies the parameters for the control plane nodes in the cluster.
103103
type ControlPlaneTopology struct {
104-
// Metadata is the metadata applied to the machines of the ControlPlane.
104+
// Metadata is the metadata applied to ControlPlane and the machines of the ControlPlane.
105105
// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
106106
//
107107
// This field is supported if and only if the control plane provider template
@@ -133,7 +133,7 @@ type WorkersTopology struct {
133133
// MachineDeploymentTopology specifies the different parameters for a set of worker nodes in the topology.
134134
// This set of nodes is managed by a MachineDeployment object whose lifecycle is managed by the Cluster controller.
135135
type MachineDeploymentTopology struct {
136-
// Metadata is the metadata applied to the machines of the MachineDeployment.
136+
// Metadata is the metadata applied to the MachineDeployment and the machines of the MachineDeployment.
137137
// At runtime this metadata is merged with the corresponding metadata from the ClusterClass.
138138
// +optional
139139
Metadata ObjectMeta `json:"metadata,omitempty"`

config/crd/bases/cluster.x-k8s.io_clusters.yaml

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/contract/controlplane.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,13 @@ func (c *ControlPlaneContract) IsScaling(obj *unstructured.Unstructured) (bool,
203203
return false, nil
204204
}
205205

206+
// Metadata provides access to the metadata of a ControlPlane object.
207+
func (c *ControlPlaneContract) Metadata() *Metadata {
208+
return &Metadata{
209+
path: Path{"metadata"},
210+
}
211+
}
212+
206213
// ControlPlaneMachineTemplate provides a helper struct for working with MachineTemplate in ClusterClass.
207214
type ControlPlaneMachineTemplate struct{}
208215

internal/controllers/topology/cluster/desired_state.go

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,11 +176,21 @@ func (r *Reconciler) computeControlPlane(ctx context.Context, s *scope.Scope, in
176176
cluster := s.Current.Cluster
177177
currentRef := cluster.Spec.ControlPlaneRef
178178

179+
// Compute the labels and annotations to be applied to KubeadmControlPlane and Machines.
180+
// We merge the labels and annotations from topology and ClusterClass.
181+
topologyMetadata := s.Blueprint.Topology.ControlPlane.Metadata
182+
clusterClassMetadata := s.Blueprint.ClusterClass.Spec.ControlPlane.Metadata
183+
184+
machineLabels := mergeMap(topologyMetadata.Labels, clusterClassMetadata.Labels)
185+
machineAnnotations := mergeMap(topologyMetadata.Annotations, clusterClassMetadata.Annotations)
186+
179187
controlPlane, err := templateToObject(templateToInput{
180188
template: template,
181189
templateClonedFromRef: templateClonedFromRef,
182190
cluster: cluster,
183191
namePrefix: fmt.Sprintf("%s-", cluster.Name),
192+
labels: machineLabels,
193+
annotations: machineAnnotations,
184194
currentObjectRef: currentRef,
185195
// Note: It is not possible to add an ownerRef to Cluster at this stage, otherwise the provisioning
186196
// of the ControlPlane starts no matter of the object being actually referenced by the Cluster itself.
@@ -205,13 +215,7 @@ func (r *Reconciler) computeControlPlane(ctx context.Context, s *scope.Scope, in
205215
return nil, errors.Wrap(err, "failed to spec.machineTemplate.infrastructureRef in the ControlPlane object")
206216
}
207217

208-
// Compute the labels and annotations to be applied to ControlPlane machines.
209-
// We merge the labels and annotations from topology and ClusterClass.
210-
// We also add the cluster-name and the topology owned labels, so they are propagated down to Machines.
211-
topologyMetadata := s.Blueprint.Topology.ControlPlane.Metadata
212-
clusterClassMetadata := s.Blueprint.ClusterClass.Spec.ControlPlane.Metadata
213-
214-
machineLabels := mergeMap(topologyMetadata.Labels, clusterClassMetadata.Labels)
218+
// Add the cluster-name and the topology owned labels, so they are propagated down to Machines.
215219
if machineLabels == nil {
216220
machineLabels = map[string]string{}
217221
}
@@ -220,7 +224,7 @@ func (r *Reconciler) computeControlPlane(ctx context.Context, s *scope.Scope, in
220224
if err := contract.ControlPlane().MachineTemplate().Metadata().Set(controlPlane,
221225
&clusterv1.ObjectMeta{
222226
Labels: machineLabels,
223-
Annotations: mergeMap(topologyMetadata.Annotations, clusterClassMetadata.Annotations),
227+
Annotations: machineAnnotations,
224228
}); err != nil {
225229
return nil, errors.Wrap(err, "failed to set spec.machineTemplate.metadata in the ControlPlane object")
226230
}
@@ -512,6 +516,10 @@ func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlP
512516
return nil, errors.Wrapf(err, "failed to compute version for %s", machineDeploymentTopology.Name)
513517
}
514518

519+
// Compute labels for MachineDeployment and Machines
520+
machineLabels := mergeMap(machineDeploymentTopology.Metadata.Labels, machineDeploymentBlueprint.Metadata.Labels)
521+
machineAnnotations := mergeMap(machineDeploymentTopology.Metadata.Annotations, machineDeploymentBlueprint.Metadata.Annotations)
522+
515523
// Compute the MachineDeployment object.
516524
gv := clusterv1.GroupVersion
517525
desiredMachineDeploymentObj := &clusterv1.MachineDeployment{
@@ -527,8 +535,8 @@ func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlP
527535
ClusterName: s.Current.Cluster.Name,
528536
Template: clusterv1.MachineTemplateSpec{
529537
ObjectMeta: clusterv1.ObjectMeta{
530-
Labels: mergeMap(machineDeploymentTopology.Metadata.Labels, machineDeploymentBlueprint.Metadata.Labels),
531-
Annotations: mergeMap(machineDeploymentTopology.Metadata.Annotations, machineDeploymentBlueprint.Metadata.Annotations),
538+
Labels: machineLabels,
539+
Annotations: machineAnnotations,
532540
},
533541
Spec: clusterv1.MachineSpec{
534542
ClusterName: s.Current.Cluster.Name,
@@ -562,7 +570,10 @@ func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlP
562570
labels[clusterv1.ClusterLabelName] = s.Current.Cluster.Name
563571
labels[clusterv1.ClusterTopologyOwnedLabel] = ""
564572
labels[clusterv1.ClusterTopologyMachineDeploymentLabelName] = machineDeploymentTopology.Name
565-
desiredMachineDeploymentObj.SetLabels(labels)
573+
desiredMachineDeploymentObj.SetLabels(mergeMap(labels, machineLabels))
574+
575+
// Apply Annotations
576+
desiredMachineDeploymentObj.SetAnnotations(machineAnnotations)
566577

567578
// Set the selector with the subset of labels identifying controlled machines.
568579
// NOTE: this prevents the web hook to add cluster.x-k8s.io/deployment-name label, that is
@@ -710,6 +721,8 @@ type templateToInput struct {
710721
cluster *clusterv1.Cluster
711722
namePrefix string
712723
currentObjectRef *corev1.ObjectReference
724+
labels map[string]string
725+
annotations map[string]string
713726
// OwnerRef is an optional OwnerReference to attach to the cloned object.
714727
ownerRef *metav1.OwnerReference
715728
}
@@ -724,14 +737,17 @@ func templateToObject(in templateToInput) (*unstructured.Unstructured, error) {
724737
labels[clusterv1.ClusterLabelName] = in.cluster.Name
725738
labels[clusterv1.ClusterTopologyOwnedLabel] = ""
726739

740+
templateLabels := mergeMap(labels, in.labels)
741+
727742
// Generate the object from the template.
728743
// NOTE: OwnerRef can't be set at this stage; other controllers are going to add OwnerReferences when
729744
// the object is actually created.
730745
object, err := external.GenerateTemplate(&external.GenerateTemplateInput{
731746
Template: in.template,
732747
TemplateRef: in.templateClonedFromRef,
733748
Namespace: in.cluster.Namespace,
734-
Labels: labels,
749+
Labels: templateLabels,
750+
Annotations: in.annotations,
735751
ClusterName: in.cluster.Name,
736752
OwnerRef: in.ownerRef,
737753
})

internal/controllers/topology/cluster/desired_state_test.go

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ func TestComputeControlPlane(t *testing.T) {
308308
cluster: scope.Current.Cluster,
309309
templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref,
310310
template: blueprint.ControlPlane.Template,
311+
labels: mergeMap(blueprint.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels),
312+
annotations: mergeMap(blueprint.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
311313
currentRef: nil,
312314
obj: obj,
313315
})
@@ -349,6 +351,8 @@ func TestComputeControlPlane(t *testing.T) {
349351
cluster: scope.Current.Cluster,
350352
templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref,
351353
template: blueprint.ControlPlane.Template,
354+
labels: mergeMap(blueprint.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels),
355+
annotations: mergeMap(blueprint.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
352356
currentRef: nil,
353357
obj: obj,
354358
})
@@ -391,18 +395,38 @@ func TestComputeControlPlane(t *testing.T) {
391395
cluster: scope.Current.Cluster,
392396
templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref,
393397
template: blueprint.ControlPlane.Template,
398+
labels: mergeMap(blueprint.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels),
399+
annotations: mergeMap(blueprint.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
394400
currentRef: nil,
395401
obj: obj,
396402
})
397-
gotMetadata, err := contract.ControlPlane().MachineTemplate().Metadata().Get(obj)
403+
404+
gotMachineTemplateMetadata, err := contract.ControlPlane().MachineTemplate().Metadata().Get(obj)
405+
g.Expect(err).ToNot(HaveOccurred())
406+
407+
gotControlPlaneMetadata, err := contract.ControlPlane().Metadata().Get(obj)
398408
g.Expect(err).ToNot(HaveOccurred())
399409

400410
expectedLabels := mergeMap(scope.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels)
401411
expectedLabels[clusterv1.ClusterLabelName] = cluster.Name
402412
expectedLabels[clusterv1.ClusterTopologyOwnedLabel] = ""
403-
g.Expect(gotMetadata).To(Equal(&clusterv1.ObjectMeta{
413+
414+
expectedAnnotations := mergeMap(scope.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations)
415+
416+
defaultControlPlaneAnnotations := map[string]string{
417+
clusterv1.TemplateClonedFromNameAnnotation: blueprint.ClusterClass.Spec.ControlPlane.Ref.Name,
418+
clusterv1.TemplateClonedFromGroupKindAnnotation: blueprint.ClusterClass.Spec.ControlPlane.Ref.GroupVersionKind().GroupKind().String(),
419+
}
420+
expectedControlPlaneAnnotations := mergeMap(defaultControlPlaneAnnotations, expectedAnnotations)
421+
422+
g.Expect(gotMachineTemplateMetadata).To(Equal(&clusterv1.ObjectMeta{
423+
Labels: expectedLabels,
424+
Annotations: expectedAnnotations,
425+
}))
426+
427+
g.Expect(gotControlPlaneMetadata).To(Equal(&clusterv1.ObjectMeta{
404428
Labels: expectedLabels,
405-
Annotations: mergeMap(scope.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
429+
Annotations: expectedControlPlaneAnnotations,
406430
}))
407431

408432
assertNestedField(g, obj, version, contract.ControlPlane().Version().Path()...)
@@ -444,6 +468,8 @@ func TestComputeControlPlane(t *testing.T) {
444468
templateRef: blueprint.ClusterClass.Spec.ControlPlane.Ref,
445469
template: blueprint.ControlPlane.Template,
446470
currentRef: scope.Current.Cluster.Spec.ControlPlaneRef,
471+
labels: mergeMap(blueprint.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels),
472+
annotations: mergeMap(blueprint.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
447473
obj: obj,
448474
})
449475
})
@@ -1361,6 +1387,9 @@ func TestComputeMachineDeployment(t *testing.T) {
13611387

13621388
g.Expect(actualMd.Labels).To(HaveKeyWithValue(clusterv1.ClusterTopologyMachineDeploymentLabelName, "big-pool-of-machines"))
13631389
g.Expect(actualMd.Labels).To(HaveKey(clusterv1.ClusterTopologyOwnedLabel))
1390+
g.Expect(actualMd.Labels).To(HaveKeyWithValue("foo", "baz"))
1391+
g.Expect(actualMd.Labels).To(HaveKeyWithValue("fizz", "buzz"))
1392+
g.Expect(actualMd.Annotations).To(HaveKeyWithValue("annotation-1", "annotation-1-val"))
13641393
g.Expect(controllerutil.ContainsFinalizer(actualMd, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeTrue())
13651394

13661395
g.Expect(actualMd.Spec.Selector.MatchLabels).To(HaveKey(clusterv1.ClusterTopologyOwnedLabel))
@@ -1369,6 +1398,7 @@ func TestComputeMachineDeployment(t *testing.T) {
13691398
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKeyWithValue("foo", "baz"))
13701399
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKeyWithValue("fizz", "buzz"))
13711400
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKey(clusterv1.ClusterTopologyOwnedLabel))
1401+
g.Expect(actualMd.Spec.Template.ObjectMeta.Annotations).To(HaveKeyWithValue("annotation-1", "annotation-1-val"))
13721402
g.Expect(actualMd.Spec.Template.Spec.InfrastructureRef.Name).ToNot(Equal("linux-worker-inframachinetemplate"))
13731403
g.Expect(actualMd.Spec.Template.Spec.Bootstrap.ConfigRef.Name).ToNot(Equal("linux-worker-bootstraptemplate"))
13741404
})
@@ -1415,11 +1445,15 @@ func TestComputeMachineDeployment(t *testing.T) {
14151445

14161446
g.Expect(actualMd.Labels).To(HaveKeyWithValue(clusterv1.ClusterTopologyMachineDeploymentLabelName, "big-pool-of-machines"))
14171447
g.Expect(actualMd.Labels).To(HaveKey(clusterv1.ClusterTopologyOwnedLabel))
1448+
g.Expect(actualMd.Labels).To(HaveKeyWithValue("foo", "baz"))
1449+
g.Expect(actualMd.Labels).To(HaveKeyWithValue("fizz", "buzz"))
1450+
g.Expect(actualMd.Annotations).To(HaveKeyWithValue("annotation-1", "annotation-1-val"))
14181451
g.Expect(controllerutil.ContainsFinalizer(actualMd, clusterv1.MachineDeploymentTopologyFinalizer)).To(BeFalse())
14191452

14201453
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKeyWithValue("foo", "baz"))
14211454
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKeyWithValue("fizz", "buzz"))
14221455
g.Expect(actualMd.Spec.Template.ObjectMeta.Labels).To(HaveKey(clusterv1.ClusterTopologyOwnedLabel))
1456+
g.Expect(actualMd.Spec.Template.ObjectMeta.Annotations).To(HaveKeyWithValue("annotation-1", "annotation-1-val"))
14231457
g.Expect(actualMd.Spec.Template.Spec.InfrastructureRef.Name).To(Equal("linux-worker-inframachinetemplate"))
14241458
g.Expect(actualMd.Spec.Template.Spec.Bootstrap.ConfigRef.Name).To(Equal("linux-worker-bootstraptemplate"))
14251459
})

0 commit comments

Comments
 (0)