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 }