Skip to content

Commit 64c0753

Browse files
authored
Merge pull request #13059 from liuxu623/main
🐛 fix: use MachineSet template values in completeMoveMachine for in-place updates
2 parents 7aa04da + 15b9dd4 commit 64c0753

File tree

2 files changed

+186
-2
lines changed

2 files changed

+186
-2
lines changed

internal/controllers/machineset/machineset_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,8 +422,8 @@ func (r *Reconciler) completeMoveMachine(ctx context.Context, s *scope, currentM
422422
// not updated by r.computeDesiredMachine, so we have to update them here.
423423
// Note: for MachineSets we have to explicitly also set spec.failureDomain (this is a difference from what happens in KCP
424424
// where the field is set only on create and never updated)
425-
desiredMachine.Spec.Version = currentMachine.Spec.Version
426-
desiredMachine.Spec.FailureDomain = currentMachine.Spec.FailureDomain
425+
desiredMachine.Spec.Version = s.machineSet.Spec.Template.Spec.Version
426+
desiredMachine.Spec.FailureDomain = s.machineSet.Spec.Template.Spec.FailureDomain
427427

428428
// Compute desiredInfraMachine.
429429
currentInfraMachine, err := external.GetObjectFromContractVersionedRef(ctx, r.Client, currentMachine.Spec.InfrastructureRef, currentMachine.Namespace)

internal/controllers/machineset/machineset_controller_test.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,12 @@ import (
4747
"sigs.k8s.io/controller-runtime/pkg/reconcile"
4848

4949
clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"
50+
runtimehooksv1 "sigs.k8s.io/cluster-api/api/runtime/hooks/v1alpha1"
5051
runtimev1 "sigs.k8s.io/cluster-api/api/runtime/v1beta2"
5152
"sigs.k8s.io/cluster-api/controllers/external"
5253
"sigs.k8s.io/cluster-api/feature"
5354
"sigs.k8s.io/cluster-api/internal/contract"
55+
"sigs.k8s.io/cluster-api/internal/hooks"
5456
"sigs.k8s.io/cluster-api/internal/util/ssa"
5557
"sigs.k8s.io/cluster-api/util"
5658
"sigs.k8s.io/cluster-api/util/conditions"
@@ -3478,10 +3480,19 @@ func TestMachineSetReconciler_triggerInPlaceUpdate(t *testing.T) {
34783480
wantErr: false,
34793481
},
34803482
}
3483+
3484+
// We want to test that trigger in place handles version and failure domain, which are not reconciled by syncMachines
3485+
versionBeforeInplaceUpdate := "v1.33.0"
3486+
versionAfterInplaceUpdate := "v1.34.0"
3487+
failureDomainBeforeInplaceUpdate := "fd-1"
3488+
failureDomainAfterInplaceUpdate := "fd-2"
3489+
34813490
for _, tt := range tests {
34823491
t.Run(tt.name, func(t *testing.T) {
34833492
g := NewWithT(t)
34843493

3494+
tt.ms.Spec.Template.Spec.Version = versionAfterInplaceUpdate
3495+
tt.ms.Spec.Template.Spec.FailureDomain = failureDomainAfterInplaceUpdate
34853496
tt.ms.Spec.Template.Spec.InfrastructureRef = clusterv1.ContractVersionedObjectReference{
34863497
APIGroup: infraTmpl.GroupVersionKind().Group,
34873498
Kind: infraTmpl.GetKind(),
@@ -3508,6 +3519,15 @@ func TestMachineSetReconciler_triggerInPlaceUpdate(t *testing.T) {
35083519
for _, m := range tt.machines {
35093520
m.SetNamespace(tt.ms.Namespace)
35103521

3522+
if hooks.IsPending(runtimehooksv1.UpdateMachine, m) {
3523+
m.Spec.Version = versionAfterInplaceUpdate
3524+
m.Spec.FailureDomain = failureDomainAfterInplaceUpdate
3525+
} else {
3526+
// NOTE: following values must be changed when in place upgrade is triggered for a machine
3527+
m.Spec.Version = versionBeforeInplaceUpdate
3528+
m.Spec.FailureDomain = failureDomainBeforeInplaceUpdate
3529+
}
3530+
35113531
mInfraObj := infraObj.DeepCopy()
35123532
mInfraObj.SetName(m.Name)
35133533
m.Spec.InfrastructureRef = clusterv1.ContractVersionedObjectReference{
@@ -3552,6 +3572,15 @@ func TestMachineSetReconciler_triggerInPlaceUpdate(t *testing.T) {
35523572

35533573
updatingMachines := machinesInPlaceUpdating(machines)
35543574
g.Expect(updatingMachines).To(ConsistOf(tt.wantMachinesInPlaceUpdating))
3575+
for _, m := range machines.Items {
3576+
if hooks.IsPending(runtimehooksv1.UpdateMachine, &m) {
3577+
g.Expect(m.Spec.Version).To(Equal(versionAfterInplaceUpdate))
3578+
g.Expect(m.Spec.FailureDomain).To(Equal(failureDomainAfterInplaceUpdate))
3579+
} else {
3580+
g.Expect(m.Spec.Version).To(Equal(versionBeforeInplaceUpdate))
3581+
g.Expect(m.Spec.FailureDomain).To(Equal(failureDomainBeforeInplaceUpdate))
3582+
}
3583+
}
35553584
})
35563585
}
35573586
}
@@ -4122,3 +4151,158 @@ func managedFieldsMatching(managedFields []metav1.ManagedFieldsEntry, manager st
41224151
}
41234152
return res
41244153
}
4154+
4155+
func TestReconciler_completeMoveMachine(t *testing.T) {
4156+
testCluster := &clusterv1.Cluster{
4157+
ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: testClusterName},
4158+
}
4159+
4160+
g := NewWithT(t)
4161+
scheme := runtime.NewScheme()
4162+
g.Expect(apiextensionsv1.AddToScheme(scheme)).To(Succeed())
4163+
g.Expect(clusterv1.AddToScheme(scheme)).To(Succeed())
4164+
4165+
// Create bootstrap template resource.
4166+
bootstrapResource := map[string]interface{}{
4167+
"kind": "GenericBootstrapConfig",
4168+
"apiVersion": clusterv1.GroupVersionBootstrap.String(),
4169+
"spec": map[string]interface{}{},
4170+
}
4171+
bootstrapTmpl := &unstructured.Unstructured{
4172+
Object: map[string]interface{}{
4173+
"spec": map[string]interface{}{
4174+
"template": bootstrapResource,
4175+
},
4176+
},
4177+
}
4178+
bootstrapTmpl.SetKind("GenericBootstrapConfigTemplate")
4179+
bootstrapTmpl.SetAPIVersion(clusterv1.GroupVersionBootstrap.String())
4180+
bootstrapTmpl.SetName("ms-template")
4181+
bootstrapTmpl.SetNamespace(metav1.NamespaceDefault)
4182+
4183+
// Create infrastructure template resource.
4184+
infraResource := map[string]interface{}{
4185+
"kind": "GenericInfrastructureMachine",
4186+
"apiVersion": clusterv1.GroupVersionInfrastructure.String(),
4187+
"spec": map[string]interface{}{},
4188+
}
4189+
infraTmpl := &unstructured.Unstructured{
4190+
Object: map[string]interface{}{
4191+
"spec": map[string]interface{}{
4192+
"template": infraResource,
4193+
},
4194+
},
4195+
}
4196+
infraTmpl.SetKind("GenericInfrastructureMachineTemplate")
4197+
infraTmpl.SetAPIVersion(clusterv1.GroupVersionInfrastructure.String())
4198+
infraTmpl.SetName("ms-template")
4199+
infraTmpl.SetNamespace(metav1.NamespaceDefault)
4200+
4201+
// Create a MachineSet with a specific version and failure domain
4202+
machineSet := &clusterv1.MachineSet{
4203+
ObjectMeta: metav1.ObjectMeta{
4204+
GenerateName: "ms-",
4205+
Namespace: metav1.NamespaceDefault,
4206+
},
4207+
Spec: clusterv1.MachineSetSpec{
4208+
ClusterName: testClusterName,
4209+
Template: clusterv1.MachineTemplateSpec{
4210+
Spec: clusterv1.MachineSpec{
4211+
ClusterName: testClusterName,
4212+
InfrastructureRef: clusterv1.ContractVersionedObjectReference{
4213+
Kind: "GenericInfrastructureMachineTemplate",
4214+
Name: "ms-template",
4215+
APIGroup: clusterv1.GroupVersionInfrastructure.Group,
4216+
},
4217+
Bootstrap: clusterv1.Bootstrap{
4218+
ConfigRef: clusterv1.ContractVersionedObjectReference{
4219+
Kind: "GenericBootstrapConfigTemplate",
4220+
Name: "ms-template",
4221+
APIGroup: clusterv1.GroupVersionBootstrap.Group,
4222+
},
4223+
},
4224+
Version: "v1.20.0",
4225+
FailureDomain: "failure-domain-1",
4226+
},
4227+
},
4228+
},
4229+
}
4230+
4231+
bootstrapObj := &unstructured.Unstructured{
4232+
Object: bootstrapResource["spec"].(map[string]interface{}),
4233+
}
4234+
bootstrapObj.SetKind(builder.GenericBootstrapConfigKind)
4235+
bootstrapObj.SetAPIVersion(clusterv1.GroupVersionBootstrap.String())
4236+
bootstrapObj.SetNamespace(metav1.NamespaceDefault)
4237+
bootstrapObj.SetName("current-machine")
4238+
4239+
infraObj := &unstructured.Unstructured{
4240+
Object: infraResource["spec"].(map[string]interface{}),
4241+
}
4242+
infraObj.SetKind(builder.GenericInfrastructureMachineKind)
4243+
infraObj.SetAPIVersion(clusterv1.GroupVersionInfrastructure.String())
4244+
infraObj.SetNamespace(metav1.NamespaceDefault)
4245+
infraObj.SetName("current-machine")
4246+
4247+
// Create a Machine with a different version and failure domain
4248+
machine := &clusterv1.Machine{
4249+
ObjectMeta: metav1.ObjectMeta{
4250+
Name: "current-machine",
4251+
Namespace: metav1.NamespaceDefault,
4252+
},
4253+
Spec: clusterv1.MachineSpec{
4254+
InfrastructureRef: clusterv1.ContractVersionedObjectReference{
4255+
Kind: "GenericInfrastructureMachine",
4256+
Name: "current-machine",
4257+
APIGroup: clusterv1.GroupVersionInfrastructure.Group,
4258+
},
4259+
Bootstrap: clusterv1.Bootstrap{
4260+
ConfigRef: clusterv1.ContractVersionedObjectReference{
4261+
Kind: "GenericBootstrapConfig",
4262+
Name: "current-machine",
4263+
APIGroup: clusterv1.GroupVersionBootstrap.Group,
4264+
},
4265+
},
4266+
ClusterName: testClusterName,
4267+
Version: "v1.19.0",
4268+
FailureDomain: "failure-domain-2",
4269+
},
4270+
}
4271+
4272+
fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(
4273+
builder.GenericBootstrapConfigCRD,
4274+
builder.GenericInfrastructureMachineCRD,
4275+
builder.GenericBootstrapConfigTemplateCRD,
4276+
builder.GenericInfrastructureMachineTemplateCRD,
4277+
bootstrapTmpl,
4278+
infraTmpl,
4279+
bootstrapObj,
4280+
infraObj,
4281+
testCluster,
4282+
machineSet,
4283+
machine,
4284+
).Build()
4285+
msr := &Reconciler{
4286+
Client: fakeClient,
4287+
recorder: record.NewFakeRecorder(32),
4288+
}
4289+
4290+
s := &scope{
4291+
machineSet: machineSet,
4292+
machines: []*clusterv1.Machine{machine},
4293+
getAndAdoptMachinesForMachineSetSucceeded: true,
4294+
}
4295+
4296+
err := msr.completeMoveMachine(ctx, s, machine)
4297+
g.Expect(err).ToNot(HaveOccurred())
4298+
4299+
g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(bootstrapObj), bootstrapObj)).To(Succeed())
4300+
g.Expect(bootstrapObj.GetAnnotations()).To(HaveKeyWithValue(clusterv1.UpdateInProgressAnnotation, ""))
4301+
4302+
g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(infraObj), infraObj)).To(Succeed())
4303+
g.Expect(infraObj.GetAnnotations()).To(HaveKeyWithValue(clusterv1.UpdateInProgressAnnotation, ""))
4304+
4305+
g.Expect(fakeClient.Get(ctx, client.ObjectKeyFromObject(machine), machine)).To(Succeed())
4306+
g.Expect(machine.Spec.Version).To(Equal(machineSet.Spec.Template.Spec.Version))
4307+
g.Expect(machine.Spec.FailureDomain).To(Equal(machineSet.Spec.Template.Spec.FailureDomain))
4308+
}

0 commit comments

Comments
 (0)