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