Commit fd0df9ff authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

provisioners/puppet-masterless: support hiera configs

parent 41b70aae
...@@ -22,6 +22,9 @@ type Config struct { ...@@ -22,6 +22,9 @@ type Config struct {
// Additional facts to set when executing Puppet // Additional facts to set when executing Puppet
Facter map[string]string Facter map[string]string
// Path to a hiera configuration file to upload and use.
HieraConfigPath string `mapstructure:"hiera_config_path"`
// An array of local paths of modules to upload. // An array of local paths of modules to upload.
ModulePaths []string `mapstructure:"module_paths"` ModulePaths []string `mapstructure:"module_paths"`
...@@ -41,10 +44,12 @@ type Provisioner struct { ...@@ -41,10 +44,12 @@ type Provisioner struct {
} }
type ExecuteTemplate struct { type ExecuteTemplate struct {
FacterVars string FacterVars string
ModulePath string HasHieraConfigPath bool
ManifestFile string HieraConfigPath string
Sudo bool ModulePath string
ManifestFile string
Sudo bool
} }
func (p *Provisioner) Prepare(raws ...interface{}) error { func (p *Provisioner) Prepare(raws ...interface{}) error {
...@@ -64,7 +69,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -64,7 +69,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
// Set some defaults // Set some defaults
if p.config.ExecuteCommand == "" { if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = "{{.FacterVars}}{{if .Sudo}} sudo -E {{end}}puppet apply --verbose --modulepath='{{.ModulePath}}' {{.ManifestFile}}" p.config.ExecuteCommand = "{{.FacterVars}}{{if .Sudo}} sudo -E {{end}}" +
"puppet apply --verbose --modulepath='{{.ModulePath}}' " +
"{{if .HasHieraConfigPath}}--hiera_config='{{.HieraConfigPath}}' {{end}}" +
"{{.ManifestFile}}"
} }
if p.config.StagingDir == "" { if p.config.StagingDir == "" {
...@@ -133,6 +141,17 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { ...@@ -133,6 +141,17 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Facter = newFacts p.config.Facter = newFacts
// Validation // Validation
if p.config.HieraConfigPath != "" {
info, err := os.Stat(p.config.ManifestFile)
if err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("hiera_config_path is invalid: %s", err))
} else if info.IsDir() {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("hiera_config_path must point to a file"))
}
}
if p.config.ManifestFile == "" { if p.config.ManifestFile == "" {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
fmt.Errorf("A manifest_file must be specified.")) fmt.Errorf("A manifest_file must be specified."))
...@@ -171,6 +190,16 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -171,6 +190,16 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
return fmt.Errorf("Error creating staging directory: %s", err) return fmt.Errorf("Error creating staging directory: %s", err)
} }
// Upload hiera config if set
remoteHieraConfigPath := ""
if p.config.HieraConfigPath != "" {
var err error
remoteHieraConfigPath, err = p.uploadHieraConfig(ui, comm)
if err != nil {
return fmt.Errorf("Error uploading hiera config: %s", err)
}
}
// Upload all modules // Upload all modules
modulePaths := make([]string, 0, len(p.config.ModulePaths)) modulePaths := make([]string, 0, len(p.config.ModulePaths))
for i, path := range p.config.ModulePaths { for i, path := range p.config.ModulePaths {
...@@ -198,10 +227,12 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ...@@ -198,10 +227,12 @@ 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{ command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "), FacterVars: strings.Join(facterVars, " "),
ManifestFile: remoteManifestFile, HasHieraConfigPath: remoteHieraConfigPath != "",
ModulePath: strings.Join(modulePaths, ":"), HieraConfigPath: remoteHieraConfigPath,
Sudo: !p.config.PreventSudo, ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, ":"),
Sudo: !p.config.PreventSudo,
}) })
if err != nil { if err != nil {
return err return err
...@@ -229,6 +260,22 @@ func (p *Provisioner) Cancel() { ...@@ -229,6 +260,22 @@ func (p *Provisioner) Cancel() {
os.Exit(0) os.Exit(0)
} }
func (p *Provisioner) uploadHieraConfig(ui packer.Ui, comm packer.Communicator) (string, error) {
ui.Message("Uploading hiera configuration...")
f, err := os.Open(p.config.HieraConfigPath)
if err != nil {
return "", err
}
defer f.Close()
path := fmt.Sprintf("%s/hiera.yaml", p.config.StagingDir)
if err := comm.Upload(path, f); err != nil {
return "", err
}
return path, nil
}
func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) { func (p *Provisioner) uploadManifests(ui packer.Ui, comm packer.Communicator) (string, error) {
// Create the remote manifests directory... // Create the remote manifests directory...
ui.Message("Uploading manifests...") ui.Message("Uploading manifests...")
......
...@@ -26,6 +26,31 @@ func TestProvisioner_Impl(t *testing.T) { ...@@ -26,6 +26,31 @@ func TestProvisioner_Impl(t *testing.T) {
} }
} }
func TestProvisionerPrepare_hieraConfigPath(t *testing.T) {
config := testConfig()
delete(config, "hiera_config_path")
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
// Test with a good one
tf, err := ioutil.TempFile("", "packer")
if err != nil {
t.Fatalf("error tempfile: %s", err)
}
defer os.Remove(tf.Name())
config["hiera_config_path"] = tf.Name()
p = new(Provisioner)
err = p.Prepare(config)
if err != nil {
t.Fatalf("err: %s", err)
}
}
func TestProvisionerPrepare_manifestFile(t *testing.T) { func TestProvisionerPrepare_manifestFile(t *testing.T) {
config := testConfig() config := testConfig()
......
...@@ -54,6 +54,10 @@ Optional parameters: ...@@ -54,6 +54,10 @@ Optional parameters:
[facts](http://puppetlabs.com/puppet/related-projects/facter) to make [facts](http://puppetlabs.com/puppet/related-projects/facter) to make
available when Puppet is running. available when Puppet is running.
* `hiera_config_path` (string) - The path to a local file with hiera
configuration to be uploaded to the remote machine. Hiera data directories
must be uploaded using the file provisioner separately.
* `module_paths` (array of strings) - This is an array of paths to module * `module_paths` (array of strings) - This is an array of paths to module
directories on your local filesystem. These will be uploaded to the remote directories on your local filesystem. These will be uploaded to the remote
machine. By default, this is empty. machine. By default, this is empty.
...@@ -78,6 +82,7 @@ for readability) to execute Puppet: ...@@ -78,6 +82,7 @@ for readability) to execute Puppet:
{{.FacterVars}}{{if .Sudo} sudo -E {{end}}puppet apply \ {{.FacterVars}}{{if .Sudo} sudo -E {{end}}puppet apply \
--verbose \ --verbose \
--modulepath='{{.ModulePath}}' \ --modulepath='{{.ModulePath}}' \
{{if .HasHieraConfigPath}}--hiera_config='{{.HieraConfigPath}}' {{end}} \
{{.ManifestFile}} {{.ManifestFile}}
``` ```
...@@ -87,6 +92,8 @@ can contain various template variables, defined below: ...@@ -87,6 +92,8 @@ can contain various template variables, defined below:
* `FacterVars` - Shell-friendly string of environmental variables used * `FacterVars` - Shell-friendly string of environmental variables used
to set custom facts configured for this provisioner. to set custom facts configured for this provisioner.
* `HasHieraConfigPath` - Boolean true if there is a hiera config path set.
* `HieraConfigPath` - The path to a hiera configuration file.
* `ManifestFile` - The path on the remote machine to the manifest file * `ManifestFile` - The path on the remote machine to the manifest file
for Puppet to use. for Puppet to use.
* `ModulePath` - The paths to the module directories. * `ModulePath` - The paths to the module directories.
......
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