Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions internal/service/ecs/capacity_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,20 @@ func resourceCapacityProvider() *schema.Resource {
Optional: true,
ValidateDiagFunc: enum.Validate[awstypes.PropagateMITags](),
},
"infrastructure_optimization": {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"scale_in_after": {
Type: schema.TypeInt,
Optional: true,
ValidateFunc: validation.IntBetween(-1, 3600),
},
},
},
},
},
},
},
Expand Down Expand Up @@ -930,6 +944,10 @@ func expandManagedInstancesProviderCreate(configured any) *awstypes.CreateManage
apiObject.PropagateTags = awstypes.PropagateMITags(v)
}

if v, ok := tfMap["infrastructure_optimization"].([]any); ok && len(v) > 0 {
apiObject.InfrastructureOptimization = expandInfrastructureOptimization(v)
}

return apiObject
}

Expand Down Expand Up @@ -957,6 +975,25 @@ func expandManagedInstancesProviderUpdate(configured any) *awstypes.UpdateManage
apiObject.PropagateTags = awstypes.PropagateMITags(v)
}

if v, ok := tfMap["infrastructure_optimization"].([]any); ok && len(v) > 0 {
apiObject.InfrastructureOptimization = expandInfrastructureOptimization(v)
}

return apiObject
}

func expandInfrastructureOptimization(tfList []any) *awstypes.InfrastructureOptimization {
if len(tfList) == 0 || tfList[0] == nil {
return nil
}

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

if v, ok := tfMap["scale_in_after"].(int); ok {
apiObject.ScaleInAfter = aws.Int32(int32(v))
}

return apiObject
}

Expand Down Expand Up @@ -1348,6 +1385,22 @@ func flattenManagedInstancesProvider(provider *awstypes.ManagedInstancesProvider
tfMap["instance_launch_template"] = flattenInstanceLaunchTemplate(provider.InstanceLaunchTemplate)
}

if provider.InfrastructureOptimization != nil {
tfMap["infrastructure_optimization"] = flattenInfrastructureOptimization(provider.InfrastructureOptimization)
}

return []map[string]any{tfMap}
}

func flattenInfrastructureOptimization(apiObject *awstypes.InfrastructureOptimization) []map[string]any {
if apiObject == nil {
return nil
}

tfMap := map[string]any{
"scale_in_after": aws.ToInt32(apiObject.ScaleInAfter),
}

return []map[string]any{tfMap}
}

Expand Down
106 changes: 102 additions & 4 deletions internal/service/ecs/capacity_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,47 @@ func TestAccECSCapacityProvider_updateManagedInstancesProvider(t *testing.T) {
})
}

func TestAccECSCapacityProvider_createManagedInstancesProvider_withInfrastructureOptimization(t *testing.T) {
ctx := acctest.Context(t)
var provider awstypes.CapacityProvider
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_ecs_capacity_provider.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckCapacityProviderDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccCapacityProviderConfig_managedInstancesProvider_withInfrastructureOptimization(rName, 300),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckCapacityProviderExists(ctx, resourceName, &provider),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.#", "1"),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.#", "1"),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.0.scale_in_after", "300"),
),
},
{
Config: testAccCapacityProviderConfig_managedInstancesProvider_withInfrastructureOptimization(rName, 0),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckCapacityProviderExists(ctx, resourceName, &provider),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.#", "1"),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.0.scale_in_after", "0"),
),
},
{
Config: testAccCapacityProviderConfig_managedInstancesProvider_withInfrastructureOptimization(rName, -1),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckCapacityProviderExists(ctx, resourceName, &provider),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.#", "1"),
resource.TestCheckResourceAttr(resourceName, "managed_instances_provider.0.infrastructure_optimization.0.scale_in_after", "-1"),
),
},
},
})
}

func testAccCheckCapacityProviderDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).ECSClient(ctx)
Expand Down Expand Up @@ -705,6 +746,22 @@ resource "aws_subnet" "test" {
}
}

resource "aws_security_group" "test" {
name = %[1]q
vpc_id = aws_vpc.test.id

egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}

tags = {
Name = %[1]q
}
}

