Skip to content

Commit

Permalink
Fix empty labels perma-diff
Browse files Browse the repository at this point in the history
Relies on pulumi-terraform-bridge's iwahbe/add-sdkv2-edit-state
  • Loading branch information
iwahbe committed Sep 17, 2024
1 parent a1f7fa3 commit 094a682
Show file tree
Hide file tree
Showing 7 changed files with 290 additions and 8 deletions.
11 changes: 8 additions & 3 deletions provider/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ 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/hexops/autogold/v2 v2.2.1
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.20240917103737-6fe3b038b81f
github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917103737-6fe3b038b81f
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
Expand Down Expand Up @@ -129,7 +131,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
Expand Down Expand Up @@ -158,6 +159,8 @@ require (
github.com/hashicorp/terraform-svchost v0.1.1 // indirect
github.com/hashicorp/vault/api v1.12.0 // indirect
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/hexops/gotextdiff v1.0.3 // indirect
github.com/hexops/valast v1.4.4 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.15 // indirect
Expand Down Expand Up @@ -189,6 +192,7 @@ require (
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/natefinch/atomic v1.0.1 // indirect
github.com/nightlyone/lockfile v1.0.0 // indirect
github.com/nxadm/tail v1.4.11 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/opentracing/basictracer-go v1.1.0 // indirect
Expand Down Expand Up @@ -274,4 +278,5 @@ require (
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/frand v1.4.2 // indirect
mvdan.cc/gofumpt v0.5.0 // indirect
)
15 changes: 11 additions & 4 deletions provider/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1401,12 +1401,14 @@ github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
Expand Down Expand Up @@ -1733,6 +1735,7 @@ github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKe
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
github.com/hexops/autogold v0.8.1/go.mod h1:97HLDXyG23akzAoRYJh/2OBs3kd80eHyKPvZw0S5ZBY=
github.com/hexops/autogold v1.3.0 h1:IEtGNPxBeBu8RMn8eKWh/Ll9dVNgSnJ7bp/qHgMQ14o=
github.com/hexops/autogold v1.3.0/go.mod h1:d4hwi2rid66Sag+BVuHgwakW/EmaFr8vdTSbWDbrDRI=
github.com/hexops/autogold/v2 v2.2.1 h1:JPUXuZQGkcQMv7eeDXuNMovjfoRYaa0yVcm+F3voaGY=
Expand Down Expand Up @@ -1827,6 +1830,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
Expand Down Expand Up @@ -1976,10 +1980,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.20240917103737-6fe3b038b81f h1:wXE7eSLMUjoalLxh9YvsD1nVz98Eo9oArJm/HUTJG9o=
github.com/pulumi/pulumi-terraform-bridge/pf v0.43.1-0.20240917103737-6fe3b038b81f/go.mod h1:xdU2rcUBjPX/alXMiywUK1GvN4goUHZxos8ZfT6sVXM=
github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917103737-6fe3b038b81f h1:T3PP2u4tW7aVeVTq6ncXFaHxymxYsUN0yn1SdlUaZAc=
github.com/pulumi/pulumi-terraform-bridge/v3 v3.90.1-0.20240917103737-6fe3b038b81f/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=
Expand Down Expand Up @@ -2007,6 +2011,7 @@ github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYe
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
Expand Down Expand Up @@ -2658,6 +2663,7 @@ golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
Expand Down Expand Up @@ -3112,6 +3118,7 @@ modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ=
mvdan.cc/gofumpt v0.5.0 h1:0EQ+Z56k8tXjj/6TQD25BFNKQXpCvT0rnansIc7Ug5E=
mvdan.cc/gofumpt v0.5.0/go.mod h1:HBeVDtMKRZpXyxFciAirzdKklDlGu8aAy1wEbH5Y9js=
pgregory.net/rapid v0.6.1 h1:4eyrDxyht86tT4Ztm+kvlyNBLIk071gR+ZQdhphc9dQ=
Expand Down
139 changes: 139 additions & 0 deletions provider/provider_yaml_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"strings"
"testing"

"github.com/hexops/autogold/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand All @@ -36,6 +37,7 @@ import (
"github.com/pulumi/providertest/pulumitest/optnewstack"
"github.com/pulumi/providertest/pulumitest/opttest"
"github.com/pulumi/providertest/replay"
"github.com/pulumi/pulumi/sdk/v3/go/auto"
"github.com/pulumi/pulumi/sdk/v3/go/auto/optpreview"
"github.com/pulumi/pulumi/sdk/v3/go/common/apitype"
)
Expand Down Expand Up @@ -1120,3 +1122,140 @@ func TestFirestoreDatabaseAutoname(t *testing.T) {
pt.SetConfig("gcpProj", proj)
pt.Up()
}

func TestEmptyLabels(t *testing.T) {
tests := []struct {
program string
previewStdout autogold.Value
upOutputs autogold.Value
}{
{"empty-label", autogold.Expect(`Previewing update (test):
+ pulumi:pulumi:Stack empty-label-test create
@ previewing update....
+ gcp:kms:KeyRing ring create
+ gcp:kms:CryptoKey key create
+ pulumi:pulumi:Stack empty-label-test create
Outputs:
effectiveLabels: [secret]
labels : {
empty : ""
static: "value"
}
pulumiLabels : [secret]
Resources:
+ 3 to create
`), autogold.Expect(auto.OutputMap{
"effectiveLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty": "",
"goog-pulumi-provisioned": "true",
"static": "value",
},
Secret: true,
},
"labels": auto.OutputValue{Value: map[string]interface{}{
"empty": "",
"static": "value",
}},
"pulumiLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty": "",
"goog-pulumi-provisioned": "true",
"static": "value",
},
Secret: true,
},
})},
{"empty-alone-label", autogold.Expect(`Previewing update (test):
+ pulumi:pulumi:Stack empty-alone-label-test create
@ previewing update....
+ gcp:kms:KeyRing ring create
+ gcp:kms:CryptoKey key create
+ pulumi:pulumi:Stack empty-alone-label-test create
Outputs:
effectiveLabels: [secret]
labels : {
empty: ""
}
pulumiLabels : [secret]
Resources:
+ 3 to create
`), autogold.Expect(auto.OutputMap{
"effectiveLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty": "",
"goog-pulumi-provisioned": "true",
},
Secret: true,
},
"labels": auto.OutputValue{Value: map[string]interface{}{"empty": ""}},
"pulumiLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty": "",
"goog-pulumi-provisioned": "true",
},
Secret: true,
},
})},
{"empty-default-label", autogold.Expect(`Previewing update (test):
+ pulumi:pulumi:Stack empty-default-label-test create
@ previewing update....
+ gcp:kms:KeyRing ring create
+ gcp:kms:CryptoKey key create
+ pulumi:pulumi:Stack empty-default-label-test create
Outputs:
effectiveLabels: [secret]
labels : {
static: "value"
}
pulumiLabels : [secret]
Resources:
+ 3 to create
`), autogold.Expect(auto.OutputMap{
"effectiveLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty-default": "",
"goog-pulumi-provisioned": "true",
"static": "value",
},
Secret: true,
},
"labels": auto.OutputValue{Value: map[string]interface{}{"static": "value"}},
"pulumiLabels": auto.OutputValue{
Value: map[string]interface{}{
"empty-default": "",
"goog-pulumi-provisioned": "true",
"static": "value",
},
Secret: true,
},
})},
}

