From 0fb04a1ede89e5c324eabbc3ded4b62eba5654ef Mon Sep 17 00:00:00 2001 From: Anton Tayanovskyy Date: Wed, 24 Jul 2024 19:35:28 -0400 Subject: [PATCH] Explicitly patch ProposedNew With this change it is safe to rerun go generate to vendor objchange.ProposedNew algorithm and its modification is made explicit by writing out the intentional patch. Revisiting the patch is tracked in #2247 --- pkg/tfshim/sdk-v2/internal/tf/generate.go | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/pkg/tfshim/sdk-v2/internal/tf/generate.go b/pkg/tfshim/sdk-v2/internal/tf/generate.go index 028065b9f..e258ecfb4 100644 --- a/pkg/tfshim/sdk-v2/internal/tf/generate.go +++ b/pkg/tfshim/sdk-v2/internal/tf/generate.go @@ -25,6 +25,8 @@ import ( "os/exec" "path/filepath" "strings" + + "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" ) //go:generate go run generate.go @@ -97,7 +99,7 @@ func files() []file { { src: "internal/plans/objchange/objchange.go", dest: "plans/objchange/objchange.go", - transforms: transforms, + transforms: append(transforms, patchProposedNewForUnknownBlocks), }, { src: "internal/plans/objchange/plan_valid.go", @@ -178,3 +180,27 @@ func fixupCodeTypeError(code string) string { after := `panic(fmt.Sprintf("unsupported block nesting mode %v"` return strings.ReplaceAll(code, before, after) } + +// This patch introduces a change in behavior for the vendored objchange.ProposedNew algorithm. Before the change, +// planning a block change where config is entirely unknown used to pick the prior state. After the change it picks the +// unknown. This is especially interesting when planning set-nested blocks, as when the algorithm fails to find a +// matching set element in priorState it will send prior=null instead, and proceed to substitute null with an empty +// value matching the block structure. Without the patch, this empty value will be selected over the unknown and +// surfaced to Pulumi users, which is confusing. +// +// See TestUnknowns test suite and the "unknown for set block prop" test case. +// +// TODO[pulumi/pulumi-terraform-bridge#2247] revisit this patch. +func patchProposedNewForUnknownBlocks(goCode string) string { + oldCode := `func proposedNew(schema *configschema.Block, prior, config cty.Value) cty.Value { + if config.IsNull() || !config.IsKnown() {` + + newCode := `func proposedNew(schema *configschema.Block, prior, config cty.Value) cty.Value { + if !config.IsKnown() { + return config + } + if config.IsNull() {` + updatedGoCode := strings.Replace(goCode, oldCode, newCode, 1) + contract.Assertf(updatedGoCode != oldCode, "patchProposedNewForUnknownBlocks failed to apply") + return updatedGoCode +}