diff --git a/builtin/bins/provisioner-local-exec/main.go b/builtin/bins/provisioner-local-exec/main.go new file mode 100644 index 000000000..eb697e57b --- /dev/null +++ b/builtin/bins/provisioner-local-exec/main.go @@ -0,0 +1,10 @@ +package main + +import ( + "github.com/hashicorp/terraform/builtin/provisioners/local-exec" + "github.com/hashicorp/terraform/plugin" +) + +func main() { + plugin.Serve(new(localexec.ResourceProvisioner)) +} diff --git a/builtin/bins/provisioner-local-exec/main_test.go b/builtin/bins/provisioner-local-exec/main_test.go new file mode 100644 index 000000000..06ab7d0f9 --- /dev/null +++ b/builtin/bins/provisioner-local-exec/main_test.go @@ -0,0 +1 @@ +package main diff --git a/builtin/provisioners/local-exec/resource_provisioner.go b/builtin/provisioners/local-exec/resource_provisioner.go new file mode 100644 index 000000000..7c8e01230 --- /dev/null +++ b/builtin/provisioners/local-exec/resource_provisioner.go @@ -0,0 +1,65 @@ +package localexec + +import ( + "fmt" + "os/exec" + "runtime" + + "github.com/armon/circbuf" + "github.com/hashicorp/terraform/helper/config" + "github.com/hashicorp/terraform/terraform" +) + +const ( + // maxBufSize limits how much output we collect from a local + // invocation. This is to prevent TF memory usage from growing + // to an enormous amount due to a faulty process. + maxBufSize = 8 * 1024 +) + +type ResourceProvisioner struct{} + +func (p *ResourceProvisioner) Apply( + s *terraform.ResourceState, + c *terraform.ResourceConfig) (*terraform.ResourceState, error) { + + // Get the command + commandRaw, ok := c.Get("command") + if !ok { + return s, fmt.Errorf("local-exec provisioner missing 'command'") + } + command, ok := commandRaw.(string) + if !ok { + return s, fmt.Errorf("local-exec provisioner command must be a string") + } + + // Execute the command using a shell + var shell, flag string + if runtime.GOOS == "windows" { + shell = "cmd" + flag = "/C" + } else { + shell = "/bin/sh" + flag = "-c" + } + + // Setup the command + cmd := exec.Command(shell, flag, command) + output, _ := circbuf.NewBuffer(maxBufSize) + cmd.Stderr = output + cmd.Stdout = output + + // Run the command to completion + if err := cmd.Run(); err != nil { + return s, fmt.Errorf("Error running command '%s': %v. Output: %s", + command, err, output.Bytes()) + } + return s, nil +} + +func (p *ResourceProvisioner) Validate(c *terraform.ResourceConfig) ([]string, []error) { + validator := config.Validator{ + Required: []string{"command"}, + } + return validator.Validate(c) +} diff --git a/builtin/provisioners/local-exec/resource_provisioner_test.go b/builtin/provisioners/local-exec/resource_provisioner_test.go new file mode 100644 index 000000000..a066fc996 --- /dev/null +++ b/builtin/provisioners/local-exec/resource_provisioner_test.go @@ -0,0 +1,11 @@ +package localexec + +import ( + "testing" + + "github.com/hashicorp/terraform/terraform" +) + +func TestResourceProvisioner_impl(t *testing.T) { + var _ terraform.ResourceProvisioner = new(ResourceProvisioner) +}