Skip to content

Commit 67f6cda

Browse files
committed
Show that planning for one workspace, switching, and then applying the plan in the wrong workspace doesn't fail
1 parent d884031 commit 67f6cda

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

internal/command/e2etest/primary_test.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,124 @@ func TestPrimarySeparatePlan(t *testing.T) {
149149

150150
}
151151

152+
func TestPrimarySeparatePlan_incorrectWorkspace(t *testing.T) {
153+
t.Parallel()
154+
155+
// This test reaches out to releases.hashicorp.com to download the
156+
// template and null providers, so it can only run if network access is
157+
// allowed.
158+
skipIfCannotAccessNetwork(t)
159+
160+
fixturePath := filepath.Join("testdata", "full-workflow-null")
161+
tf := e2e.NewBinary(t, terraformBin, fixturePath)
162+
163+
//// INIT
164+
stdout, stderr, err := tf.Run("init")
165+
if err != nil {
166+
t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, stderr)
167+
}
168+
169+
// Make sure we actually downloaded the plugins, rather than picking up
170+
// copies that might be already installed globally on the system.
171+
if !strings.Contains(stdout, "Installing hashicorp/template v") {
172+
t.Errorf("template provider download message is missing from init output:\n%s", stdout)
173+
t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)")
174+
}
175+
if !strings.Contains(stdout, "Installing hashicorp/null v") {
176+
t.Errorf("null provider download message is missing from init output:\n%s", stdout)
177+
t.Logf("(this can happen if you have a copy of the plugin in one of the global plugin search dirs)")
178+
}
179+
180+
//// PLAN
181+
stdout, stderr, err = tf.Run("plan", "-out=tfplan")
182+
if err != nil {
183+
t.Fatalf("unexpected plan error: %s\nstderr:\n%s", err, stderr)
184+
}
185+
186+
if !strings.Contains(stdout, "1 to add, 0 to change, 0 to destroy") {
187+
t.Errorf("incorrect plan tally; want 1 to add:\n%s", stdout)
188+
}
189+
190+
if !strings.Contains(stdout, "Saved the plan to: tfplan") {
191+
t.Errorf("missing \"Saved the plan to...\" message in plan output\n%s", stdout)
192+
}
193+
if !strings.Contains(stdout, "terraform apply \"tfplan\"") {
194+
t.Errorf("missing next-step instruction in plan output\n%s", stdout)
195+
}
196+
197+
plan, err := tf.Plan("tfplan")
198+
if err != nil {
199+
t.Fatalf("failed to read plan file: %s", err)
200+
}
201+
202+
if plan.Backend.Workspace != "default" {
203+
t.Fatalf("expected plan to contain Workspace %q, got %q", "default", plan.Backend.Workspace)
204+
}
205+
206+
// Create and select a workspace that doesn't match the plan made above
207+
newWorkspace := "foobar"
208+
stdout, stderr, err = tf.Run("workspace", "new", newWorkspace, "-no-color")
209+
if err != nil {
210+
t.Fatalf("unexpected error: %s\nstderr:\n%s", err, stderr)
211+
}
212+
expectedMsg := fmt.Sprintf("Created and switched to workspace %q!", newWorkspace)
213+
if !strings.Contains(stdout, expectedMsg) {
214+
t.Errorf("unexpected output, expected %q, but got:\n%s", expectedMsg, stdout)
215+
}
216+
217+
//// APPLY
218+
stdout, stderr, err = tf.Run("apply", "tfplan")
219+
if err != nil {
220+
t.Fatalf("unexpected apply error: %s\nstderr:\n%s", err, stderr)
221+
}
222+
223+
if !strings.Contains(stdout, "Resources: 1 added, 0 changed, 0 destroyed") {
224+
t.Errorf("incorrect apply tally; want 1 added:\n%s", stdout)
225+
}
226+
227+
state, err := tf.LocalState()
228+
if err != nil {
229+
t.Fatalf("failed to read state file: %s", err)
230+
}
231+
232+
stateResources := state.RootModule().Resources
233+
var gotResources []string
234+
for n := range stateResources {
235+
gotResources = append(gotResources, n)
236+
}
237+
sort.Strings(gotResources)
238+
239+
wantResources := []string{
240+
"data.template_file.test",
241+
"null_resource.test",
242+
}
243+
244+
if !reflect.DeepEqual(gotResources, wantResources) {
245+
t.Errorf("wrong resources in state\ngot: %#v\nwant: %#v", gotResources, wantResources)
246+
}
247+
248+
//// DESTROY
249+
stdout, stderr, err = tf.Run("destroy", "-auto-approve")
250+
if err != nil {
251+
t.Fatalf("unexpected destroy error: %s\nstderr:\n%s", err, stderr)
252+
}
253+
254+
if !strings.Contains(stdout, "Resources: 1 destroyed") {
255+
t.Errorf("incorrect destroy tally; want 1 destroyed:\n%s", stdout)
256+
}
257+
258+
state, err = tf.LocalState()
259+
if err != nil {
260+
t.Fatalf("failed to read state file after destroy: %s", err)
261+
}
262+
263+
stateResources = state.RootModule().Resources
264+
if len(stateResources) != 0 {
265+
t.Errorf("wrong resources in state after destroy; want none, but still have:%s", spew.Sdump(stateResources))
266+
}
267+
268+
}
269+
152270
func TestPrimaryChdirOption(t *testing.T) {
153271
t.Parallel()
154272

0 commit comments

Comments
 (0)