Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aws_ecs_service: add tag_specification support #38662

Merged
3 changes: 3 additions & 0 deletions .changelog/38662.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_ecs_service: Add `volume_configuration.managed_ebs_volume.tag_specifications` attribute
```
68 changes: 63 additions & 5 deletions internal/service/ecs/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -1050,6 +1050,31 @@ func resourceService() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"tag_specifications": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
names.AttrResourceType: {
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: enum.Validate[awstypes.EBSResourceType](),
},
names.AttrPropagateTags: {
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
if awstypes.PropagateTags(old) == awstypes.PropagateTagsNone && new == "" {
return true
}
return false
},
ValidateDiagFunc: enum.Validate[awstypes.PropagateTags](),
},
names.AttrTags: tftags.TagsSchema(),
},
},
},
},
},
},
Expand Down Expand Up @@ -1202,7 +1227,7 @@ func resourceServiceCreate(ctx context.Context, d *schema.ResourceData, meta int
}

if v, ok := d.GetOk("volume_configuration"); ok && len(v.([]interface{})) > 0 {
input.VolumeConfigurations = expandVolumeConfigurations(v.([]interface{}))
input.VolumeConfigurations = expandVolumeConfigurations(ctx, v.([]interface{}))
}

output, err := retryServiceCreate(ctx, conn, input)
Expand Down Expand Up @@ -1486,7 +1511,7 @@ func resourceServiceUpdate(ctx context.Context, d *schema.ResourceData, meta int
}

if d.HasChange("volume_configuration") {
input.VolumeConfigurations = expandVolumeConfigurations(d.Get("volume_configuration").([]interface{}))
input.VolumeConfigurations = expandVolumeConfigurations(ctx, d.Get("volume_configuration").([]interface{}))
}

// Retry due to IAM eventual consistency.
Expand Down Expand Up @@ -2258,7 +2283,7 @@ func expandSecretOptions(sop []interface{}) []awstypes.Secret {
return out
}

func expandVolumeConfigurations(vc []interface{}) []awstypes.ServiceVolumeConfiguration {
func expandVolumeConfigurations(ctx context.Context, vc []interface{}) []awstypes.ServiceVolumeConfiguration {
if len(vc) == 0 {
return nil
}
Expand All @@ -2273,15 +2298,15 @@ func expandVolumeConfigurations(vc []interface{}) []awstypes.ServiceVolumeConfig
}

if v, ok := p["managed_ebs_volume"].([]interface{}); ok && len(v) > 0 {
config.ManagedEBSVolume = expandManagedEBSVolume(v)
config.ManagedEBSVolume = expandManagedEBSVolume(ctx, v)
}
vcs = append(vcs, config)
}

return vcs
}

func expandManagedEBSVolume(ebs []interface{}) *awstypes.ServiceManagedEBSVolumeConfiguration {
func expandManagedEBSVolume(ctx context.Context, ebs []interface{}) *awstypes.ServiceManagedEBSVolumeConfiguration {
if len(ebs) == 0 {
return &awstypes.ServiceManagedEBSVolumeConfiguration{}
}
Expand Down Expand Up @@ -2315,10 +2340,43 @@ func expandManagedEBSVolume(ebs []interface{}) *awstypes.ServiceManagedEBSVolume
if v, ok := raw[names.AttrVolumeType].(string); ok && v != "" {
config.VolumeType = aws.String(v)
}
if v, ok := raw["tag_specifications"].([]interface{}); ok && len(v) > 0 {
config.TagSpecifications = expandTagSpecifications(ctx, v)
}

return config
}

func expandTagSpecifications(ctx context.Context, ts []interface{}) []awstypes.EBSTagSpecification {
if len(ts) == 0 {
return []awstypes.EBSTagSpecification{}
}

var s []awstypes.EBSTagSpecification
for _, item := range ts {
raw, ok := item.(map[string]interface{})
if !ok {
continue
}

var config awstypes.EBSTagSpecification
if v, ok := raw[names.AttrResourceType].(string); ok && v != "" {
config.ResourceType = awstypes.EBSResourceType(v)
}
if v, ok := raw[names.AttrPropagateTags].(string); ok && v != "" {
config.PropagateTags = awstypes.PropagateTags(v)
}
if v, ok := raw[names.AttrTags].(map[string]any); ok && len(v) > 0 {
if v := tftags.New(ctx, v).IgnoreAWS(); len(v) > 0 {
config.Tags = Tags(v)
}
}
s = append(s, config)
}

return s
}

func expandServices(srv []interface{}) []awstypes.ServiceConnectService {
if len(srv) == 0 {
return nil
Expand Down
50 changes: 50 additions & 0 deletions internal/service/ecs/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,28 @@ func TestAccECSService_VolumeConfiguration_basic(t *testing.T) {
})
}

func TestAccECSService_VolumeConfiguration_tagSpecifications(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_volumeConfiguration_tagSpecifications(rName),
Check: resource.ComposeTestCheckFunc(
testAccCheckServiceExists(ctx, resourceName, &service),
),
},
},
})
}

func TestAccECSService_VolumeConfiguration_update(t *testing.T) {
ctx := acctest.Context(t)
var service awstypes.Service
Expand Down Expand Up @@ -2298,6 +2320,34 @@ resource "aws_ecs_service" "test" {
`, rName))
}

