Seperate remote_path into remote_folder and remote_script. (#3462)

Commonly /tmp is set as noexec, as a result packer scripts
fail to run. In order to get around this one can set a
remote_path, whoever, remote path requires full filename
and path.

By making remote_path a combination of
remote_folder/remote_script we can change remote_folder
and keep the default script_nnn.sh

Signed-off-by: Ian Duffy <ian@ianduffy.ie>
This commit is contained in:
Ian Duffy 2016-04-27 00:04:29 +01:00 committed by Chris Bednarski
parent d296260164
commit 7e653370b7
3 changed files with 157 additions and 5 deletions

View File

@ -44,8 +44,17 @@ type Config struct {
// your command(s) are executed.
Vars []string `mapstructure:"environment_vars"`
// The remote folder where the local shell script will be uploaded to.
// This should be set to a pre-existing directory, it defaults to /tmp
RemoteFolder string `mapstructure:"remote_folder"`
// The remote file name of the local shell script.
// This defaults to script_nnn.sh
RemoteFile string `mapstructure:"remote_file"`
// The remote path where the local shell script will be uploaded to.
// This should be set to a writable file that is in a pre-existing directory.
// This defaults to remote_folder/remote_file
RemotePath string `mapstructure:"remote_path"`
// The command used to execute the script. The '{{ .Path }}' variable
@ -104,9 +113,17 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
p.config.RawStartRetryTimeout = "5m"
}
if p.config.RemoteFolder == "" {
p.config.RemoteFolder = "/tmp"
}
if p.config.RemoteFile == "" {
p.config.RemoteFile = fmt.Sprintf("script_%d.sh", rand.Intn(9999))
}
if p.config.RemotePath == "" {
p.config.RemotePath = fmt.Sprintf(
"/tmp/script_%d.sh", rand.Intn(9999))
"%s/%s", p.config.RemoteFolder, p.config.RemoteFile)
}
if p.config.Scripts == nil {

View File

@ -5,6 +5,8 @@ import (
"io/ioutil"
"os"
"testing"
"strings"
"regexp"
)
func testConfig() map[string]interface{} {
@ -217,3 +219,131 @@ func TestProvisionerQuote_EnvironmentVars(t *testing.T) {
t.Fatalf("%s should be equal to %s", p.config.Vars[1], expectedValue)
}
}
func TestProvisioner_RemoteFolderSetSuccessfully(t *testing.T) {
config := testConfig()
expectedRemoteFolder := "/example/path"
config["remote_folder"] = expectedRemoteFolder
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if !strings.Contains(p.config.RemotePath, expectedRemoteFolder) {
t.Fatalf("remote path does not contain remote_folder")
}
}
func TestProvisioner_RemoteFolderDefaultsToTmp(t *testing.T) {
config := testConfig()
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if p.config.RemoteFolder != "/tmp" {
t.Fatalf("remote_folder did not default to /tmp")
}
if !strings.Contains(p.config.RemotePath, "/tmp") {
t.Fatalf("remote path does not contain remote_folder")
}
}
func TestProvisioner_RemoteFileSetSuccessfully(t *testing.T) {
config := testConfig()
expectedRemoteFile := "example.sh"
config["remote_file"] = expectedRemoteFile
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if !strings.Contains(p.config.RemotePath, expectedRemoteFile) {
t.Fatalf("remote path does not contain remote_file")
}
}
func TestProvisioner_RemoteFileDefaultsToScriptnnnn(t *testing.T) {
config := testConfig()
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
remoteFileRegex := regexp.MustCompile("script_[0-9]{4}.sh")
if !remoteFileRegex.MatchString(p.config.RemoteFile) {
t.Fatalf("remote_file did not default to script_nnnn.sh")
}
if !remoteFileRegex.MatchString(p.config.RemotePath) {
t.Fatalf("remote_path did not match script_nnnn.sh")
}
}
func TestProvisioner_RemotePathSetViaRemotePathAndRemoteFile(t *testing.T) {
config := testConfig()
expectedRemoteFile := "example.sh"
expectedRemoteFolder := "/example/path"
config["remote_file"] = expectedRemoteFile
config["remote_folder"] = expectedRemoteFolder
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if p.config.RemotePath != expectedRemoteFolder + "/" + expectedRemoteFile {
t.Fatalf("remote path does not contain remote_file")
}
}
func TestProvisioner_RemotePathOverridesRemotePathAndRemoteFile(t *testing.T) {
config := testConfig()
expectedRemoteFile := "example.sh"
expectedRemoteFolder := "/example/path"
expectedRemotePath := "/example/remote/path/script.sh"
config["remote_file"] = expectedRemoteFile
config["remote_folder"] = expectedRemoteFolder
config["remote_path"] = expectedRemotePath
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if p.config.RemotePath != expectedRemotePath {
t.Fatalf("remote path does not contain remote_path")
}
}
func TestProvisionerRemotePathDefaultsSuccessfully(t *testing.T) {
config := testConfig()
p := new(Provisioner)
err := p.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
remotePathRegex := regexp.MustCompile("/tmp/script_[0-9]{4}.sh")
if !remotePathRegex.MatchString(p.config.RemotePath) {
t.Fatalf("remote path does not match the expected default regex")
}
}

View File

@ -78,10 +78,15 @@ Optional parameters:
**Important:** If you customize this, be sure to include something like the
`-e` flag, otherwise individual steps failing won't fail the provisioner.
- `remote_path` (string) - The filename where the script will be uploaded
to in the machine. This defaults to `/tmp/script_nnn.sh` where "nnn" is
a randomly generated number. This value must be a writable location and
any parent directories must already exist.
- `remote_folder` (string) - The folder where the uploaded script will reside on
the machine. This defaults to '/tmp'.
- `remote_file` (string) - The filename the uploaded script will have on the machine.
This defaults to 'script_nnn.sh'.
- `remote_path` (string) - The full path to the uploaded script will have on the
machine. By default this is remote_folder/remote_file, if set this option will
override both remote_folder and remote_file.
- `skip_clean` (boolean) - If true, specifies that the helper scripts
uploaded to the system will not be removed by Packer. This defaults to