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