Skip to content

Commit 87fa8c9

Browse files
kibbles-n-bytespmorie
authored andcommitted
fix status update when starting orphan mitigation (#1372)
* keep InProgressProperties when orphan mitigating * add instance OM handling in API server * add binding OM to API server validation * do not clear IPP for binding OM * add integration test * add tests * format code
1 parent 11f18f3 commit 87fa8c9

11 files changed

+482
-26
lines changed

pkg/apis/servicecatalog/validation/binding.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ func validateServiceBindingStatus(status *sc.ServiceBindingStatus, fldPath *fiel
9595
allErrs = append(allErrs, field.Forbidden(fldPath.Child("operationStartTime"), "operationStartTime must not be present when currentOperation is not present"))
9696
}
9797
} else {
98-
if status.OperationStartTime == nil {
99-
allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present"))
98+
if status.OperationStartTime == nil && !status.OrphanMitigationInProgress {
99+
allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present and no orphan mitigation in progress"))
100100
}
101101
// Do not allow the binding to be ready if there is an on-going operation
102102
for i, c := range status.Conditions {

pkg/apis/servicecatalog/validation/binding_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,45 @@ func TestValidateServiceBinding(t *testing.T) {
412412
create: false,
413413
valid: false,
414414
},
415+
{
416+
name: "failed bind starting orphan mitigation",
417+
binding: func() *servicecatalog.ServiceBinding {
418+
b := validServiceBindingWithInProgressBind()
419+
b.Status.OperationStartTime = nil
420+
b.Status.OrphanMitigationInProgress = true
421+
b.Status.Conditions = []servicecatalog.ServiceBindingCondition{
422+
{
423+
Type: servicecatalog.ServiceBindingConditionReady,
424+
Status: servicecatalog.ConditionFalse,
425+
},
426+
{
427+
Type: servicecatalog.ServiceBindingConditionFailed,
428+
Status: servicecatalog.ConditionTrue,
429+
},
430+
}
431+
return b
432+
}(),
433+
valid: true,
434+
},
435+
{
436+
name: "in-progress orphan mitigation",
437+
binding: func() *servicecatalog.ServiceBinding {
438+
b := validServiceBindingWithInProgressBind()
439+
b.Status.OrphanMitigationInProgress = true
440+
b.Status.Conditions = []servicecatalog.ServiceBindingCondition{
441+
{
442+
Type: servicecatalog.ServiceBindingConditionReady,
443+
Status: servicecatalog.ConditionFalse,
444+
},
445+
{
446+
Type: servicecatalog.ServiceBindingConditionFailed,
447+
Status: servicecatalog.ConditionTrue,
448+
},
449+
}
450+
return b
451+
}(),
452+
valid: true,
453+
},
415454
}
416455

417456
for _, tc := range cases {

pkg/apis/servicecatalog/validation/instance.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ func validateServiceInstanceStatus(status *sc.ServiceInstanceStatus, fldPath *fi
122122
allErrs = append(allErrs, field.Forbidden(fldPath.Child("lastOperation"), "lastOperation cannot be true when currentOperation is not present"))
123123
}
124124
} else {
125-
if status.OperationStartTime == nil {
126-
allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present"))
125+
if status.OperationStartTime == nil && !status.OrphanMitigationInProgress {
126+
allErrs = append(allErrs, field.Required(fldPath.Child("operationStartTime"), "operationStartTime is required when currentOperation is present and no orphan mitigation in progress"))
127127
}
128128
// Do not allow the instance to be ready if there is an on-going operation
129129
for i, c := range status.Conditions {

pkg/apis/servicecatalog/validation/instance_test.go

+39
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,45 @@ func TestValidateServiceInstance(t *testing.T) {
493493
create: true,
494494
valid: false,
495495
},
496+
{
497+
name: "failed provision starting orphan mitigation",
498+
instance: func() *servicecatalog.ServiceInstance {
499+
i := validServiceInstanceWithInProgressProvision()
500+
i.Status.OperationStartTime = nil
501+
i.Status.OrphanMitigationInProgress = true
502+
i.Status.Conditions = []servicecatalog.ServiceInstanceCondition{
503+
{
504+
Type: servicecatalog.ServiceInstanceConditionReady,
505+
Status: servicecatalog.ConditionFalse,
506+
},
507+
{
508+
Type: servicecatalog.ServiceInstanceConditionFailed,
509+
Status: servicecatalog.ConditionTrue,
510+
},
511+
}
512+
return i
513+
}(),
514+
valid: true,
515+
},
516+
{
517+
name: "in-progress orphan mitigation",
518+
instance: func() *servicecatalog.ServiceInstance {
519+
i := validServiceInstanceWithInProgressProvision()
520+
i.Status.OrphanMitigationInProgress = true
521+
i.Status.Conditions = []servicecatalog.ServiceInstanceCondition{
522+
{
523+
Type: servicecatalog.ServiceInstanceConditionReady,
524+
Status: servicecatalog.ConditionFalse,
525+
},
526+
{
527+
Type: servicecatalog.ServiceInstanceConditionFailed,
528+
Status: servicecatalog.ConditionTrue,
529+
},
530+
}
531+
return i
532+
}(),
533+
valid: true,
534+
},
496535
}
497536

498537
for _, tc := range cases {

pkg/controller/controller_binding.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,6 @@ func (c *controller) setAndUpdateOrphanMitigation(binding *v1beta1.ServiceBindin
131131
)
132132
toUpdate.Status.OrphanMitigationInProgress = true
133133
toUpdate.Status.OperationStartTime = nil
134-
toUpdate.Status.InProgressProperties = nil
135134
glog.V(5).Info(s)
136135

137136
c.setServiceBindingCondition(
@@ -544,6 +543,7 @@ func (c *controller) reconcileServiceBinding(binding *v1beta1.ServiceBinding) er
544543
// request, so this is what the Broker knows about the state of the
545544
// binding.
546545
toUpdate.Status.ExternalProperties = toUpdate.Status.InProgressProperties
546+
toUpdate.Status.InProgressProperties = nil
547547

548548
err = c.injectServiceBinding(binding, response.Credentials)
549549
if err != nil {

pkg/controller/controller_binding_test.go

+13-11
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,12 @@ func TestReconcileServiceBindingWithSecretConflict(t *testing.T) {
311311
assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding)
312312

313313
updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding)
314+
314315
assertServiceBindingReadyFalse(t, updatedServiceBinding, errorInjectingBindResultReason)
315316
assertServiceBindingCurrentOperation(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind)
316317
assertServiceBindingOperationStartTimeSet(t, updatedServiceBinding, true)
317318
assertServiceBindingReconciledGeneration(t, updatedServiceBinding, binding.Status.ReconciledGeneration)
318-
assertServiceBindingInProgressPropertiesParameters(t, updatedServiceBinding, nil, "")
319+
assertServiceBindingInProgressPropertiesNil(t, updatedServiceBinding)
319320
// External properties are updated because the bind request with the Broker was successful
320321
assertServiceBindingExternalPropertiesParameters(t, updatedServiceBinding, nil, "")
321322
assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false)
@@ -1979,16 +1980,12 @@ func TestReconcileBindingWithSecretConflictFailedAfterFinalRetry(t *testing.T) {
19791980
assertNumberOfActions(t, actions, 1)
19801981

19811982
updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding)
1982-
assertServiceBindingReadyFalse(t, updatedServiceBinding, errorServiceBindingOrphanMitigation)
1983+
1984+
assertServiceBindingCondition(t, updatedServiceBinding, v1beta1.ServiceBindingConditionReady, v1beta1.ConditionFalse, errorServiceBindingOrphanMitigation)
19831985
assertServiceBindingCondition(t, updatedServiceBinding, v1beta1.ServiceBindingConditionFailed, v1beta1.ConditionTrue, errorReconciliationRetryTimeoutReason)
1984-
assertServiceBindingCurrentOperation(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind)
1985-
assertServiceBindingOperationStartTimeSet(t, updatedServiceBinding, false)
1986-
assertServiceBindingReconciledGeneration(t, updatedServiceBinding, binding.Status.ReconciledGeneration)
1986+
assertServiceBindingStartingOrphanMitigation(t, updatedServiceBinding, binding)
19871987
assertServiceBindingInProgressPropertiesNil(t, updatedServiceBinding)
1988-
// External properties are updated because the bind request with the Broker was successful
19891988
assertServiceBindingExternalPropertiesParameters(t, updatedServiceBinding, nil, "")
1990-
assertServiceBindingCondition(t, updatedServiceBinding, v1beta1.ServiceBindingConditionReady, v1beta1.ConditionFalse, errorServiceBindingOrphanMitigation)
1991-
assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, true)
19921989

19931990
kubeActions := fakeKubeClient.Actions()
19941991
assertNumberOfActions(t, kubeActions, 2)
@@ -2333,10 +2330,15 @@ func TestReconcileBindingWithSetOrphanMitigation(t *testing.T) {
23332330
assertServiceBindingReadyFalse(t, updatedServiceBinding)
23342331

23352332
updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding)
2336-
assertServiceBindingReadyFalse(t, updatedServiceBinding)
2337-
assertServiceBindingCondition(t, updatedServiceBinding, v1beta1.ServiceBindingConditionReady, v1beta1.ConditionFalse)
23382333

2339-
assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, tc.setOrphanMitigation)
2334+
if tc.setOrphanMitigation {
2335+
assertServiceBindingStartingOrphanMitigation(t, updatedServiceBinding, binding)
2336+
} else {
2337+
assertServiceBindingReadyFalse(t, updatedServiceBinding)
2338+
assertServiceBindingCondition(t, updatedServiceBinding, v1beta1.ServiceBindingConditionReady, v1beta1.ConditionFalse)
2339+
assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, tc.setOrphanMitigation)
2340+
assertServiceBindingExternalPropertiesNil(t, updatedServiceBinding)
2341+
}
23402342
}
23412343
}
23422344

