github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/ccv3/space_test.go (about) 1 package ccv3_test 2 3 import ( 4 "fmt" 5 "net/http" 6 7 "code.cloudfoundry.org/cli/types" 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/constant" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/ghttp" 15 ) 16 17 var _ = Describe("Spaces", func() { 18 var client *Client 19 20 BeforeEach(func() { 21 client, _ = NewTestClient() 22 }) 23 24 Describe("CreateSpace", func() { 25 var ( 26 space Space 27 spaceToCreate Space 28 warnings Warnings 29 executeErr error 30 ) 31 32 JustBeforeEach(func() { 33 spaceToCreate = Space{Name: "some-space", Relationships: Relationships{constant.RelationshipTypeOrganization: Relationship{GUID: "some-org-guid"}}} 34 space, warnings, executeErr = client.CreateSpace(spaceToCreate) 35 }) 36 37 When("spaces exist", func() { 38 BeforeEach(func() { 39 response := `{ 40 "name": "some-space", 41 "guid": "some-space-guid" 42 }` 43 44 expectedBody := `{ 45 "name": "some-space", 46 "relationships": { 47 "organization": { 48 "data": { "guid": "some-org-guid" } 49 } 50 } 51 }` 52 server.AppendHandlers( 53 CombineHandlers( 54 VerifyRequest(http.MethodPost, "/v3/spaces"), 55 VerifyJSON(expectedBody), 56 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 57 ), 58 ) 59 }) 60 61 It("returns the given space and all warnings", func() { 62 Expect(executeErr).ToNot(HaveOccurred()) 63 Expect(warnings).To(ConsistOf("this is a warning")) 64 65 Expect(space).To(Equal(Space{ 66 GUID: "some-space-guid", 67 Name: "some-space", 68 })) 69 }) 70 }) 71 72 When("the cloud controller returns errors and warnings", func() { 73 BeforeEach(func() { 74 response := `{ 75 "errors": [ 76 { 77 "code": 10008, 78 "detail": "The request is semantically invalid: command presence", 79 "title": "CF-UnprocessableEntity" 80 }, 81 { 82 "code": 10010, 83 "detail": "Isolation segment not found", 84 "title": "CF-ResourceNotFound" 85 } 86 ] 87 }` 88 server.AppendHandlers( 89 CombineHandlers( 90 VerifyRequest(http.MethodPost, "/v3/spaces"), 91 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 92 ), 93 ) 94 }) 95 96 It("returns the error and all warnings", func() { 97 Expect(executeErr).To(MatchError(ccerror.MultiError{ 98 ResponseCode: http.StatusTeapot, 99 Errors: []ccerror.V3Error{ 100 { 101 Code: 10008, 102 Detail: "The request is semantically invalid: command presence", 103 Title: "CF-UnprocessableEntity", 104 }, 105 { 106 Code: 10010, 107 Detail: "Isolation segment not found", 108 Title: "CF-ResourceNotFound", 109 }, 110 }, 111 })) 112 Expect(warnings).To(ConsistOf("this is a warning")) 113 }) 114 }) 115 116 }) 117 118 Describe("GetSpaces", func() { 119 var ( 120 query Query 121 122 spaces []Space 123 warnings Warnings 124 executeErr error 125 ) 126 127 JustBeforeEach(func() { 128 spaces, warnings, executeErr = client.GetSpaces(query) 129 }) 130 131 When("spaces exist", func() { 132 BeforeEach(func() { 133 response1 := fmt.Sprintf(`{ 134 "pagination": { 135 "next": { 136 "href": "%s/v3/spaces?names=some-space-name&page=2&per_page=2" 137 } 138 }, 139 "resources": [ 140 { 141 "name": "space-name-1", 142 "guid": "space-guid-1", 143 "relationships": { 144 "organization": { 145 "data": { "guid": "org-guid-1" } 146 } 147 } 148 }, 149 { 150 "name": "space-name-2", 151 "guid": "space-guid-2", 152 "relationships": { 153 "organization": { 154 "data": { "guid": "org-guid-2" } 155 } 156 } 157 } 158 ] 159 }`, server.URL()) 160 response2 := `{ 161 "pagination": { 162 "next": null 163 }, 164 "resources": [ 165 { 166 "name": "space-name-3", 167 "guid": "space-guid-3", 168 "relationships": { 169 "organization": { 170 "data": { "guid": "org-guid-3" } 171 } 172 } 173 } 174 ] 175 }` 176 177 server.AppendHandlers( 178 CombineHandlers( 179 VerifyRequest(http.MethodGet, "/v3/spaces", "names=some-space-name"), 180 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 181 ), 182 ) 183 server.AppendHandlers( 184 CombineHandlers( 185 VerifyRequest(http.MethodGet, "/v3/spaces", "names=some-space-name&page=2&per_page=2"), 186 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 187 ), 188 ) 189 190 query = Query{ 191 Key: NameFilter, 192 Values: []string{"some-space-name"}, 193 } 194 }) 195 196 It("returns the queried spaces and all warnings", func() { 197 Expect(executeErr).NotTo(HaveOccurred()) 198 199 Expect(spaces).To(ConsistOf( 200 Space{Name: "space-name-1", GUID: "space-guid-1", Relationships: Relationships{ 201 constant.RelationshipTypeOrganization: Relationship{GUID: "org-guid-1"}, 202 }}, 203 Space{Name: "space-name-2", GUID: "space-guid-2", Relationships: Relationships{ 204 constant.RelationshipTypeOrganization: Relationship{GUID: "org-guid-2"}, 205 }}, 206 Space{Name: "space-name-3", GUID: "space-guid-3", Relationships: Relationships{ 207 constant.RelationshipTypeOrganization: Relationship{GUID: "org-guid-3"}, 208 }}, 209 )) 210 Expect(warnings).To(ConsistOf("this is a warning", "this is another warning")) 211 }) 212 }) 213 214 When("the cloud controller returns errors and warnings", func() { 215 BeforeEach(func() { 216 response := `{ 217 "errors": [ 218 { 219 "code": 10008, 220 "detail": "The request is semantically invalid: command presence", 221 "title": "CF-UnprocessableEntity" 222 }, 223 { 224 "code": 10010, 225 "detail": "Space not found", 226 "title": "CF-SpaceNotFound" 227 } 228 ] 229 }` 230 server.AppendHandlers( 231 CombineHandlers( 232 VerifyRequest(http.MethodGet, "/v3/spaces"), 233 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 234 ), 235 ) 236 }) 237 238 It("returns the error and all warnings", func() { 239 Expect(executeErr).To(MatchError(ccerror.MultiError{ 240 ResponseCode: http.StatusTeapot, 241 Errors: []ccerror.V3Error{ 242 { 243 Code: 10008, 244 Detail: "The request is semantically invalid: command presence", 245 Title: "CF-UnprocessableEntity", 246 }, 247 { 248 Code: 10010, 249 Detail: "Space not found", 250 Title: "CF-SpaceNotFound", 251 }, 252 }, 253 })) 254 Expect(warnings).To(ConsistOf("this is a warning")) 255 }) 256 }) 257 }) 258 259 Describe("UpdateSpace", func() { 260 var ( 261 spaceToUpdate Space 262 updatedSpace Space 263 warnings Warnings 264 executeErr error 265 ) 266 267 JustBeforeEach(func() { 268 updatedSpace, warnings, executeErr = client.UpdateSpace(spaceToUpdate) 269 }) 270 271 When("the organization is updated successfully", func() { 272 BeforeEach(func() { 273 response := `{ 274 "guid": "some-space-guid", 275 "name": "some-space-name", 276 "metadata": { 277 "labels": { 278 "k1":"v1", 279 "k2":"v2" 280 } 281 } 282 }` 283 284 expectedBody := map[string]interface{}{ 285 "name": "some-space-name", 286 "metadata": map[string]interface{}{ 287 "labels": map[string]string{ 288 "k1": "v1", 289 "k2": "v2", 290 }, 291 }, 292 } 293 294 server.AppendHandlers( 295 CombineHandlers( 296 VerifyRequest(http.MethodPatch, "/v3/spaces/some-guid"), 297 VerifyJSONRepresenting(expectedBody), 298 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 299 ), 300 ) 301 302 spaceToUpdate = Space{ 303 Name: "some-space-name", 304 GUID: "some-guid", 305 Metadata: &Metadata{ 306 Labels: map[string]types.NullString{ 307 "k1": types.NewNullString("v1"), 308 "k2": types.NewNullString("v2"), 309 }, 310 }, 311 } 312 }) 313 314 It("should include the labels in the JSON", func() { 315 Expect(executeErr).ToNot(HaveOccurred()) 316 Expect(server.ReceivedRequests()).To(HaveLen(3)) 317 Expect(len(warnings)).To(Equal(1)) 318 Expect(warnings).To(ConsistOf("this is a warning")) 319 Expect(updatedSpace.Metadata.Labels).To(BeEquivalentTo( 320 map[string]types.NullString{ 321 "k1": types.NewNullString("v1"), 322 "k2": types.NewNullString("v2"), 323 })) 324 }) 325 326 }) 327 328 }) 329 330 Describe("DeleteSpace", func() { 331 var ( 332 jobURL JobURL 333 warnings Warnings 334 executeErr error 335 ) 336 337 JustBeforeEach(func() { 338 jobURL, warnings, executeErr = client.DeleteSpace("space-guid") 339 }) 340 341 When("no errors are encountered", func() { 342 BeforeEach(func() { 343 server.AppendHandlers( 344 CombineHandlers( 345 VerifyRequest(http.MethodDelete, "/v3/spaces/space-guid"), 346 RespondWith(http.StatusAccepted, nil, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}, "Location": []string{"job-url"}}), 347 )) 348 }) 349 350 It("deletes the Space and returns all warnings", func() { 351 Expect(executeErr).NotTo(HaveOccurred()) 352 Expect(warnings).To(ConsistOf(Warnings{"warning-1", "warning-2"})) 353 Expect(jobURL).To(Equal(JobURL("job-url"))) 354 }) 355 }) 356 357 When("an error is encountered", func() { 358 BeforeEach(func() { 359 response := `{ 360 "errors": [ 361 { 362 "detail": "Space not found", 363 "title": "CF-ResourceNotFound", 364 "code": 10010 365 } 366 ] 367 }` 368 server.AppendHandlers( 369 CombineHandlers( 370 VerifyRequest(http.MethodDelete, "/v3/spaces/space-guid"), 371 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}}), 372 )) 373 }) 374 375 It("returns an error and all warnings", func() { 376 Expect(executeErr).To(MatchError(ccerror.ResourceNotFoundError{ 377 Message: "Space not found", 378 })) 379 Expect(warnings).To(ConsistOf(Warnings{"warning-1", "warning-2"})) 380 }) 381 }) 382 }) 383 })