func testAccServiceConfig_volumeConfiguration_tagSpecifications(rName string) string {
return acctest.ConfigCompose(testAccServiceConfig_baseVolumeConfiguration(rName), fmt.Sprintf(`
resource "aws_ecs_service" "test" {
name = %[1]q
cluster = aws_ecs_cluster.test.id
task_definition = aws_ecs_task_definition.test.arn
desired_count = 1

volume_configuration {
name = "vol1"
managed_ebs_volume {
role_arn = aws_iam_role.ecs_service.arn
size_in_gb = "8"
tag_specifications {
resource_type = "volume"
propagate_tags = "SERVICE"
tags = {
Name = %[1]q
}
}
}
}

depends_on = [aws_iam_role_policy.ecs_service]
}
`, rName))
}

func testAccServiceConfig_volumeConfiguration_update(rName, volumeType string, size int) string {
return acctest.ConfigCompose(testAccServiceConfig_baseVolumeConfiguration(rName), fmt.Sprintf(`
resource "aws_ecs_service" "test" {
Expand Down
9 changes: 9 additions & 0 deletions website/docs/r/ecs_service.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ The `managed_ebs_volume` configuration block supports the following:
* `snapshot_id` - (Optional) Snapshot that Amazon ECS uses to create the volume. You must specify either a `size_in_gb` or a `snapshot_id`.
* `throughput` - (Optional) Throughput to provision for a volume, in MiB/s, with a maximum of 1,000 MiB/s.
* `volume_type` - (Optional) Volume type.
* `tag_specifications` - (Optional) The tags to apply to the volume. [See below](#tag_specifications).

### capacity_provider_strategy

Expand Down Expand Up @@ -318,6 +319,14 @@ For more information, see [Task Networking](https://docs.aws.amazon.com/AmazonEC
* `dns_name` - (Optional) Name that you use in the applications of client tasks to connect to this service.
* `port` - (Required) Listening port number for the Service Connect proxy. This port is available inside of all of the tasks within the same namespace.

### tag_specifications

`tag_specifications` supports the following:

* `resource_type` - (Required) The type of volume resource. Valid values, `volume`.
* `propagate_tags` - (Optional) Determines whether to propagate the tags from the task definition to the Amazon EBS volume.
* `tags` - (Optional) The tags applied to this Amazon EBS volume. `AmazonECSCreated` and `AmazonECSManaged` are reserved tags that can't be used.

## Attribute Reference

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