github.com/lymingtonprecision/terraform@v0.9.9-0.20170613092852-62acef9611a9/command/push_test.go (about) 1 package command 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "compress/gzip" 7 "fmt" 8 "io" 9 "os" 10 "path/filepath" 11 "reflect" 12 "runtime" 13 "sort" 14 "strings" 15 "testing" 16 17 atlas "github.com/hashicorp/atlas-go/v1" 18 "github.com/hashicorp/terraform/helper/copy" 19 "github.com/hashicorp/terraform/terraform" 20 "github.com/mitchellh/cli" 21 ) 22 23 func TestPush_good(t *testing.T) { 24 tmp, cwd := testCwd(t) 25 defer testFixCwd(t, tmp, cwd) 26 27 // Create remote state file, this should be pulled 28 conf, srv := testRemoteState(t, testState(), 200) 29 defer srv.Close() 30 31 // Persist local remote state 32 s := terraform.NewState() 33 s.Serial = 5 34 s.Remote = conf 35 testStateFileRemote(t, s) 36 37 // Path where the archive will be "uploaded" to 38 archivePath := testTempFile(t) 39 defer os.Remove(archivePath) 40 41 client := &mockPushClient{File: archivePath} 42 ui := new(cli.MockUi) 43 c := &PushCommand{ 44 Meta: Meta{ 45 testingOverrides: metaOverridesForProvider(testProvider()), 46 Ui: ui, 47 }, 48 49 client: client, 50 } 51 52 args := []string{ 53 "-vcs=false", 54 testFixturePath("push"), 55 } 56 if code := c.Run(args); code != 0 { 57 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 58 } 59 60 actual := testArchiveStr(t, archivePath) 61 expected := []string{ 62 ".terraform/", 63 ".terraform/terraform.tfstate", 64 "main.tf", 65 } 66 if !reflect.DeepEqual(actual, expected) { 67 t.Fatalf("bad: %#v", actual) 68 } 69 70 variables := make(map[string]interface{}) 71 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 72 t.Fatalf("bad: %#v", client.UpsertOptions) 73 } 74 75 if client.UpsertOptions.Name != "foo" { 76 t.Fatalf("bad: %#v", client.UpsertOptions) 77 } 78 } 79 80 func TestPush_goodBackendInit(t *testing.T) { 81 // Create a temporary working directory that is empty 82 td := tempDir(t) 83 copy.CopyDir(testFixturePath("push-backend-new"), td) 84 defer os.RemoveAll(td) 85 defer testChdir(t, td)() 86 87 // init backend 88 ui := new(cli.MockUi) 89 ci := &InitCommand{ 90 Meta: Meta{ 91 Ui: ui, 92 }, 93 } 94 if code := ci.Run(nil); code != 0 { 95 t.Fatalf("bad: %d\n%s", code, ui.ErrorWriter) 96 } 97 98 // Path where the archive will be "uploaded" to 99 archivePath := testTempFile(t) 100 defer os.Remove(archivePath) 101 102 client := &mockPushClient{File: archivePath} 103 ui = new(cli.MockUi) 104 c := &PushCommand{ 105 Meta: Meta{ 106 testingOverrides: metaOverridesForProvider(testProvider()), 107 Ui: ui, 108 }, 109 110 client: client, 111 } 112 113 args := []string{ 114 "-vcs=false", 115 td, 116 } 117 if code := c.Run(args); code != 0 { 118 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 119 } 120 121 actual := testArchiveStr(t, archivePath) 122 expected := []string{ 123 // Expected weird behavior, doesn't affect unpackaging 124 ".terraform/", 125 ".terraform/", 126 ".terraform/plugins/", 127 fmt.Sprintf(".terraform/plugins/%s_%s/", runtime.GOOS, runtime.GOARCH), 128 fmt.Sprintf(".terraform/plugins/%s_%s/lock.json", runtime.GOOS, runtime.GOARCH), 129 ".terraform/terraform.tfstate", 130 ".terraform/terraform.tfstate", 131 "main.tf", 132 } 133 if !reflect.DeepEqual(actual, expected) { 134 t.Fatalf("bad: %#v", actual) 135 } 136 137 variables := make(map[string]interface{}) 138 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 139 t.Fatalf("bad: %#v", client.UpsertOptions) 140 } 141 142 if client.UpsertOptions.Name != "hello" { 143 t.Fatalf("bad: %#v", client.UpsertOptions) 144 } 145 } 146 147 func TestPush_noUploadModules(t *testing.T) { 148 // Path where the archive will be "uploaded" to 149 archivePath := testTempFile(t) 150 defer os.Remove(archivePath) 151 152 client := &mockPushClient{File: archivePath} 153 ui := new(cli.MockUi) 154 c := &PushCommand{ 155 Meta: Meta{ 156 testingOverrides: metaOverridesForProvider(testProvider()), 157 Ui: ui, 158 }, 159 160 client: client, 161 } 162 163 // Path of the test. We have to do some renaming to avoid our own 164 // VCS getting in the way. 165 path := testFixturePath("push-no-upload") 166 defer os.RemoveAll(filepath.Join(path, ".terraform")) 167 168 // Move into that directory 169 defer testChdir(t, path)() 170 171 // Do a "terraform get" 172 { 173 ui := new(cli.MockUi) 174 c := &GetCommand{ 175 Meta: Meta{ 176 testingOverrides: metaOverridesForProvider(testProvider()), 177 Ui: ui, 178 }, 179 } 180 181 if code := c.Run([]string{}); code != 0 { 182 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 183 } 184 } 185 186 // Create remote state file, this should be pulled 187 conf, srv := testRemoteState(t, testState(), 200) 188 defer srv.Close() 189 190 // Persist local remote state 191 s := terraform.NewState() 192 s.Serial = 5 193 s.Remote = conf 194 defer os.Remove(testStateFileRemote(t, s)) 195 196 args := []string{ 197 "-vcs=false", 198 "-name=mitchellh/tf-test", 199 "-upload-modules=false", 200 path, 201 } 202 if code := c.Run(args); code != 0 { 203 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 204 } 205 206 // NOTE: The duplicates below are not ideal but are how things work 207 // currently due to how we manually add the files to the archive. This 208 // is definitely a "bug" we can fix in the future. 209 actual := testArchiveStr(t, archivePath) 210 expected := []string{ 211 ".terraform/", 212 ".terraform/", 213 ".terraform/terraform.tfstate", 214 ".terraform/terraform.tfstate", 215 "child/", 216 "child/main.tf", 217 "main.tf", 218 } 219 if !reflect.DeepEqual(actual, expected) { 220 t.Fatalf("bad: %#v", actual) 221 } 222 } 223 224 func TestPush_input(t *testing.T) { 225 tmp, cwd := testCwd(t) 226 defer testFixCwd(t, tmp, cwd) 227 228 // Create remote state file, this should be pulled 229 conf, srv := testRemoteState(t, testState(), 200) 230 defer srv.Close() 231 232 // Persist local remote state 233 s := terraform.NewState() 234 s.Serial = 5 235 s.Remote = conf 236 testStateFileRemote(t, s) 237 238 // Path where the archive will be "uploaded" to 239 archivePath := testTempFile(t) 240 defer os.Remove(archivePath) 241 242 client := &mockPushClient{File: archivePath} 243 ui := new(cli.MockUi) 244 c := &PushCommand{ 245 Meta: Meta{ 246 testingOverrides: metaOverridesForProvider(testProvider()), 247 Ui: ui, 248 }, 249 250 client: client, 251 } 252 253 // Disable test mode so input would be asked and setup the 254 // input reader/writers. 255 test = false 256 defer func() { test = true }() 257 defaultInputReader = bytes.NewBufferString("foo\n") 258 defaultInputWriter = new(bytes.Buffer) 259 260 args := []string{ 261 "-vcs=false", 262 testFixturePath("push-input"), 263 } 264 if code := c.Run(args); code != 0 { 265 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 266 } 267 268 variables := map[string]interface{}{ 269 "foo": "foo", 270 } 271 272 if !reflect.DeepEqual(client.UpsertOptions.Variables, variables) { 273 t.Fatalf("bad: %#v", client.UpsertOptions.Variables) 274 } 275 } 276 277 // We want a variable from atlas to fill a missing variable locally 278 func TestPush_inputPartial(t *testing.T) { 279 tmp, cwd := testCwd(t) 280 defer testFixCwd(t, tmp, cwd) 281 282 // Create remote state file, this should be pulled 283 conf, srv := testRemoteState(t, testState(), 200) 284 defer srv.Close() 285 286 // Persist local remote state 287 s := terraform.NewState() 288 s.Serial = 5 289 s.Remote = conf 290 testStateFileRemote(t, s) 291 292 // Path where the archive will be "uploaded" to 293 archivePath := testTempFile(t) 294 defer os.Remove(archivePath) 295 296 client := &mockPushClient{ 297 File: archivePath, 298 GetResult: map[string]atlas.TFVar{ 299 "foo": atlas.TFVar{Key: "foo", Value: "bar"}, 300 }, 301 } 302 ui := new(cli.MockUi) 303 c := &PushCommand{ 304 Meta: Meta{ 305 testingOverrides: metaOverridesForProvider(testProvider()), 306 Ui: ui, 307 }, 308 309 client: client, 310 } 311 312 // Disable test mode so input would be asked and setup the 313 // input reader/writers. 314 test = false 315 defer func() { test = true }() 316 defaultInputReader = bytes.NewBufferString("foo\n") 317 defaultInputWriter = new(bytes.Buffer) 318 319 args := []string{ 320 "-vcs=false", 321 testFixturePath("push-input-partial"), 322 } 323 if code := c.Run(args); code != 0 { 324 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 325 } 326 327 expectedTFVars := []atlas.TFVar{ 328 {Key: "bar", Value: "foo"}, 329 {Key: "foo", Value: "bar"}, 330 } 331 if !reflect.DeepEqual(client.UpsertOptions.TFVars, expectedTFVars) { 332 t.Logf("expected: %#v", expectedTFVars) 333 t.Fatalf("got: %#v", client.UpsertOptions.TFVars) 334 } 335 } 336 337 // This tests that the push command will override Atlas variables 338 // if requested. 339 func TestPush_localOverride(t *testing.T) { 340 // Disable test mode so input would be asked and setup the 341 // input reader/writers. 342 test = false 343 defer func() { test = true }() 344 defaultInputReader = bytes.NewBufferString("nope\n") 345 defaultInputWriter = new(bytes.Buffer) 346 347 tmp, cwd := testCwd(t) 348 defer testFixCwd(t, tmp, cwd) 349 350 // Create remote state file, this should be pulled 351 conf, srv := testRemoteState(t, testState(), 200) 352 defer srv.Close() 353 354 // Persist local remote state 355 s := terraform.NewState() 356 s.Serial = 5 357 s.Remote = conf 358 testStateFileRemote(t, s) 359 360 // Path where the archive will be "uploaded" to 361 archivePath := testTempFile(t) 362 defer os.Remove(archivePath) 363 364 client := &mockPushClient{File: archivePath} 365 // Provided vars should override existing ones 366 client.GetResult = map[string]atlas.TFVar{ 367 "foo": atlas.TFVar{ 368 Key: "foo", 369 Value: "old", 370 }, 371 } 372 ui := new(cli.MockUi) 373 c := &PushCommand{ 374 Meta: Meta{ 375 testingOverrides: metaOverridesForProvider(testProvider()), 376 Ui: ui, 377 }, 378 379 client: client, 380 } 381 382 path := testFixturePath("push-tfvars") 383 args := []string{ 384 "-var-file", path + "/terraform.tfvars", 385 "-vcs=false", 386 "-overwrite=foo", 387 path, 388 } 389 if code := c.Run(args); code != 0 { 390 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 391 } 392 393 actual := testArchiveStr(t, archivePath) 394 expected := []string{ 395 ".terraform/", 396 ".terraform/terraform.tfstate", 397 "main.tf", 398 "terraform.tfvars", 399 } 400 if !reflect.DeepEqual(actual, expected) { 401 t.Fatalf("bad: %#v", actual) 402 } 403 404 if client.UpsertOptions.Name != "foo" { 405 t.Fatalf("bad: %#v", client.UpsertOptions) 406 } 407 408 expectedTFVars := pushTFVars() 409 410 if !reflect.DeepEqual(client.UpsertOptions.TFVars, expectedTFVars) { 411 t.Logf("expected: %#v", expectedTFVars) 412 t.Fatalf("got: %#v", client.UpsertOptions.TFVars) 413 } 414 } 415 416 // This tests that the push command will override Atlas variables 417 // even if we don't have it defined locally 418 func TestPush_remoteOverride(t *testing.T) { 419 // Disable test mode so input would be asked and setup the 420 // input reader/writers. 421 test = false 422 defer func() { test = true }() 423 defaultInputReader = bytes.NewBufferString("nope\n") 424 defaultInputWriter = new(bytes.Buffer) 425 426 tmp, cwd := testCwd(t) 427 defer testFixCwd(t, tmp, cwd) 428 429 // Create remote state file, this should be pulled 430 conf, srv := testRemoteState(t, testState(), 200) 431 defer srv.Close() 432 433 // Persist local remote state 434 s := terraform.NewState() 435 s.Serial = 5 436 s.Remote = conf 437 testStateFileRemote(t, s) 438 439 // Path where the archive will be "uploaded" to 440 archivePath := testTempFile(t) 441 defer os.Remove(archivePath) 442 443 client := &mockPushClient{File: archivePath} 444 // Provided vars should override existing ones 445 client.GetResult = map[string]atlas.TFVar{ 446 "remote": atlas.TFVar{ 447 Key: "remote", 448 Value: "old", 449 }, 450 } 451 ui := new(cli.MockUi) 452 c := &PushCommand{ 453 Meta: Meta{ 454 testingOverrides: metaOverridesForProvider(testProvider()), 455 Ui: ui, 456 }, 457 458 client: client, 459 } 460 461 path := testFixturePath("push-tfvars") 462 args := []string{ 463 "-var-file", path + "/terraform.tfvars", 464 "-vcs=false", 465 "-overwrite=remote", 466 "-var", 467 "remote=new", 468 path, 469 } 470 471 if code := c.Run(args); code != 0 { 472 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 473 } 474 475 actual := testArchiveStr(t, archivePath) 476 expected := []string{ 477 ".terraform/", 478 ".terraform/terraform.tfstate", 479 "main.tf", 480 "terraform.tfvars", 481 } 482 if !reflect.DeepEqual(actual, expected) { 483 t.Fatalf("bad: %#v", actual) 484 } 485 486 if client.UpsertOptions.Name != "foo" { 487 t.Fatalf("bad: %#v", client.UpsertOptions) 488 } 489 490 found := false 491 // find the "remote" var and make sure we're going to set it 492 for _, tfVar := range client.UpsertOptions.TFVars { 493 if tfVar.Key == "remote" { 494 found = true 495 if tfVar.Value != "new" { 496 t.Log("'remote' variable should be set to 'new'") 497 t.Fatalf("sending instead: %#v", tfVar) 498 } 499 } 500 } 501 502 if !found { 503 t.Fatal("'remote' variable not being sent to atlas") 504 } 505 } 506 507 // This tests that the push command prefers Atlas variables over 508 // local ones. 509 func TestPush_preferAtlas(t *testing.T) { 510 // Disable test mode so input would be asked and setup the 511 // input reader/writers. 512 test = false 513 defer func() { test = true }() 514 defaultInputReader = bytes.NewBufferString("nope\n") 515 defaultInputWriter = new(bytes.Buffer) 516 517 tmp, cwd := testCwd(t) 518 defer testFixCwd(t, tmp, cwd) 519 520 // Create remote state file, this should be pulled 521 conf, srv := testRemoteState(t, testState(), 200) 522 defer srv.Close() 523 524 // Persist local remote state 525 s := terraform.NewState() 526 s.Serial = 5 527 s.Remote = conf 528 testStateFileRemote(t, s) 529 530 // Path where the archive will be "uploaded" to 531 archivePath := testTempFile(t) 532 defer os.Remove(archivePath) 533 534 client := &mockPushClient{File: archivePath} 535 // Provided vars should override existing ones 536 client.GetResult = map[string]atlas.TFVar{ 537 "foo": atlas.TFVar{ 538 Key: "foo", 539 Value: "old", 540 }, 541 } 542 ui := new(cli.MockUi) 543 c := &PushCommand{ 544 Meta: Meta{ 545 testingOverrides: metaOverridesForProvider(testProvider()), 546 Ui: ui, 547 }, 548 549 client: client, 550 } 551 552 path := testFixturePath("push-tfvars") 553 args := []string{ 554 "-var-file", path + "/terraform.tfvars", 555 "-vcs=false", 556 path, 557 } 558 if code := c.Run(args); code != 0 { 559 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 560 } 561 562 actual := testArchiveStr(t, archivePath) 563 expected := []string{ 564 ".terraform/", 565 ".terraform/terraform.tfstate", 566 "main.tf", 567 "terraform.tfvars", 568 } 569 if !reflect.DeepEqual(actual, expected) { 570 t.Fatalf("bad: %#v", actual) 571 } 572 573 if client.UpsertOptions.Name != "foo" { 574 t.Fatalf("bad: %#v", client.UpsertOptions) 575 } 576 577 // change the expected response to match our change 578 expectedTFVars := pushTFVars() 579 for i, v := range expectedTFVars { 580 if v.Key == "foo" { 581 expectedTFVars[i] = atlas.TFVar{Key: "foo", Value: "old"} 582 } 583 } 584 585 if !reflect.DeepEqual(expectedTFVars, client.UpsertOptions.TFVars) { 586 t.Logf("expected: %#v", expectedTFVars) 587 t.Fatalf("got: %#v", client.UpsertOptions.TFVars) 588 } 589 } 590 591 // This tests that the push command will send the variables in tfvars 592 func TestPush_tfvars(t *testing.T) { 593 // Disable test mode so input would be asked and setup the 594 // input reader/writers. 595 test = false 596 defer func() { test = true }() 597 defaultInputReader = bytes.NewBufferString("nope\n") 598 defaultInputWriter = new(bytes.Buffer) 599 600 tmp, cwd := testCwd(t) 601 defer testFixCwd(t, tmp, cwd) 602 603 // Create remote state file, this should be pulled 604 conf, srv := testRemoteState(t, testState(), 200) 605 defer srv.Close() 606 607 // Persist local remote state 608 s := terraform.NewState() 609 s.Serial = 5 610 s.Remote = conf 611 testStateFileRemote(t, s) 612 613 // Path where the archive will be "uploaded" to 614 archivePath := testTempFile(t) 615 defer os.Remove(archivePath) 616 617 client := &mockPushClient{File: archivePath} 618 ui := new(cli.MockUi) 619 c := &PushCommand{ 620 Meta: Meta{ 621 testingOverrides: metaOverridesForProvider(testProvider()), 622 Ui: ui, 623 }, 624 625 client: client, 626 } 627 628 path := testFixturePath("push-tfvars") 629 args := []string{ 630 "-var-file", path + "/terraform.tfvars", 631 "-vcs=false", 632 "-var", 633 "bar=[1,2]", 634 path, 635 } 636 if code := c.Run(args); code != 0 { 637 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 638 } 639 640 actual := testArchiveStr(t, archivePath) 641 expected := []string{ 642 ".terraform/", 643 ".terraform/terraform.tfstate", 644 "main.tf", 645 "terraform.tfvars", 646 } 647 if !reflect.DeepEqual(actual, expected) { 648 t.Fatalf("bad: %#v", actual) 649 } 650 651 if client.UpsertOptions.Name != "foo" { 652 t.Fatalf("bad: %#v", client.UpsertOptions) 653 } 654 655 //now check TFVars 656 tfvars := pushTFVars() 657 // update bar to match cli value 658 for i, v := range tfvars { 659 if v.Key == "bar" { 660 tfvars[i].Value = "[1, 2]" 661 tfvars[i].IsHCL = true 662 } 663 } 664 665 for i, expected := range tfvars { 666 got := client.UpsertOptions.TFVars[i] 667 if got != expected { 668 t.Logf("%2d expected: %#v", i, expected) 669 t.Fatalf(" got: %#v", got) 670 } 671 } 672 } 673 674 func TestPush_name(t *testing.T) { 675 tmp, cwd := testCwd(t) 676 defer testFixCwd(t, tmp, cwd) 677 678 // Create remote state file, this should be pulled 679 conf, srv := testRemoteState(t, testState(), 200) 680 defer srv.Close() 681 682 // Persist local remote state 683 s := terraform.NewState() 684 s.Serial = 5 685 s.Remote = conf 686 testStateFileRemote(t, s) 687 688 // Path where the archive will be "uploaded" to 689 archivePath := testTempFile(t) 690 defer os.Remove(archivePath) 691 692 client := &mockPushClient{File: archivePath} 693 ui := new(cli.MockUi) 694 c := &PushCommand{ 695 Meta: Meta{ 696 testingOverrides: metaOverridesForProvider(testProvider()), 697 Ui: ui, 698 }, 699 700 client: client, 701 } 702 703 args := []string{ 704 "-name", "bar", 705 "-vcs=false", 706 testFixturePath("push"), 707 } 708 if code := c.Run(args); code != 0 { 709 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 710 } 711 712 if client.UpsertOptions.Name != "bar" { 713 t.Fatalf("bad: %#v", client.UpsertOptions) 714 } 715 } 716 717 func TestPush_noState(t *testing.T) { 718 tmp, cwd := testCwd(t) 719 defer testFixCwd(t, tmp, cwd) 720 721 ui := new(cli.MockUi) 722 c := &PushCommand{ 723 Meta: Meta{ 724 testingOverrides: metaOverridesForProvider(testProvider()), 725 Ui: ui, 726 }, 727 } 728 729 args := []string{} 730 if code := c.Run(args); code != 1 { 731 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 732 } 733 } 734 735 func TestPush_noRemoteState(t *testing.T) { 736 // Create a temporary working directory that is empty 737 td := tempDir(t) 738 copy.CopyDir(testFixturePath("push-no-remote"), td) 739 defer os.RemoveAll(td) 740 defer testChdir(t, td)() 741 742 state := &terraform.State{ 743 Modules: []*terraform.ModuleState{ 744 &terraform.ModuleState{ 745 Path: []string{"root"}, 746 Resources: map[string]*terraform.ResourceState{ 747 "test_instance.foo": &terraform.ResourceState{ 748 Type: "test_instance", 749 Primary: &terraform.InstanceState{ 750 ID: "bar", 751 }, 752 }, 753 }, 754 }, 755 }, 756 } 757 statePath := testStateFile(t, state) 758 759 // Path where the archive will be "uploaded" to 760 archivePath := testTempFile(t) 761 defer os.Remove(archivePath) 762 763 client := &mockPushClient{File: archivePath} 764 ui := new(cli.MockUi) 765 c := &PushCommand{ 766 Meta: Meta{ 767 Ui: ui, 768 }, 769 client: client, 770 } 771 772 args := []string{ 773 "-vcs=false", 774 "-state", statePath, 775 td, 776 } 777 if code := c.Run(args); code != 1 { 778 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 779 } 780 781 errStr := ui.ErrorWriter.String() 782 if !strings.Contains(errStr, "remote backend") { 783 t.Fatalf("bad: %s", errStr) 784 } 785 } 786 787 func TestPush_plan(t *testing.T) { 788 tmp, cwd := testCwd(t) 789 defer testFixCwd(t, tmp, cwd) 790 791 // Create remote state file, this should be pulled 792 conf, srv := testRemoteState(t, testState(), 200) 793 defer srv.Close() 794 795 // Persist local remote state 796 s := terraform.NewState() 797 s.Serial = 5 798 s.Remote = conf 799 testStateFileRemote(t, s) 800 801 // Create a plan 802 planPath := testPlanFile(t, &terraform.Plan{ 803 Module: testModule(t, "apply"), 804 }) 805 806 ui := new(cli.MockUi) 807 c := &PushCommand{ 808 Meta: Meta{ 809 testingOverrides: metaOverridesForProvider(testProvider()), 810 Ui: ui, 811 }, 812 } 813 814 args := []string{planPath} 815 if code := c.Run(args); code != 1 { 816 t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) 817 } 818 } 819 820 func testArchiveStr(t *testing.T, path string) []string { 821 f, err := os.Open(path) 822 if err != nil { 823 t.Fatalf("err: %s", err) 824 } 825 defer f.Close() 826 827 // Ungzip 828 gzipR, err := gzip.NewReader(f) 829 if err != nil { 830 t.Fatalf("err: %s", err) 831 } 832 833 // Accumulator 834 result := make([]string, 0, 10) 835 836 // Untar 837 tarR := tar.NewReader(gzipR) 838 for { 839 header, err := tarR.Next() 840 if err == io.EOF { 841 break 842 } 843 if err != nil { 844 t.Fatalf("err: %s", err) 845 } 846 847 result = append(result, header.Name) 848 } 849 850 sort.Strings(result) 851 return result 852 } 853 854 // we always quote map keys to be safe 855 func pushTFVars() []atlas.TFVar { 856 return []atlas.TFVar{ 857 {Key: "bar", Value: "foo", IsHCL: false}, 858 {Key: "baz", Value: `{ 859 "A" = "a" 860 }`, IsHCL: true}, 861 {Key: "fob", Value: `["a", "quotes \"in\" quotes"]`, IsHCL: true}, 862 {Key: "foo", Value: "bar", IsHCL: false}, 863 } 864 } 865 866 // the structure returned from the push-tfvars test fixture 867 func pushTFVarsMap() map[string]atlas.TFVar { 868 vars := make(map[string]atlas.TFVar) 869 for _, v := range pushTFVars() { 870 vars[v.Key] = v 871 } 872 return vars 873 }