provisioner/*: convert to interpolation

This commit is contained in:
Mitchell Hashimoto 2015-05-27 14:41:47 -07:00
parent 5b343ca98c
commit c2381be44f
2 changed files with 39 additions and 120 deletions

View File

@ -8,14 +8,16 @@ import (
"strings"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
const DefaultStagingDir = "/tmp/packer-provisioner-ansible-local"
type Config struct {
common.PackerConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
// The command to run ansible
Command string
@ -54,21 +56,16 @@ type Provisioner struct {
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
}
p.config.tpl.UserVars = p.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
// Defaults
if p.config.Command == "" {
p.config.Command = "ANSIBLE_FORCE_COLOR=1 PYTHONUNBUFFERED=1 ansible-playbook"
@ -78,44 +75,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = DefaultStagingDir
}
// Templates
templates := map[string]*string{
"command": &p.config.Command,
"group_vars": &p.config.GroupVars,
"host_vars": &p.config.HostVars,
"playbook_file": &p.config.PlaybookFile,
"playbook_dir": &p.config.PlaybookDir,
"staging_dir": &p.config.StagingDir,
"inventory_file": &p.config.InventoryFile,
}
for n, ptr := range templates {
var err error
*ptr, err = p.config.tpl.Process(*ptr, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
sliceTemplates := map[string][]string{
"extra_arguments": p.config.ExtraArguments,
"playbook_paths": p.config.PlaybookPaths,
"role_paths": p.config.RolePaths,
}
for n, slice := range sliceTemplates {
for i, elem := range slice {
var err error
slice[i], err = p.config.tpl.Process(elem, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
}
}
}
// Validation
var errs *packer.MultiError
err = validateFileConfig(p.config.PlaybookFile, "playbook_file", true)
if err != nil {
errs = packer.MultiErrorAppend(errs, err)

View File

@ -15,7 +15,9 @@ import (
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/common/uuid"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type Config struct {
@ -38,7 +40,7 @@ type Config struct {
ValidationKeyPath string `mapstructure:"validation_key_path"`
ValidationClientName string `mapstructure:"validation_client_name"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
}
type Provisioner struct {
@ -65,42 +67,19 @@ type InstallChefTemplate struct {
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"execute_command",
"install_command",
},
},
}, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
}
p.config.tpl.UserVars = p.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"chef_environment": &p.config.ChefEnvironment,
"ssl_verify_mode": &p.config.SslVerifyMode,
"config_template": &p.config.ConfigTemplate,
"node_name": &p.config.NodeName,
"staging_dir": &p.config.StagingDir,
"chef_server_url": &p.config.ServerUrl,
"execute_command": &p.config.ExecuteCommand,
"install_command": &p.config.InstallCommand,
"validation_key_path": &p.config.ValidationKeyPath,
"validation_client_name": &p.config.ValidationClientName,
}
for n, ptr := range templates {
var err error
*ptr, err = p.config.tpl.Process(*ptr, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s: %s", n, err))
}
}
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-client " +
"--no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
@ -120,33 +99,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = "/tmp/packer-chef-client"
}
sliceTemplates := map[string][]string{
"run_list": p.config.RunList,
}
for n, slice := range sliceTemplates {
for i, elem := range slice {
var err error
slice[i], err = p.config.tpl.Process(elem, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
}
}
}
validates := map[string]*string{
"execute_command": &p.config.ExecuteCommand,
"install_command": &p.config.InstallCommand,
}
for n, ptr := range validates {
if err := p.config.tpl.Validate(*ptr); err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error parsing %s: %s", n, err))
}
}
var errs *packer.MultiError
if p.config.ConfigTemplate != "" {
fi, err := os.Stat(p.config.ConfigTemplate)
if err != nil {
@ -291,14 +244,16 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeN
tpl = string(tplBytes)
}
configString, err := p.config.tpl.Process(tpl, &ConfigTemplate{
ctx := p.config.ctx
ctx.Data = &ConfigTemplate{
NodeName: nodeName,
ServerUrl: serverUrl,
ValidationKeyPath: remoteKeyPath,
ValidationClientName: validationClientName,
ChefEnvironment: chefEnvironment,
SslVerifyMode: sslVerifyMode,
})
}
configString, err := interpolate.Render(tpl, &ctx)
if err != nil {
return "", err
}
@ -415,11 +370,12 @@ func (p *Provisioner) removeDir(ui packer.Ui, comm packer.Communicator, dir stri
}
func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config string, json string) error {
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteTemplate{
p.config.ctx.Data = &ExecuteTemplate{
ConfigPath: config,
JsonPath: json,
Sudo: !p.config.PreventSudo,
})
}
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil {
return err
}
@ -444,9 +400,10 @@ func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config
func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
ui.Message("Installing Chef...")
command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{
p.config.ctx.Data = &InstallChefTemplate{
Sudo: !p.config.PreventSudo,
})
}
command, err := interpolate.Render(p.config.InstallCommand, &p.config.ctx)
if err != nil {
return err
}
@ -532,24 +489,25 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) {
// Copy the user variables so that we can restore them later, and
// make sure we make the quotes JSON-friendly in the user variables.
originalUserVars := make(map[string]string)
for k, v := range p.config.tpl.UserVars {
for k, v := range p.config.ctx.UserVariables {
originalUserVars[k] = v
}
// Make sure we reset them no matter what
defer func() {
p.config.tpl.UserVars = originalUserVars
p.config.ctx.UserVariables = originalUserVars
}()
// Make the current user variables JSON string safe.
for k, v := range p.config.tpl.UserVars {
for k, v := range p.config.ctx.UserVariables {
v = strings.Replace(v, `\`, `\\`, -1)
v = strings.Replace(v, `"`, `\"`, -1)
p.config.tpl.UserVars[k] = v
p.config.ctx.UserVariables[k] = v
}
// Process the bytes with the template processor
jsonBytesProcessed, err := p.config.tpl.Process(string(jsonBytes), nil)
p.config.ctx.Data = nil
jsonBytesProcessed, err := interpolate.Render(string(jsonBytes), &p.config.ctx)
if err != nil {
return nil, err
}