github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+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, 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 Expect(firstConfig.TargetedSpaceGUID).To(Equal(spaceGUID)) 219 220 Expect(fakeV2Actor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1)) 221 passedName, passedSpaceGUID := fakeV2Actor.GetApplicationByNameAndSpaceArgsForCall(0) 222 Expect(passedName).To(Equal(app.Name)) 223 Expect(passedSpaceGUID).To(Equal(spaceGUID)) 224 }) 225 226 It("sets the current routes", func() { 227 Expect(firstConfig.CurrentRoutes).To(ConsistOf(route)) 228 229 Expect(fakeV2Actor.GetApplicationRoutesCallCount()).To(Equal(1)) 230 Expect(fakeV2Actor.GetApplicationRoutesArgsForCall(0)).To(Equal(app.GUID)) 231 }) 232 233 It("sets the bound services", func() { 234 Expect(firstConfig.CurrentServices).To(Equal(map[string]v2action.ServiceInstance{ 235 "service-1": v2action.ServiceInstance{Name: "service-1", GUID: "service-instance-1"}, 236 "service-2": v2action.ServiceInstance{Name: "service-2", GUID: "service-instance-2"}, 237 })) 238 239 Expect(fakeV2Actor.GetServiceInstancesByApplicationCallCount()).To(Equal(1)) 240 Expect(fakeV2Actor.GetServiceInstancesByApplicationArgsForCall(0)).To(Equal("some-app-guid")) 241 }) 242 }) 243 244 Context("when retrieving the application's services errors", func() { 245 var expectedErr error 246 247 BeforeEach(func() { 248 expectedErr = errors.New("dios mio") 249 fakeV2Actor.GetServiceInstancesByApplicationReturns(nil, v2action.Warnings{"service-instance-warning-1", "service-instance-warning-2"}, expectedErr) 250 }) 251 252 It("returns the error and warnings", func() { 253 Expect(executeErr).To(MatchError(expectedErr)) 254 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings", "service-instance-warning-1", "service-instance-warning-2")) 255 }) 256 }) 257 258 Context("when the --random-route flag is provided", func() { 259 BeforeEach(func() { 260 manifestApps[0].RandomRoute = true 261 }) 262 263 It("does not generate a random route", func() { 264 Expect(executeErr).ToNot(HaveOccurred()) 265 Expect(warnings).To(ConsistOf( 266 "some-app-warning-1", 267 "some-app-warning-2", 268 "app-route-warnings", 269 )) 270 Expect(firstConfig.DesiredRoutes).To(ConsistOf(route)) 271 272 Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0)) 273 }) 274 }) 275 }) 276 277 Context("when there is not an existing route and no errors are encountered", func() { 278 BeforeEach(func() { 279 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 280 }) 281 282 Context("when the --random-route flag is provided", func() { 283 BeforeEach(func() { 284 manifestApps[0].RandomRoute = true 285 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 286 fakeRandomWordGenerator.RandomNounReturns("apple") 287 }) 288 289 It("appends a random route to the current route for desired routes", func() { 290 Expect(executeErr).ToNot(HaveOccurred()) 291 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings", "private-domain-warnings", "shared-domain-warnings")) 292 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 293 v2action.Route{ 294 Domain: domain, 295 SpaceGUID: spaceGUID, 296 Host: "some-app-striped-apple", 297 }, 298 )) 299 }) 300 }) 301 }) 302 303 Context("when retrieving the application's routes errors", func() { 304 var expectedErr error 305 306 BeforeEach(func() { 307 expectedErr = errors.New("dios mio") 308 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, expectedErr) 309 }) 310 311 It("returns the error and warnings", func() { 312 Expect(executeErr).To(MatchError(expectedErr)) 313 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "app-route-warnings")) 314 }) 315 }) 316 }) 317 318 Context("when the application does not exist", func() { 319 BeforeEach(func() { 320 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, v2action.Warnings{"some-app-warning-1", "some-app-warning-2"}, actionerror.ApplicationNotFoundError{}) 321 }) 322 323 It("creates a new application and sets it to the desired application", func() { 324 Expect(executeErr).ToNot(HaveOccurred()) 325 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "private-domain-warnings", "shared-domain-warnings")) 326 Expect(firstConfig.CurrentApplication).To(Equal(Application{Application: v2action.Application{}})) 327 Expect(firstConfig.DesiredApplication).To(Equal(Application{ 328 Application: v2action.Application{ 329 Name: appName, 330 SpaceGUID: spaceGUID, 331 }})) 332 Expect(firstConfig.TargetedSpaceGUID).To(Equal(spaceGUID)) 333 }) 334 335 Context("when the --random-route flag is provided", func() { 336 BeforeEach(func() { 337 manifestApps[0].RandomRoute = true 338 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 339 fakeRandomWordGenerator.RandomNounReturns("apple") 340 }) 341 342 It("appends a random route to the current route for desired routes", func() { 343 Expect(executeErr).ToNot(HaveOccurred()) 344 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "private-domain-warnings", "shared-domain-warnings")) 345 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 346 v2action.Route{ 347 Domain: domain, 348 SpaceGUID: spaceGUID, 349 Host: "some-app-striped-apple", 350 }, 351 )) 352 }) 353 354 Context("when the -d flag is provided", func() { 355 Context("when the domain is an http domain", func() { 356 var httpDomain v2action.Domain 357 358 BeforeEach(func() { 359 httpDomain = v2action.Domain{ 360 Name: "some-http-domain.com", 361 } 362 363 manifestApps[0].Domain = "some-http-domain.com" 364 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{httpDomain}, v2action.Warnings{"domain-warnings-1", "domain-warnings-2"}, nil) 365 fakeRandomWordGenerator.RandomAdjectiveReturns("striped") 366 fakeRandomWordGenerator.RandomNounReturns("apple") 367 }) 368 369 It("appends a random HTTP route to the desired routes", func() { 370 Expect(executeErr).ToNot(HaveOccurred()) 371 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "domain-warnings-1", "domain-warnings-2")) 372 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 373 v2action.Route{ 374 Host: "some-app-striped-apple", 375 Domain: httpDomain, 376 SpaceGUID: spaceGUID, 377 }, 378 )) 379 }) 380 }) 381 382 Context("when the domain is a tcp domain", func() { 383 var tcpDomain v2action.Domain 384 BeforeEach(func() { 385 tcpDomain = v2action.Domain{ 386 Name: "some-tcp-domain.com", 387 RouterGroupType: constant.TCPRouterGroup, 388 } 389 390 manifestApps[0].Domain = "some-tcp-domain.com" 391 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{tcpDomain}, v2action.Warnings{"domain-warnings-1", "domain-warnings-2"}, nil) 392 }) 393 394 It("appends a random TCP route to the desired routes", func() { 395 Expect(executeErr).ToNot(HaveOccurred()) 396 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2", "domain-warnings-1", "domain-warnings-2")) 397 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 398 v2action.Route{ 399 Domain: tcpDomain, 400 SpaceGUID: spaceGUID, 401 Port: types.NullInt{IsSet: false}, 402 }, 403 )) 404 }) 405 }) 406 }) 407 }) 408 }) 409 410 Context("when retrieving the application errors", func() { 411 var expectedErr error 412 413 BeforeEach(func() { 414 expectedErr = errors.New("dios mio") 415 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, v2action.Warnings{"some-app-warning-1", "some-app-warning-2"}, expectedErr) 416 }) 417 418 It("returns the error and warnings", func() { 419 Expect(executeErr).To(MatchError(expectedErr)) 420 Expect(warnings).To(ConsistOf("some-app-warning-1", "some-app-warning-2")) 421 }) 422 }) 423 424 Context("when overriding application properties", func() { 425 var stack v2action.Stack 426 427 Context("when the manifest contains all the properties", func() { 428 BeforeEach(func() { 429 manifestApps[0].Buildpack = types.FilteredString{IsSet: true, Value: "some-buildpack"} 430 manifestApps[0].Command = types.FilteredString{IsSet: true, Value: "some-command"} 431 manifestApps[0].DockerImage = "some-docker-image" 432 manifestApps[0].DockerUsername = "some-docker-username" 433 manifestApps[0].DockerPassword = "some-docker-password" 434 manifestApps[0].HealthCheckTimeout = 5 435 manifestApps[0].Instances = types.NullInt{Value: 1, IsSet: true} 436 manifestApps[0].DiskQuota = types.NullByteSizeInMb{Value: 2, IsSet: true} 437 manifestApps[0].Memory = types.NullByteSizeInMb{Value: 3, IsSet: true} 438 manifestApps[0].StackName = "some-stack" 439 manifestApps[0].EnvironmentVariables = map[string]string{ 440 "env1": "1", 441 "env3": "3", 442 } 443 444 stack = v2action.Stack{ 445 Name: "some-stack", 446 GUID: "some-stack-guid", 447 } 448 449 fakeV2Actor.GetStackByNameReturns(stack, v2action.Warnings{"some-stack-warning"}, nil) 450 }) 451 452 It("overrides the current application properties", func() { 453 Expect(warnings).To(ConsistOf("some-stack-warning", "private-domain-warnings", "shared-domain-warnings")) 454 455 Expect(firstConfig.DesiredApplication.Buildpack).To(Equal(types.FilteredString{IsSet: true, Value: "some-buildpack"})) 456 Expect(firstConfig.DesiredApplication.Command).To(Equal(types.FilteredString{IsSet: true, Value: "some-command"})) 457 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image")) 458 Expect(firstConfig.DesiredApplication.DockerCredentials.Username).To(Equal("some-docker-username")) 459 Expect(firstConfig.DesiredApplication.DockerCredentials.Password).To(Equal("some-docker-password")) 460 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 461 "env1": "1", 462 "env3": "3", 463 })) 464 Expect(firstConfig.DesiredApplication.HealthCheckTimeout).To(Equal(5)) 465 Expect(firstConfig.DesiredApplication.Instances).To(Equal(types.NullInt{Value: 1, IsSet: true})) 466 Expect(firstConfig.DesiredApplication.DiskQuota).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 2})) 467 Expect(firstConfig.DesiredApplication.Memory).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 3})) 468 Expect(firstConfig.DesiredApplication.StackGUID).To(Equal("some-stack-guid")) 469 Expect(firstConfig.DesiredApplication.Stack).To(Equal(stack)) 470 471 Expect(fakeV2Actor.GetStackByNameCallCount()).To(Equal(1)) 472 Expect(fakeV2Actor.GetStackByNameArgsForCall(0)).To(Equal("some-stack")) 473 }) 474 }) 475 476 Context("when the manifest does not contain any properties", func() { 477 BeforeEach(func() { 478 stack = v2action.Stack{ 479 Name: "some-stack", 480 GUID: "some-stack-guid", 481 } 482 fakeV2Actor.GetStackReturns(stack, nil, nil) 483 484 app := v2action.Application{ 485 Buildpack: types.FilteredString{IsSet: true, Value: "some-buildpack"}, 486 Command: types.FilteredString{IsSet: true, Value: "some-command"}, 487 DockerCredentials: ccv2.DockerCredentials{ 488 Username: "some-docker-username", 489 Password: "some-docker-password", 490 }, 491 DockerImage: "some-docker-image", 492 DiskQuota: types.NullByteSizeInMb{IsSet: true, Value: 2}, 493 EnvironmentVariables: map[string]string{ 494 "env2": "2", 495 "env3": "9", 496 }, 497 GUID: "some-app-guid", 498 HealthCheckHTTPEndpoint: "/some-endpoint", 499 HealthCheckTimeout: 5, 500 HealthCheckType: "port", 501 Instances: types.NullInt{Value: 3, IsSet: true}, 502 Memory: types.NullByteSizeInMb{IsSet: true, Value: 3}, 503 Name: appName, 504 StackGUID: stack.GUID, 505 } 506 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 507 }) 508 509 It("keeps the original app properties", func() { 510 Expect(firstConfig.DesiredApplication.Buildpack).To(Equal(types.FilteredString{IsSet: true, Value: "some-buildpack"})) 511 Expect(firstConfig.DesiredApplication.Command).To(Equal(types.FilteredString{IsSet: true, Value: "some-command"})) 512 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image")) 513 Expect(firstConfig.DesiredApplication.DockerCredentials.Username).To(Equal("some-docker-username")) 514 Expect(firstConfig.DesiredApplication.DockerCredentials.Password).To(Equal("some-docker-password")) 515 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 516 "env2": "2", 517 "env3": "9", 518 })) 519 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/some-endpoint")) 520 Expect(firstConfig.DesiredApplication.HealthCheckTimeout).To(Equal(5)) 521 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckPort)) 522 Expect(firstConfig.DesiredApplication.Instances).To(Equal(types.NullInt{Value: 3, IsSet: true})) 523 Expect(firstConfig.DesiredApplication.DiskQuota).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 2})) 524 Expect(firstConfig.DesiredApplication.Memory).To(Equal(types.NullByteSizeInMb{IsSet: true, Value: 3})) 525 Expect(firstConfig.DesiredApplication.StackGUID).To(Equal("some-stack-guid")) 526 Expect(firstConfig.DesiredApplication.Stack).To(Equal(stack)) 527 }) 528 }) 529 530 Context("when setting health check variables", func() { 531 Context("when setting the type to 'http'", func() { 532 BeforeEach(func() { 533 manifestApps[0].HealthCheckType = "http" 534 }) 535 536 Context("when the http health check endpoint is set", func() { 537 BeforeEach(func() { 538 manifestApps[0].HealthCheckHTTPEndpoint = "/some/endpoint" 539 }) 540 541 It("should overried the health check type and the endpoint should be set", func() { 542 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/some/endpoint")) 543 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckHTTP)) 544 }) 545 }) 546 547 Context("when the http health check endpoint is not set", func() { 548 It("should override the health check type and the endpoint should be defaulted to \"/\"", func() { 549 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(Equal("/")) 550 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckHTTP)) 551 }) 552 }) 553 }) 554 555 Context("when setting type to 'port'", func() { 556 BeforeEach(func() { 557 manifestApps[0].HealthCheckType = "port" 558 }) 559 560 It("should override the health check type and the endpoint should not be set", func() { 561 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 562 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckPort)) 563 }) 564 }) 565 566 Context("when setting type to 'process'", func() { 567 BeforeEach(func() { 568 manifestApps[0].HealthCheckType = "process" 569 }) 570 571 It("should override the health check type and the endpoint should not be set", func() { 572 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 573 Expect(firstConfig.DesiredApplication.HealthCheckType).To(Equal(constant.ApplicationHealthCheckProcess)) 574 }) 575 }) 576 577 Context("when type is unset", func() { 578 It("leaves the previously set values", func() { 579 Expect(firstConfig.DesiredApplication.HealthCheckHTTPEndpoint).To(BeEmpty()) 580 Expect(firstConfig.DesiredApplication.HealthCheckType).To(BeEmpty()) 581 }) 582 }) 583 }) 584 585 Context("when retrieving the stack errors", func() { 586 var expectedErr error 587 588 BeforeEach(func() { 589 manifestApps[0].StackName = "some-stack" 590 591 expectedErr = errors.New("potattototototototootot") 592 fakeV2Actor.GetStackByNameReturns(v2action.Stack{}, v2action.Warnings{"some-stack-warning"}, expectedErr) 593 }) 594 595 It("returns the error and warnings", func() { 596 Expect(executeErr).To(MatchError(expectedErr)) 597 Expect(warnings).To(ConsistOf("some-stack-warning")) 598 }) 599 }) 600 601 Context("when both the manifest and application contains environment variables", func() { 602 BeforeEach(func() { 603 manifestApps[0].EnvironmentVariables = map[string]string{ 604 "env1": "1", 605 "env3": "3", 606 } 607 608 app := v2action.Application{ 609 EnvironmentVariables: map[string]string{ 610 "env2": "2", 611 "env3": "9", 612 }, 613 } 614 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 615 }) 616 617 It("adds/overrides the existing environment variables", func() { 618 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(Equal(map[string]string{ 619 "env1": "1", 620 "env2": "2", 621 "env3": "3", 622 })) 623 624 // Does not modify original set of env vars 625 Expect(firstConfig.CurrentApplication.EnvironmentVariables).To(Equal(map[string]string{ 626 "env2": "2", 627 "env3": "9", 628 })) 629 }) 630 }) 631 632 Context("when neither the manifest or the application contains environment variables", func() { 633 It("leaves the EnvironmentVariables as nil", func() { 634 Expect(firstConfig.DesiredApplication.EnvironmentVariables).To(BeNil()) 635 }) 636 }) 637 638 Context("when no-start is set to true", func() { 639 BeforeEach(func() { 640 noStart = true 641 }) 642 643 It("sets the desired app state to stopped", func() { 644 Expect(executeErr).ToNot(HaveOccurred()) 645 Expect(firstConfig.DesiredApplication.Stopped()).To(BeTrue()) 646 }) 647 }) 648 }) 649 650 Context("when the manifest contains services", func() { 651 BeforeEach(func() { 652 manifestApps[0].Services = []string{"service_1", "service_2"} 653 fakeV2Actor.GetServiceInstancesByApplicationReturns([]v2action.ServiceInstance{ 654 {Name: "service_1", SpaceGUID: spaceGUID}, 655 {Name: "service_3", SpaceGUID: spaceGUID}, 656 }, v2action.Warnings{"some-service-warning-1"}, nil) 657 }) 658 659 Context("when retrieving services is successful", func() { 660 BeforeEach(func() { 661 fakeV2Actor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{Name: "service_2", SpaceGUID: spaceGUID}, v2action.Warnings{"some-service-warning-2"}, nil) 662 }) 663 664 It("sets DesiredServices", func() { 665 Expect(executeErr).ToNot(HaveOccurred()) 666 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "some-service-warning-1", "some-service-warning-2")) 667 Expect(firstConfig.DesiredServices).To(Equal(map[string]v2action.ServiceInstance{ 668 "service_1": v2action.ServiceInstance{Name: "service_1", SpaceGUID: spaceGUID}, 669 "service_2": v2action.ServiceInstance{Name: "service_2", SpaceGUID: spaceGUID}, 670 "service_3": v2action.ServiceInstance{Name: "service_3", SpaceGUID: spaceGUID}, 671 })) 672 673 Expect(fakeV2Actor.GetServiceInstanceByNameAndSpaceCallCount()).To(Equal(1)) 674 675 inputServiceName, inputSpaceGUID := fakeV2Actor.GetServiceInstanceByNameAndSpaceArgsForCall(0) 676 Expect(inputServiceName).To(Equal("service_2")) 677 Expect(inputSpaceGUID).To(Equal(spaceGUID)) 678 }) 679 }) 680 681 Context("when retrieving services fails", func() { 682 var expectedErr error 683 684 BeforeEach(func() { 685 expectedErr = errors.New("po-tat-toe") 686 fakeV2Actor.GetServiceInstanceByNameAndSpaceReturns(v2action.ServiceInstance{}, v2action.Warnings{"some-service-warning-2"}, expectedErr) 687 }) 688 689 It("returns the error and warnings", func() { 690 Expect(executeErr).To(MatchError(expectedErr)) 691 Expect(warnings).To(ConsistOf("some-service-warning-1", "some-service-warning-2")) 692 }) 693 }) 694 }) 695 696 Context("when no-route is set", func() { 697 BeforeEach(func() { 698 manifestApps[0].NoRoute = true 699 700 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 701 }) 702 703 It("should set NoRoute to true", func() { 704 Expect(executeErr).ToNot(HaveOccurred()) 705 Expect(warnings).To(BeEmpty()) 706 Expect(firstConfig.NoRoute).To(BeTrue()) 707 Expect(firstConfig.DesiredRoutes).To(BeEmpty()) 708 }) 709 710 It("should skip route generation", func() { 711 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(0)) 712 Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0)) 713 }) 714 }) 715 716 Context("when routes are defined", func() { 717 BeforeEach(func() { 718 manifestApps[0].Routes = []string{"route-1.private-domain.com", "route-2.private-domain.com"} 719 }) 720 721 Context("when retrieving the routes are successful", func() { 722 BeforeEach(func() { 723 // Assumes new routes 724 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 725 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{domain}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, nil) 726 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 727 }) 728 729 Context("when the --random-route flag is provided", func() { 730 BeforeEach(func() { 731 manifestApps[0].RandomRoute = true 732 }) 733 734 It("adds the new routes to the desired routes, and does not generate a random route", func() { 735 Expect(executeErr).ToNot(HaveOccurred()) 736 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "get-route-warnings", "get-route-warnings")) 737 Expect(firstConfig.DesiredRoutes).To(ConsistOf(v2action.Route{ 738 Domain: domain, 739 Host: "route-1", 740 SpaceGUID: spaceGUID, 741 }, v2action.Route{ 742 Domain: domain, 743 Host: "route-2", 744 SpaceGUID: spaceGUID, 745 })) 746 747 Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0)) 748 }) 749 }) 750 751 It("adds the new routes to the desired routes", func() { 752 Expect(executeErr).ToNot(HaveOccurred()) 753 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "get-route-warnings", "get-route-warnings")) 754 Expect(firstConfig.DesiredRoutes).To(ConsistOf(v2action.Route{ 755 Domain: domain, 756 Host: "route-1", 757 SpaceGUID: spaceGUID, 758 }, v2action.Route{ 759 Domain: domain, 760 Host: "route-2", 761 SpaceGUID: spaceGUID, 762 })) 763 }) 764 }) 765 766 Context("when retrieving the routes fails", func() { 767 var expectedErr error 768 BeforeEach(func() { 769 expectedErr = errors.New("dios mio") 770 // Assumes new routes 771 fakeV2Actor.GetApplicationByNameAndSpaceReturns(v2action.Application{}, nil, actionerror.ApplicationNotFoundError{}) 772 fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{domain}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, expectedErr) 773 }) 774 775 It("returns errors and warnings", func() { 776 Expect(executeErr).To(MatchError(expectedErr)) 777 Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2")) 778 }) 779 }) 780 }) 781 782 Context("when routes are not defined", func() { 783 var app v2action.Application 784 785 BeforeEach(func() { 786 app = v2action.Application{ 787 GUID: "some-app-guid", 788 Name: appName, 789 } 790 fakeV2Actor.GetApplicationByNameAndSpaceReturns(app, nil, nil) 791 }) 792 793 Context("when the default route is mapped", func() { 794 var existingRoute v2action.Route 795 796 BeforeEach(func() { 797 existingRoute = v2action.Route{ 798 Domain: v2action.Domain{ 799 Name: "some-domain.com", 800 GUID: "some-domain-guid", 801 }, 802 Host: app.Name, 803 GUID: "route-guid", 804 SpaceGUID: spaceGUID, 805 } 806 fakeV2Actor.GetApplicationRoutesReturns([]v2action.Route{existingRoute}, v2action.Warnings{"app-route-warnings"}, nil) 807 }) 808 809 Context("when only the -d flag is provided", func() { 810 BeforeEach(func() { 811 manifestApps[0].Domain = "some-private-domain" 812 }) 813 814 Context("when the provided domain exists", func() { 815 BeforeEach(func() { 816 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 817 []v2action.Domain{domain}, 818 v2action.Warnings{"some-organization-domain-warning"}, 819 nil, 820 ) 821 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 822 }) 823 824 It("it uses the provided domain instead of the first shared domain", func() { 825 Expect(executeErr).ToNot(HaveOccurred()) 826 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings", "get-route-warnings")) 827 828 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 829 existingRoute, 830 v2action.Route{ 831 Domain: domain, 832 Host: appName, 833 SpaceGUID: spaceGUID, 834 }), 835 ) 836 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 837 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 838 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 839 Expect(orgGUIDArg).To(Equal(orgGUID)) 840 }) 841 }) 842 843 Context("when the provided domain does not exist", func() { 844 BeforeEach(func() { 845 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 846 []v2action.Domain{}, 847 v2action.Warnings{"some-organization-domain-warning"}, 848 nil, 849 ) 850 }) 851 852 It("returns an DomainNotFoundError", func() { 853 Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "some-private-domain"})) 854 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings")) 855 856 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 857 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 858 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 859 Expect(orgGUIDArg).To(Equal(orgGUID)) 860 }) 861 }) 862 }) 863 }) 864 865 Context("when the default route is not mapped to the app", func() { 866 Context("when only the -d flag is provided", func() { 867 BeforeEach(func() { 868 manifestApps[0].Domain = "some-private-domain" 869 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 870 }) 871 872 Context("when the provided domain exists", func() { 873 BeforeEach(func() { 874 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 875 []v2action.Domain{domain}, 876 v2action.Warnings{"some-organization-domain-warning"}, 877 nil, 878 ) 879 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 880 }) 881 882 It("it uses the provided domain instead of the first shared domain", func() { 883 Expect(executeErr).ToNot(HaveOccurred()) 884 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings", "get-route-warnings")) 885 886 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 887 v2action.Route{ 888 Domain: domain, 889 Host: appName, 890 SpaceGUID: spaceGUID, 891 }), 892 ) 893 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 894 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 895 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 896 Expect(orgGUIDArg).To(Equal(orgGUID)) 897 }) 898 }) 899 900 Context("when the provided domain does not exist", func() { 901 BeforeEach(func() { 902 fakeV2Actor.GetDomainsByNameAndOrganizationReturns( 903 []v2action.Domain{}, 904 v2action.Warnings{"some-organization-domain-warning"}, 905 nil, 906 ) 907 }) 908 909 It("returns an DomainNotFoundError", func() { 910 Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "some-private-domain"})) 911 Expect(warnings).To(ConsistOf("some-organization-domain-warning", "app-route-warnings")) 912 913 Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1)) 914 domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0) 915 Expect(domainNamesArg).To(Equal([]string{"some-private-domain"})) 916 Expect(orgGUIDArg).To(Equal(orgGUID)) 917 }) 918 }) 919 }) 920 921 Context("when there are routes bound to the application", func() { 922 var existingRoute v2action.Route 923 924 BeforeEach(func() { 925 existingRoute = v2action.Route{ 926 Domain: v2action.Domain{ 927 Name: "some-domain.com", 928 GUID: "some-domain-guid", 929 }, 930 Host: app.Name, 931 GUID: "route-guid", 932 SpaceGUID: spaceGUID, 933 } 934 fakeV2Actor.GetApplicationRoutesReturns([]v2action.Route{existingRoute}, v2action.Warnings{"app-route-warnings"}, nil) 935 }) 936 937 It("does not bind any addition routes", func() { 938 Expect(executeErr).ToNot(HaveOccurred()) 939 Expect(warnings).To(ConsistOf("app-route-warnings")) 940 Expect(firstConfig.DesiredRoutes).To(ConsistOf(existingRoute)) 941 Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0)) 942 }) 943 }) 944 945 Context("when there are no routes bound to the application", func() { 946 BeforeEach(func() { 947 fakeV2Actor.GetApplicationRoutesReturns(nil, v2action.Warnings{"app-route-warnings"}, nil) 948 949 // Assumes new route 950 fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{}) 951 }) 952 953 It("adds the default route to desired routes", func() { 954 Expect(executeErr).ToNot(HaveOccurred()) 955 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "app-route-warnings", "get-route-warnings")) 956 Expect(firstConfig.DesiredRoutes).To(ConsistOf( 957 v2action.Route{ 958 Domain: domain, 959 Host: appName, 960 SpaceGUID: spaceGUID, 961 })) 962 }) 963 }) 964 }) 965 }) 966 967 Context("when scanning for files", func() { 968 Context("given a directory", func() { 969 Context("when scanning is successful", func() { 970 var resources []sharedaction.Resource 971 972 BeforeEach(func() { 973 resources = []sharedaction.Resource{ 974 {Filename: "I am a file!"}, 975 {Filename: "I am not a file"}, 976 } 977 fakeSharedActor.GatherDirectoryResourcesReturns(resources, nil) 978 }) 979 980 It("sets the full resource list on the config", func() { 981 Expect(executeErr).ToNot(HaveOccurred()) 982 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 983 Expect(firstConfig.AllResources).To(Equal(actor.ConvertSharedResourcesToV2Resources(resources))) 984 Expect(firstConfig.Path).To(Equal(filesPath)) 985 Expect(firstConfig.Archive).To(BeFalse()) 986 987 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(1)) 988 Expect(fakeSharedActor.GatherDirectoryResourcesArgsForCall(0)).To(Equal(filesPath)) 989 }) 990 }) 991 992 Context("when scanning errors", func() { 993 var expectedErr error 994 995 BeforeEach(func() { 996 expectedErr = errors.New("dios mio") 997 fakeSharedActor.GatherDirectoryResourcesReturns(nil, expectedErr) 998 }) 999 1000 It("returns the error and warnings", func() { 1001 Expect(executeErr).To(MatchError(expectedErr)) 1002 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1003 }) 1004 }) 1005 }) 1006 1007 Context("given an archive", func() { 1008 var archive string 1009 1010 BeforeEach(func() { 1011 f, err := ioutil.TempFile("", "convert-to-application-configs-archive") 1012 Expect(err).ToNot(HaveOccurred()) 1013 archive = f.Name() 1014 Expect(f.Close()).ToNot(HaveOccurred()) 1015 1016 // The temp file created on OSX contains a symlink and needs to be evaluated. 1017 archive, err = filepath.EvalSymlinks(archive) 1018 Expect(err).ToNot(HaveOccurred()) 1019 1020 manifestApps[0].Path = archive 1021 }) 1022 1023 AfterEach(func() { 1024 Expect(os.RemoveAll(archive)).ToNot(HaveOccurred()) 1025 }) 1026 1027 Context("when scanning is successful", func() { 1028 var resources []sharedaction.Resource 1029 1030 BeforeEach(func() { 1031 resources = []sharedaction.Resource{ 1032 {Filename: "I am a file!"}, 1033 {Filename: "I am not a file"}, 1034 } 1035 fakeSharedActor.GatherArchiveResourcesReturns(resources, nil) 1036 }) 1037 1038 It("sets the full resource list on the config", func() { 1039 Expect(executeErr).ToNot(HaveOccurred()) 1040 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1041 Expect(firstConfig.AllResources).To(Equal(actor.ConvertSharedResourcesToV2Resources(resources))) 1042 Expect(firstConfig.Path).To(Equal(archive)) 1043 Expect(firstConfig.Archive).To(BeTrue()) 1044 1045 Expect(fakeSharedActor.GatherArchiveResourcesCallCount()).To(Equal(1)) 1046 Expect(fakeSharedActor.GatherArchiveResourcesArgsForCall(0)).To(Equal(archive)) 1047 }) 1048 }) 1049 1050 Context("when scanning errors", func() { 1051 var expectedErr error 1052 1053 BeforeEach(func() { 1054 expectedErr = errors.New("dios mio") 1055 fakeSharedActor.GatherArchiveResourcesReturns(nil, expectedErr) 1056 }) 1057 1058 It("returns the error and warnings", func() { 1059 Expect(executeErr).To(MatchError(expectedErr)) 1060 Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings")) 1061 }) 1062 }) 1063 }) 1064 }) 1065 1066 Context("when a docker image is configured", func() { 1067 BeforeEach(func() { 1068 manifestApps[0].DockerImage = "some-docker-image-path" 1069 }) 1070 1071 It("sets the docker image on DesiredApplication and does not gather resources", func() { 1072 Expect(executeErr).ToNot(HaveOccurred()) 1073 Expect(firstConfig.DesiredApplication.DockerImage).To(Equal("some-docker-image-path")) 1074 1075 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(0)) 1076 }) 1077 }) 1078 }) 1079 })