for _, tt := range tests {
tt := tt

t.Run(tt.program, func(t *testing.T) {
pt := pulumiTest(t, "test-programs/"+tt.program)
proj := getProject()
pt.SetConfig("gcpProj", proj)

previewResult := pt.Preview()
tt.previewStdout.Equal(t, previewResult.StdOut)

upResult := pt.Up()
tt.upOutputs.Equal(t, upResult.Outputs)

pt.Preview(optpreview.ExpectNoChanges())
})
}
}
72 changes: 71 additions & 1 deletion provider/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
"github.com/pulumi/pulumi/sdk/v3/go/common/tokens"
"github.com/pulumi/pulumi/sdk/v3/go/common/util/contract"
"github.com/pulumi/pulumi/sdk/v3/go/property"

"github.com/pulumi/pulumi-gcp/provider/v8/pkg/version"
)
Expand Down Expand Up @@ -454,14 +456,82 @@ 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) {
// actualLabels holds the labels that we expect to be applied. It is the union of
// labels (from the resource) and defaultLabels (from the provider)
actualLabels := property.Map{}

// Apply default labels first.
if pConfig := resource.FromResourcePropertyValue(resource.NewProperty(req.ProviderConfig)); pConfig.IsMap() {
l := pConfig.AsMap()["defaultLabels"]
if l.IsMap() {
actualLabels = l.AsMap()
}
}

// Apply labels next, allowing labels to override defaultLabels.
if inputs, ok := (resource.PropertyPath{"labels"}.Get(resource.NewProperty(req.NewInputs))); ok {
if labels := resource.FromResourcePropertyValue(inputs); labels.IsMap() {
for k, v := range labels.AsMap() {
actualLabels[k] = v
}
}
}

// fixOutputLabels fixes falsely unknown values label values.
fixOutputLabels := func(output cty.Value) cty.Value {
if !output.Type().IsMapType() || !output.IsKnown() {
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 := actualLabels[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
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())

Expand Down
19 changes: 19 additions & 0 deletions provider/test-programs/empty-alone-label/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: empty-alone-label
runtime: yaml
resources:
ring:
type: gcp:kms:KeyRing
properties:
location: us-central1
key:
type: gcp:kms:CryptoKey
properties:
keyRing: ${ring.id}
labels:
empty: ""
options:
retainOnDelete: true
outputs:
labels: ${key.labels}
effectiveLabels: ${key.effectiveLabels}
pulumiLabels: ${key.pulumiLabels}
Loading

0 comments on commit 094a682

Please sign in to comment.