github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/actor/pushaction/application_config_test.go (about) 1 package pushaction_test 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 9 "code.cloudfoundry.org/cli/actor/actionerror" 10 . "code.cloudfoundry.org/cli/actor/pushaction" 11 "code.cloudfoundry.org/cli/actor/pushaction/pushactionfakes" 12 "code.cloudfoundry.org/cli/actor/sharedaction" 13 "code.cloudfoundry.org/cli/actor/v2action" 14 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 15 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant" 16 "code.cloudfoundry.org/cli/types" 17 "code.cloudfoundry.org/cli/util/manifest" 18 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 ) 22 23 var _ = Describe("Application Config", func() { 24 var ( 25 actor *Actor 26 fakeV2Actor *pushactionfakes.FakeV2Actor 27 fakeSharedActor *pushactionfakes.FakeSharedActor 28 fakeRandomWordGenerator *pushactionfakes.FakeRandomWordGenerator 29 ) 30 31 BeforeEach(func() { 32 fakeV2Actor = new(pushactionfakes.FakeV2Actor) 33 fakeSharedActor = new(pushactionfakes.FakeSharedActor) 34 actor = NewActor(fakeV2Actor, nil, fakeSharedActor) 35 36 fakeRandomWordGenerator = new(pushactionfakes.FakeRandomWordGenerator) 37 actor.WordGenerator = fakeRandomWordGenerator 38 }) 39 40 Describe("ApplicationConfig", func() { 41 Describe("CreatingApplication", func() { 42 Context("when the app did not exist", func() { 43 It("returns true", func() { 44 config := ApplicationConfig{} 45 Expect(config.CreatingApplication()).To(BeTrue()) 46 }) 47 }) 48 49 Context("when the app exists", func() { 50 It("returns false", func() { 51 config := ApplicationConfig{CurrentApplication: Application{Application: v2action.Application{GUID: "some-app-guid"}}} 52 Expect(config.CreatingApplication()).To(BeFalse()) 53 }) 54 }) 55 }) 56 57 Describe("UpdatedApplication", func() { 58 Context("when the app did not exist", func() { 59 It("returns false", func() { 60 config := ApplicationConfig{} 61 Expect(config.UpdatingApplication()).To(BeFalse()) 62 }) 63 }) 64 65 Context("when the app exists", func() { 66 It("returns true", func() { 67 config := ApplicationConfig{CurrentApplication: Application{Application: v2action.Application{GUID: "some-app-guid"}}} 68 Expect(config.UpdatingApplication()).To(BeTrue()) 69 }) 70 }) 71 }) 72 }) 73 74 Describe("ConvertToApplicationConfigs", func() { 75 var ( 76 appName string 77 domain v2action.Domain 78 filesPath string 79 80 orgGUID string 81 spaceGUID string 82 noStart bool 83 manifestApps []manifest.Application 84 85 configs []ApplicationConfig 86 warnings Warnings 87 executeErr error 88 89 firstConfig ApplicationConfig 90 ) 91 92 BeforeEach(func() { 93 appName = "some-app" 94 orgGUID = "some-org-guid" 95 spaceGUID = "some-space-guid" 96 noStart = false 97 98 var err error 99 filesPath, err = ioutil.TempDir("", "convert-to-application-configs") 100 Expect(err).ToNot(HaveOccurred()) 101 102 // The temp directory created on OSX contains a symlink and needs to be evaluated. 103 filesPath, err = filepath.EvalSymlinks(filesPath) 104 Expect(err).ToNot(HaveOccurred()) 105 106 manifestApps = []manifest.Application{{ 107 Name: appName, 108 Path: filesPath, 109 }} 110 111 domain = v2action.Domain{ 112 Name: "private-domain.com", 113 GUID: "some-private-domain-guid", 114 } 115 116 // Prevents NoDomainsFoundError 117 fakeV2Actor.GetOrganizationDomainsReturns( 118 []v2action.Domain{domain}, 119 v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, 120 nil, 121 ) 122 }) 123 124 JustBeforeEach(func() { 125 configs, warnings, executeErr = actor.ConvertToApplicationConfigs(orgGUID, spaceGUID, noStart, manifestApps) 126 if len(configs) > 0 { 127 firstConfig = configs[0] 128 } 129 }) 130 131 AfterEach(func() { 132 Expect(os.RemoveAll(filesPath)).ToNot(HaveOccurred()) 133 }) 134 135 Context("when the path is a symlink", func() { 136 var target string 137 138 BeforeEach(func() { 139 parentDir := filepath.Dir(filesPath) 140 target = filepath.Join(parentDir, "i-r-symlink") 141 Expect(os.Symlink(filesPath, target)).ToNot(HaveOccurred()) 142 manifestApps[0].Path = target 143 }) 144 145 AfterEach(func() { 146 Expect(os.RemoveAll(target)).ToNot(HaveOccurred()) 147 }) 148 149 It("evaluates the symlink into an absolute path", func() { 150 Expect(executeErr).ToNot(HaveOccurred()) 151 152 Expect(firstConfig.Path).To(Equal(filesPath)) 153 }) 154 155 Context("given a path that does not exist", func() { 156 BeforeEach(func() { 157 manifestApps[0].Path = "/i/will/fight/you/if/this/exists" 158 }) 159 160 It("returns errors and warnings", func() { 161 Expect(os.IsNotExist(executeErr)).To(BeTrue()) 162 163 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(0)) 164 Expect(fakeSharedActor.GatherArchiveResourcesCallCount()).To(Equal(0)) 165 }) 166 }) 167 }) 168 169 Context("when the application exists", func() { 170 var app Application 171 var route v2action.Route 172 173 BeforeEach(func() { 174 app = Application{ 175 Application: v2action.Application{ 176 Name: appName, 177 GUID: "some-app-guid", 178 SpaceGUID: spaceGUID, 179 }} 180 181 route = v2action.Route{ 182 Domain: v2action.Domain{ 183 Name: "some-domain.com", 184 GUID: "some-domain-guid", 185 }, 186 Host: app.Name, 187 GUID: "route-guid", 188 SpaceGUID: spaceGUID, 189 } 190 191 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app.Application, v2action.Warnings{"some-app-warning-1", "some-app-warning-2"}, nil) 192 }) 193 194 Context("when there is an existing route and retrieving the route(s) is successful", func() { 195 BeforeEach(func() { 196 fakeV2Actor.GetApplicationRoutesReturns([]v2action.Route{route}, v2action.Warnings{"app-route-warnings"}, nil) 197 }) 198 199 Context("when retrieving the application's services is successful", func() { 200 var services []v2action.ServiceInstance 201 202 BeforeEach(func() { 203 services = []v2action.ServiceInstance{ 204 {Name: "service-1", GUID: "service-instance-1"}, 205 {Name: "service-2", GUID: "service-instance-2"}, 206 } 207 208 fakeV2Actor.GetServiceInstancesByApplicationReturns(services, v2action.Warnings{"service-instance-warning-1", "service-instance-warning-2"}, nil) 209 }) 210 211 It("return warnings", func() { 212 Expect(executeErr).ToNot(HaveOccurred()) 213 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings", "service-instance-warning-1", "service-instance-warning-2")) 214 }) 215 216 It("sets the current application to the existing application", func() { 217 Expect(firstConfig.CurrentApplication).To(Equal(app)) 218 219 Expect(fakeV2Actor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1)) 220 passedName, passedSpaceGUID := fakeV2Actor.GetApplicationByNameAndSpaceArgsForCall(0) 221 Expect(passedName).To(Equal(app.Name)) 222 Expect(passedSpaceGUID).To(Equal(spaceGUID)) 223 }) 224 225 It("sets the current routes", func() { 226 Expect(firstConfig.CurrentRoutes).To(ConsistOf(route)) 227 228 Expect(fakeV2Actor.GetApplicationRoutesCallCount()).To(Equal(1)) 229 Expect(fakeV2Actor.GetApplicationRoutesArgsForCall(0)).To(Equal(app.GUID)) 230 }) 231 232 It("sets the bound services", func() { 233 Expect(firstConfig.CurrentServices).To(Equal(map[string]v2action.ServiceInstance{ 234 "service-1": v2action.ServiceInstance{Name: "service-1", GUID: "service-instance-1"}, 235 "service-2": v2action.ServiceInstance{Name: "service-2", GUID: "service-instance-2"}, 236 })) 237 238 Expect(fakeV2Actor.GetServiceInstancesByApplicationCallCount()).To(Equal(1)) 239 Expect(fakeV2Actor.GetServiceInstancesByApplicationArgsForCall(0)).To(Equal("some-app-guid")) 240 }) 241 }) 242 243 Context("when retrieving the application's services errors", func() { 244 var expectedErr error 245 246 BeforeEach(func() { 247 expectedErr = errors.New("dios mio") 248 fakeV2Actor.GetServiceInstancesByApplicationReturns(nil, v2action.Warnings{"service-instance-warning-1", "service-instance-warning-2"}, expectedErr) 249 }) 250 251 It("returns the error and warnings", func() { 252 Expect(executeErr).To(MatchError(expectedErr)) 253 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings", "service-instance-warning-1", "service-instance-warning-2")) 254 }) 255 }) 256 257 Context("when the --random-route flag is provided", func() { 258 BeforeEach(func() { 259 manifestApps[0].RandomRoute = true 260 }) 261 262 It("does not generate a random route", func() { 263 Expect(executeErr).ToNot(HaveOccurred()) 264 Expect(warnings).To(ConsistOf( 265 "some-app-warning-1", 266 "some-app-warning-2", 267 "app-route-warnings", 268 )) 269 Expect(firstConfig.DesiredRoutes).To(ConsistOf(route)) 270 271 Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0)) 272 }) 273 }) 274 }) 275 276 Context("when there is not an existing route and no errors are encountered", func() { 277 BeforeEach(func() { 278 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 279 }) 280 281 Context("when the --random-route flag is provided", func() { 282 BeforeEach(func() { 283 manifestApps[0].RandomRoute = true 284 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 285 fakeRandomWordGenerator.RandomNounReturns("apple") 286 }) 287 288 It("appends a random route to the current route for desired routes", func() { 289 Expect(executeErr).ToNot(HaveOccurred()) 290 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings", "private-domain-warnings", "shared-domain-warnings")) 291 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 292 v2action.Route{ 293 Domain: domain, 294 SpaceGUID: spaceGUID, 295 Host: "some-app-striped-apple", 296 }, 297 )) 298 }) 299 }) 300 }) 301 302 Context("when retrieving the application's routes errors", func() { 303 var expectedErr error 304 305 BeforeEach(func() { 306 expectedErr = errors.New("dios mio") 307 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, expectedErr) 308 }) 309 310 It("returns the error and warnings", func() { 311 Expect(executeErr).To(MatchError(expectedErr)) 312 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings")) 313 }) 314 }) 315 }) 316 317 Context("when the application does not exist", func() { 318 BeforeEach(func() { 319 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, v2action.Warnings{"some-app-warning-1", "some-app-warning-2"}, actionerror.ApplicationNotFoundError{}) 320 }) 321 322 It("creates a new application and sets it to the desired application", func() { 323 Expect(executeErr).ToNot(HaveOccurred()) 324 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "private-domain-warnings", "shared-domain-warnings")) 325 Expect(firstConfig.CurrentApplication).To(Equal(Application{Application: v2action.Application{}})) 326 Expect(firstConfig.DesiredApplication).To(Equal(Application{ 327 Application: v2action.Application{ 328 Name: appName, 329 SpaceGUID: spaceGUID, 330 }})) 331 }) 332 333 Context("when the --random-route flag is provided", func() { 334 BeforeEach(func() { 335 manifestApps[0].RandomRoute = true 336 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 337 fakeRandomWordGenerator.RandomNounReturns("apple") 338 }) 339 340 It("appends a random route to the current route for desired routes", func() { 341 Expect(executeErr).ToNot(HaveOccurred()) 342 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "private-domain-warnings", "shared-domain-warnings")) 343 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 344 v2action.Route{ 345 Domain: domain, 346 SpaceGUID: spaceGUID, 347 Host: "some-app-striped-apple", 348 }, 349 )) 350 }) 351 352 Context("when the -d flag is provided", func() { 353 Context("when the domain is an http domain", func() { 354 var httpDomain v2action.Domain 355 356 BeforeEach(func() { 357 httpDomain = v2action.Domain{ 358 Name: "some-http-domain.com", 359 } 360 361 manifestApps[0].Domain = "some-http-domain.com" 362 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{httpDomain}, v2action.Warnings{"domain-warnings-1", "domain-warnings-2"}, nil) 363 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 364 fakeRandomWordGenerator.RandomNounReturns("apple") 365 }) 366 367 It("appends a random HTTP route to the desired routes", func() { 368 Expect(executeErr).ToNot(HaveOccurred()) 369 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "domain-warnings-1", "domain-warnings-2")) 370 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 371 v2action.Route{ 372 Host: "some-app-striped-apple", 373 Domain: httpDomain, 374 SpaceGUID: spaceGUID, 375 }, 376 )) 377 }) 378 }) 379 380 Context("when the domain is a tcp domain", func() { 381 var tcpDomain v2action.Domain 382 BeforeEach(func() { 383 tcpDomain = v2action.Domain{ 384 Name: "some-tcp-domain.com", 385 RouterGroupType: constant.TCPRouterGroup, 386 } 387 388 manifestApps[0].Domain = "some-tcp-domain.com" 389 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{tcpDomain}, v2action.Warnings{"domain-warnings-1", "domain-warnings-2"}, nil) 390 }) 391 392 It("appends a random TCP route to the desired routes", func() { 393 Expect(executeErr).ToNot(HaveOccurred()) 394 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "domain-warnings-1", "domain-warnings-2")) 395 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 396 v2action.Route{ 397 Domain: tcpDomain, 398 SpaceGUID: spaceGUID, 399 Port: types.NullInt{IsSet: false}, 400 }, 401 )) 402 }) 403 }) 404 }) 405 }) 406 }) 407 408 Context("when retrieving the application errors", func() { 409 var expectedErr error 410 411 BeforeEach(func() { 412 expectedErr = errors.New("dios mio") 413 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, v2action.Warnings{"some-app-warning-1", "some-app-warning-2"}, expectedErr) 414 }) 415 416 It("returns the error and warnings", func() { 417 Expect(executeErr).To(MatchError(expectedErr)) 418 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2")) 419 }) 420 }) 421 422 Context("when overriding application properties", func() { 423 var stack v2action.Stack 424 425 Context("when the manifest contains all the properties", func() { 426 BeforeEach(func() { 427 manifestApps[0].Buildpack = types.FilteredString{IsSet: true, Value: "some-buildpack"} 428 manifestApps[0].Command = types.FilteredString{IsSet: true, Value: "some-command"} 429 manifestApps[0].DockerImage = "some-docker-image" 430 manifestApps[0].DockerUsername = "some-docker-username" 431 manifestApps[0].DockerPassword = "some-docker-password" 432 manifestApps[0].HealthCheckTimeout = 5 433 manifestApps[0].Instances = types.NullInt{Value: 1, IsSet: true} 434 manifestApps[0].DiskQuota = types.NullByteSizeInMb{Value: 2, IsSet: true} 435 manifestApps[0].Memory = types.NullByteSizeInMb{Value: 3, IsSet: true} 436 manifestApps[0].StackName = "some-stack" 437 manifestApps[0].EnvironmentVariables = map[string]string{ 438 "env1": "1", 439 "env3": "3", 440 } 441 442 stack = v2action.Stack{ 443 Name: "some-stack", 444 GUID: "some-stack-guid", 445 } 446 447 fakeV2Actor.GetStackByNameReturns(stack, v2action.Warnings{"some-stack-warning"}, nil) 448 }) 449 450 It("overrides the current application properties", func() { 451 Expect(warnings).To(ConsistOf("some-stack-warning", "private-domain-warnings", "shared-domain-warnings")) 452 453 Expect(firstConfig.DesiredApplication.Buildpack).To(Equal(types.FilteredString{IsSet: true, Value: "some-buildpack"})) 454 Expect(firstConfig.DesiredApplication.Command).To(Equal(types.FilteredString{IsSet: true, Value: "some-command"})) 455 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image")) 456 Expect(firstConfig.DesiredApplication.DockerCredentials.Username).To(Equal("some-docker-username")) 457 Expect(firstConfig.DesiredApplication.DockerCredentials.Password).To(Equal("some-docker-password")) 458 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 459 "env1": "1", 460 "env3": "3", 461 })) 462 Expect(firstConfig.DesiredApplication.HealthCheckTimeout).To(Equal(5)) 463 Expect(firstConfig.DesiredApplication.Instances).To(Equal(types.NullInt{Value: 1, IsSet: true})) 464 Expect(firstConfig.DesiredApplication.DiskQuota).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 2})) 465 Expect(firstConfig.DesiredApplication.Memory).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 3})) 466 Expect(firstConfig.DesiredApplication.StackGUID).To(Equal("some-stack-guid")) 467 Expect(firstConfig.DesiredApplication.Stack).To(Equal(stack)) 468 469 Expect(fakeV2Actor.GetStackByNameCallCount()).To(Equal(1)) 470 Expect(fakeV2Actor.GetStackByNameArgsForCall(0)).To(Equal("some-stack")) 471 }) 472 }) 473 474 Context("when the manifest does not contain any properties", func() { 475 BeforeEach(func() { 476 stack = v2action.Stack{ 477 Name: "some-stack", 478 GUID: "some-stack-guid", 479 } 480 fakeV2Actor.GetStackReturns(stack, nil, nil) 481 482 app := v2action.Application{ 483 Buildpack: types.FilteredString{IsSet: true, Value: "some-buildpack"}, 484 Command: types.FilteredString{IsSet: true, Value: "some-command"}, 485 DockerCredentials: ccv2.DockerCredentials{ 486 Username: "some-docker-username", 487 Password: "some-docker-password", 488 }, 489 DockerImage: "some-docker-image", 490 DiskQuota: types.NullByteSizeInMb{IsSet: true, Value: 2}, 491 EnvironmentVariables: map[string]string{ 492 "env2": "2", 493 "env3": "9", 494 }, 495 GUID: "some-app-guid", 496 HealthCheckHTTPEndpoint: "/some-endpoint", 497 HealthCheckTimeout: 5, 498 HealthCheckType: "port", 499 Instances: types.NullInt{Value: 3, IsSet: true}, 500 Memory: types.NullByteSizeInMb{IsSet: true, Value: 3}, 501 Name: appName, 502 StackGUID: stack.GUID, 503 } 504 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 505 }) 506 507 It("keeps the original app properties", func() { 508 Expect(firstConfig.DesiredApplication.Buildpack).To(Equal(types.FilteredString{IsSet: true, Value: "some-buildpack"})) 509 Expect(firstConfig.DesiredApplication.Command).To(Equal(types.FilteredString{IsSet: true, Value: "some-command"})) 510 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image")) 511 Expect(firstConfig.DesiredApplication.DockerCredentials.Username).To(Equal("some-docker-username")) 512 Expect(firstConfig.DesiredApplication.DockerCredentials.Password).To(Equal("some-docker-password")) 513 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 514 "env2": "2", 515 "env3": "9", 516 })) 517 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/some-endpoint")) 518 Expect(firstConfig.DesiredApplication.HealthCheckTimeout).To(Equal(5)) 519 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckPort)) 520 Expect(firstConfig.DesiredApplication.Instances).To(Equal(types.NullInt{Value: 3, IsSet: true})) 521 Expect(firstConfig.DesiredApplication.DiskQuota).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 2})) 522 Expect(firstConfig.DesiredApplication.Memory).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 3})) 523 Expect(firstConfig.DesiredApplication.StackGUID).To(Equal("some-stack-guid")) 524 Expect(firstConfig.DesiredApplication.Stack).To(Equal(stack)) 525 }) 526 }) 527 528 Context("when setting health check variables", func() { 529 Context("when setting the type to 'http'", func() { 530 BeforeEach(func() { 531 manifestApps[0].HealthCheckType = "http" 532 }) 533 534 Context("when the http health check endpoint is set", func() { 535 BeforeEach(func() { 536 manifestApps[0].HealthCheckHTTPEndpoint = "/some/endpoint" 537 }) 538 539 It("should overried the health check type and the endpoint should be set", func() { 540 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/some/endpoint")) 541 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckHTTP)) 542 }) 543 }) 544 545 Context("when the http health check endpoint is not set", func() { 546 It("should override the health check type and the endpoint should be defaulted to \"/\"", func() { 547 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/")) 548 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckHTTP)) 549 }) 550 }) 551 }) 552 553 Context("when setting type to 'port'", func() { 554 BeforeEach(func() { 555 manifestApps[0].HealthCheckType = "port" 556 }) 557 558 It("should override the health check type and the endpoint should not be set", func() { 559 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 560 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckPort)) 561 }) 562 }) 563 564 Context("when setting type to 'process'", func() { 565 BeforeEach(func() { 566 manifestApps[0].HealthCheckType = "process" 567 }) 568 569 It("should override the health check type and the endpoint should not be set", func() { 570 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 571 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckProcess)) 572 }) 573 }) 574 575 Context("when type is unset", func() { 576 It("leaves the previously set values", func() { 577 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 578 Expect(firstConfig.DesiredApplication.HealthCheckType).To(BeEmpty()) 579 }) 580 }) 581 }) 582 583 Context("when retrieving the stack errors", func() { 584 var expectedErr error 585 586 BeforeEach(func() { 587 manifestApps[0].StackName = "some-stack" 588 589 expectedErr = errors.New("potattototototototootot") 590 fakeV2Actor.GetStackByNameReturns(v2action.Stack{}, v2action.Warnings{"some-stack-warning"}, expectedErr) 591 }) 592 593 It("returns the error and warnings", func() { 594 Expect(executeErr).To(MatchError(expectedErr)) 595 Expect(warnings).To(ConsistOf("some-stack-warning")) 596 }) 597 }) 598 599 Context("when both the manifest and application contains environment variables", func() { 600 BeforeEach(func() { 601 manifestApps[0].EnvironmentVariables = map[string]string{ 602 "env1": "1", 603 "env3": "3", 604 } 605 606 app := v2action.Application{ 607 EnvironmentVariables: map[string]string{ 608 "env2": "2", 609 "env3": "9", 610 }, 611 } 612 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 613 }) 614 615 It("adds/overrides the existing environment variables", func() { 616 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 617 "env1": "1", 618 "env2": "2", 619 "env3": "3", 620 })) 621 622 // Does not modify original set of env vars 623 Expect(firstConfig.CurrentApplication.EnvironmentVariables).To(Equal(map[string]string{ 624 "env2": "2", 625 "env3": "9", 626 })) 627 }) 628 }) 629 630 Context("when neither the manifest or the application contains environment variables", func() { 631 It("leaves the EnvironmentVariables as nil", func() { 632 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(BeNil()) 633 }) 634 }) 635 636 Context("when no-start is set to true", func() { 637 BeforeEach(func() { 638 noStart = true 639 }) 640 641 It("sets the desired app state to stopped", func() { 642 Expect(executeErr).ToNot(HaveOccurred()) 643 Expect(firstConfig.DesiredApplication.Stopped()).To(BeTrue()) 644 }) 645 }) 646 }) 647 648 Context("when the manifest contains services", func() { 649 BeforeEach(func() { 650 manifestApps[0].Services = []string{"service_1", "service_2"} 651 fakeV2Actor.GetServiceInstancesByApplicationReturns([]v2action.ServiceInstance{ 652 {Name: "service_1", SpaceGUID: spaceGUID}, 653 {Name: "service_3", SpaceGUID: spaceGUID}, 654 }, v2action.Warnings{"some-service-warning-1"}, nil) 655 }) 656 657 Context("when retrieving services is successful", func() { 658 BeforeEach(func() { 659 fakeV2Actor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{Name: "service_2", SpaceGUID: spaceGUID}, v2action.Warnings{"some-service-warning-2"}, nil) 660 }) 661 662 It("sets DesiredServices", func() { 663 Expect(executeErr).ToNot(HaveOccurred()) 664 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "some-service-warning-1", "some-service-warning-2")) 665 Expect(firstConfig.DesiredServices).To(Equal(map[string]v2action.ServiceInstance{ 666 "service_1": v2action.ServiceInstance{Name: "service_1", SpaceGUID: spaceGUID}, 667 "service_2": v2action.ServiceInstance{Name: "service_2", SpaceGUID: spaceGUID}, 668 "service_3": v2action.ServiceInstance{Name: "service_3", SpaceGUID: spaceGUID}, 669 })) 670 671 Expect(fakeV2Actor.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1)) 672 673 inputServiceName, inputSpaceGUID := fakeV2Actor.GetServiceInstanceByNameAndSpaceArgsForCall(0) 674 Expect(inputServiceName).To(Equal("service_2")) 675 Expect(inputSpaceGUID).To(Equal(spaceGUID)) 676 }) 677 }) 678 679 Context("when retrieving services fails", func() { 680 var expectedErr error 681 682 BeforeEach(func() { 683 expectedErr = errors.New("po-tat-toe") 684 fakeV2Actor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{}, v2action.Warnings{"some-service-warning-2"}, expectedErr) 685 }) 686 687 It("returns the error and warnings", func() { 688 Expect(executeErr).To(MatchError(expectedErr)) 689 Expect(warnings).To(ConsistOf("some-service-warning-1", "some-service-warning-2")) 690 }) 691 }) 692 }) 693 694 Context("when no-route is set", func() { 695 BeforeEach(func() { 696 manifestApps[0].NoRoute = true 697 698 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 699 }) 700 701 It("should set NoRoute to true", func() { 702 Expect(executeErr).ToNot(HaveOccurred()) 703 Expect(warnings).To(BeEmpty()) 704 Expect(firstConfig.NoRoute).To(BeTrue()) 705 Expect(firstConfig.DesiredRoutes).To(BeEmpty()) 706 }) 707 708 It("should skip route generation", func() { 709 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(0)) 710 Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0)) 711 }) 712 }) 713 714 Context("when routes are defined", func() { 715 BeforeEach(func() { 716 manifestApps[0].Routes = []string{"route-1.private-domain.com", "route-2.private-domain.com"} 717 }) 718 719 Context("when retrieving the routes are successful", func() { 720 BeforeEach(func() { 721 // Assumes new routes 722 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 723 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{domain}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, nil) 724 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 725 }) 726 727 Context("when the --random-route flag is provided", func() { 728 BeforeEach(func() { 729 manifestApps[0].RandomRoute = true 730 }) 731 732 It("adds the new routes to the desired routes, and does not generate a random route", func() { 733 Expect(executeErr).ToNot(HaveOccurred()) 734 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "get-route-warnings", "get-route-warnings")) 735 Expect(firstConfig.DesiredRoutes).To(ConsistOf(v2action.Route{ 736 Domain: domain, 737 Host: "route-1", 738 SpaceGUID: spaceGUID, 739 }, v2action.Route{ 740 Domain: domain, 741 Host: "route-2", 742 SpaceGUID: spaceGUID, 743 })) 744 745 Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0)) 746 }) 747 }) 748 749 It("adds the new routes to the desired routes", func() { 750 Expect(executeErr).ToNot(HaveOccurred()) 751 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "get-route-warnings", "get-route-warnings")) 752 Expect(firstConfig.DesiredRoutes).To(ConsistOf(v2action.Route{ 753 Domain: domain, 754 Host: "route-1", 755 SpaceGUID: spaceGUID, 756 }, v2action.Route{ 757 Domain: domain, 758 Host: "route-2", 759 SpaceGUID: spaceGUID, 760 })) 761 }) 762 }) 763 764 Context("when retrieving the routes fails", func() { 765 var expectedErr error 766 BeforeEach(func() { 767 expectedErr = errors.New("dios mio") 768 // Assumes new routes 769 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 770 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{domain}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, expectedErr) 771 }) 772 773 It("returns errors and warnings", func() { 774 Expect(executeErr).To(MatchError(expectedErr)) 775 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2")) 776 }) 777 }) 778 }) 779 780 Context("when routes are not defined", func() { 781 var app v2action.Application 782 783 BeforeEach(func() { 784 app = v2action.Application{ 785 GUID: "some-app-guid", 786 Name: appName, 787 } 788 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 789 }) 790 791 Context("when the default route is mapped", func() { 792 var existingRoute v2action.Route 793 794 BeforeEach(func() { 795 existingRoute = v2action.Route{ 796 Domain: v2action.Domain{ 797 Name: "some-domain.com", 798 GUID: "some-domain-guid", 799 }, 800 Host: app.Name, 801 GUID: "route-guid", 802 SpaceGUID: spaceGUID, 803 } 804 fakeV2Actor.GetApplicationRoutesReturns([]v2action.Route{existingRoute}, v2action.Warnings{"app-route-warnings"}, nil) 805 }) 806 807 Context("when only the -d flag is provided", func() { 808 BeforeEach(func() { 809 manifestApps[0].Domain = "some-private-domain" 810 }) 811 812 Context("when the provided domain exists", func() { 813 BeforeEach(func() { 814 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 815 []v2action.Domain{domain}, 816 v2action.Warnings{"some-organization-domain-warning"}, 817 nil, 818 ) 819 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 820 }) 821 822 It("it uses the provided domain instead of the first shared domain", func() { 823 Expect(executeErr).ToNot(HaveOccurred()) 824 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings", "get-route-warnings")) 825 826 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 827 existingRoute, 828 v2action.Route{ 829 Domain: domain, 830 Host: appName, 831 SpaceGUID: spaceGUID, 832 }), 833 ) 834 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 835 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 836 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 837 Expect(orgGUIDArg).To(Equal(orgGUID)) 838 }) 839 }) 840 841 Context("when the provided domain does not exist", func() { 842 BeforeEach(func() { 843 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 844 []v2action.Domain{}, 845 v2action.Warnings{"some-organization-domain-warning"}, 846 nil, 847 ) 848 }) 849 850 It("returns an DomainNotFoundError", func() { 851 Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "some-private-domain"})) 852 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings")) 853 854 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 855 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 856 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 857 Expect(orgGUIDArg).To(Equal(orgGUID)) 858 }) 859 }) 860 }) 861 }) 862 863 Context("when the default route is not mapped to the app", func() { 864 Context("when only the -d flag is provided", func() { 865 BeforeEach(func() { 866 manifestApps[0].Domain = "some-private-domain" 867 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 868 }) 869 870 Context("when the provided domain exists", func() { 871 BeforeEach(func() { 872 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 873 []v2action.Domain{domain}, 874 v2action.Warnings{"some-organization-domain-warning"}, 875 nil, 876 ) 877 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 878 }) 879 880 It("it uses the provided domain instead of the first shared domain", func() { 881 Expect(executeErr).ToNot(HaveOccurred()) 882 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings", "get-route-warnings")) 883 884 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 885 v2action.Route{ 886 Domain: domain, 887 Host: appName, 888 SpaceGUID: spaceGUID, 889 }), 890 ) 891 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 892 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 893 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 894 Expect(orgGUIDArg).To(Equal(orgGUID)) 895 }) 896 }) 897 898 Context("when the provided domain does not exist", func() { 899 BeforeEach(func() { 900 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 901 []v2action.Domain{}, 902 v2action.Warnings{"some-organization-domain-warning"}, 903 nil, 904 ) 905 }) 906 907 It("returns an DomainNotFoundError", func() { 908 Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "some-private-domain"})) 909 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings")) 910 911 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 912 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 913 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 914 Expect(orgGUIDArg).To(Equal(orgGUID)) 915 }) 916 }) 917 }) 918 919 Context("when there are routes bound to the application", func() { 920 var existingRoute v2action.Route 921 922 BeforeEach(func() { 923 existingRoute = v2action.Route{ 924 Domain: v2action.Domain{ 925 Name: "some-domain.com", 926 GUID: "some-domain-guid", 927 }, 928 Host: app.Name, 929 GUID: "route-guid", 930 SpaceGUID: spaceGUID, 931 } 932 fakeV2Actor.GetApplicationRoutesReturns([]v2action.Route{existingRoute}, v2action.Warnings{"app-route-warnings"}, nil) 933 }) 934 935 It("does not bind any addition routes", func() { 936 Expect(executeErr).ToNot(HaveOccurred()) 937 Expect(warnings).To(ConsistOf("app-route-warnings")) 938 Expect(firstConfig.DesiredRoutes).To(ConsistOf(existingRoute)) 939 Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0)) 940 }) 941 }) 942 943 Context("when there are no routes bound to the application", func() { 944 BeforeEach(func() { 945 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 946 947 // Assumes new route 948 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 949 }) 950 951 It("adds the default route to desired routes", func() { 952 Expect(executeErr).ToNot(HaveOccurred()) 953 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "app-route-warnings", "get-route-warnings")) 954 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 955 v2action.Route{ 956 Domain: domain, 957 Host: appName, 958 SpaceGUID: spaceGUID, 959 })) 960 }) 961 }) 962 }) 963 }) 964 965 Context("when scanning for files", func() { 966 Context("given a directory", func() { 967 Context("when scanning is successful", func() { 968 var resources []sharedaction.Resource 969 970 BeforeEach(func() { 971 resources = []sharedaction.Resource{ 972 {Filename: "I am a file!"}, 973 {Filename: "I am not a file"}, 974 } 975 fakeSharedActor.GatherDirectoryResourcesReturns(resources, nil) 976 }) 977 978 It("sets the full resource list on the config", func() { 979 Expect(executeErr).ToNot(HaveOccurred()) 980 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 981 Expect(firstConfig.AllResources).To(Equal(actor.ConvertSharedResourcesToV2Resources(resources))) 982 Expect(firstConfig.Path).To(Equal(filesPath)) 983 Expect(firstConfig.Archive).To(BeFalse()) 984 985 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(1)) 986 Expect(fakeSharedActor.GatherDirectoryResourcesArgsForCall(0)).To(Equal(filesPath)) 987 }) 988 }) 989 990 Context("when scanning errors", func() { 991 var expectedErr error 992 993 BeforeEach(func() { 994 expectedErr = errors.New("dios mio") 995 fakeSharedActor.GatherDirectoryResourcesReturns(nil, expectedErr) 996 }) 997 998 It("returns the error and warnings", func() { 999 Expect(executeErr).To(MatchError(expectedErr)) 1000 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1001 }) 1002 }) 1003 }) 1004 1005 Context("given an archive", func() { 1006 var archive string 1007 1008 BeforeEach(func() { 1009 f, err := ioutil.TempFile("", "convert-to-application-configs-archive") 1010 Expect(err).ToNot(HaveOccurred()) 1011 archive = f.Name() 1012 Expect(f.Close()).ToNot(HaveOccurred()) 1013 1014 // The temp file created on OSX contains a symlink and needs to be evaluated. 1015 archive, err = filepath.EvalSymlinks(archive) 1016 Expect(err).ToNot(HaveOccurred()) 1017 1018 manifestApps[0].Path = archive 1019 }) 1020 1021 AfterEach(func() { 1022 Expect(os.RemoveAll(archive)).ToNot(HaveOccurred()) 1023 }) 1024 1025 Context("when scanning is successful", func() { 1026 var resources []sharedaction.Resource 1027 1028 BeforeEach(func() { 1029 resources = []sharedaction.Resource{ 1030 {Filename: "I am a file!"}, 1031 {Filename: "I am not a file"}, 1032 } 1033 fakeSharedActor.GatherArchiveResourcesReturns(resources, nil) 1034 }) 1035 1036 It("sets the full resource list on the config", func() { 1037 Expect(executeErr).ToNot(HaveOccurred()) 1038 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1039 Expect(firstConfig.AllResources).To(Equal(actor.ConvertSharedResourcesToV2Resources(resources))) 1040 Expect(firstConfig.Path).To(Equal(archive)) 1041 Expect(firstConfig.Archive).To(BeTrue()) 1042 1043 Expect(fakeSharedActor.GatherArchiveResourcesCallCount()).To(Equal(1)) 1044 Expect(fakeSharedActor.GatherArchiveResourcesArgsForCall(0)).To(Equal(archive)) 1045 }) 1046 }) 1047 1048 Context("when scanning errors", func() { 1049 var expectedErr error 1050 1051 BeforeEach(func() { 1052 expectedErr = errors.New("dios mio") 1053 fakeSharedActor.GatherArchiveResourcesReturns(nil, expectedErr) 1054 }) 1055 1056 It("returns the error and warnings", func() { 1057 Expect(executeErr).To(MatchError(expectedErr)) 1058 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1059 }) 1060 }) 1061 }) 1062 }) 1063 1064 Context("when a docker image is configured", func() { 1065 BeforeEach(func() { 1066 manifestApps[0].DockerImage = "some-docker-image-path" 1067 }) 1068 1069 It("sets the docker image on DesiredApplication and does not gather resources", func() { 1070 Expect(executeErr).ToNot(HaveOccurred()) 1071 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image-path")) 1072 1073 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(0)) 1074 }) 1075 }) 1076 1077 Context("when a droplet is provided", func() { 1078 BeforeEach(func() { 1079 manifestApps[0].DropletPath = filesPath 1080 }) 1081 1082 It("sets the droplet on DesiredApplication and does not gather resources", func() { 1083 Expect(executeErr).ToNot(HaveOccurred()) 1084 Expect(firstConfig.DropletPath).To(Equal(filesPath)) 1085 1086 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(0)) 1087 }) 1088 }) 1089 1090 Context("when buildpacks (plural) are provided", func() { 1091 BeforeEach(func() { 1092 manifestApps[0].Buildpacks = []string{ 1093 "some-buildpack-1", 1094 "some-buildpack-2", 1095 } 1096 }) 1097 1098 It("sets the buildpacks on DesiredApplication", func() { 1099 Expect(executeErr).ToNot(HaveOccurred()) 1100 Expect(len(firstConfig.DesiredApplication.Buildpacks)).To(Equal(2)) 1101 Expect(firstConfig.DesiredApplication.Buildpacks[0]).To(Equal("some-buildpack-1")) 1102 Expect(firstConfig.DesiredApplication.Buildpacks[1]).To(Equal("some-buildpack-2")) 1103 }) 1104 1105 Context("when the buildpacks are an empty array", func() { 1106 BeforeEach(func() { 1107 manifestApps[0].Buildpacks = []string{} 1108 }) 1109 1110 It("set the buildpacks on DesiredApplication to empty array", func() { 1111 Expect(executeErr).ToNot(HaveOccurred()) 1112 Expect(firstConfig.DesiredApplication.Buildpacks).To(Equal([]string{})) 1113 }) 1114 }) 1115 }) 1116 }) 1117 })