pkg/controller/controller_instance.go

-1
Original file line numberDiff line numberDiff line change
@@ -1924,7 +1924,6 @@ func setServiceInstanceStartOrphanMitigation(toUpdate *v1beta1.ServiceInstance)
19241924
toUpdate.Status.OperationStartTime = nil
19251925
toUpdate.Status.AsyncOpInProgress = false
19261926
toUpdate.Status.OrphanMitigationInProgress = true
1927-
toUpdate.Status.InProgressProperties = nil
19281927
}
19291928

19301929
// shouldStartOrphanMitigation returns whether an error with the given status

pkg/controller/controller_instance_test.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -2898,14 +2898,18 @@ func TestReconcileServiceInstanceWithHTTPStatusCodeErrorOrphanMitigation(t *test
28982898
continue
28992899
}
29002900

2901-
if tc.triggersOrphanMitigation && err == nil {
2902-
t.Errorf("%v: Reconciler should return error so that instance is orphan mitigated", tc.name)
2903-
continue
2904-
}
2905-
2906-
if !tc.triggersOrphanMitigation && err != nil {
2907-
t.Errorf("%v: Reconciler should treat as terminal condition and not requeue", tc.name)
2908-
continue
2901+
if tc.triggersOrphanMitigation {
2902+
// TODO(mkibbe): Rework this to be an expects, not asserts
2903+
assertServiceInstanceStartingOrphanMitigation(t, updatedServiceInstance, errorProvisionCallFailedReason, instance)
2904+
if err == nil {
2905+
t.Errorf("%v: Reconciler should return error so that instance is orphan mitigated", tc.name)
2906+
continue
2907+
}
2908+
} else {
2909+
if err != nil {
2910+
t.Errorf("%v: Reconciler should treat as terminal condition and not requeue", tc.name)
2911+
continue
2912+
}
29092913
}
29102914
}
29112915
}

