diff --git a/builtin/provisioners/local-exec/resource_provisioner.go b/builtin/provisioners/local-exec/resource_provisioner.go index f537bb34ab57..056f5ac14c44 100644 --- a/builtin/provisioners/local-exec/resource_provisioner.go +++ b/builtin/provisioners/local-exec/resource_provisioner.go @@ -28,12 +28,15 @@ func Provisioner() terraform.ResourceProvisioner { Type: schema.TypeString, Required: true, }, - "interpreter": &schema.Schema{ Type: schema.TypeList, Elem: &schema.Schema{Type: schema.TypeString}, Optional: true, }, + "environment": &schema.Schema{ + Type: schema.TypeMap, + Optional: true, + }, }, ApplyFunc: applyFn, @@ -45,13 +48,21 @@ func applyFn(ctx context.Context) error { o := ctx.Value(schema.ProvOutputKey).(terraform.UIOutput) command := data.Get("command").(string) - if command == "" { return fmt.Errorf("local-exec provisioner command must be a non-empty string") } + var env []string + env = make([]string, len(environment)) + for k := range environment { + entry := fmt.Sprintf("%s=%s", k, environment[k].(string)) + env = append(env, entry) + } + // Execute the command using a shell interpreter := data.Get("interpreter").([]interface{}) + // Execute the command with env + environment := data.Get("environment").(map[string]interface{}) var cmdargs []string if len(interpreter) > 0 { @@ -78,10 +89,15 @@ func applyFn(ctx context.Context) error { return fmt.Errorf("failed to initialize pipe for output: %s", err) } + var cmdEnv []string + cmdEnv = os.Environ() + cmdEnv = append(cmdEnv, env...) + // Setup the command cmd := exec.CommandContext(ctx, cmdargs[0], cmdargs[1:]...) cmd.Stderr = pw cmd.Stdout = pw + cmd.Env = cmdEnv 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 a32b15c5958e..d5c1bbe8c71a 100644 --- a/builtin/provisioners/local-exec/resource_provisioner_test.go +++ b/builtin/provisioners/local-exec/resource_provisioner_test.go @@ -145,3 +145,27 @@ func TestResourceProvider_ApplyCustomInterpreter(t *testing.T) { t.Errorf("wrong output\ngot: %s\nwant: %s", got, want) } } + +func TestResourceProvider_ApplyCustomEnv(t *testing.T) { + c := testConfig(t, map[string]interface{}{ + "command": "echo $FOO $BAR $BAZ", + "environment": map[string]interface{}{ + "FOO": "BAR", + "BAR": 1, + "BAZ": "true", + }, + }) + + output := new(terraform.MockUIOutput) + p := Provisioner() + + if err := p.Apply(output, nil, c); err != nil { + t.Fatalf("err: %v", err) + } + + got := strings.TrimSpace(output.OutputMessage) + want := "BAR 1 true" + 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 bf08bf346958..5bd5c4f39fad 100644 --- a/website/docs/provisioners/local-exec.html.markdown +++ b/website/docs/provisioners/local-exec.html.markdown @@ -47,6 +47,9 @@ The following arguments are supported: form "/bin/bash", "-c", "echo foo". If `interpreter` is unspecified, sensible defaults will be chosen based on the system OS. +* `environment` - (Optional) block of key value pairs representing the + environment of the executed command. inherits the current process environment. + ### Interpreter Examples ```hcl @@ -66,3 +69,19 @@ resource "null_resource" "example2" { } } ``` + +```hcl +resource "aws_instance" "web" { + # ... + + provisioner "local-exec" { + command = "echo $FOO $BAR $BAZ >> env_vars.txt" + + environment { + FOO = "bar" + BAR = 1 + BAZ = "true" + } + } +} +```