resource "aws_ecs_cluster" "test" {
name = %[1]q
}
Expand Down Expand Up @@ -771,7 +828,8 @@ resource "aws_ecs_capacity_provider" "test" {
ec2_instance_profile_arn = aws_iam_instance_profile.test.arn

network_configuration {
subnets = aws_subnet.test[*].id
subnets = aws_subnet.test[*].id
security_groups = [aws_security_group.test.id]
}
}
}
Expand All @@ -793,7 +851,8 @@ resource "aws_ecs_capacity_provider" "test" {
ec2_instance_profile_arn = aws_iam_instance_profile.test.arn

network_configuration {
subnets = aws_subnet.test[*].id
subnets = aws_subnet.test[*].id
security_groups = [aws_security_group.test.id]
}

instance_requirements {
Expand Down Expand Up @@ -831,7 +890,8 @@ resource "aws_ecs_capacity_provider" "test" {
ec2_instance_profile_arn = aws_iam_instance_profile.test.arn

network_configuration {
subnets = aws_subnet.test[*].id
subnets = aws_subnet.test[*].id
security_groups = [aws_security_group.test.id]
}

storage_configuration {
Expand Down Expand Up @@ -867,7 +927,8 @@ resource "aws_ecs_capacity_provider" "test" {
ec2_instance_profile_arn = aws_iam_instance_profile.test.arn

network_configuration {
subnets = aws_subnet.test[*].id
subnets = aws_subnet.test[*].id
security_groups = [aws_security_group.test.id]
}

instance_requirements {
Expand All @@ -884,3 +945,40 @@ resource "aws_ecs_capacity_provider" "test" {
}
`, rName))
}

func testAccCapacityProviderConfig_managedInstancesProvider_withInfrastructureOptimization(rName string, scaleInAfter int) string {
return acctest.ConfigCompose(testAccCapacityProviderConfig_managedInstancesProvider_base(rName), fmt.Sprintf(`
resource "aws_ecs_capacity_provider" "test" {
name = %[1]q
cluster = aws_ecs_cluster.test.name

managed_instances_provider {
infrastructure_role_arn = aws_iam_role.test.arn
propagate_tags = "NONE"

instance_launch_template {
ec2_instance_profile_arn = aws_iam_instance_profile.test.arn

network_configuration {
subnets = aws_subnet.test[*].id
security_groups = [aws_security_group.test.id]
}

instance_requirements {
vcpu_count {
min = 1
}

memory_mib {
min = 1024
}
}
}

infrastructure_optimization {
scale_in_after = %[2]d
}
}
}
`, rName, scaleInAfter))
}
8 changes: 8 additions & 0 deletions website/docs/r/ecs_capacity_provider.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ This resource supports the following arguments:
* `infrastructure_role_arn` - (Required) The Amazon Resource Name (ARN) of the infrastructure role that Amazon ECS uses to manage instances on your behalf. This role must have permissions to launch, terminate, and manage Amazon EC2 instances, as well as access to other AWS services required for Amazon ECS Managed Instances functionality. For more information, see [Amazon ECS infrastructure IAM role](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/infrastructure_IAM_role.html) in the Amazon ECS Developer Guide.
* `instance_launch_template` - (Required) The launch template configuration that specifies how Amazon ECS should launch Amazon EC2 instances. This includes the instance profile, network configuration, storage settings, and instance requirements for attribute-based instance type selection. For more information, see [Store instance launch parameters in Amazon EC2 launch templates](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-launch-templates.html) in the Amazon EC2 User Guide. Detailed below.
* `propagate_tags` - (Optional) Specifies whether to propagate tags from the capacity provider to the Amazon ECS Managed Instances. When enabled, tags applied to the capacity provider are automatically applied to all instances launched by this provider. Valid values are `CAPACITY_PROVIDER` and `NONE`.
* `infrastructure_optimization` - (Optional) Defines how Amazon ECS Managed Instances optimizes the infrastructure in your capacity provider. Configure it to turn on or off the infrastructure optimization in your capacity provider, and to control the idle EC2 instances optimization delay.

### `instance_launch_template`

Expand Down Expand Up @@ -167,6 +168,13 @@ This resource supports the following arguments:
* `total_local_storage_gb` - (Optional) The minimum and maximum total local storage in gigabytes (GB) for instance types with local storage.
* `vcpu_count` - (Required) The minimum and maximum number of vCPUs for the instance types. Amazon ECS selects instance types that have vCPU counts within this range.

### `infrastructure_optimization`

* `scale_in_after` - (Optional) This parameter defines the number of seconds Amazon ECS Managed Instances waits before optimizing EC2 instances that have become idle or underutilized. A longer delay increases the likelihood of placing new tasks on idle instances, reducing startup time. A shorter delay helps reduce infrastructure costs by optimizing idle instances more quickly. Valid values are:
* Not set (null) - Uses the default optimization behavior.
* `-1` - Disables automatic infrastructure optimization.
* `0` to `3600` (inclusive) - Specifies the number of seconds to wait before optimizing instances.

## Attribute Reference

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