Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changelog/44972.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
```release-note:bug
resource/aws_cloudfront_continuous_deployment_policy: Fix `Source type "...cloudfront.stagingDistributionDNSNamesModel" does not implement attr.Value` error. This fixes a regression introduced in [v6.17.0](https://github.com/hashicorp/terraform-provider-aws/blob/main/CHANGELOG.md#6170-october-16-2025)
5 changes: 3 additions & 2 deletions internal/framework/flex/autoflex.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,9 @@ func autoflexTags(field reflect.StructField) (string, tagOptions) {
}

type fieldOpts struct {
legacy bool
omitempty bool
legacy bool
omitempty bool
xmlWrapper bool
}

// valueWithElementsAs extends the Value interface for values that have an ElementsAs method.
Expand Down
55 changes: 32 additions & 23 deletions internal/framework/flex/autoflex_expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,19 +182,19 @@ func (expander autoExpander) convert(ctx context.Context, sourcePath path.Path,

// Aggregate types.
case basetypes.ObjectValuable:
diags.Append(expander.object(ctx, sourcePath, vFrom, targetPath, vTo)...)
diags.Append(expander.object(ctx, sourcePath, vFrom, targetPath, vTo, fieldOpts)...)
return diags

case basetypes.ListValuable:
diags.Append(expander.list(ctx, sourcePath, vFrom, targetPath, vTo)...)
diags.Append(expander.list(ctx, sourcePath, vFrom, targetPath, vTo, fieldOpts)...)
return diags

case basetypes.MapValuable:
diags.Append(expander.map_(ctx, vFrom, vTo)...)
diags.Append(expander.map_(ctx, vFrom, vTo, fieldOpts)...)
return diags

case basetypes.SetValuable:
diags.Append(expander.set(ctx, sourcePath, vFrom, targetPath, vTo)...)
diags.Append(expander.set(ctx, sourcePath, vFrom, targetPath, vTo, fieldOpts)...)
return diags
}

Expand Down Expand Up @@ -538,7 +538,7 @@ func (expander autoExpander) string(ctx context.Context, vFrom basetypes.StringV
}

// string copies a Plugin Framework Object(ish) value to a compatible AWS API value.
func (expander autoExpander) object(ctx context.Context, sourcePath path.Path, vFrom basetypes.ObjectValuable, targetPath path.Path, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) object(ctx context.Context, sourcePath path.Path, vFrom basetypes.ObjectValuable, targetPath path.Path, vTo reflect.Value, _ fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

_, d := vFrom.ToObjectValue(ctx)
Expand Down Expand Up @@ -588,7 +588,7 @@ func (expander autoExpander) object(ctx context.Context, sourcePath path.Path, v
}

// list copies a Plugin Framework List(ish) value to a compatible AWS API value.
func (expander autoExpander) list(ctx context.Context, sourcePath path.Path, vFrom basetypes.ListValuable, targetPath path.Path, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) list(ctx context.Context, sourcePath path.Path, vFrom basetypes.ListValuable, targetPath path.Path, vTo reflect.Value, fieldOpts fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

v, d := vFrom.ToListValue(ctx)
Expand All @@ -599,16 +599,16 @@ func (expander autoExpander) list(ctx context.Context, sourcePath path.Path, vFr

switch v.ElementType(ctx).(type) {
case basetypes.Int64Typable:
diags.Append(expander.listOrSetOfInt64(ctx, v, vTo)...)
diags.Append(expander.listOrSetOfInt64(ctx, v, vTo, fieldOpts)...)
return diags

case basetypes.StringTypable:
diags.Append(expander.listOrSetOfString(ctx, v, vTo)...)
diags.Append(expander.listOrSetOfString(ctx, v, vTo, fieldOpts)...)
return diags

case basetypes.ObjectTypable:
if vFrom, ok := vFrom.(fwtypes.NestedObjectCollectionValue); ok {
diags.Append(expander.nestedObjectCollection(ctx, sourcePath, vFrom, targetPath, vTo)...)
diags.Append(expander.nestedObjectCollection(ctx, sourcePath, vFrom, targetPath, vTo, fieldOpts)...)
return diags
}
}
Expand All @@ -622,13 +622,13 @@ func (expander autoExpander) list(ctx context.Context, sourcePath path.Path, vFr
}

// listOrSetOfInt64 copies a Plugin Framework ListOfInt64(ish) or SetOfInt64(ish) value to a compatible AWS API value.
func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value, fieldOpts fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

switch vTo.Kind() {
case reflect.Struct:
// Check if target is an XML wrapper struct
if isXMLWrapperStruct(vTo.Type()) {
if fieldOpts.xmlWrapper && isXMLWrapperStruct(vTo.Type()) {
diags.Append(expander.xmlWrapper(ctx, vFrom, vTo, "Items")...)
return diags
}
Expand Down Expand Up @@ -701,13 +701,13 @@ func (expander autoExpander) listOrSetOfInt64(ctx context.Context, vFrom valueWi
}

// listOrSetOfString copies a Plugin Framework ListOfString(ish) or SetOfString(ish) value to a compatible AWS API value.
func (expander autoExpander) listOrSetOfString(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) listOrSetOfString(ctx context.Context, vFrom valueWithElementsAs, vTo reflect.Value, fieldOpts fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

switch vTo.Kind() {
case reflect.Struct:
// Check if target is an XML wrapper struct
if isXMLWrapperStruct(vTo.Type()) {
if fieldOpts.xmlWrapper && isXMLWrapperStruct(vTo.Type()) {
diags.Append(expander.xmlWrapper(ctx, vFrom, vTo, "Items")...)
return diags
}
Expand Down Expand Up @@ -766,7 +766,7 @@ func (expander autoExpander) listOrSetOfString(ctx context.Context, vFrom valueW
}

// map_ copies a Plugin Framework Map(ish) value to a compatible AWS API value.
func (expander autoExpander) map_(ctx context.Context, vFrom basetypes.MapValuable, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) map_(ctx context.Context, vFrom basetypes.MapValuable, vTo reflect.Value, _ fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

v, d := vFrom.ToMapValue(ctx)
Expand Down Expand Up @@ -893,7 +893,7 @@ func (expander autoExpander) mapOfString(ctx context.Context, vFrom basetypes.Ma
}

// set copies a Plugin Framework Set(ish) value to a compatible AWS API value.
func (expander autoExpander) set(ctx context.Context, sourcePath path.Path, vFrom basetypes.SetValuable, targetPath path.Path, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) set(ctx context.Context, sourcePath path.Path, vFrom basetypes.SetValuable, targetPath path.Path, vTo reflect.Value, fieldOpts fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

v, d := vFrom.ToSetValue(ctx)
Expand All @@ -904,16 +904,16 @@ func (expander autoExpander) set(ctx context.Context, sourcePath path.Path, vFro

switch v.ElementType(ctx).(type) {
case basetypes.Int64Typable:
diags.Append(expander.listOrSetOfInt64(ctx, v, vTo)...)
diags.Append(expander.listOrSetOfInt64(ctx, v, vTo, fieldOpts)...)
return diags

case basetypes.StringTypable:
diags.Append(expander.listOrSetOfString(ctx, v, vTo)...)
diags.Append(expander.listOrSetOfString(ctx, v, vTo, fieldOpts)...)
return diags

case basetypes.ObjectTypable:
if vFrom, ok := vFrom.(fwtypes.NestedObjectCollectionValue); ok {
diags.Append(expander.nestedObjectCollection(ctx, sourcePath, vFrom, targetPath, vTo)...)
diags.Append(expander.nestedObjectCollection(ctx, sourcePath, vFrom, targetPath, vTo, fieldOpts)...)
return diags
}
}
Expand All @@ -927,13 +927,13 @@ func (expander autoExpander) set(ctx context.Context, sourcePath path.Path, vFro
}

// nestedObjectCollection copies a Plugin Framework NestedObjectCollectionValue value to a compatible AWS API value.
func (expander autoExpander) nestedObjectCollection(ctx context.Context, sourcePath path.Path, vFrom fwtypes.NestedObjectCollectionValue, targetPath path.Path, vTo reflect.Value) diag.Diagnostics {
func (expander autoExpander) nestedObjectCollection(ctx context.Context, sourcePath path.Path, vFrom fwtypes.NestedObjectCollectionValue, targetPath path.Path, vTo reflect.Value, fieldOpts fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

switch tTo := vTo.Type(); vTo.Kind() {
case reflect.Struct:
// Check if target is an XML wrapper struct before handling as generic struct
if isXMLWrapperStruct(tTo) {
if fieldOpts.xmlWrapper && isXMLWrapperStruct(tTo) {
diags.Append(expander.nestedObjectCollectionToXMLWrapper(ctx, sourcePath, vFrom, targetPath, vTo)...)
return diags
}
Expand All @@ -947,7 +947,7 @@ func (expander autoExpander) nestedObjectCollection(ctx context.Context, sourceP
switch tElem := tTo.Elem(); tElem.Kind() {
case reflect.Struct:
// Check if target is a pointer to XML wrapper struct
if isXMLWrapperStruct(tElem) {
if fieldOpts.xmlWrapper && isXMLWrapperStruct(tElem) {
// Create new instance of the XML wrapper struct
newWrapper := reflect.New(tElem)
diags.Append(expander.nestedObjectCollectionToXMLWrapper(ctx, sourcePath, vFrom, targetPath, newWrapper.Elem())...)
Expand Down Expand Up @@ -1221,7 +1221,8 @@ func expandStruct(ctx context.Context, sourcePath path.Path, from any, targetPat
})

opts := fieldOpts{
legacy: fromFieldOpts.Legacy(),
legacy: fromFieldOpts.Legacy(),
xmlWrapper: fromFieldOpts.XMLWrapperField() != "",
}

diags.Append(flexer.convert(ctx, sourcePath.AtName(fromFieldName), valFrom.FieldByIndex(fromField.Index), targetPath.AtName(toFieldName), toFieldVal, opts)...)
Expand Down Expand Up @@ -1587,7 +1588,15 @@ func isXMLWrapperStruct(t reflect.Type) bool {
return false
}

return true
// Items and Quantity should be the only non-anonymous fields
nNonAnonymousFields := 0
for i := 0; i < t.NumField(); i++ {
if !t.Field(i).Anonymous {
nNonAnonymousFields++
}
}

return nNonAnonymousFields == 2
}

// nestedObjectCollectionToXMLWrapper converts a NestedObjectCollectionValue to an XML wrapper struct
Expand Down
21 changes: 11 additions & 10 deletions internal/framework/flex/autoflex_flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,15 @@ func (flattener autoFlattener) convert(ctx context.Context, sourcePath path.Path
return diags

case reflect.Map:
diags.Append(flattener.map_(ctx, sourcePath, vFrom, targetPath, tTo, vTo)...)
diags.Append(flattener.map_(ctx, sourcePath, vFrom, targetPath, tTo, vTo, fieldOpts)...)
return diags

case reflect.Struct:
diags.Append(flattener.struct_(ctx, sourcePath, vFrom, false, targetPath, tTo, vTo, fieldOpts)...)
return diags

case reflect.Interface:
diags.Append(flattener.interface_(ctx, vFrom, tTo, vTo)...)
diags.Append(flattener.interface_(ctx, vFrom, tTo, vTo, fieldOpts)...)
return diags
}

Expand Down Expand Up @@ -612,7 +612,7 @@ func (flattener autoFlattener) pointer(ctx context.Context, sourcePath path.Path
return diags
}

func (flattener autoFlattener) interface_(ctx context.Context, vFrom reflect.Value, tTo attr.Type, vTo reflect.Value) diag.Diagnostics {
func (flattener autoFlattener) interface_(ctx context.Context, vFrom reflect.Value, tTo attr.Type, vTo reflect.Value, _ fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

switch tTo := tTo.(type) {
Expand Down Expand Up @@ -846,7 +846,7 @@ func (flattener autoFlattener) slice(ctx context.Context, sourcePath path.Path,
}

// map_ copies an AWS API map value to a compatible Plugin Framework value.
func (flattener autoFlattener) map_(ctx context.Context, sourcePath path.Path, vFrom reflect.Value, targetPath path.Path, tTo attr.Type, vTo reflect.Value) diag.Diagnostics {
func (flattener autoFlattener) map_(ctx context.Context, sourcePath path.Path, vFrom reflect.Value, targetPath path.Path, tTo attr.Type, vTo reflect.Value, _ fieldOpts) diag.Diagnostics {
var diags diag.Diagnostics

switch tMapKey := vFrom.Type().Key(); tMapKey.Kind() {
Expand Down Expand Up @@ -1731,7 +1731,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
for toField := range tfreflect.ExportedStructFields(typeTo) {
toFieldName := toField.Name
_, toOpts := autoflexTags(toField)
if wrapperField := toOpts.WrapperField(); wrapperField != "" {
if wrapperField := toOpts.XMLWrapperField(); wrapperField != "" {
toFieldVal := valTo.FieldByIndex(toField.Index)
if !toFieldVal.CanSet() {
continue
Expand Down Expand Up @@ -1776,7 +1776,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
continue
}
toFieldName := toField.Name
toNameOverride, toOpts := autoflexTags(toField)
toNameOverride, toFieldOpts := autoflexTags(toField)
toFieldVal := valTo.FieldByIndex(toField.Index)
if toNameOverride == "-" {
tflog.SubsystemTrace(ctx, subsystemName, "Skipping ignored target field", map[string]any{
Expand All @@ -1785,7 +1785,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
})
continue
}
if toOpts.NoFlatten() {
if toFieldOpts.NoFlatten() {
tflog.SubsystemTrace(ctx, subsystemName, "Skipping noflatten target field", map[string]any{
logAttrKeySourceFieldname: fromFieldName,
logAttrKeyTargetFieldname: toFieldName,
Expand All @@ -1807,7 +1807,7 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
})

// Check if target has wrapper tag and source is an XML wrapper struct
if wrapperField := toOpts.WrapperField(); wrapperField != "" {
if wrapperField := toFieldOpts.XMLWrapperField(); wrapperField != "" {
fromFieldVal := valFrom.FieldByIndex(fromField.Index)
if isXMLWrapperStruct(fromFieldVal.Type()) {
tflog.SubsystemTrace(ctx, subsystemName, "Converting XML wrapper struct to collection", map[string]any{
Expand Down Expand Up @@ -1836,8 +1836,9 @@ func flattenStruct(ctx context.Context, sourcePath path.Path, from any, targetPa
}

opts := fieldOpts{
legacy: toOpts.Legacy(),
omitempty: toOpts.OmitEmpty(),
legacy: toFieldOpts.Legacy(),
omitempty: toFieldOpts.OmitEmpty(),
xmlWrapper: toFieldOpts.XMLWrapperField() != "",
}

diags.Append(flexer.convert(ctx, sourcePath.AtName(fromFieldName), valFrom.FieldByIndex(fromField.Index), targetPath.AtName(toFieldName), toFieldVal, opts)...)
Expand Down
16 changes: 8 additions & 8 deletions internal/framework/flex/autoflex_maps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func TestExpandMapBlock(t *testing.T) {
},
"map block key list": {
Source: &tfMapBlockList{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElement](ctx, []tfMapBlockElement{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElement{
{
MapBlockKey: types.StringValue("x"),
Attr1: types.StringValue("a"),
Expand Down Expand Up @@ -242,7 +242,7 @@ func TestExpandMapBlock(t *testing.T) {
},
"map block key set": {
Source: &tfMapBlockSet{
MapBlock: fwtypes.NewSetNestedObjectValueOfValueSliceMust[tfMapBlockElement](ctx, []tfMapBlockElement{
MapBlock: fwtypes.NewSetNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElement{
{
MapBlockKey: types.StringValue("x"),
Attr1: types.StringValue("a"),
Expand Down Expand Up @@ -329,7 +329,7 @@ func TestExpandMapBlock(t *testing.T) {
},
"map block enum key": {
Source: &tfMapBlockListEnumKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElementEnumKey](ctx, []tfMapBlockElementEnumKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElementEnumKey{
{
MapBlockKey: fwtypes.StringEnumValue(testEnumList),
Attr1: types.StringValue("a"),
Expand Down Expand Up @@ -359,7 +359,7 @@ func TestExpandMapBlock(t *testing.T) {

"map block list no key": {
Source: &tfMapBlockListNoKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElementNoKey](ctx, []tfMapBlockElementNoKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElementNoKey{
{
Attr1: types.StringValue("a"),
Attr2: types.StringValue("b"),
Expand Down Expand Up @@ -491,7 +491,7 @@ func TestFlattenMapBlock(t *testing.T) {
},
Target: &tfMapBlockList{},
WantTarget: &tfMapBlockList{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElement](ctx, []tfMapBlockElement{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElement{
{
MapBlockKey: types.StringValue("x"),
Attr1: types.StringValue("a"),
Expand All @@ -511,7 +511,7 @@ func TestFlattenMapBlock(t *testing.T) {
},
Target: &tfMapBlockSet{},
WantTarget: &tfMapBlockSet{
MapBlock: fwtypes.NewSetNestedObjectValueOfValueSliceMust[tfMapBlockElement](ctx, []tfMapBlockElement{
MapBlock: fwtypes.NewSetNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElement{
{
MapBlockKey: types.StringValue("x"),
Attr1: types.StringValue("a"),
Expand Down Expand Up @@ -540,7 +540,7 @@ func TestFlattenMapBlock(t *testing.T) {
},
Target: &tfMapBlockList{},
WantTarget: &tfMapBlockList{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElement](ctx, []tfMapBlockElement{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElement{
{
MapBlockKey: types.StringValue("x"),
Attr1: types.StringValue("a"),
Expand Down Expand Up @@ -580,7 +580,7 @@ func TestFlattenMapBlock(t *testing.T) {
},
Target: &tfMapBlockListEnumKey{},
WantTarget: &tfMapBlockListEnumKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust[tfMapBlockElementEnumKey](ctx, []tfMapBlockElementEnumKey{
MapBlock: fwtypes.NewListNestedObjectValueOfValueSliceMust(ctx, []tfMapBlockElementEnumKey{
{
MapBlockKey: fwtypes.StringEnumValue(testEnumList),
Attr1: types.StringValue("a"),
Expand Down
Loading
Loading