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