Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove rawNames from makeObjectTerraformInputs #1851

Merged
merged 7 commits into from
Apr 13, 2024
2 changes: 1 addition & 1 deletion pkg/tfbridge/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ func (p *Provider) Check(ctx context.Context, req *pulumirpc.CheckRequest) (*pul

// After all is said and done, we need to go back and return only what got populated as a diff from the origin.
pinputs := MakeTerraformOutputs(
ctx, p.tf, inputs, res.TF.Schema(), res.Schema.Fields, assets, false, p.supportsSecrets,
ctx, p.tf, inputs, res.TF.Schema(), res.Schema.Fields, assets, p.supportsSecrets,
)

pinputsWithSecrets := MarkSchemaSecrets(ctx, res.TF.Schema(), res.Schema.Fields,
Expand Down
46 changes: 27 additions & 19 deletions pkg/tfbridge/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -1021,7 +1021,7 @@ func MakeTerraformResult(
outs = obj
}

outMap := MakeTerraformOutputs(ctx, p, outs, tfs, ps, assets, false, supportsSecrets)
outMap := MakeTerraformOutputs(ctx, p, outs, tfs, ps, assets, supportsSecrets)

// If there is any Terraform metadata associated with this state, record it.
if state != nil && len(state.Meta()) != 0 {
Expand All @@ -1042,18 +1042,17 @@ func MakeTerraformOutputs(
tfs shim.SchemaMap,
ps map[string]*SchemaInfo,
assets AssetTable,
rawNames,
supportsSecrets bool,
) resource.PropertyMap {
result := make(resource.PropertyMap)

for key, value := range outs {
// First do a lookup of the name/info.
name, tfi, psi := getInfoFromTerraformName(key, tfs, ps, rawNames)
name, tfi, psi := getInfoFromTerraformName(key, tfs, ps, false)
contract.Assertf(name != "", `name != ""`)

// Next perform a translation of the value accordingly.
out := MakeTerraformOutput(ctx, p, value, tfi, psi, assets, rawNames, supportsSecrets)
out := MakeTerraformOutput(ctx, p, value, tfi, psi, assets, supportsSecrets)
//if !out.IsNull() {
result[name] = out
//}
Expand All @@ -1076,11 +1075,11 @@ func MakeTerraformOutput(
tfs shim.Schema,
ps *SchemaInfo,
assets AssetTable,
rawNames, supportsSecrets bool,
supportsSecrets bool,
) resource.PropertyValue {

buildOutput := func(p shim.Provider, v interface{},
tfs shim.Schema, ps *SchemaInfo, assets AssetTable, rawNames, supportsSecrets bool) resource.PropertyValue {
tfs shim.Schema, ps *SchemaInfo, assets AssetTable, supportsSecrets bool) resource.PropertyValue {
if assets != nil && ps != nil && ps.Asset != nil {
if asset, has := assets[ps]; has {
// if we have the value, it better actually be an asset or an archive.
Expand Down Expand Up @@ -1137,7 +1136,7 @@ func MakeTerraformOutput(
if err != nil || coerced == t {
return resource.NewStringProperty(t)
}
return MakeTerraformOutput(ctx, p, coerced, tfs, ps, assets, rawNames, supportsSecrets)
return MakeTerraformOutput(ctx, p, coerced, tfs, ps, assets, supportsSecrets)
case reflect.Slice:
elems := []interface{}{}
for i := 0; i < val.Len(); i++ {
Expand All @@ -1148,7 +1147,7 @@ func MakeTerraformOutput(

var arr []resource.PropertyValue
for _, elem := range elems {
arr = append(arr, MakeTerraformOutput(ctx, p, elem, tfes, pes, assets, rawNames, supportsSecrets))
arr = append(arr, MakeTerraformOutput(ctx, p, elem, tfes, pes, assets, supportsSecrets))
}
// For TypeList or TypeSet with MaxItems==1, we will have projected as a scalar nested value, so need to extract
// out the single element (or null).
Expand All @@ -1164,32 +1163,41 @@ func MakeTerraformOutput(
}
return resource.NewArrayProperty(arr)
case reflect.Map:
outs := map[string]interface{}{}
// Build a go map of output values.
outs := map[string]any{}
for _, key := range val.MapKeys() {
contract.Assertf(key.Kind() == reflect.String, "key.Kind() == reflect.String")
outs[key.String()] = val.MapIndex(key).Interface()
}
var tfflds shim.SchemaMap

if tfs != nil {
if res, isres := tfs.Elem().(shim.Resource); isres {
tfflds = res.Schema()
// This is an object, so we need key translations.
if res, ok := tfs.Elem().(shim.Resource); ok {
var psflds map[string]*SchemaInfo
if ps != nil {
psflds = ps.Fields
}
obj := MakeTerraformOutputs(ctx, p, outs,
res.Schema(), psflds, assets, supportsSecrets)
return resource.NewObjectProperty(obj)
}
}
var psflds map[string]*SchemaInfo
if ps != nil {
psflds = ps.Fields

// It's not an object, so it must be a map
obj := make(resource.PropertyMap, len(outs))
etfs, eps := elemSchemas(tfs, ps)
for k, v := range outs {
obj[resource.PropertyKey(k)] = MakeTerraformOutput(ctx, p, v,
etfs, eps, assets, supportsSecrets)
}
obj := MakeTerraformOutputs(
ctx, p, outs, tfflds, psflds, assets, rawNames || shimutil.IsOfTypeMap(tfs), supportsSecrets,
)
return resource.NewObjectProperty(obj)
default:
contract.Failf("Unexpected TF output property value: %#v with type %#T", v, v)
return resource.NewNullProperty()
}
}

output := buildOutput(p, v, tfs, ps, assets, rawNames, supportsSecrets)
output := buildOutput(p, v, tfs, ps, assets, supportsSecrets)

if tfs != nil && tfs.Sensitive() && supportsSecrets {
return resource.MakeSecret(output)
Expand Down
50 changes: 33 additions & 17 deletions pkg/tfbridge/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,10 +396,31 @@ func TestTerraformOutputsWithSecretsSupported(t *testing.T) {
},
{
name: "object_property_value",

// NOTE: This input does not match the schema's type. The tfValue *should* be wrapped
// in a []any{}. [MakeTerraformOutputs] handles this case, but it shouldn't need to
// and tf should never return it.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it handles it because it's trying to do MaxItems=1 mismatch toleration or something. Hard to know.

tfValue: map[string]interface{}{
"property_a": "a",
"property_b": true,
},
tfType: &schema.Schema{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, strange test case it didn't have tfType before so it was trying to parse untyped?

Type: shim.TypeList,
Required: true,
MaxItems: 1,
Elem: (&schema.Resource{
Schema: schema.SchemaMap{
"property_a": (&schema.Schema{
Type: shim.TypeString,
Optional: true,
}).Shim(),
"property_b": (&schema.Schema{
Type: shim.TypeBool,
Optional: true,
}).Shim(),
},
}).Shim(),
},
expect: autogold.Expect(resource.PropertyMap{resource.PropertyKey("objectPropertyValue"): resource.PropertyValue{
V: resource.PropertyMap{
resource.PropertyKey("propertyA"): resource.PropertyValue{
Expand Down Expand Up @@ -607,9 +628,8 @@ func TestTerraformOutputsWithSecretsSupported(t *testing.T) {
},
schemaMap,
schemaInfo,
nil, /* assets */
false, /* useRawNames */
true, /* supportsSecrets */
nil, /* assets */
true, /* supportsSecrets */
)
tt.expect.Equal(t, result)
})
Expand Down Expand Up @@ -638,8 +658,7 @@ func TestTerraformOutputsWithSecretsUnsupported(t *testing.T) {
},
}),
map[string]*SchemaInfo{},
nil, /* assets */
false, /*useRawNames*/
nil, /* assets */
false,
)
assert.Equal(t, resource.NewPropertyMapFromMap(map[string]interface{}{
Expand Down Expand Up @@ -1026,7 +1045,7 @@ func TestDefaults(t *testing.T) {
}
inputs, assets, err := makeTerraformInputsForConfig(olds, props, tfs, ps)
assert.NoError(t, err)
outputs := MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, false, true)
outputs := MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, true)

// sort the defaults list before the equality test below.
sortDefaultsList(outputs)
Expand Down Expand Up @@ -1072,7 +1091,7 @@ func TestDefaults(t *testing.T) {
assert.Equal(t, "true", inputs["x2stringxbool"])
assert.Equal(t, "1", inputs["x2stringxint"])

outputs = MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, false, true)
outputs = MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, true)

// sort the defaults list before the equality test below.
sortDefaultsList(outputs)
Expand Down Expand Up @@ -1141,7 +1160,7 @@ func TestDefaultsConflictsWith(t *testing.T) {

inputs, assets, err := makeTerraformInputsForConfig(olds, props, tfs, ps)
assert.NoError(t, err)
outputs := MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, false, true)
outputs := MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, true)
sortDefaultsList(outputs)

assert.Equal(t, resource.NewPropertyMapFromMap(map[string]interface{}{
Expand All @@ -1161,7 +1180,7 @@ func TestDefaultsConflictsWith(t *testing.T) {
inputs, assets, err = makeTerraformInputsForConfig(olds, props, tfs, ps)
assert.NoError(t, err)

outputs = MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, false, true)
outputs = MakeTerraformOutputs(ctx, f.NewTestProvider(), inputs, tfs, ps, assets, true)
sortDefaultsList(outputs)

assert.Equal(t, resource.NewPropertyMapFromMap(map[string]interface{}{
Expand Down Expand Up @@ -1195,7 +1214,7 @@ func TestComputedAsset(t *testing.T) {
}
inputs, assets, err := makeTerraformInputsNoDefaults(olds, props, tfs, ps)
assert.NoError(t, err)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, false, true)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, true)
assert.Equal(t, resource.PropertyMap{
"zzz": resource.PropertyValue{V: resource.Computed{Element: resource.PropertyValue{V: ""}}},
}, outputs)
Expand All @@ -1215,7 +1234,7 @@ func TestInvalidAsset(t *testing.T) {
}
inputs, assets, err := makeTerraformInputsNoDefaults(olds, props, tfs, ps)
assert.NoError(t, err)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, false, true)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, true)
assert.Equal(t, resource.PropertyMap{
"zzz": resource.NewStringProperty("invalid"),
}, outputs)
Expand Down Expand Up @@ -1280,8 +1299,7 @@ func TestOverridingTFSchema(t *testing.T) {
tfInputs,
tfSchema,
typeOverrides,
nil, /* assets */
false, /*useRawNames*/
nil, /* assets */
true,
)
assert.Equal(t, tfOutputs, result)
Expand Down Expand Up @@ -1332,7 +1350,7 @@ func TestArchiveAsAsset(t *testing.T) {
}
inputs, assets, err := makeTerraformInputsNoDefaults(olds, props, tfs, ps)
assert.NoError(t, err)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, false, true)
outputs := MakeTerraformOutputs(ctx, shimv1.NewProvider(testTFProvider), inputs, tfs, ps, assets, true)
assert.True(t, arch.DeepEquals(outputs["zzz"]))
}

Expand Down Expand Up @@ -1701,8 +1719,7 @@ func TestStringOutputsWithSchema(t *testing.T) {
"not_a_float_value": {Type: schemav1.TypeFloat},
}),
map[string]*SchemaInfo{},
nil, /* assets */
false, /* useRawNames */
nil, /* assets */
true,
)

Expand Down Expand Up @@ -2760,7 +2777,6 @@ func TestOutputNumberTypes(t *testing.T) {
tfs,
map[string]*SchemaInfo{},
AssetTable{},
false,
true,
)
assert.Equal(t, resource.PropertyMap{
Expand Down