Skip to content

Commit

Permalink
Merge pull request #40225 from hashicorp/f-ecs_az_rebalancing
Browse files Browse the repository at this point in the history
r/aws_ecs_service: add `availability_zone_rebalancing` attribute
  • Loading branch information
johnsonaj authored Nov 21, 2024
2 parents 32bf7df + c535a80 commit d26cf72
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changelog/40225.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:enhancement
resource/aws_ecs_service: Add `availability_zone_rebalancing` attribute
```

```release-note:enhancement
data-source/aws_ecs_service: Add `availability_zone_rebalancing` attribute
```
17 changes: 17 additions & 0 deletions internal/service/ecs/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,12 @@ func resourceService() *schema.Resource {
},
},
},
"availability_zone_rebalancing": {
Type: schema.TypeString,
Optional: true,
Default: awstypes.AvailabilityZoneRebalancingDisabled,
ValidateDiagFunc: enum.Validate[awstypes.AvailabilityZoneRebalancing](),
},
names.AttrCapacityProviderStrategy: {
Type: schema.TypeSet,
Optional: true,
Expand Down Expand Up @@ -1178,6 +1184,10 @@ func resourceServiceCreate(ctx context.Context, d *schema.ResourceData, meta int
input.DeploymentConfiguration.Alarms = expandAlarms(v.([]interface{})[0].(map[string]interface{}))
}

if v, ok := d.GetOk("availability_zone_rebalancing"); ok {
input.AvailabilityZoneRebalancing = awstypes.AvailabilityZoneRebalancing(v.(string))
}

if v, ok := d.GetOk("cluster"); ok {
input.Cluster = aws.String(v.(string))
}
Expand Down Expand Up @@ -1317,6 +1327,7 @@ func resourceServiceRead(ctx context.Context, d *schema.ResourceData, meta inter
}

d.SetId(aws.ToString(service.ServiceArn))
d.Set("availability_zone_rebalancing", service.AvailabilityZoneRebalancing)
if err := d.Set(names.AttrCapacityProviderStrategy, flattenCapacityProviderStrategyItems(service.CapacityProviderStrategy)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting capacity_provider_strategy: %s", err)
}
Expand Down Expand Up @@ -1435,6 +1446,12 @@ func resourceServiceUpdate(ctx context.Context, d *schema.ResourceData, meta int
}
}

if d.HasChange("availability_zone_rebalancing") {
if v, ok := d.GetOk("availability_zone_rebalancing"); ok {
input.AvailabilityZoneRebalancing = awstypes.AvailabilityZoneRebalancing(v.(string))
}
}

if d.HasChange(names.AttrCapacityProviderStrategy) {
input.CapacityProviderStrategy = expandCapacityProviderStrategyItems(d.Get(names.AttrCapacityProviderStrategy).(*schema.Set))
}
Expand Down
5 changes: 5 additions & 0 deletions internal/service/ecs/service_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ func dataSourceService() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"availability_zone_rebalancing": {
Type: schema.TypeString,
Computed: true,
},
"cluster_arn": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -69,6 +73,7 @@ func dataSourceServiceRead(ctx context.Context, d *schema.ResourceData, meta int
arn := aws.ToString(service.ServiceArn)
d.SetId(arn)
d.Set(names.AttrARN, arn)
d.Set("availability_zone_rebalancing", service.AvailabilityZoneRebalancing)
d.Set("cluster_arn", service.ClusterArn)
d.Set("desired_count", service.DesiredCount)
d.Set("launch_type", service.LaunchType)
Expand Down
1 change: 1 addition & 0 deletions internal/service/ecs/service_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestAccECSServiceDataSource_basic(t *testing.T) {
Config: testAccServiceDataSourceConfig_basic(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, names.AttrID, dataSourceName, names.AttrARN),
resource.TestCheckResourceAttrPair(resourceName, "availability_zone_rebalancing", dataSourceName, "availability_zone_rebalancing"),
resource.TestCheckResourceAttrPair(resourceName, "desired_count", dataSourceName, "desired_count"),
resource.TestCheckResourceAttrPair(resourceName, "launch_type", dataSourceName, "launch_type"),
resource.TestCheckResourceAttrPair(resourceName, "scheduling_strategy", dataSourceName, "scheduling_strategy"),
Expand Down
107 changes: 107 additions & 0 deletions internal/service/ecs/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func TestAccECSService_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "alarms.#", "0"),
resource.TestCheckResourceAttr(resourceName, "service_registries.#", "0"),
resource.TestCheckResourceAttr(resourceName, "scheduling_strategy", "REPLICA"),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", "DISABLED"),
resource.TestCheckResourceAttr(resourceName, "vpc_lattice_configuration.#", "0"),
),
},
Expand All @@ -114,6 +115,7 @@ func TestAccECSService_basic(t *testing.T) {
resource.TestCheckResourceAttr(resourceName, "alarms.#", "0"),
resource.TestCheckResourceAttr(resourceName, "service_registries.#", "0"),
resource.TestCheckResourceAttr(resourceName, "scheduling_strategy", "REPLICA"),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", "DISABLED"),
resource.TestCheckResourceAttr(resourceName, "vpc_lattice_configuration.#", "0"),
),
},
Expand Down Expand Up @@ -1770,6 +1772,50 @@ func TestAccECSService_executeCommand(t *testing.T) {
})
}

func TestAccECSService_AvailabilityZoneRebalancing(t *testing.T) {
ctx := acctest.Context(t)
var service awstypes.Service
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
resourceName := "aws_ecs_service.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.ECSServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckServiceDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccServiceConfig_availabilityZoneRebalancing(rName, "ENABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists(ctx, resourceName, &service),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", string(awstypes.AvailabilityZoneRebalancingEnabled)),
),
},
{
Config: testAccServiceConfig_availabilityZoneRebalancing_nullUpdate(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists(ctx, resourceName, &service),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", string(awstypes.AvailabilityZoneRebalancingDisabled)),
),
},
{
Config: testAccServiceConfig_availabilityZoneRebalancing(rName, "DISABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists(ctx, resourceName, &service),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", string(awstypes.AvailabilityZoneRebalancingDisabled)),
),
},
{
Config: testAccServiceConfig_availabilityZoneRebalancing(rName, "ENABLED"),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists(ctx, resourceName, &service),
resource.TestCheckResourceAttr(resourceName, "availability_zone_rebalancing", string(awstypes.AvailabilityZoneRebalancingEnabled)),
),
},
},
})
}

func testAccCheckServiceDestroy(ctx context.Context) resource.TestCheckFunc {
return func(s *terraform.State) error {
conn := acctest.Provider.Meta().(*conns.AWSClient).ECSClient(ctx)
Expand Down Expand Up @@ -5448,3 +5494,64 @@ resource "aws_ecs_service" "test" {
}
`, rName)
}

