diff --git a/builtin/provisioners/local-exec/resource_provisioner.go b/builtin/provisioners/local-exec/resource_provisioner.go index f537bb34a..3cb56f4a0 100644 --- a/builtin/provisioners/local-exec/resource_provisioner.go +++ b/builtin/provisioners/local-exec/resource_provisioner.go @@ -34,6 +34,11 @@ func Provisioner() terraform.ResourceProvisioner { Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, + + "working_dir": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + }, }, ApplyFunc: applyFn, @@ -69,6 +74,8 @@ func applyFn(ctx context.Context) error { } cmdargs = append(cmdargs, command) + workingdir := data.Get("working_dir").(string) + // Setup the reader that will read the output from the command. // We use an os.Pipe so that the *os.File can be passed directly to the // process, and not rely on goroutines copying the data which may block. @@ -82,6 +89,10 @@ func applyFn(ctx context.Context) error { cmd := exec.CommandContext(ctx, cmdargs[0], cmdargs[1:]...) cmd.Stderr = pw cmd.Stdout = pw + // Dir specifies the working directory of the command. + // If Dir is the empty string (this is default), runs the command + // in the calling process's current directory. + cmd.Dir = workingdir output, _ := circbuf.NewBuffer(maxBufSize) diff --git a/builtin/provisioners/local-exec/resource_provisioner_test.go b/builtin/provisioners/local-exec/resource_provisioner_test.go index a32b15c59..7db982f05 100644 --- a/builtin/provisioners/local-exec/resource_provisioner_test.go +++ b/builtin/provisioners/local-exec/resource_provisioner_test.go @@ -145,3 +145,32 @@ func TestResourceProvider_ApplyCustomInterpreter(t *testing.T) { t.Errorf("wrong output\ngot: %s\nwant: %s", got, want) } } + +func TestResourceProvider_ApplyCustomWorkingDirectory(t *testing.T) { + testdir := "working_dir_test" + os.Mkdir(testdir, 0755) + defer os.Remove(testdir) + + c := testConfig(t, map[string]interface{}{ + "working_dir": testdir, + "command": "echo `pwd`", + }) + + output := new(terraform.MockUIOutput) + p := Provisioner() + + if err := p.Apply(output, nil, c); err != nil { + t.Fatalf("err: %v", err) + } + + dir, err := os.Getwd() + if err != nil { + t.Fatalf("err: %v", err) + } + + got := strings.TrimSpace(output.OutputMessage) + want := dir + "/" + testdir + if got != want { + t.Errorf("wrong output\ngot: %s\nwant: %s", got, want) + } +} diff --git a/website/docs/provisioners/local-exec.html.markdown b/website/docs/provisioners/local-exec.html.markdown index bf08bf346..6dd79e7ba 100644 --- a/website/docs/provisioners/local-exec.html.markdown +++ b/website/docs/provisioners/local-exec.html.markdown @@ -39,6 +39,10 @@ The following arguments are supported: It is evaluated in a shell, and can use environment variables or Terraform variables. +* `working_dir` - (Optional) If provided, specifies the working directory where + `command` will be executed. It can be provided as as a relative path to the + current working directory or as an absolute path. The directory must exist. + * `interpreter` - (Optional) If provided, this is a list of interpreter arguments used to execute the command. The first argument is the interpreter itself. It can be provided as a relative path to the current