From 913ad33a11aa93247be0ab294a2c62b11cf917e0 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 20:40:13 -0400 Subject: [PATCH 1/8] standardize across both puppet-{masterless,server} --- provisioner/puppet-masterless/provisioner.go | 32 +++++++++++--------- provisioner/puppet-server/provisioner.go | 18 ++++++++--- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index c7360c646..959104ab4 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -71,8 +71,9 @@ type Config struct { } type guestOSTypeConfig struct { + tempDir string stagingDir string - executeCommand string + executeCommand string facterVarsFmt string facterVarsJoiner string modulePathJoiner string @@ -80,6 +81,8 @@ type guestOSTypeConfig struct { var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { + #FIXME assumes both Packer host and target are same OS + tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` + @@ -97,9 +100,11 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ modulePathJoiner: ":", }, provisioner.WindowsOSType: { - stagingDir: "C:/Windows/Temp/packer-puppet-masterless", + #FIXME assumes both Packer host and target are same OS + tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), + stagingDir: path.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 --detailed-exitcodes " + "{{if .Debug}}--debug {{end}}" + @@ -121,24 +126,23 @@ type Provisioner struct { } type ExecuteTemplate struct { - WorkingDir string - FacterVars string + FacterVars string HieraConfigPath string - ModulePath string - ManifestFile string - ManifestDir string - PuppetBinDir string - Sudo bool - WorkingDir string - Debug bool - ExtraArguments string + ModulePath string + ManifestFile string + ManifestDir string + PuppetBinDir string + Sudo bool + WorkingDir string + Debug bool + ExtraArguments string } func (p *Provisioner) Prepare(raws ...interface{}) error { err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ + InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "execute_command", "extra_arguments", diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 46263e72b..0ba1cfb7d 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -87,6 +87,10 @@ type Config struct { // permissions in this directory. StagingDir string `mapstructure:"staging_dir"` + // 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"` @@ -105,10 +109,11 @@ type guestOSTypeConfig struct { var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { + #FIXME assumes both Packer host and target are same OS tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + - "{{.FacterVars}}" + + `{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` + "{{if .Sudo}}sudo -E {{end}}" + `{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` + "puppet agent --onetime --no-daemonize --detailed-exitcodes " + @@ -122,10 +127,11 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ facterVarsJoiner: " ", }, provisioner.WindowsOSType: { + #FIXME assumes both Packer host and target are same OS tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + - "{{.FacterVars}} " + + `{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` + `{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` + "puppet agent --onetime --no-daemonize --detailed-exitcodes " + "{{if .Debug}}--debug {{end}}" + @@ -149,18 +155,20 @@ type ExecuteTemplate struct { FacterVars string ClientCertPath string ClientPrivateKeyPath string - PuppetNode string + PuppetNode string PuppetServer string - ExtraArguments string PuppetBinDir string Sudo bool + WorkingDir string + Debug bool + ExtraArguments string } func (p *Provisioner) Prepare(raws ...interface{}) error { err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ + InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "execute_command", "extra_arguments", From 0fa037d2970e86723c858ac1b373b590d55a80b6 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 21:38:51 -0400 Subject: [PATCH 2/8] move comments outside of datastructure --- provisioner/puppet-masterless/provisioner.go | 3 +-- provisioner/puppet-server/provisioner.go | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index 959104ab4..57a5311c7 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -79,9 +79,9 @@ type guestOSTypeConfig struct { modulePathJoiner string } +#FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { - #FIXME assumes both Packer host and target are same OS tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + @@ -100,7 +100,6 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ modulePathJoiner: ":", }, provisioner.WindowsOSType: { - #FIXME assumes both Packer host and target are same OS tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 0ba1cfb7d..485a252bd 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -107,9 +107,9 @@ type guestOSTypeConfig struct { facterVarsJoiner string } +#FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { - #FIXME assumes both Packer host and target are same OS tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + @@ -127,7 +127,6 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ facterVarsJoiner: " ", }, provisioner.WindowsOSType: { - #FIXME assumes both Packer host and target are same OS tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + From 25252f083eb753b9e221568aed904a86e86152a9 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 22:33:54 -0400 Subject: [PATCH 3/8] remove duplicated section --- provisioner/puppet-server/provisioner.go | 38 ------------------------ 1 file changed, 38 deletions(-) diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 485a252bd..19066faa6 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -14,44 +14,6 @@ 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 From bb1aed5264ff13ceaf029ea044f28ff2b81dce04 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 22:34:15 -0400 Subject: [PATCH 4/8] fix line-endings --- .gitattributes | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 7230f36f4..07e7d50e4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,3 @@ -common/test-fixtures/root/* eol=lf \ No newline at end of file +common/test-fixtures/root/* eol=lf +*.go eol=lf From d57842e06d764a7a01d6d3772c15cd41f310f216 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 22:44:16 -0400 Subject: [PATCH 5/8] Golang doesn't use C-style comments --- provisioner/puppet-masterless/provisioner.go | 2 +- provisioner/puppet-server/provisioner.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index 57a5311c7..347a20de9 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -79,7 +79,7 @@ type guestOSTypeConfig struct { modulePathJoiner string } -#FIXME assumes both Packer host and target are same OS +// FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { tempDir: "/tmp", diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 19066faa6..20ff54243 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -69,7 +69,7 @@ type guestOSTypeConfig struct { facterVarsJoiner string } -#FIXME assumes both Packer host and target are same OS +// FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { tempDir: "/tmp", From 2450e57fbee838f70a62d1dc0252c3eeb2fdc815 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 22:51:48 -0400 Subject: [PATCH 6/8] run gofmt for alignment and whitespace management --- provisioner/puppet-masterless/provisioner.go | 26 ++++++++++---------- provisioner/puppet-server/provisioner.go | 8 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index 347a20de9..c7bb6ddc2 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -73,7 +73,7 @@ type Config struct { type guestOSTypeConfig struct { tempDir string stagingDir string - executeCommand string + executeCommand string facterVarsFmt string facterVarsJoiner string modulePathJoiner string @@ -82,7 +82,7 @@ type guestOSTypeConfig struct { // FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { - tempDir: "/tmp", + tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` + @@ -100,7 +100,7 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ modulePathJoiner: ":", }, provisioner.WindowsOSType: { - tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), + tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` + @@ -125,23 +125,23 @@ type Provisioner struct { } type ExecuteTemplate struct { - FacterVars string + FacterVars string HieraConfigPath string - ModulePath string - ManifestFile string - ManifestDir string - PuppetBinDir string - Sudo bool - WorkingDir string - Debug bool - ExtraArguments string + ModulePath string + ManifestFile string + ManifestDir string + PuppetBinDir string + Sudo bool + WorkingDir string + Debug bool + ExtraArguments string } func (p *Provisioner) Prepare(raws ...interface{}) error { err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ + InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "execute_command", "extra_arguments", diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 20ff54243..146d40f9e 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -72,7 +72,7 @@ type guestOSTypeConfig struct { // FIXME assumes both Packer host and target are same OS var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.UnixOSType: { - tempDir: "/tmp", + tempDir: "/tmp", stagingDir: "/tmp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} {{end}}` + @@ -89,7 +89,7 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ facterVarsJoiner: " ", }, provisioner.WindowsOSType: { - tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), + tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-server", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` + @@ -116,7 +116,7 @@ type ExecuteTemplate struct { FacterVars string ClientCertPath string ClientPrivateKeyPath string - PuppetNode string + PuppetNode string PuppetServer string PuppetBinDir string Sudo bool @@ -129,7 +129,7 @@ func (p *Provisioner) Prepare(raws ...interface{}) error { err := config.Decode(&p.config, &config.DecodeOpts{ Interpolate: true, InterpolateContext: &p.config.ctx, - InterpolateFilter: &interpolate.RenderFilter{ + InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "execute_command", "extra_arguments", From 422b4a073ec8e2b64cfb0630e25aa9e326427f77 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 23:22:52 -0400 Subject: [PATCH 7/8] remove danling "options" and fix class reference --- provisioner/puppet-masterless/provisioner.go | 7 ++----- provisioner/puppet-server/provisioner.go | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner.go b/provisioner/puppet-masterless/provisioner.go index c7bb6ddc2..61494c9d7 100644 --- a/provisioner/puppet-masterless/provisioner.go +++ b/provisioner/puppet-masterless/provisioner.go @@ -65,9 +65,6 @@ type Config struct { // If true, packer will ignore all exit-codes from a puppet run IgnoreExitCodes bool `mapstructure:"ignore_exit_codes"` - - // The Guest OS Type (unix or windows) - GuestOSType string `mapstructure:"guest_os_type"` } type guestOSTypeConfig struct { @@ -100,8 +97,8 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ modulePathJoiner: ":", }, provisioner.WindowsOSType: { - tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), - stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless", + tempDir: filepath.ToSlash(os.Getenv("TEMP")), + stagingDir: filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-masterless", executeCommand: "cd {{.WorkingDir}} && " + `{{if ne .FacterVars ""}}{{.FacterVars}} && {{end}}` + `{{if ne .PuppetBinDir ""}}{{.PuppetBinDir}}/{{end}}` + diff --git a/provisioner/puppet-server/provisioner.go b/provisioner/puppet-server/provisioner.go index 146d40f9e..8bd29a40e 100644 --- a/provisioner/puppet-server/provisioner.go +++ b/provisioner/puppet-server/provisioner.go @@ -5,6 +5,7 @@ package puppetserver import ( "fmt" "os" + "path/filepath" "strings" "github.com/hashicorp/packer/common" @@ -89,8 +90,8 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ facterVarsJoiner: " ", }, provisioner.WindowsOSType: { - tempDir: path.filepath.ToSlash(os.Getenv("TEMP")), - stagingDir: path.filepath.ToSlash(os.Getenv("SYSTEMROOT")) + "/Temp/packer-puppet-server", + 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}}` + @@ -243,7 +244,6 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { ClientPrivateKeyPath: remoteClientPrivateKeyPath, PuppetNode: p.config.PuppetNode, PuppetServer: p.config.PuppetServer, - Options: p.config.Options, PuppetBinDir: p.config.PuppetBinDir, Sudo: !p.config.PreventSudo, WorkingDir: p.config.WorkingDir, From 1aa7358c13ebb825d58d325276cb676a5e398e23 Mon Sep 17 00:00:00 2001 From: Matthew Patton Date: Fri, 27 Apr 2018 23:41:31 -0400 Subject: [PATCH 8/8] syncronize tests to new command structure --- provisioner/puppet-masterless/provisioner_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/provisioner/puppet-masterless/provisioner_test.go b/provisioner/puppet-masterless/provisioner_test.go index dd6725768..fe64f28bd 100644 --- a/provisioner/puppet-masterless/provisioner_test.go +++ b/provisioner/puppet-masterless/provisioner_test.go @@ -53,7 +53,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) } @@ -89,8 +89,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) } @@ -115,7 +115,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 C:/Windows/Temp/packer-puppet-masterless && puppet apply --detailed-exitcodes /r/m/f" assert.Equal(t, expected, command) } @@ -152,8 +152,8 @@ func TestGuestOSConfig_full_windows(t *testing.T) { expected := "cd C:/Windows/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) }