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