github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/actor/v7action/service_key_test.go (about)

     1  package v7action_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/actor/actionerror"
     5  	. "code.cloudfoundry.org/cli/actor/v7action"
     6  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  	"code.cloudfoundry.org/cli/cf/errors"
    11  	"code.cloudfoundry.org/cli/resources"
    12  	"code.cloudfoundry.org/cli/types"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  )
    16  
    17  var _ = Describe("Service Key Action", func() {
    18  	var (
    19  		actor                     *Actor
    20  		fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient
    21  	)
    22  
    23  	BeforeEach(func() {
    24  		fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient)
    25  		actor = NewActor(fakeCloudControllerClient, nil, nil, nil, nil, nil)
    26  	})
    27  
    28  	Describe("CreateServiceKey", func() {
    29  		const (
    30  			serviceInstanceName = "fake-service-instance-name"
    31  			serviceInstanceGUID = "fake-service-instance-guid"
    32  			serviceKeyName      = "fake-key-name"
    33  			spaceGUID           = "fake-space-guid"
    34  			fakeJobURL          = ccv3.JobURL("fake-job-url")
    35  		)
    36  
    37  		var (
    38  			params         CreateServiceKeyParams
    39  			warnings       Warnings
    40  			executionError error
    41  			stream         chan PollJobEvent
    42  		)
    43  
    44  		BeforeEach(func() {
    45  			fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
    46  				resources.ServiceInstance{
    47  					Name: serviceInstanceName,
    48  					GUID: serviceInstanceGUID,
    49  				},
    50  				ccv3.IncludedResources{},
    51  				ccv3.Warnings{"get instance warning"},
    52  				nil,
    53  			)
    54  
    55  			fakeCloudControllerClient.CreateServiceCredentialBindingReturns(
    56  				fakeJobURL,
    57  				ccv3.Warnings{"create key warning"},
    58  				nil,
    59  			)
    60  
    61  			fakeStream := make(chan ccv3.PollJobEvent)
    62  			fakeCloudControllerClient.PollJobToEventStreamReturns(fakeStream)
    63  			go func() {
    64  				fakeStream <- ccv3.PollJobEvent{
    65  					State:    constant.JobPolling,
    66  					Warnings: ccv3.Warnings{"poll warning"},
    67  				}
    68  			}()
    69  
    70  			params = CreateServiceKeyParams{
    71  				SpaceGUID:           spaceGUID,
    72  				ServiceInstanceName: serviceInstanceName,
    73  				ServiceKeyName:      serviceKeyName,
    74  				Parameters: types.NewOptionalObject(map[string]interface{}{
    75  					"foo": "bar",
    76  				}),
    77  			}
    78  		})
    79  
    80  		JustBeforeEach(func() {
    81  			stream, warnings, executionError = actor.CreateServiceKey(params)
    82  		})
    83  
    84  		It("returns an event stream, warnings, and no errors", func() {
    85  			Expect(executionError).NotTo(HaveOccurred())
    86  
    87  			Expect(warnings).To(ConsistOf(Warnings{
    88  				"get instance warning",
    89  				"create key warning",
    90  			}))
    91  
    92  			Eventually(stream).Should(Receive(Equal(PollJobEvent{
    93  				State:    JobPolling,
    94  				Warnings: Warnings{"poll warning"},
    95  				Err:      nil,
    96  			})))
    97  		})
    98  
    99  		Describe("service instance lookup", func() {
   100  			It("makes the correct call", func() {
   101  				Expect(fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
   102  				actualServiceInstanceName, actualSpaceGUID, actualQuery := fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceArgsForCall(0)
   103  				Expect(actualServiceInstanceName).To(Equal(serviceInstanceName))
   104  				Expect(actualSpaceGUID).To(Equal(spaceGUID))
   105  				Expect(actualQuery).To(BeEmpty())
   106  			})
   107  
   108  			When("not found", func() {
   109  				BeforeEach(func() {
   110  					fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   111  						resources.ServiceInstance{},
   112  						ccv3.IncludedResources{},
   113  						ccv3.Warnings{"get instance warning"},
   114  						ccerror.ServiceInstanceNotFoundError{Name: serviceInstanceName},
   115  					)
   116  				})
   117  
   118  				It("returns the error and warning", func() {
   119  					Expect(warnings).To(ContainElement("get instance warning"))
   120  					Expect(executionError).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName}))
   121  				})
   122  			})
   123  
   124  			When("fails", func() {
   125  				BeforeEach(func() {
   126  					fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   127  						resources.ServiceInstance{},
   128  						ccv3.IncludedResources{},
   129  						ccv3.Warnings{"get instance warning"},
   130  						errors.New("boof"),
   131  					)
   132  				})
   133  
   134  				It("returns the error and warning", func() {
   135  					Expect(warnings).To(ContainElement("get instance warning"))
   136  					Expect(executionError).To(MatchError("boof"))
   137  				})
   138  			})
   139  		})
   140  
   141  		Describe("initiating the create", func() {
   142  			It("makes the correct call", func() {
   143  				Expect(fakeCloudControllerClient.CreateServiceCredentialBindingCallCount()).To(Equal(1))
   144  				Expect(fakeCloudControllerClient.CreateServiceCredentialBindingArgsForCall(0)).To(Equal(resources.ServiceCredentialBinding{
   145  					Type:                resources.KeyBinding,
   146  					Name:                serviceKeyName,
   147  					ServiceInstanceGUID: serviceInstanceGUID,
   148  					Parameters: types.NewOptionalObject(map[string]interface{}{
   149  						"foo": "bar",
   150  					}),
   151  				}))
   152  			})
   153  
   154  			When("key already exists", func() {
   155  				BeforeEach(func() {
   156  					fakeCloudControllerClient.CreateServiceCredentialBindingReturns(
   157  						"",
   158  						ccv3.Warnings{"create binding warning"},
   159  						ccerror.ServiceKeyTakenError{
   160  							Message: "The binding name is invalid. Key binding names must be unique. The service instance already has a key binding with name 'fake-key-name'.",
   161  						},
   162  					)
   163  				})
   164  
   165  				It("returns an actionerror and warnings", func() {
   166  					Expect(warnings).To(ContainElement("create binding warning"))
   167  					Expect(executionError).To(MatchError(actionerror.ResourceAlreadyExistsError{
   168  						Message: "Service key fake-key-name already exists",
   169  					}))
   170  				})
   171  			})
   172  
   173  			When("fails", func() {
   174  				BeforeEach(func() {
   175  					fakeCloudControllerClient.CreateServiceCredentialBindingReturns(
   176  						"",
   177  						ccv3.Warnings{"create binding warning"},
   178  						errors.New("boop"),
   179  					)
   180  				})
   181  
   182  				It("returns the error and warnings", func() {
   183  					Expect(warnings).To(ContainElement("create binding warning"))
   184  					Expect(executionError).To(MatchError("boop"))
   185  				})
   186  			})
   187  		})
   188  
   189  		Describe("polling the job", func() {
   190  			It("polls the job", func() {
   191  				Expect(fakeCloudControllerClient.PollJobToEventStreamCallCount()).To(Equal(1))
   192  				Expect(fakeCloudControllerClient.PollJobToEventStreamArgsForCall(0)).To(Equal(fakeJobURL))
   193  			})
   194  		})
   195  	})
   196  
   197  	Describe("GetServiceKeysByServiceInstance", func() {
   198  		const (
   199  			serviceInstanceName = "fake-service-instance-name"
   200  			serviceInstanceGUID = "fake-service-instance-guid"
   201  			spaceGUID           = "fake-space-guid"
   202  		)
   203  
   204  		BeforeEach(func() {
   205  			fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   206  				resources.ServiceInstance{
   207  					Name: serviceInstanceName,
   208  					GUID: serviceInstanceGUID,
   209  					Type: resources.ManagedServiceInstance,
   210  				},
   211  				ccv3.IncludedResources{},
   212  				ccv3.Warnings{"get instance warning"},
   213  				nil,
   214  			)
   215  
   216  			fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   217  				[]resources.ServiceCredentialBinding{
   218  					{GUID: "1", Name: "flopsy", LastOperation: resources.LastOperation{Type: "create", State: "succeeded"}},
   219  					{GUID: "2", Name: "mopsy", LastOperation: resources.LastOperation{Type: "create", State: "failed"}},
   220  					{GUID: "3", Name: "cottontail", LastOperation: resources.LastOperation{Type: "update", State: "succeeded"}},
   221  					{GUID: "4", Name: "peter", LastOperation: resources.LastOperation{Type: "create", State: "in progress"}},
   222  				},
   223  				ccv3.Warnings{"get keys warning"},
   224  				nil,
   225  			)
   226  		})
   227  
   228  		var (
   229  			keys           []resources.ServiceCredentialBinding
   230  			warnings       Warnings
   231  			executionError error
   232  		)
   233  
   234  		JustBeforeEach(func() {
   235  			keys, warnings, executionError = actor.GetServiceKeysByServiceInstance(serviceInstanceName, spaceGUID)
   236  		})
   237  
   238  		It("makes the correct call to get the service instance", func() {
   239  			Expect(fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
   240  			actualServiceInstanceName, actualSpaceGUID, actualQuery := fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceArgsForCall(0)
   241  			Expect(actualServiceInstanceName).To(Equal(serviceInstanceName))
   242  			Expect(actualSpaceGUID).To(Equal(spaceGUID))
   243  			Expect(actualQuery).To(BeEmpty())
   244  		})
   245  
   246  		It("makes the correct call to get the service keys", func() {
   247  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsCallCount()).To(Equal(1))
   248  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsArgsForCall(0)).To(ConsistOf(
   249  				ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}},
   250  				ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}},
   251  			))
   252  		})
   253  
   254  		It("returns a list of keys, with warnings and no error", func() {
   255  			Expect(executionError).NotTo(HaveOccurred())
   256  			Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   257  			Expect(keys).To(Equal([]resources.ServiceCredentialBinding{
   258  				{GUID: "1", Name: "flopsy", LastOperation: resources.LastOperation{Type: "create", State: "succeeded"}},
   259  				{GUID: "2", Name: "mopsy", LastOperation: resources.LastOperation{Type: "create", State: "failed"}},
   260  				{GUID: "3", Name: "cottontail", LastOperation: resources.LastOperation{Type: "update", State: "succeeded"}},
   261  				{GUID: "4", Name: "peter", LastOperation: resources.LastOperation{Type: "create", State: "in progress"}},
   262  			}))
   263  		})
   264  
   265  		When("service instance not found", func() {
   266  			BeforeEach(func() {
   267  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   268  					resources.ServiceInstance{},
   269  					ccv3.IncludedResources{},
   270  					ccv3.Warnings{"get instance warning"},
   271  					ccerror.ServiceInstanceNotFoundError{Name: serviceInstanceName},
   272  				)
   273  			})
   274  
   275  			It("returns the error and warning", func() {
   276  				Expect(warnings).To(ContainElement("get instance warning"))
   277  				Expect(executionError).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName}))
   278  			})
   279  		})
   280  
   281  		When("get service instance fails", func() {
   282  			BeforeEach(func() {
   283  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   284  					resources.ServiceInstance{},
   285  					ccv3.IncludedResources{},
   286  					ccv3.Warnings{"get instance warning"},
   287  					errors.New("boof"),
   288  				)
   289  			})
   290  
   291  			It("returns the error and warning", func() {
   292  				Expect(warnings).To(ContainElement("get instance warning"))
   293  				Expect(executionError).To(MatchError("boof"))
   294  			})
   295  		})
   296  
   297  		When("get keys fails", func() {
   298  			BeforeEach(func() {
   299  				fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   300  					[]resources.ServiceCredentialBinding{},
   301  					ccv3.Warnings{"get keys warning"},
   302  					errors.New("boom"),
   303  				)
   304  			})
   305  
   306  			It("returns the error and warning", func() {
   307  				Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   308  				Expect(executionError).To(MatchError("boom"))
   309  			})
   310  		})
   311  	})
   312  
   313  	Describe("GetServiceKeyByServiceInstanceAndName", func() {
   314  		const (
   315  			serviceInstanceName = "fake-service-instance-name"
   316  			serviceInstanceGUID = "fake-service-instance-guid"
   317  			serviceKeyName      = "fake-service-key-name"
   318  			serviceKeyGUID      = "fake-service-key-guid"
   319  			spaceGUID           = "fake-space-guid"
   320  		)
   321  
   322  		BeforeEach(func() {
   323  			fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   324  				resources.ServiceInstance{
   325  					Name: serviceInstanceName,
   326  					GUID: serviceInstanceGUID,
   327  					Type: resources.ManagedServiceInstance,
   328  				},
   329  				ccv3.IncludedResources{},
   330  				ccv3.Warnings{"get instance warning"},
   331  				nil,
   332  			)
   333  
   334  			fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   335  				[]resources.ServiceCredentialBinding{
   336  					{
   337  						Name: serviceKeyName,
   338  						GUID: serviceKeyGUID,
   339  					},
   340  				},
   341  				ccv3.Warnings{"get keys warning"},
   342  				nil,
   343  			)
   344  		})
   345  
   346  		var (
   347  			key            resources.ServiceCredentialBinding
   348  			warnings       Warnings
   349  			executionError error
   350  		)
   351  
   352  		JustBeforeEach(func() {
   353  			key, warnings, executionError = actor.GetServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID)
   354  		})
   355  
   356  		It("makes the correct call to get the service instance", func() {
   357  			Expect(fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
   358  			actualServiceInstanceName, actualSpaceGUID, actualQuery := fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceArgsForCall(0)
   359  			Expect(actualServiceInstanceName).To(Equal(serviceInstanceName))
   360  			Expect(actualSpaceGUID).To(Equal(spaceGUID))
   361  			Expect(actualQuery).To(BeEmpty())
   362  		})
   363  
   364  		It("makes the correct call to get the service keys", func() {
   365  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsCallCount()).To(Equal(1))
   366  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsArgsForCall(0)).To(ConsistOf(
   367  				ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}},
   368  				ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}},
   369  				ccv3.Query{Key: ccv3.NameFilter, Values: []string{serviceKeyName}},
   370  				ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}},
   371  				ccv3.Query{Key: ccv3.Page, Values: []string{"1"}},
   372  			))
   373  		})
   374  
   375  		It("returns a key, with warnings and no error", func() {
   376  			Expect(executionError).NotTo(HaveOccurred())
   377  			Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   378  			Expect(key.Name).To(Equal(serviceKeyName))
   379  			Expect(key.GUID).To(Equal(serviceKeyGUID))
   380  		})
   381  
   382  		When("service instance not found", func() {
   383  			BeforeEach(func() {
   384  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   385  					resources.ServiceInstance{},
   386  					ccv3.IncludedResources{},
   387  					ccv3.Warnings{"get instance warning"},
   388  					ccerror.ServiceInstanceNotFoundError{Name: serviceInstanceName},
   389  				)
   390  			})
   391  
   392  			It("returns the error and warning", func() {
   393  				Expect(warnings).To(ContainElement("get instance warning"))
   394  				Expect(executionError).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName}))
   395  			})
   396  		})
   397  
   398  		When("get service instance fails", func() {
   399  			BeforeEach(func() {
   400  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   401  					resources.ServiceInstance{},
   402  					ccv3.IncludedResources{},
   403  					ccv3.Warnings{"get instance warning"},
   404  					errors.New("boof"),
   405  				)
   406  			})
   407  
   408  			It("returns the error and warning", func() {
   409  				Expect(warnings).To(ContainElement("get instance warning"))
   410  				Expect(executionError).To(MatchError("boof"))
   411  			})
   412  		})
   413  
   414  		When("key not found", func() {
   415  			BeforeEach(func() {
   416  				fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   417  					[]resources.ServiceCredentialBinding{},
   418  					ccv3.Warnings{"get keys warning"},
   419  					nil,
   420  				)
   421  			})
   422  
   423  			It("returns the error and warning", func() {
   424  				Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   425  				Expect(executionError).To(MatchError(actionerror.ServiceKeyNotFoundError{
   426  					KeyName:             serviceKeyName,
   427  					ServiceInstanceName: serviceInstanceName,
   428  				}))
   429  			})
   430  		})
   431  
   432  		When("get keys fails", func() {
   433  			BeforeEach(func() {
   434  				fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   435  					[]resources.ServiceCredentialBinding{},
   436  					ccv3.Warnings{"get keys warning"},
   437  					errors.New("boom"),
   438  				)
   439  			})
   440  
   441  			It("returns the error and warning", func() {
   442  				Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   443  				Expect(executionError).To(MatchError("boom"))
   444  			})
   445  		})
   446  	})
   447  
   448  	Describe("GetServiceKeyDetailsByServiceInstanceAndName", func() {
   449  		const (
   450  			serviceInstanceName = "fake-service-instance-name"
   451  			serviceInstanceGUID = "fake-service-instance-guid"
   452  			serviceKeyName      = "fake-service-key-name"
   453  			serviceKeyGUID      = "fake-service-key-guid"
   454  			spaceGUID           = "fake-space-guid"
   455  		)
   456  
   457  		BeforeEach(func() {
   458  			fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   459  				resources.ServiceInstance{
   460  					Name: serviceInstanceName,
   461  					GUID: serviceInstanceGUID,
   462  					Type: resources.ManagedServiceInstance,
   463  				},
   464  				ccv3.IncludedResources{},
   465  				ccv3.Warnings{"get instance warning"},
   466  				nil,
   467  			)
   468  
   469  			fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   470  				[]resources.ServiceCredentialBinding{
   471  					{
   472  						Name: serviceKeyName,
   473  						GUID: serviceKeyGUID,
   474  					},
   475  				},
   476  				ccv3.Warnings{"get keys warning"},
   477  				nil,
   478  			)
   479  
   480  			fakeCloudControllerClient.GetServiceCredentialBindingDetailsReturns(
   481  				resources.ServiceCredentialBindingDetails{
   482  					Credentials: map[string]interface{}{"foo": "bar"},
   483  				},
   484  				ccv3.Warnings{"get details warning"},
   485  				nil,
   486  			)
   487  		})
   488  
   489  		var (
   490  			details        resources.ServiceCredentialBindingDetails
   491  			warnings       Warnings
   492  			executionError error
   493  		)
   494  
   495  		JustBeforeEach(func() {
   496  			details, warnings, executionError = actor.GetServiceKeyDetailsByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID)
   497  		})
   498  
   499  		It("makes the correct call to get the service instance", func() {
   500  			Expect(fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
   501  			actualServiceInstanceName, actualSpaceGUID, actualQuery := fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceArgsForCall(0)
   502  			Expect(actualServiceInstanceName).To(Equal(serviceInstanceName))
   503  			Expect(actualSpaceGUID).To(Equal(spaceGUID))
   504  			Expect(actualQuery).To(BeEmpty())
   505  		})
   506  
   507  		It("makes the correct call to get the service keys", func() {
   508  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsCallCount()).To(Equal(1))
   509  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingsArgsForCall(0)).To(ConsistOf(
   510  				ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}},
   511  				ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}},
   512  				ccv3.Query{Key: ccv3.NameFilter, Values: []string{serviceKeyName}},
   513  				ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}},
   514  				ccv3.Query{Key: ccv3.Page, Values: []string{"1"}},
   515  			))
   516  		})
   517  
   518  		It("makes the correct call to get the key details", func() {
   519  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingDetailsCallCount()).To(Equal(1))
   520  			Expect(fakeCloudControllerClient.GetServiceCredentialBindingDetailsArgsForCall(0)).To(Equal(serviceKeyGUID))
   521  		})
   522  
   523  		It("returns the details, with warnings and no error", func() {
   524  			Expect(executionError).NotTo(HaveOccurred())
   525  			Expect(warnings).To(ContainElements("get instance warning", "get keys warning", "get details warning"))
   526  			Expect(details.Credentials).To(Equal(map[string]interface{}{"foo": "bar"}))
   527  		})
   528  
   529  		When("service instance not found", func() {
   530  			BeforeEach(func() {
   531  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   532  					resources.ServiceInstance{},
   533  					ccv3.IncludedResources{},
   534  					ccv3.Warnings{"get instance warning"},
   535  					ccerror.ServiceInstanceNotFoundError{Name: serviceInstanceName},
   536  				)
   537  			})
   538  
   539  			It("returns the error and warning", func() {
   540  				Expect(warnings).To(ContainElement("get instance warning"))
   541  				Expect(executionError).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName}))
   542  			})
   543  		})
   544  
   545  		When("get service instance fails", func() {
   546  			BeforeEach(func() {
   547  				fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   548  					resources.ServiceInstance{},
   549  					ccv3.IncludedResources{},
   550  					ccv3.Warnings{"get instance warning"},
   551  					errors.New("boof"),
   552  				)
   553  			})
   554  
   555  			It("returns the error and warning", func() {
   556  				Expect(warnings).To(ContainElement("get instance warning"))
   557  				Expect(executionError).To(MatchError("boof"))
   558  			})
   559  		})
   560  
   561  		When("key not found", func() {
   562  			BeforeEach(func() {
   563  				fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   564  					[]resources.ServiceCredentialBinding{},
   565  					ccv3.Warnings{"get keys warning"},
   566  					nil,
   567  				)
   568  			})
   569  
   570  			It("returns the error and warning", func() {
   571  				Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   572  				Expect(executionError).To(MatchError(actionerror.ServiceKeyNotFoundError{
   573  					KeyName:             serviceKeyName,
   574  					ServiceInstanceName: serviceInstanceName,
   575  				}))
   576  			})
   577  		})
   578  
   579  		When("get keys fails", func() {
   580  			BeforeEach(func() {
   581  				fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   582  					[]resources.ServiceCredentialBinding{},
   583  					ccv3.Warnings{"get keys warning"},
   584  					errors.New("boom"),
   585  				)
   586  			})
   587  
   588  			It("returns the error and warning", func() {
   589  				Expect(warnings).To(ContainElements("get instance warning", "get keys warning"))
   590  				Expect(executionError).To(MatchError("boom"))
   591  			})
   592  		})
   593  
   594  		When("get details fails", func() {
   595  			BeforeEach(func() {
   596  				fakeCloudControllerClient.GetServiceCredentialBindingDetailsReturns(
   597  					resources.ServiceCredentialBindingDetails{},
   598  					ccv3.Warnings{"get details warning"},
   599  					errors.New("boom"),
   600  				)
   601  			})
   602  
   603  			It("returns the error and warning", func() {
   604  				Expect(warnings).To(ContainElements("get details warning", "get keys warning"))
   605  				Expect(executionError).To(MatchError("boom"))
   606  			})
   607  		})
   608  	})
   609  
   610  	Describe("DeleteServiceKeyByServiceInstanceAndName", func() {
   611  		const (
   612  			serviceInstanceName = "fake-service-instance-name"
   613  			serviceInstanceGUID = "fake-service-instance-guid"
   614  			spaceGUID           = "fake-space-guid"
   615  			serviceKeyName      = "fake-key-name"
   616  			serviceKeyGUID      = "fake-key-guid"
   617  			fakeJobURL          = ccv3.JobURL("fake-job-url")
   618  		)
   619  
   620  		var (
   621  			warnings       Warnings
   622  			executionError error
   623  			stream         chan PollJobEvent
   624  		)
   625  
   626  		BeforeEach(func() {
   627  			fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   628  				resources.ServiceInstance{
   629  					Name: serviceInstanceName,
   630  					GUID: serviceInstanceGUID,
   631  					Type: resources.ManagedServiceInstance,
   632  				},
   633  				ccv3.IncludedResources{},
   634  				ccv3.Warnings{"get instance warning"},
   635  				nil,
   636  			)
   637  
   638  			fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   639  				[]resources.ServiceCredentialBinding{
   640  					{GUID: serviceKeyGUID},
   641  				},
   642  				ccv3.Warnings{"get bindings warning"},
   643  				nil,
   644  			)
   645  
   646  			fakeCloudControllerClient.DeleteServiceCredentialBindingReturns(
   647  				fakeJobURL,
   648  				ccv3.Warnings{"delete binding warning"},
   649  				nil,
   650  			)
   651  
   652  			fakeStream := make(chan ccv3.PollJobEvent)
   653  			fakeCloudControllerClient.PollJobToEventStreamReturns(fakeStream)
   654  			go func() {
   655  				fakeStream <- ccv3.PollJobEvent{
   656  					State:    constant.JobPolling,
   657  					Warnings: ccv3.Warnings{"poll warning"},
   658  				}
   659  			}()
   660  		})
   661  
   662  		JustBeforeEach(func() {
   663  			stream, warnings, executionError = actor.DeleteServiceKeyByServiceInstanceAndName(serviceInstanceName, serviceKeyName, spaceGUID)
   664  		})
   665  
   666  		It("returns an event stream, warnings, and no errors", func() {
   667  			Expect(executionError).NotTo(HaveOccurred())
   668  
   669  			Expect(warnings).To(ConsistOf(Warnings{
   670  				"get instance warning",
   671  				"get bindings warning",
   672  				"delete binding warning",
   673  			}))
   674  
   675  			Eventually(stream).Should(Receive(Equal(PollJobEvent{
   676  				State:    JobPolling,
   677  				Warnings: Warnings{"poll warning"},
   678  				Err:      nil,
   679  			})))
   680  		})
   681  
   682  		Describe("service instance lookup", func() {
   683  			It("makes the correct call", func() {
   684  				Expect(fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1))
   685  				actualServiceInstanceName, actualSpaceGUID, actualQuery := fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceArgsForCall(0)
   686  				Expect(actualServiceInstanceName).To(Equal(serviceInstanceName))
   687  				Expect(actualSpaceGUID).To(Equal(spaceGUID))
   688  				Expect(actualQuery).To(BeEmpty())
   689  			})
   690  
   691  			When("not found", func() {
   692  				BeforeEach(func() {
   693  					fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   694  						resources.ServiceInstance{},
   695  						ccv3.IncludedResources{},
   696  						ccv3.Warnings{"get instance warning"},
   697  						ccerror.ServiceInstanceNotFoundError{Name: serviceInstanceName},
   698  					)
   699  				})
   700  
   701  				It("returns the error and warning", func() {
   702  					Expect(warnings).To(ContainElement("get instance warning"))
   703  					Expect(executionError).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: serviceInstanceName}))
   704  				})
   705  			})
   706  
   707  			When("fails", func() {
   708  				BeforeEach(func() {
   709  					fakeCloudControllerClient.GetServiceInstanceByNameAndSpaceReturns(
   710  						resources.ServiceInstance{},
   711  						ccv3.IncludedResources{},
   712  						ccv3.Warnings{"get instance warning"},
   713  						errors.New("boof"),
   714  					)
   715  				})
   716  
   717  				It("returns the error and warning", func() {
   718  					Expect(warnings).To(ContainElement("get instance warning"))
   719  					Expect(executionError).To(MatchError("boof"))
   720  				})
   721  			})
   722  		})
   723  
   724  		Describe("key lookup", func() {
   725  			It("makes the correct call", func() {
   726  				Expect(fakeCloudControllerClient.GetServiceCredentialBindingsCallCount()).To(Equal(1))
   727  				Expect(fakeCloudControllerClient.GetServiceCredentialBindingsArgsForCall(0)).To(ConsistOf(
   728  					ccv3.Query{Key: ccv3.TypeFilter, Values: []string{"key"}},
   729  					ccv3.Query{Key: ccv3.NameFilter, Values: []string{serviceKeyName}},
   730  					ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: []string{serviceInstanceGUID}},
   731  					ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}},
   732  					ccv3.Query{Key: ccv3.Page, Values: []string{"1"}},
   733  				))
   734  			})
   735  
   736  			When("not found", func() {
   737  				BeforeEach(func() {
   738  					fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   739  						[]resources.ServiceCredentialBinding{},
   740  						ccv3.Warnings{"get keys warning"},
   741  						nil,
   742  					)
   743  				})
   744  
   745  				It("returns the error and warning", func() {
   746  					Expect(warnings).To(ContainElement("get keys warning"))
   747  					Expect(executionError).To(MatchError(actionerror.ServiceKeyNotFoundError{
   748  						KeyName:             serviceKeyName,
   749  						ServiceInstanceName: serviceInstanceName,
   750  					}))
   751  				})
   752  			})
   753  
   754  			When("fails", func() {
   755  				BeforeEach(func() {
   756  					fakeCloudControllerClient.GetServiceCredentialBindingsReturns(
   757  						[]resources.ServiceCredentialBinding{},
   758  						ccv3.Warnings{"get key warning"},
   759  						errors.New("boom"),
   760  					)
   761  				})
   762  
   763  				It("returns the error and warning", func() {
   764  					Expect(warnings).To(ContainElement("get key warning"))
   765  					Expect(executionError).To(MatchError("boom"))
   766  				})
   767  			})
   768  		})
   769  
   770  		Describe("initiating the delete", func() {
   771  			It("makes the correct call", func() {
   772  				Expect(fakeCloudControllerClient.DeleteServiceCredentialBindingCallCount()).To(Equal(1))
   773  				Expect(fakeCloudControllerClient.DeleteServiceCredentialBindingArgsForCall(0)).To(Equal(serviceKeyGUID))
   774  			})
   775  
   776  			When("fails", func() {
   777  				BeforeEach(func() {
   778  					fakeCloudControllerClient.DeleteServiceCredentialBindingReturns(
   779  						"",
   780  						ccv3.Warnings{"delete binding warning"},
   781  						errors.New("boop"),
   782  					)
   783  				})
   784  
   785  				It("returns the error and warnings", func() {
   786  					Expect(warnings).To(ContainElement("delete binding warning"))
   787  					Expect(executionError).To(MatchError("boop"))
   788  				})
   789  			})
   790  		})
   791  
   792  		Describe("polling the job", func() {
   793  			It("polls the job", func() {
   794  				Expect(fakeCloudControllerClient.PollJobToEventStreamCallCount()).To(Equal(1))
   795  				Expect(fakeCloudControllerClient.PollJobToEventStreamArgsForCall(0)).To(Equal(fakeJobURL))
   796  			})
   797  		})
   798  	})
   799  })