terraform/builtin/provisioners/local-exec/resource_provisioner_test.go

177 lines
4.1 KiB
Go

package localexec
import (
"io/ioutil"
"os"
"strings"
"testing"
"time"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
func TestResourceProvisioner_impl(t *testing.T) {
var _ terraform.ResourceProvisioner = Provisioner()
}
func TestProvisioner(t *testing.T) {
if err := Provisioner().(*schema.Provisioner).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}
func TestResourceProvider_Apply(t *testing.T) {
defer os.Remove("test_out")
c := testConfig(t, map[string]interface{}{
"command": "echo foo > test_out",
})
output := new(terraform.MockUIOutput)
p := Provisioner()
if err := p.Apply(output, nil, c); err != nil {
t.Fatalf("err: %v", err)
}
// Check the file
raw, err := ioutil.ReadFile("test_out")
if err != nil {
t.Fatalf("err: %v", err)
}
actual := strings.TrimSpace(string(raw))
expected := "foo"
if actual != expected {
t.Fatalf("bad: %#v", actual)
}
}
func TestResourceProvider_stop(t *testing.T) {
c := testConfig(t, map[string]interface{}{
// bash/zsh/ksh will exec a single command in the same process. This
// makes certain there's a subprocess in the shell.
"command": "sleep 30; sleep 30",
})
output := new(terraform.MockUIOutput)
p := Provisioner()
doneCh := make(chan struct{})
startTime := time.Now()
go func() {
defer close(doneCh)
// The functionality of p.Apply is tested in TestResourceProvider_Apply.
// Because p.Apply is called in a goroutine, trying to t.Fatal() on its
// result would be ignored or would cause a panic if the parent goroutine
// has already completed.
_ = p.Apply(output, nil, c)
}()
mustExceed := (50 * time.Millisecond)
select {
case <-doneCh:
t.Fatalf("expected to finish sometime after %s finished in %s", mustExceed, time.Since(startTime))
case <-time.After(mustExceed):
t.Logf("correctly took longer than %s", mustExceed)
}
// Stop it
stopTime := time.Now()
p.Stop()
maxTempl := "expected to finish under %s, finished in %s"
finishWithin := (2 * time.Second)
select {
case <-doneCh:
t.Logf(maxTempl, finishWithin, time.Since(stopTime))
case <-time.After(finishWithin):
t.Fatalf(maxTempl, finishWithin, time.Since(stopTime))
}
}
func TestResourceProvider_Validate_good(t *testing.T) {
c := testConfig(t, map[string]interface{}{
"command": "echo foo",
})
warn, errs := Provisioner().Validate(c)
if len(warn) > 0 {
t.Fatalf("Warnings: %v", warn)
}
if len(errs) > 0 {
t.Fatalf("Errors: %v", errs)
}
}
func TestResourceProvider_Validate_missing(t *testing.T) {
c := testConfig(t, map[string]interface{}{})
warn, errs := Provisioner().Validate(c)
if len(warn) > 0 {
t.Fatalf("Warnings: %v", warn)
}
if len(errs) == 0 {
t.Fatalf("Should have errors")
}
}
func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig {
r, err := config.NewRawConfig(c)
if err != nil {
t.Fatalf("bad: %s", err)
}
return terraform.NewResourceConfig(r)
}
func TestResourceProvider_ApplyCustomInterpreter(t *testing.T) {
c := testConfig(t, map[string]interface{}{
"interpreter": []interface{}{"echo", "is"},
"command": "not really an interpreter",
})
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 := "is not really an interpreter"
if got != want {
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)
}
}