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 }