github.com/rvichery/terraform@v0.11.10/builtin/provisioners/remote-exec/resource_provisioner_test.go (about)

     1  package remoteexec
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"io"
     7  	"testing"
     8  	"time"
     9  
    10  	"strings"
    11  
    12  	"github.com/hashicorp/terraform/communicator"
    13  	"github.com/hashicorp/terraform/communicator/remote"
    14  	"github.com/hashicorp/terraform/config"
    15  	"github.com/hashicorp/terraform/helper/schema"
    16  	"github.com/hashicorp/terraform/terraform"
    17  )
    18  
    19  func TestResourceProvisioner_impl(t *testing.T) {
    20  	var _ terraform.ResourceProvisioner = Provisioner()
    21  }
    22  
    23  func TestProvisioner(t *testing.T) {
    24  	if err := Provisioner().(*schema.Provisioner).InternalValidate(); err != nil {
    25  		t.Fatalf("err: %s", err)
    26  	}
    27  }
    28  
    29  func TestResourceProvider_Validate_good(t *testing.T) {
    30  	c := testConfig(t, map[string]interface{}{
    31  		"inline": "echo foo",
    32  	})
    33  
    34  	warn, errs := Provisioner().Validate(c)
    35  	if len(warn) > 0 {
    36  		t.Fatalf("Warnings: %v", warn)
    37  	}
    38  	if len(errs) > 0 {
    39  		t.Fatalf("Errors: %v", errs)
    40  	}
    41  }
    42  
    43  func TestResourceProvider_Validate_bad(t *testing.T) {
    44  	c := testConfig(t, map[string]interface{}{
    45  		"invalid": "nope",
    46  	})
    47  
    48  	warn, errs := Provisioner().Validate(c)
    49  	if len(warn) > 0 {
    50  		t.Fatalf("Warnings: %v", warn)
    51  	}
    52  	if len(errs) == 0 {
    53  		t.Fatalf("Should have errors")
    54  	}
    55  }
    56  
    57  var expectedScriptOut = `cd /tmp
    58  wget http://foobar
    59  exit 0
    60  `
    61  
    62  func TestResourceProvider_generateScript(t *testing.T) {
    63  	conf := map[string]interface{}{
    64  		"inline": []interface{}{
    65  			"cd /tmp",
    66  			"wget http://foobar",
    67  			"exit 0",
    68  		},
    69  	}
    70  
    71  	out, err := generateScripts(
    72  		schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf),
    73  	)
    74  	if err != nil {
    75  		t.Fatalf("err: %v", err)
    76  	}
    77  
    78  	if len(out) != 1 {
    79  		t.Fatal("expected 1 out")
    80  	}
    81  
    82  	if out[0] != expectedScriptOut {
    83  		t.Fatalf("bad: %v", out)
    84  	}
    85  }
    86  
    87  func TestResourceProvider_generateScriptEmptyInline(t *testing.T) {
    88  	p := Provisioner().(*schema.Provisioner)
    89  	conf := map[string]interface{}{
    90  		"inline": []interface{}{""},
    91  	}
    92  
    93  	_, err := generateScripts(schema.TestResourceDataRaw(
    94  		t, p.Schema, conf))
    95  	if err == nil {
    96  		t.Fatal("expected error, got none")
    97  	}
    98  
    99  	if !strings.Contains(err.Error(), "Error parsing") {
   100  		t.Fatalf("expected parsing error, got: %s", err)
   101  	}
   102  }
   103  
   104  func TestResourceProvider_CollectScripts_inline(t *testing.T) {
   105  	conf := map[string]interface{}{
   106  		"inline": []interface{}{
   107  			"cd /tmp",
   108  			"wget http://foobar",
   109  			"exit 0",
   110  		},
   111  	}
   112  
   113  	scripts, err := collectScripts(
   114  		schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf),
   115  	)
   116  	if err != nil {
   117  		t.Fatalf("err: %v", err)
   118  	}
   119  
   120  	if len(scripts) != 1 {
   121  		t.Fatalf("bad: %v", scripts)
   122  	}
   123  
   124  	var out bytes.Buffer
   125  	_, err = io.Copy(&out, scripts[0])
   126  	if err != nil {
   127  		t.Fatalf("err: %v", err)
   128  	}
   129  
   130  	if out.String() != expectedScriptOut {
   131  		t.Fatalf("bad: %v", out.String())
   132  	}
   133  }
   134  
   135  func TestResourceProvider_CollectScripts_script(t *testing.T) {
   136  	conf := map[string]interface{}{
   137  		"script": "test-fixtures/script1.sh",
   138  	}
   139  
   140  	scripts, err := collectScripts(
   141  		schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf),
   142  	)
   143  	if err != nil {
   144  		t.Fatalf("err: %v", err)
   145  	}
   146  
   147  	if len(scripts) != 1 {
   148  		t.Fatalf("bad: %v", scripts)
   149  	}
   150  
   151  	var out bytes.Buffer
   152  	_, err = io.Copy(&out, scripts[0])
   153  	if err != nil {
   154  		t.Fatalf("err: %v", err)
   155  	}
   156  
   157  	if out.String() != expectedScriptOut {
   158  		t.Fatalf("bad: %v", out.String())
   159  	}
   160  }
   161  
   162  func TestResourceProvider_CollectScripts_scripts(t *testing.T) {
   163  	conf := map[string]interface{}{
   164  		"scripts": []interface{}{
   165  			"test-fixtures/script1.sh",
   166  			"test-fixtures/script1.sh",
   167  			"test-fixtures/script1.sh",
   168  		},
   169  	}
   170  
   171  	scripts, err := collectScripts(
   172  		schema.TestResourceDataRaw(t, Provisioner().(*schema.Provisioner).Schema, conf),
   173  	)
   174  	if err != nil {
   175  		t.Fatalf("err: %v", err)
   176  	}
   177  
   178  	if len(scripts) != 3 {
   179  		t.Fatalf("bad: %v", scripts)
   180  	}
   181  
   182  	for idx := range scripts {
   183  		var out bytes.Buffer
   184  		_, err = io.Copy(&out, scripts[idx])
   185  		if err != nil {
   186  			t.Fatalf("err: %v", err)
   187  		}
   188  
   189  		if out.String() != expectedScriptOut {
   190  			t.Fatalf("bad: %v", out.String())
   191  		}
   192  	}
   193  }
   194  
   195  func TestResourceProvider_CollectScripts_scriptsEmpty(t *testing.T) {
   196  	p := Provisioner().(*schema.Provisioner)
   197  	conf := map[string]interface{}{
   198  		"scripts": []interface{}{""},
   199  	}
   200  
   201  	_, err := collectScripts(schema.TestResourceDataRaw(
   202  		t, p.Schema, conf))
   203  
   204  	if err == nil {
   205  		t.Fatal("expected error")
   206  	}
   207  
   208  	if !strings.Contains(err.Error(), "Error parsing") {
   209  		t.Fatalf("Expected parsing error, got: %s", err)
   210  	}
   211  }
   212  
   213  func TestProvisionerTimeout(t *testing.T) {
   214  	o := new(terraform.MockUIOutput)
   215  	c := new(communicator.MockCommunicator)
   216  
   217  	disconnected := make(chan struct{})
   218  	c.DisconnectFunc = func() error {
   219  		close(disconnected)
   220  		return nil
   221  	}
   222  
   223  	completed := make(chan struct{})
   224  	c.CommandFunc = func(cmd *remote.Cmd) error {
   225  		defer close(completed)
   226  		cmd.Init()
   227  		time.Sleep(2 * time.Second)
   228  		cmd.SetExitStatus(0, nil)
   229  		return nil
   230  	}
   231  	c.ConnTimeout = time.Second
   232  	c.UploadScripts = map[string]string{"hello": "echo hello"}
   233  	c.RemoteScriptPath = "hello"
   234  
   235  	p := Provisioner().(*schema.Provisioner)
   236  	conf := map[string]interface{}{
   237  		"inline": []interface{}{"echo hello"},
   238  	}
   239  
   240  	scripts, err := collectScripts(schema.TestResourceDataRaw(
   241  		t, p.Schema, conf))
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	ctx := context.Background()
   247  
   248  	done := make(chan struct{})
   249  
   250  	go func() {
   251  		defer close(done)
   252  		if err := runScripts(ctx, o, c, scripts); err != nil {
   253  			t.Fatal(err)
   254  		}
   255  	}()
   256  
   257  	select {
   258  	case <-disconnected:
   259  		t.Fatal("communicator disconnected before command completed")
   260  	case <-completed:
   261  	}
   262  
   263  	<-done
   264  }
   265  
   266  func testConfig(t *testing.T, c map[string]interface{}) *terraform.ResourceConfig {
   267  	r, err := config.NewRawConfig(c)
   268  	if err != nil {
   269  		t.Fatalf("bad: %s", err)
   270  	}
   271  
   272  	return terraform.NewResourceConfig(r)
   273  }