Skip to content

Commit

Permalink
Merge pull request #38942 from evan-cleary/f-aws_appautoscaling_targe…
Browse files Browse the repository at this point in the history
…t-suspended_state

r/aws_appautoscaling_target: Add suspended_state argument
  • Loading branch information
ewbankkit authored Aug 21, 2024
2 parents 87eefb3 + 9d4ff2c commit b0e9db4
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/38942.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_appautoscaling_target: Add `suspended_state` configuration block
```
77 changes: 77 additions & 0 deletions internal/service/appautoscaling/target.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,31 @@ func resourceTarget() *schema.Resource {
Required: true,
ForceNew: true,
},
"suspended_state": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"dynamic_scaling_in_suspended": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"dynamic_scaling_out_suspended": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
"scheduled_scaling_suspended": {
Type: schema.TypeBool,
Default: false,
Optional: true,
},
},
},
},
names.AttrTags: tftags.TagsSchema(),
names.AttrTagsAll: tftags.TagsSchemaComputed(),
},
Expand All @@ -100,6 +125,10 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
input.RoleARN = aws.String(v.(string))
}

if v, ok := d.GetOk("suspended_state"); ok {
input.SuspendedState = expandSuspendedState(v.([]interface{}))
}

err := registerScalableTarget(ctx, conn, input)

if err != nil {
Expand Down Expand Up @@ -141,6 +170,9 @@ func resourceTargetRead(ctx context.Context, d *schema.ResourceData, meta interf
d.Set(names.AttrRoleARN, t.RoleARN)
d.Set("scalable_dimension", t.ScalableDimension)
d.Set("service_namespace", t.ServiceNamespace)
if err := d.Set("suspended_state", flattenSuspendedState(t.SuspendedState)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting suspended_state: %s", err)
}

return diags
}
Expand All @@ -162,6 +194,10 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
input.RoleARN = aws.String(v.(string))
}

if v, ok := d.GetOk("suspended_state"); ok {
input.SuspendedState = expandSuspendedState(v.([]interface{}))
}

err := registerScalableTarget(ctx, conn, input)

if err != nil {
Expand Down Expand Up @@ -282,3 +318,44 @@ func registerScalableTarget(ctx context.Context, conn *applicationautoscaling.Cl

return err
}

func expandSuspendedState(tfList []interface{}) *awstypes.SuspendedState {
if len(tfList) == 0 || tfList[0] == nil {
return nil
}

apiObject := &awstypes.SuspendedState{}
tfMap := tfList[0].(map[string]interface{})

if v, ok := tfMap["dynamic_scaling_in_suspended"]; ok {
apiObject.DynamicScalingInSuspended = aws.Bool(v.(bool))
}
if v, ok := tfMap["dynamic_scaling_out_suspended"]; ok {
apiObject.DynamicScalingOutSuspended = aws.Bool(v.(bool))
}
if v, ok := tfMap["scheduled_scaling_suspended"]; ok {
apiObject.ScheduledScalingSuspended = aws.Bool(v.(bool))
}

return apiObject
}

func flattenSuspendedState(apiObject *awstypes.SuspendedState) []interface{} {
if apiObject == nil {
return []interface{}{}
}

tfMap := make(map[string]interface{})

if v := apiObject.DynamicScalingInSuspended; v != nil {
tfMap["dynamic_scaling_in_suspended"] = aws.ToBool(v)
}
if v := apiObject.DynamicScalingOutSuspended; v != nil {
tfMap["dynamic_scaling_out_suspended"] = aws.ToBool(v)
}
if v := apiObject.ScheduledScalingSuspended; v != nil {
tfMap["scheduled_scaling_suspended"] = aws.ToBool(v)
}

return []interface{}{tfMap}
}
169 changes: 169 additions & 0 deletions internal/service/appautoscaling/target_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,95 @@ func TestAccAppAutoScalingTarget_optionalRoleARN(t *testing.T) {
})
}

func TestAccAppAutoScalingTarget_suspendedState(t *testing.T) {
ctx := acctest.Context(t)
var readTarget awstypes.ScalableTarget
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_appautoscaling_target.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.AppAutoScalingServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckTargetDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccTargetConfig_suspendedState(rName, true, true, true),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetExists(ctx, resourceName, &readTarget),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_in_suspended", acctest.CtTrue),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_out_suspended", acctest.CtTrue),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.scheduled_scaling_suspended", acctest.CtTrue),
),
},
{
Config: testAccTargetConfig_suspendedStateDefault(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetExists(ctx, resourceName, &readTarget),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_in_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_out_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.scheduled_scaling_suspended", acctest.CtFalse),
),
},
},
})
}

func TestAccAppAutoScalingTarget_suspendedState_maintainsExisting(t *testing.T) {
ctx := acctest.Context(t)
var readTarget awstypes.ScalableTarget
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_appautoscaling_target.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.AppAutoScalingServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckTargetDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccTargetConfig_suspendedState(rName, false, false, true),
},
{
ResourceName: resourceName,
ImportState: true,
ImportStateVerify: true,
ImportStateIdFunc: testAccTargetImportStateIdFunc(resourceName),
},
{
Config: testAccTargetConfig_sansSuspendedState(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetExists(ctx, resourceName, &readTarget),
resource.TestCheckResourceAttr(resourceName, "suspended_state.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_in_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_out_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.scheduled_scaling_suspended", acctest.CtTrue),
),
},
{
Config: testAccTargetConfig_suspendedState(rName, false, true, false),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetExists(ctx, resourceName, &readTarget),
resource.TestCheckResourceAttr(resourceName, "suspended_state.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_in_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_out_suspended", acctest.CtTrue),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.scheduled_scaling_suspended", acctest.CtFalse),
),
},
{
Config: testAccTargetConfig_sansSuspendedState(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetExists(ctx, resourceName, &readTarget),
resource.TestCheckResourceAttr(resourceName, "suspended_state.#", acctest.Ct1),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_in_suspended", acctest.CtFalse),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.dynamic_scaling_out_suspended", acctest.CtTrue),
resource.TestCheckResourceAttr(resourceName, "suspended_state.0.scheduled_scaling_suspended", acctest.CtFalse),
),
},
},
})
}

func testAccCheckTargetDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).AppAutoScalingClient(ctx)
Expand Down Expand Up @@ -695,6 +784,86 @@ resource "aws_appautoscaling_target" "test" {
`, rName)
}

