provisioners/puppet-masterless: support hiera configs

This commit is contained in:
Mitchell Hashimoto 2013-09-09 13:24:17 -07:00
parent 41b70aae99
commit fd0df9ff58
3 changed files with 88 additions and 9 deletions

View File

@ -22,6 +22,9 @@ type Config struct {
// Additional facts to set when executing Puppet
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.
ModulePaths []string `mapstructure:"module_paths"`
@ -41,10 +44,12 @@ type Provisioner struct {
}
type ExecuteTemplate struct {
FacterVars string
ModulePath string
ManifestFile string
Sudo bool
FacterVars string
HasHieraConfigPath bool
HieraConfigPath string
ModulePath string
ManifestFile string
Sudo bool
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
@ -64,7 +69,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
// Set some defaults
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 == "" {
@ -133,6 +141,17 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.Facter = newFacts
// 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 == "" {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("A manifest_file must be specified."))
@ -171,6 +190,16 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
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
modulePaths := make([]string, 0, len(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 {
// Execute Puppet
command, err := p.config.tpl.Process(p.config.ExecuteCommand, &ExecuteTemplate{
FacterVars: strings.Join(facterVars, " "),
ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, ":"),
Sudo: !p.config.PreventSudo,
FacterVars: strings.Join(facterVars, " "),
HasHieraConfigPath: remoteHieraConfigPath != "",
HieraConfigPath: remoteHieraConfigPath,
ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, ":"),
Sudo: !p.config.PreventSudo,
})
if err != nil {
return err
@ -229,6 +260,22 @@ func (p *Provisioner) Cancel() {
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) {
// Create the remote manifests directory...
ui.Message("Uploading manifests...")

View File

@ -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) {
config := testConfig()

View File

@ -54,6 +54,10 @@ Optional parameters:
[facts](http://puppetlabs.com/puppet/related-projects/facter) to make
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
directories on your local filesystem. These will be uploaded to the remote
machine. By default, this is empty.
@ -78,6 +82,7 @@ for readability) to execute Puppet:
{{.FacterVars}}{{if .Sudo} sudo -E {{end}}puppet apply \
--verbose \
--modulepath='{{.ModulePath}}' \
{{if .HasHieraConfigPath}}--hiera_config='{{.HieraConfigPath}}' {{end}} \
{{.ManifestFile}}
```
@ -87,6 +92,8 @@ can contain various template variables, defined below:
* `FacterVars` - Shell-friendly string of environmental variables used
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
for Puppet to use.
* `ModulePath` - The paths to the module directories.