github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/api/service_keys_test.go (about) 1 package api_test 2 3 import ( 4 "net/http" 5 "time" 6 7 "code.cloudfoundry.org/cli/cf/terminal/terminalfakes" 8 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 9 testnet "code.cloudfoundry.org/cli/util/testhelpers/net" 10 "github.com/onsi/gomega/ghttp" 11 12 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 13 "code.cloudfoundry.org/cli/cf/errors" 14 "code.cloudfoundry.org/cli/cf/models" 15 "code.cloudfoundry.org/cli/cf/net" 16 17 . "code.cloudfoundry.org/cli/cf/api" 18 19 "code.cloudfoundry.org/cli/cf/trace/tracefakes" 20 . "github.com/onsi/ginkgo" 21 . "github.com/onsi/gomega" 22 ) 23 24 var _ = Describe("Service Keys Repo", func() { 25 var ( 26 ccServer *ghttp.Server 27 configRepo coreconfig.ReadWriter 28 repo ServiceKeyRepository 29 ) 30 31 BeforeEach(func() { 32 configRepo = testconfig.NewRepositoryWithDefaults() 33 configRepo.SetAccessToken("BEARER my_access_token") 34 35 ccServer = ghttp.NewServer() 36 configRepo.SetAPIEndpoint(ccServer.URL()) 37 38 gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 39 repo = NewCloudControllerServiceKeyRepository(configRepo, gateway) 40 }) 41 42 AfterEach(func() { 43 ccServer.Close() 44 }) 45 46 Describe("CreateServiceKey", func() { 47 It("tries to create the service key", func() { 48 ccServer.AppendHandlers( 49 ghttp.CombineHandlers( 50 ghttp.VerifyRequest("POST", "/v2/service_keys"), 51 ghttp.RespondWith(http.StatusCreated, nil), 52 ghttp.VerifyJSON(`{"service_instance_guid": "fake-instance-guid", "name": "fake-key-name"}`), 53 ), 54 ) 55 56 err := repo.CreateServiceKey("fake-instance-guid", "fake-key-name", nil) 57 Expect(err).NotTo(HaveOccurred()) 58 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 59 }) 60 61 Context("when the service key exists", func() { 62 BeforeEach(func() { 63 ccServer.AppendHandlers( 64 ghttp.CombineHandlers( 65 ghttp.VerifyRequest("POST", "/v2/service_keys"), 66 ghttp.RespondWith(http.StatusBadRequest, `{"code":360001,"description":"The service key name is taken: exist-service-key"}`), 67 ), 68 ) 69 }) 70 71 It("returns a ModelAlreadyExistsError", func() { 72 err := repo.CreateServiceKey("fake-instance-guid", "exist-service-key", nil) 73 Expect(err).To(BeAssignableToTypeOf(&errors.ModelAlreadyExistsError{})) 74 }) 75 }) 76 77 Context("when the CLI user is not a space developer or admin", func() { 78 BeforeEach(func() { 79 ccServer.AppendHandlers( 80 ghttp.CombineHandlers( 81 ghttp.VerifyRequest("POST", "/v2/service_keys"), 82 ghttp.RespondWith(http.StatusBadRequest, `{"code":10003,"description":"You are not authorized to perform the requested action"}`), 83 ), 84 ) 85 }) 86 87 It("returns a NotAuthorizedError when CLI user is not the space developer or admin", func() { 88 err := repo.CreateServiceKey("fake-instance-guid", "fake-service-key", nil) 89 Expect(err).To(HaveOccurred()) 90 Expect(err.Error()).To(ContainSubstring("You are not authorized to perform the requested action")) 91 }) 92 }) 93 94 Context("when there are parameters", func() { 95 BeforeEach(func() { 96 ccServer.AppendHandlers( 97 ghttp.CombineHandlers( 98 ghttp.VerifyRequest("POST", "/v2/service_keys"), 99 ghttp.RespondWith(http.StatusCreated, nil), 100 ghttp.VerifyJSON(`{"service_instance_guid":"fake-instance-guid","name":"fake-service-key","parameters": {"data": "hello"}}`), 101 ), 102 ) 103 }) 104 105 It("includes any provided parameters", func() { 106 paramsMap := make(map[string]interface{}) 107 paramsMap["data"] = "hello" 108 109 err := repo.CreateServiceKey("fake-instance-guid", "fake-service-key", paramsMap) 110 Expect(err).NotTo(HaveOccurred()) 111 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 112 }) 113 114 It("returns any serialization errors", func() { 115 paramsMap := make(map[string]interface{}) 116 paramsMap["data"] = make(chan bool) 117 118 err := repo.CreateServiceKey("instance-name", "plan-guid", paramsMap) 119 Expect(err).To(MatchError("json: unsupported type: chan bool")) 120 }) 121 }) 122 }) 123 124 Describe("ListServiceKeys", func() { 125 Context("when no service key is found", func() { 126 BeforeEach(func() { 127 ccServer.AppendHandlers( 128 ghttp.CombineHandlers( 129 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"), 130 ghttp.RespondWith(http.StatusOK, `{"resources": []}`), 131 ), 132 ) 133 }) 134 135 It("returns an empty result", func() { 136 serviceKeys, err := repo.ListServiceKeys("fake-instance-guid") 137 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 138 Expect(err).NotTo(HaveOccurred()) 139 Expect(serviceKeys).To(HaveLen(0)) 140 }) 141 }) 142 143 Context("when service keys are found", func() { 144 BeforeEach(func() { 145 ccServer.AppendHandlers( 146 ghttp.CombineHandlers( 147 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"), 148 ghttp.RespondWith(http.StatusOK, serviceKeysResponse), 149 ), 150 ) 151 }) 152 153 It("returns the service keys", func() { 154 serviceKeys, err := repo.ListServiceKeys("fake-instance-guid") 155 Expect(err).NotTo(HaveOccurred()) 156 Expect(serviceKeys).To(HaveLen(2)) 157 158 Expect(serviceKeys[0].Fields.GUID).To(Equal("fake-service-key-guid-1")) 159 Expect(serviceKeys[0].Fields.URL).To(Equal("/v2/service_keys/fake-guid-1")) 160 Expect(serviceKeys[0].Fields.Name).To(Equal("fake-service-key-name-1")) 161 Expect(serviceKeys[0].Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid-1")) 162 Expect(serviceKeys[0].Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url/1")) 163 164 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("username", "fake-username-1")) 165 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("password", "fake-password-1")) 166 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("host", "fake-host-1")) 167 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("port", float64(3306))) 168 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("database", "fake-db-name-1")) 169 Expect(serviceKeys[0].Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user-1:fake-password-1@fake-host-1:3306/fake-db-name-1")) 170 171 Expect(serviceKeys[1].Fields.GUID).To(Equal("fake-service-key-guid-2")) 172 Expect(serviceKeys[1].Fields.URL).To(Equal("/v2/service_keys/fake-guid-2")) 173 Expect(serviceKeys[1].Fields.Name).To(Equal("fake-service-key-name-2")) 174 Expect(serviceKeys[1].Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid-2")) 175 Expect(serviceKeys[1].Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url/1")) 176 177 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("username", "fake-username-2")) 178 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("password", "fake-password-2")) 179 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("host", "fake-host-2")) 180 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("port", float64(3306))) 181 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("database", "fake-db-name-2")) 182 Expect(serviceKeys[1].Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user-2:fake-password-2@fake-host-2:3306/fake-db-name-2")) 183 }) 184 }) 185 186 Context("when the server responds with 403", func() { 187 BeforeEach(func() { 188 ccServer.AppendHandlers( 189 ghttp.CombineHandlers( 190 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys"), 191 ghttp.RespondWith(http.StatusForbidden, `{ 192 "code": 10003, 193 "description": "You are not authorized to perform the requested action", 194 "error_code": "CF-NotAuthorized" 195 }`), 196 ), 197 ) 198 }) 199 200 It("returns a NotAuthorizedError", func() { 201 _, err := repo.ListServiceKeys("fake-instance-guid") 202 Expect(err).To(BeAssignableToTypeOf(&errors.NotAuthorizedError{})) 203 }) 204 }) 205 }) 206 207 Describe("GetServiceKey", func() { 208 Context("when the service key is found", func() { 209 BeforeEach(func() { 210 ccServer.AppendHandlers( 211 ghttp.CombineHandlers( 212 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:fake-service-key-name"), 213 ghttp.RespondWith(http.StatusOK, serviceKeyDetailResponse), 214 ), 215 ) 216 }) 217 218 It("returns service key detail", func() { 219 serviceKey, err := repo.GetServiceKey("fake-instance-guid", "fake-service-key-name") 220 Expect(err).NotTo(HaveOccurred()) 221 222 Expect(serviceKey.Fields.GUID).To(Equal("fake-service-key-guid")) 223 Expect(serviceKey.Fields.URL).To(Equal("/v2/service_keys/fake-guid")) 224 Expect(serviceKey.Fields.Name).To(Equal("fake-service-key-name")) 225 Expect(serviceKey.Fields.ServiceInstanceGUID).To(Equal("fake-service-instance-guid")) 226 Expect(serviceKey.Fields.ServiceInstanceURL).To(Equal("http://fake/service/instance/url")) 227 228 Expect(serviceKey.Credentials).To(HaveKeyWithValue("username", "fake-username")) 229 Expect(serviceKey.Credentials).To(HaveKeyWithValue("password", "fake-password")) 230 Expect(serviceKey.Credentials).To(HaveKeyWithValue("host", "fake-host")) 231 Expect(serviceKey.Credentials).To(HaveKeyWithValue("port", float64(3306))) 232 Expect(serviceKey.Credentials).To(HaveKeyWithValue("database", "fake-db-name")) 233 Expect(serviceKey.Credentials).To(HaveKeyWithValue("uri", "mysql://fake-user:fake-password@fake-host:3306/fake-db-name")) 234 }) 235 }) 236 237 Context("when the service key is not found", func() { 238 BeforeEach(func() { 239 ccServer.AppendHandlers( 240 ghttp.CombineHandlers( 241 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:non-exist-key-name"), 242 ghttp.RespondWith(http.StatusOK, `{"resources": []}`), 243 ), 244 ) 245 }) 246 247 It("returns an empty service key", func() { 248 serviceKey, err := repo.GetServiceKey("fake-instance-guid", "non-exist-key-name") 249 Expect(err).NotTo(HaveOccurred()) 250 Expect(serviceKey).To(Equal(models.ServiceKey{})) 251 }) 252 }) 253 254 Context("when the server responds with 403", func() { 255 BeforeEach(func() { 256 ccServer.AppendHandlers( 257 ghttp.CombineHandlers( 258 ghttp.VerifyRequest("GET", "/v2/service_instances/fake-instance-guid/service_keys", "q=name:fake-service-key-name"), 259 ghttp.RespondWith(http.StatusForbidden, `{ 260 "code": 10003, 261 "description": "You are not authorized to perform the requested action", 262 "error_code": "CF-NotAuthorized" 263 }`), 264 ), 265 ) 266 }) 267 268 It("returns a NotAuthorizedError", func() { 269 _, err := repo.GetServiceKey("fake-instance-guid", "fake-service-key-name") 270 Expect(err).To(BeAssignableToTypeOf(&errors.NotAuthorizedError{})) 271 }) 272 }) 273 }) 274 275 Describe("DeleteServiceKey", func() { 276 It("deletes service key successfully", func() { 277 ccServer.AppendHandlers( 278 ghttp.VerifyRequest("DELETE", "/v2/service_keys/fake-service-key-guid"), 279 ghttp.RespondWith(http.StatusOK, nil), 280 ) 281 282 err := repo.DeleteServiceKey("fake-service-key-guid") 283 Expect(err).NotTo(HaveOccurred()) 284 Expect(ccServer.ReceivedRequests()).To(HaveLen(1)) 285 }) 286 }) 287 }) 288 289 var serviceKeysResponse = `{ 290 "resources": [ 291 { 292 "metadata": { 293 "guid": "fake-service-key-guid-1", 294 "url": "/v2/service_keys/fake-guid-1", 295 "created_at": "2015-01-13T18:52:08+00:00", 296 "updated_at": null 297 }, 298 "entity": { 299 "name": "fake-service-key-name-1", 300 "service_instance_guid":"fake-service-instance-guid-1", 301 "service_instance_url":"http://fake/service/instance/url/1", 302 "credentials": { 303 "username": "fake-username-1", 304 "password": "fake-password-1", 305 "host": "fake-host-1", 306 "port": 3306, 307 "database": "fake-db-name-1", 308 "uri": "mysql://fake-user-1:fake-password-1@fake-host-1:3306/fake-db-name-1" 309 } 310 } 311 }, 312 { 313 "metadata": { 314 "guid": "fake-service-key-guid-2", 315 "url": "/v2/service_keys/fake-guid-2", 316 "created_at": "2015-01-13T18:52:08+00:00", 317 "updated_at": null 318 }, 319 "entity": { 320 "name": "fake-service-key-name-2", 321 "service_instance_guid":"fake-service-instance-guid-2", 322 "service_instance_url":"http://fake/service/instance/url/1", 323 "credentials": { 324 "username": "fake-username-2", 325 "password": "fake-password-2", 326 "host": "fake-host-2", 327 "port": 3306, 328 "database": "fake-db-name-2", 329 "uri": "mysql://fake-user-2:fake-password-2@fake-host-2:3306/fake-db-name-2" 330 } 331 } 332 } 333 ]}` 334 335 var serviceKeyDetailResponse = `{ 336 "resources": [ 337 { 338 "metadata": { 339 "guid": "fake-service-key-guid", 340 "url": "/v2/service_keys/fake-guid", 341 "created_at": "2015-01-13T18:52:08+00:00", 342 "updated_at": null 343 }, 344 "entity": { 345 "name": "fake-service-key-name", 346 "service_instance_guid":"fake-service-instance-guid", 347 "service_instance_url":"http://fake/service/instance/url", 348 "credentials": { 349 "username": "fake-username", 350 "password": "fake-password", 351 "host": "fake-host", 352 "port": 3306, 353 "database": "fake-db-name", 354 "uri": "mysql://fake-user:fake-password@fake-host:3306/fake-db-name" 355 } 356 } 357 }] 358 }` 359 360 var notAuthorizedResponse = testnet.TestResponse{Status: http.StatusForbidden, Body: `{ 361 "code": 10003, 362 "description": "You are not authorized to perform the requested action", 363 "error_code": "CF-NotAuthorized" 364 }`, 365 }