From b54c1adc30057d3445603a8a162b4bf2d18dd956 Mon Sep 17 00:00:00 2001 From: Evan Cleary Date: Tue, 5 Sep 2023 12:26:54 -0400 Subject: [PATCH 1/3] r/aws_autoscaling_group: Add `standby_instances` and `scale_in_protected_instances` attributes to instance_refresh preferences --- internal/service/autoscaling/group.go | 18 ++++ internal/service/autoscaling/group_test.go | 102 ++++++++++++++++++ .../docs/r/autoscaling_group.html.markdown | 2 + 3 files changed, 122 insertions(+) diff --git a/internal/service/autoscaling/group.go b/internal/service/autoscaling/group.go index 40d3346625d..81c7a090acf 100644 --- a/internal/service/autoscaling/group.go +++ b/internal/service/autoscaling/group.go @@ -208,11 +208,21 @@ func ResourceGroup() *schema.Resource { Default: 90, ValidateFunc: validation.IntBetween(0, 100), }, + "scale_in_protected_instances": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(autoscaling.ScaleInProtectedInstances_Values(), false), + }, "skip_matching": { Type: schema.TypeBool, Optional: true, Default: false, }, + "standby_instances": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice(autoscaling.StandbyInstances_Values(), false), + }, }, }, }, @@ -3243,10 +3253,18 @@ func expandRefreshPreferences(tfMap map[string]interface{}) *autoscaling.Refresh apiObject.MinHealthyPercentage = aws.Int64(int64(v)) } + if v, ok := tfMap["scale_in_protected_instances"].(string); ok { + apiObject.ScaleInProtectedInstances = aws.String(v) + } + if v, ok := tfMap["skip_matching"].(bool); ok { apiObject.SkipMatching = aws.Bool(v) } + if v, ok := tfMap["standby_instances"].(string); ok { + apiObject.StandbyInstances = aws.String(v) + } + return apiObject } diff --git a/internal/service/autoscaling/group_test.go b/internal/service/autoscaling/group_test.go index 030d042d4db..48856712cbb 100644 --- a/internal/service/autoscaling/group_test.go +++ b/internal/service/autoscaling/group_test.go @@ -1222,7 +1222,9 @@ func TestAccAutoScalingGroup_InstanceRefresh_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), ), @@ -1238,7 +1240,45 @@ func TestAccAutoScalingGroup_InstanceRefresh_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "true"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), + ), + }, + { + Config: testAccGroupConfig_instanceRefreshScaleInProtectedInstances(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGroupExists(ctx, resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.#", "1"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.#", "1"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.auto_rollback", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_delay", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", "Ignore"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), + ), + }, + { + Config: testAccGroupConfig_instanceRefreshStandbyInstances(rName), + Check: resource.ComposeTestCheckFunc( + testAccCheckGroupExists(ctx, resourceName, &group), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.#", "1"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.#", "1"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.auto_rollback", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_delay", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", "Ignore"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), ), @@ -1259,7 +1299,9 @@ func TestAccAutoScalingGroup_InstanceRefresh_basic(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.4", "100"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", "10"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "50"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), ), @@ -1382,7 +1424,9 @@ func TestAccAutoScalingGroup_InstanceRefresh_autoRollback(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), ), @@ -1398,7 +1442,9 @@ func TestAccAutoScalingGroup_InstanceRefresh_autoRollback(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.checkpoint_percentages.#", "0"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.instance_warmup", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.min_healthy_percentage", "0"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.scale_in_protected_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.skip_matching", "false"), + resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.preferences.0.standby_instances", ""), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.strategy", "Rolling"), resource.TestCheckResourceAttr(resourceName, "instance_refresh.0.triggers.#", "0"), ), @@ -4883,6 +4929,62 @@ resource "aws_autoscaling_group" "test" { `, rName)) } +func testAccGroupConfig_instanceRefreshScaleInProtectedInstances(rName string) string { + return acctest.ConfigCompose(testAccGroupConfig_launchConfigurationBase(rName, "t3.nano"), fmt.Sprintf(` +resource "aws_autoscaling_group" "test" { + availability_zones = [data.aws_availability_zones.available.names[0]] + name = %[1]q + max_size = 2 + min_size = 1 + desired_capacity = 1 + launch_configuration = aws_launch_configuration.test.name + + instance_refresh { + strategy = "Rolling" + + preferences { + min_healthy_percentage = 0 + scale_in_protected_instances = "Ignore" + } + } + + tag { + key = "Name" + value = %[1]q + propagate_at_launch = true + } +} +`, rName)) +} + +func testAccGroupConfig_instanceRefreshStandbyInstances(rName string) string { + return acctest.ConfigCompose(testAccGroupConfig_launchConfigurationBase(rName, "t3.nano"), fmt.Sprintf(` +resource "aws_autoscaling_group" "test" { + availability_zones = [data.aws_availability_zones.available.names[0]] + name = %[1]q + max_size = 2 + min_size = 1 + desired_capacity = 1 + launch_configuration = aws_launch_configuration.test.name + + instance_refresh { + strategy = "Rolling" + + preferences { + min_healthy_percentage = 0 + standby_instances = "Ignore" + } + } + + tag { + key = "Name" + value = %[1]q + propagate_at_launch = true + } +} +`, rName)) +} + func testAccGroupConfig_instanceRefreshAutoRollback(rName, instanceType string) string { return acctest.ConfigCompose(testAccGroupConfig_launchTemplateBase(rName, instanceType), fmt.Sprintf(` resource "aws_autoscaling_group" "test" { diff --git a/website/docs/r/autoscaling_group.html.markdown b/website/docs/r/autoscaling_group.html.markdown index e9bb0225dfa..d5cac3caacb 100644 --- a/website/docs/r/autoscaling_group.html.markdown +++ b/website/docs/r/autoscaling_group.html.markdown @@ -658,6 +658,8 @@ This configuration block supports the following: - `min_healthy_percentage` - (Optional) Amount of capacity in the Auto Scaling group that must remain healthy during an instance refresh to allow the operation to continue, as a percentage of the desired capacity of the Auto Scaling group. Defaults to `90`. - `skip_matching` - (Optional) Replace instances that already have your desired configuration. Defaults to `false`. - `auto_rollback` - (Optional) Automatically rollback if instance refresh fails. Defaults to `false`. This option may only be set to `true` when specifying a `launch_template` or `mixed_instances_policy`. + - `scale_in_protected_instances` - (Optional) Behavior when encountering instances protected from scale in are found. Available behaviors are `Refresh`, `Ignore`, and `Wait`. Default is `Wait`. + - `standby_instances` - (Optional) Behavior when encountering instances in the `Standby` state in are found. Available behaviors are `Terminate`, `Ignore`, and `Wait`. Default is `Wait`. - `triggers` - (Optional) Set of additional property names that will trigger an Instance Refresh. A refresh will always be triggered by a change in any of `launch_configuration`, `launch_template`, or `mixed_instances_policy`. ~> **NOTE:** A refresh is started when any of the following Auto Scaling Group properties change: `launch_configuration`, `launch_template`, `mixed_instances_policy`. Additional properties can be specified in the `triggers` property of `instance_refresh`. From dfceb8ccf40c0f33e9244aa55cb55a3569083215 Mon Sep 17 00:00:00 2001 From: Evan Cleary Date: Tue, 5 Sep 2023 12:43:43 -0400 Subject: [PATCH 2/3] Add changelog entry --- .changelog/33310.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changelog/33310.txt diff --git a/.changelog/33310.txt b/.changelog/33310.txt new file mode 100644 index 00000000000..473cf3fbf54 --- /dev/null +++ b/.changelog/33310.txt @@ -0,0 +1,7 @@ +```release-note:enhancement +resource/aws_autoscaling_group: Add `scale_in_protected_instances` attribute to `instance_refresh` preferences +``` + +```release-note:enhancement +resource/aws_autoscaling_group: Add `standby_instances` attribute to `instance_refresh` preferences +``` \ No newline at end of file From b2ae290e691e4a3ce66e0b542774ffe3eb316c76 Mon Sep 17 00:00:00 2001 From: Kit Ewbank Date: Tue, 5 Sep 2023 14:29:11 -0400 Subject: [PATCH 3/3] Tweak CHANGELOG entry. --- .changelog/33310.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.changelog/33310.txt b/.changelog/33310.txt index 473cf3fbf54..9f86339e308 100644 --- a/.changelog/33310.txt +++ b/.changelog/33310.txt @@ -1,7 +1,3 @@ ```release-note:enhancement -resource/aws_autoscaling_group: Add `scale_in_protected_instances` attribute to `instance_refresh` preferences -``` - -```release-note:enhancement -resource/aws_autoscaling_group: Add `standby_instances` attribute to `instance_refresh` preferences +resource/aws_autoscaling_group: Add `scale_in_protected_instances` and `standby_instances` attributes to `instance_refresh.preferences` configuration block ``` \ No newline at end of file