Skip to content

Commit

Permalink
Override directory defaulting for ExportRelease call
Browse files Browse the repository at this point in the history
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 <dwendorf@pivotal.io>
#2
  • Loading branch information
drich10 authored and wendorf committed Mar 17, 2017
1 parent 17c27b1 commit bc4848f
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 10 deletions.
44 changes: 44 additions & 0 deletions bosh/boshfakes/fake_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}

Expand Down
10 changes: 10 additions & 0 deletions bosh/command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

type Runner interface {
Execute(commandOpts interface{}) error
ExecuteWithDefaultOverride(commandOpts interface{}, override func(interface{}) (interface{}, error)) error
}

type CommandRunner struct {
Expand All @@ -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()
Expand Down
18 changes: 14 additions & 4 deletions bosh/director.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down
16 changes: 10 additions & 6 deletions bosh/director_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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")))
Expand Down

0 comments on commit bc4848f

Please sign in to comment.