Make JSON attributes work with real JSON!
This commit is contained in:
parent
45a16fceac
commit
608d874b45
|
@ -17,6 +17,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"encoding/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
const RemoteStagingPath = "/tmp/provision/chef-solo"
|
const RemoteStagingPath = "/tmp/provision/chef-solo"
|
||||||
|
@ -36,9 +37,14 @@ type config struct {
|
||||||
// An array of recipes to run.
|
// An array of recipes to run.
|
||||||
RunList []string `mapstructure:"run_list"`
|
RunList []string `mapstructure:"run_list"`
|
||||||
|
|
||||||
// An array of environment variables that will be injected before
|
// A string of JSON that will be used as the JSON attributes for the
|
||||||
// your command(s) are executed.
|
// Chef run.
|
||||||
JsonFile string `mapstructure:"json_file"`
|
Json map[string]interface{}
|
||||||
|
|
||||||
|
UseSudo bool `mapstructure:"use_sudo"`
|
||||||
|
|
||||||
|
// If true
|
||||||
|
SkipInstall bool `mapstructure:"skip_install"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Provisioner struct {
|
type Provisioner struct {
|
||||||
|
@ -48,7 +54,6 @@ type Provisioner struct {
|
||||||
type ExecuteRecipeTemplate struct {
|
type ExecuteRecipeTemplate struct {
|
||||||
SoloRbPath string
|
SoloRbPath string
|
||||||
JsonPath string
|
JsonPath string
|
||||||
RunList string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
|
@ -79,10 +84,12 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
p.config.RunList = make([]string, 0)
|
p.config.RunList = make([]string, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.config.JsonFile != "" {
|
if p.config.Json != nil {
|
||||||
if _, err := os.Stat(p.config.JsonFile); err != nil {
|
if _, err := json.Marshal(p.config.Json); err != nil {
|
||||||
errs = append(errs, fmt.Errorf("Bad JSON attributes file '%s': %s", p.config.JsonFile, err))
|
errs = append(errs, fmt.Errorf("Bad JSON: %s", err))
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
p.config.Json = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, path := range p.config.CookbookPaths {
|
for _, path := range p.config.CookbookPaths {
|
||||||
|
@ -122,7 +129,7 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
||||||
return fmt.Errorf("Error creating Chef Solo configuration file: %s", err)
|
return fmt.Errorf("Error creating Chef Solo configuration file: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonPath, err := CreateAttributesJson(p.config.JsonFile, comm)
|
jsonPath, err := CreateAttributesJson(p.config.Json, p.config.RunList, comm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error uploading JSON attributes file: %s", err)
|
return fmt.Errorf("Error uploading JSON attributes file: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -137,18 +144,19 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute requested recipes
|
// Execute requested recipes
|
||||||
for _, recipe := range p.config.RunList {
|
ui.Say("Beginning Chef Solo run")
|
||||||
ui.Say(fmt.Sprintf("chef-solo running recipe: %s", recipe))
|
|
||||||
// Compile the command
|
// Compile the command
|
||||||
var command bytes.Buffer
|
var command bytes.Buffer
|
||||||
t := template.Must(template.New("chef-run").Parse("sudo chef-solo --no-color -c {{.SoloRbPath}} -j {{.JsonPath}} -o {{.RunList}}"))
|
t := template.Must(template.New("chef-run").Parse("sudo chef-solo --no-color -c {{.SoloRbPath}} -j {{.JsonPath}}"))
|
||||||
t.Execute(&command, &ExecuteRecipeTemplate{soloRbPath, jsonPath, recipe})
|
t.Execute(&command, &ExecuteRecipeTemplate{soloRbPath, jsonPath})
|
||||||
|
|
||||||
err = executeCommand(command.String(), comm)
|
err = executeCommand(command.String(), comm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error running recipe %s: %s", recipe, err)
|
return fmt.Errorf("Error running Chef Solo: %s", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("Die")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -246,32 +254,43 @@ func CreateSoloRb(cookbookPaths []string, comm packer.Communicator) (str string,
|
||||||
return remotePath, nil
|
return remotePath, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateAttributesJson(jsonFile string, comm packer.Communicator) (str string, err error) {
|
func CreateAttributesJson(jsonAttrs map[string]interface{}, runList []string, comm packer.Communicator) (str string, err error) {
|
||||||
Ui.Say(fmt.Sprintf("Uploading Chef attributes file %s", jsonFile))
|
Ui.Say(fmt.Sprintf("Creating and uploading Chef attributes file"))
|
||||||
remotePath := RemoteStagingPath + "/node.json"
|
remotePath := RemoteStagingPath + "/node.json"
|
||||||
|
|
||||||
// Create an empty JSON file if none given
|
var formattedRunList []string
|
||||||
if jsonFile == "" {
|
for _, value := range runList {
|
||||||
tf, err := ioutil.TempFile("", "packer-chef-solo-json")
|
formattedRunList = append(formattedRunList, "recipe[" + value + "]")
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
|
||||||
}
|
|
||||||
defer os.Remove(tf.Name())
|
|
||||||
|
|
||||||
// Write our contents to it
|
|
||||||
writer := bufio.NewWriter(tf)
|
|
||||||
if _, err := writer.WriteString("{}"); err != nil {
|
|
||||||
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := writer.Flush(); err != nil {
|
|
||||||
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonFile = tf.Name()
|
|
||||||
tf.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add RunList to JSON
|
||||||
|
jsonAttrs["run_list"] = formattedRunList
|
||||||
|
|
||||||
|
// Convert to JSON string
|
||||||
|
jsonString, err := json.MarshalIndent(jsonAttrs, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error parsing JSON attributes: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tf, err := ioutil.TempFile("", "packer-chef-solo-json")
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
||||||
|
}
|
||||||
|
defer os.Remove(tf.Name())
|
||||||
|
|
||||||
|
// Write our contents to it
|
||||||
|
writer := bufio.NewWriter(tf)
|
||||||
|
if _, err := writer.WriteString(string(jsonString)); err != nil {
|
||||||
|
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := writer.Flush(); err != nil {
|
||||||
|
return "", fmt.Errorf("Error preparing Chef attributes file: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
jsonFile := tf.Name()
|
||||||
|
tf.Close()
|
||||||
|
|
||||||
log.Printf("Opening %s for reading", jsonFile)
|
log.Printf("Opening %s for reading", jsonFile)
|
||||||
f, err := os.Open(jsonFile)
|
f, err := os.Open(jsonFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue