github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/command/e2etest/primary_test.go (about) 1 package e2etest 2 3 import ( 4 "path/filepath" 5 "reflect" 6 "sort" 7 "strings" 8 "testing" 9 10 "github.com/davecgh/go-spew/spew" 11 "github.com/hashicorp/terraform/e2e" 12 ) 13 14 // The tests in this file are for the "primary workflow", which includes 15 // variants of the following sequence, with different details: 16 // terraform init 17 // terraform plan 18 // terraform apply 19 // terraform destroy 20 21 func TestPrimarySeparatePlan(t *testing.T) { 22 t.Parallel() 23 24 // This test reaches out to releases.hashicorp.com to download the 25 // template and null providers, so it can only run if network access is 26 // allowed. 27 skipIfCannotAccessNetwork(t) 28 29 fixturePath := filepath.Join("test-fixtures", "full-workflow-null") 30 tf := e2e.NewBinary(terraformBin, fixturePath) 31 defer tf.Close() 32 33 //// INIT 34 stdout, stderr, err := tf.Run("init") 35 if err != nil { 36 t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, stderr) 37 } 38 39 // Make sure we actually downloaded the plugins, rather than picking up 40 // copies that might be already installed globally on the system. 41 if !strings.Contains(stdout, "- Downloading plugin for provider \"template\"") { 42 t.Errorf("template provider download message is missing from init output:\n%s", stdout) 43 t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") 44 } 45 if !strings.Contains(stdout, "- Downloading plugin for provider \"null\"") { 46 t.Errorf("null provider download message is missing from init output:\n%s", stdout) 47 t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)") 48 } 49 50 //// PLAN 51 stdout, stderr, err = tf.Run("plan", "-out=tfplan") 52 if err != nil { 53 t.Fatalf("unexpected plan error: %s\nstderr:\n%s", err, stderr) 54 } 55 56 if !strings.Contains(stdout, "1 to add, 0 to change, 0 to destroy") { 57 t.Errorf("incorrect plan tally; want 1 to add:\n%s", stdout) 58 } 59 60 if !strings.Contains(stdout, "This plan was saved to: tfplan") { 61 t.Errorf("missing \"This plan was saved to...\" message in plan output\n%s", stdout) 62 } 63 if !strings.Contains(stdout, "terraform apply \"tfplan\"") { 64 t.Errorf("missing next-step instruction in plan output\n%s", stdout) 65 } 66 67 plan, err := tf.Plan("tfplan") 68 if err != nil { 69 t.Fatalf("failed to read plan file: %s", err) 70 } 71 72 stateResources := plan.State.RootModule().Resources 73 diffResources := plan.Diff.RootModule().Resources 74 75 if len(stateResources) != 1 || stateResources["data.template_file.test"] == nil { 76 t.Errorf("incorrect state in plan; want just data.template_file.test to have been rendered, but have:\n%s", spew.Sdump(stateResources)) 77 } 78 if len(diffResources) != 1 || diffResources["null_resource.test"] == nil { 79 t.Errorf("incorrect diff in plan; want just null_resource.test to have been rendered, but have:\n%s", spew.Sdump(diffResources)) 80 } 81 82 //// APPLY 83 stdout, stderr, err = tf.Run("apply", "tfplan") 84 if err != nil { 85 t.Fatalf("unexpected apply error: %s\nstderr:\n%s", err, stderr) 86 } 87 88 if !strings.Contains(stdout, "Resources: 1 added, 0 changed, 0 destroyed") { 89 t.Errorf("incorrect apply tally; want 1 added:\n%s", stdout) 90 } 91 92 state, err := tf.LocalState() 93 if err != nil { 94 t.Fatalf("failed to read state file: %s", err) 95 } 96 97 stateResources = state.RootModule().Resources 98 var gotResources []string 99 for n := range stateResources { 100 gotResources = append(gotResources, n) 101 } 102 sort.Strings(gotResources) 103 104 wantResources := []string{ 105 "data.template_file.test", 106 "null_resource.test", 107 } 108 109 if !reflect.DeepEqual(gotResources, wantResources) { 110 t.Errorf("wrong resources in state\ngot: %#v\nwant: %#v", gotResources, wantResources) 111 } 112 113 //// DESTROY 114 stdout, stderr, err = tf.Run("destroy", "-force") 115 if err != nil { 116 t.Fatalf("unexpected destroy error: %s\nstderr:\n%s", err, stderr) 117 } 118 119 if !strings.Contains(stdout, "Resources: 1 destroyed") { 120 t.Errorf("incorrect destroy tally; want 1 destroyed:\n%s", stdout) 121 } 122 123 state, err = tf.LocalState() 124 if err != nil { 125 t.Fatalf("failed to read state file after destroy: %s", err) 126 } 127 128 stateResources = state.RootModule().Resources 129 if len(stateResources) != 0 { 130 t.Errorf("wrong resources in state after destroy; want none, but still have:%s", spew.Sdump(stateResources)) 131 } 132 133 }