func testAccTargetConfig_suspendedState(rName string, dsis, dsos, sss bool) string {
return fmt.Sprintf(`
resource "aws_dynamodb_table" "test" {
name = %[1]q
read_capacity = 5
write_capacity = 5
hash_key = "TestKey"
attribute {
name = "TestKey"
type = "S"
}
}
resource "aws_appautoscaling_target" "test" {
service_namespace = "dynamodb"
resource_id = "table/${aws_dynamodb_table.test.name}"
scalable_dimension = "dynamodb:table:ReadCapacityUnits"
min_capacity = 2
max_capacity = 15
suspended_state {
dynamic_scaling_in_suspended = %[2]t
dynamic_scaling_out_suspended = %[3]t
scheduled_scaling_suspended = %[4]t
}
}
`, rName, dsis, dsos, sss)
}

func testAccTargetConfig_suspendedStateDefault(rName string) string {
return fmt.Sprintf(`
resource "aws_dynamodb_table" "test" {
name = %[1]q
read_capacity = 5
write_capacity = 5
hash_key = "TestKey"
attribute {
name = "TestKey"
type = "S"
}
}
resource "aws_appautoscaling_target" "test" {
service_namespace = "dynamodb"
resource_id = "table/${aws_dynamodb_table.test.name}"
scalable_dimension = "dynamodb:table:ReadCapacityUnits"
min_capacity = 2
max_capacity = 15
suspended_state {}
}
`, rName)
}

func testAccTargetConfig_sansSuspendedState(rName string) string {
return fmt.Sprintf(`
resource "aws_dynamodb_table" "test" {
name = %[1]q
read_capacity = 5
write_capacity = 5
hash_key = "TestKey"
attribute {
name = "TestKey"
type = "S"
}
}
resource "aws_appautoscaling_target" "test" {
service_namespace = "dynamodb"
resource_id = "table/${aws_dynamodb_table.test.name}"
scalable_dimension = "dynamodb:table:ReadCapacityUnits"
min_capacity = 2
max_capacity = 15
}
`, rName)
}

func testAccTargetImportStateIdFunc(resourceName string) resource.ImportStateIdFunc {
return func(s *terraform.State) (string, error) {
rs, ok := s.RootModule().Resources[resourceName]
Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/appautoscaling_target.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,17 @@ This resource supports the following arguments:
* `role_arn` - (Optional) ARN of the IAM role that allows Application AutoScaling to modify your scalable target on your behalf. This defaults to an IAM Service-Linked Role for most services and custom IAM Roles are ignored by the API for those namespaces. See the [AWS Application Auto Scaling documentation](https://docs.aws.amazon.com/autoscaling/application/userguide/security_iam_service-with-iam.html#security_iam_service-with-iam-roles) for more information about how this service interacts with IAM.
* `scalable_dimension` - (Required) Scalable dimension of the scalable target. Documentation can be found in the `ScalableDimension` parameter at: [AWS Application Auto Scaling API Reference](https://docs.aws.amazon.com/autoscaling/application/APIReference/API_RegisterScalableTarget.html#API_RegisterScalableTarget_RequestParameters)
* `service_namespace` - (Required) AWS service namespace of the scalable target. Documentation can be found in the `ServiceNamespace` parameter at: [AWS Application Auto Scaling API Reference](https://docs.aws.amazon.com/autoscaling/application/APIReference/API_RegisterScalableTarget.html#API_RegisterScalableTarget_RequestParameters)
* `suspended_state` - (Optional) Specifies whether the scaling activities for a scalable target are in a suspended state.
* `tags` - (Optional) Map of tags to assign to the scalable target. If configured with a provider [`default_tags` configuration block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs#default_tags-configuration-block) present, tags with matching keys will overwrite those defined at the provider-level.

### suspended_state

The `suspended_state` configuration block supports the following arguments:

* `dynamic_scaling_in_suspended` (Optional) Whether scale in by a target tracking scaling policy or a step scaling policy is suspended. Default is `false`.
* `dynamic_scaling_out_suspended` (Optional) Whether scale out by a target tracking scaling policy or a step scaling policy is suspended. Default is `false`.
* `scheduled_scaling_suspended` (Optional) Whether scheduled scaling is suspended. Default is `false`.

## Attribute Reference

This resource exports the following attributes in addition to the arguments above:
Expand Down

0 comments on commit b0e9db4

Please sign in to comment.