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

F/resource aws elasticache subnet group: Support Tags #19119

Merged
3 changes: 3 additions & 0 deletions .changelog/19119.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_elasticache_subnet_group: Add `tags` argument
```
50 changes: 46 additions & 4 deletions aws/resource_aws_elasticache_subnet_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsElasticacheSubnetGroup() *schema.Resource {
Expand Down Expand Up @@ -46,12 +47,22 @@ func resourceAwsElasticacheSubnetGroup() *schema.Resource {
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchema(),
"tags_all": tagsSchemaComputed(),
},

CustomizeDiff: SetTagsDiff,
}
}

func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
tags := defaultTagsConfig.MergeTags(keyvaluetags.New(d.Get("tags").(map[string]interface{})))

// Get the group properties
name := d.Get("name").(string)
Expand All @@ -66,11 +77,12 @@ func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interf
CacheSubnetGroupDescription: aws.String(desc),
CacheSubnetGroupName: aws.String(name),
SubnetIds: subnetIds,
Tags: tags.IgnoreAws().ElasticacheTags(),
}

_, err := conn.CreateCacheSubnetGroup(req)
if err != nil {
return fmt.Errorf("Error creating CacheSubnetGroup: %s", err)
return fmt.Errorf("error creating ElastiCache Subnet Group (%s): %w", name, err)
}

// Assign the group name as the resource ID
Expand All @@ -79,11 +91,14 @@ func resourceAwsElasticacheSubnetGroupCreate(d *schema.ResourceData, meta interf
// name contained uppercase characters.
d.SetId(strings.ToLower(name))

return nil
return resourceAwsElasticacheSubnetGroupRead(d, meta)
}

func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn
defaultTagsConfig := meta.(*AWSClient).DefaultTagsConfig
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

req := &elasticache.DescribeCacheSubnetGroupsInput{
CacheSubnetGroupName: aws.String(d.Get("name").(string)),
}
Expand Down Expand Up @@ -118,15 +133,34 @@ func resourceAwsElasticacheSubnetGroupRead(d *schema.ResourceData, meta interfac
ids[i] = *s.SubnetIdentifier
}

d.Set("arn", group.ARN)
d.Set("name", group.CacheSubnetGroupName)
d.Set("description", group.CacheSubnetGroupDescription)
d.Set("subnet_ids", ids)

tags, err := keyvaluetags.ElasticacheListTags(conn, d.Get("arn").(string))

if err != nil && !isAWSErr(err, "UnknownOperationException", "") {
return fmt.Errorf("error listing tags for ElastiCache SubnetGroup (%s): %w", d.Id(), err)
}

tags = tags.IgnoreAws().IgnoreConfig(ignoreTagsConfig)

//lintignore:AWSR002
if err := d.Set("tags", tags.RemoveDefaultConfig(defaultTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %w", err)
}

if err := d.Set("tags_all", tags.Map()); err != nil {
return fmt.Errorf("error setting tags_all: %w", err)
}

return nil
}

func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).elasticacheconn

if d.HasChanges("subnet_ids", "description") {
var subnets []*string
if v := d.Get("subnet_ids"); v != nil {
Expand All @@ -141,8 +175,16 @@ func resourceAwsElasticacheSubnetGroupUpdate(d *schema.ResourceData, meta interf
CacheSubnetGroupDescription: aws.String(d.Get("description").(string)),
SubnetIds: subnets,
})

if err != nil {
return err
return fmt.Errorf("error updating ElastiCache Subnet Group (%s): %w", d.Id(), err)
}
}

if d.HasChange("tags_all") {
o, n := d.GetChange("tags_all")
if err := keyvaluetags.ElasticacheUpdateTags(conn, d.Get("arn").(string), o, n); err != nil {
return fmt.Errorf("error updating tags: %w", err)
}
}

Expand Down Expand Up @@ -184,7 +226,7 @@ func resourceAwsElasticacheSubnetGroupDelete(d *schema.ResourceData, meta interf
}

if err != nil {
return fmt.Errorf("error deleting Elasticache Subnet Group (%s): %s", d.Id(), err)
return fmt.Errorf("error deleting ElastiCache Subnet Group (%s): %w", d.Id(), err)
}

return nil
Expand Down
116 changes: 116 additions & 0 deletions aws/resource_aws_elasticache_subnet_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,53 @@ func TestAccAWSElasticacheSubnetGroup_update(t *testing.T) {
})
}

func TestAccAWSElasticacheSubnetGroup_tags(t *testing.T) {
var csg elasticache.CacheSubnetGroup
resourceName := "aws_elasticache_subnet_group.test"
rInt := acctest.RandInt()

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, elasticache.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSElasticacheSubnetGroupDestroy,
Steps: []resource.TestStep{
{
Config: testAccAWSElasticacheSubnetGroupTags1(rInt, "key1", "value1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists(resourceName, &csg),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{
"description"},
},
{
Config: testAccAWSElasticacheSubnetGroupTags2(rInt, "key1", "value1updated", "key2", "value2"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists(resourceName, &csg),
resource.TestCheckResourceAttr(resourceName, "tags.%", "2"),
resource.TestCheckResourceAttr(resourceName, "tags.key1", "value1updated"),
resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
),
},
{
Config: testAccAWSElasticacheSubnetGroupTags1(rInt, "key2", "value2"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSElasticacheSubnetGroupExists(resourceName, &csg),
resource.TestCheckResourceAttr(resourceName, "tags.%", "1"),
resource.TestCheckResourceAttr(resourceName, "tags.key2", "value2"),
),
},
},
})
}

func testAccCheckAWSElasticacheSubnetGroupDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).elasticacheconn

Expand Down Expand Up @@ -299,3 +346,72 @@ resource "aws_elasticache_subnet_group" "test" {
}
`, rInt))
}

