github.com/nevins-b/terraform@v0.3.8-0.20170215184714-bbae22007d5a/command/apply_destroy_test.go (about)

     1  package command
     2  
     3  import (
     4  	"os"
     5  	"strings"
     6  	"testing"
     7  
     8  	"github.com/hashicorp/terraform/terraform"
     9  	"github.com/mitchellh/cli"
    10  )
    11  
    12  func TestApply_destroy(t *testing.T) {
    13  	originalState := &terraform.State{
    14  		Modules: []*terraform.ModuleState{
    15  			&terraform.ModuleState{
    16  				Path: []string{"root"},
    17  				Resources: map[string]*terraform.ResourceState{
    18  					"test_instance.foo": &terraform.ResourceState{
    19  						Type: "test_instance",
    20  						Primary: &terraform.InstanceState{
    21  							ID: "bar",
    22  						},
    23  					},
    24  				},
    25  			},
    26  		},
    27  	}
    28  
    29  	statePath := testStateFile(t, originalState)
    30  
    31  	p := testProvider()
    32  	ui := new(cli.MockUi)
    33  	c := &ApplyCommand{
    34  		Destroy: true,
    35  		Meta: Meta{
    36  			ContextOpts: testCtxConfig(p),
    37  			Ui:          ui,
    38  		},
    39  	}
    40  
    41  	// Run the apply command pointing to our existing state
    42  	args := []string{
    43  		"-force",
    44  		"-state", statePath,
    45  		testFixturePath("apply"),
    46  	}
    47  	if code := c.Run(args); code != 0 {
    48  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
    49  	}
    50  
    51  	// Verify a new state exists
    52  	if _, err := os.Stat(statePath); err != nil {
    53  		t.Fatalf("err: %s", err)
    54  	}
    55  
    56  	f, err := os.Open(statePath)
    57  	if err != nil {
    58  		t.Fatalf("err: %s", err)
    59  	}
    60  	defer f.Close()
    61  
    62  	state, err := terraform.ReadState(f)
    63  	if err != nil {
    64  		t.Fatalf("err: %s", err)
    65  	}
    66  	if state == nil {
    67  		t.Fatal("state should not be nil")
    68  	}
    69  
    70  	actualStr := strings.TrimSpace(state.String())
    71  	expectedStr := strings.TrimSpace(testApplyDestroyStr)
    72  	if actualStr != expectedStr {
    73  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
    74  	}
    75  
    76  	// Should have a backup file
    77  	f, err = os.Open(statePath + DefaultBackupExtension)
    78  	if err != nil {
    79  		t.Fatalf("err: %s", err)
    80  	}
    81  
    82  	backupState, err := terraform.ReadState(f)
    83  	f.Close()
    84  	if err != nil {
    85  		t.Fatalf("err: %s", err)
    86  	}
    87  
    88  	actualStr = strings.TrimSpace(backupState.String())
    89  	expectedStr = strings.TrimSpace(originalState.String())
    90  	if actualStr != expectedStr {
    91  		t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
    92  	}
    93  }
    94  
    95  func TestApply_destroyLockedState(t *testing.T) {
    96  	originalState := &terraform.State{
    97  		Modules: []*terraform.ModuleState{
    98  			&terraform.ModuleState{
    99  				Path: []string{"root"},
   100  				Resources: map[string]*terraform.ResourceState{
   101  					"test_instance.foo": &terraform.ResourceState{
   102  						Type: "test_instance",
   103  						Primary: &terraform.InstanceState{
   104  							ID: "bar",
   105  						},
   106  					},
   107  				},
   108  			},
   109  		},
   110  	}
   111  
   112  	statePath := testStateFile(t, originalState)
   113  
   114  	unlock, err := testLockState("./testdata", statePath)
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	defer unlock()
   119  
   120  	p := testProvider()
   121  	ui := new(cli.MockUi)
   122  	c := &ApplyCommand{
   123  		Destroy: true,
   124  		Meta: Meta{
   125  			ContextOpts: testCtxConfig(p),
   126  			Ui:          ui,
   127  		},
   128  	}
   129  
   130  	// Run the apply command pointing to our existing state
   131  	args := []string{
   132  		"-force",
   133  		"-state", statePath,
   134  		testFixturePath("apply"),
   135  	}
   136  
   137  	if code := c.Run(args); code == 0 {
   138  		t.Fatal("expected error")
   139  	}
   140  
   141  	output := ui.ErrorWriter.String()
   142  	if !strings.Contains(output, "locked") {
   143  		t.Fatal("command output does not look like a lock error:", output)
   144  	}
   145  }
   146  
   147  func TestApply_destroyPlan(t *testing.T) {
   148  	planPath := testPlanFile(t, &terraform.Plan{
   149  		Module: testModule(t, "apply"),
   150  	})
   151  
   152  	p := testProvider()
   153  	ui := new(cli.MockUi)
   154  	c := &ApplyCommand{
   155  		Destroy: true,
   156  		Meta: Meta{
   157  			ContextOpts: testCtxConfig(p),
   158  			Ui:          ui,
   159  		},
   160  	}
   161  
   162  	// Run the apply command pointing to our existing state
   163  	args := []string{
   164  		planPath,
   165  	}
   166  	if code := c.Run(args); code != 1 {
   167  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   168  	}
   169  }
   170  
   171  func TestApply_destroyTargeted(t *testing.T) {
   172  	originalState := &terraform.State{
   173  		Modules: []*terraform.ModuleState{
   174  			&terraform.ModuleState{
   175  				Path: []string{"root"},
   176  				Resources: map[string]*terraform.ResourceState{
   177  					"test_instance.foo": &terraform.ResourceState{
   178  						Type: "test_instance",
   179  						Primary: &terraform.InstanceState{
   180  							ID: "i-ab123",
   181  						},
   182  					},
   183  					"test_load_balancer.foo": &terraform.ResourceState{
   184  						Type: "test_load_balancer",
   185  						Primary: &terraform.InstanceState{
   186  							ID: "lb-abc123",
   187  						},
   188  					},
   189  				},
   190  			},
   191  		},
   192  	}
   193  
   194  	statePath := testStateFile(t, originalState)
   195  
   196  	p := testProvider()
   197  	ui := new(cli.MockUi)
   198  	c := &ApplyCommand{
   199  		Destroy: true,
   200  		Meta: Meta{
   201  			ContextOpts: testCtxConfig(p),
   202  			Ui:          ui,
   203  		},
   204  	}
   205  
   206  	// Run the apply command pointing to our existing state
   207  	args := []string{
   208  		"-force",
   209  		"-target", "test_instance.foo",
   210  		"-state", statePath,
   211  		testFixturePath("apply-destroy-targeted"),
   212  	}
   213  	if code := c.Run(args); code != 0 {
   214  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
   215  	}
   216  
   217  	// Verify a new state exists
   218  	if _, err := os.Stat(statePath); err != nil {
   219  		t.Fatalf("err: %s", err)
   220  	}
   221  
   222  	f, err := os.Open(statePath)
   223  	if err != nil {
   224  		t.Fatalf("err: %s", err)
   225  	}
   226  	defer f.Close()
   227  
   228  	state, err := terraform.ReadState(f)
   229  	if err != nil {
   230  		t.Fatalf("err: %s", err)
   231  	}
   232  	if state == nil {
   233  		t.Fatal("state should not be nil")
   234  	}
   235  
   236  	actualStr := strings.TrimSpace(state.String())
   237  	expectedStr := strings.TrimSpace(testApplyDestroyStr)
   238  	if actualStr != expectedStr {
   239  		t.Fatalf("bad:\n\n%s\n\nexpected:\n\n%s", actualStr, expectedStr)
   240  	}
   241  
   242  	// Should have a backup file
   243  	f, err = os.Open(statePath + DefaultBackupExtension)
   244  	if err != nil {
   245  		t.Fatalf("err: %s", err)
   246  	}
   247  
   248  	backupState, err := terraform.ReadState(f)
   249  	f.Close()
   250  	if err != nil {
   251  		t.Fatalf("err: %s", err)
   252  	}
   253  
   254  	actualStr = strings.TrimSpace(backupState.String())
   255  	expectedStr = strings.TrimSpace(originalState.String())
   256  	if actualStr != expectedStr {
   257  		t.Fatalf("bad:\n\nactual:\n%s\n\nexpected:\nb%s", actualStr, expectedStr)
   258  	}
   259  }
   260  
   261  const testApplyDestroyStr = `
   262  <no state>
   263  `