Commit 2b4df93f authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

provisioner/*: interpolation

parent c2381be4
......@@ -7,12 +7,15 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type Config struct {
......@@ -34,7 +37,7 @@ type Config struct {
SkipInstall bool `mapstructure:"skip_install"`
StagingDir string `mapstructure:"staging_directory"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
}
type Provisioner struct {
......@@ -69,16 +72,18 @@ type InstallChefTemplate struct {
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
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.UserVars = p.config.PackerUserVars
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}"
......@@ -96,57 +101,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = "/tmp/packer-chef-solo"
}
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"config_template": &p.config.ConfigTemplate,
"data_bags_path": &p.config.DataBagsPath,
"encrypted_data_bag_secret": &p.config.EncryptedDataBagSecretPath,
"roles_path": &p.config.RolesPath,
"staging_dir": &p.config.StagingDir,
"environments_path": &p.config.EnvironmentsPath,
"chef_environment": &p.config.ChefEnvironment,
}
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{
"cookbook_paths": p.config.CookbookPaths,
"remote_cookbook_paths": p.config.RemoteCookbookPaths,
"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 {
......@@ -362,7 +317,7 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local
tpl = string(tplBytes)
}
configString, err := p.config.tpl.Process(tpl, &ConfigTemplate{
p.config.ctx.Data = &ConfigTemplate{
CookbookPaths: strings.Join(cookbook_paths, ","),
RolesPath: rolesPath,
DataBagsPath: dataBagsPath,
......@@ -373,7 +328,8 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local
HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "",
HasEnvironmentsPath: environmentsPath != "",
ChefEnvironment: chefEnvironment,
})
}
configString, err := interpolate.Render(tpl, &p.config.ctx)
if err != nil {
return "", err
}
......@@ -433,11 +389,12 @@ func (p *Provisioner) createDir(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
}
......@@ -462,9 +419,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
}
......@@ -533,24 +491,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
}
......
......@@ -3,12 +3,15 @@ package file
import (
"errors"
"fmt"
"os"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"os"
"github.com/mitchellh/packer/template/interpolate"
)
type config struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
// The local path of the file to upload.
......@@ -17,42 +20,25 @@ type config struct {
// The remote path where the local file will be uploaded to.
Destination string
tpl *packer.ConfigTemplate
ctx interpolate.Context
}
type Provisioner struct {
config config
config Config
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
p.config.tpl.UserVars = p.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"source": &p.config.Source,
"destination": &p.config.Destination,
}
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))
}
}
var errs *packer.MultiError
if _, err := os.Stat(p.config.Source); err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Bad source '%s': %s", p.config.Source, err))
......
......@@ -5,16 +5,19 @@ package puppetmasterless
import (
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os"
"path/filepath"
"strings"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type Config struct {
common.PackerConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
// The command used to execute Puppet.
ExecuteCommand string `mapstructure:"execute_command"`
......@@ -57,20 +60,18 @@ type ExecuteTemplate 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",
},
},
}, 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)
// Set some defaults
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{.FacterVars}} {{if .Sudo}} sudo -E {{end}}" +
......@@ -85,71 +86,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = "/tmp/packer-puppet-masterless"
}
// Templates
templates := map[string]*string{
"hiera_config_path": &p.config.HieraConfigPath,
"manifest_file": &p.config.ManifestFile,
"manifest_dir": &p.config.ManifestDir,
"staging_dir": &p.config.StagingDir,
}
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{
"module_paths": p.config.ModulePaths,
}
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,
}
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))
}
}
newFacts := make(map[string]string)
for k, v := range p.config.Facter {
k, err := p.config.tpl.Process(k, nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Error processing facter key %s: %s", k, err))
continue
}
v, err := p.config.tpl.Process(v, nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Error processing facter value '%s': %s", v, err))
continue
}
newFacts[k] = v
}
p.config.Facter = newFacts
// Validation
var errs *packer.MultiError
if p.config.HieraConfigPath != "" {
info, err := os.Stat(p.config.HieraConfigPath)
if err != nil {
......@@ -255,14 +193,15 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
}
// Execute Puppet
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteTemplate{
p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "),
HieraConfigPath: remoteHieraConfigPath,
ManifestDir: remoteManifestDir,
ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, ":"),
Sudo: !p.config.PreventSudo,
})
}
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil {
return err
}
......
......@@ -4,15 +4,18 @@ package puppetserver
import (
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os"
"strings"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
type Config struct {
common.PackerConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
// Additional facts to set when executing Puppet
Facter map[string]string
......@@ -55,62 +58,21 @@ type ExecuteTemplate struct {
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
p.config.tpl.UserVars = p.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
if p.config.StagingDir == "" {
p.config.StagingDir = "/tmp/packer-puppet-server"
}
// Templates
templates := map[string]*string{
"client_cert_dir": &p.config.ClientCertPath,
"client_private_key_dir": &p.config.ClientPrivateKeyPath,
"puppet_server": &p.config.PuppetServer,
"puppet_node": &p.config.PuppetNode,
"options": &p.config.Options,
}
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))
}
}
newFacts := make(map[string]string)
for k, v := range p.config.Facter {
k, err := p.config.tpl.Process(k, nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Error processing facter key %s: %s", k, err))
continue
}
v, err := p.config.tpl.Process(v, nil)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Error processing facter value '%s': %s", v, err))
continue
}
newFacts[k] = v
}
p.config.Facter = newFacts
var errs *packer.MultiError
if p.config.ClientCertPath != "" {
info, err := os.Stat(p.config.ClientCertPath)
if err != nil {
......@@ -178,7 +140,7 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
}
// Execute Puppet
command, err := p.config.tpl.Process(p.commandTemplate(), &ExecuteTemplate{
p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "),
ClientCertPath: remoteClientCertPath,
ClientPrivateKeyPath: remoteClientPrivateKeyPath,
......@@ -186,7 +148,8 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
PuppetServer: p.config.PuppetServer,
Options: p.config.Options,
Sudo: !p.config.PreventSudo,
})
}
command, err := interpolate.Render(p.commandTemplate(), &p.config.ctx)
if err != nil {
return err
}
......
......@@ -5,10 +5,13 @@ package saltmasterless
import (
"errors"
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os"
"path/filepath"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
const DefaultTempConfigDir = "/tmp/salt"
......@@ -32,7 +35,7 @@ type Config struct {
// Where files will be copied before moving to the /srv/salt directory
TempConfigDir string `mapstructure:"temp_config_dir"`
tpl *packer.ConfigTemplate
ctx interpolate.Context
}
type Provisioner struct {
......@@ -40,40 +43,21 @@ type Provisioner struct {
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...)
if err != nil {
return err
}
p.config.tpl, err = packer.NewConfigTemplate()
err := config.Decode(&p.config, &config.DecodeOpts{
Interpolate: true,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
p.config.tpl.UserVars = p.config.PackerUserVars
if p.config.TempConfigDir == "" {
p.config.TempConfigDir = DefaultTempConfigDir
}
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
templates := map[string]*string{
"bootstrap_args": &p.config.BootstrapArgs,
"minion_config": &p.config.MinionConfig,
"local_state_tree": &p.config.LocalStateTree,
"local_pillar_roots": &p.config.LocalPillarRoots,
"temp_config_dir": &p.config.TempConfigDir,
}
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))
}
}
var errs *packer.MultiError
// require a salt state tree
if p.config.LocalStateTree == "" {
......
......@@ -6,19 +6,22 @@ import (
"bufio"
"errors"
"fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"io"
"io/ioutil"
"log"
"os"
"strings"
"time"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/template/interpolate"
)
const DefaultRemotePath = "/tmp/script.sh"
type config struct {
type Config struct {
common.PackerConfig `mapstructure:",squash"`
// If true, the script contains binary and line endings will not be
......@@ -57,11 +60,11 @@ type config struct {
RawStartRetryTimeout string `mapstructure:"start_retry_timeout"`
startRetryTimeout time.Duration
tpl *packer.ConfigTemplate
ctx interpolate.Context
}
type Provisioner struct {
config config
config Config
}
type ExecuteCommandTemplate struct {
......@@ -70,20 +73,18 @@ type ExecuteCommandTemplate 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",
},
},
}, 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)
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
}
......@@ -112,6 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Vars = make([]string, 0)
}
var errs *packer.MultiError
if p.config.Script != "" && len(p.config.Scripts) > 0 {
errs = packer.MultiErrorAppend(errs,
errors.New("Only one of script or scripts can be specified."))
......@@ -121,39 +123,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Scripts = []string{p.config.Script}
}
templates := map[string]*string{
"inline_shebang": &p.config.InlineShebang,
"script": &p.config.Script,
"start_retry_timeout": &p.config.RawStartRetryTimeout,
"remote_path": &p.config.RemotePath,
}
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{
"inline": p.config.Inline,
"scripts": p.config.Scripts,
"environment_vars": p.config.Vars,
}
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))
}
}
}
if len(p.config.Scripts) == 0 && p.config.Inline == nil {
errs = packer.MultiErrorAppend(errs,
errors.New("Either a script file or inline script must be specified."))
......@@ -248,10 +217,11 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
flattendVars := strings.Join(envVars, " ")
// Compile the command
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{
p.config.ctx.Data = &ExecuteCommandTemplate{
Vars: flattendVars,
Path: p.config.RemotePath,
})
}
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil {
return fmt.Errorf("Error processing command: %s", err)
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment