Merge pull request #6215 from tb3088/delay-extraArgs-4462_clean

Delay evaluation of ExtraArguments and standardize puppet-server and puppet-masterless
This commit is contained in:
M. Marsh 2018-05-08 15:03:55 -07:00 committed by GitHub
commit abb70bfa80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 300 additions and 237 deletions

View File

@ -20,6 +20,12 @@ type Config struct {
common.PackerConfig `mapstructure:",squash"`
ctx interpolate.Context
// If true, staging directory is removed after executing puppet.
CleanStagingDir bool `mapstructure:"clean_staging_directory"`
// The Guest OS Type (unix or windows)
GuestOSType string `mapstructure:"guest_os_type"`
// The command used to execute Puppet.
ExecuteCommand string `mapstructure:"execute_command"`
@ -32,6 +38,9 @@ type Config struct {
// Path to a hiera configuration file to upload and use.
HieraConfigPath string `mapstructure:"hiera_config_path"`
// If true, packer will ignore all exit-codes from a puppet run
IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"`
// An array of local paths of modules to upload.
ModulePaths []string `mapstructure:"module_paths"`
@ -45,47 +54,42 @@ type Config struct {
// If true, `sudo` will NOT be used to execute Puppet.
PreventSudo bool `mapstructure:"prevent_sudo"`
// The directory where files will be uploaded. Packer requires write
// permissions in this directory.
StagingDir string `mapstructure:"staging_directory"`
// If true, staging directory is removed after executing puppet.
CleanStagingDir bool `mapstructure:"clean_staging_directory"`
// The directory from which the command will be executed.
// Packer requires the directory to exist when running puppet.
WorkingDir string `mapstructure:"working_directory"`
// The directory that contains the puppet binary.
// E.g. if it can't be found on the standard path.
PuppetBinDir string `mapstructure:"puppet_bin_dir"`
// If true, packer will ignore all exit-codes from a puppet run
IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"`
// The directory where files will be uploaded. Packer requires write
// permissions in this directory.
StagingDir string `mapstructure:"staging_directory"`
// The Guest OS Type (unix or windows)
GuestOSType string `mapstructure:"guest_os_type"`
// The directory from which the command will be executed.
// Packer requires the directory to exist when running puppet.
WorkingDir string `mapstructure:"working_directory"`
}
type guestOSTypeConfig struct {
stagingDir string
executeCommand string
facterVarsFmt string
facterVarsJoiner string
modulePathJoiner string
stagingDir string
tempDir string
}
// FIXME assumes both Packer host and target are same OS
var guestOSTypeConfigs = map[string]guestOSTypeConfig{
provisioner.UnixOSType: {
tempDir: "/tmp",
stagingDir: "/tmp/packer-puppet-masterless",
executeCommand: "cd {{.WorkingDir}} && " +
`{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` +
"{{if .Sudo}}sudo -E {{end}}" +
`{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` +
`puppet apply --verbose --modulepath='{{.ModulePath}}' ` +
"puppet apply --detailed-exitcodes " +
"{{if .Debug}}--debug {{end}}" +
`{{if ne .ModulePath ""}}--modulepath='{{.ModulePath}}' {{end}}` +
`{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}` +
`{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}` +
"--detailed-exitcodes " +
`{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}` +
"{{.ManifestFile}}",
facterVarsFmt: "FACTER_%s='%s'",
@ -93,14 +97,16 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{
modulePathJoiner: ":",
},
provisioner.WindowsOSType: {
stagingDir: "C:/Windows/Temp/packer-puppet-masterless",
tempDir: filepath.ToSlash(os.Getenv("TEMP")),
stagingDir: filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless",
executeCommand: "cd {{.WorkingDir}} && " +
"{{.FacterVars}} && " +
`{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` +
`{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` +
`puppet apply --verbose --modulepath='{{.ModulePath}}' ` +
"puppet apply --detailed-exitcodes " +
"{{if .Debug}}--debug {{end}}" +
`{{if ne .ModulePath ""}}--modulepath='{{.ModulePath}}' {{end}}` +
`{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}` +
`{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}` +
"--detailed-exitcodes " +
`{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}` +
"{{.ManifestFile}}",
facterVarsFmt: `SET "FACTER_%s=%s"`,
@ -116,15 +122,17 @@ type Provisioner struct {
}
type ExecuteTemplate struct {
WorkingDir string
FacterVars string
HieraConfigPath string
ModulePath string
ManifestFile string
ManifestDir string
PuppetBinDir string
Sudo bool
ExtraArguments string
Debug bool
ExtraArguments string
FacterVars string
HieraConfigPath string
ModulePath string
ModulePathJoiner string
ManifestFile string
ManifestDir string
PuppetBinDir string
Sudo bool
WorkingDir string
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
@ -134,6 +142,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"execute_command",
"extra_arguments",
},
},
}, raws...)
@ -162,10 +171,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.ExecuteCommand = p.guestOSTypeConfig.executeCommand
}
if p.config.ExecuteCommand == "" {
p.config.ExecuteCommand = p.guestOSTypeConfig.executeCommand
}
if p.config.StagingDir == "" {
p.config.StagingDir = p.guestOSTypeConfig.stagingDir
}
@ -286,18 +291,26 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
facterVars = append(facterVars, fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, k, v))
}
// Execute Puppet
p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
HieraConfigPath: remoteHieraConfigPath,
ManifestDir: remoteManifestDir,
ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, p.guestOSTypeConfig.modulePathJoiner),
PuppetBinDir: p.config.PuppetBinDir,
Sudo: !p.config.PreventSudo,
WorkingDir: p.config.WorkingDir,
ExtraArguments: strings.Join(p.config.ExtraArguments, " "),
data := ExecuteTemplate{
ExtraArguments: "",
FacterVars: strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
HieraConfigPath: remoteHieraConfigPath,
ManifestDir: remoteManifestDir,
ManifestFile: remoteManifestFile,
ModulePath: strings.Join(modulePaths, p.guestOSTypeConfig.modulePathJoiner),
ModulePathJoiner: p.guestOSTypeConfig.modulePathJoiner,
PuppetBinDir: p.config.PuppetBinDir,
Sudo: !p.config.PreventSudo,
WorkingDir: p.config.WorkingDir,
}
p.config.ctx.Data = &data
_ExtraArguments, err := interpolate.Render(strings.Join(p.config.ExtraArguments, " "), &p.config.ctx)
if err != nil {
return err
}
data.ExtraArguments = _ExtraArguments
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil {
return err

View File

@ -5,6 +5,7 @@ import (
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"testing"
@ -58,7 +59,7 @@ func TestGuestOSConfig_empty_unix(t *testing.T) {
}
expected := "cd /tmp/packer-puppet-masterless && " +
"sudo -E puppet apply --verbose --modulepath='' --detailed-exitcodes /r/m/f"
"sudo -E puppet apply --detailed-exitcodes /r/m/f"
assert.Equal(t, expected, command)
}
@ -97,8 +98,8 @@ func TestGuestOSConfig_full_unix(t *testing.T) {
expected := "cd /tmp/packer-puppet-masterless && FACTER_lhs='rhs' FACTER_foo='bar' " +
"sudo -E puppet apply " +
"--verbose --modulepath='/m/p:/a/b' --hiera_config='/h/c/p' " +
"--manifestdir='/r/m/d' --detailed-exitcodes /r/m/f"
"--detailed-exitcodes --modulepath='/m/p:/a/b' --hiera_config='/h/c/p' " +
"--manifestdir='/r/m/d' /r/m/f"
assert.Equal(t, expected, command)
}
@ -126,7 +127,7 @@ func TestGuestOSConfig_empty_windows(t *testing.T) {
t.Fatalf("err: %s", err)
}
expected := "cd C:/Windows/Temp/packer-puppet-masterless && && puppet apply --verbose --modulepath='' --detailed-exitcodes /r/m/f"
expected := "cd " + filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless && puppet apply --detailed-exitcodes /r/m/f"
assert.Equal(t, expected, command)
}
@ -164,10 +165,10 @@ func TestGuestOSConfig_full_windows(t *testing.T) {
t.Fatalf("err: %s", err)
}
expected := "cd C:/Windows/Temp/packer-puppet-masterless && " +
expected := "cd " + filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless && " +
"SET \"FACTER_lhs=rhs\" & SET \"FACTER_foo=bar\" && " +
"puppet apply --verbose --modulepath='/m/p;/a/b' --hiera_config='/h/c/p' " +
"--manifestdir='/r/m/d' --detailed-exitcodes /r/m/f"
"puppet apply --detailed-exitcodes --modulepath='/m/p;/a/b' --hiera_config='/h/c/p' " +
"--manifestdir='/r/m/d' /r/m/f"
assert.Equal(t, expected, command)
}

