github.com/rsyabuta/packer@v1.1.4-0.20180119234903-5ef0c2280f0b/provisioner/shell/provisioner_test.go (about)

     1  package shell
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"regexp"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/packer/packer"
    11  )
    12  
    13  func testConfig() map[string]interface{} {
    14  	return map[string]interface{}{
    15  		"inline": []interface{}{"foo", "bar"},
    16  	}
    17  }
    18  
    19  func TestProvisioner_Impl(t *testing.T) {
    20  	var raw interface{}
    21  	raw = &Provisioner{}
    22  	if _, ok := raw.(packer.Provisioner); !ok {
    23  		t.Fatalf("must be a Provisioner")
    24  	}
    25  }
    26  
    27  func TestProvisionerPrepare_Defaults(t *testing.T) {
    28  	var p Provisioner
    29  	config := testConfig()
    30  
    31  	err := p.Prepare(config)
    32  	if err != nil {
    33  		t.Fatalf("err: %s", err)
    34  	}
    35  
    36  	if p.config.ExpectDisconnect != false {
    37  		t.Errorf("expected ExpectDisconnect to default to false")
    38  	}
    39  
    40  	if p.config.RemotePath == "" {
    41  		t.Errorf("unexpected remote path: %s", p.config.RemotePath)
    42  	}
    43  }
    44  
    45  func TestProvisionerPrepare_ExpectDisconnect(t *testing.T) {
    46  	config := testConfig()
    47  	p := new(Provisioner)
    48  	config["expect_disconnect"] = false
    49  
    50  	err := p.Prepare(config)
    51  	if err != nil {
    52  		t.Fatalf("err: %s", err)
    53  	}
    54  
    55  	if p.config.ExpectDisconnect != false {
    56  		t.Errorf("expected ExpectDisconnect to be false")
    57  	}
    58  
    59  	config["expect_disconnect"] = true
    60  	p = new(Provisioner)
    61  	err = p.Prepare(config)
    62  	if err != nil {
    63  		t.Fatalf("err: %s", err)
    64  	}
    65  
    66  	if p.config.ExpectDisconnect != true {
    67  		t.Errorf("expected ExpectDisconnect to be true")
    68  	}
    69  }
    70  
    71  func TestProvisionerPrepare_InlineShebang(t *testing.T) {
    72  	config := testConfig()
    73  
    74  	delete(config, "inline_shebang")
    75  	p := new(Provisioner)
    76  	err := p.Prepare(config)
    77  	if err != nil {
    78  		t.Fatalf("should not have error: %s", err)
    79  	}
    80  
    81  	if p.config.InlineShebang != "/bin/sh -e" {
    82  		t.Fatalf("bad value: %s", p.config.InlineShebang)
    83  	}
    84  
    85  	// Test with a good one
    86  	config["inline_shebang"] = "foo"
    87  	p = new(Provisioner)
    88  	err = p.Prepare(config)
    89  	if err != nil {
    90  		t.Fatalf("should not have error: %s", err)
    91  	}
    92  
    93  	if p.config.InlineShebang != "foo" {
    94  		t.Fatalf("bad value: %s", p.config.InlineShebang)
    95  	}
    96  }
    97  
    98  func TestProvisionerPrepare_InvalidKey(t *testing.T) {
    99  	var p Provisioner
   100  	config := testConfig()
   101  
   102  	// Add a random key
   103  	config["i_should_not_be_valid"] = true
   104  	err := p.Prepare(config)
   105  	if err == nil {
   106  		t.Fatal("should have error")
   107  	}
   108  }
   109  
   110  func TestProvisionerPrepare_Script(t *testing.T) {
   111  	config := testConfig()
   112  	delete(config, "inline")
   113  
   114  	config["script"] = "/this/should/not/exist"
   115  	p := new(Provisioner)
   116  	err := p.Prepare(config)
   117  	if err == nil {
   118  		t.Fatal("should have error")
   119  	}
   120  
   121  	// Test with a good one
   122  	tf, err := ioutil.TempFile("", "packer")
   123  	if err != nil {
   124  		t.Fatalf("error tempfile: %s", err)
   125  	}
   126  	defer os.Remove(tf.Name())
   127  
   128  	config["script"] = tf.Name()
   129  	p = new(Provisioner)
   130  	err = p.Prepare(config)
   131  	if err != nil {
   132  		t.Fatalf("should not have error: %s", err)
   133  	}
   134  }
   135  
   136  func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
   137  	var p Provisioner
   138  	config := testConfig()
   139  
   140  	delete(config, "inline")
   141  	delete(config, "script")
   142  	err := p.Prepare(config)
   143  	if err == nil {
   144  		t.Fatal("should have error")
   145  	}
   146  
   147  	// Test with both
   148  	tf, err := ioutil.TempFile("", "packer")
   149  	if err != nil {
   150  		t.Fatalf("error tempfile: %s", err)
   151  	}
   152  	defer os.Remove(tf.Name())
   153  
   154  	config["inline"] = []interface{}{"foo"}
   155  	config["script"] = tf.Name()
   156  	err = p.Prepare(config)
   157  	if err == nil {
   158  		t.Fatal("should have error")
   159  	}
   160  }
   161  
   162  func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
   163  	var p Provisioner
   164  	config := testConfig()
   165  
   166  	// Test with both
   167  	tf, err := ioutil.TempFile("", "packer")
   168  	if err != nil {
   169  		t.Fatalf("error tempfile: %s", err)
   170  	}
   171  	defer os.Remove(tf.Name())
   172  
   173  	config["inline"] = []interface{}{"foo"}
   174  	config["scripts"] = []string{tf.Name()}
   175  	err = p.Prepare(config)
   176  	if err == nil {
   177  		t.Fatal("should have error")
   178  	}
   179  }
   180  
   181  func TestProvisionerPrepare_Scripts(t *testing.T) {
   182  	config := testConfig()
   183  	delete(config, "inline")
   184  
   185  	config["scripts"] = []string{}
   186  	p := new(Provisioner)
   187  	err := p.Prepare(config)
   188  	if err == nil {
   189  		t.Fatal("should have error")
   190  	}
   191  
   192  	// Test with a good one
   193  	tf, err := ioutil.TempFile("", "packer")
   194  	if err != nil {
   195  		t.Fatalf("error tempfile: %s", err)
   196  	}
   197  	defer os.Remove(tf.Name())
   198  
   199  	config["scripts"] = []string{tf.Name()}
   200  	p = new(Provisioner)
   201  	err = p.Prepare(config)
   202  	if err != nil {
   203  		t.Fatalf("should not have error: %s", err)
   204  	}
   205  }
   206  
   207  func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
   208  	config := testConfig()
   209  
   210  	// Test with a bad case
   211  	config["environment_vars"] = []string{"badvar", "good=var"}
   212  	p := new(Provisioner)
   213  	err := p.Prepare(config)
   214  	if err == nil {
   215  		t.Fatal("should have error")
   216  	}
   217  
   218  	// Test with a trickier case
   219  	config["environment_vars"] = []string{"=bad"}
   220  	p = new(Provisioner)
   221  	err = p.Prepare(config)
   222  	if err == nil {
   223  		t.Fatal("should have error")
   224  	}
   225  
   226  	// Test with a good case
   227  	// Note: baz= is a real env variable, just empty
   228  	config["environment_vars"] = []string{"FOO=bar", "baz="}
   229  	p = new(Provisioner)
   230  	err = p.Prepare(config)
   231  	if err != nil {
   232  		t.Fatalf("should not have error: %s", err)
   233  	}
   234  
   235  	// Test when the env variable value contains an equals sign
   236  	config["environment_vars"] = []string{"good=withequals=true"}
   237  	p = new(Provisioner)
   238  	err = p.Prepare(config)
   239  	if err != nil {
   240  		t.Fatalf("should not have error: %s", err)
   241  	}
   242  
   243  	// Test when the env variable value starts with an equals sign
   244  	config["environment_vars"] = []string{"good==true"}
   245  	p = new(Provisioner)
   246  	err = p.Prepare(config)
   247  	if err != nil {
   248  		t.Fatalf("should not have error: %s", err)
   249  	}
   250  }
   251  
   252  func TestProvisioner_createFlattenedEnvVars(t *testing.T) {
   253  	var flattenedEnvVars string
   254  	config := testConfig()
   255  
   256  	userEnvVarTests := [][]string{
   257  		{},                     // No user env var
   258  		{"FOO=bar"},            // Single user env var
   259  		{"FOO=bar's"},          // User env var with single quote in value
   260  		{"FOO=bar", "BAZ=qux"}, // Multiple user env vars
   261  		{"FOO=bar=baz"},        // User env var with value containing equals
   262  		{"FOO==bar"},           // User env var with value starting with equals
   263  	}
   264  	expected := []string{
   265  		`PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   266  		`FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   267  		`FOO='bar'"'"'s' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   268  		`BAZ='qux' FOO='bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   269  		`FOO='bar=baz' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   270  		`FOO='=bar' PACKER_BUILDER_TYPE='iso' PACKER_BUILD_NAME='vmware' `,
   271  	}
   272  
   273  	p := new(Provisioner)
   274  	p.Prepare(config)
   275  
   276  	// Defaults provided by Packer
   277  	p.config.PackerBuildName = "vmware"
   278  	p.config.PackerBuilderType = "iso"
   279  
   280  	for i, expectedValue := range expected {
   281  		p.config.Vars = userEnvVarTests[i]
   282  		flattenedEnvVars = p.createFlattenedEnvVars()
   283  		if flattenedEnvVars != expectedValue {
   284  			t.Fatalf("expected flattened env vars to be: %s, got %s.", expectedValue, flattenedEnvVars)
   285  		}
   286  	}
   287  }
   288  
   289  func TestProvisioner_RemoteFolderSetSuccessfully(t *testing.T) {
   290  	config := testConfig()
   291  
   292  	expectedRemoteFolder := "/example/path"
   293  	config["remote_folder"] = expectedRemoteFolder
   294  
   295  	p := new(Provisioner)
   296  	err := p.Prepare(config)
   297  	if err != nil {
   298  		t.Fatalf("should not have error: %s", err)
   299  	}
   300  
   301  	if !strings.Contains(p.config.RemotePath, expectedRemoteFolder) {
   302  		t.Fatalf("remote path does not contain remote_folder")
   303  	}
   304  }
   305  
   306  func TestProvisioner_RemoteFolderDefaultsToTmp(t *testing.T) {
   307  	config := testConfig()
   308  
   309  	p := new(Provisioner)
   310  	err := p.Prepare(config)
   311  	if err != nil {
   312  		t.Fatalf("should not have error: %s", err)
   313  	}
   314  
   315  	if p.config.RemoteFolder != "/tmp" {
   316  		t.Fatalf("remote_folder did not default to /tmp")
   317  	}
   318  
   319  	if !strings.Contains(p.config.RemotePath, "/tmp") {
   320  		t.Fatalf("remote path does not contain remote_folder")
   321  	}
   322  }
   323  
   324  func TestProvisioner_RemoteFileSetSuccessfully(t *testing.T) {
   325  	config := testConfig()
   326  
   327  	expectedRemoteFile := "example.sh"
   328  	config["remote_file"] = expectedRemoteFile
   329  
   330  	p := new(Provisioner)
   331  	err := p.Prepare(config)
   332  	if err != nil {
   333  		t.Fatalf("should not have error: %s", err)
   334  	}
   335  
   336  	if !strings.Contains(p.config.RemotePath, expectedRemoteFile) {
   337  		t.Fatalf("remote path does not contain remote_file")
   338  	}
   339  }
   340  
   341  func TestProvisioner_RemoteFileDefaultsToScriptnnnn(t *testing.T) {
   342  	config := testConfig()
   343  
   344  	p := new(Provisioner)
   345  	err := p.Prepare(config)
   346  	if err != nil {
   347  		t.Fatalf("should not have error: %s", err)
   348  	}
   349  
   350  	remoteFileRegex := regexp.MustCompile("script_[0-9]{4}.sh")
   351  
   352  	if !remoteFileRegex.MatchString(p.config.RemoteFile) {
   353  		t.Fatalf("remote_file did not default to script_nnnn.sh")
   354  	}
   355  
   356  	if !remoteFileRegex.MatchString(p.config.RemotePath) {
   357  		t.Fatalf("remote_path did not match script_nnnn.sh")
   358  	}
   359  }
   360  
   361  func TestProvisioner_RemotePathSetViaRemotePathAndRemoteFile(t *testing.T) {
   362  	config := testConfig()
   363  
   364  	expectedRemoteFile := "example.sh"
   365  	expectedRemoteFolder := "/example/path"
   366  	config["remote_file"] = expectedRemoteFile
   367  	config["remote_folder"] = expectedRemoteFolder
   368  
   369  	p := new(Provisioner)
   370  	err := p.Prepare(config)
   371  	if err != nil {
   372  		t.Fatalf("should not have error: %s", err)
   373  	}
   374  
   375  	if p.config.RemotePath != expectedRemoteFolder+"/"+expectedRemoteFile {
   376  		t.Fatalf("remote path does not contain remote_file")
   377  	}
   378  }
   379  
   380  func TestProvisioner_RemotePathOverridesRemotePathAndRemoteFile(t *testing.T) {
   381  	config := testConfig()
   382  
   383  	expectedRemoteFile := "example.sh"
   384  	expectedRemoteFolder := "/example/path"
   385  	expectedRemotePath := "/example/remote/path/script.sh"
   386  	config["remote_file"] = expectedRemoteFile
   387  	config["remote_folder"] = expectedRemoteFolder
   388  	config["remote_path"] = expectedRemotePath
   389  
   390  	p := new(Provisioner)
   391  	err := p.Prepare(config)
   392  	if err != nil {
   393  		t.Fatalf("should not have error: %s", err)
   394  	}
   395  
   396  	if p.config.RemotePath != expectedRemotePath {
   397  		t.Fatalf("remote path does not contain remote_path")
   398  	}
   399  }
   400  
   401  func TestProvisionerRemotePathDefaultsSuccessfully(t *testing.T) {
   402  	config := testConfig()
   403  
   404  	p := new(Provisioner)
   405  	err := p.Prepare(config)
   406  	if err != nil {
   407  		t.Fatalf("should not have error: %s", err)
   408  	}
   409  
   410  	remotePathRegex := regexp.MustCompile("/tmp/script_[0-9]{4}.sh")
   411  
   412  	if !remotePathRegex.MatchString(p.config.RemotePath) {
   413  		t.Fatalf("remote path does not match the expected default regex")
   414  	}
   415  }