github.com/andrewrynhard/terraform@v0.9.5-0.20170502003928-8d286b83eae4/backend/local/backend_plan_test.go (about)

     1  package local
     2  
     3  import (
     4  	"context"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/backend"
    11  	"github.com/hashicorp/terraform/config/module"
    12  	"github.com/hashicorp/terraform/terraform"
    13  )
    14  
    15  func TestLocal_planBasic(t *testing.T) {
    16  	b := TestLocal(t)
    17  	p := TestLocalProvider(t, b, "test")
    18  
    19  	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
    20  	defer modCleanup()
    21  
    22  	op := testOperationPlan()
    23  	op.Module = mod
    24  	op.PlanRefresh = true
    25  
    26  	run, err := b.Operation(context.Background(), op)
    27  	if err != nil {
    28  		t.Fatalf("bad: %s", err)
    29  	}
    30  	<-run.Done()
    31  	if run.Err != nil {
    32  		t.Fatalf("err: %s", err)
    33  	}
    34  
    35  	if !p.DiffCalled {
    36  		t.Fatal("diff should be called")
    37  	}
    38  }
    39  
    40  func TestLocal_planNoConfig(t *testing.T) {
    41  	b := TestLocal(t)
    42  	TestLocalProvider(t, b, "test")
    43  
    44  	op := testOperationPlan()
    45  	op.Module = nil
    46  	op.PlanRefresh = true
    47  
    48  	run, err := b.Operation(context.Background(), op)
    49  	if err != nil {
    50  		t.Fatalf("bad: %s", err)
    51  	}
    52  	<-run.Done()
    53  
    54  	err = run.Err
    55  	if err == nil {
    56  		t.Fatal("should error")
    57  	}
    58  	if !strings.Contains(err.Error(), "configuration") {
    59  		t.Fatalf("bad: %s", err)
    60  	}
    61  }
    62  
    63  func TestLocal_planRefreshFalse(t *testing.T) {
    64  	b := TestLocal(t)
    65  	p := TestLocalProvider(t, b, "test")
    66  	terraform.TestStateFile(t, b.StatePath, testPlanState())
    67  
    68  	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
    69  	defer modCleanup()
    70  
    71  	op := testOperationPlan()
    72  	op.Module = mod
    73  
    74  	run, err := b.Operation(context.Background(), op)
    75  	if err != nil {
    76  		t.Fatalf("bad: %s", err)
    77  	}
    78  	<-run.Done()
    79  	if run.Err != nil {
    80  		t.Fatalf("err: %s", err)
    81  	}
    82  
    83  	if p.RefreshCalled {
    84  		t.Fatal("refresh should not be called")
    85  	}
    86  
    87  	if !run.PlanEmpty {
    88  		t.Fatal("plan should be empty")
    89  	}
    90  }
    91  
    92  func TestLocal_planDestroy(t *testing.T) {
    93  	b := TestLocal(t)
    94  	p := TestLocalProvider(t, b, "test")
    95  	terraform.TestStateFile(t, b.StatePath, testPlanState())
    96  
    97  	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
    98  	defer modCleanup()
    99  
   100  	outDir := testTempDir(t)
   101  	defer os.RemoveAll(outDir)
   102  	planPath := filepath.Join(outDir, "plan.tfplan")
   103  
   104  	op := testOperationPlan()
   105  	op.Destroy = true
   106  	op.PlanRefresh = true
   107  	op.Module = mod
   108  	op.PlanOutPath = planPath
   109  
   110  	run, err := b.Operation(context.Background(), op)
   111  	if err != nil {
   112  		t.Fatalf("bad: %s", err)
   113  	}
   114  	<-run.Done()
   115  	if run.Err != nil {
   116  		t.Fatalf("err: %s", err)
   117  	}
   118  
   119  	if !p.RefreshCalled {
   120  		t.Fatal("refresh should be called")
   121  	}
   122  
   123  	if run.PlanEmpty {
   124  		t.Fatal("plan should not be empty")
   125  	}
   126  
   127  	plan := testReadPlan(t, planPath)
   128  	for _, m := range plan.Diff.Modules {
   129  		for _, r := range m.Resources {
   130  			if !r.Destroy {
   131  				t.Fatalf("bad: %#v", r)
   132  			}
   133  		}
   134  	}
   135  }
   136  
   137  func TestLocal_planDestroyNoConfig(t *testing.T) {
   138  	b := TestLocal(t)
   139  	p := TestLocalProvider(t, b, "test")
   140  	terraform.TestStateFile(t, b.StatePath, testPlanState())
   141  
   142  	outDir := testTempDir(t)
   143  	defer os.RemoveAll(outDir)
   144  	planPath := filepath.Join(outDir, "plan.tfplan")
   145  
   146  	op := testOperationPlan()
   147  	op.Destroy = true
   148  	op.PlanRefresh = true
   149  	op.Module = nil
   150  	op.PlanOutPath = planPath
   151  
   152  	run, err := b.Operation(context.Background(), op)
   153  	if err != nil {
   154  		t.Fatalf("bad: %s", err)
   155  	}
   156  	<-run.Done()
   157  	if run.Err != nil {
   158  		t.Fatalf("err: %s", err)
   159  	}
   160  
   161  	if !p.RefreshCalled {
   162  		t.Fatal("refresh should be called")
   163  	}
   164  
   165  	if run.PlanEmpty {
   166  		t.Fatal("plan should not be empty")
   167  	}
   168  
   169  	plan := testReadPlan(t, planPath)
   170  	for _, m := range plan.Diff.Modules {
   171  		for _, r := range m.Resources {
   172  			if !r.Destroy {
   173  				t.Fatalf("bad: %#v", r)
   174  			}
   175  		}
   176  	}
   177  }
   178  
   179  func TestLocal_planOutPathNoChange(t *testing.T) {
   180  	b := TestLocal(t)
   181  	TestLocalProvider(t, b, "test")
   182  	terraform.TestStateFile(t, b.StatePath, testPlanState())
   183  
   184  	mod, modCleanup := module.TestTree(t, "./test-fixtures/plan")
   185  	defer modCleanup()
   186  
   187  	outDir := testTempDir(t)
   188  	defer os.RemoveAll(outDir)
   189  	planPath := filepath.Join(outDir, "plan.tfplan")
   190  
   191  	op := testOperationPlan()
   192  	op.Module = mod
   193  	op.PlanOutPath = planPath
   194  
   195  	run, err := b.Operation(context.Background(), op)
   196  	if err != nil {
   197  		t.Fatalf("bad: %s", err)
   198  	}
   199  	<-run.Done()
   200  	if run.Err != nil {
   201  		t.Fatalf("err: %s", err)
   202  	}
   203  
   204  	plan := testReadPlan(t, planPath)
   205  	if !plan.Diff.Empty() {
   206  		t.Fatalf("expected empty plan to be written")
   207  	}
   208  }
   209  
   210  func testOperationPlan() *backend.Operation {
   211  	return &backend.Operation{
   212  		Type: backend.OperationTypePlan,
   213  	}
   214  }
   215  
   216  // testPlanState is just a common state that we use for testing refresh.
   217  func testPlanState() *terraform.State {
   218  	return &terraform.State{
   219  		Version: 2,
   220  		Modules: []*terraform.ModuleState{
   221  			&terraform.ModuleState{
   222  				Path: []string{"root"},
   223  				Resources: map[string]*terraform.ResourceState{
   224  					"test_instance.foo": &terraform.ResourceState{
   225  						Type: "test_instance",
   226  						Primary: &terraform.InstanceState{
   227  							ID: "bar",
   228  						},
   229  					},
   230  				},
   231  			},
   232  		},
   233  	}
   234  }
   235  
   236  func testReadPlan(t *testing.T, path string) *terraform.Plan {
   237  	f, err := os.Open(path)
   238  	if err != nil {
   239  		t.Fatalf("err: %s", err)
   240  	}
   241  	defer f.Close()
   242  
   243  	p, err := terraform.ReadPlan(f)
   244  	if err != nil {
   245  		t.Fatalf("err: %s", err)
   246  	}
   247  
   248  	return p
   249  }