Skip to content

Commit

Permalink
Merge pull request #30842 from hashicorp/td-rm-asg-tags
Browse files Browse the repository at this point in the history
`r/aws_autoscaling_group`: Remove deprecated `tags` attribute
  • Loading branch information
jar-b committed Apr 26, 2023
2 parents 3f73a0a + f35dfa4 commit 7cd0236
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 170 deletions.
3 changes: 3 additions & 0 deletions .changelog/30842.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:breaking-change
resource/aws_autoscaling_group: Remove deprecated `tags` attribute
```
96 changes: 5 additions & 91 deletions internal/service/autoscaling/group.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,52 +744,6 @@ func ResourceGroup() *schema.Resource {

return create.StringHashcode(buf.String())
},
ConflictsWith: []string{"tags"},
},
"tags": {
Deprecated: "Use tag instead",
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeMap,
Elem: &schema.Schema{Type: schema.TypeString},
},
// Terraform 0.11 and earlier can provide incorrect type
// information during difference handling, in which boolean
// values are represented as "0" and "1". This Set function
// normalizes these hashing variations, while the Terraform
// Plugin SDK automatically suppresses the boolean/string
// difference in the value itself.
Set: func(v interface{}) int {
var buf bytes.Buffer

m, ok := v.(map[string]interface{})

if !ok {
return 0
}

if v, ok := m["key"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}

if v, ok := m["value"].(string); ok {
buf.WriteString(fmt.Sprintf("%s-", v))
}

if v, ok := m["propagate_at_launch"].(bool); ok {
buf.WriteString(fmt.Sprintf("%t-", v))
} else if v, ok := m["propagate_at_launch"].(string); ok {
if b, err := strconv.ParseBool(v); err == nil {
buf.WriteString(fmt.Sprintf("%t-", b))
} else {
buf.WriteString(fmt.Sprintf("%s-", v))
}
}

return create.StringHashcode(buf.String())
},
ConflictsWith: []string{"tag"},
},
"target_group_arns": {
Type: schema.TypeSet,
Expand Down Expand Up @@ -977,10 +931,6 @@ func resourceGroupCreate(ctx context.Context, d *schema.ResourceData, meta inter
createInput.Tags = Tags(KeyValueTags(ctx, v, asgName, TagResourceTypeGroup).IgnoreAWS())
}

if v, ok := d.GetOk("tags"); ok {
createInput.Tags = Tags(KeyValueTags(ctx, v, asgName, TagResourceTypeGroup).IgnoreAWS())
}

if v, ok := d.GetOk("target_group_arns"); ok && len(v.(*schema.Set).List()) > 0 {
createInput.TargetGroupARNs = flex.ExpandStringSet(v.(*schema.Set))
}
Expand Down Expand Up @@ -1177,31 +1127,8 @@ func resourceGroupRead(ctx context.Context, d *schema.ResourceData, meta interfa
d.Set("warm_pool", nil)
}

var tagOk, tagsOk bool
var v interface{}

// Deprecated: In a future major version, this should always set all tags except those ignored.
// Remove d.GetOk() and Only() handling.
if v, tagOk = d.GetOk("tag"); tagOk {
proposedStateTags := KeyValueTags(ctx, v, d.Id(), TagResourceTypeGroup)

if err := d.Set("tag", ListOfMap(KeyValueTags(ctx, g.Tags, d.Id(), TagResourceTypeGroup).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Only(proposedStateTags))); err != nil {
return sdkdiag.AppendErrorf(diags, "setting tag: %s", err)
}
}

if v, tagsOk = d.GetOk("tags"); tagsOk {
proposedStateTags := KeyValueTags(ctx, v, d.Id(), TagResourceTypeGroup)

if err := d.Set("tags", ListOfStringMap(KeyValueTags(ctx, g.Tags, d.Id(), TagResourceTypeGroup).IgnoreAWS().IgnoreConfig(ignoreTagsConfig).Only(proposedStateTags))); err != nil {
return sdkdiag.AppendErrorf(diags, "setting tags: %s", err)
}
}

if !tagOk && !tagsOk {
if err := d.Set("tag", ListOfMap(KeyValueTags(ctx, g.Tags, d.Id(), TagResourceTypeGroup).IgnoreAWS().IgnoreConfig(ignoreTagsConfig))); err != nil {
return sdkdiag.AppendErrorf(diags, "setting tag: %s", err)
}
if err := d.Set("tag", ListOfMap(KeyValueTags(ctx, g.Tags, d.Id(), TagResourceTypeGroup).IgnoreAWS().IgnoreConfig(ignoreTagsConfig))); err != nil {
return sdkdiag.AppendErrorf(diags, "setting tag: %s", err)
}

return diags
Expand All @@ -1219,7 +1146,6 @@ func resourceGroupUpdate(ctx context.Context, d *schema.ResourceData, meta inter
"load_balancers",
"suspended_processes",
"tag",
"tags",
"target_group_arns",
"warm_pool",
) {
Expand Down Expand Up @@ -1339,17 +1265,11 @@ func resourceGroupUpdate(ctx context.Context, d *schema.ResourceData, meta inter
}
}

if d.HasChanges("tag", "tags") {
if d.HasChanges("tag") {
oTagRaw, nTagRaw := d.GetChange("tag")
oTagsRaw, nTagsRaw := d.GetChange("tags")

oTag := KeyValueTags(ctx, oTagRaw, d.Id(), TagResourceTypeGroup)
oTags := KeyValueTags(ctx, oTagsRaw, d.Id(), TagResourceTypeGroup)
oldTags := Tags(oTag.Merge(oTags))

nTag := KeyValueTags(ctx, nTagRaw, d.Id(), TagResourceTypeGroup)
nTags := KeyValueTags(ctx, nTagsRaw, d.Id(), TagResourceTypeGroup)
newTags := Tags(nTag.Merge(nTags))
oldTags := Tags(KeyValueTags(ctx, oTagRaw, d.Id(), TagResourceTypeGroup))
newTags := Tags(KeyValueTags(ctx, nTagRaw, d.Id(), TagResourceTypeGroup))

if err := UpdateTags(ctx, conn, d.Id(), TagResourceTypeGroup, oldTags, newTags); err != nil {
return sdkdiag.AppendErrorf(diags, "updating tags for Auto Scaling Group (%s): %s", d.Id(), err)
Expand Down Expand Up @@ -1501,12 +1421,6 @@ func resourceGroupUpdate(ctx context.Context, d *schema.ResourceData, meta inter
}
}

if v.Contains("tag") && !v.Contains("tags") {
triggers = append(triggers, "tags") // nozero
} else if !v.Contains("tag") && v.Contains("tags") {
triggers = append(triggers, "tag") // nozero
}

shouldRefreshInstances = d.HasChanges(triggers...)
}
}
Expand Down
63 changes: 8 additions & 55 deletions internal/service/autoscaling/group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,36 +274,6 @@ func TestAccAutoScalingGroup_tags(t *testing.T) {
})
}

func TestAccAutoScalingGroup_deprecatedTags(t *testing.T) {
ctx := acctest.Context(t)
var group autoscaling.Group
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_autoscaling_group.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, autoscaling.EndpointsID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckGroupDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccGroupConfig_deprecatedTags1(rName, "key1", "value1", true),
Check: resource.ComposeTestCheckFunc(
testAccCheckGroupExists(ctx, resourceName, &group),
resource.TestCheckResourceAttr(resourceName, "tag.#", "0"),
resource.TestCheckResourceAttr(resourceName, "tags.#", "1"),
resource.TestCheckTypeSetElemNestedAttrs(resourceName, "tags.*", map[string]string{
"key": "key1",
"value": "value1",
"propagate_at_launch": "true",
}),
),
},
testAccGroupImportStep(resourceName),
},
})
}

func TestAccAutoScalingGroup_simple(t *testing.T) {
ctx := acctest.Context(t)
var group autoscaling.Group
Expand Down Expand Up @@ -1165,7 +1135,7 @@ func TestAccAutoScalingGroup_InstanceRefresh_triggers(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.#", "0"),
resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"),
resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "1"),
resource.TestCheckTypeSetElemAttr(resourceName, "instance_refresh.0.triggers.*", "tags"),
resource.TestCheckTypeSetElemAttr(resourceName, "instance_refresh.0.triggers.*", "tag"),
testAccCheckInstanceRefreshCount(ctx, &group, 1),
testAccCheckInstanceRefreshStatus(ctx, &group, 0, autoscaling.InstanceRefreshStatusPending, autoscaling.InstanceRefreshStatusInProgress),
),
Expand Down Expand Up @@ -1256,6 +1226,7 @@ func TestAccAutoScalingGroup_ALBTargetGroups_elbCapacity(t *testing.T) {
var group autoscaling.Group
resourceName := "aws_autoscaling_group.test"
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
subnetCount := 2
var tg elbv2.TargetGroup

resource.ParallelTest(t, resource.TestCase{
Expand All @@ -1265,7 +1236,7 @@ func TestAccAutoScalingGroup_ALBTargetGroups_elbCapacity(t *testing.T) {
CheckDestroy: testAccCheckGroupDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccGroupConfig_targetELBCapacity(rName),
Config: testAccGroupConfig_targetELBCapacity(rName, subnetCount),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckGroupExists(ctx, resourceName, &group),
testAccCheckLBTargetGroupExists(ctx, "aws_lb_target_group.test", &tg),
Expand Down Expand Up @@ -3738,24 +3709,6 @@ resource "aws_autoscaling_group" "test" {
`, rName, tagKey1, tagValue1, tagPropagateAtLaunch1, tagKey2, tagValue2, tagPropagateAtLaunch2))
}

