From 3311d3a48d47c79a7bcb0efc8e87d0e401708444 Mon Sep 17 00:00:00 2001 From: Brian Hicks Date: Tue, 27 Dec 2016 16:48:11 -0600 Subject: [PATCH] provisioner(converge): interpolate execute_command --- provisioner/converge/provisioner.go | 49 +++++++++++++++--------- provisioner/converge/provisioner_test.go | 37 ++++++++++++------ 2 files changed, 57 insertions(+), 29 deletions(-) diff --git a/provisioner/converge/provisioner.go b/provisioner/converge/provisioner.go index d4fe0b743..aabaf45e7 100644 --- a/provisioner/converge/provisioner.go +++ b/provisioner/converge/provisioner.go @@ -38,6 +38,7 @@ type Config struct { Module string `mapstructure:"module"` WorkingDirectory string `mapstructure:"working_directory"` Params map[string]string `mapstucture:"params"` + ExecuteCommand string `mapstructure:"execute_command"` ctx interpolate.Context } @@ -71,6 +72,20 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { return err } + // require a single module + if p.config.Module == "" { + return errors.New("Converge requires a module to provision the system") + } + + // set defaults + if p.config.WorkingDirectory == "" { + p.config.WorkingDirectory = "/tmp" + } + + if p.config.ExecuteCommand == "" { + p.config.ExecuteCommand = "cd {{.WorkingDirectory}} && sudo converge apply --local --log-level=WARNING --paramsJSON '{{.ParamsJSON}}' {{.Module}}" + } + // validate version if !versionRegex.Match([]byte(p.config.Version)) { return fmt.Errorf("Invalid Converge version %q specified. Valid versions include only letters, numbers, dots, and dashes", p.config.Version) @@ -86,15 +101,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } } - // validate modules - if p.config.Module == "" { - return errors.New("Converge requires a module to provision the system") - } - - if p.config.WorkingDirectory == "" { - p.config.WorkingDirectory = "/tmp" - } - return err } @@ -183,18 +189,25 @@ func (p *Provisioner) applyModules(ui packer.Ui, comm packer.Communicator) error return fmt.Errorf("Could not marshal parameters as JSON: %s", err) } + p.config.ctx.Data = struct { + ParamsJSON, WorkingDirectory, Module string + }{ + ParamsJSON: string(params), + WorkingDirectory: p.config.WorkingDirectory, + Module: p.config.Module, + } + command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx) + if err != nil { + return fmt.Errorf("Could not interpolate execute command: %s", err) + } + // run Converge in the specified directory var runOut bytes.Buffer cmd := &packer.RemoteCmd{ - Command: fmt.Sprintf( - "cd %s && converge apply --local --log-level=WARNING --paramsJSON '%s' %s", - p.config.WorkingDirectory, - string(params), - p.config.Module, - ), - Stdin: nil, - Stdout: &runOut, - Stderr: &runOut, + Command: command, + Stdin: nil, + Stdout: &runOut, + Stderr: &runOut, } if err := comm.Start(cmd); err != nil { return fmt.Errorf("Error applying %q: %s", p.config.Module, err) diff --git a/provisioner/converge/provisioner_test.go b/provisioner/converge/provisioner_test.go index fd32b104a..7a7e5ac09 100644 --- a/provisioner/converge/provisioner_test.go +++ b/provisioner/converge/provisioner_test.go @@ -31,20 +31,35 @@ func TestProvisioner_Impl(t *testing.T) { func TestProvisionerPrepare(t *testing.T) { t.Run("defaults", func(t *testing.T) { - var p Provisioner - config := testConfig() + t.Run("working_directory", func(t *testing.T) { + var p Provisioner + config := testConfig() + + delete(config, "working_directory") + + if err := p.Prepare(config); err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.WorkingDirectory != "/tmp" { + t.Fatalf("unexpected module directory: %s", p.config.WorkingDirectory) + } + }) - // delete any keys that we're testing here to make sure they're actually - // being set by `Prepare` - delete(config, "working_directory") + t.Run("execute_command", func(t *testing.T) { + var p Provisioner + config := testConfig() - if err := p.Prepare(config); err != nil { - t.Errorf("err: %s", err) - } + delete(config, "execute_command") - if p.config.WorkingDirectory != "/tmp" { - t.Errorf("unexpected module directory: %s", p.config.WorkingDirectory) - } + if err := p.Prepare(config); err != nil { + t.Fatalf("err: %s", err) + } + + if p.config.ExecuteCommand == "" { + t.Fatal("execute command unexpectedly blank") + } + }) }) t.Run("validate", func(t *testing.T) {