github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/api/spaces/spaces_test.go (about) 1 package spaces_test 2 3 import ( 4 "fmt" 5 "net/http" 6 "net/http/httptest" 7 "time" 8 9 "code.cloudfoundry.org/cli/cf/api/apifakes" 10 "code.cloudfoundry.org/cli/cf/errors" 11 "code.cloudfoundry.org/cli/cf/models" 12 "code.cloudfoundry.org/cli/cf/net" 13 "code.cloudfoundry.org/cli/cf/terminal/terminalfakes" 14 "code.cloudfoundry.org/cli/cf/trace/tracefakes" 15 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 16 testnet "code.cloudfoundry.org/cli/util/testhelpers/net" 17 18 . "code.cloudfoundry.org/cli/cf/api/spaces" 19 . "code.cloudfoundry.org/cli/util/testhelpers/matchers" 20 . "github.com/onsi/ginkgo" 21 . "github.com/onsi/gomega" 22 "github.com/onsi/gomega/ghttp" 23 ) 24 25 var _ = Describe("Space Repository", func() { 26 Describe("ListSpaces", func() { 27 var ( 28 ccServer *ghttp.Server 29 repo CloudControllerSpaceRepository 30 ) 31 32 BeforeEach(func() { 33 ccServer = ghttp.NewServer() 34 configRepo := testconfig.NewRepositoryWithDefaults() 35 configRepo.SetAPIEndpoint(ccServer.URL()) 36 gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 37 repo = NewCloudControllerSpaceRepository(configRepo, gateway) 38 ccServer.AppendHandlers( 39 ghttp.CombineHandlers( 40 ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&inline-relations-depth=1"), 41 ghttp.VerifyHeader(http.Header{ 42 "accept": []string{"application/json"}, 43 }), 44 ghttp.RespondWith(http.StatusOK, `{ 45 "total_results": 3, 46 "total_pages": 2, 47 "prev_url": null, 48 "next_url": "/v2/organizations/my-org-guid/spaces?order-by=name&page=2&inline-relations-depth=1", 49 "resources": [ 50 { 51 "metadata": { "guid": "space3-guid" }, 52 "entity": { 53 "name": "Alpha", 54 "allow_ssh": true, 55 "security_groups": [ 56 { 57 "metadata": { "guid": "4302b3b4-4afc-4f12-ae6d-ed1bb815551f" }, 58 "entity": { "name": "imma-security-group" } 59 } 60 ] 61 } 62 }, 63 { 64 "metadata": { "guid": "space2-guid" }, 65 "entity": { "name": "Beta" } 66 } 67 ] 68 }`), 69 ), 70 ) 71 72 ccServer.AppendHandlers( 73 ghttp.CombineHandlers( 74 ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&page=2&inline-relations-depth=1"), 75 ghttp.VerifyHeader(http.Header{ 76 "accept": []string{"application/json"}, 77 }), 78 ghttp.RespondWith(http.StatusOK, `{ 79 "total_results": 3, 80 "total_pages": 2, 81 "prev_url": null, 82 "next_url": null, 83 "resources": [ 84 { 85 "metadata": { "guid": "space1-guid" }, 86 "entity": { "name": "Gamma" } 87 } 88 ] 89 }`), 90 ), 91 ) 92 }) 93 94 AfterEach(func() { 95 ccServer.Close() 96 }) 97 98 It("lists all the spaces", func() { 99 spaces := []models.Space{} 100 apiErr := repo.ListSpaces(func(space models.Space) bool { 101 spaces = append(spaces, space) 102 return true 103 }) 104 105 Expect(apiErr).NotTo(HaveOccurred()) 106 Expect(len(spaces)).To(Equal(3)) 107 Expect(spaces[0].GUID).To(Equal("space3-guid")) 108 Expect(spaces[0].AllowSSH).To(BeTrue()) 109 Expect(spaces[0].SecurityGroups[0].Name).To(Equal("imma-security-group")) 110 Expect(spaces[0].Name).To(Equal("Alpha")) 111 112 Expect(spaces[1].GUID).To(Equal("space2-guid")) 113 Expect(spaces[1].Name).To(Equal("Beta")) 114 115 Expect(spaces[2].GUID).To(Equal("space1-guid")) 116 Expect(spaces[2].Name).To(Equal("Gamma")) 117 }) 118 }) 119 120 Describe("ListSpacesFromOrg", func() { 121 var ( 122 ccServer *ghttp.Server 123 repo CloudControllerSpaceRepository 124 ) 125 126 BeforeEach(func() { 127 ccServer = ghttp.NewServer() 128 configRepo := testconfig.NewRepositoryWithDefaults() 129 configRepo.SetAPIEndpoint(ccServer.URL()) 130 configRepo.SetOrganizationFields(models.OrganizationFields{}) 131 gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 132 repo = NewCloudControllerSpaceRepository(configRepo, gateway) 133 ccServer.AppendHandlers( 134 ghttp.CombineHandlers( 135 ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&inline-relations-depth=1"), 136 ghttp.VerifyHeader(http.Header{ 137 "accept": []string{"application/json"}, 138 }), 139 ghttp.RespondWith(http.StatusOK, `{ 140 "total_results": 3, 141 "total_pages": 2, 142 "prev_url": null, 143 "next_url": "/v2/organizations/my-org-guid/spaces?order-by=name&page=2&inline-relations-depth=1", 144 "resources": [ 145 { 146 "metadata": { "guid": "space3-guid" }, 147 "entity": { 148 "name": "Alpha", 149 "allow_ssh": true, 150 "security_groups": [ 151 { 152 "metadata": { "guid": "4302b3b4-4afc-4f12-ae6d-ed1bb815551f" }, 153 "entity": { "name": "imma-security-group" } 154 } 155 ] 156 } 157 }, 158 { 159 "metadata": { "guid": "space2-guid" }, 160 "entity": { "name": "Beta" } 161 } 162 ] 163 }`), 164 ), 165 ) 166 167 ccServer.AppendHandlers( 168 ghttp.CombineHandlers( 169 ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&page=2&inline-relations-depth=1"), 170 ghttp.VerifyHeader(http.Header{ 171 "accept": []string{"application/json"}, 172 }), 173 ghttp.RespondWith(http.StatusOK, `{ 174 "total_results": 3, 175 "total_pages": 2, 176 "prev_url": null, 177 "next_url": null, 178 "resources": [ 179 { 180 "metadata": { "guid": "space1-guid" }, 181 "entity": { "name": "Gamma" } 182 } 183 ] 184 }`), 185 ), 186 ) 187 }) 188 189 AfterEach(func() { 190 ccServer.Close() 191 }) 192 193 It("lists all the spaces", func() { 194 spaces := []models.Space{} 195 apiErr := repo.ListSpacesFromOrg("my-org-guid", func(space models.Space) bool { 196 spaces = append(spaces, space) 197 return true 198 }) 199 200 Expect(apiErr).NotTo(HaveOccurred()) 201 Expect(len(spaces)).To(Equal(3)) 202 Expect(spaces[0].GUID).To(Equal("space3-guid")) 203 Expect(spaces[0].AllowSSH).To(BeTrue()) 204 Expect(spaces[0].SecurityGroups[0].Name).To(Equal("imma-security-group")) 205 Expect(spaces[0].Name).To(Equal("Alpha")) 206 207 Expect(spaces[1].GUID).To(Equal("space2-guid")) 208 Expect(spaces[1].Name).To(Equal("Beta")) 209 210 Expect(spaces[2].GUID).To(Equal("space1-guid")) 211 Expect(spaces[2].Name).To(Equal("Gamma")) 212 }) 213 }) 214 215 Describe("finding spaces by name", func() { 216 It("returns the space", func() { 217 testSpacesFindByNameWithOrg("my-org-guid", 218 func(repo SpaceRepository, spaceName string) (models.Space, error) { 219 return repo.FindByName(spaceName) 220 }, 221 ) 222 }) 223 224 It("can find spaces in a particular org", func() { 225 testSpacesFindByNameWithOrg("another-org-guid", 226 func(repo SpaceRepository, spaceName string) (models.Space, error) { 227 return repo.FindByNameInOrg(spaceName, "another-org-guid") 228 }, 229 ) 230 }) 231 232 It("returns a 'not found' response when the space doesn't exist", func() { 233 testSpacesDidNotFindByNameWithOrg("my-org-guid", 234 func(repo SpaceRepository, spaceName string) (models.Space, error) { 235 return repo.FindByName(spaceName) 236 }, 237 ) 238 }) 239 240 It("returns a 'not found' response when the space doesn't exist in the given org", func() { 241 testSpacesDidNotFindByNameWithOrg("another-org-guid", 242 func(repo SpaceRepository, spaceName string) (models.Space, error) { 243 return repo.FindByNameInOrg(spaceName, "another-org-guid") 244 }, 245 ) 246 }) 247 }) 248 249 It("creates spaces without a space-quota", func() { 250 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 251 Method: "POST", 252 Path: "/v2/spaces", 253 Matcher: testnet.RequestBodyMatcher(`{"name":"space-name","organization_guid":"my-org-guid"}`), 254 Response: testnet.TestResponse{Status: http.StatusCreated, Body: ` 255 { 256 "metadata": { 257 "guid": "space-guid" 258 }, 259 "entity": { 260 "name": "space-name" 261 } 262 }`}, 263 }) 264 265 ts, handler, repo := createSpacesRepo(request) 266 defer ts.Close() 267 268 space, apiErr := repo.Create("space-name", "my-org-guid", "") 269 Expect(handler).To(HaveAllRequestsCalled()) 270 Expect(apiErr).NotTo(HaveOccurred()) 271 Expect(space.GUID).To(Equal("space-guid")) 272 Expect(space.SpaceQuotaGUID).To(Equal("")) 273 }) 274 275 It("creates spaces with a space-quota", func() { 276 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 277 Method: "POST", 278 Path: "/v2/spaces", 279 Matcher: testnet.RequestBodyMatcher(`{"name":"space-name","organization_guid":"my-org-guid","space_quota_definition_guid":"space-quota-guid"}`), 280 Response: testnet.TestResponse{Status: http.StatusCreated, Body: ` 281 { 282 "metadata": { 283 "guid": "space-guid" 284 }, 285 "entity": { 286 "name": "space-name", 287 "space_quota_definition_guid":"space-quota-guid" 288 } 289 }`}, 290 }) 291 292 ts, handler, repo := createSpacesRepo(request) 293 defer ts.Close() 294 295 space, apiErr := repo.Create("space-name", "my-org-guid", "space-quota-guid") 296 Expect(handler).To(HaveAllRequestsCalled()) 297 Expect(apiErr).NotTo(HaveOccurred()) 298 Expect(space.GUID).To(Equal("space-guid")) 299 Expect(space.SpaceQuotaGUID).To(Equal("space-quota-guid")) 300 }) 301 302 It("sets allow_ssh field", func() { 303 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 304 Method: "PUT", 305 Path: "/v2/spaces/my-space-guid", 306 Matcher: testnet.RequestBodyMatcher(`{"allow_ssh":true}`), 307 Response: testnet.TestResponse{Status: http.StatusCreated}, 308 }) 309 310 ts, handler, repo := createSpacesRepo(request) 311 defer ts.Close() 312 313 apiErr := repo.SetAllowSSH("my-space-guid", true) 314 Expect(handler).To(HaveAllRequestsCalled()) 315 Expect(apiErr).NotTo(HaveOccurred()) 316 }) 317 318 It("renames spaces", func() { 319 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 320 Method: "PUT", 321 Path: "/v2/spaces/my-space-guid", 322 Matcher: testnet.RequestBodyMatcher(`{"name":"new-space-name"}`), 323 Response: testnet.TestResponse{Status: http.StatusCreated}, 324 }) 325 326 ts, handler, repo := createSpacesRepo(request) 327 defer ts.Close() 328 329 apiErr := repo.Rename("my-space-guid", "new-space-name") 330 Expect(handler).To(HaveAllRequestsCalled()) 331 Expect(apiErr).NotTo(HaveOccurred()) 332 }) 333 334 It("deletes spaces", func() { 335 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 336 Method: "DELETE", 337 Path: "/v2/spaces/my-space-guid?recursive=true", 338 Response: testnet.TestResponse{Status: http.StatusOK}, 339 }) 340 341 ts, handler, repo := createSpacesRepo(request) 342 defer ts.Close() 343 344 apiErr := repo.Delete("my-space-guid") 345 Expect(handler).To(HaveAllRequestsCalled()) 346 Expect(apiErr).NotTo(HaveOccurred()) 347 }) 348 }) 349 350 func testSpacesFindByNameWithOrg(orgGUID string, findByName func(SpaceRepository, string) (models.Space, error)) { 351 findSpaceByNameResponse := testnet.TestResponse{ 352 Status: http.StatusOK, 353 Body: ` 354 { 355 "resources": [ 356 { 357 "metadata": { 358 "guid": "space1-guid" 359 }, 360 "entity": { 361 "name": "Space1", 362 "organization_guid": "org1-guid", 363 "organization": { 364 "metadata": { 365 "guid": "org1-guid" 366 }, 367 "entity": { 368 "name": "Org1" 369 } 370 }, 371 "apps": [ 372 { 373 "metadata": { 374 "guid": "app1-guid" 375 }, 376 "entity": { 377 "name": "app1" 378 } 379 }, 380 { 381 "metadata": { 382 "guid": "app2-guid" 383 }, 384 "entity": { 385 "name": "app2" 386 } 387 } 388 ], 389 "domains": [ 390 { 391 "metadata": { 392 "guid": "domain1-guid" 393 }, 394 "entity": { 395 "name": "domain1" 396 } 397 } 398 ], 399 "service_instances": [ 400 { 401 "metadata": { 402 "guid": "service1-guid" 403 }, 404 "entity": { 405 "name": "service1" 406 } 407 } 408 ] 409 } 410 } 411 ] 412 }`} 413 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 414 Method: "GET", 415 Path: fmt.Sprintf("/v2/organizations/%s/spaces?q=name%%3Aspace1", orgGUID), 416 Response: findSpaceByNameResponse, 417 }) 418 419 ts, handler, repo := createSpacesRepo(request) 420 defer ts.Close() 421 422 space, apiErr := findByName(repo, "Space1") 423 Expect(handler).To(HaveAllRequestsCalled()) 424 Expect(apiErr).NotTo(HaveOccurred()) 425 Expect(space.Name).To(Equal("Space1")) 426 Expect(space.GUID).To(Equal("space1-guid")) 427 428 Expect(space.Organization.GUID).To(Equal("org1-guid")) 429 430 Expect(len(space.Applications)).To(Equal(2)) 431 Expect(space.Applications[0].GUID).To(Equal("app1-guid")) 432 Expect(space.Applications[1].GUID).To(Equal("app2-guid")) 433 434 Expect(len(space.Domains)).To(Equal(1)) 435 Expect(space.Domains[0].GUID).To(Equal("domain1-guid")) 436 437 Expect(len(space.ServiceInstances)).To(Equal(1)) 438 Expect(space.ServiceInstances[0].GUID).To(Equal("service1-guid")) 439 440 Expect(apiErr).NotTo(HaveOccurred()) 441 return 442 } 443 444 func testSpacesDidNotFindByNameWithOrg(orgGUID string, findByName func(SpaceRepository, string) (models.Space, error)) { 445 request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{ 446 Method: "GET", 447 Path: fmt.Sprintf("/v2/organizations/%s/spaces?q=name%%3Aspace1", orgGUID), 448 Response: testnet.TestResponse{ 449 Status: http.StatusOK, 450 Body: ` { "resources": [ ] }`, 451 }, 452 }) 453 454 ts, handler, repo := createSpacesRepo(request) 455 defer ts.Close() 456 457 _, apiErr := findByName(repo, "Space1") 458 Expect(handler).To(HaveAllRequestsCalled()) 459 460 Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil()) 461 } 462 463 func createSpacesRepo(reqs ...testnet.TestRequest) (ts *httptest.Server, handler *testnet.TestHandler, repo SpaceRepository) { 464 ts, handler = testnet.NewServer(reqs) 465 configRepo := testconfig.NewRepositoryWithDefaults() 466 configRepo.SetAPIEndpoint(ts.URL) 467 gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "") 468 repo = NewCloudControllerSpaceRepository(configRepo, gateway) 469 return 470 }