provisioner(converge): flatten execution fields

pull/4326/head
Brian Hicks 10 years ago
parent 3658a0b6b5
commit fe4b972d32
No known key found for this signature in database
GPG Key ID: FF1F407C0D3C2430

@ -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
}

@ -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)
}
})
})
}

Loading…
Cancel
Save