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