github.com/cbroglie/terraform@v0.7.0-rc3.0.20170410193827-735dfc416d46/backend/local/backend_test.go (about)

     1  package local
     2  
     3  import (
     4  	"errors"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"reflect"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/terraform/backend"
    13  	"github.com/hashicorp/terraform/state"
    14  	"github.com/hashicorp/terraform/terraform"
    15  )
    16  
    17  func TestLocal_impl(t *testing.T) {
    18  	var _ backend.Enhanced = new(Local)
    19  	var _ backend.Local = new(Local)
    20  	var _ backend.CLI = new(Local)
    21  }
    22  
    23  func TestLocal_backend(t *testing.T) {
    24  	defer testTmpDir(t)()
    25  	b := &Local{}
    26  	backend.TestBackend(t, b, b)
    27  }
    28  
    29  func checkState(t *testing.T, path, expected string) {
    30  	// Read the state
    31  	f, err := os.Open(path)
    32  	if err != nil {
    33  		t.Fatalf("err: %s", err)
    34  	}
    35  
    36  	state, err := terraform.ReadState(f)
    37  	f.Close()
    38  	if err != nil {
    39  		t.Fatalf("err: %s", err)
    40  	}
    41  
    42  	actual := strings.TrimSpace(state.String())
    43  	expected = strings.TrimSpace(expected)
    44  	if actual != expected {
    45  		t.Fatalf("state does not match! actual:\n%s\n\nexpected:\n%s", actual, expected)
    46  	}
    47  }
    48  
    49  func TestLocal_StatePaths(t *testing.T) {
    50  	b := &Local{}
    51  
    52  	// Test the defaults
    53  	path, out, back := b.StatePaths("")
    54  
    55  	if path != DefaultStateFilename {
    56  		t.Fatalf("expected %q, got %q", DefaultStateFilename, path)
    57  	}
    58  
    59  	if out != DefaultStateFilename {
    60  		t.Fatalf("expected %q, got %q", DefaultStateFilename, out)
    61  	}
    62  
    63  	dfltBackup := DefaultStateFilename + DefaultBackupExtension
    64  	if back != dfltBackup {
    65  		t.Fatalf("expected %q, got %q", dfltBackup, back)
    66  	}
    67  
    68  	// check with env
    69  	testEnv := "test_env"
    70  	path, out, back = b.StatePaths(testEnv)
    71  
    72  	expectedPath := filepath.Join(DefaultEnvDir, testEnv, DefaultStateFilename)
    73  	expectedOut := expectedPath
    74  	expectedBackup := expectedPath + DefaultBackupExtension
    75  
    76  	if path != expectedPath {
    77  		t.Fatalf("expected %q, got %q", expectedPath, path)
    78  	}
    79  
    80  	if out != expectedOut {
    81  		t.Fatalf("expected %q, got %q", expectedOut, out)
    82  	}
    83  
    84  	if back != expectedBackup {
    85  		t.Fatalf("expected %q, got %q", expectedBackup, back)
    86  	}
    87  
    88  }
    89  
    90  func TestLocal_addAndRemoveStates(t *testing.T) {
    91  	defer testTmpDir(t)()
    92  	dflt := backend.DefaultStateName
    93  	expectedStates := []string{dflt}
    94  
    95  	b := &Local{}
    96  	states, err := b.States()
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  
   101  	if !reflect.DeepEqual(states, expectedStates) {
   102  		t.Fatalf("expected []string{%q}, got %q", dflt, states)
   103  	}
   104  
   105  	expectedA := "test_A"
   106  	if _, err := b.State(expectedA); err != nil {
   107  		t.Fatal(err)
   108  	}
   109  
   110  	states, err = b.States()
   111  	if err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	expectedStates = append(expectedStates, expectedA)
   116  	if !reflect.DeepEqual(states, expectedStates) {
   117  		t.Fatalf("expected %q, got %q", expectedStates, states)
   118  	}
   119  
   120  	expectedB := "test_B"
   121  	if _, err := b.State(expectedB); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	states, err = b.States()
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	expectedStates = append(expectedStates, expectedB)
   131  	if !reflect.DeepEqual(states, expectedStates) {
   132  		t.Fatalf("expected %q, got %q", expectedStates, states)
   133  	}
   134  
   135  	if err := b.DeleteState(expectedA); err != nil {
   136  		t.Fatal(err)
   137  	}
   138  
   139  	states, err = b.States()
   140  	if err != nil {
   141  		t.Fatal(err)
   142  	}
   143  
   144  	expectedStates = []string{dflt, expectedB}
   145  	if !reflect.DeepEqual(states, expectedStates) {
   146  		t.Fatalf("expected %q, got %q", expectedStates, states)
   147  	}
   148  
   149  	if err := b.DeleteState(expectedB); err != nil {
   150  		t.Fatal(err)
   151  	}
   152  
   153  	states, err = b.States()
   154  	if err != nil {
   155  		t.Fatal(err)
   156  	}
   157  
   158  	expectedStates = []string{dflt}
   159  	if !reflect.DeepEqual(states, expectedStates) {
   160  		t.Fatalf("expected %q, got %q", expectedStates, states)
   161  	}
   162  
   163  	if err := b.DeleteState(dflt); err == nil {
   164  		t.Fatal("expected error deleting default state")
   165  	}
   166  }
   167  
   168  // a local backend which returns sentinel errors for NamedState methods to
   169  // verify it's being called.
   170  type testDelegateBackend struct {
   171  	*Local
   172  }
   173  
   174  var errTestDelegateState = errors.New("State called")
   175  var errTestDelegateStates = errors.New("States called")
   176  var errTestDelegateDeleteState = errors.New("Delete called")
   177  
   178  func (b *testDelegateBackend) State(name string) (state.State, error) {
   179  	return nil, errTestDelegateState
   180  }
   181  
   182  func (b *testDelegateBackend) States() ([]string, error) {
   183  	return nil, errTestDelegateStates
   184  }
   185  
   186  func (b *testDelegateBackend) DeleteState(name string) error {
   187  	return errTestDelegateDeleteState
   188  }
   189  
   190  // verify that the MultiState methods are dispatched to the correct Backend.
   191  func TestLocal_multiStateBackend(t *testing.T) {
   192  	// assign a separate backend where we can read the state
   193  	b := &Local{
   194  		Backend: &testDelegateBackend{},
   195  	}
   196  
   197  	if _, err := b.State("test"); err != errTestDelegateState {
   198  		t.Fatal("expected errTestDelegateState, got:", err)
   199  	}
   200  
   201  	if _, err := b.States(); err != errTestDelegateStates {
   202  		t.Fatal("expected errTestDelegateStates, got:", err)
   203  	}
   204  
   205  	if err := b.DeleteState("test"); err != errTestDelegateDeleteState {
   206  		t.Fatal("expected errTestDelegateDeleteState, got:", err)
   207  	}
   208  
   209  }
   210  
   211  // change into a tmp dir and return a deferable func to change back and cleanup
   212  func testTmpDir(t *testing.T) func() {
   213  	tmp, err := ioutil.TempDir("", "tf")
   214  	if err != nil {
   215  		t.Fatal(err)
   216  	}
   217  
   218  	old, err := os.Getwd()
   219  	if err != nil {
   220  		t.Fatal(err)
   221  	}
   222  
   223  	if err := os.Chdir(tmp); err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	return func() {
   228  		// ignore errors and try to clean up
   229  		os.Chdir(old)
   230  		os.RemoveAll(tmp)
   231  	}
   232  }