From dceb55c929f054cf151e93f6ad0953a5f0a03cb9 Mon Sep 17 00:00:00 2001 From: Ian Wahbe Date: Mon, 16 Sep 2024 17:02:35 +0200 Subject: [PATCH] Fix empty labels perma-diff Relies on pulumi-terraform-bridge's iwahbe/add-sdkv2-edit-state --- provider/go.mod | 6 ++--- provider/go.sum | 8 +++--- provider/resources.go | 61 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/provider/go.mod b/provider/go.mod index 15f0a37066..15257ae403 100644 --- a/provider/go.mod +++ b/provider/go.mod @@ -5,11 +5,12 @@ go 1.22 toolchain go1.22.7 require ( + github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.33.0 github.com/hashicorp/terraform-provider-google-beta v0.0.0 github.com/pulumi/providertest v0.0.14 - github.com/pulumi/pulumi-terraform-bridge/pf v0.43.0 - github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.0 + github.com/pulumi/pulumi-terraform-bridge/pf v0.43.1-0.20240917093314-ed4e944e34e2 + github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917093314-ed4e944e34e2 github.com/pulumi/pulumi/pkg/v3 v3.130.0 github.com/pulumi/pulumi/sdk/v3 v3.130.0 github.com/stretchr/testify v1.9.0 @@ -129,7 +130,6 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect github.com/hashicorp/go-getter v1.7.5 // indirect github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect diff --git a/provider/go.sum b/provider/go.sum index d846454485..aed8d9d94d 100644 --- a/provider/go.sum +++ b/provider/go.sum @@ -1976,10 +1976,10 @@ github.com/pulumi/providertest v0.0.14 h1:5QlAPAAs82jkQraHsJvq1xgVfC7xtW8sFJwv2p github.com/pulumi/providertest v0.0.14/go.mod h1:GcsqEGgSngwaNOD+kICJPIUQlnA911fGBU8HDlJvVL0= github.com/pulumi/pulumi-java/pkg v0.14.0 h1:CKL7lLF81Fq6VRhA5TNFsSMnHraTNCUzIhqCzYX8Wzk= github.com/pulumi/pulumi-java/pkg v0.14.0/go.mod h1:VybuJMWJtJc9ZNbt1kcYH4TbpocMx9mEi7YWL2Co99c= -github.com/pulumi/pulumi-terraform-bridge/pf v0.43.0 h1:g15WgVKJBhFtzhLqOky6R77QIU3x4KkunrLHDSkK6CM= -github.com/pulumi/pulumi-terraform-bridge/pf v0.43.0/go.mod h1:xdU2rcUBjPX/alXMiywUK1GvN4goUHZxos8ZfT6sVXM= -github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.0 h1:e7xfYAiXCE8LCwfKvbGeNAjdPmKwPM3kavEXECt3wvs= -github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.0/go.mod h1:dIVp4qG+GsUwmpz40L7Z+PZnzHf3cQq1CAFwhz++ris= +github.com/pulumi/pulumi-terraform-bridge/pf v0.43.1-0.20240917093314-ed4e944e34e2 h1:h4Ne9Bw4fuQOHsEoAotEneas//4tbug92Ubpnpcjpgo= +github.com/pulumi/pulumi-terraform-bridge/pf v0.43.1-0.20240917093314-ed4e944e34e2/go.mod h1:xdU2rcUBjPX/alXMiywUK1GvN4goUHZxos8ZfT6sVXM= +github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917093314-ed4e944e34e2 h1:PgG0nRr1ym74rZMyOiR7ULUoQbSqgv00h4qAKeK7HJM= +github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917093314-ed4e944e34e2/go.mod h1:dIVp4qG+GsUwmpz40L7Z+PZnzHf3cQq1CAFwhz++ris= github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.9-0.20240227144008-2da15b3d6f6e h1:yON1jwN6gg4cjnOQF607I3fTiFyIDr9WSsQNXHD6wbM= github.com/pulumi/pulumi-terraform-bridge/x/muxer v0.0.9-0.20240227144008-2da15b3d6f6e/go.mod h1:AvlZujvfRiEu+60frCGEhaLeGttjHwM/g+47+IdPZXw= github.com/pulumi/pulumi-yaml v1.9.2 h1:BCUuRPA1USmFXrExiHRU8yJ+OiphLYnroPxKRgGCJrs= diff --git a/provider/resources.go b/provider/resources.go index a988ec59ad..fb71e84425 100644 --- a/provider/resources.go +++ b/provider/resources.go @@ -14,6 +14,7 @@ import ( // Allow embedding metadata in the provider _ "embed" + "github.com/hashicorp/go-cty/cty" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" gcpPFProvider "github.com/hashicorp/terraform-provider-google-beta/google-beta/fwprovider" gcpProvider "github.com/hashicorp/terraform-provider-google-beta/google-beta/provider" @@ -454,6 +455,63 @@ func preConfigureCallbackWithLogger(credentialsValidationRun *atomic.Bool, gcpCl //go:embed cmd/pulumi-resource-gcp/bridge-metadata.json var metadata []byte +// A predicate function that always returns true. +func always[T any](T) bool { return true } + +// fixEmptyLabels applies a state edit to fix +// https://github.com/pulumi/pulumi-gcp/issues/2372. +func fixEmptyLabels(_ context.Context, req shimv2.PlanStateEditRequest) (cty.Value, error) { + inputs, ok := resource.PropertyPath{"labels"}.Get(resource.NewProperty(req.NewInputs)) + if !ok { + return req.PlanState, nil + } + + labels := resource.FromResourcePropertyValue(inputs) + if !labels.IsMap() { + // No labels found, so we don't need to correct + return req.PlanState, nil + } + + // fixOutputLabels fixes falsely computed values inherited from "labels". + fixOutputLabels := func(output cty.Value) cty.Value { + if !output.Type().IsMapType() { + return output + } + m := output.AsValueMap() + for k, v := range m { + if v.IsKnown() { + // If v is known, then it is not falsely computed. No + // action is needed. + continue + } + label, ok := labels.AsMap()[k] // labels is in the Pulumi namespace + if !ok || label.IsComputed() || !label.IsString() { + // If we didn't inherit label from "labels" or the label + // is actually computed, then just continue. + continue + } + + // Assign the correct label, discarding the erroneously computed + // value. + m[k] = cty.StringVal(label.AsString()) + } + return cty.MapVal(m) + } + + // Apply f to m[k] if k in m. + mapIfExists := func(m map[string]cty.Value, k string, f func(cty.Value) cty.Value) { + v, ok := m[k] + if ok { + m[k] = f(v) + } + } + + planState := req.PlanState.AsValueMap() + mapIfExists(planState, "effective_labels", fixOutputLabels) + mapIfExists(planState, "terraform_labels", fixOutputLabels) + return cty.ObjectVal(planState), nil +} + // Provider returns additional overlaid schema and metadata associated with the gcp package. // //nolint:lll @@ -461,7 +519,8 @@ func Provider() tfbridge.ProviderInfo { p := pf.MuxShimWithDisjointgPF( context.Background(), shimv2.NewProvider(gcpProvider.Provider(), - shimv2.WithPlanResourceChange(func(_ string) bool { return true }), + shimv2.WithPlanResourceChange(always), + shimv2.WithPlanStateEdit(fixEmptyLabels), ), gcpPFProvider.New())