func testAccGroupConfig_deprecatedTags1(rName, tagKey1, tagValue1 string, tagPropagateAtLaunch1 bool) string {
return acctest.ConfigCompose(testAccGroupConfig_launchConfigurationBase(rName, "t2.micro"), fmt.Sprintf(`
resource "aws_autoscaling_group" "test" {
availability_zones = [data.aws_availability_zones.available.names[0]]
max_size = 0
min_size = 0
name = %[1]q
launch_configuration = aws_launch_configuration.test.name
tags = [{
"key" = %[2]q
"value" = %[3]q
"propagate_at_launch" = %[4]t
}]
}
`, rName, tagKey1, tagValue1, tagPropagateAtLaunch1))
}

func testAccGroupConfig_simple(rName string) string {
return acctest.ConfigCompose(testAccGroupConfig_launchConfigurationBase(rName, "t2.micro"), fmt.Sprintf(`
resource "aws_autoscaling_group" "test" {
Expand Down Expand Up @@ -4519,7 +4472,7 @@ resource "aws_autoscaling_group" "test" {
instance_refresh {
strategy = "Rolling"
triggers = ["tags"]
triggers = ["tag"]
}
tag {
Expand Down Expand Up @@ -4622,10 +4575,10 @@ resource "aws_autoscaling_group" "test" {
`, rName, targetGroupCount))
}

