diff --git a/backend/local/backend_plan_test.go b/backend/local/backend_plan_test.go index 144260308..b0d6419fa 100644 --- a/backend/local/backend_plan_test.go +++ b/backend/local/backend_plan_test.go @@ -4,6 +4,7 @@ import ( "context" "os" "path/filepath" + "reflect" "strings" "testing" @@ -207,6 +208,73 @@ func TestLocal_planOutPathNoChange(t *testing.T) { } } +// TestLocal_planScaleOutNoDupeCount tests a Refresh/Plan sequence when a +// resource count is scaled out. The scaled out node needs to exist in the +// graph and run through a plan-style sequence during the refresh phase, but +// can conflate the count if its post-diff count hooks are not skipped. This +// checks to make sure the correct resource count is ultimately given to the +// UI. +func TestLocal_planScaleOutNoDupeCount(t *testing.T) { + b := TestLocal(t) + TestLocalProvider(t, b, "test") + state := &terraform.State{ + Version: 2, + Modules: []*terraform.ModuleState{ + &terraform.ModuleState{ + Path: []string{"root"}, + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo.0": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + }, + }, + "test_instance.foo.1": &terraform.ResourceState{ + Type: "test_instance", + Primary: &terraform.InstanceState{ + ID: "bar", + }, + }, + }, + }, + }, + } + terraform.TestStateFile(t, b.StatePath, state) + + actual := new(CountHook) + b.ContextOpts.Hooks = append(b.ContextOpts.Hooks, actual) + + mod, modCleanup := module.TestTree(t, "./test-fixtures/plan-scaleout") + defer modCleanup() + + outDir := testTempDir(t) + defer os.RemoveAll(outDir) + + op := testOperationPlan() + op.Module = mod + op.PlanRefresh = true + + run, err := b.Operation(context.Background(), op) + if err != nil { + t.Fatalf("bad: %s", err) + } + <-run.Done() + if run.Err != nil { + t.Fatalf("err: %s", err) + } + + expected := new(CountHook) + expected.ToAdd = 1 + expected.ToChange = 0 + expected.ToRemoveAndAdd = 0 + expected.ToRemove = 0 + + if !reflect.DeepEqual(expected, actual) { + t.Fatalf("Expected %#v, got %#v instead.", + expected, actual) + } +} + func testOperationPlan() *backend.Operation { return &backend.Operation{ Type: backend.OperationTypePlan, diff --git a/backend/local/test-fixtures/plan-scaleout/main.tf b/backend/local/test-fixtures/plan-scaleout/main.tf new file mode 100644 index 000000000..4067af592 --- /dev/null +++ b/backend/local/test-fixtures/plan-scaleout/main.tf @@ -0,0 +1,10 @@ +resource "test_instance" "foo" { + count = 3 + ami = "bar" + + # This is here because at some point it caused a test failure + network_interface { + device_index = 0 + description = "Main network interface" + } +}