From 74bfd71de19b58e83666133aa093b0f1387018be Mon Sep 17 00:00:00 2001 From: Davide Imola Date: Wed, 24 Mar 2021 22:07:11 +0100 Subject: [PATCH] Fix the observedGeneration update --- .../kubeadm/controllers/controller.go | 1 + .../kubeadm/controllers/controller_test.go | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/controlplane/kubeadm/controllers/controller.go b/controlplane/kubeadm/controllers/controller.go index fbc8263ba8d8..7168f88e2de3 100644 --- a/controlplane/kubeadm/controllers/controller.go +++ b/controlplane/kubeadm/controllers/controller.go @@ -235,6 +235,7 @@ func patchKubeadmControlPlane(ctx context.Context, patchHelper *patch.Helper, kc controlplanev1.AvailableCondition, controlplanev1.CertificatesAvailableCondition, }}, + patch.WithStatusObservedGeneration{}, ) } diff --git a/controlplane/kubeadm/controllers/controller_test.go b/controlplane/kubeadm/controllers/controller_test.go index e50d5f77bc22..cc9f5652585d 100644 --- a/controlplane/kubeadm/controllers/controller_test.go +++ b/controlplane/kubeadm/controllers/controller_test.go @@ -174,6 +174,61 @@ func TestClusterToKubeadmControlPlaneOtherControlPlane(t *testing.T) { g.Expect(got).To(BeNil()) } +func TestReconcileUpdateObservedGeneration(t *testing.T) { + g := NewWithT(t) + r := &KubeadmControlPlaneReconciler{ + Client: testEnv, + recorder: record.NewFakeRecorder(32), + managementCluster: &internal.Management{Client: testEnv.Client}, + Log: log.NullLogger{}, + } + ctx := context.TODO() + + cluster, kcp, _ := createClusterWithControlPlane() + g.Expect(testEnv.CreateObj(ctx, cluster)).To(Succeed()) + g.Expect(testEnv.CreateObj(ctx, kcp)).To(Succeed()) + + // read kcp.Generation after create + errGettingObject := testEnv.Get(ctx, util.ObjectKey(kcp), kcp) + g.Expect(errGettingObject).NotTo(HaveOccurred()) + generation := kcp.Generation + + // Set cluster.status.InfrastructureReady so we actually enter in the reconcile loop + patch := client.RawPatch(types.MergePatchType, []byte(fmt.Sprintf("{\"status\":{\"infrastructureReady\":%t}}", true))) + g.Expect(testEnv.Status().Patch(ctx, cluster, patch)).To(Succeed()) + + // call reconcile the first time, so we can check if observedGeneration is set when adding a finalizer + result, err := r.Reconcile(ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(result).To(Equal(ctrl.Result{})) + + g.Eventually(func() int64 { + errGettingObject = testEnv.Get(ctx, util.ObjectKey(kcp), kcp) + g.Expect(errGettingObject).NotTo(HaveOccurred()) + return kcp.Status.ObservedGeneration + }, 10*time.Second).Should(Equal(generation)) + + // triggers a generation change by changing the spec + kcp.Spec.Replicas = pointer.Int32Ptr(*kcp.Spec.Replicas + 2) + g.Expect(testEnv.Update(ctx, kcp)).To(Succeed()) + + // read kcp.Generation after the update + errGettingObject = testEnv.Get(ctx, util.ObjectKey(kcp), kcp) + g.Expect(errGettingObject).NotTo(HaveOccurred()) + generation = kcp.Generation + + // call reconcile the second time, so we can check if observedGeneration is set when calling defer patch + // NB. The call to reconcile fails because KCP is not properly setup (e.g. missing InfrastructureTemplate) + // but this is not important because what we want is KCP to be patched + _, _ = r.Reconcile(ctrl.Request{NamespacedName: util.ObjectKey(kcp)}) + + g.Eventually(func() int64 { + errGettingObject = testEnv.Get(ctx, util.ObjectKey(kcp), kcp) + g.Expect(errGettingObject).NotTo(HaveOccurred()) + return kcp.Status.ObservedGeneration + }, 10*time.Second).Should(Equal(generation)) +} + func TestReconcileNoClusterOwnerRef(t *testing.T) { g := NewWithT(t)