View File

@ -5,6 +5,7 @@ package puppetserver
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/hashicorp/packer/common"
@ -14,56 +15,12 @@ import (
"github.com/hashicorp/packer/template/interpolate"
)
type guestOSTypeConfig struct {
executeCommand string
facterVarsFmt string
facterVarsJoiner string
stagingDir string
}
var guestOSTypeConfigs = map[string]guestOSTypeConfig{
provisioner.UnixOSType: {
executeCommand: "{{.FacterVars}} {{if .Sudo}}sudo -E {{end}}" +
"{{if ne .PuppetBinDir \"\"}}{{.PuppetBinDir}}/{{end}}puppet agent " +
"--onetime --no-daemonize " +
"{{if ne .PuppetServer \"\"}}--server='{{.PuppetServer}}' {{end}}" +
"{{if ne .Options \"\"}}{{.Options}} {{end}}" +
"{{if ne .PuppetNode \"\"}}--certname={{.PuppetNode}} {{end}}" +
"{{if ne .ClientCertPath \"\"}}--certdir='{{.ClientCertPath}}' {{end}}" +
"{{if ne .ClientPrivateKeyPath \"\"}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}" +
"--detailed-exitcodes",
facterVarsFmt: "FACTER_%s='%s'",
facterVarsJoiner: " ",
stagingDir: "/tmp/packer-puppet-server",
},
provisioner.WindowsOSType: {
executeCommand: "{{.FacterVars}} " +
"{{if ne .PuppetBinDir \"\"}}{{.PuppetBinDir}}/{{end}}puppet agent " +
"--onetime --no-daemonize " +
"{{if ne .PuppetServer \"\"}}--server='{{.PuppetServer}}' {{end}}" +
"{{if ne .Options \"\"}}{{.Options}} {{end}}" +
"{{if ne .PuppetNode \"\"}}--certname={{.PuppetNode}} {{end}}" +
"{{if ne .ClientCertPath \"\"}}--certdir='{{.ClientCertPath}}' {{end}}" +
"{{if ne .ClientPrivateKeyPath \"\"}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}" +
"--detailed-exitcodes",
facterVarsFmt: "SET \"FACTER_%s=%s\"",
facterVarsJoiner: " & ",
stagingDir: "C:/Windows/Temp/packer-puppet-server",
},
}
type Config struct {
common.PackerConfig `mapstructure:",squash"`
ctx interpolate.Context
// The command used to execute Puppet.
ExecuteCommand string `mapstructure:"execute_command"`
// The Guest OS Type (unix or windows)
GuestOSType string `mapstructure:"guest_os_type"`
// Additional facts to set when executing Puppet
Facter map[string]string
// If true, staging directory is removed after executing puppet.
CleanStagingDir bool `mapstructure:"clean_staging_directory"`
// A path to the client certificate
ClientCertPath string `mapstructure:"client_cert_path"`
@ -71,28 +28,86 @@ type Config struct {
// A path to a directory containing the client private keys
ClientPrivateKeyPath string `mapstructure:"client_private_key_path"`
// The command used to execute Puppet.
ExecuteCommand string `mapstructure:"execute_command"`
// Additional argument to pass when executing Puppet.
ExtraArguments []string `mapstructure:"extra_arguments"`
// Additional facts to set when executing Puppet
Facter map[string]string
// The Guest OS Type (unix or windows)
GuestOSType string `mapstructure:"guest_os_type"`
// If true, packer will ignore all exit-codes from a puppet run
IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"`
// If true, `sudo` will NOT be used to execute Puppet.
PreventSudo bool `mapstructure:"prevent_sudo"`
// The directory that contains the puppet binary.
// E.g. if it can't be found on the standard path.
PuppetBinDir string `mapstructure:"puppet_bin_dir"`
// The hostname of the Puppet node.
PuppetNode string `mapstructure:"puppet_node"`
// The hostname of the Puppet server.
PuppetServer string `mapstructure:"puppet_server"`
// Additional options to be passed to `puppet agent`.
Options string `mapstructure:"options"`
// If true, `sudo` will NOT be used to execute Puppet.
PreventSudo bool `mapstructure:"prevent_sudo"`
// The directory where files will be uploaded. Packer requires write
// permissions in this directory.
StagingDir string `mapstructure:"staging_dir"`
// The directory that contains the puppet binary.
// E.g. if it can't be found on the standard path.
PuppetBinDir string `mapstructure:"puppet_bin_dir"`
// The directory from which the command will be executed.
// Packer requires the directory to exist when running puppet.
WorkingDir string `mapstructure:"working_directory"`
}
// If true, packer will ignore all exit-codes from a puppet run
IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"`
type guestOSTypeConfig struct {
executeCommand string
facterVarsFmt string
facterVarsJoiner string
stagingDir string
tempDir string
}
// FIXME assumes both Packer host and target are same OS
var guestOSTypeConfigs = map[string]guestOSTypeConfig{
provisioner.UnixOSType: {
tempDir: "/tmp",
stagingDir: "/tmp/packer-puppet-server",
executeCommand: "cd {{.WorkingDir}} && " +
`{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` +
"{{if .Sudo}}sudo -E {{end}}" +
`{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` +
"puppet agent --onetime --no-daemonize --detailed-exitcodes " +
"{{if .Debug}}--debug {{end}}" +
`{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}` +
`{{if ne .PuppetNode ""}}--certname='{{.PuppetNode}}' {{end}}` +
`{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}` +
`{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}` +
`{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}`,
facterVarsFmt: "FACTER_%s='%s'",
facterVarsJoiner: " ",
},
provisioner.WindowsOSType: {
tempDir: filepath.ToSlash(os.Getenv("TEMP")),
stagingDir: filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-server",
executeCommand: "cd {{.WorkingDir}} && " +
`{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` +
`{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` +
"puppet agent --onetime --no-daemonize --detailed-exitcodes " +
"{{if .Debug}}--debug {{end}}" +
`{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}` +
`{{if ne .PuppetNode ""}}--certname='{{.PuppetNode}}' {{end}}` +
`{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}` +
`{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}` +
`{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}`,
facterVarsFmt: `SET "FACTER_%s=%s"`,
facterVarsJoiner: " & ",
},
}
type Provisioner struct {
@ -102,14 +117,16 @@ type Provisioner struct {
}
type ExecuteTemplate struct {
FacterVars string
ClientCertPath string
ClientPrivateKeyPath string
Debug bool
ExtraArguments string
FacterVars string
PuppetNode string
PuppetServer string
Options string
PuppetBinDir string
Sudo bool
WorkingDir string
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
@ -119,6 +136,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"execute_command",
"extra_arguments",
},
},
}, raws...)
@ -150,6 +168,10 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.StagingDir = p.guestOSTypeConfig.stagingDir
}
if p.config.WorkingDir == "" {
p.config.WorkingDir = p.config.StagingDir
}
if p.config.Facter == nil {
p.config.Facter = make(map[string]string)
}
@ -223,17 +245,25 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
facterVars = append(facterVars, fmt.Sprintf(p.guestOSTypeConfig.facterVarsFmt, k, v))
}
// Execute Puppet
p.config.ctx.Data = &ExecuteTemplate{
FacterVars: strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
data := ExecuteTemplate{
ClientCertPath: remoteClientCertPath,
ClientPrivateKeyPath: remoteClientPrivateKeyPath,
ExtraArguments: "",
FacterVars: strings.Join(facterVars, p.guestOSTypeConfig.facterVarsJoiner),
PuppetNode: p.config.PuppetNode,
PuppetServer: p.config.PuppetServer,
Options: p.config.Options,
PuppetBinDir: p.config.PuppetBinDir,
Sudo: !p.config.PreventSudo,
WorkingDir: p.config.WorkingDir,
}
p.config.ctx.Data = &data
_ExtraArguments, err := interpolate.Render(strings.Join(p.config.ExtraArguments, " "), &p.config.ctx)
if err != nil {
return err
}
data.ExtraArguments = _ExtraArguments
command, err := interpolate.Render(p.config.ExecuteCommand, &p.config.ctx)
if err != nil {
return err
@ -252,6 +282,12 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
return fmt.Errorf("Puppet exited with a non-zero exit status: %d", cmd.ExitStatus)
}
if p.config.CleanStagingDir {
if err := p.removeDir(ui, comm, p.config.StagingDir); err != nil {
return fmt.Errorf("Error removing staging directory: %s", err)
}
}
return nil
}
@ -284,6 +320,22 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri
return nil
}
func (p *Provisioner) removeDir(ui packer.Ui, comm packer.Communicator, dir string) error {
cmd := &packer.RemoteCmd{
Command: fmt.Sprintf("rm -fr '%s'", dir),
}
if err := cmd.StartWithUi(comm, ui); err != nil {
return err
}
if cmd.ExitStatus != 0 {
return fmt.Errorf("Non-zero exit status.")
}
return nil
}
func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
if err := p.createDir(ui, comm, dst); err != nil {
return err

View File

@ -54,68 +54,64 @@ Required parameters:
Optional parameters:
- `execute_command` (string) - The command used to execute Puppet. This has
various [configuration template
variables](/docs/templates/engine.html) available. See
below for more information.
- `execute_command` (string) - The command-line to execute Puppet. This also has
various [configuration template variables](/docs/templates/engine.html) available.
- `extra_arguments` (array of strings) - This is an array of additional options to
pass to the puppet command when executing puppet. This allows for
customization of the `execute_command` without having to completely replace
or include it's contents, making forward-compatible customizations much
easier.
- `extra_arguments` (array of strings) - Additional options to
pass to the Puppet command. This allows for customization of
`execute_command` without having to completely replace
or subsume its contents, making forward-compatible customizations much
easier to maintain.
This string is lazy-evaluated so one can incorporate logic driven by template variables as
well as private elements of ExecuteTemplate (see source: provisioner/puppet-masterless/provisioner.go).
```
[
{{if ne "{{user environment}}" ""}}--environment={{user environment}}{{end}},
{{if ne ".ModulePath" ""}}--modulepath="{{.ModulePath}}{{.ModulePathJoiner}}$(puppet config print {{if ne "{{user `environment`}}" ""}}--environment={{user `environment`}}{{end}} modulepath)"{{end}}
]
```
- `facter` (object of key/value strings) - Additional
- `facter` (object of key:value strings) - Additional
[facts](https://puppetlabs.com/facter) to make
available when Puppet is running.
available to the Puppet run.
- `guest_os_type` (string) - The target guest OS type, either "unix" or
"windows". Setting this to "windows" will cause the provisioner to use
Windows friendly paths and commands. By default, this is "unix".
- `guest_os_type` (string) - The remote host's OS type ('windows' or 'unix') to
tailor command-line and path separators. (default: unix).
- `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.
- `hiera_config_path` (string) - Local path to self-contained Hiera
data to be uploaded. NOTE: If you need data directories
they must be previously transferred with a File provisioner.
- `ignore_exit_codes` (boolean) - If true, Packer will never consider the
provisioner a failure.
- `ignore_exit_codes` (boolean) - If true, Packer will ignore failures.
- `manifest_dir` (string) - The path to a local directory with manifests to be
uploaded to the remote machine. This is useful if your main manifest file
uses imports. This directory doesn't necessarily contain the
`manifest_file`. It is a separate directory that will be set as the
"manifestdir" setting on Puppet.
- `manifest_dir` (string) - Local directory with manifests to be
uploaded. This is useful if your main manifest uses imports, but the
directory might not contain the `manifest_file` itself.
~> `manifest_dir` is passed to `puppet apply` as the `--manifestdir` option.
~> `manifest_dir` is passed to Puppet as `--manifestdir` option.
This option was deprecated in puppet 3.6, and removed in puppet 4.0. If you have
multiple manifests you should use `manifest_file` instead.
- `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.
- `module_paths` (array of strings) - Array of local module
directories to be uploaded.
- `prevent_sudo` (boolean) - By default, the configured commands that are
executed to run Puppet are executed with `sudo`. If this is true, then the
sudo will be omitted.
- `prevent_sudo` (boolean) - On Unix platforms Puppet is typically invoked with `sudo`. If true,
it will be omitted. (default: false)
- `puppet_bin_dir` (string) - The path to the directory that contains the puppet
binary for running `puppet apply`. Usually, this would be found via the `$PATH`
or `%PATH%` environment variable, but some builders (notably, the Docker one) do
not run profile-setup scripts, therefore the path is usually empty.
- `puppet_bin_dir` (string) - Path to the Puppet binary. Ideally the program
should be on the system (unix: `$PATH`, windows: `%PATH%`), but some builders (eg. Docker) do
not run profile-setup scripts and therefore PATH might be empty or minimal.
- `staging_directory` (string) - This is the directory where all the configuration
of Puppet by Packer will be placed. By default this is "/tmp/packer-puppet-masterless"
when guest OS type is unix and "C:/Windows/Temp/packer-puppet-masterless" when windows.
This directory doesn't need to exist but must have proper permissions so that the SSH
user that Packer uses is able to create directories and write into this folder.
If the permissions are not correct, use a shell provisioner prior to this to configure
it properly.
- `staging_directory` (string) - Directory to where uploaded files
will be placed (unix: "/tmp/packer-puppet-masterless",
windows: "%SYSTEMROOT%/Temp/packer-puppet-masterless").
It doesn't need to pre-exist, but the parent must have permissions sufficient
for the account Packer connects as to create directories and write files.
Use a Shell provisioner to prepare the way if needed.
- `working_directory` (string) - This is the directory from which the puppet
command will be run. When using hiera with a relative path, this option
allows to ensure that the paths are working properly. If not specified,
defaults to the value of specified `staging_directory` (or its default value
if not specified either).
- `working_directory` (string) - Directory from which `execute_command` will be run.
If using Hiera files with relative paths, this option can be helpful. (default: `staging_directory`)
## Execute Command
@ -124,45 +120,33 @@ readability) to execute Puppet:
```
cd {{.WorkingDir}} &&
{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}
{{if .Sudo}}sudo -E {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet apply --verbose --modulepath='{{.ModulePath}}'
{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}
{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}
--detailed-exitcodes
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
{{.ManifestFile}}
{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}
{{if .Sudo}}sudo -E {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet apply --detailed-exitcodes
{{if .Debug}}--debug {{end}}
{{if ne .ModulePath ""}}--modulepath='{{.ModulePath}}' {{end}}
{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}
{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
{{.ManifestFile}}
```
The following command is used if guest OS type is windows:
```
cd {{.WorkingDir}} &&
{{.FacterVars}} &&
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet apply --verbose --modulepath='{{.ModulePath}}'
{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}
{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}
--detailed-exitcodes
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
{{.ManifestFile}}
{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet apply --detailed-exitcodes
{{if .Debug}}--debug {{end}}
{{if ne .ModulePath ""}}--modulepath='{{.ModulePath}}' {{end}}
{{if ne .HieraConfigPath ""}}--hiera_config='{{.HieraConfigPath}}' {{end}}
{{if ne .ManifestDir ""}}--manifestdir='{{.ManifestDir}}' {{end}}
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
{{.ManifestFile}}
```
This command can be customized using the `execute_command` configuration. As you
can see from the default value above, the value of this configuration can
contain various template variables, defined below:
- `WorkingDir` - The path from which Puppet will be executed.
- `FacterVars` - Shell-friendly string of environmental variables used to set
custom facts configured for this provisioner.
- `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.
- `Sudo` - A boolean of whether to `sudo` the command or not, depending on the
value of the `prevent_sudo` configuration.
## Default Facts
In addition to being able to specify custom Facter facts using the `facter`

View File

@ -50,31 +50,38 @@ listed below:
contains the client private key for the node. This defaults to nothing, in
which case a client private key won't be uploaded.
- `execute_command` (string) - The command used to execute Puppet. This has
- `execute_command` (string) - The command-line to execute Puppet. This also has
various [configuration template variables](/docs/templates/engine.html) available.
See below for more information.
- `facter` (object of key/value strings) - Additional Facter facts to make
- `extra_arguments` (array of strings) - Additional options to
pass to the Puppet command. This allows for customization of
`execute_command` without having to completely replace
or subsume its contents, making forward-compatible customizations much
easier to maintain.
This string is lazy-evaluated so one can incorporate logic driven by template variables as
well as private elements of ExecuteTemplate (see source: provisioner/puppet-server/provisioner.go).
```
[
{{if ne "{{user environment}}" ""}}--environment={{user environment}}{{end}}
]
```
- `facter` (object of key/value strings) - Additional
[facts](https://puppetlabs.com/facter) to make
available to the Puppet run.
- `guest_os_type` (string) - The target guest OS type, either "unix" or
"windows". Setting this to "windows" will cause the provisioner to use
Windows friendly paths and commands. By default, this is "unix".
- `guest_os_type` (string) - The remote host's OS type ('windows' or 'unix') to
tailor command-line and path separators. (default: unix).
- `ignore_exit_codes` (boolean) - If true, Packer will never consider the
provisioner a failure.
- `ignore_exit_codes` (boolean) - If true, Packer will ignore failures.
- `options` (string) - Additional command line options to pass to
`puppet agent` when Puppet is run.
- `prevent_sudo` (boolean) - On Unix platforms Puppet is typically invoked with `sudo`. If true,
it will be omitted. (default: false)
- `prevent_sudo` (boolean) - By default, the configured commands that are
executed to run Puppet are executed with `sudo`. If this is true, then the
sudo will be omitted.
- `puppet_bin_dir` (string) - The path to the directory that contains the puppet
binary for running `puppet agent`. Usually, this would be found via the `$PATH`
or `%PATH%` environment variable, but some builders (notably, the Docker one) do
not run profile-setup scripts, therefore the path is usually empty.
- `puppet_bin_dir` (string) - Path to the Puppet binary. Ideally the program
should be on the system (unix: `$PATH`, windows: `%PATH%`), but some builders (eg. Docker) do
not run profile-setup scripts and therefore PATH might be empty or minimal.
- `puppet_node` (string) - The name of the node. If this isn't set, the fully
qualified domain name will be used.
@ -82,42 +89,48 @@ listed below:
- `puppet_server` (string) - Hostname of the Puppet server. By default
"puppet" will be used.
- `staging_dir` (string) - This is the directory where all the
configuration of Puppet by Packer will be placed. By default this
is /tmp/packer-puppet-server. This directory doesn't need to exist but
must have proper permissions so that the SSH user that Packer uses is able
to create directories and write into this folder. If the permissions are not
correct, use a shell provisioner prior to this to configure it properly.
- `staging_dir` (string) - Directory to where uploaded files
will be placed (unix: "/tmp/packer-puppet-masterless",
windows: "%SYSTEMROOT%/Temp/packer-puppet-masterless").
It doesn't need to pre-exist, but the parent must have permissions sufficient
for the account Packer connects as to create directories and write files.
Use a Shell provisioner to prepare the way if needed.
## Execute Command
- `working_directory` (string) - Directory from which `execute_command` will be run.
If using Hiera files with relative paths, this option can be helpful. (default: `staging_directory`)
## Execute Command
By default, Packer uses the following command (broken across multiple lines for
readability) to execute Puppet:
```
{{.FacterVars}} {{if .Sudo}}sudo -E {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}puppet agent
--onetime --no-daemonize
{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}
{{if ne .Options ""}}{{.Options}} {{end}}
{{if ne .PuppetNode ""}}--certname={{.PuppetNode}} {{end}}
{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}
{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}
--detailed-exitcodes
cd {{.WorkingDir}} &&
{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}
{{if .Sudo}}sudo -E {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet agent --onetime --no-daemonize --detailed-exitcodes
{{if .Debug}}--debug {{end}}
{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}
{{if ne .PuppetNode ""}}--certname='{{.PuppetNode}}' {{end}}
{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}
{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
```
The following command is used if guest OS type is windows:
```
{{.FacterVars}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}puppet agent
--onetime --no-daemonize
{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}
{{if ne .Options ""}}{{.Options}} {{end}}
{{if ne .PuppetNode ""}}--certname={{.PuppetNode}} {{end}}
{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}
{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}
--detailed-exitcodes
cd {{.WorkingDir}} &&
{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}
{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}
puppet agent --onetime --no-daemonize --detailed-exitcodes
{{if .Debug}}--debug {{end}}
{{if ne .PuppetServer ""}}--server='{{.PuppetServer}}' {{end}}
{{if ne .PuppetNode ""}}--certname='{{.PuppetNode}}' {{end}}
{{if ne .ClientCertPath ""}}--certdir='{{.ClientCertPath}}' {{end}}
{{if ne .ClientPrivateKeyPath ""}}--privatekeydir='{{.ClientPrivateKeyPath}}' {{end}}
{{if ne .ExtraArguments ""}}{{.ExtraArguments}} {{end}}
```
## Default Facts