diff --git a/pkg/tfbridge/walk.go b/pkg/tfbridge/walk.go index d24cf755c..d041954a7 100644 --- a/pkg/tfbridge/walk.go +++ b/pkg/tfbridge/walk.go @@ -92,8 +92,10 @@ func propertyPathToSchemaPathInner( } // Detect single-nested blocks (object types). - if res, isRes := schema.Elem().(shim.Resource); schema.Type() == shim.TypeMap && isRes { - return propertyPathToSchemaPath(basePath, propertyPath, res.Schema(), schemaInfo.Fields) + // + // This is the case where (schema & schema.Elem) ~ {x: T}. + if res, isRes := util.CastToTypeObject(schema); isRes { + return propertyPathToSchemaPath(basePath, propertyPath, res, schemaInfo.Fields) } // Detect collections. @@ -108,8 +110,16 @@ func propertyPathToSchemaPathInner( elemPP = propertyPath[1:] } switch e := schema.Elem().(type) { + + // (schema, schemaInfo) represents a list or set nested object (schema ~ + // List[{x: T}] or schema ~ Set[{x: T}]), so we traverse the inner object + // with the associated .Elem.Fields. case shim.Resource: // object element type - return propertyPathToSchemaPath(basePath.Element(), elemPP, e.Schema(), schemaInfo.Fields) + elem := schemaInfo.Elem + if elem == nil { + elem = &SchemaInfo{} + } + return propertyPathToSchemaPath(basePath.Element(), elemPP, e.Schema(), elem.Fields) case shim.Schema: // non-object element type return propertyPathToSchemaPathInner(basePath.Element(), elemPP, e, schemaInfo.Elem) case nil: // unknown element type @@ -219,8 +229,16 @@ func schemaPathToPropertyPathInner( basePath = append(basePath, "*") } switch e := schema.Elem().(type) { + + // (schema, schemaInfo) represents a list or set nested object (schema ~ + // List[{x: T}] or schema ~ Set[{x: T}]), so we traverse the inner object + // with the associated .Elem.Fields. case shim.Resource: // object element type - return schemaPathToPropertyPath(basePath, schemaPath[1:], e.Schema(), schemaInfo.Fields) + elem := schemaInfo.Elem + if elem == nil { + elem = &SchemaInfo{} + } + return schemaPathToPropertyPath(basePath, schemaPath[1:], e.Schema(), elem.Fields) case shim.Schema: // non-object element type return schemaPathToPropertyPathInner(basePath, schemaPath[1:], e, schemaInfo.Elem) case nil: // unknown element type diff --git a/pkg/tfbridge/walk_test.go b/pkg/tfbridge/walk_test.go index 807eec799..93a15fb77 100644 --- a/pkg/tfbridge/walk_test.go +++ b/pkg/tfbridge/walk_test.go @@ -70,6 +70,10 @@ func TestPropertyPathToSchemaPath(t *testing.T) { Type: shim.TypeMap, Elem: xySchema, }).Shim(), + "list_obj": (&schema.Schema{ + Type: shim.TypeList, + Elem: xySchema, + }).Shim(), } schemaInfos := map[string]*SchemaInfo{ @@ -79,6 +83,14 @@ func TestPropertyPathToSchemaPath(t *testing.T) { "list_str_named": { Name: "listStr", }, + "list_obj": { + Name: "listObj", + Elem: &SchemaInfo{ + Fields: map[string]*SchemaInfo{ + "x_prop": {Name: "xOverride"}, + }, + }, + }, } type testCase struct { @@ -164,6 +176,11 @@ func TestPropertyPathToSchemaPath(t *testing.T) { pp: []any{"flatListViaSchemaInfo", "xProp"}, expected: walk.NewSchemaPath().GetAttr("flat_list_via_schema_info").Element().GetAttr("x_prop"), }, + { + name: "override list nested object property", + pp: resource.PropertyPath{"listObj", 0, "xOverride"}, + expected: walk.NewSchemaPath().GetAttr("list_obj").Element().GetAttr("x_prop"), + }, } for _, tc := range cases {