From bc4848f5adeee9aa3bdf2b5ba964d131b6d5e024 Mon Sep 17 00:00:00 2001 From: Derek Richard Date: Fri, 17 Mar 2017 13:59:27 -0700 Subject: [PATCH] Override directory defaulting for ExportRelease call bosh-cli will try to default the directory in ExportReleaseOpts when go-flag parsing, even if we have already set one. We need a hook later in the process to un-default it to our desired directory. [#141621101] Signed-off-by: Dan Wendorf #2 --- bosh/boshfakes/fake_runner.go | 44 +++++++++++++++++++++++++++++++++++ bosh/command_runner.go | 10 ++++++++ bosh/director.go | 18 ++++++++++---- bosh/director_test.go | 16 ++++++++----- 4 files changed, 78 insertions(+), 10 deletions(-) diff --git a/bosh/boshfakes/fake_runner.go b/bosh/boshfakes/fake_runner.go index 43578ee6d..db4796eef 100644 --- a/bosh/boshfakes/fake_runner.go +++ b/bosh/boshfakes/fake_runner.go @@ -16,6 +16,15 @@ type FakeRunner struct { executeReturns struct { result1 error } + ExecuteWithDefaultOverrideStub func(commandOpts interface{}, override func(interface{}) (interface{}, error)) error + executeWithDefaultOverrideMutex sync.RWMutex + executeWithDefaultOverrideArgsForCall []struct { + commandOpts interface{} + override func(interface{}) (interface{}, error) + } + executeWithDefaultOverrideReturns struct { + result1 error + } invocations map[string][][]interface{} invocationsMutex sync.RWMutex } @@ -52,11 +61,46 @@ func (fake *FakeRunner) ExecuteReturns(result1 error) { }{result1} } +func (fake *FakeRunner) ExecuteWithDefaultOverride(commandOpts interface{}, override func(interface{}) (interface{}, error)) error { + fake.executeWithDefaultOverrideMutex.Lock() + fake.executeWithDefaultOverrideArgsForCall = append(fake.executeWithDefaultOverrideArgsForCall, struct { + commandOpts interface{} + override func(interface{}) (interface{}, error) + }{commandOpts, override}) + fake.recordInvocation("ExecuteWithDefaultOverride", []interface{}{commandOpts, override}) + fake.executeWithDefaultOverrideMutex.Unlock() + if fake.ExecuteWithDefaultOverrideStub != nil { + return fake.ExecuteWithDefaultOverrideStub(commandOpts, override) + } + return fake.executeWithDefaultOverrideReturns.result1 +} + +func (fake *FakeRunner) ExecuteWithDefaultOverrideCallCount() int { + fake.executeWithDefaultOverrideMutex.RLock() + defer fake.executeWithDefaultOverrideMutex.RUnlock() + return len(fake.executeWithDefaultOverrideArgsForCall) +} + +func (fake *FakeRunner) ExecuteWithDefaultOverrideArgsForCall(i int) (interface{}, func(interface{}) (interface{}, error)) { + fake.executeWithDefaultOverrideMutex.RLock() + defer fake.executeWithDefaultOverrideMutex.RUnlock() + return fake.executeWithDefaultOverrideArgsForCall[i].commandOpts, fake.executeWithDefaultOverrideArgsForCall[i].override +} + +func (fake *FakeRunner) ExecuteWithDefaultOverrideReturns(result1 error) { + fake.ExecuteWithDefaultOverrideStub = nil + fake.executeWithDefaultOverrideReturns = struct { + result1 error + }{result1} +} + func (fake *FakeRunner) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() fake.executeMutex.RLock() defer fake.executeMutex.RUnlock() + fake.executeWithDefaultOverrideMutex.RLock() + defer fake.executeWithDefaultOverrideMutex.RUnlock() return fake.invocations } diff --git a/bosh/command_runner.go b/bosh/command_runner.go index 09c91c493..4454205c4 100644 --- a/bosh/command_runner.go +++ b/bosh/command_runner.go @@ -6,6 +6,7 @@ import ( type Runner interface { Execute(commandOpts interface{}) error + ExecuteWithDefaultOverride(commandOpts interface{}, override func(interface{}) (interface{}, error)) error } type CommandRunner struct { @@ -19,10 +20,19 @@ func NewCommandRunner(cliCoordinator CLICoordinator) CommandRunner { } func (c CommandRunner) Execute(commandOpts interface{}) error { + return c.ExecuteWithDefaultOverride(commandOpts, func(opts interface{}) (interface{}, error) { return opts, nil }) +} + +func (c CommandRunner) ExecuteWithDefaultOverride(commandOpts interface{}, override func(interface{}) (interface{}, error)) error { deps := c.cliCoordinator.StreamingBasicDeps() globalOpts := c.cliCoordinator.GlobalOpts() setDefaults(commandOpts) + commandOpts, err := override(commandOpts) + if err != nil { + return err + } + cmd := boshcmd.NewCmd(globalOpts, commandOpts, deps) return cmd.Execute() diff --git a/bosh/director.go b/bosh/director.go index 849d32729..a9fa98a4d 100644 --- a/bosh/director.go +++ b/bosh/director.go @@ -135,10 +135,20 @@ func (d BoshDirector) ExportReleases(targetDirectory string, releases []string) releaseSlug := boshdir.NewReleaseSlug(deploymentRelease.Name(), deploymentRelease.Version().AsString()) osVersionSlug := boshdir.NewOSVersionSlug(stemcell.OSName(), stemcell.Version().AsString()) - err = d.commandRunner.Execute(&boshcmd.ExportReleaseOpts{ + directory := boshcmd.DirOrCWDArg{} + directoryFixFunction := func(defaultedOps interface{}) (interface{}, error) { + switch v := defaultedOps.(type) { + case (*boshcmd.ExportReleaseOpts): + v.Directory.Path = targetDirectory + default: + panic("todo") + } + return defaultedOps, nil + } + err = d.commandRunner.ExecuteWithDefaultOverride(&boshcmd.ExportReleaseOpts{ Args: boshcmd.ExportReleaseArgs{ReleaseSlug: releaseSlug, OSVersionSlug: osVersionSlug}, - Directory: boshcmd.DirOrCWDArg{Path: targetDirectory}, - }) + Directory: directory, + }, directoryFixFunction) if err != nil { return fmt.Errorf("could not export release %s: %s", deploymentRelease.Name(), err) } @@ -186,7 +196,7 @@ func (d BoshDirector) releasesAndStemcell() ([]boshdir.Release, boshdir.Stemcell if len(deploymentStemcells) > 1 { return []boshdir.Release{}, nil, errors.New("exporting releases from a deployment with multiple stemcells is unsupported") } - directorStemcells, err := d.cliDirector.Stemcells() + directorStemcells, err := d.cliDirector.Stemcells() if err != nil { return []boshdir.Release{}, nil, fmt.Errorf("could not fetch stemcells: %s", err) } diff --git a/bosh/director_test.go b/bosh/director_test.go index cce99908d..ba648339c 100644 --- a/bosh/director_test.go +++ b/bosh/director_test.go @@ -247,21 +247,25 @@ var _ = Describe("BoshDirector", func() { Expect(fakeBoshDirector.FindDeploymentCallCount()).To(Equal(1)) Expect(fakeBoshDirector.FindDeploymentArgsForCall(0)).To(Equal("cool-deployment")) - Expect(commandRunner.ExecuteCallCount()).To(Equal(2)) + Expect(commandRunner.ExecuteWithDefaultOverrideCallCount()).To(Equal(2)) - exportReleaseOpts := commandRunner.ExecuteArgsForCall(0).(*boshcmd.ExportReleaseOpts) + opts, optFunc := commandRunner.ExecuteWithDefaultOverrideArgsForCall(0) + exportReleaseOpts, _ := opts.(*boshcmd.ExportReleaseOpts) Expect(string(exportReleaseOpts.Args.ReleaseSlug.Name())).To(Equal("cool-release")) Expect(string(exportReleaseOpts.Args.ReleaseSlug.Version())).To(Equal("123.45")) Expect(string(exportReleaseOpts.Args.OSVersionSlug.OS())).To(Equal("minix")) Expect(string(exportReleaseOpts.Args.OSVersionSlug.Version())).To(Equal("3.4.0")) - Expect(string(exportReleaseOpts.Directory.Path)).To(Equal("/tmp/foo")) - exportReleaseOpts = commandRunner.ExecuteArgsForCall(1).(*boshcmd.ExportReleaseOpts) + fixedOpts, err := optFunc(&boshcmd.ExportReleaseOpts{Directory: boshcmd.DirOrCWDArg{Path: "wrong-path"}}) + Expect(err).ToNot(HaveOccurred()) + Expect(fixedOpts.(*boshcmd.ExportReleaseOpts).Directory.Path).To(Equal("/tmp/foo")) + + opts, optFunc = commandRunner.ExecuteWithDefaultOverrideArgsForCall(1) + exportReleaseOpts, _ = opts.(*boshcmd.ExportReleaseOpts) Expect(string(exportReleaseOpts.Args.ReleaseSlug.Name())).To(Equal("awesome-release")) Expect(string(exportReleaseOpts.Args.ReleaseSlug.Version())).To(Equal("987.65")) Expect(string(exportReleaseOpts.Args.OSVersionSlug.OS())).To(Equal("minix")) Expect(string(exportReleaseOpts.Args.OSVersionSlug.Version())).To(Equal("3.4.0")) - Expect(string(exportReleaseOpts.Directory.Path)).To(Equal("/tmp/foo")) }) Context("when requesting a release not in the manifest", func() { @@ -295,7 +299,7 @@ var _ = Describe("BoshDirector", func() { Context("when exporting releases fails", func() { It("returns an error", func() { - commandRunner.ExecuteReturns(errors.New("failed communicating with director")) + commandRunner.ExecuteWithDefaultOverrideReturns(errors.New("failed communicating with director")) err := director.ExportReleases("/tmp/foo", []string{"cool-release"}) Expect(err).To(MatchError(ContainSubstring("could not export release cool-release: failed communicating with director")))