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  }