diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2b99ca2..40fd8ea 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/antonbabenko/pre-commit-terraform - rev: v1.103.0 + rev: v1.104.0 hooks: - id: terraform_wrapper_module_for_each - id: terraform_fmt diff --git a/CHANGELOG.md b/CHANGELOG.md index 87d5aa7..f75347b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. +## [6.10.0](https://github.com/terraform-aws-modules/terraform-aws-ecs/compare/v6.9.0...v6.10.0) (2025-11-21) + +### Features + +* Add support of suspended_state block in aws_appautoscaling_target of ECS service ([#373](https://github.com/terraform-aws-modules/terraform-aws-ecs/issues/373)) ([ba34aa7](https://github.com/terraform-aws-modules/terraform-aws-ecs/commit/ba34aa700994c00dae2bf56c140331a5c6f80d7c)) + +## [6.9.0](https://github.com/terraform-aws-modules/terraform-aws-ecs/compare/v6.8.0...v6.9.0) (2025-11-17) + +### Features + +* Add support for CANARY/LINEAR deployment configuration ([#370](https://github.com/terraform-aws-modules/terraform-aws-ecs/issues/370)) ([32a563e](https://github.com/terraform-aws-modules/terraform-aws-ecs/commit/32a563e552831413bee7a0c23b125022bfeb96d9)) + +## [6.8.0](https://github.com/terraform-aws-modules/terraform-aws-ecs/compare/v6.7.0...v6.8.0) (2025-11-13) + +### Features + +* Add support for `credentialSpecs` on container definition to enable Windows gMSA ([#368](https://github.com/terraform-aws-modules/terraform-aws-ecs/issues/368)) ([654d7d2](https://github.com/terraform-aws-modules/terraform-aws-ecs/commit/654d7d2b85d5c5a044bfb8526910f09aef2f54bf)) + ## [6.7.0](https://github.com/terraform-aws-modules/terraform-aws-ecs/compare/v6.6.2...v6.7.0) (2025-10-22) ### Features diff --git a/README.md b/README.md index 9aba8c9..48487cf 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,7 @@ module "ecs" { | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.5.7 | -| [aws](#requirement\_aws) | >= 6.14 | +| [aws](#requirement\_aws) | >= 6.21 | ## Providers @@ -194,7 +194,7 @@ No resources. | [create\_task\_exec\_policy](#input\_create\_task\_exec\_policy) | Determines whether the ECS task definition IAM policy should be created. This includes permissions included in AmazonECSTaskExecutionRolePolicy as well as access to secrets and SSM parameters | `bool` | `true` | no | | [default\_capacity\_provider\_strategy](#input\_default\_capacity\_provider\_strategy) | Map of default capacity provider strategy definitions to use for the cluster |
map(object({
base = optional(number)
name = optional(string) # Will fall back to use map key if not set
weight = optional(number)
})) | `null` | no |
| [region](#input\_region) | Region where the resource(s) will be managed. Defaults to the Region set in the provider configuration | `string` | `null` | no |
-| [services](#input\_services) | Map of service definitions to create | map(object({
create = optional(bool)
create_service = optional(bool)
tags = optional(map(string))
# Service
ignore_task_definition_changes = optional(bool)
alarms = optional(object({
alarm_names = list(string)
enable = optional(bool)
rollback = optional(bool)
}))
availability_zone_rebalancing = optional(string)
capacity_provider_strategy = optional(map(object({
base = optional(number)
capacity_provider = string
weight = optional(number)
})))
deployment_circuit_breaker = optional(object({
enable = bool
rollback = bool
}))
deployment_configuration = optional(object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
lifecycle_stages = list(string)
hook_details = optional(string)
})))
}))
deployment_controller = optional(object({
type = optional(string)
}))
deployment_maximum_percent = optional(number, 200)
deployment_minimum_healthy_percent = optional(number, 66)
desired_count = optional(number, 1)
enable_ecs_managed_tags = optional(bool)
enable_execute_command = optional(bool)
force_delete = optional(bool)
force_new_deployment = optional(bool)
health_check_grace_period_seconds = optional(number)
launch_type = optional(string)
load_balancer = optional(map(object({
container_name = string
container_port = number
elb_name = optional(string)
target_group_arn = optional(string)
advanced_configuration = optional(object({
alternate_target_group_arn = string
production_listener_rule = string
role_arn = string
test_listener_rule = optional(string)
}))
})))
name = optional(string) # Will fall back to use map key if not set
assign_public_ip = optional(bool)
security_group_ids = optional(list(string))
subnet_ids = optional(list(string))
ordered_placement_strategy = optional(map(object({
field = optional(string)
type = string
})))
placement_constraints = optional(map(object({
expression = optional(string)
type = string
})))
platform_version = optional(string)
propagate_tags = optional(string)
scheduling_strategy = optional(string)
service_connect_configuration = optional(object({
enabled = optional(bool)
log_configuration = optional(object({
log_driver = string
options = optional(map(string))
secret_option = optional(list(object({
name = string
value_from = string
})))
}))
namespace = optional(string)
service = optional(list(object({
client_alias = optional(object({
dns_name = optional(string)
port = number
test_traffic_rules = optional(list(object({
header = optional(object({
name = string
value = object({
exact = string
})
}))
})))
}))
discovery_name = optional(string)
ingress_port_override = optional(number)
port_name = string
timeout = optional(object({
idle_timeout_seconds = optional(number)
per_request_timeout_seconds = optional(number)
}))
tls = optional(object({
issuer_cert_authority = object({
aws_pca_authority_arn = string
})
kms_key = optional(string)
role_arn = optional(string)
}))
})))
}))
service_registries = optional(object({
container_name = optional(string)
container_port = optional(number)
port = optional(number)
registry_arn = string
}))
sigint_rollback = optional(bool)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
triggers = optional(map(string))
volume_configuration = optional(object({
name = string
managed_ebs_volume = object({
encrypted = optional(bool)
file_system_type = optional(string)
iops = optional(number)
kms_key_id = optional(string)
size_in_gb = optional(number)
snapshot_id = optional(string)
tag_specifications = optional(list(object({
propagate_tags = optional(string)
resource_type = string
tags = optional(map(string))
})))
throughput = optional(number)
volume_type = optional(string)
})
}))
vpc_lattice_configurations = optional(object({
role_arn = string
target_group_arn = string
port_name = string
}))
wait_for_steady_state = optional(bool)
service_tags = optional(map(string))
# Service - IAM Role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Task Definition
create_task_definition = optional(bool)
task_definition_arn = optional(string)
container_definitions = optional(map(object({
operating_system_family = optional(string)
tags = optional(map(string))
# Container definition
command = optional(list(string))
cpu = optional(number)
dependsOn = optional(list(object({
condition = string
containerName = string
})))
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
enable_execute_command = optional(bool)
entrypoint = optional(list(string))
environment = optional(list(object({
name = string
value = string
})))
environmentFiles = optional(list(object({
type = string
value = string
})))
essential = optional(bool)
extraHosts = optional(list(object({
hostname = string
ipAddress = string
})))
firelensConfiguration = optional(object({
options = optional(map(string))
type = optional(string)
}))
healthCheck = optional(object({
command = optional(list(string))
interval = optional(number)
retries = optional(number)
startPeriod = optional(number)
timeout = optional(number)
}))
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(object({
capabilities = optional(object({
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(list(object({
containerPath = optional(string)
hostPath = optional(string)
permissions = optional(list(string))
})))
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(list(object({
containerPath = string
mountOptions = optional(list(string))
size = number
})))
}))
logConfiguration = optional(object({
logDriver = optional(string)
options = optional(map(string))
secretOptions = optional(list(object({
name = string
valueFrom = string
})))
}))
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(list(object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})), [])
name = optional(string)
portMappings = optional(list(object({
appProtocol = optional(string)
containerPort = optional(number)
containerPortRange = optional(string)
hostPort = optional(number)
name = optional(string)
protocol = optional(string)
})), [])
privileged = optional(bool)
pseudoTerminal = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(object({
credentialsParameter = optional(string)
}))
resourceRequirements = optional(list(object({
type = string
value = string
})))
restartPolicy = optional(object({
enabled = optional(bool)
ignoredExitCodes = optional(list(number))
restartAttemptPeriod = optional(number)
}))
secrets = optional(list(object({
name = string
valueFrom = string
})))
startTimeout = optional(number)
stopTimeout = optional(number)
systemControls = optional(list(object({
namespace = optional(string)
value = optional(string)
})))
ulimits = optional(list(object({
hardLimit = number
name = string
softLimit = number
})))
user = optional(string)
versionConsistency = optional(string)
volumesFrom = optional(list(object({
readOnly = optional(bool)
sourceContainer = optional(string)
})))
workingDirectory = optional(string)
# Cloudwatch Log Group
service = optional(string, "")
enable_cloudwatch_logging = optional(bool)
create_cloudwatch_log_group = optional(bool)
cloudwatch_log_group_name = optional(string)
cloudwatch_log_group_use_name_prefix = optional(bool)
cloudwatch_log_group_class = optional(string)
cloudwatch_log_group_retention_in_days = optional(number)
cloudwatch_log_group_kms_key_id = optional(string)
})))
cpu = optional(number, 1024)
enable_fault_injection = optional(bool)
ephemeral_storage = optional(object({
size_in_gib = number
}))
family = optional(string)
ipc_mode = optional(string)
memory = optional(number, 2048)
network_mode = optional(string)
pid_mode = optional(string)
proxy_configuration = optional(object({
container_name = string
properties = optional(map(string))
type = optional(string)
}))
requires_compatibilities = optional(list(string))
runtime_platform = optional(object({
cpu_architecture = optional(string)
operating_system_family = optional(string)
}))
skip_destroy = optional(bool)
task_definition_placement_constraints = optional(map(object({
expression = optional(string)
type = string
})))
track_latest = optional(bool)
volume = optional(map(object({
configure_at_launch = optional(bool)
docker_volume_configuration = optional(object({
autoprovision = optional(bool)
driver = optional(string)
driver_opts = optional(map(string))
labels = optional(map(string))
scope = optional(string)
}))
efs_volume_configuration = optional(object({
authorization_config = optional(object({
access_point_id = optional(string)
iam = optional(string)
}))
file_system_id = string
root_directory = optional(string)
transit_encryption = optional(string)
transit_encryption_port = optional(number)
}))
fsx_windows_file_server_volume_configuration = optional(object({
authorization_config = optional(object({
credentials_parameter = string
domain = string
}))
file_system_id = string
root_directory = string
}))
host_path = optional(string)
name = optional(string)
})))
task_tags = optional(map(string))
# Task Execution - IAM Role
create_task_exec_iam_role = optional(bool)
task_exec_iam_role_arn = optional(string)
task_exec_iam_role_name = optional(string)
task_exec_iam_role_use_name_prefix = optional(bool)
task_exec_iam_role_path = optional(string)
task_exec_iam_role_description = optional(string)
task_exec_iam_role_permissions_boundary = optional(string)
task_exec_iam_role_tags = optional(map(string))
task_exec_iam_role_policies = optional(map(string))
task_exec_iam_role_max_session_duration = optional(number)
create_task_exec_policy = optional(bool)
task_exec_ssm_param_arns = optional(list(string))
task_exec_secret_arns = optional(list(string))
task_exec_iam_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
task_exec_iam_policy_path = optional(string)
# Tasks - IAM Role
create_tasks_iam_role = optional(bool)
tasks_iam_role_arn = optional(string)
tasks_iam_role_name = optional(string)
tasks_iam_role_use_name_prefix = optional(bool)
tasks_iam_role_path = optional(string)
tasks_iam_role_description = optional(string)
tasks_iam_role_permissions_boundary = optional(string)
tasks_iam_role_tags = optional(map(string))
tasks_iam_role_policies = optional(map(string))
tasks_iam_role_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Task Set
external_id = optional(string)
scale = optional(object({
unit = optional(string)
value = optional(number)
}))
wait_until_stable = optional(bool)
wait_until_stable_timeout = optional(string)
# Autoscaling
enable_autoscaling = optional(bool)
autoscaling_min_capacity = optional(number)
autoscaling_max_capacity = optional(number)
autoscaling_policies = optional(map(object({
name = optional(string) # Will fall back to the key name if not provided
policy_type = optional(string)
predictive_scaling_policy_configuration = optional(object({
max_capacity_breach_behavior = optional(string)
max_capacity_buffer = optional(number)
metric_specification = list(object({
customized_capacity_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_load_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_scaling_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
predefined_load_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_metric_pair_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_scaling_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
target_value = number
}))
mode = optional(string)
scheduling_buffer_time = optional(number)
}))
step_scaling_policy_configuration = optional(object({
adjustment_type = optional(string)
cooldown = optional(number)
metric_aggregation_type = optional(string)
min_adjustment_magnitude = optional(number)
step_adjustment = optional(list(object({
metric_interval_lower_bound = optional(string)
metric_interval_upper_bound = optional(string)
scaling_adjustment = number
})))
}))
target_tracking_scaling_policy_configuration = optional(object({
customized_metric_specification = optional(object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
metrics = optional(list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = string
namespace = string
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
})))
namespace = optional(string)
statistic = optional(string)
unit = optional(string)
}))
disable_scale_in = optional(bool)
predefined_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
scale_in_cooldown = optional(number)
scale_out_cooldown = optional(number)
target_value = optional(number)
}))
})))
autoscaling_scheduled_actions = optional(map(object({
name = optional(string)
min_capacity = number
max_capacity = number
schedule = string
start_time = optional(string)
end_time = optional(string)
timezone = optional(string)
})))
# Security Group
create_security_group = optional(bool)
vpc_id = optional(string)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))
# ECS Infrastructure IAM Role
create_infrastructure_iam_role = optional(bool)
infrastructure_iam_role_arn = optional(string)
infrastructure_iam_role_name = optional(string)
infrastructure_iam_role_use_name_prefix = optional(bool)
infrastructure_iam_role_path = optional(string)
infrastructure_iam_role_description = optional(string)
infrastructure_iam_role_permissions_boundary = optional(string)
infrastructure_iam_role_tags = optional(map(string))
})) | `null` | no |
+| [services](#input\_services) | Map of service definitions to create | map(object({
create = optional(bool)
create_service = optional(bool)
tags = optional(map(string))
# Service
ignore_task_definition_changes = optional(bool)
alarms = optional(object({
alarm_names = list(string)
enable = optional(bool)
rollback = optional(bool)
}))
availability_zone_rebalancing = optional(string)
capacity_provider_strategy = optional(map(object({
base = optional(number)
capacity_provider = string
weight = optional(number)
})))
deployment_circuit_breaker = optional(object({
enable = bool
rollback = bool
}))
deployment_configuration = optional(object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
canary_configuration = optional(object({
canary_bake_time_in_minutes = optional(string)
canary_percent = optional(string)
}))
linear_configuration = optional(object({
step_bake_time_in_minutes = optional(string)
step_percent = optional(string)
}))
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
lifecycle_stages = list(string)
hook_details = optional(string)
})))
}))
deployment_controller = optional(object({
type = optional(string)
}))
deployment_maximum_percent = optional(number, 200)
deployment_minimum_healthy_percent = optional(number, 66)
desired_count = optional(number, 1)
enable_ecs_managed_tags = optional(bool)
enable_execute_command = optional(bool)
force_delete = optional(bool)
force_new_deployment = optional(bool)
health_check_grace_period_seconds = optional(number)
launch_type = optional(string)
load_balancer = optional(map(object({
container_name = string
container_port = number
elb_name = optional(string)
target_group_arn = optional(string)
advanced_configuration = optional(object({
alternate_target_group_arn = string
production_listener_rule = string
role_arn = string
test_listener_rule = optional(string)
}))
})))
name = optional(string) # Will fall back to use map key if not set
assign_public_ip = optional(bool)
security_group_ids = optional(list(string))
subnet_ids = optional(list(string))
ordered_placement_strategy = optional(map(object({
field = optional(string)
type = string
})))
placement_constraints = optional(map(object({
expression = optional(string)
type = string
})))
platform_version = optional(string)
propagate_tags = optional(string)
scheduling_strategy = optional(string)
service_connect_configuration = optional(object({
enabled = optional(bool)
log_configuration = optional(object({
log_driver = string
options = optional(map(string))
secret_option = optional(list(object({
name = string
value_from = string
})))
}))
namespace = optional(string)
service = optional(list(object({
client_alias = optional(object({
dns_name = optional(string)
port = number
test_traffic_rules = optional(list(object({
header = optional(object({
name = string
value = object({
exact = string
})
}))
})))
}))
discovery_name = optional(string)
ingress_port_override = optional(number)
port_name = string
timeout = optional(object({
idle_timeout_seconds = optional(number)
per_request_timeout_seconds = optional(number)
}))
tls = optional(object({
issuer_cert_authority = object({
aws_pca_authority_arn = string
})
kms_key = optional(string)
role_arn = optional(string)
}))
})))
}))
service_registries = optional(object({
container_name = optional(string)
container_port = optional(number)
port = optional(number)
registry_arn = string
}))
sigint_rollback = optional(bool)
timeouts = optional(object({
create = optional(string)
update = optional(string)
delete = optional(string)
}))
triggers = optional(map(string))
volume_configuration = optional(object({
name = string
managed_ebs_volume = object({
encrypted = optional(bool)
file_system_type = optional(string)
iops = optional(number)
kms_key_id = optional(string)
size_in_gb = optional(number)
snapshot_id = optional(string)
tag_specifications = optional(list(object({
propagate_tags = optional(string)
resource_type = string
tags = optional(map(string))
})))
throughput = optional(number)
volume_type = optional(string)
})
}))
vpc_lattice_configurations = optional(object({
role_arn = string
target_group_arn = string
port_name = string
}))
wait_for_steady_state = optional(bool)
service_tags = optional(map(string))
# Service - IAM Role
create_iam_role = optional(bool)
iam_role_arn = optional(string)
iam_role_name = optional(string)
iam_role_use_name_prefix = optional(bool)
iam_role_path = optional(string)
iam_role_description = optional(string)
iam_role_permissions_boundary = optional(string)
iam_role_tags = optional(map(string))
iam_role_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Task Definition
create_task_definition = optional(bool)
task_definition_arn = optional(string)
container_definitions = optional(map(object({
operating_system_family = optional(string)
tags = optional(map(string))
# Container definition
command = optional(list(string))
cpu = optional(number)
credentialSpecs = optional(list(string))
dependsOn = optional(list(object({
condition = string
containerName = string
})))
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
enable_execute_command = optional(bool)
entrypoint = optional(list(string))
environment = optional(list(object({
name = string
value = string
})))
environmentFiles = optional(list(object({
type = string
value = string
})))
essential = optional(bool)
extraHosts = optional(list(object({
hostname = string
ipAddress = string
})))
firelensConfiguration = optional(object({
options = optional(map(string))
type = optional(string)
}))
healthCheck = optional(object({
command = optional(list(string))
interval = optional(number)
retries = optional(number)
startPeriod = optional(number)
timeout = optional(number)
}))
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(object({
capabilities = optional(object({
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(list(object({
containerPath = optional(string)
hostPath = optional(string)
permissions = optional(list(string))
})))
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(list(object({
containerPath = string
mountOptions = optional(list(string))
size = number
})))
}))
logConfiguration = optional(object({
logDriver = optional(string)
options = optional(map(string))
secretOptions = optional(list(object({
name = string
valueFrom = string
})))
}))
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(list(object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})), [])
name = optional(string)
portMappings = optional(list(object({
appProtocol = optional(string)
containerPort = optional(number)
containerPortRange = optional(string)
hostPort = optional(number)
name = optional(string)
protocol = optional(string)
})), [])
privileged = optional(bool)
pseudoTerminal = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(object({
credentialsParameter = optional(string)
}))
resourceRequirements = optional(list(object({
type = string
value = string
})))
restartPolicy = optional(object({
enabled = optional(bool)
ignoredExitCodes = optional(list(number))
restartAttemptPeriod = optional(number)
}))
secrets = optional(list(object({
name = string
valueFrom = string
})))
startTimeout = optional(number)
stopTimeout = optional(number)
systemControls = optional(list(object({
namespace = optional(string)
value = optional(string)
})))
ulimits = optional(list(object({
hardLimit = number
name = string
softLimit = number
})))
user = optional(string)
versionConsistency = optional(string)
volumesFrom = optional(list(object({
readOnly = optional(bool)
sourceContainer = optional(string)
})))
workingDirectory = optional(string)
# Cloudwatch Log Group
service = optional(string, "")
enable_cloudwatch_logging = optional(bool)
create_cloudwatch_log_group = optional(bool)
cloudwatch_log_group_name = optional(string)
cloudwatch_log_group_use_name_prefix = optional(bool)
cloudwatch_log_group_class = optional(string)
cloudwatch_log_group_retention_in_days = optional(number)
cloudwatch_log_group_kms_key_id = optional(string)
})))
cpu = optional(number, 1024)
enable_fault_injection = optional(bool)
ephemeral_storage = optional(object({
size_in_gib = number
}))
family = optional(string)
ipc_mode = optional(string)
memory = optional(number, 2048)
network_mode = optional(string)
pid_mode = optional(string)
proxy_configuration = optional(object({
container_name = string
properties = optional(map(string))
type = optional(string)
}))
requires_compatibilities = optional(list(string))
runtime_platform = optional(object({
cpu_architecture = optional(string)
operating_system_family = optional(string)
}))
skip_destroy = optional(bool)
task_definition_placement_constraints = optional(map(object({
expression = optional(string)
type = string
})))
track_latest = optional(bool)
volume = optional(map(object({
configure_at_launch = optional(bool)
docker_volume_configuration = optional(object({
autoprovision = optional(bool)
driver = optional(string)
driver_opts = optional(map(string))
labels = optional(map(string))
scope = optional(string)
}))
efs_volume_configuration = optional(object({
authorization_config = optional(object({
access_point_id = optional(string)
iam = optional(string)
}))
file_system_id = string
root_directory = optional(string)
transit_encryption = optional(string)
transit_encryption_port = optional(number)
}))
fsx_windows_file_server_volume_configuration = optional(object({
authorization_config = optional(object({
credentials_parameter = string
domain = string
}))
file_system_id = string
root_directory = string
}))
host_path = optional(string)
name = optional(string)
})))
task_tags = optional(map(string))
# Task Execution - IAM Role
create_task_exec_iam_role = optional(bool)
task_exec_iam_role_arn = optional(string)
task_exec_iam_role_name = optional(string)
task_exec_iam_role_use_name_prefix = optional(bool)
task_exec_iam_role_path = optional(string)
task_exec_iam_role_description = optional(string)
task_exec_iam_role_permissions_boundary = optional(string)
task_exec_iam_role_tags = optional(map(string))
task_exec_iam_role_policies = optional(map(string))
task_exec_iam_role_max_session_duration = optional(number)
create_task_exec_policy = optional(bool)
task_exec_ssm_param_arns = optional(list(string))
task_exec_secret_arns = optional(list(string))
task_exec_iam_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
task_exec_iam_policy_path = optional(string)
# Tasks - IAM Role
create_tasks_iam_role = optional(bool)
tasks_iam_role_arn = optional(string)
tasks_iam_role_name = optional(string)
tasks_iam_role_use_name_prefix = optional(bool)
tasks_iam_role_path = optional(string)
tasks_iam_role_description = optional(string)
tasks_iam_role_permissions_boundary = optional(string)
tasks_iam_role_tags = optional(map(string))
tasks_iam_role_policies = optional(map(string))
tasks_iam_role_statements = optional(list(object({
sid = optional(string)
actions = optional(list(string))
not_actions = optional(list(string))
effect = optional(string)
resources = optional(list(string))
not_resources = optional(list(string))
principals = optional(list(object({
type = string
identifiers = list(string)
})))
not_principals = optional(list(object({
type = string
identifiers = list(string)
})))
condition = optional(list(object({
test = string
values = list(string)
variable = string
})))
})))
# Task Set
external_id = optional(string)
scale = optional(object({
unit = optional(string)
value = optional(number)
}))
wait_until_stable = optional(bool)
wait_until_stable_timeout = optional(string)
# Autoscaling
enable_autoscaling = optional(bool)
autoscaling_min_capacity = optional(number)
autoscaling_max_capacity = optional(number)
autoscaling_policies = optional(map(object({
name = optional(string) # Will fall back to the key name if not provided
policy_type = optional(string)
predictive_scaling_policy_configuration = optional(object({
max_capacity_breach_behavior = optional(string)
max_capacity_buffer = optional(number)
metric_specification = list(object({
customized_capacity_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_load_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_scaling_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
predefined_load_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_metric_pair_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_scaling_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
target_value = number
}))
mode = optional(string)
scheduling_buffer_time = optional(number)
}))
step_scaling_policy_configuration = optional(object({
adjustment_type = optional(string)
cooldown = optional(number)
metric_aggregation_type = optional(string)
min_adjustment_magnitude = optional(number)
step_adjustment = optional(list(object({
metric_interval_lower_bound = optional(string)
metric_interval_upper_bound = optional(string)
scaling_adjustment = number
})))
}))
target_tracking_scaling_policy_configuration = optional(object({
customized_metric_specification = optional(object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
metrics = optional(list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = string
namespace = string
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
})))
namespace = optional(string)
statistic = optional(string)
unit = optional(string)
}))
disable_scale_in = optional(bool)
predefined_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
scale_in_cooldown = optional(number)
scale_out_cooldown = optional(number)
target_value = optional(number)
}))
})))
autoscaling_scheduled_actions = optional(map(object({
name = optional(string)
min_capacity = number
max_capacity = number
schedule = string
start_time = optional(string)
end_time = optional(string)
timezone = optional(string)
})))
autoscaling_suspended_state = optional(object({
dynamic_scaling_in_suspended = optional(bool)
dynamic_scaling_out_suspended = optional(bool)
scheduled_scaling_suspended = optional(bool)
}))
# Security Group
create_security_group = optional(bool)
vpc_id = optional(string)
security_group_name = optional(string)
security_group_use_name_prefix = optional(bool)
security_group_description = optional(string)
security_group_ingress_rules = optional(map(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_egress_rules = optional(map(object({
cidr_ipv4 = optional(string)
cidr_ipv6 = optional(string)
description = optional(string)
from_port = optional(string)
ip_protocol = optional(string)
prefix_list_id = optional(string)
referenced_security_group_id = optional(string)
tags = optional(map(string))
to_port = optional(string)
})))
security_group_tags = optional(map(string))
# ECS Infrastructure IAM Role
create_infrastructure_iam_role = optional(bool)
infrastructure_iam_role_arn = optional(string)
infrastructure_iam_role_name = optional(string)
infrastructure_iam_role_use_name_prefix = optional(bool)
infrastructure_iam_role_path = optional(string)
infrastructure_iam_role_description = optional(string)
infrastructure_iam_role_permissions_boundary = optional(string)
infrastructure_iam_role_tags = optional(map(string))
})) | `null` | no |
| [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
| [task\_exec\_iam\_role\_description](#input\_task\_exec\_iam\_role\_description) | Description of the role | `string` | `null` | no |
| [task\_exec\_iam\_role\_name](#input\_task\_exec\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no |
diff --git a/examples/complete/README.md b/examples/complete/README.md
index 2477a11..1d96ae7 100644
--- a/examples/complete/README.md
+++ b/examples/complete/README.md
@@ -27,13 +27,13 @@ Note that this example may create resources which will incur monetary charges on
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
diff --git a/examples/complete/main.tf b/examples/complete/main.tf
index e37992c..a3aa3bf 100644
--- a/examples/complete/main.tf
+++ b/examples/complete/main.tf
@@ -179,6 +179,16 @@ module "ecs" {
}
}
+ # Linear deployment
+ deployment_configuration = {
+ strategy = "LINEAR"
+
+ linear_configuration = {
+ step_percent = 20
+ step_bake_time_in_minutes = 1
+ }
+ }
+
service_connect_configuration = {
namespace = aws_service_discovery_http_namespace.this.arn
service = [
diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf
index 0e90b8c..70f23a4 100644
--- a/examples/complete/versions.tf
+++ b/examples/complete/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/examples/container-definition/README.md b/examples/container-definition/README.md
index 3407b50..bfa6280 100644
--- a/examples/container-definition/README.md
+++ b/examples/container-definition/README.md
@@ -22,7 +22,7 @@ Note that this example may create resources which will incur monetary charges on
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
| [null](#requirement\_null) | >= 3.2 |
## Providers
diff --git a/examples/container-definition/versions.tf b/examples/container-definition/versions.tf
index 5c1a2c3..42207f1 100644
--- a/examples/container-definition/versions.tf
+++ b/examples/container-definition/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
null = {
source = "hashicorp/null"
diff --git a/examples/ec2-autoscaling/README.md b/examples/ec2-autoscaling/README.md
index 62a19dc..a440d1b 100644
--- a/examples/ec2-autoscaling/README.md
+++ b/examples/ec2-autoscaling/README.md
@@ -27,13 +27,13 @@ Note that this example may create resources which will incur monetary charges on
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
diff --git a/examples/ec2-autoscaling/main.tf b/examples/ec2-autoscaling/main.tf
index 5cbe9bb..bc424ea 100644
--- a/examples/ec2-autoscaling/main.tf
+++ b/examples/ec2-autoscaling/main.tf
@@ -84,6 +84,31 @@ module "ecs_service" {
name = local.name
cluster_arn = module.ecs_cluster.arn
+ # Canary deployment
+ deployment_configuration = {
+ strategy = "CANARY"
+
+ canary_configuration = {
+ canary_percent = 10.0
+ canary_bake_time_in_minutes = 5
+ }
+
+ # # Example config using lifecycle hooks
+ # lifecycle_hook = {
+ # success = {
+ # hook_target_arn = aws_lambda_function.hook_success.arn
+ # role_arn = aws_iam_role.global.arn
+ # lifecycle_stages = ["POST_SCALE_UP", "POST_TEST_TRAFFIC_SHIFT"]
+ # hook_details = jsonencode("test")
+ # }
+ # failure = {
+ # hook_target_arn = aws_lambda_function.hook_failure.arn
+ # role_arn = aws_iam_role.global.arn
+ # lifecycle_stages = ["TEST_TRAFFIC_SHIFT", "POST_PRODUCTION_TRAFFIC_SHIFT"]
+ # }
+ # }
+ }
+
# Task Definition
requires_compatibilities = ["EC2"]
capacity_provider_strategy = {
diff --git a/examples/ec2-autoscaling/versions.tf b/examples/ec2-autoscaling/versions.tf
index 0e90b8c..70f23a4 100644
--- a/examples/ec2-autoscaling/versions.tf
+++ b/examples/ec2-autoscaling/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/examples/fargate/README.md b/examples/fargate/README.md
index 39a3b0e..0a421bc 100644
--- a/examples/fargate/README.md
+++ b/examples/fargate/README.md
@@ -27,13 +27,13 @@ Note that this example may create resources which will incur monetary charges on
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
diff --git a/examples/fargate/main.tf b/examples/fargate/main.tf
index f3931b5..3994117 100644
--- a/examples/fargate/main.tf
+++ b/examples/fargate/main.tf
@@ -60,7 +60,7 @@ module "ecs_service" {
# Enables ECS Exec
enable_execute_command = true
- # for blue/green deployments
+ # Blue/green deployment
deployment_configuration = {
strategy = "BLUE_GREEN"
bake_time_in_minutes = 2
@@ -325,17 +325,18 @@ module "alb" {
priority = 1
actions = [
{
- type = "weighted-forward"
- target_groups = [
- {
- target_group_key = "ex_ecs"
- weight = 100
- },
- {
- target_group_key = "ex_ecs_alternate"
- weight = 0
- }
- ]
+ weighted_forward = {
+ target_groups = [
+ {
+ target_group_key = "ex_ecs"
+ weight = 100
+ },
+ {
+ target_group_key = "ex_ecs_alternate"
+ weight = 0
+ }
+ ]
+ }
}
]
conditions = [
@@ -350,13 +351,14 @@ module "alb" {
priority = 2
actions = [
{
- type = "weighted-forward"
- target_groups = [
- {
- target_group_key = "ex_ecs_alternate"
- weight = 100
- }
- ]
+ weighted_forward = {
+ target_groups = [
+ {
+ target_group_key = "ex_ecs_alternate"
+ weight = 100
+ }
+ ]
+ }
}
]
conditions = [
diff --git a/examples/fargate/versions.tf b/examples/fargate/versions.tf
index 0e90b8c..70f23a4 100644
--- a/examples/fargate/versions.tf
+++ b/examples/fargate/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/main.tf b/main.tf
index e464d9b..8833edf 100644
--- a/main.tf
+++ b/main.tf
@@ -171,6 +171,7 @@ module "service" {
autoscaling_max_capacity = each.value.autoscaling_max_capacity
autoscaling_policies = each.value.autoscaling_policies
autoscaling_scheduled_actions = each.value.autoscaling_scheduled_actions
+ autoscaling_suspended_state = each.value.autoscaling_suspended_state
# Security Group
create_security_group = each.value.create_security_group
diff --git a/modules/cluster/README.md b/modules/cluster/README.md
index a041d2c..793a042 100644
--- a/modules/cluster/README.md
+++ b/modules/cluster/README.md
@@ -135,13 +135,13 @@ module "ecs_cluster" {
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
diff --git a/modules/cluster/versions.tf b/modules/cluster/versions.tf
index 0e90b8c..70f23a4 100644
--- a/modules/cluster/versions.tf
+++ b/modules/cluster/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/modules/container-definition/README.md b/modules/container-definition/README.md
index b5b994e..2eab9fe 100644
--- a/modules/container-definition/README.md
+++ b/modules/container-definition/README.md
@@ -116,13 +116,13 @@ module "example_ecs_container_definition" {
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
@@ -147,6 +147,7 @@ No modules.
| [command](#input\_command) | The command that's passed to the container | `list(string)` | `null` | no |
| [cpu](#input\_cpu) | The number of cpu units to reserve for the container. This is optional for tasks using Fargate launch type and the total amount of `cpu` of all containers in a task will need to be lower than the task-level cpu value | `number` | `null` | no |
| [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module. If not, AWS will automatically create one if logging is enabled | `bool` | `true` | no |
+| [credentialSpecs](#input\_credentialSpecs) | Specs for Credentials for gMSA (Windows containers). | `list(string)` | `null` | no |
| [dependsOn](#input\_dependsOn) | The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY | list(object({
condition = string
containerName = string
})) | `null` | no |
| [disableNetworking](#input\_disableNetworking) | When this parameter is true, networking is disabled within the container | `bool` | `null` | no |
| [dnsSearchDomains](#input\_dnsSearchDomains) | Container DNS search domains. A list of DNS search domains that are presented to the container | `list(string)` | `null` | no |
diff --git a/modules/container-definition/main.tf b/modules/container-definition/main.tf
index cf73471..7d4ceb4 100644
--- a/modules/container-definition/main.tf
+++ b/modules/container-definition/main.tf
@@ -39,6 +39,7 @@ locals {
definition = {
command = var.command
cpu = var.cpu
+ credentialSpecs = var.credentialSpecs
dependsOn = var.dependsOn
disableNetworking = local.is_not_windows ? var.disableNetworking : null
dnsSearchDomains = local.is_not_windows ? var.dnsSearchDomains : null
diff --git a/modules/container-definition/variables.tf b/modules/container-definition/variables.tf
index 0c7d229..be7aa7b 100644
--- a/modules/container-definition/variables.tf
+++ b/modules/container-definition/variables.tf
@@ -34,6 +34,13 @@ variable "cpu" {
default = null
}
+# tflint-ignore: terraform_naming_convention
+variable "credentialSpecs" {
+ description = "Specs for Credentials for gMSA (Windows containers)."
+ type = list(string)
+ default = null
+}
+
# tflint-ignore: terraform_naming_convention
variable "dependsOn" {
description = "The dependencies defined for container startup and shutdown. A container can contain multiple dependencies. When a dependency is defined for container startup, for container shutdown it is reversed. The condition can be one of START, COMPLETE, SUCCESS or HEALTHY"
diff --git a/modules/container-definition/versions.tf b/modules/container-definition/versions.tf
index 0e90b8c..70f23a4 100644
--- a/modules/container-definition/versions.tf
+++ b/modules/container-definition/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/modules/service/README.md b/modules/service/README.md
index 8891e50..f0940eb 100644
--- a/modules/service/README.md
+++ b/modules/service/README.md
@@ -170,13 +170,13 @@ module "ecs_service" {
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | >= 1.5.7 |
-| [aws](#requirement\_aws) | >= 6.14 |
+| [aws](#requirement\_aws) | >= 6.21 |
## Providers
| Name | Version |
|------|---------|
-| [aws](#provider\_aws) | >= 6.14 |
+| [aws](#provider\_aws) | >= 6.21 |
## Modules
@@ -235,10 +235,11 @@ module "ecs_service" {
| [autoscaling\_min\_capacity](#input\_autoscaling\_min\_capacity) | Minimum number of tasks to run in your service | `number` | `1` | no |
| [autoscaling\_policies](#input\_autoscaling\_policies) | Map of autoscaling policies to create for the service | map(object({
name = optional(string) # Will fall back to the key name if not provided
policy_type = optional(string, "TargetTrackingScaling")
predictive_scaling_policy_configuration = optional(object({
max_capacity_breach_behavior = optional(string)
max_capacity_buffer = optional(number)
metric_specification = list(object({
customized_capacity_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_load_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
customized_scaling_metric_specification = optional(object({
metric_data_query = list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimension = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
namespace = optional(string)
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
}))
}))
predefined_load_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_metric_pair_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
predefined_scaling_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
target_value = number
}))
mode = optional(string)
scheduling_buffer_time = optional(number)
}))
step_scaling_policy_configuration = optional(object({
adjustment_type = optional(string)
cooldown = optional(number)
metric_aggregation_type = optional(string)
min_adjustment_magnitude = optional(number)
step_adjustment = optional(list(object({
metric_interval_lower_bound = optional(string)
metric_interval_upper_bound = optional(string)
scaling_adjustment = number
})))
}))
target_tracking_scaling_policy_configuration = optional(object({
customized_metric_specification = optional(object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = optional(string)
metrics = optional(list(object({
expression = optional(string)
id = string
label = optional(string)
metric_stat = optional(object({
metric = object({
dimensions = optional(list(object({
name = string
value = string
})))
metric_name = string
namespace = string
})
stat = string
unit = optional(string)
}))
return_data = optional(bool)
})))
namespace = optional(string)
statistic = optional(string)
unit = optional(string)
}))
disable_scale_in = optional(bool)
predefined_metric_specification = optional(object({
predefined_metric_type = string
resource_label = optional(string)
}))
scale_in_cooldown = optional(number, 300)
scale_out_cooldown = optional(number, 60)
target_value = optional(number, 75)
}))
})) | {
"cpu": {
"policy_type": "TargetTrackingScaling",
"target_tracking_scaling_policy_configuration": {
"predefined_metric_specification": {
"predefined_metric_type": "ECSServiceAverageCPUUtilization"
}
}
},
"memory": {
"policy_type": "TargetTrackingScaling",
"target_tracking_scaling_policy_configuration": {
"predefined_metric_specification": {
"predefined_metric_type": "ECSServiceAverageMemoryUtilization"
}
}
}
} | no |
| [autoscaling\_scheduled\_actions](#input\_autoscaling\_scheduled\_actions) | Map of autoscaling scheduled actions to create for the service | map(object({
name = optional(string)
min_capacity = number
max_capacity = number
schedule = string
start_time = optional(string)
end_time = optional(string)
timezone = optional(string)
})) | `null` | no |
+| [autoscaling\_suspended\_state](#input\_autoscaling\_suspended\_state) | Configuration block that specifies whether the scaling activities for the service are in a suspended state | object({
dynamic_scaling_in_suspended = optional(bool, false)
dynamic_scaling_out_suspended = optional(bool, false)
scheduled_scaling_suspended = optional(bool, false)
}) | `null` | no |
| [availability\_zone\_rebalancing](#input\_availability\_zone\_rebalancing) | 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` | `string` | `null` | no |
| [capacity\_provider\_strategy](#input\_capacity\_provider\_strategy) | Capacity provider strategies to use for the service. Can be one or more | map(object({
base = optional(number)
capacity_provider = string
weight = optional(number)
})) | `null` | no |
| [cluster\_arn](#input\_cluster\_arn) | ARN of the ECS cluster where the resources will be provisioned | `string` | `""` | no |
-| [container\_definitions](#input\_container\_definitions) | A map of valid [container definitions](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html). Please note that you should only provide values that are part of the container definition document | map(object({
create = optional(bool, true)
operating_system_family = optional(string)
tags = optional(map(string))
# Container definition
command = optional(list(string))
cpu = optional(number)
dependsOn = optional(list(object({
condition = string
containerName = string
})))
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
# enable_execute_command = optional(bool, false) Set in standalone variable
entrypoint = optional(list(string))
environment = optional(list(object({
name = string
value = string
})))
environmentFiles = optional(list(object({
type = string
value = string
})))
essential = optional(bool)
extraHosts = optional(list(object({
hostname = string
ipAddress = string
})))
firelensConfiguration = optional(object({
options = optional(map(string))
type = optional(string)
}))
healthCheck = optional(object({
command = optional(list(string), [])
interval = optional(number, 30)
retries = optional(number, 3)
startPeriod = optional(number)
timeout = optional(number, 5)
}))
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(object({
capabilities = optional(object({
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(list(object({
containerPath = optional(string)
hostPath = optional(string)
permissions = optional(list(string))
})))
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(list(object({
containerPath = string
mountOptions = optional(list(string))
size = number
})))
}))
logConfiguration = optional(object({
logDriver = optional(string)
options = optional(map(string))
secretOptions = optional(list(object({
name = string
valueFrom = string
})))
}))
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(list(object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})))
name = optional(string)
portMappings = optional(list(object({
appProtocol = optional(string)
containerPort = optional(number)
containerPortRange = optional(string)
hostPort = optional(number)
name = optional(string)
protocol = optional(string)
})))
privileged = optional(bool)
pseudoTerminal = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(object({
credentialsParameter = optional(string)
}))
resourceRequirements = optional(list(object({
type = string
value = string
})))
restartPolicy = optional(object({
enabled = optional(bool)
ignoredExitCodes = optional(list(number))
restartAttemptPeriod = optional(number)
})
)
secrets = optional(list(object({
name = string
valueFrom = string
})))
startTimeout = optional(number, 30)
stopTimeout = optional(number, 120)
systemControls = optional(list(object({
namespace = optional(string)
value = optional(string)
})))
ulimits = optional(list(object({
hardLimit = number
name = string
softLimit = number
})))
user = optional(string)
versionConsistency = optional(string)
volumesFrom = optional(list(object({
readOnly = optional(bool)
sourceContainer = optional(string)
})))
workingDirectory = optional(string)
# Cloudwatch Log Group
service = optional(string)
enable_cloudwatch_logging = optional(bool)
create_cloudwatch_log_group = optional(bool)
cloudwatch_log_group_name = optional(string)
cloudwatch_log_group_use_name_prefix = optional(bool)
cloudwatch_log_group_class = optional(string)
cloudwatch_log_group_retention_in_days = optional(number)
cloudwatch_log_group_kms_key_id = optional(string)
})) | `{}` | no |
+| [container\_definitions](#input\_container\_definitions) | A map of valid [container definitions](http://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_ContainerDefinition.html). Please note that you should only provide values that are part of the container definition document | map(object({
create = optional(bool, true)
operating_system_family = optional(string)
tags = optional(map(string))
# Container definition
command = optional(list(string))
cpu = optional(number)
credentialSpecs = optional(list(string))
dependsOn = optional(list(object({
condition = string
containerName = string
})))
disableNetworking = optional(bool)
dnsSearchDomains = optional(list(string))
dnsServers = optional(list(string))
dockerLabels = optional(map(string))
dockerSecurityOptions = optional(list(string))
# enable_execute_command = optional(bool, false) Set in standalone variable
entrypoint = optional(list(string))
environment = optional(list(object({
name = string
value = string
})))
environmentFiles = optional(list(object({
type = string
value = string
})))
essential = optional(bool)
extraHosts = optional(list(object({
hostname = string
ipAddress = string
})))
firelensConfiguration = optional(object({
options = optional(map(string))
type = optional(string)
}))
healthCheck = optional(object({
command = optional(list(string), [])
interval = optional(number, 30)
retries = optional(number, 3)
startPeriod = optional(number)
timeout = optional(number, 5)
}))
hostname = optional(string)
image = optional(string)
interactive = optional(bool)
links = optional(list(string))
linuxParameters = optional(object({
capabilities = optional(object({
add = optional(list(string))
drop = optional(list(string))
}))
devices = optional(list(object({
containerPath = optional(string)
hostPath = optional(string)
permissions = optional(list(string))
})))
initProcessEnabled = optional(bool)
maxSwap = optional(number)
sharedMemorySize = optional(number)
swappiness = optional(number)
tmpfs = optional(list(object({
containerPath = string
mountOptions = optional(list(string))
size = number
})))
}))
logConfiguration = optional(object({
logDriver = optional(string)
options = optional(map(string))
secretOptions = optional(list(object({
name = string
valueFrom = string
})))
}))
memory = optional(number)
memoryReservation = optional(number)
mountPoints = optional(list(object({
containerPath = optional(string)
readOnly = optional(bool)
sourceVolume = optional(string)
})))
name = optional(string)
portMappings = optional(list(object({
appProtocol = optional(string)
containerPort = optional(number)
containerPortRange = optional(string)
hostPort = optional(number)
name = optional(string)
protocol = optional(string)
})))
privileged = optional(bool)
pseudoTerminal = optional(bool)
readonlyRootFilesystem = optional(bool)
repositoryCredentials = optional(object({
credentialsParameter = optional(string)
}))
resourceRequirements = optional(list(object({
type = string
value = string
})))
restartPolicy = optional(object({
enabled = optional(bool)
ignoredExitCodes = optional(list(number))
restartAttemptPeriod = optional(number)
})
)
secrets = optional(list(object({
name = string
valueFrom = string
})))
startTimeout = optional(number, 30)
stopTimeout = optional(number, 120)
systemControls = optional(list(object({
namespace = optional(string)
value = optional(string)
})))
ulimits = optional(list(object({
hardLimit = number
name = string
softLimit = number
})))
user = optional(string)
versionConsistency = optional(string)
volumesFrom = optional(list(object({
readOnly = optional(bool)
sourceContainer = optional(string)
})))
workingDirectory = optional(string)
# Cloudwatch Log Group
service = optional(string)
enable_cloudwatch_logging = optional(bool)
create_cloudwatch_log_group = optional(bool)
cloudwatch_log_group_name = optional(string)
cloudwatch_log_group_use_name_prefix = optional(bool)
cloudwatch_log_group_class = optional(string)
cloudwatch_log_group_retention_in_days = optional(number)
cloudwatch_log_group_kms_key_id = optional(string)
})) | `{}` | no |
| [cpu](#input\_cpu) | Number of cpu units used by the task. If the `requires_compatibilities` is `FARGATE` this field is required | `number` | `1024` | no |
| [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
| [create\_iam\_role](#input\_create\_iam\_role) | Determines whether the ECS service IAM role should be created | `bool` | `true` | no |
@@ -250,7 +251,7 @@ module "ecs_service" {
| [create\_task\_exec\_policy](#input\_create\_task\_exec\_policy) | Determines whether the ECS task definition IAM policy should be created. This includes permissions included in AmazonECSTaskExecutionRolePolicy as well as access to secrets and SSM parameters | `bool` | `true` | no |
| [create\_tasks\_iam\_role](#input\_create\_tasks\_iam\_role) | Determines whether the ECS tasks IAM role should be created | `bool` | `true` | no |
| [deployment\_circuit\_breaker](#input\_deployment\_circuit\_breaker) | Configuration block for deployment circuit breaker | object({
enable = bool
rollback = bool
}) | `null` | no |
-| [deployment\_configuration](#input\_deployment\_configuration) | Configuration block for deployment settings | object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
lifecycle_stages = list(string)
hook_details = optional(string)
})))
}) | `null` | no |
+| [deployment\_configuration](#input\_deployment\_configuration) | Configuration block for deployment settings | object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
canary_configuration = optional(object({
canary_bake_time_in_minutes = optional(string)
canary_percent = optional(string)
}))
linear_configuration = optional(object({
step_bake_time_in_minutes = optional(string)
step_percent = optional(string)
}))
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
lifecycle_stages = list(string)
hook_details = optional(string)
})))
}) | `null` | no |
| [deployment\_controller](#input\_deployment\_controller) | Configuration block for deployment controller configuration | object({
type = optional(string)
}) | `null` | no |
| [deployment\_maximum\_percent](#input\_deployment\_maximum\_percent) | Upper limit (as a percentage of the service's `desired_count`) of the number of running tasks that can be running in a service during a deployment | `number` | `200` | no |
| [deployment\_minimum\_healthy\_percent](#input\_deployment\_minimum\_healthy\_percent) | Lower limit (as a percentage of the service's `desired_count`) of the number of running tasks that must remain running and healthy in a service during a deployment | `number` | `66` | no |
diff --git a/modules/service/main.tf b/modules/service/main.tf
index f467f56..b97f704 100644
--- a/modules/service/main.tf
+++ b/modules/service/main.tf
@@ -82,6 +82,24 @@ resource "aws_ecs_service" "this" {
strategy = deployment_configuration.value.strategy
bake_time_in_minutes = deployment_configuration.value.bake_time_in_minutes
+ dynamic "linear_configuration" {
+ for_each = deployment_configuration.value.linear_configuration != null ? [deployment_configuration.value.linear_configuration] : []
+
+ content {
+ step_bake_time_in_minutes = linear_configuration.value.step_bake_time_in_minutes
+ step_percent = linear_configuration.value.step_percent
+ }
+ }
+
+ dynamic "canary_configuration" {
+ for_each = deployment_configuration.value.canary_configuration != null ? [deployment_configuration.value.canary_configuration] : []
+
+ content {
+ canary_bake_time_in_minutes = canary_configuration.value.canary_bake_time_in_minutes
+ canary_percent = canary_configuration.value.canary_percent
+ }
+ }
+
dynamic "lifecycle_hook" {
for_each = deployment_configuration.value.lifecycle_hook != null ? deployment_configuration.value.lifecycle_hook : {}
@@ -405,6 +423,24 @@ resource "aws_ecs_service" "ignore_task_definition" {
strategy = deployment_configuration.value.strategy
bake_time_in_minutes = deployment_configuration.value.bake_time_in_minutes
+ dynamic "linear_configuration" {
+ for_each = deployment_configuration.value.linear_configuration != null ? [deployment_configuration.value.linear_configuration] : []
+
+ content {
+ step_percent = linear_configuration.value.step_percent
+ step_bake_time_in_minutes = linear_configuration.value.step_bake_time_in_minutes
+ }
+ }
+
+ dynamic "canary_configuration" {
+ for_each = deployment_configuration.value.canary_configuration != null ? [deployment_configuration.value.canary_configuration] : []
+
+ content {
+ canary_percent = canary_configuration.value.canary_percent
+ canary_bake_time_in_minutes = canary_configuration.value.canary_bake_time_in_minutes
+ }
+ }
+
dynamic "lifecycle_hook" {
for_each = deployment_configuration.value.lifecycle_hook != null ? deployment_configuration.value.lifecycle_hook : {}
@@ -814,6 +850,7 @@ module "container_definition" {
# Container Definition
command = each.value.command
cpu = each.value.cpu
+ credentialSpecs = each.value.credentialSpecs
dependsOn = each.value.dependsOn
disableNetworking = each.value.disableNetworking
dnsSearchDomains = each.value.dnsSearchDomains
@@ -1490,7 +1527,18 @@ resource "aws_appautoscaling_target" "this" {
resource_id = "service/${local.cluster_name}/${try(aws_ecs_service.this[0].name, aws_ecs_service.ignore_task_definition[0].name)}"
scalable_dimension = "ecs:service:DesiredCount"
service_namespace = "ecs"
- tags = var.tags
+
+ dynamic "suspended_state" {
+ for_each = local.enable_autoscaling && var.autoscaling_suspended_state != null ? [var.autoscaling_suspended_state] : []
+
+ content {
+ dynamic_scaling_in_suspended = suspended_state.value.dynamic_scaling_in_suspended
+ dynamic_scaling_out_suspended = suspended_state.value.dynamic_scaling_out_suspended
+ scheduled_scaling_suspended = suspended_state.value.scheduled_scaling_suspended
+ }
+ }
+
+ tags = var.tags
}
resource "aws_appautoscaling_policy" "this" {
diff --git a/modules/service/variables.tf b/modules/service/variables.tf
index 42afafc..b42dfe4 100644
--- a/modules/service/variables.tf
+++ b/modules/service/variables.tf
@@ -83,6 +83,14 @@ variable "deployment_configuration" {
type = object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
+ canary_configuration = optional(object({
+ canary_bake_time_in_minutes = optional(string)
+ canary_percent = optional(string)
+ }))
+ linear_configuration = optional(object({
+ step_bake_time_in_minutes = optional(string)
+ step_percent = optional(string)
+ }))
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
@@ -475,8 +483,9 @@ variable "container_definitions" {
tags = optional(map(string))
# Container definition
- command = optional(list(string))
- cpu = optional(number)
+ command = optional(list(string))
+ cpu = optional(number)
+ credentialSpecs = optional(list(string))
dependsOn = optional(list(object({
condition = string
containerName = string
@@ -1197,6 +1206,16 @@ variable "autoscaling_scheduled_actions" {
default = null
}
+variable "autoscaling_suspended_state" {
+ description = "Configuration block that specifies whether the scaling activities for the service are in a suspended state"
+ type = object({
+ dynamic_scaling_in_suspended = optional(bool, false)
+ dynamic_scaling_out_suspended = optional(bool, false)
+ scheduled_scaling_suspended = optional(bool, false)
+ })
+ default = null
+}
+
################################################################################
# Security Group
################################################################################
diff --git a/modules/service/versions.tf b/modules/service/versions.tf
index 0e90b8c..70f23a4 100644
--- a/modules/service/versions.tf
+++ b/modules/service/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/variables.tf b/variables.tf
index b537cb9..5c354d6 100644
--- a/variables.tf
+++ b/variables.tf
@@ -283,6 +283,14 @@ variable "services" {
deployment_configuration = optional(object({
strategy = optional(string)
bake_time_in_minutes = optional(string)
+ canary_configuration = optional(object({
+ canary_bake_time_in_minutes = optional(string)
+ canary_percent = optional(string)
+ }))
+ linear_configuration = optional(object({
+ step_bake_time_in_minutes = optional(string)
+ step_percent = optional(string)
+ }))
lifecycle_hook = optional(map(object({
hook_target_arn = string
role_arn = string
@@ -445,8 +453,9 @@ variable "services" {
tags = optional(map(string))
# Container definition
- command = optional(list(string))
- cpu = optional(number)
+ command = optional(list(string))
+ cpu = optional(number)
+ credentialSpecs = optional(list(string))
dependsOn = optional(list(object({
condition = string
containerName = string
@@ -858,6 +867,11 @@ variable "services" {
end_time = optional(string)
timezone = optional(string)
})))
+ autoscaling_suspended_state = optional(object({
+ dynamic_scaling_in_suspended = optional(bool)
+ dynamic_scaling_out_suspended = optional(bool)
+ scheduled_scaling_suspended = optional(bool)
+ }))
# Security Group
create_security_group = optional(bool)
vpc_id = optional(string)
diff --git a/versions.tf b/versions.tf
index 0e90b8c..70f23a4 100644
--- a/versions.tf
+++ b/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/wrappers/cluster/versions.tf b/wrappers/cluster/versions.tf
index 0e90b8c..70f23a4 100644
--- a/wrappers/cluster/versions.tf
+++ b/wrappers/cluster/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/wrappers/container-definition/main.tf b/wrappers/container-definition/main.tf
index c187ddd..c805d7d 100644
--- a/wrappers/container-definition/main.tf
+++ b/wrappers/container-definition/main.tf
@@ -11,6 +11,7 @@ module "wrapper" {
command = try(each.value.command, var.defaults.command, null)
cpu = try(each.value.cpu, var.defaults.cpu, null)
create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, true)
+ credentialSpecs = try(each.value.credentialSpecs, var.defaults.credentialSpecs, null)
dependsOn = try(each.value.dependsOn, var.defaults.dependsOn, null)
disableNetworking = try(each.value.disableNetworking, var.defaults.disableNetworking, null)
dnsSearchDomains = try(each.value.dnsSearchDomains, var.defaults.dnsSearchDomains, null)
diff --git a/wrappers/container-definition/versions.tf b/wrappers/container-definition/versions.tf
index 0e90b8c..70f23a4 100644
--- a/wrappers/container-definition/versions.tf
+++ b/wrappers/container-definition/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/wrappers/service/main.tf b/wrappers/service/main.tf
index cf6f0e1..44ebf6b 100644
--- a/wrappers/service/main.tf
+++ b/wrappers/service/main.tf
@@ -28,6 +28,7 @@ module "wrapper" {
}
})
autoscaling_scheduled_actions = try(each.value.autoscaling_scheduled_actions, var.defaults.autoscaling_scheduled_actions, null)
+ autoscaling_suspended_state = try(each.value.autoscaling_suspended_state, var.defaults.autoscaling_suspended_state, null)
availability_zone_rebalancing = try(each.value.availability_zone_rebalancing, var.defaults.availability_zone_rebalancing, null)
capacity_provider_strategy = try(each.value.capacity_provider_strategy, var.defaults.capacity_provider_strategy, null)
cluster_arn = try(each.value.cluster_arn, var.defaults.cluster_arn, "")
diff --git a/wrappers/service/versions.tf b/wrappers/service/versions.tf
index 0e90b8c..70f23a4 100644
--- a/wrappers/service/versions.tf
+++ b/wrappers/service/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}
diff --git a/wrappers/versions.tf b/wrappers/versions.tf
index 0e90b8c..70f23a4 100644
--- a/wrappers/versions.tf
+++ b/wrappers/versions.tf
@@ -4,7 +4,7 @@ terraform {
required_providers {
aws = {
source = "hashicorp/aws"
- version = ">= 6.14"
+ version = ">= 6.21"
}
}
}