From 1790f844b3f7982f7ba992c83c504bda7720923b Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 4 Jan 2023 15:12:58 -0500 Subject: [PATCH 1/2] output refs missing error_message Output references must also include the error_message expression. Fix the early return in referencesForOutput, which could skip preconditions. The small slice allocation optimization is not really needed here, since this is not a hot path at all. --- internal/terraform/node_output.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/internal/terraform/node_output.go b/internal/terraform/node_output.go index b7c45734ef44..2d5abead1748 100644 --- a/internal/terraform/node_output.go +++ b/internal/terraform/node_output.go @@ -278,19 +278,21 @@ func (n *NodeApplyableOutput) ReferenceableAddrs() []addrs.Referenceable { } func referencesForOutput(c *configs.Output) []*addrs.Reference { + var refs []*addrs.Reference + impRefs, _ := lang.ReferencesInExpr(c.Expr) expRefs, _ := lang.References(c.DependsOn) - l := len(impRefs) + len(expRefs) - if l == 0 { - return nil - } - refs := make([]*addrs.Reference, 0, l) + refs = append(refs, impRefs...) refs = append(refs, expRefs...) + for _, check := range c.Preconditions { - checkRefs, _ := lang.ReferencesInExpr(check.Condition) - refs = append(refs, checkRefs...) + condRefs, _ := lang.ReferencesInExpr(check.Condition) + refs = append(refs, condRefs...) + errRefs, _ := lang.ReferencesInExpr(check.ErrorMessage) + refs = append(refs, errRefs...) } + return refs } From 45cb0489d051c65bb4b6f5d664b3279e36d2a169 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 5 Jan 2023 10:01:25 -0500 Subject: [PATCH 2/2] test references only from output preconditions These references were getting dropped, which could cause the referenced nodes to be pruned from the graph. --- internal/terraform/context_apply2_test.go | 48 +++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/internal/terraform/context_apply2_test.go b/internal/terraform/context_apply2_test.go index 9000364ed39b..5875fbf6ce63 100644 --- a/internal/terraform/context_apply2_test.go +++ b/internal/terraform/context_apply2_test.go @@ -1784,3 +1784,51 @@ resource "test_object" "y" { _, diags = ctx.Apply(plan, m) assertNoErrors(t, diags) } + +// ensure all references from preconditions are tracked through plan and apply +func TestContext2Apply_preconditionErrorMessageRef(t *testing.T) { + p := testProvider("test") + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + m := testModuleInline(t, map[string]string{ + "main.tf": ` +module "nested" { + source = "./mod" +} + +output "nested_a" { + value = module.nested.a +} +`, + + "mod/main.tf": ` +variable "boop" { + default = "boop" +} + +variable "msg" { + default = "Incorrect boop." +} + +output "a" { + value = "x" + + precondition { + condition = var.boop == "boop" + error_message = var.msg + } +} +`, + }) + + plan, diags := ctx.Plan(m, states.NewState(), &PlanOpts{ + Mode: plans.NormalMode, + }) + assertNoErrors(t, diags) + _, diags = ctx.Apply(plan, m) + assertNoErrors(t, diags) +}