@@ -174,6 +174,61 @@ func TestClusterToKubeadmControlPlaneOtherControlPlane(t *testing.T) {
174174 g .Expect (got ).To (BeNil ())
175175}
176176
177+ func TestReconcileUpdateObservedGeneration (t * testing.T ) {
178+ g := NewWithT (t )
179+ r := & KubeadmControlPlaneReconciler {
180+ Client : testEnv ,
181+ recorder : record .NewFakeRecorder (32 ),
182+ managementCluster : & internal.Management {Client : testEnv .Client },
183+ Log : log.NullLogger {},
184+ }
185+ ctx := context .TODO ()
186+
187+ cluster , kcp , _ := createClusterWithControlPlane ()
188+ g .Expect (testEnv .CreateObj (ctx , cluster )).To (Succeed ())
189+ g .Expect (testEnv .CreateObj (ctx , kcp )).To (Succeed ())
190+
191+ // read kcp.Generation after create
192+ errGettingObject := testEnv .Get (ctx , util .ObjectKey (kcp ), kcp )
193+ g .Expect (errGettingObject ).NotTo (HaveOccurred ())
194+ generation := kcp .Generation
195+
196+ // Set cluster.status.InfrastructureReady so we actually enter in the reconcile loop
197+ patch := client .RawPatch (types .MergePatchType , []byte (fmt .Sprintf ("{\" status\" :{\" infrastructureReady\" :%t}}" , true )))
198+ g .Expect (testEnv .Status ().Patch (ctx , cluster , patch )).To (Succeed ())
199+
200+ // call reconcile the first time, so we can check if observedGeneration is set when adding a finalizer
201+ result , err := r .Reconcile (ctrl.Request {NamespacedName : util .ObjectKey (kcp )})
202+ g .Expect (err ).NotTo (HaveOccurred ())
203+ g .Expect (result ).To (Equal (ctrl.Result {}))
204+
205+ g .Eventually (func () int64 {
206+ errGettingObject = testEnv .Get (ctx , util .ObjectKey (kcp ), kcp )
207+ g .Expect (errGettingObject ).NotTo (HaveOccurred ())
208+ return kcp .Status .ObservedGeneration
209+ }, 10 * time .Second ).Should (Equal (generation ))
210+
211+ // triggers a generation change by changing the spec
212+ kcp .Spec .Replicas = pointer .Int32Ptr (* kcp .Spec .Replicas + 2 )
213+ g .Expect (testEnv .Update (ctx , kcp )).To (Succeed ())
214+
215+ // read kcp.Generation after the update
216+ errGettingObject = testEnv .Get (ctx , util .ObjectKey (kcp ), kcp )
217+ g .Expect (errGettingObject ).NotTo (HaveOccurred ())
218+ generation = kcp .Generation
219+
220+ // call reconcile the second time, so we can check if observedGeneration is set when calling defer patch
221+ // NB. The call to reconcile fails because KCP is not properly setup (e.g. missing InfrastructureTemplate)
222+ // but this is not important because what we want is KCP to be patched
223+ _ , _ = r .Reconcile (ctrl.Request {NamespacedName : util .ObjectKey (kcp )})
224+
225+ g .Eventually (func () int64 {
226+ errGettingObject = testEnv .Get (ctx , util .ObjectKey (kcp ), kcp )
227+ g .Expect (errGettingObject ).NotTo (HaveOccurred ())
228+ return kcp .Status .ObservedGeneration
229+ }, 10 * time .Second ).Should (Equal (generation ))
230+ }
231+
177232func TestReconcileNoClusterOwnerRef (t * testing.T ) {
178233 g := NewWithT (t )
179234
0 commit comments