Node DNA needs to handle multiple types

Makes chef-client provisioner consistent with chef-solo in its handling of nested JSON as well as strings.

Fixes #1096
This commit is contained in:
Ben Langfeld 2014-05-01 12:48:04 -03:00
parent 92d58a5ede
commit b801713e83
1 changed files with 59 additions and 6 deletions

View File

@ -152,12 +152,24 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
errs, fmt.Errorf("server_url must be set")) errs, fmt.Errorf("server_url must be set"))
} }
// Process the user variables within the JSON and set the JSON. jsonValid := true
// Do this early so that we can validate and show errors. for k, v := range p.config.Json {
p.config.Json, err = p.processJsonUserVars() p.config.Json[k], err = p.deepJsonFix(k, v)
if err != nil { if err != nil {
errs = packer.MultiErrorAppend( errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing user variables in JSON: %s", err)) errs, fmt.Errorf("Error processing JSON: %s", err))
jsonValid = false
}
}
if jsonValid {
// Process the user variables within the JSON and set the JSON.
// Do this early so that we can validate and show errors.
p.config.Json, err = p.processJsonUserVars()
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing user variables in JSON: %s", err))
}
} }
if errs != nil && len(errs.Errors) > 0 { if errs != nil && len(errs.Errors) > 0 {
@ -440,6 +452,47 @@ func (p *Provisioner) copyValidationKey(ui packer.Ui, comm packer.Communicator,
return nil return nil
} }
func (p *Provisioner) deepJsonFix(key string, current interface{}) (interface{}, error) {
if current == nil {
return nil, nil
}
switch c := current.(type) {
case []interface{}:
val := make([]interface{}, len(c))
for i, v := range c {
var err error
val[i], err = p.deepJsonFix(fmt.Sprintf("%s[%d]", key, i), v)
if err != nil {
return nil, err
}
}
return val, nil
case []uint8:
return string(c), nil
case map[interface{}]interface{}:
val := make(map[string]interface{})
for k, v := range c {
ks, ok := k.(string)
if !ok {
return nil, fmt.Errorf("%s: key is not string", key)
}
var err error
val[ks], err = p.deepJsonFix(
fmt.Sprintf("%s.%s", key, ks), v)
if err != nil {
return nil, err
}
}
return val, nil
default:
return current, nil
}
}
func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) { func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) {
jsonBytes, err := json.Marshal(p.config.Json) jsonBytes, err := json.Marshal(p.config.Json)
if err != nil { if err != nil {