pkg/controller/controller_test.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -1762,6 +1762,14 @@ func assertServiceInstanceOperationInProgressWithParameters(t *testing.T, obj ru
17621762
assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance)
17631763
}
17641764

1765+
func assertServiceInstanceStartingOrphanMitigation(t *testing.T, obj runtime.Object, readyReason string, originalInstance *v1beta1.ServiceInstance) {
1766+
assertServiceInstanceCurrentOperation(t, obj, v1beta1.ServiceInstanceOperationProvision)
1767+
assertServiceInstanceReadyFalse(t, obj, readyReason)
1768+
assertServiceInstanceOperationStartTimeSet(t, obj, false)
1769+
assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Status.ReconciledGeneration)
1770+
assertServiceInstanceOrphanMitigationInProgressTrue(t, obj)
1771+
}
1772+
17651773
func assertServiceInstanceOperationSuccess(t *testing.T, obj runtime.Object, operation v1beta1.ServiceInstanceOperation, planName string, originalInstance *v1beta1.ServiceInstance) {
17661774
assertServiceInstanceOperationSuccessWithParameters(t, obj, operation, planName, nil, "", originalInstance)
17671775
}
@@ -1813,7 +1821,6 @@ func assertServiceInstanceRequestFailingError(t *testing.T, obj runtime.Object,
18131821
assertServiceInstanceCondition(t, obj, v1beta1.ServiceInstanceConditionFailed, v1beta1.ConditionTrue, failureReason)
18141822
assertServiceInstanceOperationStartTimeSet(t, obj, false)
18151823
assertAsyncOpInProgressFalse(t, obj)
1816-
assertServiceInstanceInProgressPropertiesNil(t, obj)
18171824
assertServiceInstanceExternalPropertiesUnchanged(t, obj, originalInstance)
18181825
}
18191826

