Skip to content

Commit 0874250

Browse files
committed
test/e2e: Extend MD rollout test to cover in-place propagation
Signed-off-by: Stefan Büringer buringerst@vmware.com
1 parent 400f8c2 commit 0874250

16 files changed

+1666
-139
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package contract
18+
19+
import (
20+
"sync"
21+
)
22+
23+
// BootstrapConfigTemplateContract encodes information about the Machine API contract for BootstrapConfigTemplate objects
24+
// like KubeadmConfigTemplate, etc.
25+
type BootstrapConfigTemplateContract struct{}
26+
27+
var bootstrapConfigTemplate *BootstrapConfigTemplateContract
28+
var onceBootstrapConfigTemplate sync.Once
29+
30+
// BootstrapConfigTemplate provide access to the information about the Machine API contract for BootstrapConfigTemplate objects.
31+
func BootstrapConfigTemplate() *BootstrapConfigTemplateContract {
32+
onceBootstrapConfigTemplate.Do(func() {
33+
bootstrapConfigTemplate = &BootstrapConfigTemplateContract{}
34+
})
35+
return bootstrapConfigTemplate
36+
}
37+
38+
// Template provides access to the template.
39+
func (c *BootstrapConfigTemplateContract) Template() *BootstrapConfigTemplateTemplate {
40+
return &BootstrapConfigTemplateTemplate{}
41+
}
42+
43+
// BootstrapConfigTemplateTemplate provides a helper struct for working with the template in an BootstrapConfigTemplate.
44+
type BootstrapConfigTemplateTemplate struct{}
45+
46+
// Metadata provides access to the metadata of a template.
47+
func (c *BootstrapConfigTemplateTemplate) Metadata() *Metadata {
48+
return &Metadata{
49+
path: Path{"spec", "template", "metadata"},
50+
}
51+
}

