github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/provisioner/powershell/provisioner_test.go (about)

     1  package powershell
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io/ioutil"
     8  	//"log"
     9  	"os"
    10  	"regexp"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/mitchellh/packer/packer"
    16  )
    17  
    18  func testConfig() map[string]interface{} {
    19  	return map[string]interface{}{
    20  		"inline": []interface{}{"foo", "bar"},
    21  	}
    22  }
    23  
    24  func init() {
    25  	//log.SetOutput(ioutil.Discard)
    26  }
    27  
    28  func TestProvisionerPrepare_extractScript(t *testing.T) {
    29  	config := testConfig()
    30  	p := new(Provisioner)
    31  	_ = p.Prepare(config)
    32  	file, err := extractScript(p)
    33  	if err != nil {
    34  		t.Fatalf("Should not be error: %s", err)
    35  	}
    36  	t.Logf("File: %s", file)
    37  	if strings.Index(file, os.TempDir()) != 0 {
    38  		t.Fatalf("Temp file should reside in %s. File location: %s", os.TempDir(), file)
    39  	}
    40  
    41  	// File contents should contain 2 lines concatenated by newlines: foo\nbar
    42  	readFile, err := ioutil.ReadFile(file)
    43  	expectedContents := "foo\nbar\n"
    44  	s := string(readFile[:])
    45  	if s != expectedContents {
    46  		t.Fatalf("Expected generated inlineScript to equal '%s', got '%s'", expectedContents, s)
    47  	}
    48  }
    49  
    50  func TestProvisioner_Impl(t *testing.T) {
    51  	var raw interface{}
    52  	raw = &Provisioner{}
    53  	if _, ok := raw.(packer.Provisioner); !ok {
    54  		t.Fatalf("must be a Provisioner")
    55  	}
    56  }
    57  
    58  func TestProvisionerPrepare_Defaults(t *testing.T) {
    59  	var p Provisioner
    60  	config := testConfig()
    61  
    62  	err := p.Prepare(config)
    63  	if err != nil {
    64  		t.Fatalf("err: %s", err)
    65  	}
    66  
    67  	if p.config.RemotePath != DefaultRemotePath {
    68  		t.Errorf("unexpected remote path: %s", p.config.RemotePath)
    69  	}
    70  
    71  	if p.config.ElevatedUser != "" {
    72  		t.Error("expected elevated_user to be empty")
    73  	}
    74  	if p.config.ElevatedPassword != "" {
    75  		t.Error("expected elevated_password to be empty")
    76  	}
    77  
    78  	if p.config.ExecuteCommand != `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode` {
    79  		t.Fatalf(`Default command should be "if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode", but got %s`, p.config.ExecuteCommand)
    80  	}
    81  
    82  	if p.config.ElevatedExecuteCommand != `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode` {
    83  		t.Fatalf(`Default command should be "if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};{{.Vars}}&'{{.Path}}';exit $LastExitCode", but got %s`, p.config.ElevatedExecuteCommand)
    84  	}
    85  
    86  	if p.config.ValidExitCodes == nil {
    87  		t.Fatalf("ValidExitCodes should not be nil")
    88  	}
    89  	if p.config.ValidExitCodes != nil {
    90  		expCodes := []int{0}
    91  		for i, v := range p.config.ValidExitCodes {
    92  			if v != expCodes[i] {
    93  				t.Fatalf("Expected ValidExitCodes don't match actual")
    94  			}
    95  		}
    96  	}
    97  
    98  	if p.config.ElevatedEnvVarFormat != `$env:%s="%s"; ` {
    99  		t.Fatalf(`Default command should be powershell '$env:%%s="%%s"; ', but got %s`, p.config.ElevatedEnvVarFormat)
   100  	}
   101  }
   102  
   103  func TestProvisionerPrepare_Config(t *testing.T) {
   104  	config := testConfig()
   105  	config["elevated_user"] = "{{user `user`}}"
   106  	config["elevated_password"] = "{{user `password`}}"
   107  	config[packer.UserVariablesConfigKey] = map[string]string{
   108  		"user":     "myusername",
   109  		"password": "mypassword",
   110  	}
   111  
   112  	var p Provisioner
   113  	err := p.Prepare(config)
   114  	if err != nil {
   115  		t.Fatalf("err: %s", err)
   116  	}
   117  
   118  	if p.config.ElevatedUser != "myusername" {
   119  		t.Fatalf("Expected 'myusername' for key `elevated_user`: %s", p.config.ElevatedUser)
   120  	}
   121  	if p.config.ElevatedPassword != "mypassword" {
   122  		t.Fatalf("Expected 'mypassword' for key `elevated_password`: %s", p.config.ElevatedPassword)
   123  	}
   124  
   125  }
   126  
   127  func TestProvisionerPrepare_InvalidKey(t *testing.T) {
   128  	var p Provisioner
   129  	config := testConfig()
   130  
   131  	// Add a random key
   132  	config["i_should_not_be_valid"] = true
   133  	err := p.Prepare(config)
   134  	if err == nil {
   135  		t.Fatal("should have error")
   136  	}
   137  }
   138  
   139  func TestProvisionerPrepare_Elevated(t *testing.T) {
   140  	var p Provisioner
   141  	config := testConfig()
   142  
   143  	// Add a random key
   144  	config["elevated_user"] = "vagrant"
   145  	err := p.Prepare(config)
   146  
   147  	if err == nil {
   148  		t.Fatal("should have error (only provided elevated_user)")
   149  	}
   150  
   151  	config["elevated_password"] = "vagrant"
   152  	err = p.Prepare(config)
   153  
   154  	if err != nil {
   155  		t.Fatal("should not have error")
   156  	}
   157  }
   158  
   159  func TestProvisionerPrepare_Script(t *testing.T) {
   160  	config := testConfig()
   161  	delete(config, "inline")
   162  
   163  	config["script"] = "/this/should/not/exist"
   164  	p := new(Provisioner)
   165  	err := p.Prepare(config)
   166  	if err == nil {
   167  		t.Fatal("should have error")
   168  	}
   169  
   170  	// Test with a good one
   171  	tf, err := ioutil.TempFile("", "packer")
   172  	if err != nil {
   173  		t.Fatalf("error tempfile: %s", err)
   174  	}
   175  	defer os.Remove(tf.Name())
   176  
   177  	config["script"] = tf.Name()
   178  	p = new(Provisioner)
   179  	err = p.Prepare(config)
   180  	if err != nil {
   181  		t.Fatalf("should not have error: %s", err)
   182  	}
   183  }
   184  
   185  func TestProvisionerPrepare_ScriptAndInline(t *testing.T) {
   186  	var p Provisioner
   187  	config := testConfig()
   188  
   189  	delete(config, "inline")
   190  	delete(config, "script")
   191  	err := p.Prepare(config)
   192  	if err == nil {
   193  		t.Fatal("should have error")
   194  	}
   195  
   196  	// Test with both
   197  	tf, err := ioutil.TempFile("", "packer")
   198  	if err != nil {
   199  		t.Fatalf("error tempfile: %s", err)
   200  	}
   201  	defer os.Remove(tf.Name())
   202  
   203  	config["inline"] = []interface{}{"foo"}
   204  	config["script"] = tf.Name()
   205  	err = p.Prepare(config)
   206  	if err == nil {
   207  		t.Fatal("should have error")
   208  	}
   209  }
   210  
   211  func TestProvisionerPrepare_ScriptAndScripts(t *testing.T) {
   212  	var p Provisioner
   213  	config := testConfig()
   214  
   215  	// Test with both
   216  	tf, err := ioutil.TempFile("", "packer")
   217  	if err != nil {
   218  		t.Fatalf("error tempfile: %s", err)
   219  	}
   220  	defer os.Remove(tf.Name())
   221  
   222  	config["inline"] = []interface{}{"foo"}
   223  	config["scripts"] = []string{tf.Name()}
   224  	err = p.Prepare(config)
   225  	if err == nil {
   226  		t.Fatal("should have error")
   227  	}
   228  }
   229  
   230  func TestProvisionerPrepare_Scripts(t *testing.T) {
   231  	config := testConfig()
   232  	delete(config, "inline")
   233  
   234  	config["scripts"] = []string{}
   235  	p := new(Provisioner)
   236  	err := p.Prepare(config)
   237  	if err == nil {
   238  		t.Fatal("should have error")
   239  	}
   240  
   241  	// Test with a good one
   242  	tf, err := ioutil.TempFile("", "packer")
   243  	if err != nil {
   244  		t.Fatalf("error tempfile: %s", err)
   245  	}
   246  	defer os.Remove(tf.Name())
   247  
   248  	config["scripts"] = []string{tf.Name()}
   249  	p = new(Provisioner)
   250  	err = p.Prepare(config)
   251  	if err != nil {
   252  		t.Fatalf("should not have error: %s", err)
   253  	}
   254  }
   255  
   256  func TestProvisionerPrepare_EnvironmentVars(t *testing.T) {
   257  	config := testConfig()
   258  
   259  	// Test with a bad case
   260  	config["environment_vars"] = []string{"badvar", "good=var"}
   261  	p := new(Provisioner)
   262  	err := p.Prepare(config)
   263  	if err == nil {
   264  		t.Fatal("should have error")
   265  	}
   266  
   267  	// Test with a trickier case
   268  	config["environment_vars"] = []string{"=bad"}
   269  	p = new(Provisioner)
   270  	err = p.Prepare(config)
   271  	if err == nil {
   272  		t.Fatal("should have error")
   273  	}
   274  
   275  	// Test with a good case
   276  	// Note: baz= is a real env variable, just empty
   277  	config["environment_vars"] = []string{"FOO=bar", "baz="}
   278  	p = new(Provisioner)
   279  	err = p.Prepare(config)
   280  	if err != nil {
   281  		t.Fatalf("should not have error: %s", err)
   282  	}
   283  }
   284  
   285  func TestProvisionerQuote_EnvironmentVars(t *testing.T) {
   286  	config := testConfig()
   287  
   288  	config["environment_vars"] = []string{"keyone=valueone", "keytwo=value\ntwo", "keythree='valuethree'", "keyfour='value\nfour'"}
   289  	p := new(Provisioner)
   290  	p.Prepare(config)
   291  
   292  	expectedValue := "keyone=valueone"
   293  	if p.config.Vars[0] != expectedValue {
   294  		t.Fatalf("%s should be equal to %s", p.config.Vars[0], expectedValue)
   295  	}
   296  
   297  	expectedValue = "keytwo=value\ntwo"
   298  	if p.config.Vars[1] != expectedValue {
   299  		t.Fatalf("%s should be equal to %s", p.config.Vars[1], expectedValue)
   300  	}
   301  
   302  	expectedValue = "keythree='valuethree'"
   303  	if p.config.Vars[2] != expectedValue {
   304  		t.Fatalf("%s should be equal to %s", p.config.Vars[2], expectedValue)
   305  	}
   306  
   307  	expectedValue = "keyfour='value\nfour'"
   308  	if p.config.Vars[3] != expectedValue {
   309  		t.Fatalf("%s should be equal to %s", p.config.Vars[3], expectedValue)
   310  	}
   311  }
   312  
   313  func testUi() *packer.BasicUi {
   314  	return &packer.BasicUi{
   315  		Reader:      new(bytes.Buffer),
   316  		Writer:      new(bytes.Buffer),
   317  		ErrorWriter: new(bytes.Buffer),
   318  	}
   319  }
   320  
   321  func testObjects() (packer.Ui, packer.Communicator) {
   322  	ui := testUi()
   323  	return ui, new(packer.MockCommunicator)
   324  }
   325  
   326  func TestProvisionerProvision_ValidExitCodes(t *testing.T) {
   327  	config := testConfig()
   328  	delete(config, "inline")
   329  
   330  	// Defaults provided by Packer
   331  	config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
   332  	config["inline"] = []string{"whoami"}
   333  	ui := testUi()
   334  	p := new(Provisioner)
   335  
   336  	// Defaults provided by Packer
   337  	p.config.PackerBuildName = "vmware"
   338  	p.config.PackerBuilderType = "iso"
   339  	p.config.ValidExitCodes = []int{0, 200}
   340  	comm := new(packer.MockCommunicator)
   341  	comm.StartExitStatus = 200
   342  	p.Prepare(config)
   343  	err := p.Provision(ui, comm)
   344  	if err != nil {
   345  		t.Fatal("should not have error")
   346  	}
   347  }
   348  
   349  func TestProvisionerProvision_InvalidExitCodes(t *testing.T) {
   350  	config := testConfig()
   351  	delete(config, "inline")
   352  
   353  	// Defaults provided by Packer
   354  	config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
   355  	config["inline"] = []string{"whoami"}
   356  	ui := testUi()
   357  	p := new(Provisioner)
   358  
   359  	// Defaults provided by Packer
   360  	p.config.PackerBuildName = "vmware"
   361  	p.config.PackerBuilderType = "iso"
   362  	p.config.ValidExitCodes = []int{0, 200}
   363  	comm := new(packer.MockCommunicator)
   364  	comm.StartExitStatus = 201 // Invalid!
   365  	p.Prepare(config)
   366  	err := p.Provision(ui, comm)
   367  	if err == nil {
   368  		t.Fatal("should have error")
   369  	}
   370  }
   371  
   372  func TestProvisionerProvision_Inline(t *testing.T) {
   373  	config := testConfig()
   374  	delete(config, "inline")
   375  
   376  	// Defaults provided by Packer
   377  	config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
   378  	config["inline"] = []string{"whoami"}
   379  	ui := testUi()
   380  	p := new(Provisioner)
   381  
   382  	// Defaults provided by Packer
   383  	p.config.PackerBuildName = "vmware"
   384  	p.config.PackerBuilderType = "iso"
   385  	comm := new(packer.MockCommunicator)
   386  	p.Prepare(config)
   387  	err := p.Provision(ui, comm)
   388  	if err != nil {
   389  		t.Fatal("should not have error")
   390  	}
   391  
   392  	expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode`
   393  	expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiAGkAcwBvACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiAHYAbQB3AGEAcgBlACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAGkAbgBsAGkAbgBlAFMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==`
   394  	expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand `
   395  	expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded
   396  
   397  	actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1)
   398  	actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix)
   399  	if err != nil {
   400  		t.Fatal("should not have error when base64 decoding")
   401  	}
   402  
   403  	if actualCommandDecoded != expectedCommand {
   404  		t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded)
   405  	}
   406  
   407  	if comm.StartCmd.Command != expectedCommandEncoded {
   408  		t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command)
   409  	}
   410  
   411  	envVars := make([]string, 2)
   412  	envVars[0] = "FOO=BAR"
   413  	envVars[1] = "BAR=BAZ"
   414  	config["environment_vars"] = envVars
   415  	config["remote_path"] = "c:/Windows/Temp/inlineScript.ps1"
   416  
   417  	p.Prepare(config)
   418  	err = p.Provision(ui, comm)
   419  	if err != nil {
   420  		t.Fatal("should not have error")
   421  	}
   422  
   423  	expectedCommand = `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR="BAZ"; $env:FOO="BAR"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; &'c:/Windows/Temp/inlineScript.ps1';exit $LastExitCode`
   424  	expectedCommandBase64Encoded = `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AEIAQQBSAD0AIgBCAEEAWgAiADsAIAAkAGUAbgB2ADoARgBPAE8APQAiAEIAQQBSACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABFAFIAXwBUAFkAUABFAD0AIgBpAHMAbwAiADsAIAAkAGUAbgB2ADoAUABBAEMASwBFAFIAXwBCAFUASQBMAEQAXwBOAEEATQBFAD0AIgB2AG0AdwBhAHIAZQAiADsAIAAmACcAYwA6AC8AVwBpAG4AZABvAHcAcwAvAFQAZQBtAHAALwBpAG4AbABpAG4AZQBTAGMAcgBpAHAAdAAuAHAAcwAxACcAOwBlAHgAaQB0ACAAJABMAGEAcwB0AEUAeABpAHQAQwBvAGQAZQA=`
   425  	expectedCommandPrefix = `powershell -executionpolicy bypass -encodedCommand `
   426  	expectedCommandEncoded = expectedCommandPrefix + expectedCommandBase64Encoded
   427  
   428  	actualCommandWithoutPrefix = strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1)
   429  	actualCommandDecoded, err = powershellDecode(actualCommandWithoutPrefix)
   430  	if err != nil {
   431  		t.Fatal("should not have error when base64 decoding")
   432  	}
   433  
   434  	if actualCommandDecoded != expectedCommand {
   435  		t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded)
   436  	}
   437  
   438  	if comm.StartCmd.Command != expectedCommandEncoded {
   439  		t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command)
   440  	}
   441  }
   442  
   443  func TestProvisionerProvision_Scripts(t *testing.T) {
   444  	tempFile, _ := ioutil.TempFile("", "packer")
   445  	defer os.Remove(tempFile.Name())
   446  	config := testConfig()
   447  	delete(config, "inline")
   448  	config["scripts"] = []string{tempFile.Name()}
   449  	config["packer_build_name"] = "foobuild"
   450  	config["packer_builder_type"] = "footype"
   451  	ui := testUi()
   452  
   453  	p := new(Provisioner)
   454  	comm := new(packer.MockCommunicator)
   455  	p.Prepare(config)
   456  	err := p.Provision(ui, comm)
   457  	if err != nil {
   458  		t.Fatal("should not have error")
   459  	}
   460  
   461  	expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode`
   462  	expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiAGYAbwBvAHQAeQBwAGUAIgA7ACAAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAF8ATgBBAE0ARQA9ACIAZgBvAG8AYgB1AGkAbABkACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAHMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==`
   463  	expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand `
   464  	expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded
   465  
   466  	actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1)
   467  	actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix)
   468  	if err != nil {
   469  		t.Fatal("should not have error when base64 decoding")
   470  	}
   471  
   472  	if actualCommandDecoded != expectedCommand {
   473  		t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded)
   474  	}
   475  
   476  	if comm.StartCmd.Command != expectedCommandEncoded {
   477  		t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command)
   478  	}
   479  }
   480  
   481  func TestProvisionerProvision_ScriptsWithEnvVars(t *testing.T) {
   482  	tempFile, _ := ioutil.TempFile("", "packer")
   483  	config := testConfig()
   484  	ui := testUi()
   485  	defer os.Remove(tempFile.Name())
   486  	delete(config, "inline")
   487  
   488  	config["scripts"] = []string{tempFile.Name()}
   489  	config["packer_build_name"] = "foobuild"
   490  	config["packer_builder_type"] = "footype"
   491  
   492  	// Env vars - currently should not effect them
   493  	envVars := make([]string, 2)
   494  	envVars[0] = "FOO=BAR"
   495  	envVars[1] = "BAR=BAZ"
   496  	config["environment_vars"] = envVars
   497  
   498  	p := new(Provisioner)
   499  	comm := new(packer.MockCommunicator)
   500  	p.Prepare(config)
   501  	err := p.Provision(ui, comm)
   502  	if err != nil {
   503  		t.Fatal("should not have error")
   504  	}
   505  
   506  	expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:BAR="BAZ"; $env:FOO="BAR"; $env:PACKER_BUILDER_TYPE="footype"; $env:PACKER_BUILD_NAME="foobuild"; &'c:/Windows/Temp/script.ps1';exit $LastExitCode`
   507  	expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AEIAQQBSAD0AIgBCAEEAWgAiADsAIAAkAGUAbgB2ADoARgBPAE8APQAiAEIAQQBSACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABFAFIAXwBUAFkAUABFAD0AIgBmAG8AbwB0AHkAcABlACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiAGYAbwBvAGIAdQBpAGwAZAAiADsAIAAmACcAYwA6AC8AVwBpAG4AZABvAHcAcwAvAFQAZQBtAHAALwBzAGMAcgBpAHAAdAAuAHAAcwAxACcAOwBlAHgAaQB0ACAAJABMAGEAcwB0AEUAeABpAHQAQwBvAGQAZQA=`
   508  	expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand `
   509  	expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded
   510  
   511  	actualCommandWithoutPrefix := strings.Replace(comm.StartCmd.Command, expectedCommandPrefix, "", -1)
   512  	actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix)
   513  	if err != nil {
   514  		t.Fatal("should not have error when base64 decoding")
   515  	}
   516  
   517  	if actualCommandDecoded != expectedCommand {
   518  		t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded)
   519  	}
   520  
   521  	if comm.StartCmd.Command != expectedCommandEncoded {
   522  		t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, comm.StartCmd.Command)
   523  	}
   524  }
   525  
   526  func TestProvisionerProvision_UISlurp(t *testing.T) {
   527  	// UI should be called n times
   528  
   529  	// UI should receive following messages / output
   530  }
   531  
   532  func TestProvisioner_createFlattenedElevatedEnvVars_windows(t *testing.T) {
   533  	config := testConfig()
   534  
   535  	p := new(Provisioner)
   536  	err := p.Prepare(config)
   537  	if err != nil {
   538  		t.Fatalf("should not have error preparing config: %s", err)
   539  	}
   540  
   541  	// Defaults provided by Packer
   542  	p.config.PackerBuildName = "vmware"
   543  	p.config.PackerBuilderType = "iso"
   544  
   545  	// no user env var
   546  	flattenedEnvVars, err := p.createFlattenedEnvVars(true)
   547  	if err != nil {
   548  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   549  	}
   550  	if flattenedEnvVars != `$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   551  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   552  	}
   553  
   554  	// single user env var
   555  	p.config.Vars = []string{"FOO=bar"}
   556  
   557  	flattenedEnvVars, err = p.createFlattenedEnvVars(true)
   558  	if err != nil {
   559  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   560  	}
   561  	if flattenedEnvVars != `$env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   562  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   563  	}
   564  
   565  	// multiple user env vars
   566  	p.config.Vars = []string{"FOO=bar", "BAZ=qux"}
   567  
   568  	flattenedEnvVars, err = p.createFlattenedEnvVars(true)
   569  	if err != nil {
   570  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   571  	}
   572  	if flattenedEnvVars != `$env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   573  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   574  	}
   575  }
   576  
   577  func TestProvisioner_createFlattenedEnvVars_windows(t *testing.T) {
   578  	config := testConfig()
   579  
   580  	p := new(Provisioner)
   581  	err := p.Prepare(config)
   582  	if err != nil {
   583  		t.Fatalf("should not have error preparing config: %s", err)
   584  	}
   585  
   586  	// Defaults provided by Packer
   587  	p.config.PackerBuildName = "vmware"
   588  	p.config.PackerBuilderType = "iso"
   589  
   590  	// no user env var
   591  	flattenedEnvVars, err := p.createFlattenedEnvVars(false)
   592  	if err != nil {
   593  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   594  	}
   595  	if flattenedEnvVars != `$env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   596  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   597  	}
   598  
   599  	// single user env var
   600  	p.config.Vars = []string{"FOO=bar"}
   601  
   602  	flattenedEnvVars, err = p.createFlattenedEnvVars(false)
   603  	if err != nil {
   604  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   605  	}
   606  	if flattenedEnvVars != `$env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   607  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   608  	}
   609  
   610  	// multiple user env vars
   611  	p.config.Vars = []string{"FOO=bar", "BAZ=qux"}
   612  
   613  	flattenedEnvVars, err = p.createFlattenedEnvVars(false)
   614  	if err != nil {
   615  		t.Fatalf("should not have error creating flattened env vars: %s", err)
   616  	}
   617  	if flattenedEnvVars != `$env:BAZ="qux"; $env:FOO="bar"; $env:PACKER_BUILDER_TYPE="iso"; $env:PACKER_BUILD_NAME="vmware"; ` {
   618  		t.Fatalf("unexpected flattened env vars: %s", flattenedEnvVars)
   619  	}
   620  }
   621  
   622  func TestProvision_createCommandText(t *testing.T) {
   623  
   624  	config := testConfig()
   625  	p := new(Provisioner)
   626  	comm := new(packer.MockCommunicator)
   627  	p.communicator = comm
   628  	_ = p.Prepare(config)
   629  
   630  	// Non-elevated
   631  	cmd, _ := p.createCommandText()
   632  
   633  	expectedCommand := `if (Test-Path variable:global:ProgressPreference){$ProgressPreference='SilentlyContinue'};$env:PACKER_BUILDER_TYPE=""; $env:PACKER_BUILD_NAME=""; &'c:/Windows/Temp/script.ps1';exit $LastExitCode`
   634  	expectedCommandBase64Encoded := `aQBmACAAKABUAGUAcwB0AC0AUABhAHQAaAAgAHYAYQByAGkAYQBiAGwAZQA6AGcAbABvAGIAYQBsADoAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAKQB7ACQAUAByAG8AZwByAGUAcwBzAFAAcgBlAGYAZQByAGUAbgBjAGUAPQAnAFMAaQBsAGUAbgB0AGwAeQBDAG8AbgB0AGkAbgB1AGUAJwB9ADsAJABlAG4AdgA6AFAAQQBDAEsARQBSAF8AQgBVAEkATABEAEUAUgBfAFQAWQBQAEUAPQAiACIAOwAgACQAZQBuAHYAOgBQAEEAQwBLAEUAUgBfAEIAVQBJAEwARABfAE4AQQBNAEUAPQAiACIAOwAgACYAJwBjADoALwBXAGkAbgBkAG8AdwBzAC8AVABlAG0AcAAvAHMAYwByAGkAcAB0AC4AcABzADEAJwA7AGUAeABpAHQAIAAkAEwAYQBzAHQARQB4AGkAdABDAG8AZABlAA==`
   635  	expectedCommandPrefix := `powershell -executionpolicy bypass -encodedCommand `
   636  	expectedCommandEncoded := expectedCommandPrefix + expectedCommandBase64Encoded
   637  
   638  	actualCommandWithoutPrefix := strings.Replace(cmd, expectedCommandPrefix, "", -1)
   639  
   640  	actualCommandDecoded, err := powershellDecode(actualCommandWithoutPrefix)
   641  	if err != nil {
   642  		t.Fatal("should not have error when base64 decoding")
   643  	}
   644  
   645  	if actualCommandDecoded != expectedCommand {
   646  		t.Fatalf("Expected decoded: %s, got %s", expectedCommand, actualCommandDecoded)
   647  	}
   648  
   649  	if cmd != expectedCommandEncoded {
   650  		t.Fatalf("Expect command to be: %s, got %s", expectedCommandEncoded, cmd)
   651  	}
   652  
   653  	// Elevated
   654  	p.config.ElevatedUser = "vagrant"
   655  	p.config.ElevatedPassword = "vagrant"
   656  	cmd, _ = p.createCommandText()
   657  	matched, _ := regexp.MatchString("powershell -executionpolicy bypass -file \"%TEMP%(.{1})packer-elevated-shell.*", cmd)
   658  	if !matched {
   659  		t.Fatalf("Got unexpected elevated command: %s", cmd)
   660  	}
   661  }
   662  
   663  func TestProvision_generateElevatedShellRunner(t *testing.T) {
   664  
   665  	// Non-elevated
   666  	config := testConfig()
   667  	p := new(Provisioner)
   668  	p.Prepare(config)
   669  	comm := new(packer.MockCommunicator)
   670  	p.communicator = comm
   671  	path, err := p.generateElevatedRunner("whoami")
   672  
   673  	if err != nil {
   674  		t.Fatalf("Did not expect error: %s", err.Error())
   675  	}
   676  
   677  	if comm.UploadCalled != true {
   678  		t.Fatalf("Should have uploaded file")
   679  	}
   680  
   681  	matched, _ := regexp.MatchString("%TEMP%(.{1})packer-elevated-shell.*", path)
   682  	if !matched {
   683  		t.Fatalf("Got unexpected file: %s", path)
   684  	}
   685  }
   686  
   687  func TestRetryable(t *testing.T) {
   688  	config := testConfig()
   689  
   690  	count := 0
   691  	retryMe := func() error {
   692  		t.Logf("RetryMe, attempt number %d", count)
   693  		if count == 2 {
   694  			return nil
   695  		}
   696  		count++
   697  		return errors.New(fmt.Sprintf("Still waiting %d more times...", 2-count))
   698  	}
   699  	retryableSleep = 50 * time.Millisecond
   700  	p := new(Provisioner)
   701  	p.config.StartRetryTimeout = 155 * time.Millisecond
   702  	err := p.Prepare(config)
   703  	err = p.retryable(retryMe)
   704  	if err != nil {
   705  		t.Fatalf("should not have error retrying funuction")
   706  	}
   707  
   708  	count = 0
   709  	p.config.StartRetryTimeout = 10 * time.Millisecond
   710  	err = p.Prepare(config)
   711  	err = p.retryable(retryMe)
   712  	if err == nil {
   713  		t.Fatalf("should have error retrying funuction")
   714  	}
   715  }
   716  
   717  func TestCancel(t *testing.T) {
   718  	// Don't actually call Cancel() as it performs an os.Exit(0)
   719  	// which kills the 'go test' tool
   720  }