@@ -1822,6 +1829,7 @@ func assertServiceInstanceRequestFailingErrorNoOrphanMitigation(t *testing.T, ob
18221829
assertServiceInstanceCurrentOperationClear(t, obj)
18231830
assertServiceInstanceReconciledGeneration(t, obj, originalInstance.Generation)
18241831
assertServiceInstanceOrphanMitigationInProgressFalse(t, obj)
1832+
assertServiceInstanceInProgressPropertiesNil(t, obj)
18251833
}
18261834

18271835
func assertServiceInstanceRequestFailingErrorStartOrphanMitigation(t *testing.T, obj runtime.Object, operation v1beta1.ServiceInstanceOperation, readyReason string, failureReason string, originalInstance *v1beta1.ServiceInstance) {
@@ -2148,6 +2156,14 @@ func assertServiceBindingOperationInProgressWithParameters(t *testing.T, obj run
21482156
assertServiceBindingExternalPropertiesUnchanged(t, obj, originalBinding)
21492157
}
21502158

2159+
func assertServiceBindingStartingOrphanMitigation(t *testing.T, obj runtime.Object, originalBinding *v1beta1.ServiceBinding) {
2160+
assertServiceBindingCurrentOperation(t, obj, v1beta1.ServiceBindingOperationBind)
2161+
assertServiceBindingReadyFalse(t, obj, errorServiceBindingOrphanMitigation)
2162+
assertServiceBindingOperationStartTimeSet(t, obj, false)
2163+
assertServiceBindingReconciledGeneration(t, obj, originalBinding.Status.ReconciledGeneration)
2164+
assertServiceBindingOrphanMitigationSet(t, obj, true)
2165+
}
2166+
21512167
func assertServiceBindingOperationSuccess(t *testing.T, obj runtime.Object, operation v1beta1.ServiceBindingOperation, originalBinding *v1beta1.ServiceBinding) {
21522168
assertServiceBindingOperationSuccessWithParameters(t, obj, operation, nil, "", originalBinding)
21532169
}

0 commit comments

Comments
 (0)