diff --git a/provisioner/converge/provisioner.go b/provisioner/converge/provisioner.go index d7beef4de..d4fe0b743 100644 --- a/provisioner/converge/provisioner.go +++ b/provisioner/converge/provisioner.go @@ -7,7 +7,6 @@ import ( "bytes" "errors" "fmt" - "log" "net/http" "strings" @@ -34,7 +33,11 @@ type Config struct { // Modules ModuleDirs []ModuleDir `mapstructure:"module_dirs"` - Modules []Module `mapstructure:"modules"` + + // Execution + Module string `mapstructure:"module"` + WorkingDirectory string `mapstructure:"working_directory"` + Params map[string]string `mapstucture:"params"` ctx interpolate.Context } @@ -46,13 +49,6 @@ type ModuleDir struct { Exclude []string `mapstructure:"exclude"` } -// Module contains information needed to run a module -type Module struct { - Module string `mapstructure:"module"` - WorkingDirectory string `mapstructure:"working_directory"` - Params map[string]string `mapstucture:"params"` -} - // Provisioner for Converge type Provisioner struct { config Config @@ -65,6 +61,9 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, + InterpolateFilter: &interpolate.RenderFilter{ + Exclude: []string{"execute_command"}, + }, }, raws..., ) @@ -88,16 +87,12 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { } // validate modules - if len(p.config.Modules) == 0 { - return errors.New("Converge requires at least one module (\"modules\" key) to provision the system") + if p.config.Module == "" { + return errors.New("Converge requires a module to provision the system") } - for i, module := range p.config.Modules { - if module.Module == "" { - return fmt.Errorf("Module (\"module\" key) is required in Converge module #%d", i) - } - if module.WorkingDirectory == "" { - p.config.Modules[i].WorkingDirectory = "/tmp" - } + + if p.config.WorkingDirectory == "" { + p.config.WorkingDirectory = "/tmp" } return err @@ -182,48 +177,46 @@ func (p *Provisioner) sendModuleDirectories(ui packer.Ui, comm packer.Communicat } func (p *Provisioner) applyModules(ui packer.Ui, comm packer.Communicator) error { - for _, module := range p.config.Modules { - // create params JSON file - params, err := json.Marshal(module.Params) - if err != nil { - return fmt.Errorf("Could not marshal parameters as JSON: %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", - module.WorkingDirectory, - string(params), - module.Module, - ), - Stdin: nil, - Stdout: &runOut, - Stderr: &runOut, - } - if err := comm.Start(cmd); err != nil { - return fmt.Errorf("Error applying %q: %s", module.Module, err) - } - - cmd.Wait() - if cmd.ExitStatus == 127 { - ui.Error("Could not find Converge. Is it installed and in PATH?") - if !p.config.Bootstrap { - ui.Error("Bootstrapping was disabled for this run. That might be why Converge isn't present.") - } + // create params JSON file + params, err := json.Marshal(p.config.Params) + if err != nil { + return fmt.Errorf("Could not marshal parameters as JSON: %s", err) + } - return errors.New("Could not find Converge") + // 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, + } + if err := comm.Start(cmd); err != nil { + return fmt.Errorf("Error applying %q: %s", p.config.Module, err) + } - } else if cmd.ExitStatus != 0 { - ui.Error(strings.TrimSpace(runOut.String())) - ui.Error(fmt.Sprintf("exited with error code %d", cmd.ExitStatus)) - return fmt.Errorf("Error applying %q", module.Module) + cmd.Wait() + if cmd.ExitStatus == 127 { + ui.Error("Could not find Converge. Is it installed and in PATH?") + if !p.config.Bootstrap { + ui.Error("Bootstrapping was disabled for this run. That might be why Converge isn't present.") } - ui.Message(strings.TrimSpace(runOut.String())) + return errors.New("Could not find Converge") + + } else if cmd.ExitStatus != 0 { + ui.Error(strings.TrimSpace(runOut.String())) + ui.Error(fmt.Sprintf("exited with error code %d", cmd.ExitStatus)) + return fmt.Errorf("Error applying %q", p.config.Module) } + ui.Message(strings.TrimSpace(runOut.String())) + return nil } diff --git a/provisioner/converge/provisioner_test.go b/provisioner/converge/provisioner_test.go index 687210139..fd32b104a 100644 --- a/provisioner/converge/provisioner_test.go +++ b/provisioner/converge/provisioner_test.go @@ -17,11 +17,7 @@ func testConfig() map[string]interface{} { "destination": "/opt/converge", }, }, - "modules": []map[string]interface{}{ - { - "module": "/opt/converge/test.hcl", - }, - }, + "module": "/opt/converge/test.hcl", } } @@ -40,14 +36,14 @@ func TestProvisionerPrepare(t *testing.T) { // delete any keys that we're testing here to make sure they're actually // being set by `Prepare` - delete(config["modules"].([]map[string]interface{})[0], "directory") + delete(config, "working_directory") if err := p.Prepare(config); err != nil { t.Errorf("err: %s", err) } - if p.config.Modules[0].WorkingDirectory != "/tmp" { - t.Errorf("unexpected module directory: %s", p.config.Modules[0].WorkingDirectory) + if p.config.WorkingDirectory != "/tmp" { + t.Errorf("unexpected module directory: %s", p.config.WorkingDirectory) } }) @@ -93,32 +89,17 @@ func TestProvisionerPrepare(t *testing.T) { }) }) - t.Run("modules", func(t *testing.T) { - t.Run("none specified", func(t *testing.T) { - var p Provisioner - config := testConfig() - delete(config, "modules") - - err := p.Prepare(config) - if err == nil { - t.Error("expected error") - } else if err.Error() != "Converge requires at least one module (\"modules\" key) to provision the system" { - t.Errorf("bad error message: %s", err) - } - }) - - t.Run("missing module", func(t *testing.T) { - var p Provisioner - config := testConfig() - delete(config["modules"].([]map[string]interface{})[0], "module") + t.Run("no module specified", func(t *testing.T) { + var p Provisioner + config := testConfig() + delete(config, "module") - err := p.Prepare(config) - if err == nil { - t.Error("expected error") - } else if err.Error() != "Module (\"module\" key) is required in Converge module #0" { - t.Errorf("bad error message: %s", err) - } - }) + err := p.Prepare(config) + if err == nil { + t.Error("expected error") + } else if err.Error() != "Converge requires a module to provision the system" { + t.Errorf("bad error message: %s", err) + } }) }) }