func testAccServiceConfig_availabilityZoneRebalancing(rName string, serviceRebalancing string) string {
return fmt.Sprintf(`
resource "aws_ecs_cluster" "test" {
name = %[1]q
}
resource "aws_ecs_task_definition" "test" {
family = %[1]q
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "ghost:latest",
"memory": 128,
"name": "ghost"
}
]
DEFINITION
}
resource "aws_ecs_service" "test" {
name = %[1]q
cluster = aws_ecs_cluster.test.id
task_definition = aws_ecs_task_definition.test.arn
availability_zone_rebalancing = %[2]q
}
`, rName, serviceRebalancing)
}

func testAccServiceConfig_availabilityZoneRebalancing_nullUpdate(rName string) string {
return fmt.Sprintf(`
resource "aws_ecs_cluster" "test" {
name = %[1]q
}
resource "aws_ecs_task_definition" "test" {
family = %[1]q
container_definitions = <<DEFINITION
[
{
"cpu": 128,
"essential": true,
"image": "ghost:latest",
"memory": 128,
"name": "ghost"
}
]
DEFINITION
}
resource "aws_ecs_service" "test" {
name = %[1]q
cluster = aws_ecs_cluster.test.id
task_definition = aws_ecs_task_definition.test.arn
}
`, rName)
}
1 change: 1 addition & 0 deletions website/docs/r/ecs_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ The following arguments are required:
The following arguments are optional:

* `alarms` - (Optional) Information about the CloudWatch alarms. [See below](#alarms).
* `availability_zone_rebalancing` - (Optional) ECS automatically redistributes tasks within a service across Availability Zones (AZs) to mitigate the risk of impaired application availability due to underlying infrastructure failures and task lifecycle activities. The valid values are `ENABLED` and `DISABLED`. Defaults to `DISABLED`.
* `capacity_provider_strategy` - (Optional) Capacity provider strategies to use for the service. Can be one or more. These can be updated without destroying and recreating the service only if `force_new_deployment = true` and not changing from 0 `capacity_provider_strategy` blocks to greater than 0, or vice versa. See below. Conflicts with `launch_type`.
* `cluster` - (Optional) ARN of an ECS cluster.
* `deployment_circuit_breaker` - (Optional) Configuration block for deployment circuit breaker. See below.
Expand Down

0 comments on commit d26cf72

Please sign in to comment.