github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/api/cloudcontroller/ccv3/service_instance_test.go (about)

     1  package ccv3_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
    10  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/ccv3fakes"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/internal"
    13  	"code.cloudfoundry.org/cli/resources"
    14  	"code.cloudfoundry.org/cli/types"
    15  	"code.cloudfoundry.org/jsonry"
    16  	. "github.com/onsi/ginkgo"
    17  	. "github.com/onsi/gomega"
    18  )
    19  
    20  var _ = Describe("Service Instance", func() {
    21  	var (
    22  		requester *ccv3fakes.FakeRequester
    23  		client    *Client
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		requester = new(ccv3fakes.FakeRequester)
    28  		client, _ = NewFakeRequesterTestClient(requester)
    29  	})
    30  
    31  	Describe("GetServiceInstances", func() {
    32  		var (
    33  			query      Query
    34  			instances  []resources.ServiceInstance
    35  			included   IncludedResources
    36  			warnings   Warnings
    37  			executeErr error
    38  		)
    39  
    40  		JustBeforeEach(func() {
    41  			instances, included, warnings, executeErr = client.GetServiceInstances(query)
    42  		})
    43  
    44  		When("service instances exist", func() {
    45  			BeforeEach(func() {
    46  				requester.MakeListRequestCalls(func(requestParams RequestParams) (IncludedResources, Warnings, error) {
    47  					for i := 1; i <= 3; i++ {
    48  						Expect(requestParams.AppendToList(resources.ServiceInstance{
    49  							GUID: fmt.Sprintf("service-instance-%d-guid", i),
    50  							Name: fmt.Sprintf("service-instance-%d-name", i),
    51  						})).NotTo(HaveOccurred())
    52  					}
    53  					return IncludedResources{ServiceOfferings: []resources.ServiceOffering{{GUID: "fake-service-offering"}}}, Warnings{"warning-1", "warning-2"}, nil
    54  				})
    55  
    56  				query = Query{
    57  					Key:    NameFilter,
    58  					Values: []string{"some-service-instance-name"},
    59  				}
    60  			})
    61  
    62  			It("returns a list of service instances with warnings and included resources", func() {
    63  				Expect(executeErr).ToNot(HaveOccurred())
    64  
    65  				Expect(instances).To(ConsistOf(
    66  					resources.ServiceInstance{
    67  						GUID: "service-instance-1-guid",
    68  						Name: "service-instance-1-name",
    69  					},
    70  					resources.ServiceInstance{
    71  						GUID: "service-instance-2-guid",
    72  						Name: "service-instance-2-name",
    73  					},
    74  					resources.ServiceInstance{
    75  						GUID: "service-instance-3-guid",
    76  						Name: "service-instance-3-name",
    77  					},
    78  				))
    79  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
    80  				Expect(included).To(Equal(IncludedResources{ServiceOfferings: []resources.ServiceOffering{{GUID: "fake-service-offering"}}}))
    81  
    82  				Expect(requester.MakeListRequestCallCount()).To(Equal(1))
    83  				actualParams := requester.MakeListRequestArgsForCall(0)
    84  				Expect(actualParams.RequestName).To(Equal(internal.GetServiceInstancesRequest))
    85  				Expect(actualParams.Query).To(ConsistOf(query))
    86  				Expect(actualParams.ResponseBody).To(BeAssignableToTypeOf(resources.ServiceInstance{}))
    87  			})
    88  		})
    89  
    90  		When("the cloud controller returns errors and warnings", func() {
    91  			BeforeEach(func() {
    92  				errors := []ccerror.V3Error{
    93  					{
    94  						Code:   42424,
    95  						Detail: "Some detailed error message",
    96  						Title:  "CF-SomeErrorTitle",
    97  					},
    98  					{
    99  						Code:   11111,
   100  						Detail: "Some other detailed error message",
   101  						Title:  "CF-SomeOtherErrorTitle",
   102  					},
   103  				}
   104  
   105  				requester.MakeListRequestReturns(
   106  					IncludedResources{},
   107  					Warnings{"this is a warning"},
   108  					ccerror.MultiError{ResponseCode: http.StatusTeapot, Errors: errors},
   109  				)
   110  			})
   111  
   112  			It("returns the error and all warnings", func() {
   113  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   114  					ResponseCode: http.StatusTeapot,
   115  					Errors: []ccerror.V3Error{
   116  						{
   117  							Code:   42424,
   118  							Detail: "Some detailed error message",
   119  							Title:  "CF-SomeErrorTitle",
   120  						},
   121  						{
   122  							Code:   11111,
   123  							Detail: "Some other detailed error message",
   124  							Title:  "CF-SomeOtherErrorTitle",
   125  						},
   126  					},
   127  				}))
   128  				Expect(warnings).To(ConsistOf("this is a warning"))
   129  			})
   130  		})
   131  	})
   132  
   133  	Describe("GetServiceInstanceByNameAndSpace", func() {
   134  		const (
   135  			name      = "fake-service-instance-name"
   136  			spaceGUID = "fake-space-guid"
   137  		)
   138  		var (
   139  			instance   resources.ServiceInstance
   140  			included   IncludedResources
   141  			warnings   Warnings
   142  			executeErr error
   143  			query      []Query
   144  		)
   145  
   146  		BeforeEach(func() {
   147  			query = []Query{{Key: Include, Values: []string{"unicorns"}}}
   148  		})
   149  
   150  		JustBeforeEach(func() {
   151  			instance, included, warnings, executeErr = client.GetServiceInstanceByNameAndSpace(name, spaceGUID, query...)
   152  		})
   153  
   154  		It("makes the correct API request", func() {
   155  			Expect(requester.MakeListRequestCallCount()).To(Equal(1))
   156  			actualParams := requester.MakeListRequestArgsForCall(0)
   157  			Expect(actualParams.RequestName).To(Equal(internal.GetServiceInstancesRequest))
   158  			Expect(actualParams.Query).To(ConsistOf(
   159  				Query{Key: NameFilter, Values: []string{name}},
   160  				Query{Key: SpaceGUIDFilter, Values: []string{spaceGUID}},
   161  				Query{Key: PerPage, Values: []string{"1"}},
   162  				Query{Key: Page, Values: []string{"1"}},
   163  				Query{Key: Include, Values: []string{"unicorns"}},
   164  			))
   165  			Expect(actualParams.ResponseBody).To(BeAssignableToTypeOf(resources.ServiceInstance{}))
   166  		})
   167  
   168  		When("there are no matches", func() {
   169  			BeforeEach(func() {
   170  				requester.MakeListRequestReturns(
   171  					IncludedResources{},
   172  					Warnings{"this is a warning"},
   173  					nil,
   174  				)
   175  			})
   176  
   177  			It("returns an error and warnings", func() {
   178  				Expect(instance).To(Equal(resources.ServiceInstance{}))
   179  				Expect(warnings).To(ConsistOf("this is a warning"))
   180  				Expect(executeErr).To(MatchError(ccerror.ServiceInstanceNotFoundError{
   181  					Name:      name,
   182  					SpaceGUID: spaceGUID,
   183  				}))
   184  			})
   185  		})
   186  
   187  		When("there is a single match", func() {
   188  			BeforeEach(func() {
   189  				requester.MakeListRequestCalls(func(requestParams RequestParams) (IncludedResources, Warnings, error) {
   190  					Expect(requestParams.AppendToList(resources.ServiceInstance{
   191  						Name: name,
   192  						GUID: "service-instance-guid",
   193  					})).NotTo(HaveOccurred())
   194  
   195  					return IncludedResources{ServiceOfferings: []resources.ServiceOffering{{GUID: "fake-offering-guid"}}},
   196  						Warnings{"warning-1", "warning-2"},
   197  						nil
   198  				})
   199  			})
   200  
   201  			It("returns the resource, included resources, and warnings", func() {
   202  				Expect(instance).To(Equal(resources.ServiceInstance{
   203  					Name: name,
   204  					GUID: "service-instance-guid",
   205  				}))
   206  				Expect(included).To(Equal(IncludedResources{ServiceOfferings: []resources.ServiceOffering{{GUID: "fake-offering-guid"}}}))
   207  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   208  				Expect(executeErr).NotTo(HaveOccurred())
   209  			})
   210  		})
   211  
   212  		When("there are multiple matches", func() {
   213  			BeforeEach(func() {
   214  				requester.MakeListRequestCalls(func(requestParams RequestParams) (IncludedResources, Warnings, error) {
   215  					for i := 1; i <= 3; i++ {
   216  						Expect(requestParams.AppendToList(resources.ServiceInstance{
   217  							GUID: fmt.Sprintf("service-instance-%d-guid", i),
   218  							Name: fmt.Sprintf("service-instance-%d-name", i),
   219  						})).NotTo(HaveOccurred())
   220  					}
   221  					return IncludedResources{}, Warnings{"warning-1", "warning-2"}, nil
   222  				})
   223  			})
   224  
   225  			It("returns the first resource and warnings", func() {
   226  				Expect(instance).To(Equal(resources.ServiceInstance{
   227  					Name: "service-instance-1-name",
   228  					GUID: "service-instance-1-guid",
   229  				}))
   230  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   231  				Expect(executeErr).NotTo(HaveOccurred())
   232  			})
   233  		})
   234  
   235  		When("the cloud controller returns errors and warnings", func() {
   236  			BeforeEach(func() {
   237  				errors := []ccerror.V3Error{
   238  					{
   239  						Code:   42424,
   240  						Detail: "Some detailed error message",
   241  						Title:  "CF-SomeErrorTitle",
   242  					},
   243  					{
   244  						Code:   11111,
   245  						Detail: "Some other detailed error message",
   246  						Title:  "CF-SomeOtherErrorTitle",
   247  					},
   248  				}
   249  
   250  				requester.MakeListRequestCalls(func(requestParams RequestParams) (IncludedResources, Warnings, error) {
   251  					Expect(requestParams.AppendToList(resources.ServiceInstance{
   252  						GUID: "service-instance-guid",
   253  						Name: "service-instance-name",
   254  					})).NotTo(HaveOccurred())
   255  
   256  					return IncludedResources{},
   257  						Warnings{"warning-1", "warning-2"},
   258  						ccerror.MultiError{ResponseCode: http.StatusTeapot, Errors: errors}
   259  				})
   260  			})
   261  
   262  			It("returns the error and all warnings", func() {
   263  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   264  					ResponseCode: http.StatusTeapot,
   265  					Errors: []ccerror.V3Error{
   266  						{
   267  							Code:   42424,
   268  							Detail: "Some detailed error message",
   269  							Title:  "CF-SomeErrorTitle",
   270  						},
   271  						{
   272  							Code:   11111,
   273  							Detail: "Some other detailed error message",
   274  							Title:  "CF-SomeOtherErrorTitle",
   275  						},
   276  					},
   277  				}))
   278  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   279  			})
   280  		})
   281  	})
   282  
   283  	Describe("GetServiceInstanceParameters", func() {
   284  		const guid = "fake-service-instance-guid"
   285  
   286  		BeforeEach(func() {
   287  			requester.MakeRequestCalls(func(params RequestParams) (JobURL, Warnings, error) {
   288  				json.Unmarshal([]byte(`{"foo":"bar"}`), params.ResponseBody)
   289  				return "", Warnings{"one", "two"}, nil
   290  			})
   291  		})
   292  
   293  		It("makes the correct API request", func() {
   294  			client.GetServiceInstanceParameters(guid)
   295  
   296  			Expect(requester.MakeRequestCallCount()).To(Equal(1))
   297  			actualRequest := requester.MakeRequestArgsForCall(0)
   298  			Expect(actualRequest.RequestName).To(Equal(internal.GetServiceInstanceParametersRequest))
   299  			Expect(actualRequest.URIParams).To(Equal(internal.Params{"service_instance_guid": guid}))
   300  		})
   301  
   302  		It("returns the parameters", func() {
   303  			params, warnings, err := client.GetServiceInstanceParameters(guid)
   304  			Expect(err).NotTo(HaveOccurred())
   305  			Expect(warnings).To(ConsistOf("one", "two"))
   306  			Expect(params).To(Equal(types.JSONObject{"foo": "bar"}))
   307  		})
   308  
   309  		When("there is an error getting the parameters", func() {
   310  			BeforeEach(func() {
   311  				requester.MakeRequestReturns("", Warnings{"one", "two"}, errors.New("boom"))
   312  			})
   313  
   314  			It("returns warnings and an error", func() {
   315  				params, warnings, err := client.GetServiceInstanceParameters(guid)
   316  				Expect(err).To(MatchError("boom"))
   317  				Expect(warnings).To(ConsistOf("one", "two"))
   318  				Expect(params).To(BeEmpty())
   319  			})
   320  		})
   321  	})
   322  
   323  	Describe("CreateServiceInstance", func() {
   324  		Context("synchronous response", func() {
   325  			When("the request succeeds", func() {
   326  				It("returns warnings and no errors", func() {
   327  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, nil)
   328  
   329  					si := resources.ServiceInstance{
   330  						Type:            resources.UserProvidedServiceInstance,
   331  						Name:            "fake-user-provided-service-instance",
   332  						SpaceGUID:       "fake-space-guid",
   333  						Tags:            types.NewOptionalStringSlice("foo", "bar"),
   334  						RouteServiceURL: types.NewOptionalString("https://fake-route.com"),
   335  						SyslogDrainURL:  types.NewOptionalString("https://fake-sylogg.com"),
   336  						Credentials: types.NewOptionalObject(map[string]interface{}{
   337  							"foo": "bar",
   338  							"baz": 42,
   339  						}),
   340  					}
   341  
   342  					jobURL, warnings, err := client.CreateServiceInstance(si)
   343  
   344  					Expect(jobURL).To(BeEmpty())
   345  					Expect(warnings).To(ConsistOf("fake-warning"))
   346  					Expect(err).NotTo(HaveOccurred())
   347  
   348  					Expect(requester.MakeRequestCallCount()).To(Equal(1))
   349  					Expect(requester.MakeRequestArgsForCall(0)).To(Equal(RequestParams{
   350  						RequestName: internal.PostServiceInstanceRequest,
   351  						RequestBody: si,
   352  					}))
   353  				})
   354  			})
   355  
   356  			When("the request fails", func() {
   357  				It("returns errors and warnings", func() {
   358  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   359  
   360  					si := resources.ServiceInstance{
   361  						Type:            resources.UserProvidedServiceInstance,
   362  						Name:            "fake-user-provided-service-instance",
   363  						SpaceGUID:       "fake-space-guid",
   364  						Tags:            types.NewOptionalStringSlice("foo", "bar"),
   365  						RouteServiceURL: types.NewOptionalString("https://fake-route.com"),
   366  						SyslogDrainURL:  types.NewOptionalString("https://fake-sylogg.com"),
   367  						Credentials: types.NewOptionalObject(map[string]interface{}{
   368  							"foo": "bar",
   369  							"baz": 42,
   370  						}),
   371  					}
   372  
   373  					jobURL, warnings, err := client.CreateServiceInstance(si)
   374  
   375  					Expect(jobURL).To(BeEmpty())
   376  					Expect(warnings).To(ConsistOf("fake-warning"))
   377  					Expect(err).To(MatchError("bang"))
   378  				})
   379  			})
   380  		})
   381  	})
   382  
   383  	Describe("UpdateServiceInstance", func() {
   384  		const (
   385  			guid   = "fake-service-instance-guid"
   386  			jobURL = JobURL("fake-job-url")
   387  		)
   388  
   389  		var serviceInstance resources.ServiceInstance
   390  
   391  		Context("user provided", func() {
   392  			BeforeEach(func() {
   393  				serviceInstance = resources.ServiceInstance{
   394  					Name:            "fake-new-user-provided-service-instance",
   395  					Tags:            types.NewOptionalStringSlice("foo", "bar"),
   396  					RouteServiceURL: types.NewOptionalString("https://fake-route.com"),
   397  					SyslogDrainURL:  types.NewOptionalString("https://fake-sylogg.com"),
   398  					Credentials: types.NewOptionalObject(map[string]interface{}{
   399  						"foo": "bar",
   400  						"baz": 42,
   401  					}),
   402  					MaintenanceInfoVersion: "9.1.2",
   403  				}
   404  			})
   405  
   406  			When("the request succeeds", func() {
   407  				BeforeEach(func() {
   408  					requester.MakeRequestReturns(jobURL, Warnings{"fake-warning"}, nil)
   409  				})
   410  
   411  				It("returns warnings and no errors", func() {
   412  					job, warnings, err := client.UpdateServiceInstance(guid, serviceInstance)
   413  
   414  					Expect(job).To(Equal(jobURL))
   415  					Expect(warnings).To(ConsistOf("fake-warning"))
   416  					Expect(err).NotTo(HaveOccurred())
   417  
   418  					Expect(requester.MakeRequestCallCount()).To(Equal(1))
   419  					Expect(requester.MakeRequestArgsForCall(0)).To(Equal(RequestParams{
   420  						RequestName: internal.PatchServiceInstanceRequest,
   421  						URIParams:   internal.Params{"service_instance_guid": guid},
   422  						RequestBody: serviceInstance,
   423  					}))
   424  				})
   425  			})
   426  		})
   427  
   428  		Context("managed", func() {
   429  			BeforeEach(func() {
   430  				serviceInstance = resources.ServiceInstance{
   431  					Name:            "fake-new-user-provided-service-instance",
   432  					Tags:            types.NewOptionalStringSlice("foo", "bar"),
   433  					ServicePlanGUID: guid,
   434  					Parameters:      types.NewOptionalObject(map[string]interface{}{"some-param": "some-value"}),
   435  				}
   436  			})
   437  
   438  			When("the request succeeds", func() {
   439  				BeforeEach(func() {
   440  					requester.MakeRequestReturns(jobURL, Warnings{"fake-warning"}, nil)
   441  				})
   442  
   443  				It("returns warnings and no errors", func() {
   444  					job, warnings, err := client.UpdateServiceInstance(guid, serviceInstance)
   445  
   446  					Expect(job).To(Equal(jobURL))
   447  					Expect(warnings).To(ConsistOf("fake-warning"))
   448  					Expect(err).NotTo(HaveOccurred())
   449  
   450  					Expect(requester.MakeRequestCallCount()).To(Equal(1))
   451  					Expect(requester.MakeRequestArgsForCall(0)).To(Equal(RequestParams{
   452  						RequestName: internal.PatchServiceInstanceRequest,
   453  						URIParams:   internal.Params{"service_instance_guid": guid},
   454  						RequestBody: serviceInstance,
   455  					}))
   456  				})
   457  			})
   458  		})
   459  
   460  		When("the request fails", func() {
   461  			BeforeEach(func() {
   462  				requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   463  			})
   464  
   465  			It("returns errors and warnings", func() {
   466  				jobURL, warnings, err := client.UpdateServiceInstance(guid, serviceInstance)
   467  
   468  				Expect(jobURL).To(BeEmpty())
   469  				Expect(warnings).To(ConsistOf("fake-warning"))
   470  				Expect(err).To(MatchError("bang"))
   471  			})
   472  		})
   473  	})
   474  
   475  	Describe("DeleteServiceInstance", func() {
   476  		const (
   477  			guid   = "fake-service-instance-guid"
   478  			jobURL = JobURL("fake-job-url")
   479  		)
   480  
   481  		It("makes the right request", func() {
   482  			client.DeleteServiceInstance(guid)
   483  
   484  			Expect(requester.MakeRequestCallCount()).To(Equal(1))
   485  			Expect(requester.MakeRequestArgsForCall(0)).To(Equal(RequestParams{
   486  				RequestName: internal.DeleteServiceInstanceRequest,
   487  				URIParams:   internal.Params{"service_instance_guid": guid},
   488  			}))
   489  		})
   490  
   491  		When("there are query parameters", func() {
   492  			It("passes them through", func() {
   493  				client.DeleteServiceInstance(guid, Query{Key: NameFilter, Values: []string{"foo"}})
   494  
   495  				Expect(requester.MakeRequestCallCount()).To(Equal(1))
   496  				Expect(requester.MakeRequestArgsForCall(0).Query).To(ConsistOf(Query{Key: NameFilter, Values: []string{"foo"}}))
   497  			})
   498  		})
   499  
   500  		When("the request succeeds", func() {
   501  			BeforeEach(func() {
   502  				requester.MakeRequestReturns(jobURL, Warnings{"fake-warning"}, nil)
   503  			})
   504  
   505  			It("returns warnings and no errors", func() {
   506  				job, warnings, err := client.DeleteServiceInstance(guid)
   507  
   508  				Expect(job).To(Equal(jobURL))
   509  				Expect(warnings).To(ConsistOf("fake-warning"))
   510  				Expect(err).NotTo(HaveOccurred())
   511  			})
   512  		})
   513  
   514  		When("the request fails", func() {
   515  			BeforeEach(func() {
   516  				requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   517  			})
   518  
   519  			It("returns errors and warnings", func() {
   520  				jobURL, warnings, err := client.DeleteServiceInstance(guid)
   521  
   522  				Expect(jobURL).To(BeEmpty())
   523  				Expect(warnings).To(ConsistOf("fake-warning"))
   524  				Expect(err).To(MatchError("bang"))
   525  			})
   526  		})
   527  	})
   528  
   529  	Describe("shared service instances", func() {
   530  		Describe("ShareServiceInstanceToSpaces", func() {
   531  			var (
   532  				serviceInstanceGUID string
   533  				spaceGUIDs          []string
   534  			)
   535  
   536  			BeforeEach(func() {
   537  				serviceInstanceGUID = "some-service-instance-guid"
   538  				spaceGUIDs = []string{"some-space-guid", "some-other-space-guid"}
   539  			})
   540  
   541  			It("makes the right request", func() {
   542  				client.ShareServiceInstanceToSpaces(serviceInstanceGUID, spaceGUIDs)
   543  
   544  				Expect(requester.MakeRequestCallCount()).To(Equal(1))
   545  
   546  				actualRequest := requester.MakeRequestArgsForCall(0)
   547  				Expect(actualRequest.RequestName).To(Equal(internal.PostServiceInstanceRelationshipsSharedSpacesRequest))
   548  				Expect(actualRequest.URIParams).To(Equal(internal.Params{"service_instance_guid": serviceInstanceGUID}))
   549  				Expect(actualRequest.RequestBody).To(Equal(resources.RelationshipList{
   550  					GUIDs: spaceGUIDs,
   551  				}))
   552  			})
   553  
   554  			When("the request succeeds", func() {
   555  				BeforeEach(func() {
   556  					requester.MakeRequestCalls(func(params RequestParams) (JobURL, Warnings, error) {
   557  						json.Unmarshal([]byte(`{"data":[{"guid":"some-space-guid"}, {"guid":"some-other-space-guid"}]}`), params.ResponseBody)
   558  						return "", Warnings{"fake-warning"}, nil
   559  					})
   560  				})
   561  
   562  				It("returns warnings and no errors", func() {
   563  					relationships, warnings, err := client.ShareServiceInstanceToSpaces(serviceInstanceGUID, spaceGUIDs)
   564  
   565  					Expect(warnings).To(ConsistOf("fake-warning"))
   566  					Expect(err).NotTo(HaveOccurred())
   567  					Expect(relationships).To(Equal(resources.RelationshipList{GUIDs: spaceGUIDs}))
   568  				})
   569  			})
   570  
   571  			When("the request fails", func() {
   572  				BeforeEach(func() {
   573  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   574  				})
   575  
   576  				It("returns errors and warnings", func() {
   577  					_, warnings, err := client.ShareServiceInstanceToSpaces(serviceInstanceGUID, spaceGUIDs)
   578  
   579  					Expect(warnings).To(ConsistOf("fake-warning"))
   580  					Expect(err).To(MatchError("bang"))
   581  				})
   582  			})
   583  		})
   584  
   585  		Describe("UnshareServiceInstanceFromSpace", func() {
   586  			var (
   587  				serviceInstanceGUID string
   588  				spaceGUID           string
   589  			)
   590  
   591  			BeforeEach(func() {
   592  				serviceInstanceGUID = "some-service-instance-guid"
   593  				spaceGUID = "some-space-guid"
   594  			})
   595  
   596  			It("makes the right request", func() {
   597  				client.UnshareServiceInstanceFromSpace(serviceInstanceGUID, spaceGUID)
   598  
   599  				Expect(requester.MakeRequestCallCount()).To(Equal(1))
   600  				Expect(requester.MakeRequestArgsForCall(0)).To(Equal(RequestParams{
   601  					RequestName: internal.DeleteServiceInstanceRelationshipsSharedSpaceRequest,
   602  					URIParams: internal.Params{
   603  						"service_instance_guid": serviceInstanceGUID,
   604  						"space_guid":            spaceGUID},
   605  				}))
   606  			})
   607  
   608  			When("the request succeeds", func() {
   609  				BeforeEach(func() {
   610  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, nil)
   611  				})
   612  
   613  				It("returns warnings and no errors", func() {
   614  					warnings, err := client.UnshareServiceInstanceFromSpace(serviceInstanceGUID, spaceGUID)
   615  
   616  					Expect(warnings).To(ConsistOf("fake-warning"))
   617  					Expect(err).NotTo(HaveOccurred())
   618  				})
   619  			})
   620  
   621  			When("the request fails", func() {
   622  				BeforeEach(func() {
   623  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   624  				})
   625  
   626  				It("returns errors and warnings", func() {
   627  					warnings, err := client.UnshareServiceInstanceFromSpace(serviceInstanceGUID, spaceGUID)
   628  
   629  					Expect(warnings).To(ConsistOf("fake-warning"))
   630  					Expect(err).To(MatchError("bang"))
   631  				})
   632  			})
   633  		})
   634  
   635  		Describe("GetServiceInstanceSharedSpaces", func() {
   636  			var (
   637  				serviceInstanceGUID string
   638  			)
   639  
   640  			BeforeEach(func() {
   641  				serviceInstanceGUID = "some-service-instance-guid"
   642  			})
   643  
   644  			It("makes the right request", func() {
   645  				client.GetServiceInstanceSharedSpaces(serviceInstanceGUID)
   646  
   647  				Expect(requester.MakeRequestCallCount()).To(Equal(1))
   648  
   649  				actualRequest := requester.MakeRequestArgsForCall(0)
   650  				Expect(actualRequest.RequestName).To(Equal(internal.GetServiceInstanceRelationshipsSharedSpacesRequest))
   651  				Expect(actualRequest.URIParams).To(Equal(internal.Params{"service_instance_guid": serviceInstanceGUID}))
   652  				Expect(actualRequest.Query).To(ConsistOf(
   653  					Query{
   654  						Key:    FieldsSpace,
   655  						Values: []string{"guid", "name", "relationships.organization"},
   656  					},
   657  					Query{
   658  						Key:    FieldsSpaceOrganization,
   659  						Values: []string{"guid", "name"},
   660  					},
   661  				))
   662  			})
   663  
   664  			When("the request succeeds", func() {
   665  				BeforeEach(func() {
   666  					requester.MakeRequestCalls(func(params RequestParams) (JobURL, Warnings, error) {
   667  						jsonry.Unmarshal([]byte(`{
   668  								   "data": [{"guid":"some-space-guid"},{"guid":"some-other-space-guid"}],
   669  								   "links": {
   670  									  "self": {
   671  										 "href": "https://some-url/v3/service_instances/7915bc51-8203-4758-b0e2-f77bfcdc38cb/relationships/shared_spaces"
   672  									  }
   673  								   },
   674  								   "included": {
   675  									  "spaces": [
   676  										 {
   677  											"name": "some-space-name",
   678  											"guid": "some-space-guid",
   679  											"relationships": {
   680  											   "organization": {
   681  												  "data": {
   682  													 "guid": "some-org-guid"
   683  												  }
   684  											   }
   685  											}
   686  										 },
   687  										{
   688  											"name": "some-other-space-name",
   689  											"guid": "some-other-space-guid",
   690  											"relationships": {
   691  											   "organization": {
   692  												  "data": {
   693  													 "guid": "some-org-guid"
   694  												  }
   695  											   }
   696  											}
   697  										 }
   698  									  ],
   699  									  "organizations": [
   700  										 {
   701  											"name": "some-org-name",
   702  											"guid": "some-org-guid"
   703  										 }
   704  									  ]
   705  								   }
   706  								}`), params.ResponseBody)
   707  						return "", Warnings{"fake-warning"}, nil
   708  					})
   709  				})
   710  
   711  				It("returns warnings and no errors", func() {
   712  					spaces, warnings, err := client.GetServiceInstanceSharedSpaces(serviceInstanceGUID)
   713  
   714  					Expect(warnings).To(ConsistOf("fake-warning"))
   715  					Expect(err).NotTo(HaveOccurred())
   716  					Expect(spaces).To(Equal([]SpaceWithOrganization{
   717  						{
   718  							SpaceGUID:        "some-space-guid",
   719  							SpaceName:        "some-space-name",
   720  							OrganizationName: "some-org-name",
   721  						},
   722  						{
   723  							SpaceGUID:        "some-other-space-guid",
   724  							SpaceName:        "some-other-space-name",
   725  							OrganizationName: "some-org-name",
   726  						},
   727  					}))
   728  				})
   729  			})
   730  
   731  			When("the request fails", func() {
   732  				BeforeEach(func() {
   733  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   734  				})
   735  
   736  				It("returns errors and warnings", func() {
   737  					_, warnings, err := client.GetServiceInstanceSharedSpaces(serviceInstanceGUID)
   738  
   739  					Expect(warnings).To(ConsistOf("fake-warning"))
   740  					Expect(err).To(MatchError("bang"))
   741  				})
   742  			})
   743  		})
   744  
   745  		Describe("GetServiceInstanceUsageSummary", func() {
   746  			var (
   747  				serviceInstanceGUID string
   748  				spaceGUIDs          []string
   749  			)
   750  
   751  			BeforeEach(func() {
   752  				serviceInstanceGUID = "some-service-instance-guid"
   753  				spaceGUIDs = []string{"some-space-guid", "some-other-space-guid"}
   754  			})
   755  
   756  			It("makes the right request", func() {
   757  				client.GetServiceInstanceUsageSummary(serviceInstanceGUID)
   758  
   759  				Expect(requester.MakeRequestCallCount()).To(Equal(1))
   760  
   761  				actualRequest := requester.MakeRequestArgsForCall(0)
   762  				Expect(actualRequest.RequestName).To(Equal(internal.GetServiceInstanceSharedSpacesUsageSummaryRequest))
   763  				Expect(actualRequest.URIParams).To(Equal(internal.Params{"service_instance_guid": serviceInstanceGUID}))
   764  			})
   765  
   766  			When("the request succeeds", func() {
   767  				BeforeEach(func() {
   768  					requester.MakeRequestCalls(func(params RequestParams) (JobURL, Warnings, error) {
   769  						jsonry.Unmarshal([]byte(`{
   770  							"usage_summary": [
   771  								{
   772  									"space": {
   773  										"guid": "some-space-guid"
   774  									},
   775  									"bound_app_count": 2
   776  								},
   777  								{
   778  									"space": {
   779  										"guid": "some-other-space-guid"
   780  									},
   781  									"bound_app_count": 1
   782  								}
   783  							],
   784  							"links": {
   785  								"self": {
   786  									"href": "https://api.example.org/v3/service_instances/some_instance_guid/relationships/shared_spaces/usage_summary"
   787  								},
   788  								"shared_spaces": {
   789  									"href": "https://api.example.org/v3/service_instances/some_instance_guid/relationships/shared_spaces"
   790  								},
   791  								"service_instance": {
   792  									"href": "https://api.example.org/v3/service_instances/some_instance_guid"
   793  								}
   794  							}
   795  						}`), params.ResponseBody)
   796  						return "", Warnings{"fake-warning"}, nil
   797  					})
   798  				})
   799  
   800  				It("returns warnings and no errors", func() {
   801  					usageSummary, warnings, err := client.GetServiceInstanceUsageSummary(serviceInstanceGUID)
   802  
   803  					Expect(warnings).To(ConsistOf("fake-warning"))
   804  					Expect(err).NotTo(HaveOccurred())
   805  					Expect(usageSummary).To(Equal([]resources.ServiceInstanceUsageSummary{{SpaceGUID: spaceGUIDs[0], BoundAppCount: 2}, {SpaceGUID: spaceGUIDs[1], BoundAppCount: 1}}))
   806  				})
   807  			})
   808  
   809  			When("the request fails", func() {
   810  				BeforeEach(func() {
   811  					requester.MakeRequestReturns("", Warnings{"fake-warning"}, errors.New("bang"))
   812  				})
   813  
   814  				It("returns errors and warnings", func() {
   815  					_, warnings, err := client.GetServiceInstanceUsageSummary(serviceInstanceGUID)
   816  
   817  					Expect(warnings).To(ConsistOf("fake-warning"))
   818  					Expect(err).To(MatchError("bang"))
   819  				})
   820  			})
   821  		})
   822  	})
   823  })