func testAccAWSElasticacheSubnetGroupTags1(rInt int, tag1Key, tag1Value string) string {
return composeConfig(testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(`
resource "aws_vpc" "foo" {
cidr_block = "192.168.0.0/16"

tags = {
Name = "terraform-testacc-elasticache-subnet-group"
}
}

resource "aws_subnet" "foo" {
vpc_id = aws_vpc.foo.id
cidr_block = "192.168.0.0/20"
availability_zone = data.aws_availability_zones.available.names[0]

tags = {
Name = "tf-acc-elasticache-subnet-group"
}
}

resource "aws_elasticache_subnet_group" "test" {
# Including uppercase letters in this name to ensure
# that we correctly handle the fact that the API
# normalizes names to lowercase.
name = "tf-TEST-cache-subnet-%03d"
subnet_ids = [aws_subnet.foo.id]

tags = {
%q = %q
}
}
`, rInt, tag1Key, tag1Value))
}

func testAccAWSElasticacheSubnetGroupTags2(rInt int, tag1Key, tag1Value, tag2Key, tag2Value string) string {
return composeConfig(testAccAvailableAZsNoOptInConfig(), fmt.Sprintf(`
resource "aws_vpc" "foo" {
cidr_block = "192.168.0.0/16"

tags = {
Name = "terraform-testacc-elasticache-subnet-group"
}
}

resource "aws_subnet" "foo" {
vpc_id = aws_vpc.foo.id
cidr_block = "192.168.0.0/20"
availability_zone = data.aws_availability_zones.available.names[0]

tags = {
Name = "tf-acc-elasticache-subnet-group"
}
}

resource "aws_elasticache_subnet_group" "test" {
# Including uppercase letters in this name to ensure
# that we correctly handle the fact that the API
# normalizes names to lowercase.
name = "tf-TEST-cache-subnet-%03d"
subnet_ids = [aws_subnet.foo.id]

tags = {
%q = %q
%q = %q
}
}
`, rInt, tag1Key, tag1Value, tag2Key, tag2Value))
}
8 changes: 5 additions & 3 deletions website/docs/r/elasticache_subnet_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,16 @@ The following arguments are supported:
* `name` – (Required) Name for the cache subnet group. Elasticache converts this name to lowercase.
* `description` – (Optional) Description for the cache subnet group. Defaults to "Managed by Terraform".
* `subnet_ids` – (Required) List of VPC Subnet IDs for the cache subnet group
* `tags` - (Optional) Key-value map of resource tags. If configured with a provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

## Attributes Reference

In addition to all arguments above, the following attributes are exported:

* `description`
* `name`
* `subnet_ids`
* `description` - The Description of the ElastiCache Subnet Group.
* `name` - The Name of the ElastiCache Subnet Group.
* `subnet_ids` - The Subnet IDs of the ElastiCache Subnet Group.
* `tags_all` - A map of tags assigned to the resource, including those inherited from the provider [`default_tags` configuration block](/docs/providers/aws/index.html#default_tags-configuration-block).


## Import
Expand Down