internal/contract/controlplane_template.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,33 @@ func (c *ControlPlaneTemplateContract) InfrastructureMachineTemplate() *Ref {
4242
path: Path{"spec", "template", "spec", "machineTemplate", "infrastructureRef"},
4343
}
4444
}
45+
46+
// Template provides access to the template.
47+
func (c *ControlPlaneTemplateContract) Template() *ControlPlaneTemplateTemplate {
48+
return &ControlPlaneTemplateTemplate{}
49+
}
50+
51+
// ControlPlaneTemplateTemplate provides a helper struct for working with the template in an ControlPlaneTemplate..
52+
type ControlPlaneTemplateTemplate struct{}
53+
54+
// Metadata provides access to the metadata of a template.
55+
func (c *ControlPlaneTemplateTemplate) Metadata() *Metadata {
56+
return &Metadata{
57+
path: Path{"spec", "template", "metadata"},
58+
}
59+
}
60+
61+
// MachineTemplate provides access to MachineTemplate in a ControlPlaneTemplate object, if any.
62+
func (c *ControlPlaneTemplateTemplate) MachineTemplate() *ControlPlaneTemplateMachineTemplate {
63+
return &ControlPlaneTemplateMachineTemplate{}
64+
}
65+
66+
// ControlPlaneTemplateMachineTemplate provides a helper struct for working with MachineTemplate.
67+
type ControlPlaneTemplateMachineTemplate struct{}
68+
69+
// Metadata provides access to the metadata of the MachineTemplate of a ControlPlaneTemplate.
70+
func (c *ControlPlaneTemplateMachineTemplate) Metadata() *Metadata {
71+
return &Metadata{
72+
path: Path{"spec", "template", "spec", "machineTemplate", "metadata"},
73+
}
74+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package contract
18+
19+
import (
20+
"sync"
21+
)
22+
23+
// InfrastructureClusterTemplateContract encodes information about the Cluster API contract for InfrastructureClusterTemplate objects
24+
// like DockerClusterTemplates, AWSClusterTemplates, etc.
25+
type InfrastructureClusterTemplateContract struct{}
26+
27+
var infrastructureClusterTemplate *InfrastructureClusterTemplateContract
28+
var onceInfrastructureClusterTemplate sync.Once
29+
30+
// InfrastructureClusterTemplate provides access to the information about the Cluster API contract for InfrastructureClusterTemplate objects.
31+
func InfrastructureClusterTemplate() *InfrastructureClusterTemplateContract {
32+
onceInfrastructureClusterTemplate.Do(func() {
33+
infrastructureClusterTemplate = &InfrastructureClusterTemplateContract{}
34+
})
35+
return infrastructureClusterTemplate
36+
}
37+
38+
// Template provides access to the template.
39+
func (c *InfrastructureClusterTemplateContract) Template() *InfrastructureClusterTemplateTemplate {
40+
return &InfrastructureClusterTemplateTemplate{}
41+
}
42+
43+
// InfrastructureClusterTemplateTemplate provides a helper struct for working with the template in an InfrastructureClusterTemplate..
44+
type InfrastructureClusterTemplateTemplate struct{}
45+
46+
// Metadata provides access to the metadata of a template.
47+
func (c *InfrastructureClusterTemplateTemplate) Metadata() *Metadata {
48+
return &Metadata{
49+
path: Path{"spec", "template", "metadata"},
50+
}
51+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package contract
18+
19+
import (
20+
"sync"
21+
)
22+
23+
// InfrastructureMachineTemplateContract encodes information about the Machine API contract for InfrastructureMachineTemplate objects
24+
// like DockerMachineTemplates, AWSMachineTemplates, etc.
25+
type InfrastructureMachineTemplateContract struct{}
26+
27+
var infrastructureMachineTemplate *InfrastructureMachineTemplateContract
28+
var onceInfrastructureMachineTemplate sync.Once
29+
30+
// InfrastructureMachineTemplate provide access to the information about the Machine API contract for InfrastructureMachineTemplate objects.
31+
func InfrastructureMachineTemplate() *InfrastructureMachineTemplateContract {
32+
onceInfrastructureMachineTemplate.Do(func() {
33+
infrastructureMachineTemplate = &InfrastructureMachineTemplateContract{}
34+
})
35+
return infrastructureMachineTemplate
36+
}
37+
38+
// Template provides access to the template.
39+
func (c *InfrastructureMachineTemplateContract) Template() *InfrastructureMachineTemplateTemplate {
40+
return &InfrastructureMachineTemplateTemplate{}
41+
}
42+
43+
// InfrastructureMachineTemplateTemplate provides a helper struct for working with the template in an InfrastructureMachineTemplate.
44+
type InfrastructureMachineTemplateTemplate struct{}
45+
46+
// Metadata provides access to the metadata of a template.
47+
func (c *InfrastructureMachineTemplateTemplate) Metadata() *Metadata {
48+
return &Metadata{
49+
path: Path{"spec", "template", "metadata"},
50+
}
51+
}

internal/controllers/topology/cluster/desired_state.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -241,11 +241,22 @@ func (r *Reconciler) computeControlPlane(ctx context.Context, s *scope.Scope, in
241241
return nil, errors.Wrap(err, "failed to spec.machineTemplate.infrastructureRef in the ControlPlane object")
242242
}
243243

244-
// Apply the ControlPlane labels and annotations to the ControlPlane machines as well.
244+
// Add the ControlPlane labels and annotations to the ControlPlane machines as well.
245+
// Note: We have to ensure the machine template metadata copied from the control plane template is not overwritten.
246+
controlPlaneMachineTemplateMetadata, err := contract.ControlPlane().MachineTemplate().Metadata().Get(controlPlane)
247+
if err != nil {
248+
return nil, errors.Wrap(err, "failed to get spec.machineTemplate.metadata from the ControlPlane object")
249+
}
250+
for k, v := range controlPlaneLabels {
251+
controlPlaneMachineTemplateMetadata.Labels[k] = v
252+
}
253+
for k, v := range controlPlaneAnnotations {
254+
controlPlaneMachineTemplateMetadata.Annotations[k] = v
255+
}
245256
if err := contract.ControlPlane().MachineTemplate().Metadata().Set(controlPlane,
246257
&clusterv1.ObjectMeta{
247-
Labels: controlPlaneLabels,
248-
Annotations: controlPlaneAnnotations,
258+
Labels: controlPlaneMachineTemplateMetadata.Labels,
259+
Annotations: controlPlaneMachineTemplateMetadata.Annotations,
249260
}); err != nil {
250261
return nil, errors.Wrap(err, "failed to set spec.machineTemplate.metadata in the ControlPlane object")
251262
}
@@ -990,15 +1001,14 @@ func templateToTemplate(in templateToInput) *unstructured.Unstructured {
9901001
return template
9911002
}
9921003

993-
// mergeMap merges two maps into another one.
994-
// NOTE: In case a key exists in both maps, the value in the first map is preserved.
995-
func mergeMap(a, b map[string]string) map[string]string {
1004+
// mergeMap merges maps.
1005+
// NOTE: In case a key exists in multiple maps, the value of the first map is preserved.
1006+
func mergeMap(maps ...map[string]string) map[string]string {
9961007
m := make(map[string]string)
997-
for k, v := range b {
998-
m[k] = v
999-
}
1000-
for k, v := range a {
1001-
m[k] = v
1008+
for i := len(maps) - 1; i >= 0; i-- {
1009+
for k, v := range maps[i] {
1010+
m[k] = v
1011+
}
10021012
}
10031013

10041014
// Nil the result if the map is empty, thus avoiding triggering infinite reconcile

internal/controllers/topology/cluster/desired_state_test.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,17 @@ func TestComputeControlPlane(t *testing.T) {
252252

253253
controlPlaneTemplate := builder.ControlPlaneTemplate(metav1.NamespaceDefault, "template1").
254254
Build()
255+
controlPlaneMachineTemplateLabels := map[string]string{
256+
"machineTemplateLabel": "machineTemplateLabelValue",
257+
}
258+
controlPlaneMachineTemplateAnnotations := map[string]string{
259+
"machineTemplateAnnotation": "machineTemplateAnnotationValue",
260+
}
261+
controlPlaneTemplateWithMachineTemplate := controlPlaneTemplate.DeepCopy()
262+
_ = contract.ControlPlaneTemplate().Template().MachineTemplate().Metadata().Set(controlPlaneTemplate, &clusterv1.ObjectMeta{
263+
Labels: controlPlaneMachineTemplateLabels,
264+
Annotations: controlPlaneMachineTemplateAnnotations,
265+
})
255266
clusterClassDuration := 20 * time.Second
256267
clusterClass := builder.ClusterClass(metav1.NamespaceDefault, "class1").
257268
WithControlPlaneMetadata(labels, annotations).
@@ -423,7 +434,7 @@ func TestComputeControlPlane(t *testing.T) {
423434
infrastructureMachineTemplate := builder.InfrastructureMachineTemplate(metav1.NamespaceDefault, "template1").Build()
424435
clusterClass := builder.ClusterClass(metav1.NamespaceDefault, "class1").
425436
WithControlPlaneMetadata(labels, annotations).
426-
WithControlPlaneTemplate(controlPlaneTemplate).
437+
WithControlPlaneTemplate(controlPlaneTemplateWithMachineTemplate).
427438
WithControlPlaneInfrastructureMachineTemplate(infrastructureMachineTemplate).Build()
428439

429440
// aggregating templates and cluster class into a blueprint (simulating getBlueprint)
@@ -459,12 +470,12 @@ func TestComputeControlPlane(t *testing.T) {
459470
gotMetadata, err := contract.ControlPlane().MachineTemplate().Metadata().Get(obj)
460471
g.Expect(err).ToNot(HaveOccurred())
461472

462-
expectedLabels := mergeMap(s.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels)
473+
expectedLabels := mergeMap(s.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Labels, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Labels, controlPlaneMachineTemplateLabels)
463474
expectedLabels[clusterv1.ClusterNameLabel] = cluster.Name
464475
expectedLabels[clusterv1.ClusterTopologyOwnedLabel] = ""
465476
g.Expect(gotMetadata).To(Equal(&clusterv1.ObjectMeta{
466477
Labels: expectedLabels,
467-
Annotations: mergeMap(s.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations),
478+
Annotations: mergeMap(s.Current.Cluster.Spec.Topology.ControlPlane.Metadata.Annotations, blueprint.ClusterClass.Spec.ControlPlane.Metadata.Annotations, controlPlaneMachineTemplateAnnotations),
468479
}))
469480

470481
assertNestedField(g, obj, version, contract.ControlPlane().Version().Path()...)
@@ -2151,6 +2162,12 @@ func assertTemplateToObject(g *WithT, in assertTemplateInput) {
21512162
g.Expect(err).NotTo(HaveOccurred())
21522163
g.Expect(ok).To(BeTrue())
21532164
for k, v := range expectedSpec {
2165+
// Skip machineTemplate as it's asserted outside of this func.
2166+
// and we can't simply compare template with object for machineTemplate
2167+
// as computeControlPlane() adds additional fields like the timeouts.
2168+
if k == "machineTemplate" {
2169+
continue
2170+
}
21542171
g.Expect(cloneSpec).To(HaveKeyWithValue(k, v))
21552172
}
21562173
}

0 commit comments

Comments
 (0)