code.cloudfoundry.org/cli@v7.1.0+incompatible/actor/v2action/service_instance_test.go (about)

     1  package v2action_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/actor/actionerror"
     7  	. "code.cloudfoundry.org/cli/actor/v2action"
     8  	"code.cloudfoundry.org/cli/actor/v2action/v2actionfakes"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    12  
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/ginkgo/extensions/table"
    15  	. "github.com/onsi/gomega"
    16  )
    17  
    18  var _ = Describe("Service Instance Actions", func() {
    19  	var (
    20  		actor                     *Actor
    21  		fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient
    22  	)
    23  
    24  	BeforeEach(func() {
    25  		fakeCloudControllerClient = new(v2actionfakes.FakeCloudControllerClient)
    26  		actor = NewActor(fakeCloudControllerClient, nil, nil)
    27  	})
    28  
    29  	Describe("CreateServiceInstance", func() {
    30  		var (
    31  			serviceInstance       ServiceInstance
    32  			createServiceWarnings Warnings
    33  			createServiceErr      error
    34  		)
    35  
    36  		When("no broker name is specified", func() {
    37  			JustBeforeEach(func() {
    38  				serviceInstance, createServiceWarnings, createServiceErr = actor.CreateServiceInstance("space-guid", "service", "service-plan", "service-instance", "", map[string]interface{}{"some": "params"}, []string{"tag-1", "tag-2"})
    39  			})
    40  
    41  			When("there are no errors creating a service instance", func() {
    42  				var returnedInstance ccv2.ServiceInstance
    43  
    44  				BeforeEach(func() {
    45  					returnedInstance = ccv2.ServiceInstance{
    46  						GUID:            "some-service-guid",
    47  						Name:            "service",
    48  						SpaceGUID:       "space-guid",
    49  						ServiceGUID:     "service-guid",
    50  						ServicePlanGUID: "service-plan-guid",
    51  						Type:            constant.ManagedService,
    52  						Tags:            []string{"some", "tags"},
    53  						DashboardURL:    "http://dashboard.com",
    54  						LastOperation:   ccv2.LastOperation{},
    55  					}
    56  					fakeCloudControllerClient.GetSpaceServicesReturns(
    57  						[]ccv2.Service{{
    58  							GUID:              "a-service-guid",
    59  							ServiceBrokerName: "some-broker",
    60  						}},
    61  						nil,
    62  						nil,
    63  					)
    64  					fakeCloudControllerClient.GetServicePlansReturns(
    65  						[]ccv2.ServicePlan{
    66  							{
    67  								GUID: "a-random-service-plan-guid",
    68  								Name: "service-plan-2",
    69  							},
    70  							{
    71  								GUID: "the-service-plan-guid",
    72  								Name: "service-plan",
    73  							},
    74  						},
    75  						nil,
    76  						nil)
    77  					fakeCloudControllerClient.CreateServiceInstanceReturns(
    78  						returnedInstance,
    79  						ccv2.Warnings{"create-service-instance-warning"},
    80  						nil)
    81  				})
    82  
    83  				It("returns the service instance and warnings", func() {
    84  					By("getting the space services")
    85  					Expect(createServiceErr).ToNot(HaveOccurred())
    86  					Expect(serviceInstance).To(Equal(ServiceInstance(returnedInstance)))
    87  					Expect(createServiceWarnings).To(ConsistOf("create-service-instance-warning"))
    88  
    89  					Expect(fakeCloudControllerClient.GetSpaceServicesCallCount()).To(Equal(1))
    90  					spaceGUID, serviceFilter := fakeCloudControllerClient.GetSpaceServicesArgsForCall(0)
    91  					Expect(spaceGUID).Should(Equal("space-guid"))
    92  					Expect(serviceFilter).Should(Equal([]ccv2.Filter{{
    93  						Type:     constant.LabelFilter,
    94  						Operator: constant.EqualOperator,
    95  						Values:   []string{"service"},
    96  					}},
    97  					))
    98  
    99  					By("getting the plans of the service")
   100  					Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1))
   101  					planFilter := fakeCloudControllerClient.GetServicePlansArgsForCall(0)
   102  					Expect(planFilter).Should(Equal([]ccv2.Filter{{
   103  						Type:     constant.ServiceGUIDFilter,
   104  						Operator: constant.EqualOperator,
   105  						Values:   []string{"a-service-guid"},
   106  					}},
   107  					))
   108  
   109  					By("creating the service instance")
   110  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(1))
   111  					spaceGUID, planGUID, serviceInstanceName, parameters, tags := fakeCloudControllerClient.CreateServiceInstanceArgsForCall(0)
   112  					Expect(serviceInstanceName).To(Equal("service-instance"))
   113  					Expect(spaceGUID).To(Equal("space-guid"))
   114  					Expect(planGUID).To(Equal("the-service-plan-guid"))
   115  					Expect(parameters).To(Equal(map[string]interface{}{
   116  						"some": "params",
   117  					}))
   118  					Expect(tags).To(ConsistOf("tag-1", "tag-2"))
   119  				})
   120  			})
   121  
   122  			When("there are errors creating a service instance", func() {
   123  				BeforeEach(func() {
   124  					fakeCloudControllerClient.GetSpaceServicesReturns(
   125  						[]ccv2.Service{{
   126  							GUID: "a-service-guid",
   127  						}},
   128  						nil,
   129  						nil,
   130  					)
   131  					fakeCloudControllerClient.GetServicePlansReturns(
   132  						[]ccv2.ServicePlan{{
   133  							GUID: "the-service-plan-guid",
   134  							Name: "service-plan",
   135  						}},
   136  						nil,
   137  						nil)
   138  
   139  					fakeCloudControllerClient.CreateServiceInstanceReturns(
   140  						ccv2.ServiceInstance{},
   141  						ccv2.Warnings{"create-service-instance-warning"},
   142  						errors.New("boom"))
   143  				})
   144  
   145  				It("returns the error and warnings", func() {
   146  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   147  					Expect(createServiceErr).To(MatchError("boom"))
   148  					Expect(createServiceWarnings).To(ConsistOf("create-service-instance-warning"))
   149  
   150  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(1))
   151  				})
   152  			})
   153  
   154  			When("there are no matching services", func() {
   155  				BeforeEach(func() {
   156  					fakeCloudControllerClient.GetSpaceServicesReturns(
   157  						[]ccv2.Service{},
   158  						ccv2.Warnings{"service-warnings"},
   159  						nil,
   160  					)
   161  				})
   162  
   163  				It("returns the error and warnings", func() {
   164  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   165  					Expect(createServiceErr).To(MatchError(actionerror.ServiceNotFoundError{Name: "service"}))
   166  					Expect(createServiceWarnings).To(ConsistOf("service-warnings"))
   167  
   168  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   169  				})
   170  			})
   171  
   172  			When("getting services returns an error", func() {
   173  				BeforeEach(func() {
   174  					fakeCloudControllerClient.GetSpaceServicesReturns(
   175  						[]ccv2.Service{},
   176  						ccv2.Warnings{"service-warnings"},
   177  						errors.New("boom"),
   178  					)
   179  				})
   180  
   181  				It("returns the error and warnings", func() {
   182  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   183  					Expect(createServiceErr).To(MatchError("boom"))
   184  					Expect(createServiceWarnings).To(ConsistOf("service-warnings"))
   185  
   186  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   187  				})
   188  			})
   189  
   190  			When("getting service plan returns an error", func() {
   191  				BeforeEach(func() {
   192  					fakeCloudControllerClient.GetSpaceServicesReturns(
   193  						[]ccv2.Service{{
   194  							GUID: "a-service-guid",
   195  						}},
   196  						nil,
   197  						nil,
   198  					)
   199  					fakeCloudControllerClient.GetServicePlansReturns(
   200  						[]ccv2.ServicePlan{},
   201  						ccv2.Warnings{"get-plan-warning"},
   202  						errors.New("boom"),
   203  					)
   204  				})
   205  
   206  				It("returns the error and warnings", func() {
   207  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   208  					Expect(createServiceErr).To(MatchError("boom"))
   209  					Expect(createServiceWarnings).To(ConsistOf("get-plan-warning"))
   210  
   211  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   212  				})
   213  			})
   214  
   215  			When("no matching plan", func() {
   216  				BeforeEach(func() {
   217  					fakeCloudControllerClient.GetSpaceServicesReturns(
   218  						[]ccv2.Service{{
   219  							GUID: "a-service-guid",
   220  						}},
   221  						nil,
   222  						nil,
   223  					)
   224  					fakeCloudControllerClient.GetServicePlansReturns(
   225  						[]ccv2.ServicePlan{{
   226  							GUID: "the-service-plan-guid",
   227  							Name: "service-plan-2",
   228  						}},
   229  						ccv2.Warnings{"get-plan-warning"},
   230  						nil)
   231  				})
   232  
   233  				It("returns the error and warnings", func() {
   234  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   235  					Expect(createServiceErr).To(MatchError(actionerror.ServicePlanNotFoundError{PlanName: "service-plan", OfferingName: "service"}))
   236  					Expect(createServiceWarnings).To(ConsistOf("get-plan-warning"))
   237  
   238  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   239  				})
   240  			})
   241  
   242  			When("there are warnings", func() {
   243  				BeforeEach(func() {
   244  					fakeCloudControllerClient.GetSpaceServicesReturns(
   245  						[]ccv2.Service{
   246  							{Label: "service-1", GUID: "service-guid-1"},
   247  						},
   248  						[]string{"foo"},
   249  						nil)
   250  
   251  					fakeCloudControllerClient.GetServicePlansReturns(
   252  						[]ccv2.ServicePlan{
   253  							{Name: "service-plan", GUID: "service-plan-guid-1"},
   254  						},
   255  						[]string{"bar"},
   256  						nil)
   257  					fakeCloudControllerClient.CreateServiceInstanceReturns(
   258  						ccv2.ServiceInstance{},
   259  						[]string{"baz", "qux"},
   260  						nil)
   261  				})
   262  
   263  				It("returns the warnings", func() {
   264  					Expect(createServiceWarnings).To(ConsistOf([]string{"foo", "bar", "baz", "qux"}))
   265  				})
   266  			})
   267  
   268  			When("there are multiple available services by the same name", func() {
   269  				BeforeEach(func() {
   270  					// two services get returned, indicating that there are two services with the
   271  					// same name (i.e. they are provided by different service brokers)
   272  					fakeCloudControllerClient.GetSpaceServicesReturns(
   273  						[]ccv2.Service{
   274  							{
   275  								GUID:              "a-service-guid",
   276  								ServiceBrokerName: "some-broker",
   277  							},
   278  							{
   279  								GUID:              "another-service-guid",
   280  								ServiceBrokerName: "some-other-broker",
   281  							},
   282  						},
   283  						nil,
   284  						nil,
   285  					)
   286  				})
   287  
   288  				It("returns an error and warnings", func() {
   289  					Expect(fakeCloudControllerClient.GetSpaceServicesCallCount()).To(Equal(1))
   290  					spaceGUID, serviceFilter := fakeCloudControllerClient.GetSpaceServicesArgsForCall(0)
   291  					Expect(spaceGUID).Should(Equal("space-guid"))
   292  					Expect(serviceFilter).Should(Equal([]ccv2.Filter{{
   293  						Type:     constant.LabelFilter,
   294  						Operator: constant.EqualOperator,
   295  						Values:   []string{"service"},
   296  					}},
   297  					))
   298  
   299  					Expect(createServiceErr).To(MatchError(actionerror.DuplicateServiceError{Name: "service"}))
   300  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   301  				})
   302  			})
   303  		})
   304  
   305  		When("a broker name is specified", func() {
   306  			var brokerName string
   307  
   308  			BeforeEach(func() {
   309  				brokerName = "some-broker"
   310  			})
   311  
   312  			JustBeforeEach(func() {
   313  				serviceInstance, createServiceWarnings, createServiceErr = actor.CreateServiceInstance("space-guid", "service", "service-plan", "service-instance", brokerName, map[string]interface{}{"some": "params"}, []string{"tag-1", "tag-2"})
   314  			})
   315  
   316  			When("the specified service broker exists", func() {
   317  				var returnedInstance ccv2.ServiceInstance
   318  
   319  				BeforeEach(func() {
   320  					returnedInstance = ccv2.ServiceInstance{
   321  						GUID:            "some-service-guid",
   322  						Name:            "service",
   323  						SpaceGUID:       "space-guid",
   324  						ServiceGUID:     "service-guid",
   325  						ServicePlanGUID: "service-plan-guid",
   326  						Type:            constant.ManagedService,
   327  						Tags:            []string{"some", "tags"},
   328  						DashboardURL:    "http://dashboard.com",
   329  						LastOperation:   ccv2.LastOperation{},
   330  					}
   331  					fakeCloudControllerClient.GetSpaceServicesReturns(
   332  						[]ccv2.Service{
   333  							{
   334  								GUID:              "a-service-guid",
   335  								ServiceBrokerName: "some-broker",
   336  							},
   337  							{
   338  								GUID:              "another-service-guid",
   339  								ServiceBrokerName: "some-other-broker",
   340  							},
   341  						},
   342  						nil,
   343  						nil,
   344  					)
   345  					fakeCloudControllerClient.GetServicePlansReturns(
   346  						[]ccv2.ServicePlan{
   347  							{
   348  								GUID: "a-random-service-plan-guid",
   349  								Name: "service-plan-2",
   350  							},
   351  							{
   352  								GUID: "the-service-plan-guid",
   353  								Name: "service-plan",
   354  							},
   355  						},
   356  						nil,
   357  						nil)
   358  					fakeCloudControllerClient.CreateServiceInstanceReturns(
   359  						returnedInstance,
   360  						ccv2.Warnings{"create-service-instance-warning"},
   361  						nil)
   362  				})
   363  
   364  				It("returns the service instance and warnings", func() {
   365  					By("getting the space services")
   366  					Expect(createServiceErr).ToNot(HaveOccurred())
   367  
   368  					Expect(fakeCloudControllerClient.GetSpaceServicesCallCount()).To(Equal(1))
   369  					spaceGUID, serviceFilters := fakeCloudControllerClient.GetSpaceServicesArgsForCall(0)
   370  					Expect(spaceGUID).To(Equal("space-guid"))
   371  					Expect(serviceFilters).To(Equal(
   372  						[]ccv2.Filter{
   373  							{
   374  								Type:     constant.LabelFilter,
   375  								Operator: constant.EqualOperator,
   376  								Values:   []string{"service"},
   377  							},
   378  						},
   379  					))
   380  
   381  					By("getting the plans of the service")
   382  					Expect(fakeCloudControllerClient.GetServicePlansCallCount()).To(Equal(1))
   383  					planFilter := fakeCloudControllerClient.GetServicePlansArgsForCall(0)
   384  					Expect(planFilter).To(Equal([]ccv2.Filter{{
   385  						Type:     constant.ServiceGUIDFilter,
   386  						Operator: constant.EqualOperator,
   387  						Values:   []string{"a-service-guid"},
   388  					}},
   389  					))
   390  
   391  					By("creating the service instance")
   392  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(1))
   393  					spaceGUID, planGUID, serviceInstanceName, parameters, tags := fakeCloudControllerClient.CreateServiceInstanceArgsForCall(0)
   394  					Expect(serviceInstanceName).To(Equal("service-instance"))
   395  					Expect(spaceGUID).To(Equal("space-guid"))
   396  					Expect(planGUID).To(Equal("the-service-plan-guid"))
   397  					Expect(parameters).To(Equal(map[string]interface{}{
   398  						"some": "params",
   399  					}))
   400  					Expect(tags).To(ConsistOf("tag-1", "tag-2"))
   401  
   402  					Expect(serviceInstance).To(Equal(ServiceInstance(returnedInstance)))
   403  					Expect(createServiceWarnings).To(ConsistOf("create-service-instance-warning"))
   404  				})
   405  			})
   406  
   407  			When("the specified service broker is not present in the list of services accessible to the user", func() {
   408  				BeforeEach(func() {
   409  					fakeCloudControllerClient.GetSpaceServicesReturns(
   410  						[]ccv2.Service{
   411  							{
   412  								GUID:              "a-service-guid",
   413  								ServiceBrokerName: "the-wrong-broker",
   414  							},
   415  							{
   416  								GUID:              "another-service-guid",
   417  								ServiceBrokerName: "not-this-broker-either",
   418  							},
   419  						},
   420  						nil,
   421  						nil,
   422  					)
   423  				})
   424  
   425  				It("returns the error", func() {
   426  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   427  					Expect(createServiceErr).To(MatchError(actionerror.ServiceAndBrokerCombinationNotFoundError{ServiceName: "service", BrokerName: brokerName}))
   428  
   429  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   430  				})
   431  			})
   432  
   433  			When("the list of services does not include service broker names", func() {
   434  				BeforeEach(func() {
   435  					fakeCloudControllerClient.GetSpaceServicesReturns(
   436  						[]ccv2.Service{
   437  							{GUID: "a-service-guid"},
   438  							{GUID: "another-service-guid"},
   439  						},
   440  						nil,
   441  						nil,
   442  					)
   443  				})
   444  
   445  				It("returns the appropriate error", func() {
   446  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   447  					Expect(createServiceErr).To(MatchError(actionerror.ServiceAndBrokerCombinationNotFoundError{ServiceName: "service", BrokerName: brokerName}))
   448  
   449  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   450  				})
   451  			})
   452  
   453  			When("there is an error getting the list of space services", func() {
   454  				BeforeEach(func() {
   455  					fakeCloudControllerClient.GetSpaceServicesReturns(
   456  						[]ccv2.Service{{}},
   457  						ccv2.Warnings{"get-space-services-warning"},
   458  						errors.New("oh no"),
   459  					)
   460  				})
   461  
   462  				It("returns the error and warnings", func() {
   463  					Expect(serviceInstance).To(Equal(ServiceInstance{}))
   464  					Expect(createServiceErr).To(MatchError("oh no"))
   465  					Expect(createServiceWarnings).To(ConsistOf("get-space-services-warning"))
   466  
   467  					Expect(fakeCloudControllerClient.CreateServiceInstanceCallCount()).To(Equal(0))
   468  				})
   469  			})
   470  		})
   471  	})
   472  
   473  	Describe("ServiceInstance", func() {
   474  		DescribeTable("IsManaged",
   475  			func(iType constant.ServiceInstanceType, expected bool) {
   476  				Expect(ServiceInstance{Type: iType}.IsManaged()).To(Equal(expected))
   477  			},
   478  
   479  			Entry("return true for managed service", constant.ManagedService, true),
   480  			Entry("return false for any other type of service", constant.UserProvidedService, false),
   481  		)
   482  
   483  		DescribeTable("IsUserProvided",
   484  			func(iType constant.ServiceInstanceType, expected bool) {
   485  				Expect(ServiceInstance{Type: iType}.IsUserProvided()).To(Equal(expected))
   486  			},
   487  
   488  			Entry("return true for UserProvidedService service", constant.UserProvidedService, true),
   489  			Entry("return false for any other type of service", constant.ManagedService, false),
   490  		)
   491  	})
   492  
   493  	Describe("GetServiceInstance", func() {
   494  		var (
   495  			serviceInstanceGUID string
   496  
   497  			serviceInstance ServiceInstance
   498  			warnings        Warnings
   499  			executeErr      error
   500  		)
   501  
   502  		BeforeEach(func() {
   503  			serviceInstanceGUID = "service-instance-guid"
   504  		})
   505  
   506  		JustBeforeEach(func() {
   507  			serviceInstance, warnings, executeErr = actor.GetServiceInstance(serviceInstanceGUID)
   508  		})
   509  
   510  		When("the service instance exists", func() {
   511  			BeforeEach(func() {
   512  				fakeCloudControllerClient.GetServiceInstanceReturns(ccv2.ServiceInstance{Name: "some-service-instance", GUID: "service-instance-guid"}, ccv2.Warnings{"service-instance-warnings"}, nil)
   513  			})
   514  
   515  			It("returns the service instance and warnings", func() {
   516  				Expect(executeErr).ToNot(HaveOccurred())
   517  				Expect(serviceInstance).To(Equal(ServiceInstance{
   518  					GUID: "service-instance-guid",
   519  					Name: "some-service-instance",
   520  				}))
   521  				Expect(warnings).To(ConsistOf("service-instance-warnings"))
   522  
   523  				Expect(fakeCloudControllerClient.GetServiceInstanceCallCount()).To(Equal(1))
   524  				Expect(fakeCloudControllerClient.GetServiceInstanceArgsForCall(0)).To(Equal(serviceInstanceGUID))
   525  			})
   526  		})
   527  
   528  		When("the service instance does not exist", func() {
   529  			BeforeEach(func() {
   530  				fakeCloudControllerClient.GetServiceInstanceReturns(ccv2.ServiceInstance{}, ccv2.Warnings{"service-instance-warnings-1"}, ccerror.ResourceNotFoundError{})
   531  			})
   532  
   533  			It("returns errors and warnings", func() {
   534  				Expect(executeErr).To(MatchError(actionerror.ServiceInstanceNotFoundError{GUID: serviceInstanceGUID}))
   535  				Expect(warnings).To(ConsistOf("service-instance-warnings-1"))
   536  			})
   537  		})
   538  
   539  		When("retrieving the application's bound services returns an error", func() {
   540  			var expectedErr error
   541  
   542  			BeforeEach(func() {
   543  				expectedErr = errors.New("this is indeed an error, kudos!")
   544  				fakeCloudControllerClient.GetServiceInstanceReturns(ccv2.ServiceInstance{}, ccv2.Warnings{"service-instance-warnings-1"}, expectedErr)
   545  			})
   546  
   547  			It("returns errors and warnings", func() {
   548  				Expect(executeErr).To(MatchError(expectedErr))
   549  				Expect(warnings).To(ConsistOf("service-instance-warnings-1"))
   550  			})
   551  		})
   552  	})
   553  
   554  	Describe("GetServiceInstanceByNameAndSpace", func() {
   555  		When("the service instance exists", func() {
   556  			BeforeEach(func() {
   557  				fakeCloudControllerClient.GetSpaceServiceInstancesReturns(
   558  					[]ccv2.ServiceInstance{
   559  						{
   560  							GUID: "some-service-instance-guid",
   561  							Name: "some-service-instance",
   562  						},
   563  					},
   564  					ccv2.Warnings{"foo"},
   565  					nil,
   566  				)
   567  			})
   568  
   569  			It("returns the service instance and warnings", func() {
   570  				serviceInstance, warnings, err := actor.GetServiceInstanceByNameAndSpace("some-service-instance", "some-space-guid")
   571  				Expect(err).ToNot(HaveOccurred())
   572  				Expect(serviceInstance).To(Equal(ServiceInstance{
   573  					GUID: "some-service-instance-guid",
   574  					Name: "some-service-instance",
   575  				}))
   576  				Expect(warnings).To(ConsistOf("foo"))
   577  
   578  				Expect(fakeCloudControllerClient.GetSpaceServiceInstancesCallCount()).To(Equal(1))
   579  
   580  				spaceGUID, includeUserProvidedServices, queries := fakeCloudControllerClient.GetSpaceServiceInstancesArgsForCall(0)
   581  				Expect(spaceGUID).To(Equal("some-space-guid"))
   582  				Expect(includeUserProvidedServices).To(BeTrue())
   583  				Expect(queries).To(ConsistOf([]ccv2.Filter{
   584  					ccv2.Filter{
   585  						Type:     constant.NameFilter,
   586  						Operator: constant.EqualOperator,
   587  						Values:   []string{"some-service-instance"},
   588  					},
   589  				}))
   590  			})
   591  		})
   592  
   593  		When("the service instance does not exists", func() {
   594  			BeforeEach(func() {
   595  				fakeCloudControllerClient.GetSpaceServiceInstancesReturns([]ccv2.ServiceInstance{}, nil, nil)
   596  			})
   597  
   598  			It("returns a ServiceInstanceNotFoundError", func() {
   599  				_, _, err := actor.GetServiceInstanceByNameAndSpace("some-service-instance", "some-space-guid")
   600  				Expect(err).To(MatchError(actionerror.ServiceInstanceNotFoundError{Name: "some-service-instance"}))
   601  			})
   602  		})
   603  
   604  		When("the cloud controller client returns an error", func() {
   605  			var expectedError error
   606  
   607  			BeforeEach(func() {
   608  				expectedError = errors.New("I am a CloudControllerClient Error")
   609  				fakeCloudControllerClient.GetSpaceServiceInstancesReturns([]ccv2.ServiceInstance{}, nil, expectedError)
   610  			})
   611  
   612  			It("returns the error", func() {
   613  				_, _, err := actor.GetServiceInstanceByNameAndSpace("some-service-instance", "some-space-guid")
   614  				Expect(err).To(MatchError(expectedError))
   615  			})
   616  		})
   617  	})
   618  
   619  	Describe("GetServiceInstancesByApplication", func() {
   620  		var (
   621  			appGUID string
   622  
   623  			serviceInstances []ServiceInstance
   624  			warnings         Warnings
   625  			executeErr       error
   626  		)
   627  
   628  		BeforeEach(func() {
   629  			appGUID = "some-app-guid"
   630  		})
   631  
   632  		JustBeforeEach(func() {
   633  			serviceInstances, warnings, executeErr = actor.GetServiceInstancesByApplication(appGUID)
   634  		})
   635  
   636  		When("the application has services bound", func() {
   637  			var serviceBindings []ccv2.ServiceBinding
   638  
   639  			BeforeEach(func() {
   640  				serviceBindings = []ccv2.ServiceBinding{
   641  					{ServiceInstanceGUID: "service-instance-guid-1"},
   642  					{ServiceInstanceGUID: "service-instance-guid-2"},
   643  					{ServiceInstanceGUID: "service-instance-guid-3"},
   644  				}
   645  
   646  				fakeCloudControllerClient.GetServiceBindingsReturns(serviceBindings, ccv2.Warnings{"service-bindings-warnings-1", "service-bindings-warnings-2"}, nil)
   647  			})
   648  
   649  			When("retrieving the service instances is successful", func() {
   650  				BeforeEach(func() {
   651  					fakeCloudControllerClient.GetServiceInstanceReturnsOnCall(0, ccv2.ServiceInstance{Name: "some-service-instance-1"}, ccv2.Warnings{"service-instance-warnings-1"}, nil)
   652  					fakeCloudControllerClient.GetServiceInstanceReturnsOnCall(1, ccv2.ServiceInstance{Name: "some-service-instance-2"}, ccv2.Warnings{"service-instance-warnings-2"}, nil)
   653  					fakeCloudControllerClient.GetServiceInstanceReturnsOnCall(2, ccv2.ServiceInstance{Name: "some-service-instance-3"}, ccv2.Warnings{"service-instance-warnings-3"}, nil)
   654  				})
   655  
   656  				It("returns the service instances and warnings", func() {
   657  					Expect(executeErr).ToNot(HaveOccurred())
   658  					Expect(warnings).To(ConsistOf("service-bindings-warnings-1", "service-bindings-warnings-2", "service-instance-warnings-1", "service-instance-warnings-2", "service-instance-warnings-3"))
   659  					Expect(serviceInstances).To(ConsistOf(
   660  						ServiceInstance{Name: "some-service-instance-1"},
   661  						ServiceInstance{Name: "some-service-instance-2"},
   662  						ServiceInstance{Name: "some-service-instance-3"},
   663  					))
   664  
   665  					Expect(fakeCloudControllerClient.GetServiceInstanceCallCount()).To(Equal(3))
   666  					Expect(fakeCloudControllerClient.GetServiceInstanceArgsForCall(0)).To(Equal("service-instance-guid-1"))
   667  					Expect(fakeCloudControllerClient.GetServiceInstanceArgsForCall(1)).To(Equal("service-instance-guid-2"))
   668  					Expect(fakeCloudControllerClient.GetServiceInstanceArgsForCall(2)).To(Equal("service-instance-guid-3"))
   669  				})
   670  			})
   671  
   672  			When("retrieving the service instances returns an error", func() {
   673  				var expectedErr error
   674  
   675  				BeforeEach(func() {
   676  					expectedErr = errors.New("this is indeed an error, kudos!")
   677  					fakeCloudControllerClient.GetServiceInstanceReturns(ccv2.ServiceInstance{}, ccv2.Warnings{"service-instance-warnings-1", "service-instance-warnings-2"}, expectedErr)
   678  				})
   679  
   680  				It("returns errors and warnings", func() {
   681  					Expect(executeErr).To(MatchError(expectedErr))
   682  					Expect(warnings).To(ConsistOf("service-bindings-warnings-1", "service-bindings-warnings-2", "service-instance-warnings-1", "service-instance-warnings-2"))
   683  				})
   684  			})
   685  		})
   686  
   687  		When("the application has no services bound", func() {
   688  			BeforeEach(func() {
   689  				fakeCloudControllerClient.GetServiceBindingsReturns(nil, ccv2.Warnings{"service-bindings-warnings-1", "service-bindings-warnings-2"}, nil)
   690  			})
   691  
   692  			It("returns an empty list and warnings", func() {
   693  				Expect(executeErr).ToNot(HaveOccurred())
   694  				Expect(warnings).To(ConsistOf("service-bindings-warnings-1", "service-bindings-warnings-2"))
   695  				Expect(serviceInstances).To(BeEmpty())
   696  			})
   697  		})
   698  
   699  		When("retrieving the application's bound services returns an error", func() {
   700  			var expectedErr error
   701  
   702  			BeforeEach(func() {
   703  				expectedErr = errors.New("this is indeed an error, kudos!")
   704  				fakeCloudControllerClient.GetServiceBindingsReturns(nil, ccv2.Warnings{"service-bindings-warnings-1", "service-bindings-warnings-2"}, expectedErr)
   705  			})
   706  
   707  			It("returns errors and warnings", func() {
   708  				Expect(executeErr).To(MatchError(expectedErr))
   709  				Expect(warnings).To(ConsistOf("service-bindings-warnings-1", "service-bindings-warnings-2"))
   710  			})
   711  		})
   712  	})
   713  
   714  	Describe("GetServiceInstancesBySpace", func() {
   715  		When("there are service instances", func() {
   716  			BeforeEach(func() {
   717  				fakeCloudControllerClient.GetSpaceServiceInstancesReturns(
   718  					[]ccv2.ServiceInstance{
   719  						{
   720  							GUID: "some-service-instance-guid-1",
   721  							Name: "some-service-instance-1",
   722  						},
   723  						{
   724  							GUID: "some-service-instance-guid-2",
   725  							Name: "some-service-instance-2",
   726  						},
   727  					},
   728  					ccv2.Warnings{"warning-1", "warning-2"},
   729  					nil,
   730  				)
   731  			})
   732  
   733  			It("returns the service instances and warnings", func() {
   734  				serviceInstances, warnings, err := actor.GetServiceInstancesBySpace("some-space-guid")
   735  				Expect(err).ToNot(HaveOccurred())
   736  				Expect(serviceInstances).To(ConsistOf(
   737  					ServiceInstance{
   738  						GUID: "some-service-instance-guid-1",
   739  						Name: "some-service-instance-1",
   740  					},
   741  					ServiceInstance{
   742  						GUID: "some-service-instance-guid-2",
   743  						Name: "some-service-instance-2",
   744  					},
   745  				))
   746  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   747  
   748  				Expect(fakeCloudControllerClient.GetSpaceServiceInstancesCallCount()).To(Equal(1))
   749  
   750  				spaceGUID, includeUserProvidedServices, queries := fakeCloudControllerClient.GetSpaceServiceInstancesArgsForCall(0)
   751  				Expect(spaceGUID).To(Equal("some-space-guid"))
   752  				Expect(includeUserProvidedServices).To(BeTrue())
   753  				Expect(queries).To(BeNil())
   754  			})
   755  		})
   756  
   757  		When("the cloud controller client returns an error", func() {
   758  			var expectedError error
   759  
   760  			BeforeEach(func() {
   761  				expectedError = errors.New("I am a CloudControllerClient Error")
   762  				fakeCloudControllerClient.GetSpaceServiceInstancesReturns(
   763  					[]ccv2.ServiceInstance{},
   764  					ccv2.Warnings{"warning-1", "warning-2"},
   765  					expectedError)
   766  			})
   767  
   768  			It("returns the error and warnings", func() {
   769  				_, warnings, err := actor.GetServiceInstancesBySpace("some-space-guid")
   770  				Expect(err).To(MatchError(expectedError))
   771  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   772  			})
   773  		})
   774  	})
   775  
   776  	Describe("UpdateServiceInstanceMaintenanceInfo", func() {
   777  		const serviceInstanceGUID = "service-instance-guid"
   778  		var maintenanceInfo MaintenanceInfo
   779  
   780  		BeforeEach(func() {
   781  			maintenanceInfo = MaintenanceInfo{
   782  				Version: "1.2.3",
   783  			}
   784  		})
   785  
   786  		When("the update is successful", func() {
   787  			BeforeEach(func() {
   788  				fakeCloudControllerClient.UpdateServiceInstanceMaintenanceInfoReturns(
   789  					ccv2.Warnings{"warning-1", "warning-2"},
   790  					nil,
   791  				)
   792  			})
   793  
   794  			It("returns all the warnings", func() {
   795  				warnings, err := actor.UpdateServiceInstanceMaintenanceInfo(serviceInstanceGUID, maintenanceInfo)
   796  				Expect(err).NotTo(HaveOccurred())
   797  
   798  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   799  				Expect(fakeCloudControllerClient.UpdateServiceInstanceMaintenanceInfoCallCount()).To(Equal(1))
   800  				guid, minfo := fakeCloudControllerClient.UpdateServiceInstanceMaintenanceInfoArgsForCall(0)
   801  				Expect(guid).To(Equal(serviceInstanceGUID))
   802  				Expect(minfo).To(Equal(ccv2.MaintenanceInfo(maintenanceInfo)))
   803  			})
   804  		})
   805  
   806  		When("the update fails", func() {
   807  			BeforeEach(func() {
   808  				fakeCloudControllerClient.UpdateServiceInstanceMaintenanceInfoReturns(
   809  					ccv2.Warnings{"warning-1", "warning-2"},
   810  					errors.New("update failed horribly!!!"),
   811  				)
   812  			})
   813  
   814  			It("returns the error and all the warnings", func() {
   815  				warnings, err := actor.UpdateServiceInstanceMaintenanceInfo(serviceInstanceGUID, maintenanceInfo)
   816  				Expect(err).To(MatchError("update failed horribly!!!"))
   817  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   818  			})
   819  		})
   820  	})
   821  })