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

provisioner/*: interpolation

parent c2381be4
...@@ -7,12 +7,15 @@ import ( ...@@ -7,12 +7,15 @@ import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "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 { type Config struct {
...@@ -34,7 +37,7 @@ type Config struct { ...@@ -34,7 +37,7 @@ type Config struct {
SkipInstall bool `mapstructure:"skip_install"` SkipInstall bool `mapstructure:"skip_install"`
StagingDir string `mapstructure:"staging_directory"` StagingDir string `mapstructure:"staging_directory"`
tpl *packer.ConfigTemplate ctx interpolate.Context
} }
type Provisioner struct { type Provisioner struct {
...@@ -69,16 +72,18 @@ type InstallChefTemplate struct { ...@@ -69,16 +72,18 @@ type InstallChefTemplate struct {
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...) err := config.Decode(&p.config, &config.DecodeOpts{
if err != nil { Interpolate: true,
return err InterpolateFilter: &interpolate.RenderFilter{
} Exclude: []string{
"execute_command",
p.config.tpl, err = packer.NewConfigTemplate() "install_command",
},
},
}, raws...)
if err != nil { if err != nil {
return err return err
} }
p.config.tpl.UserVars = p.config.PackerUserVars
if p.config.ExecuteCommand == "" { if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{if .Sudo}}sudo {{end}}chef-solo --no-color -c {{.ConfigPath}} -j {{.JsonPath}}" 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 { ...@@ -96,57 +101,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = "/tmp/packer-chef-solo" p.config.StagingDir = "/tmp/packer-chef-solo"
} }
// Accumulate any errors var errs *packer.MultiError
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))
}
}
if p.config.ConfigTemplate != "" { if p.config.ConfigTemplate != "" {
fi, err := os.Stat(p.config.ConfigTemplate) fi, err := os.Stat(p.config.ConfigTemplate)
if err != nil { if err != nil {
...@@ -362,7 +317,7 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local ...@@ -362,7 +317,7 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local
tpl = string(tplBytes) tpl = string(tplBytes)
} }
configString, err := p.config.tpl.Process(tpl, &ConfigTemplate{ p.config.ctx.Data = &ConfigTemplate{
CookbookPaths: strings.Join(cookbook_paths, ","), CookbookPaths: strings.Join(cookbook_paths, ","),
RolesPath: rolesPath, RolesPath: rolesPath,
DataBagsPath: dataBagsPath, DataBagsPath: dataBagsPath,
...@@ -373,7 +328,8 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local ...@@ -373,7 +328,8 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, local
HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "", HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "",
HasEnvironmentsPath: environmentsPath != "", HasEnvironmentsPath: environmentsPath != "",
ChefEnvironment: chefEnvironment, ChefEnvironment: chefEnvironment,
}) }
configString, err := interpolate.Render(tpl, &p.config.ctx)
if err != nil { if err != nil {
return "", err return "", err
} }
...@@ -433,11 +389,12 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri ...@@ -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 { 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, ConfigPath: config,
JsonPath: json, JsonPath: json,
Sudo: !p.config.PreventSudo, Sudo: !p.config.PreventSudo,
}) }
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil { if err != nil {
return err return err
} }
...@@ -462,9 +419,10 @@ func (p *Provisioner) executeChef(ui packer.Ui, comm packer.Communicator, config ...@@ -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 { func (p *Provisioner) installChef(ui packer.Ui, comm packer.Communicator) error {
ui.Message("Installing Chef...") ui.Message("Installing Chef...")
command, err := p.config.tpl.Process(p.config.InstallCommand, &InstallChefTemplate{ p.config.ctx.Data = &InstallChefTemplate{
Sudo: !p.config.PreventSudo, Sudo: !p.config.PreventSudo,
}) }
command, err := interpolate.Render(p.config.InstallCommand, &p.config.ctx)
if err != nil { if err != nil {
return err return err
} }
...@@ -533,24 +491,25 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) { ...@@ -533,24 +491,25 @@ func (p *Provisioner) processJsonUserVars() (map[string]interface{}, error) {
// Copy the user variables so that we can restore them later, and // Copy the user variables so that we can restore them later, and
// make sure we make the quotes JSON-friendly in the user variables. // make sure we make the quotes JSON-friendly in the user variables.
originalUserVars := make(map[string]string) originalUserVars := make(map[string]string)
for k, v := range p.config.tpl.UserVars { for k, v := range p.config.ctx.UserVariables {
originalUserVars[k] = v originalUserVars[k] = v
} }
// Make sure we reset them no matter what // Make sure we reset them no matter what
defer func() { defer func() {
p.config.tpl.UserVars = originalUserVars p.config.ctx.UserVariables = originalUserVars
}() }()
// Make the current user variables JSON string safe. // 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)
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 // 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 { if err != nil {
return nil, err return nil, err
} }
......
...@@ -3,12 +3,15 @@ package file ...@@ -3,12 +3,15 @@ package file
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"github.com/mitchellh/packer/common" "github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/config"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"os" "github.com/mitchellh/packer/template/interpolate"
) )
type config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
// The local path of the file to upload. // The local path of the file to upload.
...@@ -17,42 +20,25 @@ type config struct { ...@@ -17,42 +20,25 @@ type config struct {
// The remote path where the local file will be uploaded to. // The remote path where the local file will be uploaded to.
Destination string Destination string
tpl *packer.ConfigTemplate ctx interpolate.Context
} }
type Provisioner struct { type Provisioner struct {
config config config Config
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...) err := config.Decode(&p.config, &config.DecodeOpts{
if err != nil { Interpolate: true,
return err InterpolateFilter: &interpolate.RenderFilter{
} Exclude: []string{},
},
p.config.tpl, err = packer.NewConfigTemplate() }, raws...)
if err != nil { if err != nil {
return err 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 { if _, err := os.Stat(p.config.Source); err != nil {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
fmt.Errorf("Bad source '%s': %s", p.config.Source, err)) fmt.Errorf("Bad source '%s': %s", p.config.Source, err))
......
...@@ -5,16 +5,19 @@ package puppetmasterless ...@@ -5,16 +5,19 @@ package puppetmasterless
import ( import (
"fmt" "fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os" "os"
"path/filepath" "path/filepath"
"strings" "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 { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate ctx interpolate.Context
// The command used to execute Puppet. // The command used to execute Puppet.
ExecuteCommand string `mapstructure:"execute_command"` ExecuteCommand string `mapstructure:"execute_command"`
...@@ -57,20 +60,18 @@ type ExecuteTemplate struct { ...@@ -57,20 +60,18 @@ type ExecuteTemplate struct {
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { 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 { if err != nil {
return err 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 // Set some defaults
if p.config.ExecuteCommand == "" { if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{.FacterVars}} {{if .Sudo}} sudo -E {{end}}" + p.config.ExecuteCommand = "{{.FacterVars}} {{if .Sudo}} sudo -E {{end}}" +
...@@ -85,71 +86,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -85,71 +86,8 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = "/tmp/packer-puppet-masterless" 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 // Validation
var errs *packer.MultiError
if p.config.HieraConfigPath != "" { if p.config.HieraConfigPath != "" {
info, err := os.Stat(p.config.HieraConfigPath) info, err := os.Stat(p.config.HieraConfigPath)
if err != nil { if err != nil {
...@@ -255,14 +193,15 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -255,14 +193,15 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
} }
// Execute Puppet // Execute Puppet
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteTemplate{ p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "), FacterVars: strings.Join(facterVars, " "),
HieraConfigPath: remoteHieraConfigPath, HieraConfigPath: remoteHieraConfigPath,
ManifestDir: remoteManifestDir, ManifestDir: remoteManifestDir,
ManifestFile: remoteManifestFile, ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, ":"), ModulePath: strings.Join(modulePaths, ":"),
Sudo: !p.config.PreventSudo, Sudo: !p.config.PreventSudo,
}) }
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -4,15 +4,18 @@ package puppetserver ...@@ -4,15 +4,18 @@ package puppetserver
import ( import (
"fmt" "fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os" "os"
"strings" "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 { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
tpl *packer.ConfigTemplate ctx interpolate.Context
// Additional facts to set when executing Puppet // Additional facts to set when executing Puppet
Facter map[string]string Facter map[string]string
...@@ -55,62 +58,21 @@ type ExecuteTemplate struct { ...@@ -55,62 +58,21 @@ type ExecuteTemplate struct {
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...) err := config.Decode(&p.config, &config.DecodeOpts{
if err != nil { Interpolate: true,
return err InterpolateFilter: &interpolate.RenderFilter{
} Exclude: []string{},
},
p.config.tpl, err = packer.NewConfigTemplate() }, raws...)
if err != nil { if err != nil {
return err return err
} }
p.config.tpl.UserVars = p.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
if p.config.StagingDir == "" { if p.config.StagingDir == "" {
p.config.StagingDir = "/tmp/packer-puppet-server" p.config.StagingDir = "/tmp/packer-puppet-server"
} }
// Templates var errs *packer.MultiError
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
if p.config.ClientCertPath != "" { if p.config.ClientCertPath != "" {
info, err := os.Stat(p.config.ClientCertPath) info, err := os.Stat(p.config.ClientCertPath)
if err != nil { if err != nil {
...@@ -178,7 +140,7 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -178,7 +140,7 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
} }
// Execute Puppet // Execute Puppet
command, err := p.config.tpl.Process(p.commandTemplate(), &ExecuteTemplate{ p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "), FacterVars: strings.Join(facterVars, " "),
ClientCertPath: remoteClientCertPath, ClientCertPath: remoteClientCertPath,
ClientPrivateKeyPath: remoteClientPrivateKeyPath, ClientPrivateKeyPath: remoteClientPrivateKeyPath,
...@@ -186,7 +148,8 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -186,7 +148,8 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
PuppetServer: p.config.PuppetServer, PuppetServer: p.config.PuppetServer,
Options: p.config.Options, Options: p.config.Options,
Sudo: !p.config.PreventSudo, Sudo: !p.config.PreventSudo,
}) }
command, err := interpolate.Render(p.commandTemplate(), &p.config.ctx)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -5,10 +5,13 @@ package saltmasterless ...@@ -5,10 +5,13 @@ package saltmasterless
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"os" "os"
"path/filepath" "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" const DefaultTempConfigDir = "/tmp/salt"
...@@ -32,7 +35,7 @@ type Config struct { ...@@ -32,7 +35,7 @@ type Config struct {
// Where files will be copied before moving to the /srv/salt directory // Where files will be copied before moving to the /srv/salt directory
TempConfigDir string `mapstructure:"temp_config_dir"` TempConfigDir string `mapstructure:"temp_config_dir"`
tpl *packer.ConfigTemplate ctx interpolate.Context
} }
type Provisioner struct { type Provisioner struct {
...@@ -40,40 +43,21 @@ type Provisioner struct { ...@@ -40,40 +43,21 @@ type Provisioner struct {
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
md, err := common.DecodeConfig(&p.config, raws...) err := config.Decode(&p.config, &config.DecodeOpts{
if err != nil { Interpolate: true,
return err InterpolateFilter: &interpolate.RenderFilter{
} Exclude: []string{},
},
p.config.tpl, err = packer.NewConfigTemplate() }, raws...)
if err != nil { if err != nil {
return err return err
} }
p.config.tpl.UserVars = p.config.PackerUserVars
if p.config.TempConfigDir == "" { if p.config.TempConfigDir == "" {
p.config.TempConfigDir = DefaultTempConfigDir p.config.TempConfigDir = DefaultTempConfigDir
} }
// Accumulate any errors var errs *packer.MultiError
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))
}
}
// require a salt state tree // require a salt state tree
if p.config.LocalStateTree == "" { if p.config.LocalStateTree == "" {
......
...@@ -6,19 +6,22 @@ import ( ...@@ -6,19 +6,22 @@ import (
"bufio" "bufio"
"errors" "errors"
"fmt" "fmt"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer"
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
"os" "os"
"strings" "strings"
"time" "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" const DefaultRemotePath = "/tmp/script.sh"
type config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
// If true, the script contains binary and line endings will not be // If true, the script contains binary and line endings will not be
...@@ -57,11 +60,11 @@ type config struct { ...@@ -57,11 +60,11 @@ type config struct {
RawStartRetryTimeout string `mapstructure:"start_retry_timeout"` RawStartRetryTimeout string `mapstructure:"start_retry_timeout"`
startRetryTimeout time.Duration startRetryTimeout time.Duration
tpl *packer.ConfigTemplate ctx interpolate.Context
} }
type Provisioner struct { type Provisioner struct {
config config config Config
} }
type ExecuteCommandTemplate struct { type ExecuteCommandTemplate struct {
...@@ -70,20 +73,18 @@ type ExecuteCommandTemplate struct { ...@@ -70,20 +73,18 @@ type ExecuteCommandTemplate struct {
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { 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 { if err != nil {
return err 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 == "" { if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}" p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
} }
...@@ -112,6 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -112,6 +113,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Vars = make([]string, 0) p.config.Vars = make([]string, 0)
} }
var errs *packer.MultiError
if p.config.Script != "" && len(p.config.Scripts) > 0 { if p.config.Script != "" && len(p.config.Scripts) > 0 {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
errors.New("Only one of script or scripts can be specified.")) errors.New("Only one of script or scripts can be specified."))
...@@ -121,39 +123,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -121,39 +123,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Scripts = []string{p.config.Script} 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 { if len(p.config.Scripts) == 0 && p.config.Inline == nil {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
errors.New("Either a script file or inline script must be specified.")) 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 { ...@@ -248,10 +217,11 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
flattendVars := strings.Join(envVars, " ") flattendVars := strings.Join(envVars, " ")
// Compile the command // Compile the command
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteCommandTemplate{ p.config.ctx.Data = &ExecuteCommandTemplate{
Vars: flattendVars, Vars: flattendVars,
Path: p.config.RemotePath, Path: p.config.RemotePath,
}) }
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil { if err != nil {
return fmt.Errorf("Error processing command: %s", err) 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