func testAccGroupConfig_targetELBCapacity(rName string) string {
func testAccGroupConfig_targetELBCapacity(rName string, subnetCount int) string {
return acctest.ConfigCompose(
acctest.ConfigLatestAmazonLinuxHVMEBSAMI(),
acctest.ConfigVPCWithSubnets(rName, 2),
acctest.ConfigVPCWithSubnets(rName, subnetCount),
fmt.Sprintf(`
resource "aws_internet_gateway" "test" {
vpc_id = aws_vpc.test.id
Expand Down Expand Up @@ -4686,7 +4639,7 @@ resource "aws_route_table" "test" {
}
resource "aws_route_table_association" "test" {
count = length(aws_subnet.test[*])
count = %[2]d
subnet_id = aws_subnet.test[count.index].id
route_table_id = aws_route_table.test.id
Expand Down Expand Up @@ -4737,7 +4690,7 @@ resource "aws_autoscaling_group" "test" {
propagate_at_launch = true
}
}
`, rName))
`, rName, subnetCount))
}

func testAccGroupConfig_warmPoolEmpty(rName string) string {
Expand Down
48 changes: 24 additions & 24 deletions website/docs/r/autoscaling_group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ resource "aws_autoscaling_group" "example" {
}
```

### Interpolated tags
### Dynamic tagging

```terraform
variable "extra_tags" {
Expand All @@ -276,28 +276,32 @@ variable "extra_tags" {
]
}
resource "aws_autoscaling_group" "bar" {
resource "aws_autoscaling_group" "test" {
name = "foobar3-terraform-test"
max_size = 5
min_size = 2
launch_configuration = aws_launch_configuration.foobar.name
vpc_zone_identifier = [aws_subnet.example1.id, aws_subnet.example2.id]
tags = concat(
[
{
"key" = "interpolation1"
"value" = "value3"
"propagate_at_launch" = true
},
{
"key" = "interpolation2"
"value" = "value4"
"propagate_at_launch" = true
},
],
var.extra_tags,
)
tag {
key = "explicit1"
value = "value1"
propagate_at_launch = true
}
tag {
key = "explicit2"
value = "value2"
propagate_at_launch = true
}
dynamic "tag" {
for_each = var.extra_tags
content {
key = tag.value.key
propagate_at_launch = tag.value.propagate_at_launch
value = tag.value.value
}
}
}
```

Expand Down Expand Up @@ -416,8 +420,7 @@ The following arguments are supported:
* `termination_policies` (Optional) List of policies to decide how the instances in the Auto Scaling Group should be terminated. The allowed values are `OldestInstance`, `NewestInstance`, `OldestLaunchConfiguration`, `ClosestToNextInstanceHour`, `OldestLaunchTemplate`, `AllocationStrategy`, `Default`. Additionally, the ARN of a Lambda function can be specified for custom termination policies.
* `suspended_processes` - (Optional) List of processes to suspend for the Auto Scaling Group. The allowed values are `Launch`, `Terminate`, `HealthCheck`, `ReplaceUnhealthy`, `AZRebalance`, `AlarmNotification`, `ScheduledActions`, `AddToLoadBalancer`, `InstanceRefresh`.
Note that if you suspend either the `Launch` or `Terminate` process types, it can prevent your Auto Scaling Group from functioning properly.
* `tag` (Optional) Configuration block(s) containing resource tags. Conflicts with `tags`. See [Tag](#tag-and-tags) below for more details.
* `tags` (Optional, **Deprecated** use `tag` instead) Set of maps containing resource tags. Conflicts with `tag`. See [Tags](#tag-and-tags) below for more details.
* `tag` (Optional) Configuration block(s) containing resource tags. See [Tag](#tag) below for more details.
* `placement_group` (Optional) Name of the placement group into which you'll launch your instances, if any.
* `metrics_granularity` - (Optional) Granularity to associate with the metrics to collect. The only valid value is `1Minute`. Default is `1Minute`.
* `enabled_metrics` - (Optional) List of metrics to collect. The allowed values are defined by the [underlying AWS API](https://docs.aws.amazon.com/autoscaling/ec2/APIReference/API_EnableMetricsCollection.html).
Expand Down Expand Up @@ -611,7 +614,7 @@ This configuration block supports the following:
* `min` - (Required) Minimum.
* `max` - (Optional) Maximum.

### tag and tags
### tag

The `tag` attribute accepts exactly one tag declaration with the following fields:

Expand All @@ -620,10 +623,7 @@ The `tag` attribute accepts exactly one tag declaration with the following field
* `propagate_at_launch` - (Required) Enables propagation of the tag to
Amazon EC2 instances launched via this ASG

To declare multiple tags additional `tag` blocks can be specified.
Alternatively the `tags` attributes can be used, which accepts a list of maps containing the above field names as keys and their respective values.
This allows the construction of dynamic lists of tags which is not possible using the single `tag` attribute.
`tag` and `tags` are mutually exclusive, only one of them can be specified.
To declare multiple tags, additional `tag` blocks can be specified.

~> **NOTE:** Other AWS APIs may automatically add special tags to their associated Auto Scaling Group for management purposes, such as ECS Capacity Providers adding the `AmazonECSManaged` tag. These generally should be included in the configuration so Terraform does not attempt to remove them and so if the `min_size` was greater than zero on creation, that these tag(s) are applied to any initial EC2 Instances in the Auto Scaling Group. If these tag(s) were missing in the Auto Scaling Group configuration on creation, affected EC2 Instances missing the tags may require manual intervention of adding the tags to ensure they work properly with the other AWS service.

Expand Down

0 comments on commit 7cd0236

Please sign in to comment.