Skip to content

Commit a2330e6

Browse files
author
Mykhailo Pechkurov
committed
Simplify the solution
1 parent 75088d8 commit a2330e6

2 files changed

Lines changed: 20 additions & 150 deletions

File tree

internal/controller/serviceinstance/controller.go

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -136,31 +136,6 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
136136
// Check if the external resource exists
137137
guid := meta.GetExternalName(cr)
138138

139-
// Deletion fast‑path:
140-
// If the object has a deletion timestamp we only need to know whether the external
141-
// resource still exists; we skip secret resolution, drift detection and state logic.
142-
if meta.WasDeleted(cr) {
143-
r, err := serviceinstance.GetByIDOrSpec(ctx, c.serviceinstance, guid, cr.Spec.ForProvider)
144-
if err != nil {
145-
if clients.ErrorIsNotFound(err) {
146-
// Already gone externally; no delete call needed.
147-
return managed.ExternalObservation{ResourceExists: false}, nil
148-
}
149-
return managed.ExternalObservation{}, errors.Wrap(err, errGet)
150-
}
151-
if r == nil {
152-
return managed.ExternalObservation{ResourceExists: false}, nil
153-
}
154-
if guid != r.GUID {
155-
meta.SetExternalName(cr, r.GUID)
156-
if err := c.kube.Update(ctx, cr); err != nil {
157-
return managed.ExternalObservation{}, errors.Wrap(err, errUpdateCR)
158-
}
159-
}
160-
// We deliberately report up-to-date; reconciler will invoke Delete().
161-
return managed.ExternalObservation{ResourceExists: true, ResourceUpToDate: true}, nil
162-
}
163-
164139
// Normal (non‑deletion) observe path.
165140
r, err := serviceinstance.GetByIDOrSpec(ctx, c.serviceinstance, guid, cr.Spec.ForProvider)
166141
if err != nil {
@@ -183,6 +158,13 @@ func (c *external) Observe(ctx context.Context, mg resource.Managed) (managed.Ex
183158
// Update atProvider from the retrieved the service instance
184159
serviceinstance.UpdateObservation(&cr.Status.AtProvider, r)
185160

161+
// If the CR is marked for deletion we stop normal observe logic.
162+
// We report "resource exists" so Crossplane will call Delete() next.
163+
// (Delete() will handle a "not found" case safely, so we don't check again here.)
164+
if meta.WasDeleted(mg) {
165+
return managed.ExternalObservation{ResourceExists: true}, nil
166+
}
167+
186168
switch r.LastOperation.State {
187169
case v1alpha1.LastOperationInitial, v1alpha1.LastOperationInProgress:
188170
// Set the CR to unavailable and signal that the reconciler should not update the resource

internal/controller/serviceinstance/controller_test.go

Lines changed: 13 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -392,41 +392,7 @@ func TestObserve(t *testing.T) {
392392
withExternalName(guid),
393393
withSpace(spaceGUID),
394394
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
395-
withDeletionTimestamp(), // mark as deleting
396-
),
397-
},
398-
want: want{
399-
mg: serviceInstance("managed",
400-
withExternalName(guid),
401-
withSpace(spaceGUID),
402-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
403-
withDeletionTimestamp(),
404-
),
405-
obs: managed.ExternalObservation{ResourceExists: true, ResourceUpToDate: true},
406-
err: nil,
407-
},
408-
service: func() *fake.MockServiceInstance {
409-
m := &fake.MockServiceInstance{}
410-
m.On("Get", guid).Return(
411-
&fake.NewServiceInstance("managed").
412-
SetName(name).
413-
SetGUID(guid).
414-
SetServicePlan(servicePlan).
415-
SetLastOperation(v1alpha1.LastOperationCreate, v1alpha1.LastOperationSucceeded).ServiceInstance,
416-
nil,
417-
)
418-
// Single() normally not called if Get by GUID succeeds; keep a safe default.
419-
m.On("Single").Return(fake.ServiceInstanceNil, fake.ErrNoResultReturned)
420-
return m
421-
},
422-
},
423-
"DeletionFastPath_NotFound": {
424-
args: args{
425-
mg: serviceInstance("managed",
426-
withExternalName(guid),
427-
withSpace(spaceGUID),
428-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
429-
withDeletionTimestamp(),
395+
withDeletionTimestamp(), // triggers meta.WasDeleted short-circuit
430396
),
431397
},
432398
want: want{
@@ -435,103 +401,30 @@ func TestObserve(t *testing.T) {
435401
withSpace(spaceGUID),
436402
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
437403
withDeletionTimestamp(),
404+
// Status updated by UpdateObservation before early return
405+
withStatus(v1alpha1.ServiceInstanceObservation{ID: &guid, ServicePlan: &servicePlan}),
438406
),
439-
obs: managed.ExternalObservation{ResourceExists: false},
407+
// Early return only sets ResourceExists: true
408+
obs: managed.ExternalObservation{ResourceExists: true},
440409
err: nil,
441410
},
442411
service: func() *fake.MockServiceInstance {
443412
m := &fake.MockServiceInstance{}
444413
m.On("Get", guid).Return(
445-
fake.ServiceInstanceNil,
446-
fake.ErrNoResultReturned,
447-
)
448-
m.On("Single").Return(
449-
fake.ServiceInstanceNil,
450-
fake.ErrNoResultReturned,
451-
)
452-
return m
453-
},
454-
},
455-
"DeletionFastPath_AdoptExternalName": {
456-
args: args{
457-
mg: serviceInstance("managed",
458-
withExternalName("not-guid"), // force mismatch
459-
withSpace(spaceGUID),
460-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
461-
withDeletionTimestamp(), // trigger deletion fast-path
462-
),
463-
},
464-
want: want{
465-
mg: serviceInstance("managed",
466-
withExternalName(guid), // updated annotation expected
467-
withSpace(spaceGUID),
468-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
469-
withDeletionTimestamp(),
470-
),
471-
obs: managed.ExternalObservation{ResourceExists: true, ResourceUpToDate: true},
472-
err: nil,
473-
},
474-
service: func() *fake.MockServiceInstance {
475-
m := &fake.MockServiceInstance{}
476-
m.On("Get", "not-guid").Return(
477-
fake.ServiceInstanceNil,
478-
fake.ErrNoResultReturned, // fall back to Single()
479-
)
480-
m.On("Single").Return(
414+
// LastOperationFailed + Create would have produced ResourceExists:false in the normal path,
415+
// proving we exited early.
481416
&fake.NewServiceInstance("managed").
482417
SetName(name).
483418
SetGUID(guid).
484419
SetServicePlan(servicePlan).
485-
SetLastOperation(v1alpha1.LastOperationCreate, v1alpha1.LastOperationSucceeded).
486-
ServiceInstance,
487-
nil,
488-
)
489-
return m
490-
},
491-
kube: &test.MockClient{
492-
MockUpdate: test.NewMockUpdateFn(nil), // successful update
493-
},
494-
},
495-
"DeletionFastPath_AdoptExternalNameUpdateError": {
496-
args: args{
497-
mg: serviceInstance("managed",
498-
withExternalName("not-guid"),
499-
withSpace(spaceGUID),
500-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
501-
withDeletionTimestamp(),
502-
),
503-
},
504-
want: want{
505-
mg: serviceInstance("managed",
506-
// meta.SetExternalName already applied in-memory even though Update fails
507-
withExternalName(guid),
508-
withSpace(spaceGUID),
509-
withServicePlan(v1alpha1.ServicePlanParameters{ID: &servicePlan}),
510-
withDeletionTimestamp(),
511-
),
512-
obs: managed.ExternalObservation{}, // aborted with error
513-
err: errors.Wrap(errBoom, errUpdateCR), // wrapped update error
514-
},
515-
service: func() *fake.MockServiceInstance {
516-
m := &fake.MockServiceInstance{}
517-
m.On("Get", "not-guid").Return(
518-
fake.ServiceInstanceNil,
519-
fake.ErrNoResultReturned,
520-
)
521-
m.On("Single").Return(
522-
&fake.NewServiceInstance("managed").
523-
SetName(name).
524-
SetGUID(guid).
525-
SetServicePlan(servicePlan).
526-
SetLastOperation(v1alpha1.LastOperationCreate, v1alpha1.LastOperationSucceeded).
420+
SetLastOperation(v1alpha1.LastOperationCreate, v1alpha1.LastOperationFailed).
527421
ServiceInstance,
528422
nil,
529423
)
424+
// Fallback shouldn't be called, keep safe default.
425+
m.On("Single").Return(fake.ServiceInstanceNil, fake.ErrNoResultReturned)
530426
return m
531427
},
532-
kube: &test.MockClient{
533-
MockUpdate: test.NewMockUpdateFn(errBoom), // force failure -> cover error wrap
534-
},
535428
},
536429
"DriftDetectionLoop": {
537430
args: args{
@@ -603,15 +496,10 @@ func TestObserve(t *testing.T) {
603496
for n, tc := range cases {
604497
t.Run(n, func(t *testing.T) {
605498
t.Logf("Testing: %s", t.Name())
606-
607-
kubeClient := tc.kube
608-
if kubeClient == nil {
609-
kubeClient = &test.MockClient{
610-
MockUpdate: test.NewMockUpdateFn(nil),
611-
}
612-
}
613499
c := &external{
614-
kube: kubeClient,
500+
kube: &test.MockClient{
501+
MockUpdate: test.NewMockUpdateFn(nil),
502+
},
615503
serviceinstance: &serviceinstance.Client{
616504
ServiceInstance: tc.service(),
617505
Job: nil,

0 commit comments

Comments
 (0)