github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/api/cloudcontroller/ccv2/application_test.go (about) 1 package ccv2_test 2 3 import ( 4 "net/http" 5 "time" 6 7 "code.cloudfoundry.org/cli/api/cloudcontroller" 8 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 9 . "github.com/onsi/ginkgo" 10 . "github.com/onsi/gomega" 11 . "github.com/onsi/gomega/ghttp" 12 ) 13 14 var _ = Describe("Application", func() { 15 var client *Client 16 17 BeforeEach(func() { 18 client = NewTestClient() 19 }) 20 21 Describe("GetApplication", func() { 22 BeforeEach(func() { 23 response := `{ 24 "metadata": { 25 "guid": "app-guid-1", 26 "updated_at": null 27 }, 28 "entity": { 29 "buildpack": "ruby 1.6.29", 30 "detected_start_command": "echo 'I am a banana'", 31 "disk_quota": 586, 32 "detected_buildpack": null, 33 "health_check_type": "port", 34 "health_check_http_endpoint": "/", 35 "instances": 13, 36 "memory": 1024, 37 "name": "app-name-1", 38 "package_state": "FAILED", 39 "package_updated_at": "2015-03-10T23:11:54Z", 40 "stack_guid": "some-stack-guid", 41 "staging_failed_reason": "some-reason", 42 "state": "STOPPED" 43 } 44 }` 45 server.AppendHandlers( 46 CombineHandlers( 47 VerifyRequest(http.MethodGet, "/v2/apps/app-guid-1"), 48 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 49 ), 50 ) 51 }) 52 53 Context("when apps exist", func() { 54 It("returns the app", func() { 55 app, warnings, err := client.GetApplication("app-guid-1") 56 Expect(err).NotTo(HaveOccurred()) 57 58 updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z") 59 Expect(err).NotTo(HaveOccurred()) 60 61 Expect(app).To(Equal(Application{ 62 Buildpack: "ruby 1.6.29", 63 DetectedBuildpack: "", 64 DetectedStartCommand: "echo 'I am a banana'", 65 DiskQuota: 586, 66 GUID: "app-guid-1", 67 HealthCheckType: "port", 68 HealthCheckHTTPEndpoint: "/", 69 Instances: 13, 70 Memory: 1024, 71 Name: "app-name-1", 72 PackageState: ApplicationPackageFailed, 73 PackageUpdatedAt: updatedAt, 74 StackGUID: "some-stack-guid", 75 StagingFailedReason: "some-reason", 76 State: ApplicationStopped, 77 })) 78 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 79 }) 80 }) 81 }) 82 83 Describe("GetApplications", func() { 84 BeforeEach(func() { 85 response1 := `{ 86 "next_url": "/v2/apps?q=space_guid:some-space-guid&page=2", 87 "resources": [ 88 { 89 "metadata": { 90 "guid": "app-guid-1", 91 "updated_at": null 92 }, 93 "entity": { 94 "buildpack": "ruby 1.6.29", 95 "detected_start_command": "echo 'I am a banana'", 96 "disk_quota": 586, 97 "detected_buildpack": null, 98 "health_check_type": "port", 99 "health_check_http_endpoint": "/", 100 "instances": 13, 101 "memory": 1024, 102 "name": "app-name-1", 103 "package_state": "FAILED", 104 "package_updated_at": "2015-03-10T23:11:54Z", 105 "stack_guid": "some-stack-guid", 106 "staging_failed_reason": "some-reason", 107 "state": "STOPPED" 108 } 109 }, 110 { 111 "metadata": { 112 "guid": "app-guid-2", 113 "updated_at": null 114 }, 115 "entity": { 116 "name": "app-name-2", 117 "detected_buildpack": "ruby 1.6.29", 118 "package_updated_at": null 119 } 120 } 121 ] 122 }` 123 response2 := `{ 124 "next_url": null, 125 "resources": [ 126 { 127 "metadata": { 128 "guid": "app-guid-3", 129 "updated_at": null 130 }, 131 "entity": { 132 "name": "app-name-3" 133 } 134 }, 135 { 136 "metadata": { 137 "guid": "app-guid-4", 138 "updated_at": null 139 }, 140 "entity": { 141 "name": "app-name-4" 142 } 143 } 144 ] 145 }` 146 server.AppendHandlers( 147 CombineHandlers( 148 VerifyRequest(http.MethodGet, "/v2/apps", "q=space_guid:some-space-guid"), 149 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 150 ), 151 ) 152 server.AppendHandlers( 153 CombineHandlers( 154 VerifyRequest(http.MethodGet, "/v2/apps", "q=space_guid:some-space-guid&page=2"), 155 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 156 ), 157 ) 158 }) 159 160 Context("when apps exist", func() { 161 It("returns all the queried apps", func() { 162 apps, warnings, err := client.GetApplications([]Query{{ 163 Filter: SpaceGUIDFilter, 164 Operator: EqualOperator, 165 Value: "some-space-guid", 166 }}) 167 Expect(err).NotTo(HaveOccurred()) 168 169 updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z") 170 Expect(err).NotTo(HaveOccurred()) 171 172 Expect(apps).To(ConsistOf([]Application{ 173 { 174 Buildpack: "ruby 1.6.29", 175 DetectedBuildpack: "", 176 DetectedStartCommand: "echo 'I am a banana'", 177 DiskQuota: 586, 178 GUID: "app-guid-1", 179 HealthCheckType: "port", 180 HealthCheckHTTPEndpoint: "/", 181 Instances: 13, 182 Memory: 1024, 183 Name: "app-name-1", 184 PackageState: ApplicationPackageFailed, 185 PackageUpdatedAt: updatedAt, 186 StackGUID: "some-stack-guid", 187 StagingFailedReason: "some-reason", 188 State: ApplicationStopped, 189 }, 190 {Name: "app-name-2", GUID: "app-guid-2", DetectedBuildpack: "ruby 1.6.29"}, 191 {Name: "app-name-3", GUID: "app-guid-3"}, 192 {Name: "app-name-4", GUID: "app-guid-4"}, 193 })) 194 Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"})) 195 }) 196 }) 197 }) 198 199 Describe("UpdateApplication", func() { 200 Context("when the update is successful", func() { 201 Context("when updating all fields", func() { //are we encoding everything correctly? 202 BeforeEach(func() { 203 response1 := `{ 204 "metadata": { 205 "guid": "some-app-guid", 206 "updated_at": null 207 }, 208 "entity": { 209 "buildpack": "ruby 1.6.29", 210 "detected_start_command": "echo 'I am a banana'", 211 "disk_quota": 586, 212 "detected_buildpack": null, 213 "health_check_type": "some-health-check-type", 214 "health_check_http_endpoint": "/anything", 215 "instances": 13, 216 "memory": 1024, 217 "name": "app-name-1", 218 "package_updated_at": "2015-03-10T23:11:54Z", 219 "stack_guid": "some-stack-guid", 220 "state": "STARTED" 221 } 222 }` 223 expectedBody := map[string]string{ 224 "health_check_http_endpoint": "/anything", 225 "health_check_type": "some-health-check-type", 226 "state": "STARTED", 227 } 228 229 server.AppendHandlers( 230 CombineHandlers( 231 VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"), 232 VerifyJSONRepresenting(expectedBody), 233 RespondWith(http.StatusCreated, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 234 ), 235 ) 236 }) 237 238 It("returns the updated object and warnings and sends all updated field", func() { 239 app, warnings, err := client.UpdateApplication(Application{ 240 GUID: "some-app-guid", 241 HealthCheckType: "some-health-check-type", 242 HealthCheckHTTPEndpoint: "/anything", 243 State: ApplicationStarted, 244 }) 245 Expect(err).NotTo(HaveOccurred()) 246 247 updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z") 248 Expect(err).NotTo(HaveOccurred()) 249 250 Expect(app).To(Equal(Application{ 251 Buildpack: "ruby 1.6.29", 252 DetectedBuildpack: "", 253 DetectedStartCommand: "echo 'I am a banana'", 254 DiskQuota: 586, 255 GUID: "some-app-guid", 256 HealthCheckType: "some-health-check-type", 257 HealthCheckHTTPEndpoint: "/anything", 258 Instances: 13, 259 Memory: 1024, 260 Name: "app-name-1", 261 PackageUpdatedAt: updatedAt, 262 StackGUID: "some-stack-guid", 263 State: ApplicationStarted, 264 })) 265 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 266 }) 267 }) 268 269 Context("when only updating one field", func() { // are we **only** encoding the things we want 270 BeforeEach(func() { 271 response1 := `{ 272 "metadata": { 273 "guid": "some-app-guid", 274 "updated_at": null 275 }, 276 "entity": { 277 "buildpack": "ruby 1.6.29", 278 "detected_start_command": "echo 'I am a banana'", 279 "disk_quota": 586, 280 "detected_buildpack": null, 281 "health_check_type": "some-health-check-type", 282 "health_check_http_endpoint": "/", 283 "instances": 13, 284 "memory": 1024, 285 "name": "app-name-1", 286 "package_updated_at": "2015-03-10T23:11:54Z", 287 "stack_guid": "some-stack-guid", 288 "state": "STOPPED" 289 } 290 }` 291 server.AppendHandlers( 292 CombineHandlers( 293 VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"), 294 VerifyBody([]byte(`{"health_check_type":"some-health-check-type"}`)), 295 RespondWith(http.StatusCreated, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 296 ), 297 ) 298 }) 299 300 It("returns the updated object and warnings and sends only updated field", func() { 301 app, warnings, err := client.UpdateApplication(Application{ 302 GUID: "some-app-guid", 303 HealthCheckType: "some-health-check-type", 304 }) 305 Expect(err).NotTo(HaveOccurred()) 306 307 updatedAt, err := time.Parse(time.RFC3339, "2015-03-10T23:11:54Z") 308 Expect(err).NotTo(HaveOccurred()) 309 310 Expect(app).To(Equal(Application{ 311 Buildpack: "ruby 1.6.29", 312 DetectedBuildpack: "", 313 DetectedStartCommand: "echo 'I am a banana'", 314 DiskQuota: 586, 315 GUID: "some-app-guid", 316 HealthCheckType: "some-health-check-type", 317 HealthCheckHTTPEndpoint: "/", 318 Instances: 13, 319 Memory: 1024, 320 Name: "app-name-1", 321 PackageUpdatedAt: updatedAt, 322 StackGUID: "some-stack-guid", 323 State: ApplicationStopped, 324 })) 325 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 326 }) 327 }) 328 }) 329 330 Context("when the update returns an error", func() { 331 BeforeEach(func() { 332 response := ` 333 { 334 "code": 210002, 335 "description": "The app could not be found: some-app-guid", 336 "error_code": "CF-AppNotFound" 337 } 338 ` 339 server.AppendHandlers( 340 CombineHandlers( 341 VerifyRequest(http.MethodPut, "/v2/apps/some-app-guid"), 342 // VerifyBody([]byte(`{"health_check_type":"some-health-check-type"}`)), 343 RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 344 ), 345 ) 346 }) 347 348 It("returns the error and warnings", func() { 349 _, warnings, err := client.UpdateApplication(Application{ 350 GUID: "some-app-guid", 351 HealthCheckType: "some-health-check-type", 352 }) 353 Expect(err).To(MatchError(cloudcontroller.ResourceNotFoundError{Message: "The app could not be found: some-app-guid"})) 354 Expect(warnings).To(ConsistOf(Warnings{"this is a warning"})) 355 }) 356 }) 357 }) 358 359 Describe("GetRouteApplications", func() { 360 Context("when the route guid is not found", func() { 361 BeforeEach(func() { 362 response := ` 363 { 364 "code": 210002, 365 "description": "The route could not be found: some-route-guid", 366 "error_code": "CF-RouteNotFound" 367 } 368 ` 369 server.AppendHandlers( 370 CombineHandlers( 371 VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps"), 372 RespondWith(http.StatusNotFound, response), 373 ), 374 ) 375 }) 376 377 It("returns an error", func() { 378 _, _, err := client.GetRouteApplications("some-route-guid", nil) 379 Expect(err).To(MatchError(cloudcontroller.ResourceNotFoundError{ 380 Message: "The route could not be found: some-route-guid", 381 })) 382 }) 383 }) 384 385 Context("when there are applications associated with this route", func() { 386 BeforeEach(func() { 387 response1 := `{ 388 "next_url": "/v2/routes/some-route-guid/apps?q=space_guid:some-space-guid&page=2", 389 "resources": [ 390 { 391 "metadata": { 392 "guid": "app-guid-1", 393 "updated_at": null 394 }, 395 "entity": { 396 "name": "app-name-1" 397 } 398 }, 399 { 400 "metadata": { 401 "guid": "app-guid-2", 402 "updated_at": null 403 }, 404 "entity": { 405 "name": "app-name-2" 406 } 407 } 408 ] 409 }` 410 response2 := `{ 411 "next_url": null, 412 "resources": [ 413 { 414 "metadata": { 415 "guid": "app-guid-3", 416 "updated_at": null 417 }, 418 "entity": { 419 "name": "app-name-3" 420 } 421 }, 422 { 423 "metadata": { 424 "guid": "app-guid-4", 425 "updated_at": null 426 }, 427 "entity": { 428 "name": "app-name-4" 429 } 430 } 431 ] 432 }` 433 server.AppendHandlers( 434 CombineHandlers( 435 VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps", "q=space_guid:some-space-guid"), 436 RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 437 ), 438 ) 439 server.AppendHandlers( 440 CombineHandlers( 441 VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps", "q=space_guid:some-space-guid&page=2"), 442 RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}), 443 ), 444 ) 445 }) 446 447 It("returns all the applications and all warnings", func() { 448 apps, warnings, err := client.GetRouteApplications("some-route-guid", []Query{{ 449 Filter: SpaceGUIDFilter, 450 Operator: EqualOperator, 451 Value: "some-space-guid", 452 }}) 453 Expect(err).NotTo(HaveOccurred()) 454 Expect(apps).To(ConsistOf([]Application{ 455 {Name: "app-name-1", GUID: "app-guid-1"}, 456 {Name: "app-name-2", GUID: "app-guid-2"}, 457 {Name: "app-name-3", GUID: "app-guid-3"}, 458 {Name: "app-name-4", GUID: "app-guid-4"}, 459 })) 460 Expect(warnings).To(ConsistOf(Warnings{"this is a warning", "this is another warning"})) 461 }) 462 }) 463 464 Context("when there are no applications associated with this route", func() { 465 BeforeEach(func() { 466 response := `{ 467 "next_url": "", 468 "resources": [] 469 }` 470 server.AppendHandlers( 471 CombineHandlers( 472 VerifyRequest(http.MethodGet, "/v2/routes/some-route-guid/apps"), 473 RespondWith(http.StatusOK, response), 474 ), 475 ) 476 }) 477 478 It("returns an empty list of applications", func() { 479 apps, _, err := client.GetRouteApplications("some-route-guid", nil) 480 Expect(err).NotTo(HaveOccurred()) 481 Expect(apps).To(BeEmpty()) 482 }) 483 }) 484 }) 485 })