github.com/lymingtonprecision/terraform@v0.9.9-0.20170613092852-62acef9611a9/command/init_test.go (about) 1 package command 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "runtime" 9 "strings" 10 "testing" 11 12 "github.com/hashicorp/terraform/helper/copy" 13 "github.com/hashicorp/terraform/plugin/discovery" 14 "github.com/mitchellh/cli" 15 ) 16 17 func TestInit_empty(t *testing.T) { 18 // Create a temporary working directory that is empty 19 td := tempDir(t) 20 os.MkdirAll(td, 0755) 21 defer os.RemoveAll(td) 22 defer testChdir(t, td)() 23 24 ui := new(cli.MockUi) 25 c := &InitCommand{ 26 Meta: Meta{ 27 testingOverrides: metaOverridesForProvider(testProvider()), 28 Ui: ui, 29 }, 30 } 31 32 args := []string{} 33 if code := c.Run(args); code != 0 { 34 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 35 } 36 } 37 38 func TestInit_multipleArgs(t *testing.T) { 39 ui := new(cli.MockUi) 40 c := &InitCommand{ 41 Meta: Meta{ 42 testingOverrides: metaOverridesForProvider(testProvider()), 43 Ui: ui, 44 }, 45 } 46 47 args := []string{ 48 "bad", 49 "bad", 50 } 51 if code := c.Run(args); code != 1 { 52 t.Fatalf("bad: \n%s", ui.OutputWriter.String()) 53 } 54 } 55 56 func TestInit_get(t *testing.T) { 57 // Create a temporary working directory that is empty 58 td := tempDir(t) 59 copy.CopyDir(testFixturePath("init-get"), td) 60 defer os.RemoveAll(td) 61 defer testChdir(t, td)() 62 63 ui := new(cli.MockUi) 64 c := &InitCommand{ 65 Meta: Meta{ 66 testingOverrides: metaOverridesForProvider(testProvider()), 67 Ui: ui, 68 }, 69 } 70 71 args := []string{} 72 if code := c.Run(args); code != 0 { 73 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 74 } 75 76 // Check output 77 output := ui.OutputWriter.String() 78 if !strings.Contains(output, "Get: file://") { 79 t.Fatalf("doesn't look like get: %s", output) 80 } 81 } 82 83 func TestInit_backend(t *testing.T) { 84 // Create a temporary working directory that is empty 85 td := tempDir(t) 86 copy.CopyDir(testFixturePath("init-backend"), td) 87 defer os.RemoveAll(td) 88 defer testChdir(t, td)() 89 90 ui := new(cli.MockUi) 91 c := &InitCommand{ 92 Meta: Meta{ 93 testingOverrides: metaOverridesForProvider(testProvider()), 94 Ui: ui, 95 }, 96 } 97 98 args := []string{} 99 if code := c.Run(args); code != 0 { 100 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 101 } 102 103 if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil { 104 t.Fatalf("err: %s", err) 105 } 106 } 107 108 func TestInit_backendUnset(t *testing.T) { 109 // Create a temporary working directory that is empty 110 td := tempDir(t) 111 copy.CopyDir(testFixturePath("init-backend"), td) 112 defer os.RemoveAll(td) 113 defer testChdir(t, td)() 114 115 { 116 ui := new(cli.MockUi) 117 c := &InitCommand{ 118 Meta: Meta{ 119 testingOverrides: metaOverridesForProvider(testProvider()), 120 Ui: ui, 121 }, 122 } 123 124 // Init 125 args := []string{} 126 if code := c.Run(args); code != 0 { 127 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 128 } 129 130 if _, err := os.Stat(filepath.Join(DefaultDataDir, DefaultStateFilename)); err != nil { 131 t.Fatalf("err: %s", err) 132 } 133 } 134 135 { 136 // Unset 137 if err := ioutil.WriteFile("main.tf", []byte(""), 0644); err != nil { 138 t.Fatalf("err: %s", err) 139 } 140 141 ui := new(cli.MockUi) 142 c := &InitCommand{ 143 Meta: Meta{ 144 testingOverrides: metaOverridesForProvider(testProvider()), 145 Ui: ui, 146 }, 147 } 148 149 args := []string{"-force-copy"} 150 if code := c.Run(args); code != 0 { 151 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 152 } 153 154 s := testStateRead(t, filepath.Join( 155 DefaultDataDir, DefaultStateFilename)) 156 if !s.Backend.Empty() { 157 t.Fatal("should not have backend config") 158 } 159 } 160 } 161 162 func TestInit_backendConfigFile(t *testing.T) { 163 // Create a temporary working directory that is empty 164 td := tempDir(t) 165 copy.CopyDir(testFixturePath("init-backend-config-file"), td) 166 defer os.RemoveAll(td) 167 defer testChdir(t, td)() 168 169 ui := new(cli.MockUi) 170 c := &InitCommand{ 171 Meta: Meta{ 172 testingOverrides: metaOverridesForProvider(testProvider()), 173 Ui: ui, 174 }, 175 } 176 177 args := []string{"-backend-config", "input.config"} 178 if code := c.Run(args); code != 0 { 179 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 180 } 181 182 // Read our saved backend config and verify we have our settings 183 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 184 if v := state.Backend.Config["path"]; v != "hello" { 185 t.Fatalf("bad: %#v", v) 186 } 187 } 188 189 func TestInit_backendConfigFileChange(t *testing.T) { 190 // Create a temporary working directory that is empty 191 td := tempDir(t) 192 copy.CopyDir(testFixturePath("init-backend-config-file-change"), td) 193 defer os.RemoveAll(td) 194 defer testChdir(t, td)() 195 196 // Ask input 197 defer testInputMap(t, map[string]string{ 198 "backend-migrate-to-new": "no", 199 })() 200 201 ui := new(cli.MockUi) 202 c := &InitCommand{ 203 Meta: Meta{ 204 testingOverrides: metaOverridesForProvider(testProvider()), 205 Ui: ui, 206 }, 207 } 208 209 args := []string{"-backend-config", "input.config"} 210 if code := c.Run(args); code != 0 { 211 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 212 } 213 214 // Read our saved backend config and verify we have our settings 215 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 216 if v := state.Backend.Config["path"]; v != "hello" { 217 t.Fatalf("bad: %#v", v) 218 } 219 } 220 221 func TestInit_backendConfigKV(t *testing.T) { 222 // Create a temporary working directory that is empty 223 td := tempDir(t) 224 copy.CopyDir(testFixturePath("init-backend-config-kv"), td) 225 defer os.RemoveAll(td) 226 defer testChdir(t, td)() 227 228 ui := new(cli.MockUi) 229 c := &InitCommand{ 230 Meta: Meta{ 231 testingOverrides: metaOverridesForProvider(testProvider()), 232 Ui: ui, 233 }, 234 } 235 236 args := []string{"-backend-config", "path=hello"} 237 if code := c.Run(args); code != 0 { 238 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 239 } 240 241 // Read our saved backend config and verify we have our settings 242 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 243 if v := state.Backend.Config["path"]; v != "hello" { 244 t.Fatalf("bad: %#v", v) 245 } 246 } 247 248 func TestInit_targetSubdir(t *testing.T) { 249 // Create a temporary working directory that is empty 250 td := tempDir(t) 251 os.MkdirAll(td, 0755) 252 defer os.RemoveAll(td) 253 defer testChdir(t, td)() 254 255 // copy the source into a subdir 256 copy.CopyDir(testFixturePath("init-backend"), filepath.Join(td, "source")) 257 258 ui := new(cli.MockUi) 259 c := &InitCommand{ 260 Meta: Meta{ 261 testingOverrides: metaOverridesForProvider(testProvider()), 262 Ui: ui, 263 }, 264 } 265 266 args := []string{ 267 "source", 268 } 269 if code := c.Run(args); code != 0 { 270 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 271 } 272 273 if _, err := os.Stat(filepath.Join(td, "source", DefaultDataDir, DefaultStateFilename)); err != nil { 274 t.Fatalf("err: %s", err) 275 } 276 277 // a data directory should not have been added to out working dir 278 if _, err := os.Stat(filepath.Join(td, DefaultDataDir)); !os.IsNotExist(err) { 279 t.Fatalf("err: %s", err) 280 } 281 } 282 283 func TestInit_backendReinitWithExtra(t *testing.T) { 284 td := tempDir(t) 285 copy.CopyDir(testFixturePath("init-backend-empty"), td) 286 defer os.RemoveAll(td) 287 defer testChdir(t, td)() 288 289 m := testMetaBackend(t, nil) 290 opts := &BackendOpts{ 291 ConfigExtra: map[string]interface{}{"path": "hello"}, 292 Init: true, 293 } 294 295 b, err := m.backendConfig(opts) 296 if err != nil { 297 t.Fatal(err) 298 } 299 300 ui := new(cli.MockUi) 301 c := &InitCommand{ 302 Meta: Meta{ 303 testingOverrides: metaOverridesForProvider(testProvider()), 304 Ui: ui, 305 }, 306 } 307 308 args := []string{"-backend-config", "path=hello"} 309 if code := c.Run(args); code != 0 { 310 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 311 } 312 313 // Read our saved backend config and verify we have our settings 314 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 315 if v := state.Backend.Config["path"]; v != "hello" { 316 t.Fatalf("bad: %#v", v) 317 } 318 319 if state.Backend.Hash != b.Hash { 320 t.Fatal("mismatched state and config backend hashes") 321 } 322 323 if state.Backend.Rehash() != b.Rehash() { 324 t.Fatal("mismatched state and config re-hashes") 325 } 326 327 // init again and make sure nothing changes 328 if code := c.Run(args); code != 0 { 329 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 330 } 331 state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 332 if v := state.Backend.Config["path"]; v != "hello" { 333 t.Fatalf("bad: %#v", v) 334 } 335 336 if state.Backend.Hash != b.Hash { 337 t.Fatal("mismatched state and config backend hashes") 338 } 339 } 340 341 // move option from config to -backend-config args 342 func TestInit_backendReinitConfigToExtra(t *testing.T) { 343 td := tempDir(t) 344 copy.CopyDir(testFixturePath("init-backend"), td) 345 defer os.RemoveAll(td) 346 defer testChdir(t, td)() 347 348 ui := new(cli.MockUi) 349 c := &InitCommand{ 350 Meta: Meta{ 351 testingOverrides: metaOverridesForProvider(testProvider()), 352 Ui: ui, 353 }, 354 } 355 356 if code := c.Run([]string{"-input=false"}); code != 0 { 357 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 358 } 359 360 // Read our saved backend config and verify we have our settings 361 state := testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 362 if v := state.Backend.Config["path"]; v != "foo" { 363 t.Fatalf("bad: %#v", v) 364 } 365 366 backendHash := state.Backend.Hash 367 368 // init again but remove the path option from the config 369 cfg := "terraform {\n backend \"local\" {}\n}\n" 370 if err := ioutil.WriteFile("main.tf", []byte(cfg), 0644); err != nil { 371 t.Fatal(err) 372 } 373 374 args := []string{"-input=false", "-backend-config=path=foo"} 375 if code := c.Run(args); code != 0 { 376 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 377 } 378 state = testStateRead(t, filepath.Join(DefaultDataDir, DefaultStateFilename)) 379 380 if state.Backend.Hash == backendHash { 381 t.Fatal("state.Backend.Hash was not updated") 382 } 383 } 384 385 // make sure inputFalse stops execution on migrate 386 func TestInit_inputFalse(t *testing.T) { 387 td := tempDir(t) 388 copy.CopyDir(testFixturePath("init-backend"), td) 389 defer os.RemoveAll(td) 390 defer testChdir(t, td)() 391 392 ui := new(cli.MockUi) 393 c := &InitCommand{ 394 Meta: Meta{ 395 testingOverrides: metaOverridesForProvider(testProvider()), 396 Ui: ui, 397 }, 398 } 399 400 args := []string{"-input=false", "-backend-config=path=foo"} 401 if code := c.Run([]string{"-input=false"}); code != 0 { 402 t.Fatalf("bad: \n%s", ui.ErrorWriter) 403 } 404 405 args = []string{"-input=false", "-backend-config=path=bar"} 406 if code := c.Run(args); code == 0 { 407 t.Fatal("init should have failed", ui.OutputWriter) 408 } 409 } 410 411 func TestInit_getProvider(t *testing.T) { 412 // Create a temporary working directory that is empty 413 td := tempDir(t) 414 copy.CopyDir(testFixturePath("init-get-providers"), td) 415 defer os.RemoveAll(td) 416 defer testChdir(t, td)() 417 418 getter := &mockGetProvider{ 419 Providers: map[string][]string{ 420 // looking for an exact version 421 "exact": []string{"1.2.3"}, 422 // config requires >= 2.3.3 423 "greater_than": []string{"2.3.4", "2.3.3", "2.3.0"}, 424 // config specifies 425 "between": []string{"3.4.5", "2.3.4", "1.2.3"}, 426 }, 427 } 428 429 ui := new(cli.MockUi) 430 c := &InitCommand{ 431 Meta: Meta{ 432 testingOverrides: metaOverridesForProvider(testProvider()), 433 Ui: ui, 434 }, 435 getProvider: getter.GetProvider, 436 } 437 438 args := []string{} 439 if code := c.Run(args); code != 0 { 440 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 441 } 442 443 // check that we got the providers for our config 444 exactPath := filepath.Join(c.pluginDir(), getter.FileName("exact", "1.2.3")) 445 if _, err := os.Stat(exactPath); os.IsNotExist(err) { 446 t.Fatal("provider 'exact' not downloaded") 447 } 448 greaterThanPath := filepath.Join(c.pluginDir(), getter.FileName("greater_than", "2.3.4")) 449 if _, err := os.Stat(greaterThanPath); os.IsNotExist(err) { 450 t.Fatal("provider 'greater_than' not downloaded") 451 } 452 betweenPath := filepath.Join(c.pluginDir(), getter.FileName("between", "2.3.4")) 453 if _, err := os.Stat(betweenPath); os.IsNotExist(err) { 454 t.Fatal("provider 'between' not downloaded") 455 } 456 } 457 458 func TestInit_getProviderMissing(t *testing.T) { 459 // Create a temporary working directory that is empty 460 td := tempDir(t) 461 copy.CopyDir(testFixturePath("init-get-providers"), td) 462 defer os.RemoveAll(td) 463 defer testChdir(t, td)() 464 465 getter := &mockGetProvider{ 466 Providers: map[string][]string{ 467 // looking for exact version 1.2.3 468 "exact": []string{"1.2.4"}, 469 // config requires >= 2.3.3 470 "greater_than": []string{"2.3.4", "2.3.3", "2.3.0"}, 471 // config specifies 472 "between": []string{"3.4.5", "2.3.4", "1.2.3"}, 473 }, 474 } 475 476 ui := new(cli.MockUi) 477 c := &InitCommand{ 478 Meta: Meta{ 479 testingOverrides: metaOverridesForProvider(testProvider()), 480 Ui: ui, 481 }, 482 getProvider: getter.GetProvider, 483 } 484 485 args := []string{} 486 if code := c.Run(args); code == 0 { 487 t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String()) 488 } 489 490 if !strings.Contains(ui.ErrorWriter.String(), "no suitable version for provider") { 491 t.Fatalf("unexpected error output: %s", ui.ErrorWriter) 492 } 493 } 494 495 func TestInit_getProviderHaveLegacyVersion(t *testing.T) { 496 // Create a temporary working directory that is empty 497 td := tempDir(t) 498 copy.CopyDir(testFixturePath("init-providers-lock"), td) 499 defer os.RemoveAll(td) 500 defer testChdir(t, td)() 501 502 if err := ioutil.WriteFile("terraform-provider-test", []byte("provider bin"), 0755); err != nil { 503 t.Fatal(err) 504 } 505 506 // provider test has a version constraint in the config, which should 507 // trigger the getProvider error below. 508 ui := new(cli.MockUi) 509 c := &InitCommand{ 510 Meta: Meta{ 511 testingOverrides: metaOverridesForProvider(testProvider()), 512 Ui: ui, 513 }, 514 getProvider: func(dst, provider string, req discovery.Constraints, protoVersion uint) error { 515 return fmt.Errorf("EXPECTED PROVIDER ERROR %s", provider) 516 }, 517 } 518 519 args := []string{} 520 if code := c.Run(args); code == 0 { 521 t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String()) 522 } 523 524 if !strings.Contains(ui.ErrorWriter.String(), "EXPECTED PROVIDER ERROR test") { 525 t.Fatalf("unexpected error output: %s", ui.ErrorWriter) 526 } 527 } 528 529 func TestInit_providerLockFile(t *testing.T) { 530 // Create a temporary working directory that is empty 531 td := tempDir(t) 532 copy.CopyDir(testFixturePath("init-provider-lock-file"), td) 533 defer os.RemoveAll(td) 534 defer testChdir(t, td)() 535 536 getter := &mockGetProvider{ 537 Providers: map[string][]string{ 538 "test": []string{"1.2.3"}, 539 }, 540 } 541 542 ui := new(cli.MockUi) 543 c := &InitCommand{ 544 Meta: Meta{ 545 testingOverrides: metaOverridesForProvider(testProvider()), 546 Ui: ui, 547 }, 548 getProvider: getter.GetProvider, 549 } 550 551 args := []string{} 552 if code := c.Run(args); code != 0 { 553 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 554 } 555 556 providersLockFile := fmt.Sprintf( 557 ".terraform/plugins/%s_%s/lock.json", 558 runtime.GOOS, runtime.GOARCH, 559 ) 560 buf, err := ioutil.ReadFile(providersLockFile) 561 if err != nil { 562 t.Fatalf("failed to read providers lock file %s: %s", providersLockFile, err) 563 } 564 // The hash in here is for the empty files that mockGetProvider produces 565 wantLockFile := strings.TrimSpace(` 566 { 567 "test": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 568 } 569 `) 570 if string(buf) != wantLockFile { 571 t.Errorf("wrong provider lock file contents\ngot: %s\nwant: %s", buf, wantLockFile) 572 } 573 }