github.com/spirius/terraform@v0.10.0-beta2.0.20170714185654-87b2c0cf8fea/command/workspace_command_test.go (about)

     1  package command
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/backend"
    11  	"github.com/hashicorp/terraform/backend/local"
    12  	"github.com/hashicorp/terraform/state"
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"github.com/mitchellh/cli"
    15  )
    16  
    17  func TestWorkspace_createAndChange(t *testing.T) {
    18  	// Create a temporary working directory that is empty
    19  	td := tempDir(t)
    20  	os.MkdirAll(td, 0755)
    21  	defer os.RemoveAll(td)
    22  	defer testChdir(t, td)()
    23  
    24  	newCmd := &WorkspaceNewCommand{}
    25  
    26  	current := newCmd.Workspace()
    27  	if current != backend.DefaultStateName {
    28  		t.Fatal("current workspace should be 'default'")
    29  	}
    30  
    31  	args := []string{"test"}
    32  	ui := new(cli.MockUi)
    33  	newCmd.Meta = Meta{Ui: ui}
    34  	if code := newCmd.Run(args); code != 0 {
    35  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
    36  	}
    37  
    38  	current = newCmd.Workspace()
    39  	if current != "test" {
    40  		t.Fatalf("current workspace should be 'test', got %q", current)
    41  	}
    42  
    43  	selCmd := &WorkspaceSelectCommand{}
    44  	args = []string{backend.DefaultStateName}
    45  	ui = new(cli.MockUi)
    46  	selCmd.Meta = Meta{Ui: ui}
    47  	if code := selCmd.Run(args); code != 0 {
    48  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
    49  	}
    50  
    51  	current = newCmd.Workspace()
    52  	if current != backend.DefaultStateName {
    53  		t.Fatal("current workspace should be 'default'")
    54  	}
    55  
    56  }
    57  
    58  // Create some workspaces and test the list output.
    59  // This also ensures we switch to the correct env after each call
    60  func TestWorkspace_createAndList(t *testing.T) {
    61  	// Create a temporary working directory that is empty
    62  	td := tempDir(t)
    63  	os.MkdirAll(td, 0755)
    64  	defer os.RemoveAll(td)
    65  	defer testChdir(t, td)()
    66  
    67  	// make sure a vars file doesn't interfere
    68  	err := ioutil.WriteFile(
    69  		DefaultVarsFilename,
    70  		[]byte(`foo = "bar"`),
    71  		0644,
    72  	)
    73  	if err != nil {
    74  		t.Fatal(err)
    75  	}
    76  
    77  	envs := []string{"test_a", "test_b", "test_c"}
    78  
    79  	// create multiple workspaces
    80  	for _, env := range envs {
    81  		ui := new(cli.MockUi)
    82  		newCmd := &WorkspaceNewCommand{
    83  			Meta: Meta{Ui: ui},
    84  		}
    85  		if code := newCmd.Run([]string{env}); code != 0 {
    86  			t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
    87  		}
    88  	}
    89  
    90  	listCmd := &WorkspaceListCommand{}
    91  	ui := new(cli.MockUi)
    92  	listCmd.Meta = Meta{Ui: ui}
    93  
    94  	if code := listCmd.Run(nil); code != 0 {
    95  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
    96  	}
    97  
    98  	actual := strings.TrimSpace(ui.OutputWriter.String())
    99  	expected := "default\n  test_a\n  test_b\n* test_c"
   100  
   101  	if actual != expected {
   102  		t.Fatalf("\nexpected: %q\nactual:  %q", expected, actual)
   103  	}
   104  }
   105  
   106  // Create some workspaces and test the show output.
   107  func TestWorkspace_createAndShow(t *testing.T) {
   108  	// Create a temporary working directory that is empty
   109  	td := tempDir(t)
   110  	os.MkdirAll(td, 0755)
   111  	defer os.RemoveAll(td)
   112  	defer testChdir(t, td)()
   113  
   114  	// make sure a vars file doesn't interfere
   115  	err := ioutil.WriteFile(
   116  		DefaultVarsFilename,
   117  		[]byte(`foo = "bar"`),
   118  		0644,
   119  	)
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  
   124  	// make sure current workspace show outputs "default"
   125  	showCmd := &WorkspaceShowCommand{}
   126  	ui := new(cli.MockUi)
   127  	showCmd.Meta = Meta{Ui: ui}
   128  
   129  	if code := showCmd.Run(nil); code != 0 {
   130  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   131  	}
   132  
   133  	actual := strings.TrimSpace(ui.OutputWriter.String())
   134  	expected := "default"
   135  
   136  	if actual != expected {
   137  		t.Fatalf("\nexpected: %q\nactual:  %q", expected, actual)
   138  	}
   139  
   140  	newCmd := &WorkspaceNewCommand{}
   141  
   142  	env := []string{"test_a"}
   143  
   144  	// create test_a workspace
   145  	ui = new(cli.MockUi)
   146  	newCmd.Meta = Meta{Ui: ui}
   147  	if code := newCmd.Run(env); code != 0 {
   148  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   149  	}
   150  
   151  	selCmd := &WorkspaceSelectCommand{}
   152  	ui = new(cli.MockUi)
   153  	selCmd.Meta = Meta{Ui: ui}
   154  	if code := selCmd.Run(env); code != 0 {
   155  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   156  	}
   157  
   158  	showCmd = &WorkspaceShowCommand{}
   159  	ui = new(cli.MockUi)
   160  	showCmd.Meta = Meta{Ui: ui}
   161  
   162  	if code := showCmd.Run(nil); code != 0 {
   163  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   164  	}
   165  
   166  	actual = strings.TrimSpace(ui.OutputWriter.String())
   167  	expected = "test_a"
   168  
   169  	if actual != expected {
   170  		t.Fatalf("\nexpected: %q\nactual:  %q", expected, actual)
   171  	}
   172  }
   173  
   174  // Don't allow names that aren't URL safe
   175  func TestWorkspace_createInvalid(t *testing.T) {
   176  	// Create a temporary working directory that is empty
   177  	td := tempDir(t)
   178  	os.MkdirAll(td, 0755)
   179  	defer os.RemoveAll(td)
   180  	defer testChdir(t, td)()
   181  
   182  	envs := []string{"test_a*", "test_b/foo", "../../../test_c", "好_d"}
   183  
   184  	// create multiple workspaces
   185  	for _, env := range envs {
   186  		ui := new(cli.MockUi)
   187  		newCmd := &WorkspaceNewCommand{
   188  			Meta: Meta{Ui: ui},
   189  		}
   190  		if code := newCmd.Run([]string{env}); code == 0 {
   191  			t.Fatalf("expected failure: \n%s", ui.OutputWriter)
   192  		}
   193  	}
   194  
   195  	// list workspaces to make sure none were created
   196  	listCmd := &WorkspaceListCommand{}
   197  	ui := new(cli.MockUi)
   198  	listCmd.Meta = Meta{Ui: ui}
   199  
   200  	if code := listCmd.Run(nil); code != 0 {
   201  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   202  	}
   203  
   204  	actual := strings.TrimSpace(ui.OutputWriter.String())
   205  	expected := "* default"
   206  
   207  	if actual != expected {
   208  		t.Fatalf("\nexpected: %q\nactual:  %q", expected, actual)
   209  	}
   210  }
   211  
   212  func TestWorkspace_createWithState(t *testing.T) {
   213  	td := tempDir(t)
   214  	os.MkdirAll(td, 0755)
   215  	defer os.RemoveAll(td)
   216  	defer testChdir(t, td)()
   217  
   218  	// create a non-empty state
   219  	originalState := &terraform.State{
   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  	err := (&state.LocalState{Path: "test.tfstate"}).WriteState(originalState)
   236  	if err != nil {
   237  		t.Fatal(err)
   238  	}
   239  
   240  	args := []string{"-state", "test.tfstate", "test"}
   241  	ui := new(cli.MockUi)
   242  	newCmd := &WorkspaceNewCommand{
   243  		Meta: Meta{Ui: ui},
   244  	}
   245  	if code := newCmd.Run(args); code != 0 {
   246  		t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter)
   247  	}
   248  
   249  	newPath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
   250  	envState := state.LocalState{Path: newPath}
   251  	err = envState.RefreshState()
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  	newState := envState.State()
   257  	originalState.Version = newState.Version // the round-trip through the state manager implicitly populates version
   258  	if !originalState.Equal(newState) {
   259  		t.Fatalf("states not equal\norig: %s\nnew: %s", originalState, newState)
   260  	}
   261  }
   262  
   263  func TestWorkspace_delete(t *testing.T) {
   264  	td := tempDir(t)
   265  	os.MkdirAll(td, 0755)
   266  	defer os.RemoveAll(td)
   267  	defer testChdir(t, td)()
   268  
   269  	// create the workspace directories
   270  	if err := os.MkdirAll(filepath.Join(local.DefaultWorkspaceDir, "test"), 0755); err != nil {
   271  		t.Fatal(err)
   272  	}
   273  
   274  	// create the workspace file
   275  	if err := os.MkdirAll(DefaultDataDir, 0755); err != nil {
   276  		t.Fatal(err)
   277  	}
   278  	if err := ioutil.WriteFile(filepath.Join(DefaultDataDir, local.DefaultWorkspaceFile), []byte("test"), 0644); err != nil {
   279  		t.Fatal(err)
   280  	}
   281  
   282  	ui := new(cli.MockUi)
   283  	delCmd := &WorkspaceDeleteCommand{
   284  		Meta: Meta{Ui: ui},
   285  	}
   286  
   287  	current := delCmd.Workspace()
   288  	if current != "test" {
   289  		t.Fatal("wrong workspace:", current)
   290  	}
   291  
   292  	// we can't delete our current workspace
   293  	args := []string{"test"}
   294  	if code := delCmd.Run(args); code == 0 {
   295  		t.Fatal("expected error deleting current workspace")
   296  	}
   297  
   298  	// change back to default
   299  	if err := delCmd.SetWorkspace(backend.DefaultStateName); err != nil {
   300  		t.Fatal(err)
   301  	}
   302  
   303  	// try the delete again
   304  	ui = new(cli.MockUi)
   305  	delCmd.Meta.Ui = ui
   306  	if code := delCmd.Run(args); code != 0 {
   307  		t.Fatalf("error deleting workspace: %s", ui.ErrorWriter)
   308  	}
   309  
   310  	current = delCmd.Workspace()
   311  	if current != backend.DefaultStateName {
   312  		t.Fatalf("wrong workspace: %q", current)
   313  	}
   314  }
   315  func TestWorkspace_deleteWithState(t *testing.T) {
   316  	td := tempDir(t)
   317  	os.MkdirAll(td, 0755)
   318  	defer os.RemoveAll(td)
   319  	defer testChdir(t, td)()
   320  
   321  	// create the workspace directories
   322  	if err := os.MkdirAll(filepath.Join(local.DefaultWorkspaceDir, "test"), 0755); err != nil {
   323  		t.Fatal(err)
   324  	}
   325  
   326  	// create a non-empty state
   327  	originalState := &terraform.State{
   328  		Modules: []*terraform.ModuleState{
   329  			&terraform.ModuleState{
   330  				Path: []string{"root"},
   331  				Resources: map[string]*terraform.ResourceState{
   332  					"test_instance.foo": &terraform.ResourceState{
   333  						Type: "test_instance",
   334  						Primary: &terraform.InstanceState{
   335  							ID: "bar",
   336  						},
   337  					},
   338  				},
   339  			},
   340  		},
   341  	}
   342  
   343  	envStatePath := filepath.Join(local.DefaultWorkspaceDir, "test", DefaultStateFilename)
   344  	err := (&state.LocalState{Path: envStatePath}).WriteState(originalState)
   345  	if err != nil {
   346  		t.Fatal(err)
   347  	}
   348  
   349  	ui := new(cli.MockUi)
   350  	delCmd := &WorkspaceDeleteCommand{
   351  		Meta: Meta{Ui: ui},
   352  	}
   353  	args := []string{"test"}
   354  	if code := delCmd.Run(args); code == 0 {
   355  		t.Fatalf("expected failure without -force.\noutput: %s", ui.OutputWriter)
   356  	}
   357  
   358  	ui = new(cli.MockUi)
   359  	delCmd.Meta.Ui = ui
   360  
   361  	args = []string{"-force", "test"}
   362  	if code := delCmd.Run(args); code != 0 {
   363  		t.Fatalf("failure: %s", ui.ErrorWriter)
   364  	}
   365  
   366  	if _, err := os.Stat(filepath.Join(local.DefaultWorkspaceDir, "test")); !os.IsNotExist(err) {
   367  		t.Fatal("env 'test' still exists!")
   368  	}
   369  }