Skip to content

Commit cba256a

Browse files
authored
Merge pull request #37977 from hashicorp/b-d/aws_ami.amiProductCodesHash-crash
d/aws_ami: Fix `interface conversion: interface {} is types.ProductCodeValues, not string` panic
2 parents ea4ad9b + 2c4bb43 commit cba256a

File tree

3 files changed

+70
-70
lines changed

3 files changed

+70
-70
lines changed

.changelog/#####.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:bug
2+
data-source/aws_ami: Fix `interface conversion: interface {} is types.ProductCodeValues, not string` panic
3+
```

internal/service/ec2/ec2_ami_data_source.go

Lines changed: 35 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
package ec2
55

66
import (
7-
"bytes"
87
"context"
98
"fmt"
10-
"log"
119
"sort"
1210
"time"
1311

@@ -20,7 +18,6 @@ import (
2018
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
2119
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
2220
"github.com/hashicorp/terraform-provider-aws/internal/conns"
23-
"github.com/hashicorp/terraform-provider-aws/internal/create"
2421
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
2522
"github.com/hashicorp/terraform-provider-aws/internal/flex"
2623
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
@@ -50,7 +47,6 @@ func dataSourceAMI() *schema.Resource {
5047
"block_device_mappings": {
5148
Type: schema.TypeSet,
5249
Computed: true,
53-
Set: amiBlockDeviceMappingHash,
5450
Elem: &schema.Resource{
5551
Schema: map[string]*schema.Schema{
5652
names.AttrDeviceName: {
@@ -170,7 +166,6 @@ func dataSourceAMI() *schema.Resource {
170166
"product_codes": {
171167
Type: schema.TypeSet,
172168
Computed: true,
173-
Set: amiProductCodesHash,
174169
Elem: &schema.Resource{
175170
Schema: map[string]*schema.Schema{
176171
"product_code_id": {
@@ -349,48 +344,54 @@ func dataSourceAMIRead(ctx context.Context, d *schema.ResourceData, meta interfa
349344
return diags
350345
}
351346

352-
func flattenAMIBlockDeviceMappings(m []awstypes.BlockDeviceMapping) *schema.Set {
353-
s := &schema.Set{
354-
F: amiBlockDeviceMappingHash,
347+
func flattenAMIBlockDeviceMappings(apiObjects []awstypes.BlockDeviceMapping) []interface{} {
348+
if len(apiObjects) == 0 {
349+
return nil
355350
}
356-
for _, v := range m {
357-
mapping := map[string]interface{}{
358-
names.AttrDeviceName: aws.ToString(v.DeviceName),
359-
names.AttrVirtualName: aws.ToString(v.VirtualName),
351+
352+
var tfList []interface{}
353+
354+
for _, apiObject := range apiObjects {
355+
tfMap := map[string]interface{}{
356+
names.AttrDeviceName: aws.ToString(apiObject.DeviceName),
357+
names.AttrVirtualName: aws.ToString(apiObject.VirtualName),
360358
}
361359

362-
if v.Ebs != nil {
360+
if apiObject := apiObject.Ebs; apiObject != nil {
363361
ebs := map[string]interface{}{
364-
names.AttrDeleteOnTermination: fmt.Sprintf("%t", aws.ToBool(v.Ebs.DeleteOnTermination)),
365-
names.AttrEncrypted: fmt.Sprintf("%t", aws.ToBool(v.Ebs.Encrypted)),
366-
names.AttrIOPS: fmt.Sprintf("%d", aws.ToInt32(v.Ebs.Iops)),
367-
names.AttrThroughput: fmt.Sprintf("%d", aws.ToInt32(v.Ebs.Throughput)),
368-
names.AttrVolumeSize: fmt.Sprintf("%d", aws.ToInt32(v.Ebs.VolumeSize)),
369-
names.AttrSnapshotID: aws.ToString(v.Ebs.SnapshotId),
370-
names.AttrVolumeType: v.Ebs.VolumeType,
362+
names.AttrDeleteOnTermination: flex.BoolToStringValue(apiObject.DeleteOnTermination),
363+
names.AttrEncrypted: flex.BoolToStringValue(apiObject.Encrypted),
364+
names.AttrIOPS: flex.Int32ToStringValue(apiObject.Iops),
365+
names.AttrSnapshotID: aws.ToString(apiObject.SnapshotId),
366+
names.AttrThroughput: flex.Int32ToStringValue(apiObject.Throughput),
367+
names.AttrVolumeSize: flex.Int32ToStringValue(apiObject.VolumeSize),
368+
names.AttrVolumeType: apiObject.VolumeType,
371369
}
372370

373-
mapping["ebs"] = ebs
371+
tfMap["ebs"] = ebs
374372
}
375373

376-
log.Printf("[DEBUG] aws_ami - adding block device mapping: %v", mapping)
377-
s.Add(mapping)
374+
tfList = append(tfList, tfMap)
378375
}
379-
return s
376+
377+
return tfList
380378
}
381379

382-
func flattenAMIProductCodes(m []awstypes.ProductCode) *schema.Set {
383-
s := &schema.Set{
384-
F: amiProductCodesHash,
380+
func flattenAMIProductCodes(apiObjects []awstypes.ProductCode) []interface{} {
381+
if len(apiObjects) == 0 {
382+
return nil
385383
}
386-
for _, v := range m {
387-
code := map[string]interface{}{
388-
"product_code_id": aws.ToString(v.ProductCodeId),
389-
"product_code_type": v.ProductCodeType,
390-
}
391-
s.Add(code)
384+
385+
var tfList []interface{}
386+
387+
for _, apiObject := range apiObjects {
388+
tfList = append(tfList, map[string]interface{}{
389+
"product_code_id": aws.ToString(apiObject.ProductCodeId),
390+
"product_code_type": apiObject.ProductCodeType,
391+
})
392392
}
393-
return s
393+
394+
return tfList
394395
}
395396

396397
func amiRootSnapshotId(image awstypes.Image) string {
@@ -420,39 +421,3 @@ func flattenAMIStateReason(m *awstypes.StateReason) map[string]interface{} {
420421
}
421422
return s
422423
}
423-
424-
func amiBlockDeviceMappingHash(v interface{}) int {
425-
var buf bytes.Buffer
426-
// All keys added in alphabetical order.
427-
m := v.(map[string]interface{})
428-
buf.WriteString(fmt.Sprintf("%s-", m[names.AttrDeviceName].(string)))
429-
if d, ok := m["ebs"]; ok {
430-
if len(d.(map[string]interface{})) > 0 {
431-
e := d.(map[string]interface{})
432-
buf.WriteString(fmt.Sprintf("%s-", e[names.AttrDeleteOnTermination].(string)))
433-
buf.WriteString(fmt.Sprintf("%s-", e[names.AttrEncrypted].(string)))
434-
buf.WriteString(fmt.Sprintf("%s-", e[names.AttrIOPS].(string)))
435-
buf.WriteString(fmt.Sprintf("%s-", e[names.AttrVolumeSize].(string)))
436-
buf.WriteString(fmt.Sprintf("%s-", e[names.AttrVolumeType]))
437-
}
438-
}
439-
if d, ok := m["no_device"]; ok {
440-
buf.WriteString(fmt.Sprintf("%s-", d.(string)))
441-
}
442-
if d, ok := m[names.AttrVirtualName]; ok {
443-
buf.WriteString(fmt.Sprintf("%s-", d.(string)))
444-
}
445-
if d, ok := m[names.AttrSnapshotID]; ok {
446-
buf.WriteString(fmt.Sprintf("%s-", d.(string)))
447-
}
448-
return create.StringHashcode(buf.String())
449-
}
450-
451-
func amiProductCodesHash(v interface{}) int {
452-
var buf bytes.Buffer
453-
m := v.(map[string]interface{})
454-
// All keys added in alphabetical order.
455-
buf.WriteString(fmt.Sprintf("%s-", m["product_code_id"].(string)))
456-
buf.WriteString(fmt.Sprintf("%s-", m["product_code_type"].(string)))
457-
return create.StringHashcode(buf.String())
458-
}

internal/service/ec2/ec2_ami_data_source_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,25 @@ func TestAccEC2AMIDataSource_gp3BlockDevice(t *testing.T) {
208208
})
209209
}
210210

211+
func TestAccEC2AMIDataSource_productCode(t *testing.T) {
212+
ctx := acctest.Context(t)
213+
datasourceName := "data.aws_ami.test"
214+
215+
resource.ParallelTest(t, resource.TestCase{
216+
PreCheck: func() { acctest.PreCheck(ctx, t) },
217+
ErrorCheck: acctest.ErrorCheck(t, names.EC2ServiceID),
218+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
219+
Steps: []resource.TestStep{
220+
{
221+
Config: testAccAMIDataSourceConfig_productCode,
222+
Check: resource.ComposeTestCheckFunc(
223+
resource.TestCheckResourceAttr(datasourceName, "product_codes.#", acctest.Ct1),
224+
),
225+
},
226+
},
227+
})
228+
}
229+
211230
// testAccAMIDataSourceConfig_latestUbuntuBionicHVMInstanceStore returns the configuration for a data source that
212231
// describes the latest Ubuntu 18.04 AMI using HVM virtualization and an instance store root device.
213232
// The data source is named 'ubuntu-bionic-ami-hvm-instance-store'.
@@ -322,3 +341,16 @@ data "aws_ami" "test" {
322341
}
323342
`)
324343
}
344+
345+
// Image with product code.
346+
const testAccAMIDataSourceConfig_productCode = `
347+
data "aws_ami" "test" {
348+
most_recent = true
349+
owners = ["679593333241"]
350+
351+
filter {
352+
name = "name"
353+
values = ["AwsMarketPublished_IBM App Connect v12.0.12.0 and IBM MQ v9.3.0.16 with RapidDeploy 5.1.12 -422d2ddd-3288-4067-be37-4e2a69450606"]
354+
}
355+
}
356+
`

0 commit comments

Comments
 (0)