diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index af22fc9b4..aed29cdc1 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -11122,3 +11122,63 @@ resource "aws_instance" "cbd" { t.Fatal("aws_instance.foo should also be create_before_destroy") } } + +func TestContext2Apply_moduleDependsOn(t *testing.T) { + m := testModule(t, "apply-module-depends-on") + + p := testProvider("test") + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("data"), + "foo": cty.NullVal(cty.String), + }), + } + p.DiffFn = testDiffFn + + // each instance being applied should happen in sequential order + applied := int64(0) + + p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { + state := req.PlannedState.AsValueMap() + num, _ := state["num"].AsBigFloat().Float64() + ord := int64(num) + if !atomic.CompareAndSwapInt64(&applied, ord-1, ord) { + actual := atomic.LoadInt64(&applied) + resp.Diagnostics = resp.Diagnostics.Append(fmt.Errorf("instance %d was applied after %d", ord, actual)) + } + + state["id"] = cty.StringVal(fmt.Sprintf("test_%d", ord)) + resp.NewState = cty.ObjectVal(state) + + return resp + } + + ctx := testContext2(t, &ContextOpts{ + Config: m, + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + _, diags := ctx.Plan() + if diags.HasErrors() { + t.Fatal(diags.ErrWithWarnings()) + } + + _, diags = ctx.Apply() + if diags.HasErrors() { + t.Fatal(diags.ErrWithWarnings()) + } + + // run the plan again to ensure that data sources are not going to be re-read + plan, diags := ctx.Plan() + if diags.HasErrors() { + t.Fatal(diags.ErrWithWarnings()) + } + + for _, res := range plan.Changes.Resources { + if res.Action != plans.NoOp { + t.Fatalf("expected NoOp, got %s for %s", res.Action, res.Addr) + } + } +} diff --git a/terraform/testdata/apply-module-depends-on/main.tf b/terraform/testdata/apply-module-depends-on/main.tf new file mode 100644 index 000000000..9f7102d53 --- /dev/null +++ b/terraform/testdata/apply-module-depends-on/main.tf @@ -0,0 +1,32 @@ +module "moda" { + source = "./moda" + depends_on = [test_instance.a, module.modb] +} + +resource "test_instance" "a" { + depends_on = [module.modb] + num = 4 + foo = test_instance.aa.id +} + +resource "test_instance" "aa" { + num = 3 + foo = module.modb.out +} + +module "modb" { + source = "./modb" + depends_on = [test_instance.b] +} + +resource "test_instance" "b" { + num = 1 +} + +output "moda_data" { + value = module.moda.out +} + +output "modb_resource" { + value = module.modb.out +} diff --git a/terraform/testdata/apply-module-depends-on/moda/main.tf b/terraform/testdata/apply-module-depends-on/moda/main.tf new file mode 100644 index 000000000..914e545c8 --- /dev/null +++ b/terraform/testdata/apply-module-depends-on/moda/main.tf @@ -0,0 +1,10 @@ +resource "test_instance" "a" { + num = 5 +} + +data "test_data_source" "a" { +} + +output "out" { + value = data.test_data_source.a.id +} diff --git a/terraform/testdata/apply-module-depends-on/modb/main.tf b/terraform/testdata/apply-module-depends-on/modb/main.tf new file mode 100644 index 000000000..17192b039 --- /dev/null +++ b/terraform/testdata/apply-module-depends-on/modb/main.tf @@ -0,0 +1,10 @@ +resource "test_instance" "b" { + num = 2 +} + +data "test_data_source" "b" { +} + +output "out" { + value = test_instance.b.id +}