github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/commands/create_app_manifest_test.go (about) 1 package commands_test 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/cli/cf/commandregistry" 7 "code.cloudfoundry.org/cli/cf/commands" 8 "code.cloudfoundry.org/cli/cf/configuration/coreconfig" 9 "code.cloudfoundry.org/cli/cf/flags" 10 "code.cloudfoundry.org/cli/cf/manifest/manifestfakes" 11 "code.cloudfoundry.org/cli/cf/models" 12 "code.cloudfoundry.org/cli/cf/requirements" 13 "code.cloudfoundry.org/cli/cf/requirements/requirementsfakes" 14 15 "code.cloudfoundry.org/cli/cf/api/apifakes" 16 "code.cloudfoundry.org/cli/cf/api/stacks/stacksfakes" 17 testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration" 18 testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal" 19 20 "os" 21 22 . "code.cloudfoundry.org/cli/util/testhelpers/matchers" 23 . "github.com/onsi/ginkgo" 24 . "github.com/onsi/gomega" 25 ) 26 27 var _ = Describe("CreateAppManifest", func() { 28 var ( 29 ui *testterm.FakeUI 30 configRepo coreconfig.Repository 31 appSummaryRepo *apifakes.FakeAppSummaryRepository 32 stackRepo *stacksfakes.FakeStackRepository 33 34 cmd commandregistry.Command 35 deps commandregistry.Dependency 36 factory *requirementsfakes.FakeFactory 37 flagContext flags.FlagContext 38 39 loginRequirement requirements.Requirement 40 targetedSpaceRequirement requirements.Requirement 41 applicationRequirement *requirementsfakes.FakeApplicationRequirement 42 43 fakeManifest *manifestfakes.FakeApp 44 ) 45 46 BeforeEach(func() { 47 ui = &testterm.FakeUI{} 48 configRepo = testconfig.NewRepositoryWithDefaults() 49 appSummaryRepo = new(apifakes.FakeAppSummaryRepository) 50 repoLocator := deps.RepoLocator.SetAppSummaryRepository(appSummaryRepo) 51 stackRepo = new(stacksfakes.FakeStackRepository) 52 repoLocator = repoLocator.SetStackRepository(stackRepo) 53 54 fakeManifest = new(manifestfakes.FakeApp) 55 56 deps = commandregistry.Dependency{ 57 UI: ui, 58 Config: configRepo, 59 RepoLocator: repoLocator, 60 AppManifest: fakeManifest, 61 } 62 63 cmd = &commands.CreateAppManifest{} 64 cmd.SetDependency(deps, false) 65 66 flagContext = flags.NewFlagContext(cmd.MetaData().Flags) 67 factory = new(requirementsfakes.FakeFactory) 68 69 loginRequirement = &passingRequirement{Name: "login-requirement"} 70 factory.NewLoginRequirementReturns(loginRequirement) 71 72 targetedSpaceRequirement = &passingRequirement{Name: "targeted-space-requirement"} 73 factory.NewTargetedSpaceRequirementReturns(targetedSpaceRequirement) 74 75 applicationRequirement = new(requirementsfakes.FakeApplicationRequirement) 76 application := models.Application{} 77 application.GUID = "app-guid" 78 applicationRequirement.GetApplicationReturns(application) 79 factory.NewApplicationRequirementReturns(applicationRequirement) 80 }) 81 82 Describe("Requirements", func() { 83 Context("when not provided exactly one arg", func() { 84 BeforeEach(func() { 85 flagContext.Parse("app-name", "extra-arg") 86 }) 87 88 It("fails with usage", func() { 89 _, err := cmd.Requirements(factory, flagContext) 90 Expect(err).To(HaveOccurred()) 91 Expect(ui.Outputs()).To(ContainSubstrings( 92 []string{"FAILED"}, 93 []string{"Incorrect Usage. Requires APP_NAME as argument"}, 94 )) 95 }) 96 }) 97 98 Context("when provided exactly one arg", func() { 99 BeforeEach(func() { 100 flagContext.Parse("app-name") 101 }) 102 103 It("returns a LoginRequirement", func() { 104 actualRequirements, err := cmd.Requirements(factory, flagContext) 105 Expect(err).NotTo(HaveOccurred()) 106 Expect(actualRequirements).To(ContainElement(loginRequirement)) 107 }) 108 109 It("returns an ApplicationRequirement", func() { 110 actualRequirements, err := cmd.Requirements(factory, flagContext) 111 Expect(err).NotTo(HaveOccurred()) 112 Expect(actualRequirements).To(ContainElement(applicationRequirement)) 113 }) 114 115 It("returns a TargetedSpaceRequirement", func() { 116 actualRequirements, err := cmd.Requirements(factory, flagContext) 117 Expect(err).NotTo(HaveOccurred()) 118 Expect(actualRequirements).To(ContainElement(targetedSpaceRequirement)) 119 }) 120 }) 121 }) 122 123 Describe("Execute", func() { 124 var ( 125 application models.Application 126 runCLIErr error 127 ) 128 129 BeforeEach(func() { 130 err := flagContext.Parse("app-name") 131 Expect(err).NotTo(HaveOccurred()) 132 cmd.Requirements(factory, flagContext) 133 134 application = models.Application{} 135 application.Name = "app-name" 136 }) 137 138 JustBeforeEach(func() { 139 runCLIErr = cmd.Execute(flagContext) 140 }) 141 142 AfterEach(func() { 143 os.Remove("app-name_manifest.yml") 144 }) 145 146 Context("when there is an app summary", func() { 147 BeforeEach(func() { 148 appSummaryRepo.GetSummaryReturns(application, nil) 149 }) 150 151 It("tries to get the app summary", func() { 152 Expect(runCLIErr).NotTo(HaveOccurred()) 153 Expect(appSummaryRepo.GetSummaryCallCount()).To(Equal(1)) 154 }) 155 }) 156 157 Context("when there is an error getting the app summary", func() { 158 BeforeEach(func() { 159 appSummaryRepo.GetSummaryReturns(models.Application{}, errors.New("get-summary-err")) 160 }) 161 162 It("prints an error", func() { 163 Expect(runCLIErr).To(HaveOccurred()) 164 Expect(runCLIErr.Error()).To(Equal("Error getting application summary: get-summary-err")) 165 }) 166 }) 167 168 Context("when getting the app summary succeeds", func() { 169 BeforeEach(func() { 170 application.Memory = 1024 171 application.InstanceCount = 2 172 application.StackGUID = "the-stack-guid" 173 appSummaryRepo.GetSummaryReturns(application, nil) 174 }) 175 176 It("sets memory", func() { 177 Expect(runCLIErr).NotTo(HaveOccurred()) 178 Expect(fakeManifest.MemoryCallCount()).To(Equal(1)) 179 name, memory := fakeManifest.MemoryArgsForCall(0) 180 Expect(name).To(Equal("app-name")) 181 Expect(memory).To(Equal(int64(1024))) 182 }) 183 184 It("sets instances", func() { 185 Expect(runCLIErr).NotTo(HaveOccurred()) 186 Expect(fakeManifest.InstancesCallCount()).To(Equal(1)) 187 name, instances := fakeManifest.InstancesArgsForCall(0) 188 Expect(name).To(Equal("app-name")) 189 Expect(instances).To(Equal(2)) 190 }) 191 192 Context("when there are app ports specified", func() { 193 BeforeEach(func() { 194 application.AppPorts = []int{1111, 2222} 195 appSummaryRepo.GetSummaryReturns(application, nil) 196 }) 197 198 It("sets app ports", func() { 199 Expect(runCLIErr).NotTo(HaveOccurred()) 200 Expect(fakeManifest.AppPortsCallCount()).To(Equal(1)) 201 name, appPorts := fakeManifest.AppPortsArgsForCall(0) 202 Expect(name).To(Equal("app-name")) 203 Expect(appPorts).To(Equal([]int{1111, 2222})) 204 }) 205 }) 206 207 Context("when app ports are not specified", func() { 208 It("does not set app ports", func() { 209 Expect(runCLIErr).NotTo(HaveOccurred()) 210 Expect(fakeManifest.AppPortsCallCount()).To(Equal(0)) 211 }) 212 }) 213 214 It("tries to get stacks", func() { 215 Expect(runCLIErr).NotTo(HaveOccurred()) 216 Expect(stackRepo.FindByGUIDCallCount()).To(Equal(1)) 217 Expect(stackRepo.FindByGUIDArgsForCall(0)).To(Equal("the-stack-guid")) 218 }) 219 220 Context("when getting stacks succeeds", func() { 221 BeforeEach(func() { 222 stackRepo.FindByGUIDReturns(models.Stack{ 223 GUID: "the-stack-guid", 224 Name: "the-stack-name", 225 }, nil) 226 }) 227 228 It("sets the stacks", func() { 229 Expect(runCLIErr).NotTo(HaveOccurred()) 230 Expect(fakeManifest.StackCallCount()).To(Equal(1)) 231 name, stackName := fakeManifest.StackArgsForCall(0) 232 Expect(name).To(Equal("app-name")) 233 Expect(stackName).To(Equal("the-stack-name")) 234 }) 235 }) 236 237 Context("when getting stacks fails", func() { 238 BeforeEach(func() { 239 stackRepo.FindByGUIDReturns(models.Stack{}, errors.New("find-by-guid-err")) 240 }) 241 242 It("fails with error", func() { 243 Expect(runCLIErr).To(HaveOccurred()) 244 Expect(runCLIErr.Error()).To(Equal("Error retrieving stack: find-by-guid-err")) 245 }) 246 }) 247 248 It("tries to save the manifest", func() { 249 Expect(runCLIErr).NotTo(HaveOccurred()) 250 Expect(fakeManifest.SaveCallCount()).To(Equal(1)) 251 }) 252 253 Context("when saving the manifest succeeds", func() { 254 BeforeEach(func() { 255 fakeManifest.SaveReturns(nil) 256 }) 257 258 It("says OK", func() { 259 Expect(runCLIErr).NotTo(HaveOccurred()) 260 Expect(ui.Outputs()).To(ContainSubstrings( 261 []string{"OK"}, 262 []string{"Manifest file created successfully at ./app-name_manifest.yml"}, 263 )) 264 }) 265 }) 266 267 Context("when saving the manifest fails", func() { 268 BeforeEach(func() { 269 fakeManifest.SaveReturns(errors.New("save-err")) 270 }) 271 272 It("fails with error", func() { 273 Expect(runCLIErr).To(HaveOccurred()) 274 Expect(runCLIErr.Error()).To(Equal("Error creating manifest file: save-err")) 275 }) 276 }) 277 278 Context("when the app has a command", func() { 279 BeforeEach(func() { 280 application.Command = "app-command" 281 appSummaryRepo.GetSummaryReturns(application, nil) 282 }) 283 284 It("sets the start command", func() { 285 Expect(runCLIErr).NotTo(HaveOccurred()) 286 Expect(fakeManifest.StartCommandCallCount()).To(Equal(1)) 287 name, command := fakeManifest.StartCommandArgsForCall(0) 288 Expect(name).To(Equal("app-name")) 289 Expect(command).To(Equal("app-command")) 290 }) 291 }) 292 293 Context("when the app has a buildpack", func() { 294 BeforeEach(func() { 295 application.BuildpackURL = "buildpack" 296 appSummaryRepo.GetSummaryReturns(application, nil) 297 }) 298 299 It("sets the buildpack", func() { 300 Expect(runCLIErr).NotTo(HaveOccurred()) 301 Expect(fakeManifest.BuildpackURLCallCount()).To(Equal(1)) 302 name, buildpack := fakeManifest.BuildpackURLArgsForCall(0) 303 Expect(name).To(Equal("app-name")) 304 Expect(buildpack).To(Equal("buildpack")) 305 }) 306 }) 307 308 Context("when the app has services", func() { 309 BeforeEach(func() { 310 application.Services = []models.ServicePlanSummary{ 311 { 312 Name: "sp1-name", 313 }, 314 { 315 Name: "sp2-name", 316 }, 317 } 318 appSummaryRepo.GetSummaryReturns(application, nil) 319 }) 320 321 It("sets the services", func() { 322 Expect(runCLIErr).NotTo(HaveOccurred()) 323 Expect(fakeManifest.ServiceCallCount()).To(Equal(2)) 324 325 name, service := fakeManifest.ServiceArgsForCall(0) 326 Expect(name).To(Equal("app-name")) 327 Expect(service).To(Equal("sp1-name")) 328 329 name, service = fakeManifest.ServiceArgsForCall(1) 330 Expect(name).To(Equal("app-name")) 331 Expect(service).To(Equal("sp2-name")) 332 }) 333 }) 334 335 Context("when the app has a health check timeout", func() { 336 BeforeEach(func() { 337 application.HealthCheckTimeout = 5 338 appSummaryRepo.GetSummaryReturns(application, nil) 339 }) 340 341 It("sets the health check timeout", func() { 342 Expect(runCLIErr).NotTo(HaveOccurred()) 343 Expect(fakeManifest.HealthCheckTimeoutCallCount()).To(Equal(1)) 344 name, timeout := fakeManifest.HealthCheckTimeoutArgsForCall(0) 345 Expect(name).To(Equal("app-name")) 346 Expect(timeout).To(Equal(5)) 347 }) 348 }) 349 350 Context("when the app has environment vars", func() { 351 BeforeEach(func() { 352 application.EnvironmentVars = map[string]interface{}{ 353 "float64-key": float64(5), 354 "bool-key": true, 355 "string-key": "string", 356 } 357 appSummaryRepo.GetSummaryReturns(application, nil) 358 }) 359 360 It("sets the env vars", func() { 361 Expect(runCLIErr).NotTo(HaveOccurred()) 362 Expect(fakeManifest.EnvironmentVarsCallCount()).To(Equal(3)) 363 actuals := map[string]interface{}{} 364 365 for i := 0; i < 3; i++ { 366 name, k, v := fakeManifest.EnvironmentVarsArgsForCall(i) 367 Expect(name).To(Equal("app-name")) 368 actuals[k] = v 369 } 370 371 Expect(actuals["float64-key"]).To(Equal("5")) 372 Expect(actuals["bool-key"]).To(Equal("true")) 373 Expect(actuals["string-key"]).To(Equal("string")) 374 }) 375 }) 376 377 Context("when the app has an environment var of an unsupported type", func() { 378 BeforeEach(func() { 379 application.EnvironmentVars = map[string]interface{}{ 380 "key": int(1), 381 } 382 appSummaryRepo.GetSummaryReturns(application, nil) 383 }) 384 385 It("fails with error", func() { 386 Expect(runCLIErr).To(HaveOccurred()) 387 Expect(runCLIErr.Error()).To(Equal("Failed to create manifest, unable to parse environment variable: key")) 388 }) 389 }) 390 391 Context("when the app has routes", func() { 392 BeforeEach(func() { 393 application.Routes = []models.RouteSummary{ 394 { 395 Host: "route-1-host", 396 Domain: models.DomainFields{ 397 Name: "http-domain", 398 }, 399 Path: "path", 400 Port: 0, 401 }, 402 { 403 Host: "", 404 Domain: models.DomainFields{ 405 Name: "tcp-domain", 406 }, 407 Path: "", 408 Port: 123, 409 }, 410 } 411 appSummaryRepo.GetSummaryReturns(application, nil) 412 }) 413 414 It("sets the domains", func() { 415 Expect(runCLIErr).NotTo(HaveOccurred()) 416 Expect(fakeManifest.RouteCallCount()).To(Equal(2)) 417 418 name, host, domainName, path, port := fakeManifest.RouteArgsForCall(0) 419 Expect(name).To(Equal("app-name")) 420 Expect(host).To(Equal("route-1-host")) 421 Expect(domainName).To(Equal("http-domain")) 422 Expect(path).To(Equal("path")) 423 Expect(port).To(Equal(0)) 424 425 name, host, domainName, path, port = fakeManifest.RouteArgsForCall(1) 426 Expect(name).To(Equal("app-name")) 427 Expect(host).To(Equal("")) 428 Expect(domainName).To(Equal("tcp-domain")) 429 Expect(path).To(Equal("")) 430 Expect(port).To(Equal(123)) 431 }) 432 }) 433 434 Context("when the app has a disk quota", func() { 435 BeforeEach(func() { 436 application.DiskQuota = 1024 437 appSummaryRepo.GetSummaryReturns(application, nil) 438 }) 439 440 It("sets the disk quota", func() { 441 Expect(runCLIErr).NotTo(HaveOccurred()) 442 Expect(fakeManifest.DiskQuotaCallCount()).To(Equal(1)) 443 name, quota := fakeManifest.DiskQuotaArgsForCall(0) 444 Expect(name).To(Equal("app-name")) 445 Expect(quota).To(Equal(int64(1024))) 446 }) 447 }) 448 449 Context("when the app has health check type", func() { 450 Context("when the health check type is port", func() { 451 BeforeEach(func() { 452 application.HealthCheckType = "port" 453 appSummaryRepo.GetSummaryReturns(application, nil) 454 }) 455 456 It("does not set the health check type nor the endpoint", func() { 457 Expect(runCLIErr).NotTo(HaveOccurred()) 458 459 Expect(fakeManifest.HealthCheckTypeCallCount()).To(Equal(0)) 460 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(0)) 461 }) 462 }) 463 464 Context("when the health check type is process", func() { 465 BeforeEach(func() { 466 application.HealthCheckType = "process" 467 appSummaryRepo.GetSummaryReturns(application, nil) 468 }) 469 470 It("sets the health check type but not the endpoint", func() { 471 Expect(runCLIErr).NotTo(HaveOccurred()) 472 473 Expect(fakeManifest.HealthCheckTypeCallCount()).To(Equal(1)) 474 name, healthCheckType := fakeManifest.HealthCheckTypeArgsForCall(0) 475 Expect(name).To(Equal("app-name")) 476 Expect(healthCheckType).To(Equal("process")) 477 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(0)) 478 }) 479 }) 480 481 Context("when the health check type is none", func() { 482 BeforeEach(func() { 483 application.HealthCheckType = "none" 484 appSummaryRepo.GetSummaryReturns(application, nil) 485 }) 486 487 It("sets the health check type but not the endpoint", func() { 488 Expect(runCLIErr).NotTo(HaveOccurred()) 489 490 Expect(fakeManifest.HealthCheckTypeCallCount()).To(Equal(1)) 491 name, healthCheckType := fakeManifest.HealthCheckTypeArgsForCall(0) 492 Expect(name).To(Equal("app-name")) 493 Expect(healthCheckType).To(Equal("none")) 494 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(0)) 495 }) 496 }) 497 498 Context("when the health check type is http", func() { 499 BeforeEach(func() { 500 application.HealthCheckType = "http" 501 appSummaryRepo.GetSummaryReturns(application, nil) 502 }) 503 504 It("sets the health check type", func() { 505 Expect(runCLIErr).NotTo(HaveOccurred()) 506 507 Expect(fakeManifest.HealthCheckTypeCallCount()).To(Equal(1)) 508 name, healthCheckType := fakeManifest.HealthCheckTypeArgsForCall(0) 509 Expect(name).To(Equal("app-name")) 510 Expect(healthCheckType).To(Equal("http")) 511 }) 512 513 Context("when the health check endpoint is the empty string", func() { 514 BeforeEach(func() { 515 application.HealthCheckHTTPEndpoint = "" 516 appSummaryRepo.GetSummaryReturns(application, nil) 517 }) 518 519 It("does not set the health check endpoint", func() { 520 Expect(runCLIErr).NotTo(HaveOccurred()) 521 522 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(0)) 523 }) 524 }) 525 526 Context("when the health check endpoint is /", func() { 527 BeforeEach(func() { 528 application.HealthCheckHTTPEndpoint = "/" 529 appSummaryRepo.GetSummaryReturns(application, nil) 530 }) 531 532 It("does not set the health check endpoint", func() { 533 Expect(runCLIErr).NotTo(HaveOccurred()) 534 535 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(0)) 536 }) 537 }) 538 539 Context("when the health check endpoint is not /", func() { 540 BeforeEach(func() { 541 application.HealthCheckHTTPEndpoint = "/some-endpoint" 542 appSummaryRepo.GetSummaryReturns(application, nil) 543 }) 544 545 It("sets the health check endpoint", func() { 546 Expect(runCLIErr).NotTo(HaveOccurred()) 547 548 Expect(fakeManifest.HealthCheckHTTPEndpointCallCount()).To(Equal(1)) 549 name, healthCheckHTTPEndpoint := fakeManifest.HealthCheckHTTPEndpointArgsForCall(0) 550 Expect(name).To(Equal("app-name")) 551 Expect(healthCheckHTTPEndpoint).To(Equal("/some-endpoint")) 552 }) 553 }) 554 }) 555 }) 556 }) 557 }) 558 })