diff --git a/pf/tests/provider_configure_test.go b/pf/tests/provider_configure_test.go index 036610680..3ad882417 100644 --- a/pf/tests/provider_configure_test.go +++ b/pf/tests/provider_configure_test.go @@ -167,3 +167,90 @@ func TestJSONNestedConfigure(t *testing.T) { } }`) } + +func TestJSONNestedConfigureWithSecrets(t *testing.T) { + server, err := newProviderServer(t, testprovider.SyntheticTestBridgeProvider()) + require.NoError(t, err) + replay.ReplaySequence(t, server, ` +[ + { + "method": "/pulumirpc.ResourceProvider/Configure", + "request": { + "args": { + "stringConfigProp": "{\"4dabf18193072939515e22adb298388d\":\"1b47061264138c4ac30d75fd1eb44270\",\"value\":\"secret-example\"}", + "mapNestedProp": "{\"k1\":{\"4dabf18193072939515e22adb298388d\":\"1b47061264138c4ac30d75fd1eb44270\",\"value\":1},\"k2\":2}", + "listNestedProps": "[{\"4dabf18193072939515e22adb298388d\":\"1b47061264138c4ac30d75fd1eb44270\",\"value\":true},false]" + } + }, + "response": { + "supportsPreview": true, + "acceptResources": true + } + }, + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:test-stack::basicprogram::testbridge:index/testres:TestConfigRes::r1", + "preview": false + }, + "response": { + "id": "id-1", + "properties": { + "configCopy": "secret-example", + "id": "id-1" + } + } + } +]`) +} + +func TestConfigureWithSecrets(t *testing.T) { + server, err := newProviderServer(t, testprovider.SyntheticTestBridgeProvider()) + require.NoError(t, err) + replay.ReplaySequence(t, server, ` +[ + { + "method": "/pulumirpc.ResourceProvider/Configure", + "request": { + "args": { + "stringConfigProp": { + "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", + "value": "secret-example" + }, + "mapNestedProp": { + "k1": { + "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", + "value": 1 + }, + "k2": 2 + }, + "listNestedProps": [ + { + "4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270", + "value": true + }, + false + ] + } + }, + "response": { + "supportsPreview": true, + "acceptResources": true + } + }, + { + "method": "/pulumirpc.ResourceProvider/Create", + "request": { + "urn": "urn:pulumi:test-stack::basicprogram::testbridge:index/testres:TestConfigRes::r1", + "preview": false + }, + "response": { + "id": "id-1", + "properties": { + "configCopy": "secret-example", + "id": "id-1" + } + } + } +]`) +} diff --git a/pkg/tfbridge/config_encoding.go b/pkg/tfbridge/config_encoding.go index ab6a14321..189500c0a 100644 --- a/pkg/tfbridge/config_encoding.go +++ b/pkg/tfbridge/config_encoding.go @@ -68,13 +68,11 @@ func (*ConfigEncoding) tryUnwrapSecret(encoded any) (any, bool) { } func (enc *ConfigEncoding) convertStringToPropertyValue(s string, typ shim.ValueType) (resource.PropertyValue, error) { - // If the schema expects a string, we can just return this as-is. - if typ == shim.TypeString { - return resource.NewStringProperty(s), nil - } - - // Otherwise, we will attempt to deserialize the input string as JSON and convert the result into a Pulumi + // We attempt to deserialize the input string as JSON and convert the result into a Pulumi // property. If the input string is empty, we will return an appropriate zero value. + // + // We need to do this for all incoming strings, even if the target type is also a string. This is how + // we account for secret or computed string values. if s == "" { return enc.zeroValue(typ), nil } @@ -102,10 +100,12 @@ func (enc *ConfigEncoding) convertStringToPropertyValue(s string, typ shim.Value func (*ConfigEncoding) zeroValue(typ shim.ValueType) resource.PropertyValue { switch typ { + case shim.TypeString: + return resource.NewProperty("") case shim.TypeBool: - return resource.NewPropertyValue(false) + return resource.NewProperty(false) case shim.TypeInt, shim.TypeFloat: - return resource.NewPropertyValue(0) + return resource.NewProperty[float64](0) case shim.TypeList, shim.TypeSet: return resource.NewPropertyValue([]interface{}{}) default: