github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/command/v2/push_command_test.go (about) 1 package v2_test 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "regexp" 9 "time" 10 11 "code.cloudfoundry.org/cli/actor/actionerror" 12 "code.cloudfoundry.org/cli/actor/pushaction" 13 "code.cloudfoundry.org/cli/actor/v2action" 14 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant" 15 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 16 "code.cloudfoundry.org/cli/command/commandfakes" 17 "code.cloudfoundry.org/cli/command/flag" 18 "code.cloudfoundry.org/cli/command/translatableerror" 19 . "code.cloudfoundry.org/cli/command/v2" 20 "code.cloudfoundry.org/cli/command/v2/v2fakes" 21 "code.cloudfoundry.org/cli/types" 22 "code.cloudfoundry.org/cli/util/configv3" 23 "code.cloudfoundry.org/cli/util/manifest" 24 "code.cloudfoundry.org/cli/util/ui" 25 26 "github.com/cloudfoundry/bosh-cli/director/template" 27 . "github.com/onsi/ginkgo" 28 . "github.com/onsi/ginkgo/extensions/table" 29 . "github.com/onsi/gomega" 30 . "github.com/onsi/gomega/gbytes" 31 ) 32 33 var _ = Describe("push Command", func() { 34 var ( 35 cmd V2PushCommand 36 testUI *ui.UI 37 fakeConfig *commandfakes.FakeConfig 38 fakeSharedActor *commandfakes.FakeSharedActor 39 fakeActor *v2fakes.FakeV2PushActor 40 fakeRestartActor *v2fakes.FakeRestartActor 41 fakeProgressBar *v2fakes.FakeProgressBar 42 input *Buffer 43 binaryName string 44 45 appName string 46 executeErr error 47 pwd string 48 ) 49 50 BeforeEach(func() { 51 input = NewBuffer() 52 testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) 53 fakeConfig = new(commandfakes.FakeConfig) 54 fakeSharedActor = new(commandfakes.FakeSharedActor) 55 fakeActor = new(v2fakes.FakeV2PushActor) 56 fakeRestartActor = new(v2fakes.FakeRestartActor) 57 fakeProgressBar = new(v2fakes.FakeProgressBar) 58 59 cmd = V2PushCommand{ 60 UI: testUI, 61 Config: fakeConfig, 62 SharedActor: fakeSharedActor, 63 Actor: fakeActor, 64 RestartActor: fakeRestartActor, 65 ProgressBar: fakeProgressBar, 66 } 67 68 appName = "some-app" 69 cmd.OptionalArgs.AppName = appName 70 binaryName = "faceman" 71 fakeConfig.BinaryNameReturns(binaryName) 72 73 var err error 74 pwd, err = os.Getwd() 75 Expect(err).ToNot(HaveOccurred()) 76 }) 77 78 Context("Execute", func() { 79 JustBeforeEach(func() { 80 executeErr = cmd.Execute(nil) 81 }) 82 83 Context("when the mutiple buildpacks are provided, and the API version is below the mutiple buildpacks minimum", func() { 84 BeforeEach(func() { 85 fakeActor.CloudControllerV3APIVersionReturns("3.1.0") 86 cmd.Buildpacks = []string{"some-buildpack", "some-other-buildpack"} 87 }) 88 89 It("returns a MinimumAPIVersionNotMetError", func() { 90 Expect(executeErr).To(MatchError(translatableerror.MinimumAPIVersionNotMetError{ 91 Command: "Multiple option '-b'", 92 CurrentVersion: "3.1.0", 93 MinimumVersion: ccversion.MinVersionManifestBuildpacksV3, 94 })) 95 }) 96 }) 97 98 Context("when the droplet flag is passed and the API version is below the minimum", func() { 99 BeforeEach(func() { 100 fakeActor.CloudControllerV2APIVersionReturns("2.6.1") 101 cmd.DropletPath = "some-droplet-path" 102 }) 103 104 It("returns a MinimumAPIVersionNotMetError", func() { 105 Expect(executeErr).To(MatchError(translatableerror.MinimumAPIVersionNotMetError{ 106 Command: "Option '--droplet'", 107 CurrentVersion: "2.6.1", 108 MinimumVersion: ccversion.MinVersionDropletUploadV2, 109 })) 110 }) 111 }) 112 113 Context("when checking target fails", func() { 114 BeforeEach(func() { 115 fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName}) 116 }) 117 118 It("returns an error", func() { 119 Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName})) 120 121 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 122 checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 123 Expect(checkTargetedOrg).To(BeTrue()) 124 Expect(checkTargetedSpace).To(BeTrue()) 125 }) 126 }) 127 128 Context("when the user is logged in, and org and space are targeted", func() { 129 BeforeEach(func() { 130 fakeConfig.HasTargetedOrganizationReturns(true) 131 fakeConfig.TargetedOrganizationReturns(configv3.Organization{GUID: "some-org-guid", Name: "some-org"}) 132 fakeConfig.HasTargetedSpaceReturns(true) 133 fakeConfig.TargetedSpaceReturns(configv3.Space{GUID: "some-space-guid", Name: "some-space"}) 134 fakeConfig.CurrentUserReturns(configv3.User{Name: "some-user"}, nil) 135 }) 136 137 Context("when the push settings are valid", func() { 138 var appManifests []manifest.Application 139 140 BeforeEach(func() { 141 appManifests = []manifest.Application{ 142 { 143 Name: appName, 144 Path: pwd, 145 }, 146 } 147 fakeActor.MergeAndValidateSettingsAndManifestsReturns(appManifests, nil) 148 }) 149 150 Context("when buildpacks (plural) is provided in the manifest and the API version is below the minimum", func() { 151 BeforeEach(func() { 152 appManifests = []manifest.Application{ 153 { 154 Name: appName, 155 Path: pwd, 156 Buildpacks: []string{"ruby-buildpack", "java-buildpack"}, 157 }, 158 } 159 160 fakeActor.MergeAndValidateSettingsAndManifestsReturns(appManifests, nil) 161 fakeActor.CloudControllerV3APIVersionReturns("3.13.0") 162 }) 163 164 It("returns a MinimumAPIVersionNotMetError", func() { 165 Expect(executeErr).To(MatchError(translatableerror.MinimumAPIVersionNotMetError{ 166 Command: "'buildpacks' in manifest", 167 CurrentVersion: "3.13.0", 168 MinimumVersion: ccversion.MinVersionManifestBuildpacksV3, 169 })) 170 }) 171 172 }) 173 174 Context("when the settings can be converted to a valid config", func() { 175 var appConfigs []pushaction.ApplicationConfig 176 177 BeforeEach(func() { 178 appConfigs = []pushaction.ApplicationConfig{ 179 { 180 CurrentApplication: pushaction.Application{Application: v2action.Application{Name: appName, State: constant.ApplicationStarted}}, 181 DesiredApplication: pushaction.Application{Application: v2action.Application{Name: appName}}, 182 CurrentRoutes: []v2action.Route{ 183 {Host: "route1", Domain: v2action.Domain{Name: "example.com"}}, 184 {Host: "route2", Domain: v2action.Domain{Name: "example.com"}}, 185 }, 186 DesiredRoutes: []v2action.Route{ 187 {Host: "route3", Domain: v2action.Domain{Name: "example.com"}}, 188 {Host: "route4", Domain: v2action.Domain{Name: "example.com"}}, 189 }, 190 TargetedSpaceGUID: "some-space-guid", 191 Path: pwd, 192 }, 193 } 194 fakeActor.ConvertToApplicationConfigsReturns(appConfigs, pushaction.Warnings{"some-config-warnings"}, nil) 195 }) 196 197 Context("when the apply is successful", func() { 198 var updatedConfig pushaction.ApplicationConfig 199 200 BeforeEach(func() { 201 fakeActor.ApplyStub = func(_ pushaction.ApplicationConfig, _ pushaction.ProgressBar) (<-chan pushaction.ApplicationConfig, <-chan pushaction.Event, <-chan pushaction.Warnings, <-chan error) { 202 configStream := make(chan pushaction.ApplicationConfig, 1) 203 eventStream := make(chan pushaction.Event) 204 warningsStream := make(chan pushaction.Warnings) 205 errorStream := make(chan error) 206 207 updatedConfig = pushaction.ApplicationConfig{ 208 CurrentApplication: pushaction.Application{Application: v2action.Application{Name: appName, GUID: "some-app-guid"}}, 209 DesiredApplication: pushaction.Application{Application: v2action.Application{Name: appName, GUID: "some-app-guid"}}, 210 TargetedSpaceGUID: "some-space-guid", 211 Path: pwd, 212 } 213 214 go func() { 215 defer GinkgoRecover() 216 217 Eventually(eventStream).Should(BeSent(pushaction.SettingUpApplication)) 218 Eventually(eventStream).Should(BeSent(pushaction.CreatedApplication)) 219 Eventually(eventStream).Should(BeSent(pushaction.UpdatedApplication)) 220 Eventually(eventStream).Should(BeSent(pushaction.CreatingAndMappingRoutes)) 221 Eventually(eventStream).Should(BeSent(pushaction.CreatedRoutes)) 222 Eventually(eventStream).Should(BeSent(pushaction.BoundRoutes)) 223 Eventually(eventStream).Should(BeSent(pushaction.UnmappingRoutes)) 224 Eventually(eventStream).Should(BeSent(pushaction.ConfiguringServices)) 225 Eventually(eventStream).Should(BeSent(pushaction.BoundServices)) 226 Eventually(eventStream).Should(BeSent(pushaction.ResourceMatching)) 227 Eventually(eventStream).Should(BeSent(pushaction.UploadingApplication)) 228 Eventually(eventStream).Should(BeSent(pushaction.CreatingArchive)) 229 Eventually(eventStream).Should(BeSent(pushaction.UploadingApplicationWithArchive)) 230 Eventually(fakeProgressBar.ReadyCallCount).Should(Equal(1)) 231 Eventually(eventStream).Should(BeSent(pushaction.RetryUpload)) 232 Eventually(eventStream).Should(BeSent(pushaction.UploadWithArchiveComplete)) 233 Eventually(fakeProgressBar.CompleteCallCount).Should(Equal(1)) 234 Eventually(configStream).Should(BeSent(updatedConfig)) 235 Eventually(eventStream).Should(BeSent(pushaction.Complete)) 236 Eventually(warningsStream).Should(BeSent(pushaction.Warnings{"apply-1", "apply-2"})) 237 close(configStream) 238 close(eventStream) 239 close(warningsStream) 240 close(errorStream) 241 }() 242 243 return configStream, eventStream, warningsStream, errorStream 244 } 245 246 fakeRestartActor.RestartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) { 247 messages := make(chan *v2action.LogMessage) 248 logErrs := make(chan error) 249 appState := make(chan v2action.ApplicationStateChange) 250 warnings := make(chan string) 251 errs := make(chan error) 252 253 go func() { 254 messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1") 255 messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1") 256 appState <- v2action.ApplicationStateStopping 257 appState <- v2action.ApplicationStateStaging 258 appState <- v2action.ApplicationStateStarting 259 close(messages) 260 close(logErrs) 261 close(appState) 262 close(warnings) 263 close(errs) 264 }() 265 266 return messages, logErrs, appState, warnings, errs 267 } 268 269 applicationSummary := v2action.ApplicationSummary{ 270 Application: v2action.Application{ 271 DetectedBuildpack: types.FilteredString{IsSet: true, Value: "some-buildpack"}, 272 DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"}, 273 GUID: "some-app-guid", 274 Instances: types.NullInt{Value: 3, IsSet: true}, 275 Memory: types.NullByteSizeInMb{IsSet: true, Value: 128}, 276 Name: appName, 277 PackageUpdatedAt: time.Unix(0, 0), 278 State: "STARTED", 279 }, 280 Stack: v2action.Stack{ 281 Name: "potatos", 282 }, 283 Routes: []v2action.Route{ 284 { 285 Host: "banana", 286 Domain: v2action.Domain{ 287 Name: "fruit.com", 288 }, 289 Path: "/hi", 290 }, 291 { 292 Domain: v2action.Domain{ 293 Name: "foobar.com", 294 }, 295 Port: types.NullInt{IsSet: true, Value: 13}, 296 }, 297 }, 298 } 299 warnings := []string{"app-summary-warning"} 300 301 applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{{State: "RUNNING"}} 302 303 fakeRestartActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil) 304 }) 305 306 Context("when no manifest is provided", func() { 307 It("passes through the command line flags", func() { 308 Expect(executeErr).ToNot(HaveOccurred()) 309 310 Expect(fakeActor.MergeAndValidateSettingsAndManifestsCallCount()).To(Equal(1)) 311 cmdSettings, _ := fakeActor.MergeAndValidateSettingsAndManifestsArgsForCall(0) 312 Expect(cmdSettings).To(Equal(pushaction.CommandLineSettings{ 313 Name: appName, 314 CurrentDirectory: pwd, 315 })) 316 }) 317 }) 318 319 Context("when a manifest is provided", func() { 320 var ( 321 tmpDir string 322 providedPath string 323 324 originalDir string 325 ) 326 327 BeforeEach(func() { 328 var err error 329 tmpDir, err = ioutil.TempDir("", "push-command-test") 330 Expect(err).ToNot(HaveOccurred()) 331 332 // OS X uses weird symlinks that causes problems for some tests 333 tmpDir, err = filepath.EvalSymlinks(tmpDir) 334 Expect(err).ToNot(HaveOccurred()) 335 336 originalDir, err = os.Getwd() 337 Expect(err).ToNot(HaveOccurred()) 338 339 cmd.OptionalArgs.AppName = "" 340 }) 341 342 AfterEach(func() { 343 Expect(os.Chdir(originalDir)).ToNot(HaveOccurred()) 344 Expect(os.RemoveAll(tmpDir)).ToNot(HaveOccurred()) 345 }) 346 347 Context("via a manifest.yml in the current directory", func() { 348 var expectedApps []manifest.Application 349 350 BeforeEach(func() { 351 err := os.Chdir(tmpDir) 352 Expect(err).ToNot(HaveOccurred()) 353 354 providedPath = filepath.Join(tmpDir, "manifest.yml") 355 err = ioutil.WriteFile(providedPath, []byte("some manifest file"), 0666) 356 Expect(err).ToNot(HaveOccurred()) 357 358 expectedApps = []manifest.Application{{Name: "some-app"}, {Name: "some-other-app"}} 359 fakeActor.ReadManifestReturns(expectedApps, nil, nil) 360 }) 361 362 Context("when reading the manifest file is successful", func() { 363 It("merges app manifest and flags", func() { 364 Expect(executeErr).ToNot(HaveOccurred()) 365 366 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 367 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(providedPath)) 368 369 Expect(fakeActor.MergeAndValidateSettingsAndManifestsCallCount()).To(Equal(1)) 370 cmdSettings, manifestApps := fakeActor.MergeAndValidateSettingsAndManifestsArgsForCall(0) 371 Expect(cmdSettings).To(Equal(pushaction.CommandLineSettings{ 372 CurrentDirectory: tmpDir, 373 })) 374 Expect(manifestApps).To(Equal(expectedApps)) 375 }) 376 377 It("outputs corresponding flavor text", func() { 378 Expect(executeErr).ToNot(HaveOccurred()) 379 380 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 381 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(providedPath))) 382 }) 383 }) 384 385 Context("when reading manifest file errors", func() { 386 var expectedErr error 387 388 BeforeEach(func() { 389 expectedErr = errors.New("I am an error!!!") 390 391 fakeActor.ReadManifestReturns(nil, nil, expectedErr) 392 }) 393 394 It("returns the error", func() { 395 Expect(executeErr).To(MatchError(expectedErr)) 396 }) 397 }) 398 399 Context("when --no-manifest is specified", func() { 400 BeforeEach(func() { 401 cmd.NoManifest = true 402 }) 403 404 It("ignores the manifest file", func() { 405 Expect(executeErr).ToNot(HaveOccurred()) 406 407 Expect(fakeActor.MergeAndValidateSettingsAndManifestsCallCount()).To(Equal(1)) 408 cmdSettings, manifestApps := fakeActor.MergeAndValidateSettingsAndManifestsArgsForCall(0) 409 Expect(cmdSettings).To(Equal(pushaction.CommandLineSettings{ 410 CurrentDirectory: tmpDir, 411 })) 412 Expect(manifestApps).To(BeNil()) 413 }) 414 }) 415 416 }) 417 418 Context("via a manifest.yaml in the current directory", func() { 419 BeforeEach(func() { 420 err := os.Chdir(tmpDir) 421 Expect(err).ToNot(HaveOccurred()) 422 423 providedPath = filepath.Join(tmpDir, "manifest.yaml") 424 err = ioutil.WriteFile(providedPath, []byte("some manifest file"), 0666) 425 Expect(err).ToNot(HaveOccurred()) 426 }) 427 428 It("should read the manifest.yml", func() { 429 Expect(executeErr).ToNot(HaveOccurred()) 430 431 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 432 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(providedPath)) 433 }) 434 }) 435 436 Context("via the -f flag", func() { 437 Context("given a path with filename 'manifest.yml'", func() { 438 BeforeEach(func() { 439 providedPath = filepath.Join(tmpDir, "manifest.yml") 440 }) 441 442 Context("when the manifest.yml file does not exist", func() { 443 BeforeEach(func() { 444 cmd.PathToManifest = flag.PathWithExistenceCheck(providedPath) 445 }) 446 447 It("returns an error", func() { 448 Expect(os.IsNotExist(executeErr)).To(BeTrue()) 449 450 Expect(testUI.Out).ToNot(Say("Pushing from manifest")) 451 Expect(testUI.Out).ToNot(Say("Using manifest file")) 452 453 Expect(fakeActor.ReadManifestCallCount()).To(Equal(0)) 454 }) 455 }) 456 457 Context("when the manifest.yml file exists", func() { 458 BeforeEach(func() { 459 err := ioutil.WriteFile(providedPath, []byte(`key: "value"`), 0666) 460 Expect(err).ToNot(HaveOccurred()) 461 462 cmd.PathToManifest = flag.PathWithExistenceCheck(providedPath) 463 }) 464 465 It("should read the manifest.yml file and outputs corresponding flavor text", func() { 466 Expect(executeErr).ToNot(HaveOccurred()) 467 468 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 469 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(providedPath))) 470 471 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 472 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(providedPath)) 473 }) 474 475 Context("variable interpolation", func() { 476 Context("vars file only", func() { 477 Context("when a vars file is also provided", func() { 478 var providedVarsFilePath string 479 480 BeforeEach(func() { 481 providedVarsFilePath = filepath.Join(tmpDir, "vars-file.yml") 482 cmd.VarsFilePaths = []flag.PathWithExistenceCheck{flag.PathWithExistenceCheck(providedVarsFilePath)} 483 }) 484 485 It("should read the vars-file.yml file and replace the variables in the manifest.yml file", func() { 486 Expect(executeErr).ToNot(HaveOccurred()) 487 488 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 489 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(providedPath))) 490 491 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 492 manifest, varsFiles, vars := fakeActor.ReadManifestArgsForCall(0) 493 Expect(manifest).To(Equal(providedPath)) 494 Expect(varsFiles).To(Equal([]string{providedVarsFilePath})) 495 Expect(vars).To(BeEmpty()) 496 }) 497 }) 498 499 Context("when multiple vars files are provided", func() { 500 var ( 501 firstProvidedVarsFilePath string 502 secondProvidedVarsFilePath string 503 ) 504 505 BeforeEach(func() { 506 firstProvidedVarsFilePath = filepath.Join(tmpDir, "vars-file-1.yml") 507 firstVarsFile := flag.PathWithExistenceCheck(firstProvidedVarsFilePath) 508 509 secondProvidedVarsFilePath = filepath.Join(tmpDir, "vars-file-2.yml") 510 secondVarsFile := flag.PathWithExistenceCheck(secondProvidedVarsFilePath) 511 cmd.VarsFilePaths = []flag.PathWithExistenceCheck{firstVarsFile, secondVarsFile} 512 }) 513 514 It("should read the vars-file.yml file and replace the variables in the manifest.yml file", func() { 515 Expect(executeErr).ToNot(HaveOccurred()) 516 517 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 518 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(providedPath))) 519 520 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 521 manifest, varsFiles, vars := fakeActor.ReadManifestArgsForCall(0) 522 Expect(manifest).To(Equal(providedPath)) 523 Expect(varsFiles).To(Equal([]string{firstProvidedVarsFilePath, secondProvidedVarsFilePath})) 524 Expect(vars).To(BeEmpty()) 525 }) 526 }) 527 }) 528 529 Context("vars flag only", func() { 530 var vars []template.VarKV 531 532 BeforeEach(func() { 533 vars = []template.VarKV{ 534 {Name: "some-var", Value: "some-value"}, 535 {Name: "another-var", Value: 1}, 536 } 537 538 cmd.Vars = vars 539 }) 540 541 It("should read the vars and pass only the vars array to ReadManifest", func() { 542 Expect(executeErr).ToNot(HaveOccurred()) 543 544 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 545 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(providedPath))) 546 547 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 548 manifest, varsFiles, vars := fakeActor.ReadManifestArgsForCall(0) 549 Expect(manifest).To(Equal(providedPath)) 550 Expect(varsFiles).To(BeEmpty()) 551 Expect(vars).To(ConsistOf([]template.VarKV{ 552 {Name: "some-var", Value: "some-value"}, 553 {Name: "another-var", Value: 1}, 554 })) 555 }) 556 }) 557 }) 558 }) 559 }) 560 561 Context("given a path that is a directory", func() { 562 563 var ( 564 ymlFile string 565 yamlFile string 566 ) 567 568 BeforeEach(func() { 569 providedPath = tmpDir 570 cmd.PathToManifest = flag.PathWithExistenceCheck(providedPath) 571 }) 572 573 Context("when the directory does not contain a 'manifest.y{a}ml' file", func() { 574 It("returns an error", func() { 575 Expect(executeErr).To(MatchError(translatableerror.ManifestFileNotFoundInDirectoryError{PathToManifest: providedPath})) 576 Expect(testUI.Out).ToNot(Say("Pushing from manifest")) 577 Expect(testUI.Out).ToNot(Say("Using manifest file")) 578 579 Expect(fakeActor.ReadManifestCallCount()).To(Equal(0)) 580 }) 581 }) 582 583 Context("when the directory contains a 'manifest.yml' file", func() { 584 BeforeEach(func() { 585 ymlFile = filepath.Join(providedPath, "manifest.yml") 586 err := ioutil.WriteFile(ymlFile, []byte(`key: "value"`), 0666) 587 Expect(err).ToNot(HaveOccurred()) 588 }) 589 590 It("should read the manifest.yml file and outputs corresponding flavor text", func() { 591 Expect(executeErr).ToNot(HaveOccurred()) 592 593 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 594 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(ymlFile))) 595 596 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 597 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(ymlFile)) 598 }) 599 }) 600 601 Context("when the directory contains a 'manifest.yaml' file", func() { 602 BeforeEach(func() { 603 yamlFile = filepath.Join(providedPath, "manifest.yaml") 604 err := ioutil.WriteFile(yamlFile, []byte(`key: "value"`), 0666) 605 Expect(err).ToNot(HaveOccurred()) 606 }) 607 608 It("should read the manifest.yaml file and outputs corresponding flavor text", func() { 609 Expect(executeErr).ToNot(HaveOccurred()) 610 611 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 612 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(yamlFile))) 613 614 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 615 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(yamlFile)) 616 }) 617 }) 618 619 Context("when the directory contains both a 'manifest.yml' and 'manifest.yaml' file", func() { 620 BeforeEach(func() { 621 ymlFile = filepath.Join(providedPath, "manifest.yml") 622 err := ioutil.WriteFile(ymlFile, []byte(`key: "value"`), 0666) 623 Expect(err).ToNot(HaveOccurred()) 624 625 yamlFile = filepath.Join(providedPath, "manifest.yaml") 626 err = ioutil.WriteFile(yamlFile, []byte(`key: "value"`), 0666) 627 Expect(err).ToNot(HaveOccurred()) 628 }) 629 630 It("should read the manifest.yml file and outputs corresponding flavor text", func() { 631 Expect(executeErr).ToNot(HaveOccurred()) 632 633 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 634 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(ymlFile))) 635 636 Expect(fakeActor.ReadManifestCallCount()).To(Equal(1)) 637 Expect(fakeActor.ReadManifestArgsForCall(0)).To(Equal(ymlFile)) 638 }) 639 }) 640 }) 641 }) 642 }) 643 644 Context("when an app name and manifest are provided", func() { 645 var ( 646 tmpDir string 647 pathToManifest string 648 649 originalDir string 650 ) 651 652 BeforeEach(func() { 653 var err error 654 tmpDir, err = ioutil.TempDir("", "push-command-test") 655 Expect(err).ToNot(HaveOccurred()) 656 657 // OS X uses weird symlinks that causes problems for some tests 658 tmpDir, err = filepath.EvalSymlinks(tmpDir) 659 Expect(err).ToNot(HaveOccurred()) 660 661 pathToManifest = filepath.Join(tmpDir, "manifest.yml") 662 err = ioutil.WriteFile(pathToManifest, []byte("some manfiest file"), 0666) 663 Expect(err).ToNot(HaveOccurred()) 664 665 originalDir, err = os.Getwd() 666 Expect(err).ToNot(HaveOccurred()) 667 668 err = os.Chdir(tmpDir) 669 Expect(err).ToNot(HaveOccurred()) 670 }) 671 672 AfterEach(func() { 673 Expect(os.Chdir(originalDir)).ToNot(HaveOccurred()) 674 Expect(os.RemoveAll(tmpDir)).ToNot(HaveOccurred()) 675 }) 676 677 It("outputs corresponding flavor text", func() { 678 Expect(executeErr).ToNot(HaveOccurred()) 679 680 Expect(testUI.Out).To(Say("Pushing from manifest to org some-org / space some-space as some-user\\.\\.\\.")) 681 Expect(testUI.Out).To(Say("Using manifest file %s", regexp.QuoteMeta(pathToManifest))) 682 }) 683 }) 684 685 It("converts the manifests to app configs and outputs config warnings", func() { 686 Expect(executeErr).ToNot(HaveOccurred()) 687 688 Expect(testUI.Err).To(Say("some-config-warnings")) 689 690 Expect(fakeActor.ConvertToApplicationConfigsCallCount()).To(Equal(1)) 691 orgGUID, spaceGUID, noStart, manifests := fakeActor.ConvertToApplicationConfigsArgsForCall(0) 692 Expect(orgGUID).To(Equal("some-org-guid")) 693 Expect(spaceGUID).To(Equal("some-space-guid")) 694 Expect(noStart).To(BeFalse()) 695 Expect(manifests).To(Equal(appManifests)) 696 }) 697 698 It("outputs flavor text prior to generating app configuration", func() { 699 Expect(executeErr).ToNot(HaveOccurred()) 700 Expect(testUI.Out).To(Say("Pushing app %s to org some-org / space some-space as some-user", appName)) 701 Expect(testUI.Out).To(Say("Getting app info\\.\\.\\.")) 702 }) 703 704 It("applies each of the application configurations", func() { 705 Expect(executeErr).ToNot(HaveOccurred()) 706 707 Expect(fakeActor.ApplyCallCount()).To(Equal(1)) 708 config, progressBar := fakeActor.ApplyArgsForCall(0) 709 Expect(config).To(Equal(appConfigs[0])) 710 Expect(progressBar).To(Equal(fakeProgressBar)) 711 }) 712 713 It("display diff of changes", func() { 714 Expect(executeErr).ToNot(HaveOccurred()) 715 716 Expect(testUI.Out).To(Say("\\s+name:\\s+%s", appName)) 717 Expect(testUI.Out).To(Say("\\s+path:\\s+%s", regexp.QuoteMeta(appConfigs[0].Path))) 718 Expect(testUI.Out).To(Say("\\s+routes:")) 719 for _, route := range appConfigs[0].CurrentRoutes { 720 Expect(testUI.Out).To(Say(route.String())) 721 } 722 for _, route := range appConfigs[0].DesiredRoutes { 723 Expect(testUI.Out).To(Say(route.String())) 724 } 725 }) 726 727 Context("when the app starts", func() { 728 It("displays app events and warnings", func() { 729 Expect(executeErr).ToNot(HaveOccurred()) 730 731 Expect(testUI.Out).To(Say("Creating app with these attributes\\.\\.\\.")) 732 Expect(testUI.Out).To(Say("Mapping routes\\.\\.\\.")) 733 Expect(testUI.Out).To(Say("Unmapping routes\\.\\.\\.")) 734 Expect(testUI.Out).To(Say("Binding services\\.\\.\\.")) 735 Expect(testUI.Out).To(Say("Comparing local files to remote cache\\.\\.\\.")) 736 Expect(testUI.Out).To(Say("All files found in remote cache; nothing to upload.")) 737 Expect(testUI.Out).To(Say("Waiting for API to complete processing files\\.\\.\\.")) 738 Expect(testUI.Out).To(Say("Packaging files to upload\\.\\.\\.")) 739 Expect(testUI.Out).To(Say("Uploading files\\.\\.\\.")) 740 Expect(testUI.Out).To(Say("Retrying upload due to an error\\.\\.\\.")) 741 Expect(testUI.Out).To(Say("Waiting for API to complete processing files\\.\\.\\.")) 742 Expect(testUI.Out).To(Say("Stopping app\\.\\.\\.")) 743 744 Expect(testUI.Err).To(Say("some-config-warnings")) 745 Expect(testUI.Err).To(Say("apply-1")) 746 Expect(testUI.Err).To(Say("apply-2")) 747 }) 748 749 It("displays app staging logs", func() { 750 Expect(executeErr).ToNot(HaveOccurred()) 751 752 Expect(testUI.Out).To(Say("log message 1")) 753 Expect(testUI.Out).To(Say("log message 2")) 754 755 Expect(fakeRestartActor.RestartApplicationCallCount()).To(Equal(1)) 756 appConfig, _ := fakeRestartActor.RestartApplicationArgsForCall(0) 757 Expect(appConfig).To(Equal(updatedConfig.CurrentApplication.Application)) 758 }) 759 760 It("displays the app summary with isolation segments as well as warnings", func() { 761 Expect(executeErr).ToNot(HaveOccurred()) 762 Expect(testUI.Out).To(Say("name:\\s+%s", appName)) 763 Expect(testUI.Out).To(Say("requested state:\\s+started")) 764 Expect(testUI.Out).To(Say("instances:\\s+1\\/3")) 765 Expect(testUI.Out).To(Say("usage:\\s+128M x 3 instances")) 766 Expect(testUI.Out).To(Say("routes:\\s+banana.fruit.com/hi, foobar.com:13")) 767 Expect(testUI.Out).To(Say("last uploaded:\\s+\\w{3} [0-3]\\d \\w{3} [0-2]\\d:[0-5]\\d:[0-5]\\d \\w+ \\d{4}")) 768 Expect(testUI.Out).To(Say("stack:\\s+potatos")) 769 Expect(testUI.Out).To(Say("buildpack:\\s+some-buildpack")) 770 Expect(testUI.Out).To(Say("start command:\\s+some start command")) 771 772 Expect(testUI.Err).To(Say("app-summary-warning")) 773 }) 774 775 Context("when the start command is explicitly set", func() { 776 BeforeEach(func() { 777 applicationSummary := v2action.ApplicationSummary{ 778 Application: v2action.Application{ 779 Command: types.FilteredString{IsSet: true, Value: "a-different-start-command"}, 780 DetectedBuildpack: types.FilteredString{IsSet: true, Value: "some-buildpack"}, 781 DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"}, 782 GUID: "some-app-guid", 783 Instances: types.NullInt{Value: 3, IsSet: true}, 784 Memory: types.NullByteSizeInMb{IsSet: true, Value: 128}, 785 Name: appName, 786 PackageUpdatedAt: time.Unix(0, 0), 787 State: "STARTED", 788 }, 789 Stack: v2action.Stack{ 790 Name: "potatos", 791 }, 792 Routes: []v2action.Route{ 793 { 794 Host: "banana", 795 Domain: v2action.Domain{ 796 Name: "fruit.com", 797 }, 798 Path: "/hi", 799 }, 800 { 801 Domain: v2action.Domain{ 802 Name: "foobar.com", 803 }, 804 Port: types.NullInt{IsSet: true, Value: 13}, 805 }, 806 }, 807 } 808 warnings := []string{"app-summary-warning"} 809 810 applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{{State: "RUNNING"}} 811 812 fakeRestartActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil) 813 }) 814 815 It("displays the correct start command", func() { 816 Expect(executeErr).ToNot(HaveOccurred()) 817 Expect(testUI.Out).To(Say("name:\\s+%s", appName)) 818 Expect(testUI.Out).To(Say("start command:\\s+a-different-start-command")) 819 }) 820 }) 821 }) 822 823 Context("when no-start is set", func() { 824 BeforeEach(func() { 825 cmd.NoStart = true 826 827 applicationSummary := v2action.ApplicationSummary{ 828 Application: v2action.Application{ 829 Command: types.FilteredString{IsSet: true, Value: "a-different-start-command"}, 830 DetectedBuildpack: types.FilteredString{IsSet: true, Value: "some-buildpack"}, 831 DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"}, 832 GUID: "some-app-guid", 833 Instances: types.NullInt{Value: 3, IsSet: true}, 834 Memory: types.NullByteSizeInMb{IsSet: true, Value: 128}, 835 Name: appName, 836 PackageUpdatedAt: time.Unix(0, 0), 837 State: "STOPPED", 838 }, 839 Stack: v2action.Stack{ 840 Name: "potatos", 841 }, 842 Routes: []v2action.Route{ 843 { 844 Host: "banana", 845 Domain: v2action.Domain{ 846 Name: "fruit.com", 847 }, 848 Path: "/hi", 849 }, 850 { 851 Domain: v2action.Domain{ 852 Name: "foobar.com", 853 }, 854 Port: types.NullInt{IsSet: true, Value: 13}, 855 }, 856 }, 857 } 858 warnings := []string{"app-summary-warning"} 859 860 fakeRestartActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil) 861 }) 862 863 Context("when the app is not running", func() { 864 It("does not start the app", func() { 865 Expect(executeErr).ToNot(HaveOccurred()) 866 Expect(testUI.Out).To(Say("Waiting for API to complete processing files\\.\\.\\.")) 867 Expect(testUI.Out).To(Say("name:\\s+%s", appName)) 868 Expect(testUI.Out).To(Say("requested state:\\s+stopped")) 869 870 Expect(fakeRestartActor.RestartApplicationCallCount()).To(Equal(0)) 871 }) 872 }) 873 }) 874 }) 875 876 Context("when the apply errors", func() { 877 var expectedErr error 878 879 BeforeEach(func() { 880 expectedErr = errors.New("no wayz dude") 881 fakeActor.ApplyStub = func(_ pushaction.ApplicationConfig, _ pushaction.ProgressBar) (<-chan pushaction.ApplicationConfig, <-chan pushaction.Event, <-chan pushaction.Warnings, <-chan error) { 882 configStream := make(chan pushaction.ApplicationConfig) 883 eventStream := make(chan pushaction.Event) 884 warningsStream := make(chan pushaction.Warnings) 885 errorStream := make(chan error) 886 887 go func() { 888 defer GinkgoRecover() 889 890 Eventually(warningsStream).Should(BeSent(pushaction.Warnings{"apply-1", "apply-2"})) 891 Eventually(errorStream).Should(BeSent(expectedErr)) 892 close(configStream) 893 close(eventStream) 894 close(warningsStream) 895 close(errorStream) 896 }() 897 898 return configStream, eventStream, warningsStream, errorStream 899 } 900 }) 901 902 It("outputs the warnings and returns the error", func() { 903 Expect(executeErr).To(MatchError(expectedErr)) 904 905 Expect(testUI.Err).To(Say("some-config-warnings")) 906 Expect(testUI.Err).To(Say("apply-1")) 907 Expect(testUI.Err).To(Say("apply-2")) 908 }) 909 }) 910 911 }) 912 913 Context("when there is an error converting the app setting into a config", func() { 914 var expectedErr error 915 916 BeforeEach(func() { 917 expectedErr = errors.New("no wayz dude") 918 fakeActor.ConvertToApplicationConfigsReturns(nil, pushaction.Warnings{"some-config-warnings"}, expectedErr) 919 }) 920 921 It("outputs the warnings and returns the error", func() { 922 Expect(executeErr).To(MatchError(expectedErr)) 923 924 Expect(testUI.Err).To(Say("some-config-warnings")) 925 }) 926 }) 927 }) 928 929 Context("when the push settings are invalid", func() { 930 var expectedErr error 931 932 BeforeEach(func() { 933 expectedErr = errors.New("no wayz dude") 934 fakeActor.MergeAndValidateSettingsAndManifestsReturns(nil, expectedErr) 935 }) 936 937 It("returns the error", func() { 938 Expect(executeErr).To(MatchError(expectedErr)) 939 }) 940 }) 941 }) 942 }) 943 944 Describe("GetCommandLineSettings", func() { 945 Context("valid flag combinations", func() { 946 var ( 947 settings pushaction.CommandLineSettings 948 commandLineSettingsErr error 949 ) 950 951 JustBeforeEach(func() { 952 settings, commandLineSettingsErr = cmd.GetCommandLineSettings() 953 Expect(commandLineSettingsErr).ToNot(HaveOccurred()) 954 }) 955 956 Context("when general app settings are given", func() { 957 BeforeEach(func() { 958 cmd.Buildpacks = []string{"some-buildpack"} 959 cmd.Command = flag.Command{FilteredString: types.FilteredString{IsSet: true, Value: "echo foo bar baz"}} 960 cmd.DiskQuota = flag.Megabytes{NullUint64: types.NullUint64{Value: 1024, IsSet: true}} 961 cmd.HealthCheckTimeout = 14 962 cmd.HealthCheckType = flag.HealthCheckType{Type: "http"} 963 cmd.Instances = flag.Instances{NullInt: types.NullInt{Value: 12, IsSet: true}} 964 cmd.Memory = flag.Megabytes{NullUint64: types.NullUint64{Value: 100, IsSet: true}} 965 cmd.StackName = "some-stack" 966 }) 967 968 It("sets them on the command line settings", func() { 969 Expect(commandLineSettingsErr).ToNot(HaveOccurred()) 970 Expect(settings.Buildpacks).To(ConsistOf("some-buildpack")) 971 Expect(settings.Command).To(Equal(types.FilteredString{IsSet: true, Value: "echo foo bar baz"})) 972 Expect(settings.DiskQuota).To(Equal(uint64(1024))) 973 Expect(settings.HealthCheckTimeout).To(Equal(14)) 974 Expect(settings.HealthCheckType).To(Equal("http")) 975 Expect(settings.Instances).To(Equal(types.NullInt{Value: 12, IsSet: true})) 976 Expect(settings.Memory).To(Equal(uint64(100))) 977 Expect(settings.StackName).To(Equal("some-stack")) 978 }) 979 }) 980 981 Context("route related flags", func() { 982 Context("when given customed route settings", func() { 983 BeforeEach(func() { 984 cmd.Domain = "some-domain" 985 }) 986 987 It("sets NoHostname on the command line settings", func() { 988 Expect(settings.DefaultRouteDomain).To(Equal("some-domain")) 989 }) 990 }) 991 992 Context("when --hostname is given", func() { 993 BeforeEach(func() { 994 cmd.Hostname = "some-hostname" 995 }) 996 997 It("sets DefaultRouteHostname on the command line settings", func() { 998 Expect(settings.DefaultRouteHostname).To(Equal("some-hostname")) 999 }) 1000 }) 1001 1002 Context("when --no-hostname is given", func() { 1003 BeforeEach(func() { 1004 cmd.NoHostname = true 1005 }) 1006 1007 It("sets NoHostname on the command line settings", func() { 1008 Expect(settings.NoHostname).To(BeTrue()) 1009 }) 1010 }) 1011 1012 Context("when --random-route is given", func() { 1013 BeforeEach(func() { 1014 cmd.RandomRoute = true 1015 }) 1016 1017 It("sets --random-route on the command line settings", func() { 1018 Expect(commandLineSettingsErr).ToNot(HaveOccurred()) 1019 Expect(settings.RandomRoute).To(BeTrue()) 1020 }) 1021 }) 1022 1023 Context("when --route-path is given", func() { 1024 BeforeEach(func() { 1025 cmd.RoutePath = flag.RoutePath{Path: "/some-path"} 1026 }) 1027 1028 It("sets --route-path on the command line settings", func() { 1029 Expect(commandLineSettingsErr).ToNot(HaveOccurred()) 1030 Expect(settings.RoutePath).To(Equal("/some-path")) 1031 }) 1032 }) 1033 1034 Context("when --no-route is given", func() { 1035 BeforeEach(func() { 1036 cmd.NoRoute = true 1037 }) 1038 1039 It("sets NoRoute on the command line settings", func() { 1040 Expect(settings.NoRoute).To(BeTrue()) 1041 }) 1042 }) 1043 }) 1044 1045 Context("app bits", func() { 1046 Context("when -p flag is given", func() { 1047 BeforeEach(func() { 1048 cmd.AppPath = "some-directory-path" 1049 }) 1050 1051 It("sets ProvidedAppPath", func() { 1052 Expect(settings.ProvidedAppPath).To(Equal("some-directory-path")) 1053 }) 1054 }) 1055 1056 Context("when the -o flag is given", func() { 1057 BeforeEach(func() { 1058 cmd.DockerImage.Path = "some-docker-image-path" 1059 }) 1060 1061 It("creates command line setting from command line arguments", func() { 1062 Expect(settings.DockerImage).To(Equal("some-docker-image-path")) 1063 }) 1064 1065 Context("--docker-username flags is given", func() { 1066 BeforeEach(func() { 1067 cmd.DockerUsername = "some-docker-username" 1068 }) 1069 1070 Context("the docker password environment variable is set", func() { 1071 BeforeEach(func() { 1072 fakeConfig.DockerPasswordReturns("some-docker-password") 1073 }) 1074 1075 It("creates command line setting from command line arguments and config", func() { 1076 Expect(testUI.Out).To(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD.")) 1077 1078 Expect(settings.Name).To(Equal(appName)) 1079 Expect(settings.DockerImage).To(Equal("some-docker-image-path")) 1080 Expect(settings.DockerUsername).To(Equal("some-docker-username")) 1081 Expect(settings.DockerPassword).To(Equal("some-docker-password")) 1082 }) 1083 }) 1084 1085 Context("the docker password environment variable is *not* set", func() { 1086 BeforeEach(func() { 1087 input.Write([]byte("some-docker-password\n")) 1088 }) 1089 1090 It("prompts the user for a password", func() { 1091 Expect(testUI.Out).To(Say("Environment variable CF_DOCKER_PASSWORD not set.")) 1092 Expect(testUI.Out).To(Say("Docker password")) 1093 1094 Expect(settings.Name).To(Equal(appName)) 1095 Expect(settings.DockerImage).To(Equal("some-docker-image-path")) 1096 Expect(settings.DockerUsername).To(Equal("some-docker-username")) 1097 Expect(settings.DockerPassword).To(Equal("some-docker-password")) 1098 }) 1099 }) 1100 }) 1101 }) 1102 }) 1103 }) 1104 1105 DescribeTable("validation errors when flags are passed", 1106 func(setup func(), expectedErr error) { 1107 setup() 1108 _, commandLineSettingsErr := cmd.GetCommandLineSettings() 1109 Expect(commandLineSettingsErr).To(MatchError(expectedErr)) 1110 }, 1111 1112 Entry("--droplet and --docker-username", 1113 func() { 1114 cmd.DropletPath = "some-droplet-path" 1115 cmd.DockerUsername = "some-docker-username" 1116 }, 1117 translatableerror.ArgumentCombinationError{Args: []string{"--droplet", "--docker-username", "-p"}}), 1118 1119 Entry("--droplet and --docker-image", 1120 func() { 1121 cmd.DropletPath = "some-droplet-path" 1122 cmd.DockerImage.Path = "some-docker-image" 1123 }, 1124 translatableerror.ArgumentCombinationError{Args: []string{"--droplet", "--docker-image", "-o"}}), 1125 1126 Entry("--droplet and -p", 1127 func() { 1128 cmd.DropletPath = "some-droplet-path" 1129 cmd.AppPath = "some-directory-path" 1130 }, 1131 translatableerror.ArgumentCombinationError{Args: []string{"--droplet", "-p"}}), 1132 1133 Entry("-o and -p", 1134 func() { 1135 cmd.DockerImage.Path = "some-docker-image" 1136 cmd.AppPath = "some-directory-path" 1137 }, 1138 translatableerror.ArgumentCombinationError{Args: []string{"--docker-image, -o", "-p"}}), 1139 1140 Entry("-b and --docker-image", 1141 func() { 1142 cmd.DockerImage.Path = "some-docker-image" 1143 cmd.Buildpacks = []string{"some-buildpack"} 1144 }, 1145 translatableerror.ArgumentCombinationError{Args: []string{"-b", "--docker-image, -o"}}), 1146 1147 Entry("--docker-username (without DOCKER_PASSWORD env set)", 1148 func() { 1149 cmd.DockerUsername = "some-docker-username" 1150 }, 1151 translatableerror.RequiredFlagsError{Arg1: "--docker-image, -o", Arg2: "--docker-username"}), 1152 1153 Entry("-d and --no-route", 1154 func() { 1155 cmd.Domain = "some-domain" 1156 cmd.NoRoute = true 1157 }, 1158 translatableerror.ArgumentCombinationError{Args: []string{"-d", "--no-route"}}), 1159 1160 Entry("--hostname and --no-hostname", 1161 func() { 1162 cmd.Hostname = "po-tate-toe" 1163 cmd.NoHostname = true 1164 }, 1165 translatableerror.ArgumentCombinationError{Args: []string{"--hostname", "-n", "--no-hostname"}}), 1166 1167 Entry("--hostname and --no-route", 1168 func() { 1169 cmd.Hostname = "po-tate-toe" 1170 cmd.NoRoute = true 1171 }, 1172 translatableerror.ArgumentCombinationError{Args: []string{"--hostname", "-n", "--no-route"}}), 1173 1174 Entry("--no-hostname and --no-route", 1175 func() { 1176 cmd.NoHostname = true 1177 cmd.NoRoute = true 1178 }, 1179 translatableerror.ArgumentCombinationError{Args: []string{"--no-hostname", "--no-route"}}), 1180 1181 Entry("-f and --no-manifest", 1182 func() { 1183 cmd.PathToManifest = "/some/path.yml" 1184 cmd.NoManifest = true 1185 }, 1186 translatableerror.ArgumentCombinationError{Args: []string{"-f", "--no-manifest"}}), 1187 1188 Entry("--random-route and --hostname", 1189 func() { 1190 cmd.Hostname = "po-tate-toe" 1191 cmd.RandomRoute = true 1192 }, 1193 translatableerror.ArgumentCombinationError{Args: []string{"--hostname", "-n", "--random-route"}}), 1194 1195 Entry("--random-route and --no-hostname", 1196 func() { 1197 cmd.RandomRoute = true 1198 cmd.NoHostname = true 1199 }, 1200 translatableerror.ArgumentCombinationError{Args: []string{"--no-hostname", "--random-route"}}), 1201 1202 Entry("--random-route and --no-route", 1203 func() { 1204 cmd.RandomRoute = true 1205 cmd.NoRoute = true 1206 }, 1207 translatableerror.ArgumentCombinationError{Args: []string{"--no-route", "--random-route"}}), 1208 1209 Entry("--random-route and --route-path", 1210 func() { 1211 cmd.RoutePath = flag.RoutePath{Path: "/bananas"} 1212 cmd.RandomRoute = true 1213 }, 1214 translatableerror.ArgumentCombinationError{Args: []string{"--random-route", "--route-path"}}), 1215 1216 Entry("--route-path and --no-route", 1217 func() { 1218 cmd.RoutePath = flag.RoutePath{Path: "/bananas"} 1219 cmd.NoRoute = true 1220 }, 1221 translatableerror.ArgumentCombinationError{Args: []string{"--route-path", "--no-route"}}), 1222 ) 1223 }) 1224 })