@@ -32,6 +32,7 @@ import (
3232 "k8s.io/apimachinery/pkg/runtime"
3333 client "sigs.k8s.io/controller-runtime/pkg/client"
3434 "sigs.k8s.io/controller-runtime/pkg/client/fake"
35+ "sigs.k8s.io/controller-runtime/pkg/client/interceptor"
3536 reconcile "sigs.k8s.io/controller-runtime/pkg/reconcile"
3637
3738 crapi "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/crapi"
@@ -61,6 +62,7 @@ func TestHandleInitial(t *testing.T) {
6162 flexCluster * akov2generated.FlexCluster
6263 kubeObjects []client.Object
6364 atlasCreateFlexClusterFunc func () (* v20250312sdk.FlexClusterDescription20241113 , * http.Response , error )
65+ interceptorFuncs * interceptor.Funcs
6466 want ctrlstate.Result
6567 wantErr string
6668 }{
@@ -123,9 +125,26 @@ func TestHandleInitial(t *testing.T) {
123125 want : ctrlstate.Result {NextState : state .StateInitial },
124126 wantErr : "failed to create flex cluster" ,
125127 },
128+ {
129+ title : "patch status fails" ,
130+ flexCluster : defaultTestFlexCluster (testClusterName , testNamespace ),
131+ kubeObjects : []client.Object {
132+ defaultTestGroup (testGroupName , testNamespace , nil ),
133+ },
134+ atlasCreateFlexClusterFunc : func () (* v20250312sdk.FlexClusterDescription20241113 , * http.Response , error ) {
135+ return & v20250312sdk.FlexClusterDescription20241113 {Id : pointer .MakePtr (testClusterName )}, nil , nil
136+ },
137+ interceptorFuncs : & interceptor.Funcs {
138+ SubResourcePatch : func (ctx context.Context , client client.Client , subResourceName string , obj client.Object , patch client.Patch , opts ... client.SubResourcePatchOption ) error {
139+ return fmt .Errorf ("simulated status patch failure" )
140+ },
141+ },
142+ want : ctrlstate.Result {NextState : state .StateInitial },
143+ wantErr : "failed to patch flex cluster status" ,
144+ },
126145 } {
127146 t .Run (tc .title , func (t * testing.T ) {
128- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
147+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , tc . interceptorFuncs )
129148
130149 flexAPI := mockadmin .NewFlexClustersApi (t )
131150 if tc .atlasCreateFlexClusterFunc != nil {
@@ -215,7 +234,7 @@ func TestHandleImportRequested(t *testing.T) {
215234 },
216235 } {
217236 t .Run (tc .title , func (t * testing.T ) {
218- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
237+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
219238
220239 flexAPI := mockadmin .NewFlexClustersApi (t )
221240 if tc .atlasGetFlexClusterFunc != nil {
@@ -284,7 +303,7 @@ func TestHandleCreating(t *testing.T) {
284303 },
285304 } {
286305 t .Run (tc .title , func (t * testing.T ) {
287- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
306+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
288307
289308 flexAPI := mockadmin .NewFlexClustersApi (t )
290309 if tc .atlasGetFlexClusterFunc != nil {
@@ -347,7 +366,7 @@ func TestHandleUpdating(t *testing.T) {
347366 },
348367 } {
349368 t .Run (tc .title , func (t * testing.T ) {
350- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
369+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
351370
352371 flexAPI := mockadmin .NewFlexClustersApi (t )
353372 if tc .atlasGetFlexClusterFunc != nil {
@@ -377,19 +396,19 @@ func TestHandleCreated(t *testing.T) {
377396 flexCluster * akov2generated.FlexCluster
378397 kubeObjects []client.Object
379398 atlasUpdateFlexClusterFunc func () (* v20250312sdk.FlexClusterDescription20241113 , * http.Response , error )
380- skipStatusSubresource bool
399+ interceptorFuncs * interceptor. Funcs
381400 want ctrlstate.Result
382401 wantErr string
383402 }{
384403 {
385404 title : "no update needed" ,
386- flexCluster : withObservedGeneration (
405+ flexCluster : withStateTracker ( withObservedGeneration (
387406 withGeneration (
388407 setGroupRef (defaultTestFlexCluster (testClusterName , testNamespace ), testGroupName ),
389408 1 ,
390409 ),
391410 1 ,
392- ),
411+ )) ,
393412 kubeObjects : []client.Object {
394413 defaultTestGroup (testGroupName , testNamespace , pointer .MakePtr (testGroupID )),
395414 },
@@ -510,13 +529,17 @@ func TestHandleCreated(t *testing.T) {
510529 StateName : pointer .MakePtr ("IDLE" ),
511530 }, nil , nil
512531 },
513- skipStatusSubresource : true ,
514- want : errorResult (state .StateCreated ),
515- wantErr : "failed to patch cluster status" ,
532+ interceptorFuncs : & interceptor.Funcs {
533+ SubResourcePatch : func (ctx context.Context , client client.Client , subResourceName string , obj client.Object , patch client.Patch , opts ... client.SubResourcePatchOption ) error {
534+ return fmt .Errorf ("simulated status patch failure" )
535+ },
536+ },
537+ want : errorResult (state .StateCreated ),
538+ wantErr : "failed to patch cluster" ,
516539 },
517540 } {
518541 t .Run (tc .title , func (t * testing.T ) {
519- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , tc .skipStatusSubresource )
542+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , tc .interceptorFuncs )
520543
521544 flexAPI := mockadmin .NewFlexClustersApi (t )
522545 if tc .atlasUpdateFlexClusterFunc != nil {
@@ -551,13 +574,13 @@ func TestHandleImported(t *testing.T) {
551574 }{
552575 {
553576 title : "no update needed" ,
554- flexCluster : withObservedGeneration (
577+ flexCluster : withStateTracker ( withObservedGeneration (
555578 withGeneration (
556579 setGroupRef (defaultTestFlexCluster (testClusterName , testNamespace ), testGroupName ),
557580 1 ,
558581 ),
559582 1 ,
560- ),
583+ )) ,
561584 kubeObjects : []client.Object {
562585 defaultTestGroup (testGroupName , testNamespace , pointer .MakePtr (testGroupID )),
563586 },
@@ -585,7 +608,7 @@ func TestHandleImported(t *testing.T) {
585608 },
586609 } {
587610 t .Run (tc .title , func (t * testing.T ) {
588- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
611+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
589612
590613 flexAPI := mockadmin .NewFlexClustersApi (t )
591614 if tc .atlasUpdateFlexClusterFunc != nil {
@@ -620,13 +643,13 @@ func TestHandleUpdated(t *testing.T) {
620643 }{
621644 {
622645 title : "no update needed" ,
623- flexCluster : withObservedGeneration (
646+ flexCluster : withStateTracker ( withObservedGeneration (
624647 withGeneration (
625648 setGroupRef (defaultTestFlexCluster (testClusterName , testNamespace ), testGroupName ),
626649 1 ,
627650 ),
628651 1 ,
629- ),
652+ )) ,
630653 kubeObjects : []client.Object {
631654 defaultTestGroup (testGroupName , testNamespace , pointer .MakePtr (testGroupID )),
632655 },
@@ -654,7 +677,7 @@ func TestHandleUpdated(t *testing.T) {
654677 },
655678 } {
656679 t .Run (tc .title , func (t * testing.T ) {
657- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
680+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
658681
659682 flexAPI := mockadmin .NewFlexClustersApi (t )
660683 if tc .atlasUpdateFlexClusterFunc != nil {
@@ -795,7 +818,7 @@ func TestHandleDeletionRequested(t *testing.T) {
795818 },
796819 } {
797820 t .Run (tc .title , func (t * testing.T ) {
798- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
821+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
799822
800823 flexAPI := mockadmin .NewFlexClustersApi (t )
801824 if tc .atlasDeleteFlexClusterFunc != nil {
@@ -888,7 +911,7 @@ func TestHandleDeleting(t *testing.T) {
888911 },
889912 } {
890913 t .Run (tc .title , func (t * testing.T ) {
891- fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , false )
914+ fakeClient := fixture .buildFakeClient (tc .flexCluster , tc .kubeObjects , nil )
892915
893916 flexAPI := mockadmin .NewFlexClustersApi (t )
894917 if tc .atlasGetFlexClusterFunc != nil {
@@ -930,17 +953,18 @@ func setupTestFixture(t *testing.T) *testFixture {
930953 return fixture
931954}
932955
933- // buildFakeClient creates a fake Kubernetes client with the given objects
934- func (f * testFixture ) buildFakeClient (flexCluster * akov2generated.FlexCluster , kubeObjects []client.Object , skipStatusSubresource bool ) client.Client {
956+ // buildFakeClient creates a fake Kubernetes client with the given objects and optional interceptor
957+ func (f * testFixture ) buildFakeClient (flexCluster * akov2generated.FlexCluster , kubeObjects []client.Object , funcs * interceptor. Funcs ) client.Client {
935958 allObjects := kubeObjects
936959 clientBuilder := fake .NewClientBuilder ().WithScheme (f .scheme )
937960
961+ if funcs != nil {
962+ clientBuilder = clientBuilder .WithInterceptorFuncs (* funcs )
963+ }
964+
938965 if flexCluster != nil {
939966 allObjects = append ([]client.Object {flexCluster }, kubeObjects ... )
940- clientBuilder = clientBuilder .WithObjects (allObjects ... )
941- if ! skipStatusSubresource {
942- clientBuilder = clientBuilder .WithStatusSubresource (flexCluster )
943- }
967+ clientBuilder = clientBuilder .WithObjects (allObjects ... ).WithStatusSubresource (flexCluster )
944968 } else {
945969 clientBuilder = clientBuilder .WithObjects (allObjects ... )
946970 }
@@ -1117,3 +1141,12 @@ func withResourcePolicyKeep(flexCluster *akov2generated.FlexCluster) *akov2gener
11171141 flexCluster .Annotations ["mongodb.com/atlas-resource-policy" ] = "keep"
11181142 return flexCluster
11191143}
1144+
1145+ // withStateTracker adds the state tracker annotation to simulate a previously reconciled object
1146+ func withStateTracker (flexCluster * akov2generated.FlexCluster , deps ... client.Object ) * akov2generated.FlexCluster {
1147+ if flexCluster .Annotations == nil {
1148+ flexCluster .Annotations = make (map [string ]string )
1149+ }
1150+ flexCluster .Annotations [ctrlstate .AnnotationStateTracker ] = ctrlstate .ComputeStateTracker (flexCluster , deps ... )
1151+ return flexCluster
1152+ }
0 commit comments