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