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

[Enhancement]: Add vpc_id output of aws_elasticache_subnet_group data source #35887

Merged
merged 4 commits into from
Feb 20, 2024
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
7 changes: 7 additions & 0 deletions .changelog/35887.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
data-source/aws_elasticache_subnet_group: Add `vpc_id` attribute
```

```release-note:enhancement
resource/aws_elasticache_subnet_group: Add `vpc_id` attribute
```
3 changes: 3 additions & 0 deletions internal/service/elasticache/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,7 @@ package elasticache
// Exports for use in tests only.
var (
ResourceServerlessCache = newResourceServerlessCache
ResourceSubnetGroup = resourceSubnetGroup

FindCacheSubnetGroupByName = findCacheSubnetGroupByName
)
29 changes: 0 additions & 29 deletions internal/service/elasticache/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,32 +301,3 @@ func FilterRedisParameterGroupNameClusterEnabledDefault(group *elasticache.Cache
}
return false
}

func FindCacheSubnetGroupByName(ctx context.Context, conn *elasticache.ElastiCache, name string) (*elasticache.CacheSubnetGroup, error) {
input := elasticache.DescribeCacheSubnetGroupsInput{
CacheSubnetGroupName: aws.String(name),
}

output, err := conn.DescribeCacheSubnetGroupsWithContext(ctx, &input)

if tfawserr.ErrCodeEquals(err, elasticache.ErrCodeCacheSubnetGroupNotFoundFault) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

if output == nil || len(output.CacheSubnetGroups) == 0 || output.CacheSubnetGroups[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if count := len(output.CacheSubnetGroups); count > 1 {
return nil, tfresource.NewTooManyResultsError(count, input)
}

return output.CacheSubnetGroups[0], nil
}
5 changes: 3 additions & 2 deletions internal/service/elasticache/service_package_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

103 changes: 80 additions & 23 deletions internal/service/elasticache/subnet_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ import (
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
Expand All @@ -26,7 +29,7 @@ import (

// @SDKResource("aws_elasticache_subnet_group", name="Subnet Group")
// @Tags(identifierAttribute="arn")
func ResourceSubnetGroup() *schema.Resource {
func resourceSubnetGroup() *schema.Resource {
return &schema.Resource{
CreateWithoutTimeout: resourceSubnetGroupCreate,
ReadWithoutTimeout: resourceSubnetGroupRead,
Expand Down Expand Up @@ -65,22 +68,17 @@ func ResourceSubnetGroup() *schema.Resource {
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
},

CustomizeDiff: resourceSubnetGroupDiff,
}
}

func resourceSubnetGroupDiff(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
// Reserved ElastiCache Subnet Groups with the name "default" do not support tagging;
// thus we must suppress the diff originating from the provider-level default_tags configuration
// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/19213
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
if len(defaultTagsConfig.GetTags()) > 0 && diff.Get("name").(string) == "default" {
return nil
CustomizeDiff: customdiff.All(
resourceSubnetGroupCustomizeDiff,
verify.SetTagsDiff,
),
}

return verify.SetTagsDiff(ctx, diff, meta)
}

func resourceSubnetGroupCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
Expand Down Expand Up @@ -108,7 +106,7 @@ func resourceSubnetGroupCreate(ctx context.Context, d *schema.ResourceData, meta
return sdkdiag.AppendErrorf(diags, "creating ElastiCache Subnet Group (%s): %s", name, err)
}

// Assign the group name as the resource ID
// Assign the group name as the resource ID.
// ElastiCache always retains the name in lower case, so we have to
// mimic that or else we won't be able to refresh a resource whose
// name contained uppercase characters.
Expand All @@ -135,7 +133,7 @@ func resourceSubnetGroupRead(ctx context.Context, d *schema.ResourceData, meta i
var diags diag.Diagnostics
conn := meta.(*conns.AWSClient).ElastiCacheConn(ctx)

group, err := FindCacheSubnetGroupByName(ctx, conn, d.Id())
group, err := findCacheSubnetGroupByName(ctx, conn, d.Id())

if !d.IsNewResource() && tfresource.NotFound(err) {
log.Printf("[WARN] ElastiCache Subnet Group (%s) not found, removing from state", d.Id())
Expand All @@ -147,15 +145,13 @@ func resourceSubnetGroupRead(ctx context.Context, d *schema.ResourceData, meta i
return sdkdiag.AppendErrorf(diags, "reading ElastiCache Subnet Group (%s): %s", d.Id(), err)
}

var subnetIDs []*string
for _, subnet := range group.Subnets {
subnetIDs = append(subnetIDs, subnet.SubnetIdentifier)
}

d.Set("arn", group.ARN)
d.Set("name", group.CacheSubnetGroupName)
d.Set("description", group.CacheSubnetGroupDescription)
d.Set("subnet_ids", aws.StringValueSlice(subnetIDs))
d.Set("name", group.CacheSubnetGroupName)
d.Set("subnet_ids", tfslices.ApplyToAll(group.Subnets, func(v *elasticache.Subnet) string {
return aws.StringValue(v.SubnetIdentifier)
}))
d.Set("vpc_id", group.VpcId)

return diags
}
Expand Down Expand Up @@ -202,3 +198,64 @@ func resourceSubnetGroupDelete(ctx context.Context, d *schema.ResourceData, meta

return diags
}

func resourceSubnetGroupCustomizeDiff(ctx context.Context, diff *schema.ResourceDiff, meta interface{}) error {
// Reserved ElastiCache Subnet Groups with the name "default" do not support tagging,
// thus we must suppress the diff originating from the provider-level default_tags configuration.
// Reference: https://github.com/hashicorp/terraform-provider-aws/issues/19213.
defaultTagsConfig := meta.(*conns.AWSClient).DefaultTagsConfig
if len(defaultTagsConfig.GetTags()) > 0 && diff.Get("name").(string) == "default" {
return nil
}

return nil
}

func findCacheSubnetGroupByName(ctx context.Context, conn *elasticache.ElastiCache, name string) (*elasticache.CacheSubnetGroup, error) {
input := &elasticache.DescribeCacheSubnetGroupsInput{
CacheSubnetGroupName: aws.String(name),
}

return findCacheSubnetGroup(ctx, conn, input, tfslices.PredicateTrue[*elasticache.CacheSubnetGroup]())
}

func findCacheSubnetGroup(ctx context.Context, conn *elasticache.ElastiCache, input *elasticache.DescribeCacheSubnetGroupsInput, filter tfslices.Predicate[*elasticache.CacheSubnetGroup]) (*elasticache.CacheSubnetGroup, error) {
output, err := findCacheSubnetGroups(ctx, conn, input, filter)

if err != nil {
return nil, err
}

return tfresource.AssertSinglePtrResult(output)
}

func findCacheSubnetGroups(ctx context.Context, conn *elasticache.ElastiCache, input *elasticache.DescribeCacheSubnetGroupsInput, filter tfslices.Predicate[*elasticache.CacheSubnetGroup]) ([]*elasticache.CacheSubnetGroup, error) {
var output []*elasticache.CacheSubnetGroup

err := conn.DescribeCacheSubnetGroupsPagesWithContext(ctx, input, func(page *elasticache.DescribeCacheSubnetGroupsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, v := range page.CacheSubnetGroups {
if v != nil && filter(v) {
output = append(output, v)
}
}

return !lastPage
})

if tfawserr.ErrCodeEquals(err, elasticache.ErrCodeCacheSubnetGroupNotFoundFault) {
return nil, &retry.NotFoundError{
LastError: err,
LastRequest: input,
}
}

if err != nil {
return nil, err
}

return output, nil
}
24 changes: 13 additions & 11 deletions internal/service/elasticache/subnet_group_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
"github.com/hashicorp/terraform-provider-aws/internal/flex"
tfslices "github.com/hashicorp/terraform-provider-aws/internal/slices"
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
)

// @SDKDataSource("aws_elasticache_subnet_group")
func DataSourceSubnetGroup() *schema.Resource {
// @SDKDataSource("aws_elasticache_subnet_group", name="Subnet Group")
func dataSourceSubnetGroup() *schema.Resource {
return &schema.Resource{
ReadWithoutTimeout: dataSourceSubnetGroupRead,

Expand All @@ -39,6 +40,10 @@ func DataSourceSubnetGroup() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
},
"tags": tftags.TagsSchema(),
"vpc_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}
Expand All @@ -50,23 +55,20 @@ func dataSourceSubnetGroupRead(ctx context.Context, d *schema.ResourceData, meta

name := d.Get("name").(string)

group, err := FindCacheSubnetGroupByName(ctx, conn, name)
group, err := findCacheSubnetGroupByName(ctx, conn, name)

if err != nil {
return sdkdiag.AppendErrorf(diags, "reading ElastiCache Subnet Group (%s): %s", name, err)
}

d.SetId(aws.StringValue(group.CacheSubnetGroupName))

var subnetIds []*string
for _, subnet := range group.Subnets {
subnetIds = append(subnetIds, subnet.SubnetIdentifier)
}

d.Set("arn", group.ARN)
d.Set("description", group.CacheSubnetGroupDescription)
d.Set("subnet_ids", flex.FlattenStringSet(subnetIds))
d.Set("name", group.CacheSubnetGroupName)
d.Set("subnet_ids", tfslices.ApplyToAll(group.Subnets, func(v *elasticache.Subnet) string {
return aws.StringValue(v.SubnetIdentifier)
}))
d.Set("vpc_id", group.VpcId)

tags, err := listTags(ctx, conn, d.Get("arn").(string))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestAccElastiCacheSubnetGroupDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "subnet_ids.#", resourceName, "subnet_ids.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
resource.TestCheckResourceAttrPair(dataSourceName, "vpc_id", resourceName, "vpc_id"),
),
},
},
Expand Down
7 changes: 1 addition & 6 deletions internal/service/elasticache/subnet_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,13 @@ func TestAccElastiCacheSubnetGroup_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "name", rName),
resource.TestCheckResourceAttr(resourceName, "subnet_ids.#", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.%", "0"),
resource.TestCheckResourceAttrSet(resourceName, "vpc_id"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"description"},
},
},
})
Expand Down Expand Up @@ -100,8 +99,6 @@ func TestAccElastiCacheSubnetGroup_tags(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"description"},
},
{
Config: testAccSubnetGroupConfig_tags2(rName, "key1", "value1updated", "key2", "value2"),
Expand Down Expand Up @@ -150,8 +147,6 @@ func TestAccElastiCacheSubnetGroup_update(t *testing.T) {
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"description"},
},
{
Config: testAccSubnetGroupConfig_updatePost(rName),
Expand Down
45 changes: 27 additions & 18 deletions internal/service/elasticache/sweep.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,38 +281,47 @@ func sweepSubnetGroups(region string) error {
return fmt.Errorf("error getting client: %w", err)
}
conn := client.ElastiCacheConn(ctx)
input := &elasticache.DescribeCacheSubnetGroupsInput{}
sweepResources := make([]sweep.Sweepable, 0)

err = conn.DescribeCacheSubnetGroupsPagesWithContext(ctx, &elasticache.DescribeCacheSubnetGroupsInput{}, func(page *elasticache.DescribeCacheSubnetGroupsOutput, lastPage bool) bool {
if len(page.CacheSubnetGroups) == 0 {
log.Print("[DEBUG] No ElastiCache Subnet Groups to sweep")
return false
err = conn.DescribeCacheSubnetGroupsPagesWithContext(ctx, input, func(page *elasticache.DescribeCacheSubnetGroupsOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, subnetGroup := range page.CacheSubnetGroups {
name := aws.StringValue(subnetGroup.CacheSubnetGroupName)
for _, v := range page.CacheSubnetGroups {
name := aws.StringValue(v.CacheSubnetGroupName)

if name == "default" {
log.Printf("[INFO] Skipping ElastiCache Subnet Group: %s", name)
continue
}

log.Printf("[INFO] Deleting ElastiCache Subnet Group: %s", name)
_, err := conn.DeleteCacheSubnetGroupWithContext(ctx, &elasticache.DeleteCacheSubnetGroupInput{
CacheSubnetGroupName: aws.String(name),
})
if err != nil {
log.Printf("[ERROR] Failed to delete ElastiCache Subnet Group (%s): %s", name, err)
}
r := resourceSubnetGroup()
d := r.Data(nil)
d.SetId(name)

sweepResources = append(sweepResources, sweep.NewSweepResource(r, d, client))
}

return !lastPage
})

if awsv1.SkipSweepError(err) {
log.Printf("[WARN] Skipping ElastiCache Subnet Group sweep for %s: %s", region, err)
return nil
}

if err != nil {
if awsv1.SkipSweepError(err) {
log.Printf("[WARN] Skipping ElastiCache Subnet Group sweep for %s: %s", region, err)
return nil
}
return fmt.Errorf("Error retrieving ElastiCache Subnet Groups: %w", err)
return fmt.Errorf("error listing ElastiCache Subnet Groups (%s): %w", region, err)
}

err = sweep.SweepOrchestrator(ctx, sweepResources)

if err != nil {
return fmt.Errorf("error sweeping ElastiCache Subnet Groups (%s): %w", region, err)
}

return nil
}

Expand Down
Loading
Loading