From 6426c9829d442b9dcf458deaaffdd28c80090c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20Luk=C5=A1a?= Date: Fri, 9 Mar 2018 22:35:14 +0100 Subject: [PATCH] Controller reconciliation rework - part 2 (ServiceBinding) (#1819) * Controller reconciliation rework - part 2 (ServiceBinding) * Exit the reconciliation loop iteration after each update to ServiceBinding * Validate KubeClient and BrokerClient actions after each invocation of reconcileServiceBinding() * Reduce code duplication in controller_binding_test.go --- pkg/controller/controller_binding.go | 4 + pkg/controller/controller_binding_test.go | 586 ++++++++++++---------- 2 files changed, 328 insertions(+), 262 deletions(-) diff --git a/pkg/controller/controller_binding.go b/pkg/controller/controller_binding.go index f21656e91575..e63f1f70b9bf 100644 --- a/pkg/controller/controller_binding.go +++ b/pkg/controller/controller_binding.go @@ -232,6 +232,8 @@ func (c *controller) reconcileServiceBindingAdd(binding *v1beta1.ServiceBinding) // over with a fresh view of the binding. return err } + // recordStartOfServiceBindingOperation has updated the binding, so we need to continue in the next iteration + return nil } response, err := brokerClient.Bind(request) @@ -342,6 +344,8 @@ func (c *controller) reconcileServiceBindingDelete(binding *v1beta1.ServiceBindi // over with a fresh view of the binding. return err } + // recordStartOfServiceBindingOperation has updated the binding, so we need to continue in the next iteration + return nil } } diff --git a/pkg/controller/controller_binding_test.go b/pkg/controller/controller_binding_test.go index a06262b23066..5ab6a7a792c9 100644 --- a/pkg/controller/controller_binding_test.go +++ b/pkg/controller/controller_binding_test.go @@ -40,6 +40,7 @@ import ( utilfeature "k8s.io/apiserver/pkg/util/feature" scfeatures "github.com/kubernetes-incubator/service-catalog/pkg/features" + "github.com/kubernetes-incubator/service-catalog/test/fake" clientgofake "k8s.io/client-go/kubernetes/fake" clientgotesting "k8s.io/client-go/testing" ) @@ -75,10 +76,6 @@ func TestReconcileServiceBindingNonExistingServiceInstance(t *testing.T) { assertNumberOfActions(t, actions, 1) // There should only be one action that says it failed because no such instance exists. - updateAction := actions[0].(clientgotesting.UpdateAction) - if e, a := "update", updateAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on actions[0]; %s", expectedGot(e, a)) - } updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) assertServiceBindingErrorBeforeRequest(t, updatedServiceBinding, errorNonexistentServiceInstanceReason, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -307,6 +304,17 @@ func TestReconcileServiceBindingWithSecretConflict(t *testing.T) { }, } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err == nil { t.Fatalf("a binding should fail to create a secret: %v", err) @@ -326,12 +334,9 @@ func TestReconcileServiceBindingWithSecretConflict(t *testing.T) { }) actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingReadyFalse(t, updatedServiceBinding, errorInjectingBindResultReason) assertServiceBindingCurrentOperation(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind) @@ -344,16 +349,8 @@ func TestReconcileServiceBindingWithSecretConflict(t *testing.T) { kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 2) - - // first action is a get on the namespace - // second action is a get on the secret - action := kubeActions[1].(clientgotesting.GetAction) - if e, a := "get", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertActionEquals(t, kubeActions[0], "get", "namespaces") + assertActionEquals(t, kubeActions[1], "get", "secrets") events := getRecordedEvents(testController) assertNumEvents(t, events, 1) @@ -413,6 +410,27 @@ func TestReconcileServiceBindingWithParameters(t *testing.T) { } binding.Spec.Parameters = &runtime.RawExtension{Raw: b} + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedParameters := map[string]interface{}{ + "args": []interface{}{ + "first-arg", + "second-arg", + }, + "name": "test-param", + } + expectedParametersChecksum := generateChecksumOfParametersOrFail(t, expectedParameters) + + binding = assertServiceBindingOperationInProgressWithParametersIsTheOnlyCatalogAction(t, fakeCatalogClient, binding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err = testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("a valid binding should not fail: %v", err) @@ -438,41 +456,20 @@ func TestReconcileServiceBindingWithParameters(t *testing.T) { }, }) - expectedParameters := map[string]interface{}{ - "args": []interface{}{ - "first-arg", - "second-arg", - }, - "name": "test-param", - } - expectedParametersChecksum, err := generateChecksumOfParameters(expectedParameters) - if err != nil { - t.Fatalf("Failed to generate parameters checksum: %v", err) - } - actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgressWithParameters(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingOperationSuccessWithParameters(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 3) + assertActionEquals(t, kubeActions[0], "get", "namespaces") + assertActionEquals(t, kubeActions[1], "get", "secrets") + assertActionEquals(t, kubeActions[2], "create", "secrets") - // first action is a get on the namespace - // second action is a get on the secret action := kubeActions[2].(clientgotesting.CreateAction) - if e, a := "create", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } actionSecret, ok := action.GetObject().(*corev1.Secret) if !ok { t.Fatal("couldn't convert secret into a corev1.Secret") @@ -617,6 +614,17 @@ func TestReconcileServiceBindingNonbindableClusterServiceClassBindablePlan(t *te }, } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("A bindable plan overrides the bindability of a service class: %v", err) @@ -636,28 +644,19 @@ func TestReconcileServiceBindingNonbindableClusterServiceClassBindablePlan(t *te }) actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingOperationSuccess(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 3) + assertActionEquals(t, kubeActions[0], "get", "namespaces") + assertActionEquals(t, kubeActions[1], "get", "secrets") + assertActionEquals(t, kubeActions[2], "create", "secrets") - // first action is a get on the namespace - // second action is a get on the secret action := kubeActions[2].(clientgotesting.CreateAction) - if e, a := "create", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } actionSecret, ok := action.GetObject().(*corev1.Secret) if !ok { t.Fatal("couldn't convert secret into a corev1.Secret") @@ -894,6 +893,17 @@ func TestReconcileServiceBindingDelete(t *testing.T) { return true, binding, nil }) + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v", err) @@ -911,27 +921,18 @@ func TestReconcileServiceBindingDelete(t *testing.T) { kubeActions := fakeKubeClient.Actions() // The action should be deleting the secret assertNumberOfActions(t, kubeActions, 1) + assertActionEquals(t, kubeActions[0], "delete", "secrets") deleteAction := kubeActions[0].(clientgotesting.DeleteActionImpl) - if e, a := "delete", deleteAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on kubeActions[1]; %s", expectedGot(e, a)) - } - if e, a := binding.Spec.SecretName, deleteAction.Name; e != a { t.Fatalf("Unexpected name of secret: %s", expectedGot(e, a)) } actions := fakeCatalogClient.Actions() - // The actions should be: - // 0. Updating the current operation - // 1. Updating the ready condition - assertNumberOfActions(t, actions, 2) + // The action should be updating the ready condition + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingOperationSuccess(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1164,6 +1165,17 @@ func TestReconcileServiceBindingDeleteFailedServiceBinding(t *testing.T) { return true, binding, nil }) + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v", err) @@ -1195,13 +1207,9 @@ func TestReconcileServiceBindingDeleteFailedServiceBinding(t *testing.T) { // The four actions should be: // 0. Updating the current operation // 1. Updating the ready condition - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingOperationSuccess(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1250,19 +1258,21 @@ func TestReconcileServiceBindingWithClusterServiceBrokerError(t *testing.T) { }, } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + err := testController.reconcileServiceBinding(binding) if err == nil { t.Fatal("reconcileServiceBinding should have returned an error") } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestRetriableError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, errorBindCallReason, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1314,19 +1324,21 @@ func TestReconcileServiceBindingWithClusterServiceBrokerHTTPError(t *testing.T) }, } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatal("reconcileServiceBinding should not have returned an error") } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestFailingError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, errorBindCallReason, "ServiceBindingReturnedFailure", binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1387,6 +1399,17 @@ func TestReconcileServiceBindingWithServiceBindingCallFailure(t *testing.T) { binding := getTestServiceBinding() + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + if err := testController.reconcileServiceBinding(binding); err == nil { t.Fatal("ServiceBinding creation should fail") } @@ -1400,13 +1423,9 @@ func TestReconcileServiceBindingWithServiceBindingCallFailure(t *testing.T) { } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestRetriableError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, errorBindCallReason, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1454,6 +1473,17 @@ func TestReconcileServiceBindingWithServiceBindingFailure(t *testing.T) { binding := getTestServiceBinding() + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + if err := testController.reconcileServiceBinding(binding); err != nil { t.Fatalf("ServiceBinding creation should complete: %v", err) } @@ -1467,13 +1497,9 @@ func TestReconcileServiceBindingWithServiceBindingFailure(t *testing.T) { } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestFailingError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, errorBindCallReason, "ServiceBindingReturnedFailure", binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1686,18 +1712,21 @@ func TestReconcileUnbindingWithClusterServiceBrokerError(t *testing.T) { if err := scmeta.AddFinalizer(binding, v1beta1.FinalizerServiceCatalog); err != nil { t.Fatalf("Finalizer error: %v", err) } + + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + if err := testController.reconcileServiceBinding(binding); err == nil { t.Fatal("reconcileServiceBinding should have returned an error") } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestRetriableError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, errorUnbindCallReason, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1751,18 +1780,21 @@ func TestReconcileUnbindingWithClusterServiceBrokerHTTPError(t *testing.T) { if err := scmeta.AddFinalizer(binding, v1beta1.FinalizerServiceCatalog); err != nil { t.Fatalf("Finalizer error: %v", err) } + + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + if err := testController.reconcileServiceBinding(binding); err == nil { t.Fatalf("reconcileServiceBinding should have returned an error") } actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingRequestRetriableError(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, errorUnbindCallReason, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -1785,7 +1817,7 @@ func TestReconcileBindingUsingOriginatingIdentity(t *testing.T) { defer utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=false", scfeatures.OriginatingIdentity)) } - fakeKubeClient, _, fakeBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ + fakeKubeClient, fakeCatalogClient, fakeBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ BindReaction: &fakeosb.BindReaction{ Response: &osb.BindResponse{}, }, @@ -1804,6 +1836,17 @@ func TestReconcileBindingUsingOriginatingIdentity(t *testing.T) { binding.Spec.UserInfo = testUserInfo } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v: a valid binding should not fail: %v", tc.name, err) @@ -1836,7 +1879,7 @@ func TestReconcileBindingDeleteUsingOriginatingIdentity(t *testing.T) { defer utilfeature.DefaultFeatureGate.Set(fmt.Sprintf("%v=false", scfeatures.OriginatingIdentity)) } - fakeKubeClient, _, fakeBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ + fakeKubeClient, fakeCatalogClient, fakeBrokerClient, testController, sharedInformers := newTestController(t, fakeosb.FakeClientConfiguration{ UnbindReaction: &fakeosb.UnbindReaction{ Response: &osb.UnbindResponse{}, }, @@ -1857,6 +1900,17 @@ func TestReconcileBindingDeleteUsingOriginatingIdentity(t *testing.T) { binding.Spec.UserInfo = testUserInfo } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v: a valid binding should not fail: %v", tc.name, err) @@ -2060,16 +2114,8 @@ func TestReconcileBindingWithSecretConflictFailedAfterFinalRetry(t *testing.T) { kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 2) - - // first action is a get on the namespace - // second action is a get on the secret - action := kubeActions[1].(clientgotesting.GetAction) - if e, a := "get", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertActionEquals(t, kubeActions[0], "get", "namespaces") + assertActionEquals(t, kubeActions[1], "get", "secrets") events := getRecordedEvents(testController) @@ -2196,6 +2242,30 @@ func TestReconcileServiceBindingWithSecretParameters(t *testing.T) { }, } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expectedParameters := map[string]interface{}{ + "a": "1", + "b": "", + } + expectedParametersChecksum := generateChecksumOfParametersOrFail(t, map[string]interface{}{ + "a": "1", + "b": "2", + }) + + binding = assertServiceBindingOperationInProgressWithParametersIsTheOnlyCatalogAction(t, fakeCatalogClient, binding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum) + fakeCatalogClient.ClearActions() + + kubeActions := fakeKubeClient.Actions() + assertNumberOfActions(t, kubeActions, 2) + assertActionEquals(t, kubeActions[0], "get", "namespaces") + assertActionEquals(t, kubeActions[1], "get", "secrets") + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err = testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("a valid binding should not fail: %v", err) @@ -2218,41 +2288,23 @@ func TestReconcileServiceBindingWithSecretParameters(t *testing.T) { }, }) - expectedParameters := map[string]interface{}{ - "a": "1", - "b": "", - } - expectedParametersChecksum, err := generateChecksumOfParameters(map[string]interface{}{ - "a": "1", - "b": "2", - }) - if err != nil { - t.Fatalf("Failed to generate parameters checksum: %v", err) - } - actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding) - assertServiceBindingOperationInProgressWithParameters(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding) assertServiceBindingOperationSuccessWithParameters(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, expectedParameters, expectedParametersChecksum, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - kubeActions := fakeKubeClient.Actions() + kubeActions = fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 4) + assertActionEquals(t, kubeActions[0], "get", "namespaces") - // first action is a get on the namespace // second action is a get on the secret, to build the parameters + assertActionEquals(t, kubeActions[1], "get", "secrets") action, ok := kubeActions[1].(clientgotesting.GetAction) if !ok { t.Fatalf("unexpected type of action: expected a GetAction, got %T", kubeActions[0]) } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action: %s", expectedGot(e, a)) - } if e, a := "param-secret-name", action.GetName(); e != a { t.Fatalf("Unexpected name of secret fetched: %s", expectedGot(e, a)) } @@ -2382,6 +2434,18 @@ func TestReconcileBindingWithSetOrphanMitigation(t *testing.T) { startTime := metav1.NewTime(time.Now().Add(-7 * 24 * time.Hour)) binding.Status.OperationStartTime = &startTime + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + assertServiceBindingReadyFalse(t, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeServiceBrokerClient.Actions(), 0) + if err := testController.reconcileServiceBinding(binding); tc.shouldReturnError && err == nil || !tc.shouldReturnError && err != nil { t.Fatalf("expected to return %v from reconciliation attempt, got %v", tc.shouldReturnError, err) } @@ -2401,21 +2465,12 @@ func TestReconcileBindingWithSetOrphanMitigation(t *testing.T) { kubeActions := fakeKubeClient.Actions() assertNumberOfActions(t, kubeActions, 1) - action := kubeActions[0].(clientgotesting.GetAction) - if e, a := "get", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "namespaces", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertActionEquals(t, kubeActions[0], "get", "namespaces") actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingReadyFalse(t, updatedServiceBinding) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingExternalPropertiesNil(t, updatedServiceBinding) @@ -2474,15 +2529,7 @@ func TestReconcileBindingWithOrphanMitigationInProgress(t *testing.T) { if err := testController.reconcileServiceBinding(binding); err != nil { t.Fatalf("reconciliation should complete since the retry duration has elapsed: %v", err) } - kubeActions := fakeKubeClient.Actions() - assertNumberOfActions(t, kubeActions, 1) - action := kubeActions[0].(clientgotesting.GetAction) - if e, a := "delete", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) brokerActions := fakeServiceBrokerClient.Actions() assertNumberOfClusterServiceBrokerActions(t, brokerActions, 1) @@ -2555,15 +2602,7 @@ func TestReconcileBindingWithOrphanMitigationReconciliationRetryTimeOut(t *testi if err := testController.reconcileServiceBinding(binding); err != nil { t.Fatalf("reconciliation should complete since the retry duration has elapsed: %v", err) } - kubeActions := fakeKubeClient.Actions() - assertNumberOfActions(t, kubeActions, 1) - action := kubeActions[0].(clientgotesting.GetAction) - if e, a := "delete", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) brokerActions := fakeServiceBrokerClient.Actions() assertNumberOfClusterServiceBrokerActions(t, brokerActions, 1) @@ -2634,6 +2673,27 @@ func TestReconcileServiceBindingDeleteDuringOngoingOperation(t *testing.T) { timeOfReconciliation := metav1.Now() + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + + // Verify that the operation start time was reset to Now + if binding.Status.OperationStartTime.Before(&timeOfReconciliation) { + t.Fatalf( + "OperationStartTime should not be before the time that the reconciliation started. OperationStartTime=%v. timeOfReconciliation=%v", + binding.Status.OperationStartTime, + timeOfReconciliation, + ) + } + + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v", err) @@ -2648,39 +2708,15 @@ func TestReconcileServiceBindingDeleteDuringOngoingOperation(t *testing.T) { PlanID: testClusterServicePlanGUID, }) - kubeActions := fakeKubeClient.Actions() - // The action should be deleting the secret - assertNumberOfActions(t, kubeActions, 1) - - deleteAction := kubeActions[0].(clientgotesting.DeleteActionImpl) - if e, a := "delete", deleteAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on kubeActions[1]; %s", expectedGot(e, a)) - } - - if e, a := binding.Spec.SecretName, deleteAction.Name; e != a { - t.Fatalf("Unexpected name of secret: %s", expectedGot(e, a)) - } + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) actions := fakeCatalogClient.Actions() // The actions should be: // 0. Updating the current operation // 1. Updating the ready condition - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - // Verify that the operation start time was reset to Now - if updatedServiceBinding.Status.OperationStartTime.Before(&timeOfReconciliation) { - t.Fatalf( - "OperationStartTime should not be before the time that the reconciliation started. OperationStartTime=%v. timeOfReconciliation=%v", - updatedServiceBinding.Status.OperationStartTime, - timeOfReconciliation, - ) - } - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingOperationSuccess(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -2733,6 +2769,27 @@ func TestReconcileServiceBindingDeleteDuringOrphanMitigation(t *testing.T) { timeOfReconciliation := metav1.Now() + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + + // Verify that the operation start time was reset to Now + if binding.Status.OperationStartTime.Before(&timeOfReconciliation) { + t.Fatalf( + "OperationStartTime should not be before the time that the reconciliation started. OperationStartTime=%v. timeOfReconciliation=%v", + binding.Status.OperationStartTime, + timeOfReconciliation, + ) + } + + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeClusterServiceBrokerClient.Actions(), 0) + err := testController.reconcileServiceBinding(binding) if err != nil { t.Fatalf("%v", err) @@ -2747,39 +2804,15 @@ func TestReconcileServiceBindingDeleteDuringOrphanMitigation(t *testing.T) { PlanID: testClusterServicePlanGUID, }) - kubeActions := fakeKubeClient.Actions() - // The action should be deleting the secret - assertNumberOfActions(t, kubeActions, 1) - - deleteAction := kubeActions[0].(clientgotesting.DeleteActionImpl) - if e, a := "delete", deleteAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on kubeActions[1]; %s", expectedGot(e, a)) - } - - if e, a := binding.Spec.SecretName, deleteAction.Name; e != a { - t.Fatalf("Unexpected name of secret: %s", expectedGot(e, a)) - } + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) actions := fakeCatalogClient.Actions() // The actions should be: // 0. Updating the current operation // 1. Updating the ready condition - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) - - // Verify that the operation start time was reset to Now - if updatedServiceBinding.Status.OperationStartTime.Before(&timeOfReconciliation) { - t.Fatalf( - "OperationStartTime should not be before the time that the reconciliation started. OperationStartTime=%v. timeOfReconciliation=%v", - updatedServiceBinding.Status.OperationStartTime, - timeOfReconciliation, - ) - } - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingOperationSuccess(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) assertServiceBindingOrphanMitigationSet(t, updatedServiceBinding, false) @@ -2823,6 +2856,17 @@ func TestReconcileServiceBindingAsynchronousBind(t *testing.T) { t.Fatalf("Expected polling queue to not have any record of test binding") } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertGetNamespaceAction(t, fakeKubeClient.Actions()) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeServiceBrokerClient.Actions(), 0) + if err := testController.reconcileServiceBinding(binding); err != nil { t.Fatalf("a valid binding should not fail: %v", err) } @@ -2857,12 +2901,9 @@ func TestReconcileServiceBindingAsynchronousBind(t *testing.T) { // Service Catalog actions actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, binding) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingAsyncInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationBind, asyncBindingReason, testOperation, binding) // Events @@ -2908,6 +2949,17 @@ func TestReconcileServiceBindingAsynchronousUnbind(t *testing.T) { t.Fatalf("Expected polling queue to not have any record of test binding") } + if err := testController.reconcileServiceBinding(binding); err != nil { + t.Fatalf("unexpected error: %v", err) + } + binding = assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding) + fakeCatalogClient.ClearActions() + + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) + fakeKubeClient.ClearActions() + + assertNumberOfClusterServiceBrokerActions(t, fakeServiceBrokerClient.Actions(), 0) + if err := testController.reconcileServiceBinding(binding); err != nil { t.Fatalf("a valid binding should not fail: %v", err) } @@ -2928,25 +2980,13 @@ func TestReconcileServiceBindingAsynchronousUnbind(t *testing.T) { }) // Kube actions - kubeActions := fakeKubeClient.Actions() - assertNumberOfActions(t, kubeActions, 1) - deleteAction := kubeActions[0].(clientgotesting.DeleteActionImpl) - if e, a := "delete", deleteAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on kubeActions[1]; expected %v, got %v", e, a) - } - - if e, a := binding.Spec.SecretName, deleteAction.Name; e != a { - t.Fatalf("Unexpected name of secret: expected %v, got %v", e, a) - } + assertDeleteSecretAction(t, fakeKubeClient.Actions(), binding.Spec.SecretName) // Service Catalog actions actions := fakeCatalogClient.Actions() - assertNumberOfActions(t, actions, 2) + assertNumberOfActions(t, actions, 1) updatedServiceBinding := assertUpdateStatus(t, actions[0], binding).(*v1beta1.ServiceBinding) - assertServiceBindingOperationInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, binding) - - updatedServiceBinding = assertUpdateStatus(t, actions[1], binding).(*v1beta1.ServiceBinding) assertServiceBindingAsyncInProgress(t, updatedServiceBinding, v1beta1.ServiceBindingOperationUnbind, asyncUnbindingReason, testOperation, binding) // Events @@ -3185,14 +3225,7 @@ func TestPollServiceBinding(t *testing.T) { validateBrokerActionsFunc: validatePollBindingLastOperationAndGetBindingActions, validateKubeActionsFunc: func(t *testing.T, actions []clientgotesting.Action) { assertNumberOfActions(t, actions, 1) - - action := actions[0].(clientgotesting.GetAction) - if e, a := "get", action.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", action.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertActionEquals(t, actions[0], "get", "secrets") }, validateConditionsFunc: func(t *testing.T, updatedBinding *v1beta1.ServiceBinding, originalBinding *v1beta1.ServiceBinding) { assertServiceBindingAsyncBindErrorAfterStateSucceeded(t, updatedBinding, errorInjectingBindResultReason, originalBinding) @@ -3233,24 +3266,8 @@ func TestPollServiceBinding(t *testing.T) { validateBrokerActionsFunc: validatePollBindingLastOperationAndGetBindingActions, validateKubeActionsFunc: func(t *testing.T, actions []clientgotesting.Action) { assertNumberOfActions(t, actions, 2) - - // GET on Secret - getAction := actions[0].(clientgotesting.GetAction) - if e, a := "get", getAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", getAction.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } - - // CREATE on Secret - createAction := actions[1].(clientgotesting.CreateAction) - if e, a := "create", createAction.GetVerb(); e != a { - t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) - } - if e, a := "secrets", createAction.GetResource().Resource; e != a { - t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) - } + assertActionEquals(t, actions[0], "get", "secrets") + assertActionEquals(t, actions[1], "create", "secrets") }, validateConditionsFunc: func(t *testing.T, updatedBinding *v1beta1.ServiceBinding, originalBinding *v1beta1.ServiceBinding) { assertServiceBindingOperationSuccess(t, updatedBinding, v1beta1.ServiceBindingOperationBind, originalBinding) @@ -3653,3 +3670,48 @@ func TestPollServiceBinding(t *testing.T) { }) } } + +func assertServiceBindingBindInProgressIsTheOnlyCatalogAction(t *testing.T, fakeCatalogClient *fake.Clientset, binding *v1beta1.ServiceBinding) *v1beta1.ServiceBinding { + return assertServiceBindingOperationInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding, v1beta1.ServiceBindingOperationBind) +} + +func assertServiceBindingUnbindInProgressIsTheOnlyCatalogAction(t *testing.T, fakeCatalogClient *fake.Clientset, binding *v1beta1.ServiceBinding) *v1beta1.ServiceBinding { + return assertServiceBindingOperationInProgressIsTheOnlyCatalogAction(t, fakeCatalogClient, binding, v1beta1.ServiceBindingOperationUnbind) +} + +func assertServiceBindingOperationInProgressIsTheOnlyCatalogAction(t *testing.T, fakeCatalogClient *fake.Clientset, binding *v1beta1.ServiceBinding, operation v1beta1.ServiceBindingOperation) *v1beta1.ServiceBinding { + return assertServiceBindingOperationInProgressWithParametersIsTheOnlyCatalogAction(t, fakeCatalogClient, binding, operation, nil, "") +} + +func assertServiceBindingOperationInProgressWithParametersIsTheOnlyCatalogAction(t *testing.T, fakeCatalogClient *fake.Clientset, binding *v1beta1.ServiceBinding, operation v1beta1.ServiceBindingOperation, parameters map[string]interface{}, parametersChecksum string) *v1beta1.ServiceBinding { + actions := fakeCatalogClient.Actions() + assertNumberOfActions(t, actions, 1) + updateObject := assertUpdateStatus(t, actions[0], binding) + assertServiceBindingOperationInProgressWithParameters(t, updateObject, operation, parameters, parametersChecksum, binding) + assertServiceBindingOrphanMitigationSet(t, updateObject, false) + return updateObject.(*v1beta1.ServiceBinding) +} + +func assertGetNamespaceAction(t *testing.T, kubeActions []clientgotesting.Action) { + assertNumberOfActions(t, kubeActions, 1) + assertActionEquals(t, kubeActions[0], "get", "namespaces") +} + +func assertDeleteSecretAction(t *testing.T, kubeActions []clientgotesting.Action, secretName string) { + assertNumberOfActions(t, kubeActions, 1) + assertActionEquals(t, kubeActions[0], "delete", "secrets") + + deleteAction := kubeActions[0].(clientgotesting.DeleteActionImpl) + if e, a := secretName, deleteAction.Name; e != a { + t.Fatalf("Unexpected name of secret: %s", expectedGot(e, a)) + } +} + +func assertActionEquals(t *testing.T, action clientgotesting.Action, expectedVerb, expectedResource string) { + if e, a := expectedVerb, action.GetVerb(); e != a { + t.Fatalf("Unexpected verb on action; %s", expectedGot(e, a)) + } + if e, a := expectedResource, action.GetResource().Resource; e != a { + t.Fatalf("Unexpected resource on action; %s", expectedGot(e, a)) + } +}