From 666796e8eb9a6a4bd128e7ac720ca88b665abaec Mon Sep 17 00:00:00 2001 From: Dave Sanderson Date: Tue, 12 Dec 2017 14:39:13 -0700 Subject: [PATCH] Add ability to stat a remote path --- provisioner/guest_commands.go | 7 ++++ provisioner/salt-masterless/provisioner.go | 40 ++++++++++++++----- .../docs/provisioners/salt-masterless.html.md | 2 + 3 files changed, 38 insertions(+), 11 deletions(-) diff --git a/provisioner/guest_commands.go b/provisioner/guest_commands.go index 715d6cb31..b186ef2bf 100644 --- a/provisioner/guest_commands.go +++ b/provisioner/guest_commands.go @@ -13,6 +13,7 @@ type guestOSTypeCommand struct { chmod string mkdir string removeDir string + statPath string } var guestOSTypeCommands = map[string]guestOSTypeCommand{ @@ -20,11 +21,13 @@ var guestOSTypeCommands = map[string]guestOSTypeCommand{ chmod: "chmod %s '%s'", mkdir: "mkdir -p '%s'", removeDir: "rm -rf '%s'", + statPath: "stat '%s'", }, WindowsOSType: { chmod: "echo 'skipping chmod %s %s'", // no-op mkdir: "powershell.exe -Command \"New-Item -ItemType directory -Force -ErrorAction SilentlyContinue -Path %s\"", removeDir: "powershell.exe -Command \"rm %s -recurse -force\"", + statPath: "powershell.exe -Commond \"test-path %s\"", }, } @@ -64,6 +67,10 @@ func (g *GuestCommands) escapePath(path string) string { return path } +func (g *GuestCommands) StatPath(path string) string { + return g.sudo(fmt.Sprintf(g.commands().statPath, g.escapePath(path))) +} + func (g *GuestCommands) sudo(cmd string) string { if g.GuestOSType == UnixOSType && g.Sudo { return "sudo " + cmd diff --git a/provisioner/salt-masterless/provisioner.go b/provisioner/salt-masterless/provisioner.go index 1e9cffc48..16566865f 100644 --- a/provisioner/salt-masterless/provisioner.go +++ b/provisioner/salt-masterless/provisioner.go @@ -17,10 +17,6 @@ import ( "github.com/hashicorp/packer/template/interpolate" ) -const DefaultTempConfigDir = "/tmp/salt" -const DefaultStateTreeDir = "/srv/salt" -const DefaultPillarRootDir = "/srv/pillar" - type Config struct { common.PackerConfig `mapstructure:",squash"` @@ -102,9 +98,9 @@ var guestOSTypeConfigs = map[string]guestOSTypeConfig{ provisioner.WindowsOSType: { configDir: "C:/salt/conf", tempDir: "C:/Windows/Temp/salt/", - stateRoot: "C:/srv/salt/", - pillarRoot: "C:/srv/pillar/", - bootstrapFetchCmd: "Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.ps1' -OutFile 'C:/Windows/Temp/bootstrap-salt.ps1'", + stateRoot: "C:/salt/state", + pillarRoot: "C:/salt/pillar/", + bootstrapFetchCmd: "powershell Invoke-WebRequest -Uri 'https://raw.githubusercontent.com/saltstack/salt-bootstrap/stable/bootstrap-salt.ps1' -OutFile 'C:/Windows/Temp/bootstrap-salt.ps1'", bootstrapRunCmd: "Powershell C:/Windows/Temp/bootstrap-salt.ps1", }, } @@ -305,9 +301,14 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { } else { dst = p.guestOSTypeConfig.stateRoot } - if err = p.removeDir(ui, comm, dst); err != nil { - return fmt.Errorf("Unable to clear salt tree: %s", err) + + // only remove state tree if it exists or windows throws a fit + if err = p.statPath(ui, comm, dst); err == nil { + if err = p.removeDir(ui, comm, dst); err != nil { + return fmt.Errorf("Unable to clear salt tree: %s", err) + } } + if err = p.moveFile(ui, comm, dst, src); err != nil { return fmt.Errorf("Unable to move %s/states to %s: %s", p.config.TempConfigDir, dst, err) } @@ -327,8 +328,11 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error { } else { dst = p.guestOSTypeConfig.pillarRoot } - if err = p.removeDir(ui, comm, dst); err != nil { - return fmt.Errorf("Unable to clear pillar root: %s", err) + // only remove path if it exists or windows throws a fit + if err = p.statPath(ui, comm, dst); err == nil { + if err = p.removeDir(ui, comm, dst); err != nil { + return fmt.Errorf("Unable to clear pillar root: %s", err) + } } if err = p.moveFile(ui, comm, dst, src); err != nil { return fmt.Errorf("Unable to move %s/pillar to %s: %s", p.config.TempConfigDir, dst, err) @@ -433,6 +437,20 @@ func (p *Provisioner) createDir(ui packer.Ui, comm packer.Communicator, dir stri return nil } +func (p *Provisioner) statPath(ui packer.Ui, comm packer.Communicator, path string) error { + ui.Message(fmt.Sprintf("Verifying Path: %s", path)) + cmd := &packer.RemoteCmd{ + Command: p.guestCommands.StatPath(path), + } + 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) removeDir(ui packer.Ui, comm packer.Communicator, dir string) error { ui.Message(fmt.Sprintf("Removing directory: %s", dir)) cmd := &packer.RemoteCmd{ diff --git a/website/source/docs/provisioners/salt-masterless.html.md b/website/source/docs/provisioners/salt-masterless.html.md index 443f37561..ad6920614 100644 --- a/website/source/docs/provisioners/salt-masterless.html.md +++ b/website/source/docs/provisioners/salt-masterless.html.md @@ -90,3 +90,5 @@ Optional: - `salt_bin_dir` (string) - Path to the `salt-call` executable. Useful if it is not on the PATH. + +- `guest_os_type` (string) - The target guest OS type, either "unix" or "windows".