github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/api/cloudcontroller/ccv2/service_binding_test.go (about)

     1  package ccv2_test
     2  
     3  import (
     4  	"net/http"
     5  
     6  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     7  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
     9  	. "github.com/onsi/ginkgo"
    10  	. "github.com/onsi/gomega"
    11  	. "github.com/onsi/gomega/ghttp"
    12  )
    13  
    14  var _ = Describe("Service Binding", func() {
    15  	var client *Client
    16  
    17  	BeforeEach(func() {
    18  		client = NewTestClient()
    19  	})
    20  
    21  	Describe("CreateServiceBinding", func() {
    22  		Context("when the create is successful", func() {
    23  			Context("when a service binding name is provided", func() {
    24  				BeforeEach(func() {
    25  					expectedRequestBody := map[string]interface{}{
    26  						"service_instance_guid": "some-service-instance-guid",
    27  						"app_guid":              "some-app-guid",
    28  						"name":                  "some-binding-name",
    29  						"parameters": map[string]interface{}{
    30  							"the-service-broker": "wants this object",
    31  						},
    32  					}
    33  					response := `
    34  						{
    35  							"metadata": {
    36  								"guid": "some-service-binding-guid"
    37  							}
    38  						}`
    39  					server.AppendHandlers(
    40  						CombineHandlers(
    41  							VerifyRequest(http.MethodPost, "/v2/service_bindings"),
    42  							VerifyJSONRepresenting(expectedRequestBody),
    43  							RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    44  						),
    45  					)
    46  				})
    47  
    48  				It("returns the created object and warnings", func() {
    49  					parameters := map[string]interface{}{
    50  						"the-service-broker": "wants this object",
    51  					}
    52  					serviceBinding, warnings, err := client.CreateServiceBinding("some-app-guid", "some-service-instance-guid", "some-binding-name", parameters)
    53  					Expect(err).NotTo(HaveOccurred())
    54  
    55  					Expect(serviceBinding).To(Equal(ServiceBinding{GUID: "some-service-binding-guid"}))
    56  					Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
    57  				})
    58  			})
    59  
    60  			Context("when a service binding name is not provided", func() {
    61  				BeforeEach(func() {
    62  					expectedRequestBody := map[string]interface{}{
    63  						"service_instance_guid": "some-service-instance-guid",
    64  						"app_guid":              "some-app-guid",
    65  						"parameters": map[string]interface{}{
    66  							"the-service-broker": "wants this object",
    67  						},
    68  					}
    69  					response := `
    70  						{
    71  							"metadata": {
    72  								"guid": "some-service-binding-guid"
    73  							}
    74  						}`
    75  					server.AppendHandlers(
    76  						CombineHandlers(
    77  							VerifyRequest(http.MethodPost, "/v2/service_bindings"),
    78  							VerifyJSONRepresenting(expectedRequestBody),
    79  							RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    80  						),
    81  					)
    82  				})
    83  
    84  				It("returns the created object and warnings", func() {
    85  					parameters := map[string]interface{}{
    86  						"the-service-broker": "wants this object",
    87  					}
    88  					serviceBinding, warnings, err := client.CreateServiceBinding("some-app-guid", "some-service-instance-guid", "", parameters)
    89  					Expect(err).NotTo(HaveOccurred())
    90  
    91  					Expect(serviceBinding).To(Equal(ServiceBinding{GUID: "some-service-binding-guid"}))
    92  					Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
    93  				})
    94  			})
    95  		})
    96  
    97  		Context("when the create returns an error", func() {
    98  			BeforeEach(func() {
    99  				response := `
   100  				{
   101  					  "description": "The app space binding to service is taken: some-app-guid some-service-instance-guid",
   102  						  "error_code": "CF-ServiceBindingAppServiceTaken",
   103  							  "code": 90003
   104  							}
   105  			`
   106  				server.AppendHandlers(
   107  					CombineHandlers(
   108  						VerifyRequest(http.MethodPost, "/v2/service_bindings"),
   109  						RespondWith(http.StatusBadRequest, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   110  					),
   111  				)
   112  			})
   113  
   114  			It("returns the error and warnings", func() {
   115  				parameters := map[string]interface{}{
   116  					"the-service-broker": "wants this object",
   117  				}
   118  				_, warnings, err := client.CreateServiceBinding("some-app-guid", "some-service-instance-guid", "", parameters)
   119  				Expect(err).To(MatchError(ccerror.ServiceBindingTakenError{Message: "The app space binding to service is taken: some-app-guid some-service-instance-guid"}))
   120  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   121  			})
   122  		})
   123  	})
   124  
   125  	Describe("DeleteServiceBinding", func() {
   126  		Context("when the service binding exist", func() {
   127  			BeforeEach(func() {
   128  				server.AppendHandlers(CombineHandlers(VerifyRequest(http.MethodDelete, "/v2/service_bindings/some-service-binding-guid"), RespondWith(http.StatusNoContent, "{}", http.Header{"X-Cf-Warnings": {"this is a warning"}})))
   129  			})
   130  
   131  			It("deletes the service binding", func() {
   132  				warnings, err := client.DeleteServiceBinding("some-service-binding-guid")
   133  				Expect(err).NotTo(HaveOccurred())
   134  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   135  			})
   136  		})
   137  
   138  		Context("when the service binding does not exist", func() {
   139  			BeforeEach(func() {
   140  				response := `{
   141  				"code": 90004,
   142  				"description": "The service binding could not be found: some-service-binding-guid",
   143  				"error_code": "CF-ServiceBindingNotFound"
   144  			}`
   145  				server.AppendHandlers(
   146  					CombineHandlers(
   147  						VerifyRequest(http.MethodDelete, "/v2/service_bindings/some-service-binding-guid"),
   148  						RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   149  					),
   150  				)
   151  			})
   152  
   153  			It("returns a not found error", func() {
   154  				warnings, err := client.DeleteServiceBinding("some-service-binding-guid")
   155  				Expect(err).To(MatchError(ccerror.ResourceNotFoundError{
   156  					Message: "The service binding could not be found: some-service-binding-guid",
   157  				}))
   158  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   159  			})
   160  		})
   161  	})
   162  
   163  	Describe("GetServiceBinding", func() {
   164  		var (
   165  			serviceBinding ServiceBinding
   166  			warnings       Warnings
   167  			executeErr     error
   168  		)
   169  
   170  		JustBeforeEach(func() {
   171  			serviceBinding, warnings, executeErr = client.GetServiceBinding("some-service-binding-guid")
   172  		})
   173  
   174  		Context("when the cc returns an error", func() {
   175  			BeforeEach(func() {
   176  				response := `{
   177  					"code": 1,
   178  					"description": "some error description",
   179  					"error_code": "CF-SomeError"
   180  				}`
   181  				server.AppendHandlers(
   182  					CombineHandlers(
   183  						VerifyRequest(http.MethodGet, "/v2/service_bindings/some-service-binding-guid"),
   184  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}}),
   185  					),
   186  				)
   187  			})
   188  
   189  			It("returns the error", func() {
   190  				Expect(executeErr).To(MatchError(ccerror.V2UnexpectedResponseError{
   191  					V2ErrorResponse: ccerror.V2ErrorResponse{
   192  						Code:        1,
   193  						Description: "some error description",
   194  						ErrorCode:   "CF-SomeError",
   195  					},
   196  					ResponseCode: http.StatusTeapot,
   197  				}))
   198  
   199  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   200  			})
   201  		})
   202  
   203  		Context("when there are no errors", func() {
   204  			BeforeEach(func() {
   205  				response := `{
   206  						"metadata": {
   207  							"guid": "service-binding-guid-1"
   208  						},
   209  						"entity": {
   210  							"app_guid":"app-guid-1",
   211  							"service_instance_guid": "service-instance-guid-1"
   212  						}
   213  					}`
   214  				server.AppendHandlers(
   215  					CombineHandlers(
   216  						VerifyRequest(http.MethodGet, "/v2/service_bindings/some-service-binding-guid"),
   217  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}}),
   218  					),
   219  				)
   220  			})
   221  
   222  			It("returns the service binding", func() {
   223  				Expect(executeErr).ToNot(HaveOccurred())
   224  				Expect(warnings).To(ConsistOf("warning-1", "warning-2"))
   225  
   226  				Expect(serviceBinding).To(Equal(ServiceBinding{
   227  					GUID:                "service-binding-guid-1",
   228  					AppGUID:             "app-guid-1",
   229  					ServiceInstanceGUID: "service-instance-guid-1",
   230  				}))
   231  			})
   232  		})
   233  	})
   234  
   235  	Describe("GetServiceBindings", func() {
   236  		BeforeEach(func() {
   237  			response1 := `{
   238  				"next_url": "/v2/service_bindings?q=app_guid:some-app-guid&page=2",
   239  				"resources": [
   240  					{
   241  						"metadata": {
   242  							"guid": "service-binding-guid-1"
   243  						},
   244  						"entity": {
   245  							"app_guid":"app-guid-1",
   246  							"service_instance_guid": "service-instance-guid-1"
   247  						}
   248  					},
   249  					{
   250  						"metadata": {
   251  							"guid": "service-binding-guid-2"
   252  						},
   253  						"entity": {
   254  							"app_guid":"app-guid-2",
   255  							"service_instance_guid": "service-instance-guid-2"
   256  						}
   257  					}
   258  				]
   259  			}`
   260  			response2 := `{
   261  				"next_url": null,
   262  				"resources": [
   263  					{
   264  						"metadata": {
   265  							"guid": "service-binding-guid-3"
   266  						},
   267  						"entity": {
   268  							"app_guid":"app-guid-3",
   269  							"service_instance_guid": "service-instance-guid-3"
   270  						}
   271  					},
   272  					{
   273  						"metadata": {
   274  							"guid": "service-binding-guid-4"
   275  						},
   276  						"entity": {
   277  							"app_guid":"app-guid-4",
   278  							"service_instance_guid": "service-instance-guid-4"
   279  						}
   280  					}
   281  				]
   282  			}`
   283  			server.AppendHandlers(
   284  				CombineHandlers(
   285  					VerifyRequest(http.MethodGet, "/v2/service_bindings", "q=app_guid:some-app-guid"),
   286  					RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   287  				),
   288  			)
   289  			server.AppendHandlers(
   290  				CombineHandlers(
   291  					VerifyRequest(http.MethodGet, "/v2/service_bindings", "q=app_guid:some-app-guid&page=2"),
   292  					RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   293  				),
   294  			)
   295  		})
   296  
   297  		Context("when service bindings exist", func() {
   298  			It("returns all the queried service bindings", func() {
   299  				serviceBindings, warnings, err := client.GetServiceBindings(Filter{
   300  					Type:     constant.AppGUIDFilter,
   301  					Operator: constant.EqualOperator,
   302  					Values:   []string{"some-app-guid"},
   303  				})
   304  				Expect(err).NotTo(HaveOccurred())
   305  				Expect(serviceBindings).To(ConsistOf([]ServiceBinding{
   306  					{GUID: "service-binding-guid-1", AppGUID: "app-guid-1", ServiceInstanceGUID: "service-instance-guid-1"},
   307  					{GUID: "service-binding-guid-2", AppGUID: "app-guid-2", ServiceInstanceGUID: "service-instance-guid-2"},
   308  					{GUID: "service-binding-guid-3", AppGUID: "app-guid-3", ServiceInstanceGUID: "service-instance-guid-3"},
   309  					{GUID: "service-binding-guid-4", AppGUID: "app-guid-4", ServiceInstanceGUID: "service-instance-guid-4"},
   310  				}))
   311  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"}))
   312  			})
   313  		})
   314  	})
   315  
   316  	Describe("GetServiceInstanceServiceBindings", func() {
   317  		Context("when there are service bindings", func() {
   318  			BeforeEach(func() {
   319  				response1 := `{
   320  					"next_url": "/v2/service_instances/some-service-instance-guid/service_bindings?page=2",
   321  					"resources": [
   322  						{
   323  							"metadata": {
   324  								"guid": "service-binding-guid-1"
   325  							},
   326  							"entity": {
   327  								"app_guid":"app-guid-1",
   328  								"service_instance_guid": "service-instance-guid-1"
   329  							}
   330  						},
   331  						{
   332  							"metadata": {
   333  								"guid": "service-binding-guid-2"
   334  							},
   335  							"entity": {
   336  								"app_guid":"app-guid-2",
   337  								"service_instance_guid": "service-instance-guid-2"
   338  							}
   339  						}
   340  					]
   341  				}`
   342  				response2 := `{
   343  					"next_url": null,
   344  					"resources": [
   345  						{
   346  							"metadata": {
   347  								"guid": "service-binding-guid-3"
   348  							},
   349  							"entity": {
   350  								"app_guid":"app-guid-3",
   351  								"service_instance_guid": "service-instance-guid-3"
   352  							}
   353  						},
   354  						{
   355  							"metadata": {
   356  								"guid": "service-binding-guid-4"
   357  							},
   358  							"entity": {
   359  								"app_guid":"app-guid-4",
   360  								"service_instance_guid": "service-instance-guid-4"
   361  							}
   362  						}
   363  					]
   364  				}`
   365  				server.AppendHandlers(
   366  					CombineHandlers(
   367  						VerifyRequest(http.MethodGet, "/v2/service_instances/some-service-instance-guid/service_bindings"),
   368  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   369  					),
   370  				)
   371  				server.AppendHandlers(
   372  					CombineHandlers(
   373  						VerifyRequest(http.MethodGet, "/v2/service_instances/some-service-instance-guid/service_bindings", "page=2"),
   374  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   375  					),
   376  				)
   377  			})
   378  
   379  			It("returns all the service bindings and all warnings", func() {
   380  				serviceBindings, warnings, err := client.GetServiceInstanceServiceBindings("some-service-instance-guid")
   381  				Expect(err).NotTo(HaveOccurred())
   382  				Expect(serviceBindings).To(Equal([]ServiceBinding{
   383  					{GUID: "service-binding-guid-1", AppGUID: "app-guid-1", ServiceInstanceGUID: "service-instance-guid-1"},
   384  					{GUID: "service-binding-guid-2", AppGUID: "app-guid-2", ServiceInstanceGUID: "service-instance-guid-2"},
   385  					{GUID: "service-binding-guid-3", AppGUID: "app-guid-3", ServiceInstanceGUID: "service-instance-guid-3"},
   386  					{GUID: "service-binding-guid-4", AppGUID: "app-guid-4", ServiceInstanceGUID: "service-instance-guid-4"},
   387  				}))
   388  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"}))
   389  			})
   390  		})
   391  
   392  		Context("when there are no service bindings", func() {
   393  			BeforeEach(func() {
   394  				response1 := `{
   395  					"next_url": null,
   396  					"resources": []
   397  				}`
   398  				server.AppendHandlers(
   399  					CombineHandlers(
   400  						VerifyRequest(http.MethodGet, "/v2/service_instances/some-service-instance-guid/service_bindings"),
   401  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   402  					),
   403  				)
   404  			})
   405  			It("returns an empty list of service bindings and all warnings", func() {
   406  				serviceBindings, warnings, err := client.GetServiceInstanceServiceBindings("some-service-instance-guid")
   407  				Expect(err).NotTo(HaveOccurred())
   408  				Expect(serviceBindings).To(HaveLen(0))
   409  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   410  			})
   411  		})
   412  
   413  		Context("when an error is encountered", func() {
   414  			BeforeEach(func() {
   415  				response := `{
   416  				 "description": "Unknown request",
   417  				 "error_code": "CF-NotFound",
   418  				 "code": 10000
   419  				}`
   420  				server.AppendHandlers(
   421  					CombineHandlers(
   422  						VerifyRequest(http.MethodGet, "/v2/service_instances/some-service-instance-guid/service_bindings"),
   423  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   424  					),
   425  				)
   426  			})
   427  
   428  			It("returns an error and all warnings", func() {
   429  				_, warnings, err := client.GetServiceInstanceServiceBindings("some-service-instance-guid")
   430  				Expect(err).To(MatchError(ccerror.V2UnexpectedResponseError{
   431  					V2ErrorResponse: ccerror.V2ErrorResponse{
   432  						Code:        10000,
   433  						Description: "Unknown request",
   434  						ErrorCode:   "CF-NotFound",
   435  					},
   436  					RequestIDs:   nil,
   437  					ResponseCode: 418,
   438  				}))
   439  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   440  			})
   441  		})
   442  	})
   443  
   444  	Describe("GetUserProvidedServiceInstanceServiceBindings", func() {
   445  		Context("when there are service bindings", func() {
   446  			BeforeEach(func() {
   447  				response1 := `{
   448  					"next_url": "/v2/user_provided_service_instances/some-user-provided-service-instance-guid/service_bindings?page=2",
   449  					"resources": [
   450  						{
   451  							"metadata": {
   452  								"guid": "service-binding-guid-1"
   453  							},
   454  							"entity": {
   455  								"app_guid":"app-guid-1",
   456  								"service_instance_guid": "user-provided-service-instance-guid-1"
   457  							}
   458  						},
   459  						{
   460  							"metadata": {
   461  								"guid": "service-binding-guid-2"
   462  							},
   463  							"entity": {
   464  								"app_guid":"app-guid-2",
   465  								"service_instance_guid": "user-provided-service-instance-guid-2"
   466  							}
   467  						}
   468  					]
   469  				}`
   470  				response2 := `{
   471  					"next_url": null,
   472  					"resources": [
   473  						{
   474  							"metadata": {
   475  								"guid": "service-binding-guid-3"
   476  							},
   477  							"entity": {
   478  								"app_guid":"app-guid-3",
   479  								"service_instance_guid": "user-provided-service-instance-guid-3"
   480  							}
   481  						},
   482  						{
   483  							"metadata": {
   484  								"guid": "service-binding-guid-4"
   485  							},
   486  							"entity": {
   487  								"app_guid":"app-guid-4",
   488  								"service_instance_guid": "user-provided-service-instance-guid-4"
   489  							}
   490  						}
   491  					]
   492  				}`
   493  				server.AppendHandlers(
   494  					CombineHandlers(
   495  						VerifyRequest(http.MethodGet, "/v2/user_provided_service_instances/some-user-provided-service-instance-guid/service_bindings"),
   496  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   497  					),
   498  				)
   499  				server.AppendHandlers(
   500  					CombineHandlers(
   501  						VerifyRequest(http.MethodGet, "/v2/user_provided_service_instances/some-user-provided-service-instance-guid/service_bindings", "page=2"),
   502  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   503  					),
   504  				)
   505  			})
   506  
   507  			It("returns all the service bindings and all warnings", func() {
   508  				serviceBindings, warnings, err := client.GetUserProvidedServiceInstanceServiceBindings("some-user-provided-service-instance-guid")
   509  				Expect(err).NotTo(HaveOccurred())
   510  				Expect(serviceBindings).To(Equal([]ServiceBinding{
   511  					{GUID: "service-binding-guid-1", AppGUID: "app-guid-1", ServiceInstanceGUID: "user-provided-service-instance-guid-1"},
   512  					{GUID: "service-binding-guid-2", AppGUID: "app-guid-2", ServiceInstanceGUID: "user-provided-service-instance-guid-2"},
   513  					{GUID: "service-binding-guid-3", AppGUID: "app-guid-3", ServiceInstanceGUID: "user-provided-service-instance-guid-3"},
   514  					{GUID: "service-binding-guid-4", AppGUID: "app-guid-4", ServiceInstanceGUID: "user-provided-service-instance-guid-4"},
   515  				}))
   516  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"}))
   517  			})
   518  		})
   519  
   520  		Context("when there are no service bindings", func() {
   521  			BeforeEach(func() {
   522  				response := `{
   523  					"next_url": null,
   524  					"resources": []
   525  				}`
   526  				server.AppendHandlers(
   527  					CombineHandlers(
   528  						VerifyRequest(http.MethodGet, "/v2/user_provided_service_instances/some-user-provided-service-instance-guid/service_bindings"),
   529  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   530  					),
   531  				)
   532  			})
   533  
   534  			It("returns an empty list of service bindings and all warnings", func() {
   535  				serviceBindings, warnings, err := client.GetUserProvidedServiceInstanceServiceBindings("some-user-provided-service-instance-guid")
   536  				Expect(err).NotTo(HaveOccurred())
   537  				Expect(serviceBindings).To(HaveLen(0))
   538  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   539  			})
   540  		})
   541  
   542  		Context("when an error is encountered", func() {
   543  			BeforeEach(func() {
   544  				response := `{
   545  				 "description": "Unknown request",
   546  				 "error_code": "CF-NotFound",
   547  				 "code": 10000
   548  				}`
   549  				server.AppendHandlers(
   550  					CombineHandlers(
   551  						VerifyRequest(http.MethodGet, "/v2/user_provided_service_instances/some-user-provided-service-instance-guid/service_bindings"),
   552  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   553  					),
   554  				)
   555  			})
   556  
   557  			It("returns an error and all warnings", func() {
   558  				_, warnings, err := client.GetUserProvidedServiceInstanceServiceBindings("some-user-provided-service-instance-guid")
   559  				Expect(err).To(MatchError(ccerror.V2UnexpectedResponseError{
   560  					V2ErrorResponse: ccerror.V2ErrorResponse{
   561  						Code:        10000,
   562  						Description: "Unknown request",
   563  						ErrorCode:   "CF-NotFound",
   564  					},
   565  					RequestIDs:   nil,
   566  					ResponseCode: 418,
   567  				}))
   568  				Expect(warnings).To(ConsistOf(Warnings{"this is a warning"}))
   569  			})
   570  		})
   571  	})
   572  })