github.com/dacamp/packer@v0.10.2/provisioner/windows-shell/provisioner_test.go (about)

     1  package shell
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"github.com/mitchellh/packer/packer"
     8  	"io/ioutil"
     9  	"log"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  )
    15  
    16  func testConfig() map[string]interface{} {
    17  	return map[string]interface{}{
    18  		"inline": []interface{}{"foo", "bar"},
    19  	}
    20  }
    21  
    22  func TestProvisionerPrepare_extractScript(t *testing.T) {
    23  	config := testConfig()
    24  	p := new(Provisioner)
    25  	_ = p.Prepare(config)
    26  	file, err := extractScript(p)
    27  	if err != nil {
    28  		t.Fatalf("Should not be error: %s", err)
    29  	}
    30  	log.Printf("File: %s", file)
    31  	if strings.Index(file, os.TempDir()) != 0 {
    32  		t.Fatalf("Temp file should reside in %s. File location: %s", os.TempDir(), file)
    33  	}
    34  
    35  	// File contents should contain 2 lines concatenated by newlines: foo\nbar
    36  	readFile, err := ioutil.ReadFile(file)
    37  	expectedContents := "foo\nbar\n"
    38  	s := string(readFile[:])
    39  	if s != expectedContents {
    40  		t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", expectedContents, s)
    41  	}
    42  }
    43  
    44  func TestProvisioner_Impl(t *testing.T) {
    45  	var raw interface{}
    46  	raw = &Provisioner{}
    47  	if _, ok := raw.(packer.Provisioner); !ok {
    48  		t.Fatalf("must be a Provisioner")
    49  	}
    50  }
    51  
    52  func TestProvisionerPrepare_Defaults(t *testing.T) {
    53  	var p Provisioner
    54  	config := testConfig()
    55  
    56  	err := p.Prepare(config)
    57  	if err != nil {
    58  		t.Fatalf("err: %s", err)
    59  	}
    60  
    61  	if p.config.RemotePath != DefaultRemotePath {
    62  		t.Errorf("unexpected remote path: %s", p.config.RemotePath)
    63  	}
    64  
    65  	if p.config.ExecuteCommand != "{{.Vars}}\"{{.Path}}\"" {
    66  		t.Fatalf("Default command should be powershell {{.Vars}}\"{{.Path}}\", but got %s", p.config.ExecuteCommand)
    67  	}
    68  }
    69  
    70  func TestProvisionerPrepare_Config(t *testing.T) {
    71  
    72  }
    73  
    74  func TestProvisionerPrepare_InvalidKey(t *testing.T) {
    75  	var p Provisioner
    76  	config := testConfig()
    77  
    78  	// Add a random key
    79  	config["i_should_not_be_valid"] = true
    80  	err := p.Prepare(config)
    81  	if err == nil {
    82  		t.Fatal("should have error")
    83  	}
    84  }
    85  
    86  func TestProvisionerPrepare_Script(t *testing.T) {
    87  	config := testConfig()
    88  	delete(config, "inline")
    89  
    90  	config["script"] = "/this/should/not/exist"
    91  	p := new(Provisioner)
    92  	err := p.Prepare(config)
    93  	if err == nil {
    94  		t.Fatal("should have error")
    95  	}
    96  
    97  	// Test with a good one
    98  	tf, err := ioutil.TempFile("", "packer")
    99  	if err != nil {
   100  		t.Fatalf("error tempfile: %s", err)
   101  	}
   102  	defer os.Remove(tf.Name())
   103  
   104  	config["script"] = tf.Name()
   105  	p = new(Provisioner)
   106  	err = p.Prepare(config)
   107  	if err != nil {
   108  		t.Fatalf("should not have error: %s", err)
   109  	}
   110  }
   111  
   112  func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
   113  	var p Provisioner
   114  	config := testConfig()
   115  
   116  	delete(config, "inline")
   117  	delete(config, "script")
   118  	err := p.Prepare(config)
   119  	if err == nil {
   120  		t.Fatal("should have error")
   121  	}
   122  
   123  	// Test with both
   124  	tf, err := ioutil.TempFile("", "packer")
   125  	if err != nil {
   126  		t.Fatalf("error tempfile: %s", err)
   127  	}
   128  	defer os.Remove(tf.Name())
   129  
   130  	config["inline"] = []interface{}{"foo"}
   131  	config["script"] = tf.Name()
   132  	err = p.Prepare(config)
   133  	if err == nil {
   134  		t.Fatal("should have error")
   135  	}
   136  }
   137  
   138  func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
   139  	var p Provisioner
   140  	config := testConfig()
   141  
   142  	// Test with both
   143  	tf, err := ioutil.TempFile("", "packer")
   144  	if err != nil {
   145  		t.Fatalf("error tempfile: %s", err)
   146  	}
   147  	defer os.Remove(tf.Name())
   148  
   149  	config["inline"] = []interface{}{"foo"}
   150  	config["scripts"] = []string{tf.Name()}
   151  	err = p.Prepare(config)
   152  	if err == nil {
   153  		t.Fatal("should have error")
   154  	}
   155  }
   156  
   157  func TestProvisionerPrepare_Scripts(t *testing.T) {
   158  	config := testConfig()
   159  	delete(config, "inline")
   160  
   161  	config["scripts"] = []string{}
   162  	p := new(Provisioner)
   163  	err := p.Prepare(config)
   164  	if err == nil {
   165  		t.Fatal("should have error")
   166  	}
   167  
   168  	// Test with a good one
   169  	tf, err := ioutil.TempFile("", "packer")
   170  	if err != nil {
   171  		t.Fatalf("error tempfile: %s", err)
   172  	}
   173  	defer os.Remove(tf.Name())
   174  
   175  	config["scripts"] = []string{tf.Name()}
   176  	p = new(Provisioner)
   177  	err = p.Prepare(config)
   178  	if err != nil {
   179  		t.Fatalf("should not have error: %s", err)
   180  	}
   181  }
   182  
   183  func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
   184  	config := testConfig()
   185  
   186  	// Test with a bad case
   187  	config["environment_vars"] = []string{"badvar", "good=var"}
   188  	p := new(Provisioner)
   189  	err := p.Prepare(config)
   190  	if err == nil {
   191  		t.Fatal("should have error")
   192  	}
   193  
   194  	// Test with a trickier case
   195  	config["environment_vars"] = []string{"=bad"}
   196  	p = new(Provisioner)
   197  	err = p.Prepare(config)
   198  	if err == nil {
   199  		t.Fatal("should have error")
   200  	}
   201  
   202  	// Test with a good case
   203  	// Note: baz= is a real env variable, just empty
   204  	config["environment_vars"] = []string{"FOO=bar", "baz="}
   205  	p = new(Provisioner)
   206  	err = p.Prepare(config)
   207  	if err != nil {
   208  		t.Fatalf("should not have error: %s", err)
   209  	}
   210  }
   211  
   212  func TestProvisionerQuote_EnvironmentVars(t *testing.T) {
   213  	config := testConfig()
   214  
   215  	config["environment_vars"] = []string{"keyone=valueone", "keytwo=value\ntwo", "keythree='valuethree'", "keyfour='value\nfour'"}
   216  	p := new(Provisioner)
   217  	p.Prepare(config)
   218  
   219  	expectedValue := "keyone=valueone"
   220  	if p.config.Vars[0] != expectedValue {
   221  		t.Fatalf("%s should be equal to %s", p.config.Vars[0], expectedValue)
   222  	}
   223  
   224  	expectedValue = "keytwo=value\ntwo"
   225  	if p.config.Vars[1] != expectedValue {
   226  		t.Fatalf("%s should be equal to %s", p.config.Vars[1], expectedValue)
   227  	}
   228  
   229  	expectedValue = "keythree='valuethree'"
   230  	if p.config.Vars[2] != expectedValue {
   231  		t.Fatalf("%s should be equal to %s", p.config.Vars[2], expectedValue)
   232  	}
   233  
   234  	expectedValue = "keyfour='value\nfour'"
   235  	if p.config.Vars[3] != expectedValue {
   236  		t.Fatalf("%s should be equal to %s", p.config.Vars[3], expectedValue)
   237  	}
   238  }
   239  
   240  func testUi() *packer.BasicUi {
   241  	return &packer.BasicUi{
   242  		Reader:      new(bytes.Buffer),
   243  		Writer:      new(bytes.Buffer),
   244  		ErrorWriter: new(bytes.Buffer),
   245  	}
   246  }
   247  
   248  func testObjects() (packer.Ui, packer.Communicator) {
   249  	ui := testUi()
   250  	return ui, new(packer.MockCommunicator)
   251  }
   252  
   253  func TestProvisionerProvision_Inline(t *testing.T) {
   254  	config := testConfig()
   255  	delete(config, "inline")
   256  
   257  	// Defaults provided by Packer
   258  	config["remote_path"] = "c:/Windows/Temp/inlineScript.bat"
   259  	config["inline"] = []string{"whoami"}
   260  	ui := testUi()
   261  	p := new(Provisioner)
   262  
   263  	// Defaults provided by Packer
   264  	p.config.PackerBuildName = "vmware"
   265  	p.config.PackerBuilderType = "iso"
   266  	comm := new(packer.MockCommunicator)
   267  	p.Prepare(config)
   268  	err := p.Provision(ui, comm)
   269  	if err != nil {
   270  		t.Fatal("should not have error")
   271  	}
   272  
   273  	expectedCommand := `set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && "c:/Windows/Temp/inlineScript.bat"`
   274  
   275  	// Should run the command without alteration
   276  	if comm.StartCmd.Command != expectedCommand {
   277  		t.Fatalf("Expect command to be: %s, got %s", expectedCommand, comm.StartCmd.Command)
   278  	}
   279  
   280  	envVars := make([]string, 2)
   281  	envVars[0] = "FOO=BAR"
   282  	envVars[1] = "BAR=BAZ"
   283  	config["environment_vars"] = envVars
   284  	config["remote_path"] = "c:/Windows/Temp/inlineScript.bat"
   285  
   286  	p.Prepare(config)
   287  	err = p.Provision(ui, comm)
   288  	if err != nil {
   289  		t.Fatal("should not have error")
   290  	}
   291  
   292  	expectedCommand = `set "BAR=BAZ" && set "FOO=BAR" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && "c:/Windows/Temp/inlineScript.bat"`
   293  
   294  	// Should run the command without alteration
   295  	if comm.StartCmd.Command != expectedCommand {
   296  		t.Fatalf("Expect command to be: %s, got: %s", expectedCommand, comm.StartCmd.Command)
   297  	}
   298  }
   299  
   300  func TestProvisionerProvision_Scripts(t *testing.T) {
   301  	tempFile, _ := ioutil.TempFile("", "packer")
   302  	defer os.Remove(tempFile.Name())
   303  	config := testConfig()
   304  	delete(config, "inline")
   305  	config["scripts"] = []string{tempFile.Name()}
   306  	config["packer_build_name"] = "foobuild"
   307  	config["packer_builder_type"] = "footype"
   308  	ui := testUi()
   309  
   310  	p := new(Provisioner)
   311  	comm := new(packer.MockCommunicator)
   312  	p.Prepare(config)
   313  	err := p.Provision(ui, comm)
   314  	if err != nil {
   315  		t.Fatal("should not have error")
   316  	}
   317  
   318  	//powershell -Command "$env:PACKER_BUILDER_TYPE=''"; powershell -Command "$env:PACKER_BUILD_NAME='foobuild'";  powershell -Command c:/Windows/Temp/script.ps1
   319  	expectedCommand := `set "PACKER_BUILDER_TYPE=footype" && set "PACKER_BUILD_NAME=foobuild" && "c:/Windows/Temp/script.bat"`
   320  
   321  	// Should run the command without alteration
   322  	if comm.StartCmd.Command != expectedCommand {
   323  		t.Fatalf("Expect command to be %s NOT %s", expectedCommand, comm.StartCmd.Command)
   324  	}
   325  }
   326  
   327  func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
   328  	tempFile, _ := ioutil.TempFile("", "packer")
   329  	config := testConfig()
   330  	ui := testUi()
   331  	defer os.Remove(tempFile.Name())
   332  	delete(config, "inline")
   333  
   334  	config["scripts"] = []string{tempFile.Name()}
   335  	config["packer_build_name"] = "foobuild"
   336  	config["packer_builder_type"] = "footype"
   337  
   338  	// Env vars - currently should not effect them
   339  	envVars := make([]string, 2)
   340  	envVars[0] = "FOO=BAR"
   341  	envVars[1] = "BAR=BAZ"
   342  	config["environment_vars"] = envVars
   343  
   344  	p := new(Provisioner)
   345  	comm := new(packer.MockCommunicator)
   346  	p.Prepare(config)
   347  	err := p.Provision(ui, comm)
   348  	if err != nil {
   349  		t.Fatal("should not have error")
   350  	}
   351  
   352  	expectedCommand := `set "BAR=BAZ" && set "FOO=BAR" && set "PACKER_BUILDER_TYPE=footype" && set "PACKER_BUILD_NAME=foobuild" && "c:/Windows/Temp/script.bat"`
   353  
   354  	// Should run the command without alteration
   355  	if comm.StartCmd.Command != expectedCommand {
   356  		t.Fatalf("Expect command to be %s NOT %s", expectedCommand, comm.StartCmd.Command)
   357  	}
   358  }
   359  
   360  func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
   361  	config := testConfig()
   362  
   363  	p := new(Provisioner)
   364  	err := p.Prepare(config)
   365  	if err != nil {
   366  		t.Fatalf("should not have error preparing config: %s", err)
   367  	}
   368  
   369  	// Defaults provided by Packer
   370  	p.config.PackerBuildName = "vmware"
   371  	p.config.PackerBuilderType = "iso"
   372  
   373  	// no user env var
   374  	flattenedEnvVars, err := p.createFlattenedEnvVars()
   375  	if err != nil {
   376  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   377  	}
   378  	expectedEnvVars := `set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `
   379  	if flattenedEnvVars != expectedEnvVars {
   380  		t.Fatalf("expected flattened env vars to be: %s, got: %s", expectedEnvVars, flattenedEnvVars)
   381  	}
   382  
   383  	// single user env var
   384  	p.config.Vars = []string{"FOO=bar"}
   385  
   386  	flattenedEnvVars, err = p.createFlattenedEnvVars()
   387  	if err != nil {
   388  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   389  	}
   390  	expectedEnvVars = `set "FOO=bar" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `
   391  	if flattenedEnvVars != expectedEnvVars {
   392  		t.Fatalf("expected flattened env vars to be: %s, got: %s", expectedEnvVars, flattenedEnvVars)
   393  	}
   394  
   395  	// multiple user env vars
   396  	p.config.Vars = []string{"FOO=bar", "BAZ=qux"}
   397  
   398  	flattenedEnvVars, err = p.createFlattenedEnvVars()
   399  	if err != nil {
   400  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   401  	}
   402  	expectedEnvVars = `set "BAZ=qux" && set "FOO=bar" && set "PACKER_BUILDER_TYPE=iso" && set "PACKER_BUILD_NAME=vmware" && `
   403  	if flattenedEnvVars != expectedEnvVars {
   404  		t.Fatalf("expected flattened env vars to be: %s, got: %s", expectedEnvVars, flattenedEnvVars)
   405  	}
   406  }
   407  
   408  func TestRetryable(t *testing.T) {
   409  	config := testConfig()
   410  
   411  	count := 0
   412  	retryMe := func() error {
   413  		log.Printf("RetryMe, attempt number %d", count)
   414  		if count == 2 {
   415  			return nil
   416  		}
   417  		count++
   418  		return errors.New(fmt.Sprintf("Still waiting %d more times...", 2-count))
   419  	}
   420  	retryableSleep = 50 * time.Millisecond
   421  	p := new(Provisioner)
   422  	p.config.StartRetryTimeout = 155 * time.Millisecond
   423  	err := p.Prepare(config)
   424  	err = p.retryable(retryMe)
   425  	if err != nil {
   426  		t.Fatalf("should not have error retrying funuction")
   427  	}
   428  
   429  	count = 0
   430  	p.config.StartRetryTimeout = 10 * time.Millisecond
   431  	err = p.Prepare(config)
   432  	err = p.retryable(retryMe)
   433  	if err == nil {
   434  		t.Fatalf("should have error retrying funuction")
   435  	}
   436  }
   437  
   438  func TestCancel(t *testing.T) {
   439  	// Don't actually call Cancel() as it performs an os.Exit(0)
   440  	// which kills the 'go test' tool
   441  }