Skip to content

Commit

Permalink
r/aws_autoscaling_group_tag: new resource for tagging existing ASGs
Browse files Browse the repository at this point in the history
  • Loading branch information
jbg committed Jul 12, 2021
1 parent 24656c8 commit 5377524
Show file tree
Hide file tree
Showing 5 changed files with 421 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/20009.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-resource
aws_autoscaling_group_tag
```
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ func Provider() *schema.Provider {
"aws_athena_workgroup": resourceAwsAthenaWorkgroup(),
"aws_autoscaling_attachment": resourceAwsAutoscalingAttachment(),
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
"aws_autoscaling_group_tag": resourceAwsAutoscalingGroupTag(),
"aws_autoscaling_lifecycle_hook": resourceAwsAutoscalingLifecycleHook(),
"aws_autoscaling_notification": resourceAwsAutoscalingNotification(),
"aws_autoscaling_policy": resourceAwsAutoscalingPolicy(),
Expand Down
143 changes: 143 additions & 0 deletions aws/resource_aws_autoscaling_group_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package aws

import (
"fmt"
"log"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func resourceAwsAutoscalingGroupTag() *schema.Resource {
return &schema.Resource{
Create: resourceAwsAutoscalingGroupTagCreate,
Read: resourceAwsAutoscalingGroupTagRead,
Update: resourceAwsAutoscalingGroupTagUpdate,
Delete: resourceAwsAutoscalingGroupTagDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"asg_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"tag": {
Type: schema.TypeList,
MaxItems: 1,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"value": {
Type: schema.TypeString,
Required: true,
},
"propagate_at_launch": {
Type: schema.TypeBool,
Required: true,
},
},
},
},
},
}
}

func extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(id string) (string, string, error) {
parts := strings.SplitN(id, ",", 2)

if len(parts) != 2 {
return "", "", fmt.Errorf("Invalid resource ID; cannot look up resource: %s", id)
}

return parts[0], parts[1], nil
}

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

asgName := d.Get("asg_name").(string)
tags := d.Get("tag").([]interface{})

tag := tags[0].(map[string]interface{})
key := tag["key"].(string)

if err := keyvaluetags.AutoscalingUpdateTags(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, nil, tags); err != nil {
return fmt.Errorf("error updating Autoscaling Tag (%s) for resource (%s): %w", key, asgName, err)
}

d.SetId(fmt.Sprintf("%s,%s", asgName, key))

return resourceAwsAutoscalingGroupTagRead(d, meta)
}

func resourceAwsAutoscalingGroupTagRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
asgName, key, err := extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(d.Id())

if err != nil {
return err
}

exists, tagData, err := keyvaluetags.AutoscalingGetTag(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, key)

if err != nil {
return fmt.Errorf("error reading Autoscaling Tag (%s) for resource (%s): %w", key, asgName, err)
}

if !exists {
log.Printf("[WARN] Autoscaling Tag (%s) for resource (%s) not found, removing from state", key, asgName)
d.SetId("")
return nil
}

d.Set("asg_name", asgName)

tag := map[string]interface{}{
"key": key,
"value": tagData.Value,

"propagate_at_launch": tagData.AdditionalBoolFields["PropagateAtLaunch"],
}
d.Set("tag", []map[string]interface{}{tag})

return nil
}

func resourceAwsAutoscalingGroupTagUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
asgName, key, err := extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(d.Id())

if err != nil {
return err
}

if err := keyvaluetags.AutoscalingUpdateTags(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, nil, d.Get("tag")); err != nil {
return fmt.Errorf("error updating Autoscaling Tag (%s) for resource (%s): %w", key, asgName, err)
}

return resourceAwsAutoscalingGroupTagRead(d, meta)
}

func resourceAwsAutoscalingGroupTagDelete(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).autoscalingconn
asgName, key, err := extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(d.Id())

if err != nil {
return err
}

if err := keyvaluetags.AutoscalingUpdateTags(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, d.Get("tag"), nil); err != nil {
return fmt.Errorf("error deleting Autoscaling Tag (%s) for resource (%s): %w", key, asgName, err)
}

return nil
}
204 changes: 204 additions & 0 deletions aws/resource_aws_autoscaling_group_tag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
package aws

import (
"fmt"
"testing"

"github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func TestAccAWSAutoscalingGroupTag_basic(t *testing.T) {
resourceName := "aws_autoscaling_group_tag.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, autoscaling.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAutoscalingGroupTagDestroy,
Steps: []resource.TestStep{
{
Config: testAccAutoscalingGroupTagConfig("key1", "value1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAutoscalingGroupTagExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tag.0.key", "key1"),
resource.TestCheckResourceAttr(resourceName, "tag.0.value", "value1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccAWSAutoscalingGroupTag_disappears(t *testing.T) {
resourceName := "aws_autoscaling_group_tag.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, autoscaling.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAutoscalingGroupTagDestroy,
Steps: []resource.TestStep{
{
Config: testAccAutoscalingGroupTagConfig("key1", "value1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAutoscalingGroupTagExists(resourceName),
testAccCheckResourceDisappears(testAccProvider, resourceAwsAutoscalingGroupTag(), resourceName),
),
ExpectNonEmptyPlan: true,
},
},
})
}

func TestAccAWSAutoscalingGroupTag_Value(t *testing.T) {
resourceName := "aws_autoscaling_group_tag.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, autoscaling.EndpointsID),
Providers: testAccProviders,
CheckDestroy: testAccCheckAutoscalingGroupTagDestroy,
Steps: []resource.TestStep{
{
Config: testAccAutoscalingGroupTagConfig("key1", "value1"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAutoscalingGroupTagExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tag.0.key", "key1"),
resource.TestCheckResourceAttr(resourceName, "tag.0.value", "value1"),
),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAutoscalingGroupTagConfig("key1", "value1updated"),
Check: resource.ComposeTestCheckFunc(
testAccCheckAutoscalingGroupTagExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "tag.0.key", "key1"),
resource.TestCheckResourceAttr(resourceName, "tag.0.value", "value1updated"),
),
},
},
})
}

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

for _, rs := range s.RootModule().Resources {
if rs.Type != "aws_autoscaling_group_tag" {
continue
}

asgName, key, err := extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(rs.Primary.ID)

if err != nil {
return err
}

exists, _, err := keyvaluetags.AutoscalingGetTag(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, key)

if err != nil {
return err
}

if exists {
return fmt.Errorf("Tag (%s) for resource (%s) still exists", key, asgName)
}
}

return nil
}

func testAccCheckAutoscalingGroupTagExists(n string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not found: %s", n)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

asgName, key, err := extractAutoscalingGroupNameAndKeyFromAutoscalingGroupTagID(rs.Primary.ID)

if err != nil {
return err
}

conn := testAccProvider.Meta().(*AWSClient).autoscalingconn

exists, _, err := keyvaluetags.AutoscalingGetTag(conn, asgName, autoscalingTagResourceTypeAutoScalingGroup, key)

if err != nil {
return err
}

if !exists {
return fmt.Errorf("Tag (%s) for resource (%s) not found", key, asgName)
}

return nil
}
}

func testAccAutoscalingGroupTagConfig(key string, value string) string {
return fmt.Sprintf(`
data "aws_ami" "latest_al2" {
owners = ["amazon"]
most_recent = true
filter {
name = "name"
values = ["amzn2-ami-hvm-*-x86_64-ebs"]
}
}
resource "aws_launch_template" "test" {
name_prefix = "terraform-test-"
image_id = data.aws_ami.latest_al2.id
instance_type = "t2.nano"
}
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_autoscaling_group" "test" {
lifecycle {
ignore_changes = [tag]
}
availability_zones = data.aws_availability_zones.available.names
min_size = 0
max_size = 0
launch_template {
id = aws_launch_template.test.id
version = "$Latest"
}
}
resource "aws_autoscaling_group_tag" "test" {
asg_name = aws_autoscaling_group.test.name
tag {
key = %[1]q
value = %[2]q
propagate_at_launch = true
}
}
`, key, value)
}
Loading

0 comments on commit 5377524

Please sign in to comment.