v if var.create }
55 |
56 | create = try(each.value.create, true)
57 | create_service = try(each.value.create_service, true)
58 |
59 | # Service
60 | ignore_task_definition_changes = try(each.value.ignore_task_definition_changes, false)
61 | alarms = try(each.value.alarms, {})
62 | capacity_provider_strategy = try(each.value.capacity_provider_strategy, {})
63 | cluster_arn = module.cluster.arn
64 | deployment_circuit_breaker = try(each.value.deployment_circuit_breaker, {})
65 | deployment_controller = try(each.value.deployment_controller, {})
66 | deployment_maximum_percent = try(each.value.deployment_maximum_percent, 200)
67 | deployment_minimum_healthy_percent = try(each.value.deployment_minimum_healthy_percent, 66)
68 | desired_count = try(each.value.desired_count, 1)
69 | enable_ecs_managed_tags = try(each.value.enable_ecs_managed_tags, true)
70 | enable_execute_command = try(each.value.enable_execute_command, false)
71 | force_new_deployment = try(each.value.force_new_deployment, true)
72 | health_check_grace_period_seconds = try(each.value.health_check_grace_period_seconds, null)
73 | launch_type = try(each.value.launch_type, "FARGATE")
74 | load_balancer = lookup(each.value, "load_balancer", {})
75 | name = try(each.value.name, each.key)
76 | assign_public_ip = try(each.value.assign_public_ip, false)
77 | security_group_ids = lookup(each.value, "security_group_ids", [])
78 | subnet_ids = lookup(each.value, "subnet_ids", [])
79 | ordered_placement_strategy = try(each.value.ordered_placement_strategy, {})
80 | placement_constraints = try(each.value.placement_constraints, {})
81 | platform_version = try(each.value.platform_version, null)
82 | propagate_tags = try(each.value.propagate_tags, null)
83 | scheduling_strategy = try(each.value.scheduling_strategy, null)
84 | service_connect_configuration = lookup(each.value, "service_connect_configuration", {})
85 | service_registries = lookup(each.value, "service_registries", {})
86 | timeouts = try(each.value.timeouts, {})
87 | triggers = try(each.value.triggers, {})
88 | wait_for_steady_state = try(each.value.wait_for_steady_state, null)
89 |
90 | # Service IAM role
91 | create_iam_role = try(each.value.create_iam_role, true)
92 | iam_role_arn = lookup(each.value, "iam_role_arn", null)
93 | iam_role_name = try(each.value.iam_role_name, null)
94 | iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, true)
95 | iam_role_path = try(each.value.iam_role_path, null)
96 | iam_role_description = try(each.value.iam_role_description, null)
97 | iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, null)
98 | iam_role_tags = try(each.value.iam_role_tags, {})
99 | iam_role_statements = lookup(each.value, "iam_role_statements", {})
100 |
101 | # Task definition
102 | create_task_definition = try(each.value.create_task_definition, true)
103 | task_definition_arn = lookup(each.value, "task_definition_arn", null)
104 | container_definitions = try(each.value.container_definitions, {})
105 | container_definition_defaults = try(each.value.container_definition_defaults, {})
106 | cpu = try(each.value.cpu, 1024)
107 | ephemeral_storage = try(each.value.ephemeral_storage, {})
108 | family = try(each.value.family, null)
109 | inference_accelerator = try(each.value.inference_accelerator, {})
110 | ipc_mode = try(each.value.ipc_mode, null)
111 | memory = try(each.value.memory, 2048)
112 | network_mode = try(each.value.network_mode, "awsvpc")
113 | pid_mode = try(each.value.pid_mode, null)
114 | proxy_configuration = try(each.value.proxy_configuration, {})
115 | requires_compatibilities = try(each.value.requires_compatibilities, ["FARGATE"])
116 | runtime_platform = try(each.value.runtime_platform, {
117 | operating_system_family = "LINUX"
118 | cpu_architecture = "X86_64"
119 | })
120 | skip_destroy = try(each.value.skip_destroy, null)
121 | volume = try(each.value.volume, {})
122 | task_tags = try(each.value.task_tags, {})
123 |
124 | # Task execution IAM role
125 | create_task_exec_iam_role = try(each.value.create_task_exec_iam_role, true)
126 | task_exec_iam_role_arn = lookup(each.value, "task_exec_iam_role_arn", null)
127 | task_exec_iam_role_name = try(each.value.task_exec_iam_role_name, null)
128 | task_exec_iam_role_use_name_prefix = try(each.value.task_exec_iam_role_use_name_prefix, true)
129 | task_exec_iam_role_path = try(each.value.task_exec_iam_role_path, null)
130 | task_exec_iam_role_description = try(each.value.task_exec_iam_role_description, null)
131 | task_exec_iam_role_permissions_boundary = try(each.value.task_exec_iam_role_permissions_boundary, null)
132 | task_exec_iam_role_tags = try(each.value.task_exec_iam_role_tags, {})
133 | task_exec_iam_role_policies = try(each.value.task_exec_iam_role_policies, {})
134 | task_exec_iam_role_max_session_duration = try(each.value.task_exec_iam_role_max_session_duration, null)
135 |
136 | # Task execution IAM role policy
137 | create_task_exec_policy = try(each.value.create_task_exec_policy, true)
138 | task_exec_ssm_param_arns = lookup(each.value, "task_exec_ssm_param_arns", ["arn:aws:ssm:*:*:parameter/*"])
139 | task_exec_secret_arns = lookup(each.value, "task_exec_secret_arns", ["arn:aws:secretsmanager:*:*:secret:*"])
140 | task_exec_iam_statements = lookup(each.value, "task_exec_iam_statements", {})
141 |
142 | # Tasks - IAM role
143 | create_tasks_iam_role = try(each.value.create_tasks_iam_role, true)
144 | tasks_iam_role_arn = lookup(each.value, "tasks_iam_role_arn", null)
145 | tasks_iam_role_name = try(each.value.tasks_iam_role_name, null)
146 | tasks_iam_role_use_name_prefix = try(each.value.tasks_iam_role_use_name_prefix, true)
147 | tasks_iam_role_path = try(each.value.tasks_iam_role_path, null)
148 | tasks_iam_role_description = try(each.value.tasks_iam_role_description, null)
149 | tasks_iam_role_permissions_boundary = try(each.value.tasks_iam_role_permissions_boundary, null)
150 | tasks_iam_role_tags = try(each.value.tasks_iam_role_tags, {})
151 | tasks_iam_role_policies = lookup(each.value, "tasks_iam_role_policies", {})
152 | tasks_iam_role_statements = lookup(each.value, "tasks_iam_role_statements", {})
153 |
154 | # Task set
155 | external_id = try(each.value.external_id, null)
156 | scale = try(each.value.scale, {})
157 | force_delete = try(each.value.force_delete, null)
158 | wait_until_stable = try(each.value.wait_until_stable, null)
159 | wait_until_stable_timeout = try(each.value.wait_until_stable_timeout, null)
160 |
161 | # Autoscaling
162 | enable_autoscaling = try(each.value.enable_autoscaling, true)
163 | autoscaling_min_capacity = try(each.value.autoscaling_min_capacity, 1)
164 | autoscaling_max_capacity = try(each.value.autoscaling_max_capacity, 10)
165 | autoscaling_policies = try(each.value.autoscaling_policies, {
166 | cpu = {
167 | policy_type = "TargetTrackingScaling"
168 |
169 | target_tracking_scaling_policy_configuration = {
170 | predefined_metric_specification = {
171 | predefined_metric_type = "ECSServiceAverageCPUUtilization"
172 | }
173 | }
174 | }
175 | memory = {
176 | policy_type = "TargetTrackingScaling"
177 |
178 | target_tracking_scaling_policy_configuration = {
179 | predefined_metric_specification = {
180 | predefined_metric_type = "ECSServiceAverageMemoryUtilization"
181 | }
182 | }
183 | }
184 | })
185 | autoscaling_scheduled_actions = try(each.value.autoscaling_scheduled_actions, {})
186 |
187 | # Security Group
188 | create_security_group = try(each.value.create_security_group, true)
189 | security_group_name = try(each.value.security_group_name, null)
190 | security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, true)
191 | security_group_description = try(each.value.security_group_description, null)
192 | security_group_rules = lookup(each.value, "security_group_rules", {})
193 | security_group_tags = try(each.value.security_group_tags, {})
194 |
195 | tags = merge(var.tags, try(each.value.tags, {}))
196 | }
197 |
--------------------------------------------------------------------------------
/modules/cluster/README.md:
--------------------------------------------------------------------------------
1 | # Amazon ECS Cluster Terraform Module
2 |
3 | Terraform module which creates Amazon ECS (Elastic Container Service) cluster resources on AWS.
4 |
5 | ## Available Features
6 |
7 | - ECS cluster
8 | - Fargate capacity providers
9 | - EC2 AutoScaling Group capacity providers
10 | - ECS Service w/ task definition, task set, and container definition support
11 |
12 | For more details see the [design doc](https://github.com/terraform-aws-modules/terraform-aws-ecs/blob/master/docs/README.md)
13 |
14 | ## Usage
15 |
16 | ### Fargate Capacity Providers
17 |
18 | ```hcl
19 | module "ecs_cluster" {
20 | source = "terraform-aws-modules/ecs/aws//modules/cluster"
21 |
22 | cluster_name = "ecs-fargate"
23 |
24 | cluster_configuration = {
25 | execute_command_configuration = {
26 | logging = "OVERRIDE"
27 | log_configuration = {
28 | cloud_watch_log_group_name = "/aws/ecs/aws-ec2"
29 | }
30 | }
31 | }
32 |
33 | fargate_capacity_providers = {
34 | FARGATE = {
35 | default_capacity_provider_strategy = {
36 | weight = 50
37 | }
38 | }
39 | FARGATE_SPOT = {
40 | default_capacity_provider_strategy = {
41 | weight = 50
42 | }
43 | }
44 | }
45 |
46 | tags = {
47 | Environment = "Development"
48 | Project = "EcsEc2"
49 | }
50 | }
51 | ```
52 |
53 | ### EC2 Autoscaling Capacity Providers
54 |
55 | ```hcl
56 | module "ecs_cluster" {
57 | source = "terraform-aws-modules/ecs/aws//modules/cluster"
58 |
59 | cluster_name = "ecs-ec2"
60 |
61 | cluster_configuration = {
62 | execute_command_configuration = {
63 | logging = "OVERRIDE"
64 | log_configuration = {
65 | cloud_watch_log_group_name = "/aws/ecs/aws-ec2"
66 | }
67 | }
68 | }
69 |
70 | autoscaling_capacity_providers = {
71 | one = {
72 | auto_scaling_group_arn = "arn:aws:autoscaling:eu-west-1:012345678901:autoScalingGroup:08419a61:autoScalingGroupName/ecs-ec2-one-20220603194933774300000011"
73 | managed_termination_protection = "ENABLED"
74 |
75 | managed_scaling = {
76 | maximum_scaling_step_size = 5
77 | minimum_scaling_step_size = 1
78 | status = "ENABLED"
79 | target_capacity = 60
80 | }
81 |
82 | default_capacity_provider_strategy = {
83 | weight = 60
84 | base = 20
85 | }
86 | }
87 | two = {
88 | auto_scaling_group_arn = "arn:aws:autoscaling:eu-west-1:012345678901:autoScalingGroup:08419a61:autoScalingGroupName/ecs-ec2-two-20220603194933774300000022"
89 | managed_termination_protection = "ENABLED"
90 |
91 | managed_scaling = {
92 | maximum_scaling_step_size = 15
93 | minimum_scaling_step_size = 5
94 | status = "ENABLED"
95 | target_capacity = 90
96 | }
97 |
98 | default_capacity_provider_strategy = {
99 | weight = 40
100 | }
101 | }
102 | }
103 |
104 | tags = {
105 | Environment = "Development"
106 | Project = "EcsEc2"
107 | }
108 | }
109 | ```
110 |
111 | ## Conditional Creation
112 |
113 | The following values are provided to toggle on/off creation of the associated resources as desired:
114 |
115 | ```hcl
116 | module "ecs_cluster" {
117 | source = "terraform-aws-modules/ecs/aws//modules/cluster"
118 |
119 | # Disable creation of cluster and all resources
120 | create = false
121 |
122 | # ... omitted
123 | }
124 | ```
125 |
126 | ## Examples
127 |
128 | - [ECS Cluster Complete](https://github.com/terraform-aws-modules/terraform-aws-ecs/tree/master/examples/complete)
129 | - [ECS Cluster w/ EC2 Autoscaling Capacity Provider](https://github.com/terraform-aws-modules/terraform-aws-ecs/tree/master/examples/ec2-autoscaling)
130 | - [ECS Cluster w/ Fargate Capacity Provider](https://github.com/terraform-aws-modules/terraform-aws-ecs/tree/master/examples/fargate)
131 |
132 |
133 | ## Requirements
134 |
135 | | Name | Version |
136 | |------|---------|
137 | | [terraform](#requirement\_terraform) | >= 1.0 |
138 | | [aws](#requirement\_aws) | >= 4.66.1 |
139 |
140 | ## Providers
141 |
142 | | Name | Version |
143 | |------|---------|
144 | | [aws](#provider\_aws) | >= 4.66.1 |
145 |
146 | ## Modules
147 |
148 | No modules.
149 |
150 | ## Resources
151 |
152 | | Name | Type |
153 | |------|------|
154 | | [aws_cloudwatch_log_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource |
155 | | [aws_ecs_capacity_provider.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_capacity_provider) | resource |
156 | | [aws_ecs_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster) | resource |
157 | | [aws_ecs_cluster_capacity_providers.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecs_cluster_capacity_providers) | resource |
158 | | [aws_iam_policy.task_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | resource |
159 | | [aws_iam_role.task_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
160 | | [aws_iam_role_policy_attachment.task_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
161 | | [aws_iam_role_policy_attachment.task_exec_additional](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
162 | | [aws_iam_policy_document.task_exec](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
163 | | [aws_iam_policy_document.task_exec_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source |
164 |
165 | ## Inputs
166 |
167 | | Name | Description | Type | Default | Required |
168 | |------|-------------|------|---------|:--------:|
169 | | [autoscaling\_capacity\_providers](#input\_autoscaling\_capacity\_providers) | Map of autoscaling capacity provider definitions to create for the cluster | `any` | `{}` | no |
170 | | [cloudwatch\_log\_group\_kms\_key\_id](#input\_cloudwatch\_log\_group\_kms\_key\_id) | If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html) | `string` | `null` | no |
171 | | [cloudwatch\_log\_group\_name](#input\_cloudwatch\_log\_group\_name) | Custom name of CloudWatch Log Group for ECS cluster | `string` | `null` | no |
172 | | [cloudwatch\_log\_group\_retention\_in\_days](#input\_cloudwatch\_log\_group\_retention\_in\_days) | Number of days to retain log events | `number` | `90` | no |
173 | | [cloudwatch\_log\_group\_tags](#input\_cloudwatch\_log\_group\_tags) | A map of additional tags to add to the log group created | `map(string)` | `{}` | no |
174 | | [cluster\_configuration](#input\_cluster\_configuration) | The execute command configuration for the cluster | `any` | `{}` | no |
175 | | [cluster\_name](#input\_cluster\_name) | Name of the cluster (up to 255 letters, numbers, hyphens, and underscores) | `string` | `""` | no |
176 | | [cluster\_service\_connect\_defaults](#input\_cluster\_service\_connect\_defaults) | Configures a default Service Connect namespace | `map(string)` | `{}` | no |
177 | | [cluster\_settings](#input\_cluster\_settings) | List of configuration block(s) with cluster settings. For example, this can be used to enable CloudWatch Container Insights for a cluster | `any` | [
{
"name": "containerInsights",
"value": "enabled"
}
]
| no |
178 | | [create](#input\_create) | Determines whether resources will be created (affects all resources) | `bool` | `true` | no |
179 | | [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled | `bool` | `true` | no |
180 | | [create\_task\_exec\_iam\_role](#input\_create\_task\_exec\_iam\_role) | Determines whether the ECS task definition IAM role should be created | `bool` | `false` | no |
181 | | [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 |
182 | | [default\_capacity\_provider\_use\_fargate](#input\_default\_capacity\_provider\_use\_fargate) | Determines whether to use Fargate or autoscaling for default capacity provider strategy | `bool` | `true` | no |
183 | | [fargate\_capacity\_providers](#input\_fargate\_capacity\_providers) | Map of Fargate capacity provider definitions to use for the cluster | `any` | `{}` | no |
184 | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no |
185 | | [task\_exec\_iam\_role\_description](#input\_task\_exec\_iam\_role\_description) | Description of the role | `string` | `null` | no |
186 | | [task\_exec\_iam\_role\_name](#input\_task\_exec\_iam\_role\_name) | Name to use on IAM role created | `string` | `null` | no |
187 | | [task\_exec\_iam\_role\_path](#input\_task\_exec\_iam\_role\_path) | IAM role path | `string` | `null` | no |
188 | | [task\_exec\_iam\_role\_permissions\_boundary](#input\_task\_exec\_iam\_role\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the IAM role | `string` | `null` | no |
189 | | [task\_exec\_iam\_role\_policies](#input\_task\_exec\_iam\_role\_policies) | Map of IAM role policy ARNs to attach to the IAM role | `map(string)` | `{}` | no |
190 | | [task\_exec\_iam\_role\_tags](#input\_task\_exec\_iam\_role\_tags) | A map of additional tags to add to the IAM role created | `map(string)` | `{}` | no |
191 | | [task\_exec\_iam\_role\_use\_name\_prefix](#input\_task\_exec\_iam\_role\_use\_name\_prefix) | Determines whether the IAM role name (`task_exec_iam_role_name`) is used as a prefix | `bool` | `true` | no |
192 | | [task\_exec\_iam\_statements](#input\_task\_exec\_iam\_statements) | A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage | `any` | `{}` | no |
193 | | [task\_exec\_secret\_arns](#input\_task\_exec\_secret\_arns) | List of SecretsManager secret ARNs the task execution role will be permitted to get/read | `list(string)` | [
"arn:aws:secretsmanager:*:*:secret:*"
]
| no |
194 | | [task\_exec\_ssm\_param\_arns](#input\_task\_exec\_ssm\_param\_arns) | List of SSM parameter ARNs the task execution role will be permitted to get/read | `list(string)` | [
"arn:aws:ssm:*:*:parameter/*"
]
| no |
195 |
196 | ## Outputs
197 |
198 | | Name | Description |
199 | |------|-------------|
200 | | [arn](#output\_arn) | ARN that identifies the cluster |
201 | | [autoscaling\_capacity\_providers](#output\_autoscaling\_capacity\_providers) | Map of autoscaling capacity providers created and their attributes |
202 | | [cloudwatch\_log\_group\_arn](#output\_cloudwatch\_log\_group\_arn) | ARN of CloudWatch log group created |
203 | | [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of CloudWatch log group created |
204 | | [cluster\_capacity\_providers](#output\_cluster\_capacity\_providers) | Map of cluster capacity providers attributes |
205 | | [id](#output\_id) | ID that identifies the cluster |
206 | | [name](#output\_name) | Name that identifies the cluster |
207 | | [task\_exec\_iam\_role\_arn](#output\_task\_exec\_iam\_role\_arn) | Task execution IAM role ARN |
208 | | [task\_exec\_iam\_role\_name](#output\_task\_exec\_iam\_role\_name) | Task execution IAM role name |
209 | | [task\_exec\_iam\_role\_unique\_id](#output\_task\_exec\_iam\_role\_unique\_id) | Stable and unique string identifying the task execution IAM role |
210 |
211 |
212 | ## License
213 |
214 | Apache-2.0 Licensed. See [LICENSE](https://github.com/terraform-aws-modules/terraform-aws-ecs/blob/master/LICENSE).
215 |
--------------------------------------------------------------------------------
/modules/cluster/main.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Cluster
3 | ################################################################################
4 |
5 | locals {
6 | execute_command_configuration = {
7 | logging = "OVERRIDE"
8 | log_configuration = {
9 | cloud_watch_log_group_name = try(aws_cloudwatch_log_group.this[0].name, null)
10 | }
11 | }
12 | }
13 |
14 | resource "aws_ecs_cluster" "this" {
15 | count = var.create ? 1 : 0
16 |
17 | name = var.cluster_name
18 |
19 | dynamic "configuration" {
20 | for_each = var.create_cloudwatch_log_group ? [var.cluster_configuration] : []
21 |
22 | content {
23 | dynamic "execute_command_configuration" {
24 | for_each = try([merge(local.execute_command_configuration, configuration.value.execute_command_configuration)], [{}])
25 |
26 | content {
27 | kms_key_id = try(execute_command_configuration.value.kms_key_id, null)
28 | logging = try(execute_command_configuration.value.logging, "DEFAULT")
29 |
30 | dynamic "log_configuration" {
31 | for_each = try([execute_command_configuration.value.log_configuration], [])
32 |
33 | content {
34 | cloud_watch_encryption_enabled = try(log_configuration.value.cloud_watch_encryption_enabled, null)
35 | cloud_watch_log_group_name = try(log_configuration.value.cloud_watch_log_group_name, null)
36 | s3_bucket_name = try(log_configuration.value.s3_bucket_name, null)
37 | s3_bucket_encryption_enabled = try(log_configuration.value.s3_bucket_encryption_enabled, null)
38 | s3_key_prefix = try(log_configuration.value.s3_key_prefix, null)
39 | }
40 | }
41 | }
42 | }
43 | }
44 | }
45 |
46 | dynamic "configuration" {
47 | for_each = !var.create_cloudwatch_log_group && length(var.cluster_configuration) > 0 ? [var.cluster_configuration] : []
48 |
49 | content {
50 | dynamic "execute_command_configuration" {
51 | for_each = try([configuration.value.execute_command_configuration], [{}])
52 |
53 | content {
54 | kms_key_id = try(execute_command_configuration.value.kms_key_id, null)
55 | logging = try(execute_command_configuration.value.logging, "DEFAULT")
56 |
57 | dynamic "log_configuration" {
58 | for_each = try([execute_command_configuration.value.log_configuration], [])
59 |
60 | content {
61 | cloud_watch_encryption_enabled = try(log_configuration.value.cloud_watch_encryption_enabled, null)
62 | cloud_watch_log_group_name = try(log_configuration.value.cloud_watch_log_group_name, null)
63 | s3_bucket_name = try(log_configuration.value.s3_bucket_name, null)
64 | s3_bucket_encryption_enabled = try(log_configuration.value.s3_bucket_encryption_enabled, null)
65 | s3_key_prefix = try(log_configuration.value.s3_key_prefix, null)
66 | }
67 | }
68 | }
69 | }
70 | }
71 | }
72 |
73 | dynamic "service_connect_defaults" {
74 | for_each = length(var.cluster_service_connect_defaults) > 0 ? [var.cluster_service_connect_defaults] : []
75 |
76 | content {
77 | namespace = service_connect_defaults.value.namespace
78 | }
79 | }
80 |
81 | dynamic "setting" {
82 | for_each = flatten([var.cluster_settings])
83 |
84 | content {
85 | name = setting.value.name
86 | value = setting.value.value
87 | }
88 | }
89 |
90 | tags = var.tags
91 | }
92 |
93 | ################################################################################
94 | # CloudWatch Log Group
95 | ################################################################################
96 | resource "aws_cloudwatch_log_group" "this" {
97 | count = var.create && var.create_cloudwatch_log_group ? 1 : 0
98 |
99 | name = try(coalesce(var.cloudwatch_log_group_name, "/aws/ecs/${var.cluster_name}"), "")
100 | retention_in_days = var.cloudwatch_log_group_retention_in_days
101 | kms_key_id = var.cloudwatch_log_group_kms_key_id
102 |
103 | tags = merge(var.tags, var.cloudwatch_log_group_tags)
104 | }
105 |
106 | ################################################################################
107 | # Cluster Capacity Providers
108 | ################################################################################
109 |
110 | locals {
111 | default_capacity_providers = merge(
112 | { for k, v in var.fargate_capacity_providers : k => v if var.default_capacity_provider_use_fargate },
113 | { for k, v in var.autoscaling_capacity_providers : k => v if !var.default_capacity_provider_use_fargate }
114 | )
115 | }
116 |
117 | resource "aws_ecs_cluster_capacity_providers" "this" {
118 | count = var.create && length(merge(var.fargate_capacity_providers, var.autoscaling_capacity_providers)) > 0 ? 1 : 0
119 |
120 | cluster_name = aws_ecs_cluster.this[0].name
121 | capacity_providers = distinct(concat(
122 | [for k, v in var.fargate_capacity_providers : try(v.name, k)],
123 | [for k, v in var.autoscaling_capacity_providers : try(v.name, k)]
124 | ))
125 |
126 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/cluster-capacity-providers.html#capacity-providers-considerations
127 | dynamic "default_capacity_provider_strategy" {
128 | for_each = local.default_capacity_providers
129 | iterator = strategy
130 |
131 | content {
132 | capacity_provider = try(strategy.value.name, strategy.key)
133 | base = try(strategy.value.default_capacity_provider_strategy.base, null)
134 | weight = try(strategy.value.default_capacity_provider_strategy.weight, null)
135 | }
136 | }
137 |
138 | depends_on = [
139 | aws_ecs_capacity_provider.this
140 | ]
141 | }
142 |
143 | ################################################################################
144 | # Capacity Provider - Autoscaling Group(s)
145 | ################################################################################
146 |
147 | resource "aws_ecs_capacity_provider" "this" {
148 | for_each = { for k, v in var.autoscaling_capacity_providers : k => v if var.create }
149 |
150 | name = try(each.value.name, each.key)
151 |
152 | auto_scaling_group_provider {
153 | auto_scaling_group_arn = each.value.auto_scaling_group_arn
154 | # When you use managed termination protection, you must also use managed scaling otherwise managed termination protection won't work
155 | managed_termination_protection = length(try([each.value.managed_scaling], [])) == 0 ? "DISABLED" : try(each.value.managed_termination_protection, null)
156 |
157 | dynamic "managed_scaling" {
158 | for_each = try([each.value.managed_scaling], [])
159 |
160 | content {
161 | instance_warmup_period = try(managed_scaling.value.instance_warmup_period, null)
162 | maximum_scaling_step_size = try(managed_scaling.value.maximum_scaling_step_size, null)
163 | minimum_scaling_step_size = try(managed_scaling.value.minimum_scaling_step_size, null)
164 | status = try(managed_scaling.value.status, null)
165 | target_capacity = try(managed_scaling.value.target_capacity, null)
166 | }
167 | }
168 | }
169 |
170 | tags = merge(var.tags, try(each.value.tags, {}))
171 | }
172 |
173 | ################################################################################
174 | # Task Execution - IAM Role
175 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
176 | ################################################################################
177 |
178 | locals {
179 | task_exec_iam_role_name = try(coalesce(var.task_exec_iam_role_name, var.cluster_name), "")
180 |
181 | create_task_exec_iam_role = var.create && var.create_task_exec_iam_role
182 | create_task_exec_policy = local.create_task_exec_iam_role && var.create_task_exec_policy
183 | }
184 |
185 | data "aws_iam_policy_document" "task_exec_assume" {
186 | count = local.create_task_exec_iam_role ? 1 : 0
187 |
188 | statement {
189 | sid = "ECSTaskExecutionAssumeRole"
190 | actions = ["sts:AssumeRole"]
191 |
192 | principals {
193 | type = "Service"
194 | identifiers = ["ecs-tasks.amazonaws.com"]
195 | }
196 | }
197 | }
198 |
199 | resource "aws_iam_role" "task_exec" {
200 | count = local.create_task_exec_iam_role ? 1 : 0
201 |
202 | name = var.task_exec_iam_role_use_name_prefix ? null : local.task_exec_iam_role_name
203 | name_prefix = var.task_exec_iam_role_use_name_prefix ? "${local.task_exec_iam_role_name}-" : null
204 | path = var.task_exec_iam_role_path
205 | description = coalesce(var.task_exec_iam_role_description, "Task execution role for ${var.cluster_name}")
206 |
207 | assume_role_policy = data.aws_iam_policy_document.task_exec_assume[0].json
208 | permissions_boundary = var.task_exec_iam_role_permissions_boundary
209 | force_detach_policies = true
210 |
211 | tags = merge(var.tags, var.task_exec_iam_role_tags)
212 | }
213 |
214 | resource "aws_iam_role_policy_attachment" "task_exec_additional" {
215 | for_each = { for k, v in var.task_exec_iam_role_policies : k => v if local.create_task_exec_iam_role }
216 |
217 | role = aws_iam_role.task_exec[0].name
218 | policy_arn = each.value
219 | }
220 |
221 | data "aws_iam_policy_document" "task_exec" {
222 | count = local.create_task_exec_policy ? 1 : 0
223 |
224 | # Pulled from AmazonECSTaskExecutionRolePolicy
225 | statement {
226 | sid = "Logs"
227 | actions = [
228 | "logs:CreateLogStream",
229 | "logs:PutLogEvents",
230 | ]
231 | resources = ["*"]
232 | }
233 |
234 | # Pulled from AmazonECSTaskExecutionRolePolicy
235 | statement {
236 | sid = "ECR"
237 | actions = [
238 | "ecr:GetAuthorizationToken",
239 | "ecr:BatchCheckLayerAvailability",
240 | "ecr:GetDownloadUrlForLayer",
241 | "ecr:BatchGetImage",
242 | ]
243 | resources = ["*"]
244 | }
245 |
246 | dynamic "statement" {
247 | for_each = length(var.task_exec_ssm_param_arns) > 0 ? [1] : []
248 |
249 | content {
250 | sid = "GetSSMParams"
251 | actions = ["ssm:GetParameters"]
252 | resources = var.task_exec_ssm_param_arns
253 | }
254 | }
255 |
256 | dynamic "statement" {
257 | for_each = length(var.task_exec_secret_arns) > 0 ? [1] : []
258 |
259 | content {
260 | sid = "GetSecrets"
261 | actions = ["secretsmanager:GetSecretValue"]
262 | resources = var.task_exec_secret_arns
263 | }
264 | }
265 |
266 | dynamic "statement" {
267 | for_each = var.task_exec_iam_statements
268 |
269 | content {
270 | sid = try(statement.value.sid, null)
271 | actions = try(statement.value.actions, null)
272 | not_actions = try(statement.value.not_actions, null)
273 | effect = try(statement.value.effect, null)
274 | resources = try(statement.value.resources, null)
275 | not_resources = try(statement.value.not_resources, null)
276 |
277 | dynamic "principals" {
278 | for_each = try(statement.value.principals, [])
279 |
280 | content {
281 | type = principals.value.type
282 | identifiers = principals.value.identifiers
283 | }
284 | }
285 |
286 | dynamic "not_principals" {
287 | for_each = try(statement.value.not_principals, [])
288 |
289 | content {
290 | type = not_principals.value.type
291 | identifiers = not_principals.value.identifiers
292 | }
293 | }
294 |
295 | dynamic "condition" {
296 | for_each = try(statement.value.conditions, [])
297 |
298 | content {
299 | test = condition.value.test
300 | values = condition.value.values
301 | variable = condition.value.variable
302 | }
303 | }
304 | }
305 | }
306 | }
307 |
308 | resource "aws_iam_policy" "task_exec" {
309 | count = local.create_task_exec_policy ? 1 : 0
310 |
311 | name = var.task_exec_iam_role_use_name_prefix ? null : local.task_exec_iam_role_name
312 | name_prefix = var.task_exec_iam_role_use_name_prefix ? "${local.task_exec_iam_role_name}-" : null
313 | description = coalesce(var.task_exec_iam_role_description, "Task execution role IAM policy")
314 | policy = data.aws_iam_policy_document.task_exec[0].json
315 |
316 | tags = merge(var.tags, var.task_exec_iam_role_tags)
317 | }
318 |
319 | resource "aws_iam_role_policy_attachment" "task_exec" {
320 | count = local.create_task_exec_policy ? 1 : 0
321 |
322 | role = aws_iam_role.task_exec[0].name
323 | policy_arn = aws_iam_policy.task_exec[0].arn
324 | }
325 |
--------------------------------------------------------------------------------
/modules/cluster/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Cluster
3 | ################################################################################
4 |
5 | output "arn" {
6 | description = "ARN that identifies the cluster"
7 | value = try(aws_ecs_cluster.this[0].arn, null)
8 | }
9 |
10 | output "id" {
11 | description = "ID that identifies the cluster"
12 | value = try(aws_ecs_cluster.this[0].id, null)
13 | }
14 |
15 | output "name" {
16 | description = "Name that identifies the cluster"
17 | value = try(aws_ecs_cluster.this[0].name, null)
18 | }
19 |
20 | ################################################################################
21 | # CloudWatch Log Group
22 | ################################################################################
23 |
24 | output "cloudwatch_log_group_name" {
25 | description = "Name of CloudWatch log group created"
26 | value = try(aws_cloudwatch_log_group.this[0].name, null)
27 | }
28 |
29 | output "cloudwatch_log_group_arn" {
30 | description = "ARN of CloudWatch log group created"
31 | value = try(aws_cloudwatch_log_group.this[0].arn, null)
32 | }
33 |
34 | ################################################################################
35 | # Cluster Capacity Providers
36 | ################################################################################
37 |
38 | output "cluster_capacity_providers" {
39 | description = "Map of cluster capacity providers attributes"
40 | value = { for k, v in aws_ecs_cluster_capacity_providers.this : v.id => v }
41 | }
42 |
43 | ################################################################################
44 | # Capacity Provider - Autoscaling Group(s)
45 | ################################################################################
46 |
47 | output "autoscaling_capacity_providers" {
48 | description = "Map of autoscaling capacity providers created and their attributes"
49 | value = aws_ecs_capacity_provider.this
50 | }
51 |
52 | ################################################################################
53 | # Task Execution - IAM Role
54 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
55 | ################################################################################
56 |
57 | output "task_exec_iam_role_name" {
58 | description = "Task execution IAM role name"
59 | value = try(aws_iam_role.task_exec[0].name, null)
60 | }
61 |
62 | output "task_exec_iam_role_arn" {
63 | description = "Task execution IAM role ARN"
64 | value = try(aws_iam_role.task_exec[0].arn, null)
65 | }
66 |
67 | output "task_exec_iam_role_unique_id" {
68 | description = "Stable and unique string identifying the task execution IAM role"
69 | value = try(aws_iam_role.task_exec[0].unique_id, null)
70 | }
71 |
--------------------------------------------------------------------------------
/modules/cluster/variables.tf:
--------------------------------------------------------------------------------
1 | variable "create" {
2 | description = "Determines whether resources will be created (affects all resources)"
3 | type = bool
4 | default = true
5 | }
6 |
7 | variable "tags" {
8 | description = "A map of tags to add to all resources"
9 | type = map(string)
10 | default = {}
11 | }
12 |
13 | ################################################################################
14 | # Cluster
15 | ################################################################################
16 |
17 | variable "cluster_name" {
18 | description = "Name of the cluster (up to 255 letters, numbers, hyphens, and underscores)"
19 | type = string
20 | default = ""
21 | }
22 |
23 | variable "cluster_configuration" {
24 | description = "The execute command configuration for the cluster"
25 | type = any
26 | default = {}
27 | }
28 |
29 | variable "cluster_settings" {
30 | description = "List of configuration block(s) with cluster settings. For example, this can be used to enable CloudWatch Container Insights for a cluster"
31 | type = any
32 | default = [
33 | {
34 | name = "containerInsights"
35 | value = "enabled"
36 | }
37 | ]
38 | }
39 |
40 | variable "cluster_service_connect_defaults" {
41 | description = "Configures a default Service Connect namespace"
42 | type = map(string)
43 | default = {}
44 | }
45 |
46 | ################################################################################
47 | # CloudWatch Log Group
48 | ################################################################################
49 |
50 | variable "create_cloudwatch_log_group" {
51 | description = "Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled"
52 | type = bool
53 | default = true
54 | }
55 |
56 | variable "cloudwatch_log_group_name" {
57 | description = "Custom name of CloudWatch Log Group for ECS cluster"
58 | type = string
59 | default = null
60 | }
61 |
62 | variable "cloudwatch_log_group_retention_in_days" {
63 | description = "Number of days to retain log events"
64 | type = number
65 | default = 90
66 | }
67 |
68 | variable "cloudwatch_log_group_kms_key_id" {
69 | description = "If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html)"
70 | type = string
71 | default = null
72 | }
73 |
74 | variable "cloudwatch_log_group_tags" {
75 | description = "A map of additional tags to add to the log group created"
76 | type = map(string)
77 | default = {}
78 | }
79 |
80 | ################################################################################
81 | # Capacity Providers
82 | ################################################################################
83 |
84 | variable "default_capacity_provider_use_fargate" {
85 | description = "Determines whether to use Fargate or autoscaling for default capacity provider strategy"
86 | type = bool
87 | default = true
88 | }
89 |
90 | variable "fargate_capacity_providers" {
91 | description = "Map of Fargate capacity provider definitions to use for the cluster"
92 | type = any
93 | default = {}
94 | }
95 |
96 | variable "autoscaling_capacity_providers" {
97 | description = "Map of autoscaling capacity provider definitions to create for the cluster"
98 | type = any
99 | default = {}
100 | }
101 |
102 | ################################################################################
103 | # Task Execution - IAM Role
104 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
105 | ################################################################################
106 |
107 | variable "create_task_exec_iam_role" {
108 | description = "Determines whether the ECS task definition IAM role should be created"
109 | type = bool
110 | default = false
111 | }
112 |
113 | variable "task_exec_iam_role_name" {
114 | description = "Name to use on IAM role created"
115 | type = string
116 | default = null
117 | }
118 |
119 | variable "task_exec_iam_role_use_name_prefix" {
120 | description = "Determines whether the IAM role name (`task_exec_iam_role_name`) is used as a prefix"
121 | type = bool
122 | default = true
123 | }
124 |
125 | variable "task_exec_iam_role_path" {
126 | description = "IAM role path"
127 | type = string
128 | default = null
129 | }
130 |
131 | variable "task_exec_iam_role_description" {
132 | description = "Description of the role"
133 | type = string
134 | default = null
135 | }
136 |
137 | variable "task_exec_iam_role_permissions_boundary" {
138 | description = "ARN of the policy that is used to set the permissions boundary for the IAM role"
139 | type = string
140 | default = null
141 | }
142 |
143 | variable "task_exec_iam_role_tags" {
144 | description = "A map of additional tags to add to the IAM role created"
145 | type = map(string)
146 | default = {}
147 | }
148 |
149 | variable "task_exec_iam_role_policies" {
150 | description = "Map of IAM role policy ARNs to attach to the IAM role"
151 | type = map(string)
152 | default = {}
153 | }
154 |
155 | variable "create_task_exec_policy" {
156 | description = "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"
157 | type = bool
158 | default = true
159 | }
160 |
161 | variable "task_exec_ssm_param_arns" {
162 | description = "List of SSM parameter ARNs the task execution role will be permitted to get/read"
163 | type = list(string)
164 | default = ["arn:aws:ssm:*:*:parameter/*"]
165 | }
166 |
167 | variable "task_exec_secret_arns" {
168 | description = "List of SecretsManager secret ARNs the task execution role will be permitted to get/read"
169 | type = list(string)
170 | default = ["arn:aws:secretsmanager:*:*:secret:*"]
171 | }
172 |
173 | variable "task_exec_iam_statements" {
174 | description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage"
175 | type = any
176 | default = {}
177 | }
178 |
--------------------------------------------------------------------------------
/modules/cluster/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/container-definition/main.tf:
--------------------------------------------------------------------------------
1 | data "aws_region" "current" {}
2 |
3 | locals {
4 | is_not_windows = contains(["LINUX"], var.operating_system_family)
5 |
6 | log_group_name = try(coalesce(var.cloudwatch_log_group_name, "/aws/ecs/${var.service}/${var.name}"), "")
7 |
8 | log_configuration = merge(
9 | { for k, v in {
10 | logDriver = "awslogs",
11 | options = {
12 | awslogs-region = data.aws_region.current.name,
13 | awslogs-group = try(aws_cloudwatch_log_group.this[0].name, ""),
14 | awslogs-stream-prefix = "ecs"
15 | },
16 | } : k => v if var.enable_cloudwatch_logging },
17 | var.log_configuration
18 | )
19 |
20 | linux_parameters = var.enable_execute_command ? merge({ "initProcessEnabled" : true }, var.linux_parameters) : merge({ "initProcessEnabled" : false }, var.linux_parameters)
21 |
22 | health_check = length(var.health_check) > 0 ? merge({
23 | interval = 30,
24 | retries = 3,
25 | timeout = 5
26 | }, var.health_check) : null
27 |
28 | definition = {
29 | command = length(var.command) > 0 ? var.command : null
30 | cpu = var.cpu
31 | dependsOn = length(var.dependencies) > 0 ? var.dependencies : null # depends_on is a reserved word
32 | disableNetworking = local.is_not_windows ? var.disable_networking : null
33 | dnsSearchDomains = local.is_not_windows && length(var.dns_search_domains) > 0 ? var.dns_search_domains : null
34 | dnsServers = local.is_not_windows && length(var.dns_servers) > 0 ? var.dns_servers : null
35 | dockerLabels = length(var.docker_labels) > 0 ? var.docker_labels : null
36 | dockerSecurityOptions = length(var.docker_security_options) > 0 ? var.docker_security_options : null
37 | entrypoint = length(var.entrypoint) > 0 ? var.entrypoint : null
38 | environment = var.environment
39 | environmentFiles = length(var.environment_files) > 0 ? var.environment_files : null
40 | essential = var.essential
41 | extraHosts = local.is_not_windows && length(var.extra_hosts) > 0 ? var.extra_hosts : null
42 | firelensConfiguration = length(var.firelens_configuration) > 0 ? var.firelens_configuration : null
43 | healthCheck = local.health_check
44 | hostname = var.hostname
45 | image = var.image
46 | interactive = var.interactive
47 | links = local.is_not_windows && length(var.links) > 0 ? var.links : null
48 | linuxParameters = local.is_not_windows && length(local.linux_parameters) > 0 ? local.linux_parameters : null
49 | logConfiguration = length(local.log_configuration) > 0 ? local.log_configuration : null
50 | memory = var.memory
51 | memoryReservation = var.memory_reservation
52 | mountPoints = var.mount_points
53 | name = var.name
54 | portMappings = var.port_mappings
55 | privileged = local.is_not_windows ? var.privileged : null
56 | pseudoTerminal = var.pseudo_terminal
57 | readonlyRootFilesystem = local.is_not_windows ? var.readonly_root_filesystem : null
58 | repositoryCredentials = length(var.repository_credentials) > 0 ? var.repository_credentials : null
59 | resourceRequirements = length(var.resource_requirements) > 0 ? var.resource_requirements : null
60 | secrets = length(var.secrets) > 0 ? var.secrets : null
61 | startTimeout = var.start_timeout
62 | stopTimeout = var.stop_timeout
63 | systemControls = length(var.system_controls) > 0 ? var.system_controls : []
64 | ulimits = local.is_not_windows && length(var.ulimits) > 0 ? var.ulimits : null
65 | user = local.is_not_windows ? var.user : null
66 | volumesFrom = var.volumes_from
67 | workingDirectory = var.working_directory
68 | }
69 |
70 | # Strip out all null values, ECS API will provide defaults in place of null/empty values
71 | container_definition = { for k, v in local.definition : k => v if v != null }
72 | }
73 |
74 | resource "aws_cloudwatch_log_group" "this" {
75 | count = var.create_cloudwatch_log_group && var.enable_cloudwatch_logging ? 1 : 0
76 |
77 | name = var.cloudwatch_log_group_use_name_prefix ? null : local.log_group_name
78 | name_prefix = var.cloudwatch_log_group_use_name_prefix ? "${local.log_group_name}-" : null
79 | retention_in_days = var.cloudwatch_log_group_retention_in_days
80 | kms_key_id = var.cloudwatch_log_group_kms_key_id
81 |
82 | tags = var.tags
83 | }
84 |
--------------------------------------------------------------------------------
/modules/container-definition/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Container Definition
3 | ################################################################################
4 |
5 | output "container_definition" {
6 | description = "Container definition"
7 | value = local.container_definition
8 | }
9 |
10 | ################################################################################
11 | # CloudWatch Log Group
12 | ################################################################################
13 |
14 | output "cloudwatch_log_group_name" {
15 | description = "Name of CloudWatch log group created"
16 | value = try(aws_cloudwatch_log_group.this[0].name, null)
17 | }
18 |
19 | output "cloudwatch_log_group_arn" {
20 | description = "ARN of CloudWatch log group created"
21 | value = try(aws_cloudwatch_log_group.this[0].arn, null)
22 | }
23 |
--------------------------------------------------------------------------------
/modules/container-definition/variables.tf:
--------------------------------------------------------------------------------
1 | variable "operating_system_family" {
2 | description = "The OS family for task"
3 | type = string
4 | default = "LINUX"
5 | }
6 |
7 | ################################################################################
8 | # Container Definition
9 | ################################################################################
10 |
11 | variable "command" {
12 | description = "The command that's passed to the container"
13 | type = list(string)
14 | default = []
15 | }
16 |
17 | variable "cpu" {
18 | description = "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"
19 | type = number
20 | default = null
21 | }
22 |
23 | variable "dependencies" {
24 | 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"
25 | type = list(object({
26 | condition = string
27 | containerName = string
28 | }))
29 | default = []
30 | }
31 |
32 | variable "disable_networking" {
33 | description = "When this parameter is true, networking is disabled within the container"
34 | type = bool
35 | default = null
36 | }
37 |
38 | variable "dns_search_domains" {
39 | description = "Container DNS search domains. A list of DNS search domains that are presented to the container"
40 | type = list(string)
41 | default = []
42 | }
43 |
44 | variable "dns_servers" {
45 | description = "Container DNS servers. This is a list of strings specifying the IP addresses of the DNS servers"
46 | type = list(string)
47 | default = []
48 | }
49 |
50 | variable "docker_labels" {
51 | description = "A key/value map of labels to add to the container"
52 | type = map(string)
53 | default = {}
54 | }
55 |
56 | variable "docker_security_options" {
57 | description = "A list of strings to provide custom labels for SELinux and AppArmor multi-level security systems. This field isn't valid for containers in tasks using the Fargate launch type"
58 | type = list(string)
59 | default = []
60 | }
61 |
62 | variable "enable_execute_command" {
63 | description = "Specifies whether to enable Amazon ECS Exec for the tasks within the service"
64 | type = bool
65 | default = false
66 | }
67 |
68 | variable "entrypoint" {
69 | description = "The entry point that is passed to the container"
70 | type = list(string)
71 | default = []
72 | }
73 |
74 | variable "environment" {
75 | description = "The environment variables to pass to the container"
76 | type = list(object({
77 | name = string
78 | value = string
79 | }))
80 | default = []
81 | }
82 |
83 | variable "environment_files" {
84 | description = "A list of files containing the environment variables to pass to a container"
85 | type = list(object({
86 | value = string
87 | type = string
88 | }))
89 | default = []
90 | }
91 |
92 | variable "essential" {
93 | description = "If the `essential` parameter of a container is marked as `true`, and that container fails or stops for any reason, all other containers that are part of the task are stopped"
94 | type = bool
95 | default = null
96 | }
97 |
98 | variable "extra_hosts" {
99 | description = "A list of hostnames and IP address mappings to append to the `/etc/hosts` file on the container"
100 | type = list(object({
101 | hostname = string
102 | ipAddress = string
103 | }))
104 | default = []
105 | }
106 |
107 | variable "firelens_configuration" {
108 | description = "The FireLens configuration for the container. This is used to specify and configure a log router for container logs. For more information, see [Custom Log Routing](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_firelens.html) in the Amazon Elastic Container Service Developer Guide"
109 | type = any
110 | default = {}
111 | }
112 |
113 | variable "health_check" {
114 | description = "The container health check command and associated configuration parameters for the container. See [HealthCheck](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html)"
115 | type = any
116 | default = {}
117 | }
118 |
119 | variable "hostname" {
120 | description = "The hostname to use for your container"
121 | type = string
122 | default = null
123 | }
124 |
125 | variable "image" {
126 | description = "The image used to start a container. This string is passed directly to the Docker daemon. By default, images in the Docker Hub registry are available. Other repositories are specified with either `repository-url/image:tag` or `repository-url/image@digest`"
127 | type = string
128 | default = null
129 | }
130 |
131 | variable "interactive" {
132 | description = "When this parameter is `true`, you can deploy containerized applications that require `stdin` or a `tty` to be allocated"
133 | type = bool
134 | default = false
135 | }
136 |
137 | variable "links" {
138 | description = "The links parameter allows containers to communicate with each other without the need for port mappings. This parameter is only supported if the network mode of a task definition is `bridge`"
139 | type = list(string)
140 | default = []
141 | }
142 |
143 | variable "linux_parameters" {
144 | description = "Linux-specific modifications that are applied to the container, such as Linux kernel capabilities. For more information see [KernelCapabilities](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_KernelCapabilities.html)"
145 | type = any
146 | default = {}
147 | }
148 |
149 | variable "log_configuration" {
150 | description = "The log configuration for the container. For more information see [LogConfiguration](https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_LogConfiguration.html)"
151 | type = any
152 | default = {}
153 | }
154 |
155 | variable "memory" {
156 | description = "The amount (in MiB) of memory to present to the container. If your container attempts to exceed the memory specified here, the container is killed. The total amount of memory reserved for all containers within a task must be lower than the task `memory` value, if one is specified"
157 | type = number
158 | default = null
159 | }
160 |
161 | variable "memory_reservation" {
162 | description = "The soft limit (in MiB) of memory to reserve for the container. When system memory is under heavy contention, Docker attempts to keep the container memory to this soft limit. However, your container can consume more memory when it needs to, up to either the hard limit specified with the `memory` parameter (if applicable), or all of the available memory on the container instance"
163 | type = number
164 | default = null
165 | }
166 |
167 | variable "mount_points" {
168 | description = "The mount points for data volumes in your container"
169 | type = list(any)
170 | default = []
171 | }
172 |
173 | variable "name" {
174 | description = "The name of a container. If you're linking multiple containers together in a task definition, the name of one container can be entered in the links of another container to connect the containers. Up to 255 letters (uppercase and lowercase), numbers, underscores, and hyphens are allowed"
175 | type = string
176 | default = null
177 | }
178 |
179 | variable "port_mappings" {
180 | description = "The list of port mappings for the container. Port mappings allow containers to access ports on the host container instance to send or receive traffic. For task definitions that use the awsvpc network mode, only specify the containerPort. The hostPort can be left blank or it must be the same value as the containerPort"
181 | type = list(any)
182 | default = []
183 | }
184 |
185 | variable "privileged" {
186 | description = "When this parameter is true, the container is given elevated privileges on the host container instance (similar to the root user)"
187 | type = bool
188 | default = false
189 | }
190 |
191 | variable "pseudo_terminal" {
192 | description = "When this parameter is true, a `TTY` is allocated"
193 | type = bool
194 | default = false
195 | }
196 |
197 | variable "readonly_root_filesystem" {
198 | description = "When this parameter is true, the container is given read-only access to its root file system"
199 | type = bool
200 | default = true
201 | }
202 |
203 | variable "repository_credentials" {
204 | description = "Container repository credentials; required when using a private repo. This map currently supports a single key; \"credentialsParameter\", which should be the ARN of a Secrets Manager's secret holding the credentials"
205 | type = map(string)
206 | default = {}
207 | }
208 |
209 | variable "resource_requirements" {
210 | description = "The type and amount of a resource to assign to a container. The only supported resource is a GPU"
211 | type = list(object({
212 | type = string
213 | value = string
214 | }))
215 | default = []
216 | }
217 |
218 | variable "secrets" {
219 | description = "The secrets to pass to the container. For more information, see [Specifying Sensitive Data](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/specifying-sensitive-data.html) in the Amazon Elastic Container Service Developer Guide"
220 | type = list(object({
221 | name = string
222 | valueFrom = string
223 | }))
224 | default = []
225 | }
226 |
227 | variable "start_timeout" {
228 | description = "Time duration (in seconds) to wait before giving up on resolving dependencies for a container"
229 | type = number
230 | default = 30
231 | }
232 |
233 | variable "stop_timeout" {
234 | description = "Time duration (in seconds) to wait before the container is forcefully killed if it doesn't exit normally on its own"
235 | type = number
236 | default = 120
237 | }
238 |
239 | variable "system_controls" {
240 | description = "A list of namespaced kernel parameters to set in the container"
241 | type = list(map(string))
242 | default = []
243 | }
244 |
245 | variable "ulimits" {
246 | description = "A list of ulimits to set in the container. If a ulimit value is specified in a task definition, it overrides the default values set by Docker"
247 | type = list(object({
248 | hardLimit = number
249 | name = string
250 | softLimit = number
251 | }))
252 | default = []
253 | }
254 |
255 | variable "user" {
256 | description = "The user to run as inside the container. Can be any of these formats: user, user:group, uid, uid:gid, user:gid, uid:group. The default (null) will use the container's configured `USER` directive or root if not set"
257 | type = string
258 | default = null
259 | }
260 |
261 | variable "volumes_from" {
262 | description = "Data volumes to mount from another container"
263 | type = list(any)
264 | default = []
265 | }
266 |
267 | variable "working_directory" {
268 | description = "The working directory to run commands inside the container"
269 | type = string
270 | default = null
271 | }
272 |
273 | ################################################################################
274 | # CloudWatch Log Group
275 | ################################################################################
276 |
277 | variable "service" {
278 | description = "The name of the service that the container definition is associated with"
279 | type = string
280 | default = ""
281 | }
282 |
283 | variable "enable_cloudwatch_logging" {
284 | description = "Determines whether CloudWatch logging is configured for this container definition. Set to `false` to use other logging drivers"
285 | type = bool
286 | default = true
287 | }
288 |
289 | variable "create_cloudwatch_log_group" {
290 | description = "Determines whether a log group is created by this module. If not, AWS will automatically create one if logging is enabled"
291 | type = bool
292 | default = true
293 | }
294 |
295 | variable "cloudwatch_log_group_name" {
296 | description = "Custom name of CloudWatch log group for a service associated with the container definition"
297 | type = string
298 | default = null
299 | }
300 |
301 | variable "cloudwatch_log_group_use_name_prefix" {
302 | description = "Determines whether the log group name should be used as a prefix"
303 | type = bool
304 | default = false
305 | }
306 |
307 | variable "cloudwatch_log_group_retention_in_days" {
308 | description = "Number of days to retain log events. Default is 30 days"
309 | type = number
310 | default = 30
311 | }
312 |
313 | variable "cloudwatch_log_group_kms_key_id" {
314 | description = "If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html)"
315 | type = string
316 | default = null
317 | }
318 |
319 | variable "tags" {
320 | description = "A map of tags to add to all resources"
321 | type = map(string)
322 | default = {}
323 | }
324 |
--------------------------------------------------------------------------------
/modules/container-definition/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/modules/service/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Service
3 | ################################################################################
4 |
5 | output "id" {
6 | description = "ARN that identifies the service"
7 | value = try(aws_ecs_service.this[0].id, aws_ecs_service.ignore_task_definition[0].id, null)
8 | }
9 |
10 | output "name" {
11 | description = "Name of the service"
12 | value = try(aws_ecs_service.this[0].name, aws_ecs_service.ignore_task_definition[0].name, null)
13 | }
14 |
15 | ################################################################################
16 | # IAM Role
17 | ################################################################################
18 |
19 | output "iam_role_name" {
20 | description = "Service IAM role name"
21 | value = try(aws_iam_role.service[0].name, null)
22 | }
23 |
24 | output "iam_role_arn" {
25 | description = "Service IAM role ARN"
26 | value = try(aws_iam_role.service[0].arn, var.iam_role_arn)
27 | }
28 |
29 | output "iam_role_unique_id" {
30 | description = "Stable and unique string identifying the service IAM role"
31 | value = try(aws_iam_role.service[0].unique_id, null)
32 | }
33 |
34 | ################################################################################
35 | # Container Definition
36 | ################################################################################
37 |
38 | output "container_definitions" {
39 | description = "Container definitions"
40 | value = module.container_definition
41 | }
42 |
43 | ################################################################################
44 | # Task Definition
45 | ################################################################################
46 |
47 | output "task_definition_arn" {
48 | description = "Full ARN of the Task Definition (including both `family` and `revision`)"
49 | value = try(aws_ecs_task_definition.this[0].arn, var.task_definition_arn)
50 | }
51 |
52 | output "task_definition_revision" {
53 | description = "Revision of the task in a particular family"
54 | value = try(aws_ecs_task_definition.this[0].revision, null)
55 | }
56 |
57 | output "task_definition_family" {
58 | description = "The unique name of the task definition"
59 | value = try(aws_ecs_task_definition.this[0].family, null)
60 | }
61 |
62 | output "task_definition_family_revision" {
63 | description = "The family and revision (family:revision) of the task definition"
64 | value = "${try(aws_ecs_task_definition.this[0].family, "")}:${local.max_task_def_revision}"
65 | }
66 |
67 | ################################################################################
68 | # Task Execution - IAM Role
69 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
70 | ################################################################################
71 |
72 | output "task_exec_iam_role_name" {
73 | description = "Task execution IAM role name"
74 | value = try(aws_iam_role.task_exec[0].name, null)
75 | }
76 |
77 | output "task_exec_iam_role_arn" {
78 | description = "Task execution IAM role ARN"
79 | value = try(aws_iam_role.task_exec[0].arn, var.task_exec_iam_role_arn)
80 | }
81 |
82 | output "task_exec_iam_role_unique_id" {
83 | description = "Stable and unique string identifying the task execution IAM role"
84 | value = try(aws_iam_role.task_exec[0].unique_id, null)
85 | }
86 |
87 | ################################################################################
88 | # Tasks - IAM role
89 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html
90 | ################################################################################
91 |
92 | output "tasks_iam_role_name" {
93 | description = "Tasks IAM role name"
94 | value = try(aws_iam_role.tasks[0].name, null)
95 | }
96 |
97 | output "tasks_iam_role_arn" {
98 | description = "Tasks IAM role ARN"
99 | value = try(aws_iam_role.tasks[0].arn, var.tasks_iam_role_arn)
100 | }
101 |
102 | output "tasks_iam_role_unique_id" {
103 | description = "Stable and unique string identifying the tasks IAM role"
104 | value = try(aws_iam_role.tasks[0].unique_id, null)
105 | }
106 |
107 | ################################################################################
108 | # Task Set
109 | ################################################################################
110 |
111 | output "task_set_id" {
112 | description = "The ID of the task set"
113 | value = try(aws_ecs_task_set.this[0].task_set_id, aws_ecs_task_set.ignore_task_definition[0].task_set_id, null)
114 | }
115 |
116 | output "task_set_arn" {
117 | description = "The Amazon Resource Name (ARN) that identifies the task set"
118 | value = try(aws_ecs_task_set.this[0].arn, aws_ecs_task_set.ignore_task_definition[0].arn, null)
119 | }
120 |
121 | output "task_set_stability_status" {
122 | description = "The stability status. This indicates whether the task set has reached a steady state"
123 | value = try(aws_ecs_task_set.this[0].stability_status, aws_ecs_task_set.ignore_task_definition[0].stability_status, null)
124 | }
125 |
126 | output "task_set_status" {
127 | description = "The status of the task set"
128 | value = try(aws_ecs_task_set.this[0].status, aws_ecs_task_set.ignore_task_definition[0].status, null)
129 | }
130 |
131 | ################################################################################
132 | # Autoscaling
133 | ################################################################################
134 |
135 | output "autoscaling_policies" {
136 | description = "Map of autoscaling policies and their attributes"
137 | value = aws_appautoscaling_policy.this
138 | }
139 |
140 | output "autoscaling_scheduled_actions" {
141 | description = "Map of autoscaling scheduled actions and their attributes"
142 | value = aws_appautoscaling_scheduled_action.this
143 | }
144 |
145 | ################################################################################
146 | # Security Group
147 | ################################################################################
148 |
149 | output "security_group_arn" {
150 | description = "Amazon Resource Name (ARN) of the security group"
151 | value = try(aws_security_group.this[0].arn, null)
152 | }
153 |
154 | output "security_group_id" {
155 | description = "ID of the security group"
156 | value = try(aws_security_group.this[0].id, null)
157 | }
158 |
--------------------------------------------------------------------------------
/modules/service/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | ################################################################################
2 | # Cluster
3 | ################################################################################
4 |
5 | output "cluster_arn" {
6 | description = "ARN that identifies the cluster"
7 | value = module.cluster.arn
8 | }
9 |
10 | output "cluster_id" {
11 | description = "ID that identifies the cluster"
12 | value = module.cluster.id
13 | }
14 |
15 | output "cluster_name" {
16 | description = "Name that identifies the cluster"
17 | value = module.cluster.name
18 | }
19 |
20 | output "cloudwatch_log_group_name" {
21 | description = "Name of CloudWatch log group created"
22 | value = module.cluster.cloudwatch_log_group_name
23 | }
24 |
25 | output "cloudwatch_log_group_arn" {
26 | description = "ARN of CloudWatch log group created"
27 | value = module.cluster.cloudwatch_log_group_arn
28 | }
29 |
30 | output "cluster_capacity_providers" {
31 | description = "Map of cluster capacity providers attributes"
32 | value = module.cluster.cluster_capacity_providers
33 | }
34 |
35 | output "autoscaling_capacity_providers" {
36 | description = "Map of autoscaling capacity providers created and their attributes"
37 | value = module.cluster.autoscaling_capacity_providers
38 | }
39 |
40 | output "task_exec_iam_role_name" {
41 | description = "Task execution IAM role name"
42 | value = module.cluster.task_exec_iam_role_name
43 | }
44 |
45 | output "task_exec_iam_role_arn" {
46 | description = "Task execution IAM role ARN"
47 | value = module.cluster.task_exec_iam_role_arn
48 | }
49 |
50 | output "task_exec_iam_role_unique_id" {
51 | description = "Stable and unique string identifying the task execution IAM role"
52 | value = module.cluster.task_exec_iam_role_unique_id
53 | }
54 |
55 | ################################################################################
56 | # Service(s)
57 | ################################################################################
58 |
59 | output "services" {
60 | description = "Map of services created and their attributes"
61 | value = module.service
62 | }
63 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | variable "create" {
2 | description = "Determines whether resources will be created (affects all resources)"
3 | type = bool
4 | default = true
5 | }
6 |
7 | variable "tags" {
8 | description = "A map of tags to add to all resources"
9 | type = map(string)
10 | default = {}
11 | }
12 |
13 | ################################################################################
14 | # Cluster
15 | ################################################################################
16 |
17 | variable "cluster_name" {
18 | description = "Name of the cluster (up to 255 letters, numbers, hyphens, and underscores)"
19 | type = string
20 | default = ""
21 | }
22 |
23 | variable "cluster_configuration" {
24 | description = "The execute command configuration for the cluster"
25 | type = any
26 | default = {}
27 | }
28 |
29 | variable "cluster_settings" {
30 | description = "List of configuration block(s) with cluster settings. For example, this can be used to enable CloudWatch Container Insights for a cluster"
31 | type = any
32 | default = [
33 | {
34 | name = "containerInsights"
35 | value = "enabled"
36 | }
37 | ]
38 | }
39 |
40 | variable "cluster_service_connect_defaults" {
41 | description = "Configures a default Service Connect namespace"
42 | type = map(string)
43 | default = {}
44 | }
45 |
46 | variable "cluster_tags" {
47 | description = "A map of additional tags to add to the cluster"
48 | type = map(string)
49 | default = {}
50 | }
51 |
52 | ################################################################################
53 | # CloudWatch Log Group
54 | ################################################################################
55 |
56 | variable "create_cloudwatch_log_group" {
57 | description = "Determines whether a log group is created by this module for the cluster logs. If not, AWS will automatically create one if logging is enabled"
58 | type = bool
59 | default = true
60 | }
61 |
62 | variable "cloudwatch_log_group_name" {
63 | description = "Custom name of CloudWatch Log Group for ECS cluster"
64 | type = string
65 | default = null
66 | }
67 |
68 | variable "cloudwatch_log_group_retention_in_days" {
69 | description = "Number of days to retain log events"
70 | type = number
71 | default = 90
72 | }
73 |
74 | variable "cloudwatch_log_group_kms_key_id" {
75 | description = "If a KMS Key ARN is set, this key will be used to encrypt the corresponding log group. Please be sure that the KMS Key has an appropriate key policy (https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html)"
76 | type = string
77 | default = null
78 | }
79 |
80 | variable "cloudwatch_log_group_tags" {
81 | description = "A map of additional tags to add to the log group created"
82 | type = map(string)
83 | default = {}
84 | }
85 |
86 | ################################################################################
87 | # Capacity Providers
88 | ################################################################################
89 |
90 | variable "default_capacity_provider_use_fargate" {
91 | description = "Determines whether to use Fargate or autoscaling for default capacity provider strategy"
92 | type = bool
93 | default = true
94 | }
95 |
96 | variable "fargate_capacity_providers" {
97 | description = "Map of Fargate capacity provider definitions to use for the cluster"
98 | type = any
99 | default = {}
100 | }
101 |
102 | variable "autoscaling_capacity_providers" {
103 | description = "Map of autoscaling capacity provider definitions to create for the cluster"
104 | type = any
105 | default = {}
106 | }
107 |
108 | ################################################################################
109 | # Task Execution - IAM Role
110 | # https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
111 | ################################################################################
112 |
113 | variable "create_task_exec_iam_role" {
114 | description = "Determines whether the ECS task definition IAM role should be created"
115 | type = bool
116 | default = false
117 | }
118 |
119 | variable "task_exec_iam_role_name" {
120 | description = "Name to use on IAM role created"
121 | type = string
122 | default = null
123 | }
124 |
125 | variable "task_exec_iam_role_use_name_prefix" {
126 | description = "Determines whether the IAM role name (`task_exec_iam_role_name`) is used as a prefix"
127 | type = bool
128 | default = true
129 | }
130 |
131 | variable "task_exec_iam_role_path" {
132 | description = "IAM role path"
133 | type = string
134 | default = null
135 | }
136 |
137 | variable "task_exec_iam_role_description" {
138 | description = "Description of the role"
139 | type = string
140 | default = null
141 | }
142 |
143 | variable "task_exec_iam_role_permissions_boundary" {
144 | description = "ARN of the policy that is used to set the permissions boundary for the IAM role"
145 | type = string
146 | default = null
147 | }
148 |
149 | variable "task_exec_iam_role_tags" {
150 | description = "A map of additional tags to add to the IAM role created"
151 | type = map(string)
152 | default = {}
153 | }
154 |
155 | variable "task_exec_iam_role_policies" {
156 | description = "Map of IAM role policy ARNs to attach to the IAM role"
157 | type = map(string)
158 | default = {}
159 | }
160 |
161 | variable "create_task_exec_policy" {
162 | description = "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"
163 | type = bool
164 | default = true
165 | }
166 |
167 | variable "task_exec_ssm_param_arns" {
168 | description = "List of SSM parameter ARNs the task execution role will be permitted to get/read"
169 | type = list(string)
170 | default = ["arn:aws:ssm:*:*:parameter/*"]
171 | }
172 |
173 | variable "task_exec_secret_arns" {
174 | description = "List of SecretsManager secret ARNs the task execution role will be permitted to get/read"
175 | type = list(string)
176 | default = ["arn:aws:secretsmanager:*:*:secret:*"]
177 | }
178 |
179 | variable "task_exec_iam_statements" {
180 | description = "A map of IAM policy [statements](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document#statement) for custom permission usage"
181 | type = any
182 | default = {}
183 | }
184 |
185 | ################################################################################
186 | # Service(s)
187 | ################################################################################
188 |
189 | variable "services" {
190 | description = "Map of service definitions to create"
191 | type = any
192 | default = {}
193 | }
194 |
--------------------------------------------------------------------------------
/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/wrappers/README.md:
--------------------------------------------------------------------------------
1 | # Wrapper for the root module
2 |
3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
4 |
5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
6 |
7 | This wrapper does not implement any extra functionality.
8 |
9 | ## Usage with Terragrunt
10 |
11 | `terragrunt.hcl`:
12 |
13 | ```hcl
14 | terraform {
15 | source = "tfr:///terraform-aws-modules/ecs/aws//wrappers"
16 | # Alternative source:
17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-ecs.git//wrappers?ref=master"
18 | }
19 |
20 | inputs = {
21 | defaults = { # Default values
22 | create = true
23 | tags = {
24 | Terraform = "true"
25 | Environment = "dev"
26 | }
27 | }
28 |
29 | items = {
30 | my-item = {
31 | # omitted... can be any argument supported by the module
32 | }
33 | my-second-item = {
34 | # omitted... can be any argument supported by the module
35 | }
36 | # omitted...
37 | }
38 | }
39 | ```
40 |
41 | ## Usage with Terraform
42 |
43 | ```hcl
44 | module "wrapper" {
45 | source = "terraform-aws-modules/ecs/aws//wrappers"
46 |
47 | defaults = { # Default values
48 | create = true
49 | tags = {
50 | Terraform = "true"
51 | Environment = "dev"
52 | }
53 | }
54 |
55 | items = {
56 | my-item = {
57 | # omitted... can be any argument supported by the module
58 | }
59 | my-second-item = {
60 | # omitted... can be any argument supported by the module
61 | }
62 | # omitted...
63 | }
64 | }
65 | ```
66 |
67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer
68 |
69 | `eu-west-1/s3-buckets/terragrunt.hcl`:
70 |
71 | ```hcl
72 | terraform {
73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74 | # Alternative source:
75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76 | }
77 |
78 | inputs = {
79 | defaults = {
80 | force_destroy = true
81 |
82 | attach_elb_log_delivery_policy = true
83 | attach_lb_log_delivery_policy = true
84 | attach_deny_insecure_transport_policy = true
85 | attach_require_latest_tls_policy = true
86 | }
87 |
88 | items = {
89 | bucket1 = {
90 | bucket = "my-random-bucket-1"
91 | }
92 | bucket2 = {
93 | bucket = "my-random-bucket-2"
94 | tags = {
95 | Secure = "probably"
96 | }
97 | }
98 | }
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/wrappers/cluster/README.md:
--------------------------------------------------------------------------------
1 | # Wrapper for module: `modules/cluster`
2 |
3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
4 |
5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
6 |
7 | This wrapper does not implement any extra functionality.
8 |
9 | ## Usage with Terragrunt
10 |
11 | `terragrunt.hcl`:
12 |
13 | ```hcl
14 | terraform {
15 | source = "tfr:///terraform-aws-modules/ecs/aws//wrappers/cluster"
16 | # Alternative source:
17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-ecs.git//wrappers/cluster?ref=master"
18 | }
19 |
20 | inputs = {
21 | defaults = { # Default values
22 | create = true
23 | tags = {
24 | Terraform = "true"
25 | Environment = "dev"
26 | }
27 | }
28 |
29 | items = {
30 | my-item = {
31 | # omitted... can be any argument supported by the module
32 | }
33 | my-second-item = {
34 | # omitted... can be any argument supported by the module
35 | }
36 | # omitted...
37 | }
38 | }
39 | ```
40 |
41 | ## Usage with Terraform
42 |
43 | ```hcl
44 | module "wrapper" {
45 | source = "terraform-aws-modules/ecs/aws//wrappers/cluster"
46 |
47 | defaults = { # Default values
48 | create = true
49 | tags = {
50 | Terraform = "true"
51 | Environment = "dev"
52 | }
53 | }
54 |
55 | items = {
56 | my-item = {
57 | # omitted... can be any argument supported by the module
58 | }
59 | my-second-item = {
60 | # omitted... can be any argument supported by the module
61 | }
62 | # omitted...
63 | }
64 | }
65 | ```
66 |
67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer
68 |
69 | `eu-west-1/s3-buckets/terragrunt.hcl`:
70 |
71 | ```hcl
72 | terraform {
73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74 | # Alternative source:
75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76 | }
77 |
78 | inputs = {
79 | defaults = {
80 | force_destroy = true
81 |
82 | attach_elb_log_delivery_policy = true
83 | attach_lb_log_delivery_policy = true
84 | attach_deny_insecure_transport_policy = true
85 | attach_require_latest_tls_policy = true
86 | }
87 |
88 | items = {
89 | bucket1 = {
90 | bucket = "my-random-bucket-1"
91 | }
92 | bucket2 = {
93 | bucket = "my-random-bucket-2"
94 | tags = {
95 | Secure = "probably"
96 | }
97 | }
98 | }
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/wrappers/cluster/main.tf:
--------------------------------------------------------------------------------
1 | module "wrapper" {
2 | source = "../../modules/cluster"
3 |
4 | for_each = var.items
5 |
6 | autoscaling_capacity_providers = try(each.value.autoscaling_capacity_providers, var.defaults.autoscaling_capacity_providers, {})
7 | cloudwatch_log_group_kms_key_id = try(each.value.cloudwatch_log_group_kms_key_id, var.defaults.cloudwatch_log_group_kms_key_id, null)
8 | cloudwatch_log_group_name = try(each.value.cloudwatch_log_group_name, var.defaults.cloudwatch_log_group_name, null)
9 | cloudwatch_log_group_retention_in_days = try(each.value.cloudwatch_log_group_retention_in_days, var.defaults.cloudwatch_log_group_retention_in_days, 90)
10 | cloudwatch_log_group_tags = try(each.value.cloudwatch_log_group_tags, var.defaults.cloudwatch_log_group_tags, {})
11 | cluster_configuration = try(each.value.cluster_configuration, var.defaults.cluster_configuration, {})
12 | cluster_name = try(each.value.cluster_name, var.defaults.cluster_name, "")
13 | cluster_service_connect_defaults = try(each.value.cluster_service_connect_defaults, var.defaults.cluster_service_connect_defaults, {})
14 | cluster_settings = try(each.value.cluster_settings, var.defaults.cluster_settings, [
15 | {
16 | name = "containerInsights"
17 | value = "enabled"
18 | }
19 | ])
20 | create = try(each.value.create, var.defaults.create, true)
21 | create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, true)
22 | create_task_exec_iam_role = try(each.value.create_task_exec_iam_role, var.defaults.create_task_exec_iam_role, false)
23 | create_task_exec_policy = try(each.value.create_task_exec_policy, var.defaults.create_task_exec_policy, true)
24 | default_capacity_provider_use_fargate = try(each.value.default_capacity_provider_use_fargate, var.defaults.default_capacity_provider_use_fargate, true)
25 | fargate_capacity_providers = try(each.value.fargate_capacity_providers, var.defaults.fargate_capacity_providers, {})
26 | tags = try(each.value.tags, var.defaults.tags, {})
27 | task_exec_iam_role_description = try(each.value.task_exec_iam_role_description, var.defaults.task_exec_iam_role_description, null)
28 | task_exec_iam_role_name = try(each.value.task_exec_iam_role_name, var.defaults.task_exec_iam_role_name, null)
29 | task_exec_iam_role_path = try(each.value.task_exec_iam_role_path, var.defaults.task_exec_iam_role_path, null)
30 | task_exec_iam_role_permissions_boundary = try(each.value.task_exec_iam_role_permissions_boundary, var.defaults.task_exec_iam_role_permissions_boundary, null)
31 | task_exec_iam_role_policies = try(each.value.task_exec_iam_role_policies, var.defaults.task_exec_iam_role_policies, {})
32 | task_exec_iam_role_tags = try(each.value.task_exec_iam_role_tags, var.defaults.task_exec_iam_role_tags, {})
33 | task_exec_iam_role_use_name_prefix = try(each.value.task_exec_iam_role_use_name_prefix, var.defaults.task_exec_iam_role_use_name_prefix, true)
34 | task_exec_iam_statements = try(each.value.task_exec_iam_statements, var.defaults.task_exec_iam_statements, {})
35 | task_exec_secret_arns = try(each.value.task_exec_secret_arns, var.defaults.task_exec_secret_arns, ["arn:aws:secretsmanager:*:*:secret:*"])
36 | task_exec_ssm_param_arns = try(each.value.task_exec_ssm_param_arns, var.defaults.task_exec_ssm_param_arns, ["arn:aws:ssm:*:*:parameter/*"])
37 | }
38 |
--------------------------------------------------------------------------------
/wrappers/cluster/outputs.tf:
--------------------------------------------------------------------------------
1 | output "wrapper" {
2 | description = "Map of outputs of a wrapper."
3 | value = module.wrapper
4 | # sensitive = false # No sensitive module output found
5 | }
6 |
--------------------------------------------------------------------------------
/wrappers/cluster/variables.tf:
--------------------------------------------------------------------------------
1 | variable "defaults" {
2 | description = "Map of default values which will be used for each item."
3 | type = any
4 | default = {}
5 | }
6 |
7 | variable "items" {
8 | description = "Maps of items to create a wrapper from. Values are passed through to the module."
9 | type = any
10 | default = {}
11 | }
12 |
--------------------------------------------------------------------------------
/wrappers/cluster/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/wrappers/container-definition/README.md:
--------------------------------------------------------------------------------
1 | # Wrapper for module: `modules/container-definition`
2 |
3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
4 |
5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
6 |
7 | This wrapper does not implement any extra functionality.
8 |
9 | ## Usage with Terragrunt
10 |
11 | `terragrunt.hcl`:
12 |
13 | ```hcl
14 | terraform {
15 | source = "tfr:///terraform-aws-modules/ecs/aws//wrappers/container-definition"
16 | # Alternative source:
17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-ecs.git//wrappers/container-definition?ref=master"
18 | }
19 |
20 | inputs = {
21 | defaults = { # Default values
22 | create = true
23 | tags = {
24 | Terraform = "true"
25 | Environment = "dev"
26 | }
27 | }
28 |
29 | items = {
30 | my-item = {
31 | # omitted... can be any argument supported by the module
32 | }
33 | my-second-item = {
34 | # omitted... can be any argument supported by the module
35 | }
36 | # omitted...
37 | }
38 | }
39 | ```
40 |
41 | ## Usage with Terraform
42 |
43 | ```hcl
44 | module "wrapper" {
45 | source = "terraform-aws-modules/ecs/aws//wrappers/container-definition"
46 |
47 | defaults = { # Default values
48 | create = true
49 | tags = {
50 | Terraform = "true"
51 | Environment = "dev"
52 | }
53 | }
54 |
55 | items = {
56 | my-item = {
57 | # omitted... can be any argument supported by the module
58 | }
59 | my-second-item = {
60 | # omitted... can be any argument supported by the module
61 | }
62 | # omitted...
63 | }
64 | }
65 | ```
66 |
67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer
68 |
69 | `eu-west-1/s3-buckets/terragrunt.hcl`:
70 |
71 | ```hcl
72 | terraform {
73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74 | # Alternative source:
75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76 | }
77 |
78 | inputs = {
79 | defaults = {
80 | force_destroy = true
81 |
82 | attach_elb_log_delivery_policy = true
83 | attach_lb_log_delivery_policy = true
84 | attach_deny_insecure_transport_policy = true
85 | attach_require_latest_tls_policy = true
86 | }
87 |
88 | items = {
89 | bucket1 = {
90 | bucket = "my-random-bucket-1"
91 | }
92 | bucket2 = {
93 | bucket = "my-random-bucket-2"
94 | tags = {
95 | Secure = "probably"
96 | }
97 | }
98 | }
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/wrappers/container-definition/main.tf:
--------------------------------------------------------------------------------
1 | module "wrapper" {
2 | source = "../../modules/container-definition"
3 |
4 | for_each = var.items
5 |
6 | cloudwatch_log_group_kms_key_id = try(each.value.cloudwatch_log_group_kms_key_id, var.defaults.cloudwatch_log_group_kms_key_id, null)
7 | cloudwatch_log_group_name = try(each.value.cloudwatch_log_group_name, var.defaults.cloudwatch_log_group_name, null)
8 | cloudwatch_log_group_retention_in_days = try(each.value.cloudwatch_log_group_retention_in_days, var.defaults.cloudwatch_log_group_retention_in_days, 30)
9 | cloudwatch_log_group_use_name_prefix = try(each.value.cloudwatch_log_group_use_name_prefix, var.defaults.cloudwatch_log_group_use_name_prefix, false)
10 | command = try(each.value.command, var.defaults.command, [])
11 | cpu = try(each.value.cpu, var.defaults.cpu, null)
12 | create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, true)
13 | dependencies = try(each.value.dependencies, var.defaults.dependencies, [])
14 | disable_networking = try(each.value.disable_networking, var.defaults.disable_networking, null)
15 | dns_search_domains = try(each.value.dns_search_domains, var.defaults.dns_search_domains, [])
16 | dns_servers = try(each.value.dns_servers, var.defaults.dns_servers, [])
17 | docker_labels = try(each.value.docker_labels, var.defaults.docker_labels, {})
18 | docker_security_options = try(each.value.docker_security_options, var.defaults.docker_security_options, [])
19 | enable_cloudwatch_logging = try(each.value.enable_cloudwatch_logging, var.defaults.enable_cloudwatch_logging, true)
20 | enable_execute_command = try(each.value.enable_execute_command, var.defaults.enable_execute_command, false)
21 | entrypoint = try(each.value.entrypoint, var.defaults.entrypoint, [])
22 | environment = try(each.value.environment, var.defaults.environment, [])
23 | environment_files = try(each.value.environment_files, var.defaults.environment_files, [])
24 | essential = try(each.value.essential, var.defaults.essential, null)
25 | extra_hosts = try(each.value.extra_hosts, var.defaults.extra_hosts, [])
26 | firelens_configuration = try(each.value.firelens_configuration, var.defaults.firelens_configuration, {})
27 | health_check = try(each.value.health_check, var.defaults.health_check, {})
28 | hostname = try(each.value.hostname, var.defaults.hostname, null)
29 | image = try(each.value.image, var.defaults.image, null)
30 | interactive = try(each.value.interactive, var.defaults.interactive, false)
31 | links = try(each.value.links, var.defaults.links, [])
32 | linux_parameters = try(each.value.linux_parameters, var.defaults.linux_parameters, {})
33 | log_configuration = try(each.value.log_configuration, var.defaults.log_configuration, {})
34 | memory = try(each.value.memory, var.defaults.memory, null)
35 | memory_reservation = try(each.value.memory_reservation, var.defaults.memory_reservation, null)
36 | mount_points = try(each.value.mount_points, var.defaults.mount_points, [])
37 | name = try(each.value.name, var.defaults.name, null)
38 | operating_system_family = try(each.value.operating_system_family, var.defaults.operating_system_family, "LINUX")
39 | port_mappings = try(each.value.port_mappings, var.defaults.port_mappings, [])
40 | privileged = try(each.value.privileged, var.defaults.privileged, false)
41 | pseudo_terminal = try(each.value.pseudo_terminal, var.defaults.pseudo_terminal, false)
42 | readonly_root_filesystem = try(each.value.readonly_root_filesystem, var.defaults.readonly_root_filesystem, true)
43 | repository_credentials = try(each.value.repository_credentials, var.defaults.repository_credentials, {})
44 | resource_requirements = try(each.value.resource_requirements, var.defaults.resource_requirements, [])
45 | secrets = try(each.value.secrets, var.defaults.secrets, [])
46 | service = try(each.value.service, var.defaults.service, "")
47 | start_timeout = try(each.value.start_timeout, var.defaults.start_timeout, 30)
48 | stop_timeout = try(each.value.stop_timeout, var.defaults.stop_timeout, 120)
49 | system_controls = try(each.value.system_controls, var.defaults.system_controls, [])
50 | tags = try(each.value.tags, var.defaults.tags, {})
51 | ulimits = try(each.value.ulimits, var.defaults.ulimits, [])
52 | user = try(each.value.user, var.defaults.user, null)
53 | volumes_from = try(each.value.volumes_from, var.defaults.volumes_from, [])
54 | working_directory = try(each.value.working_directory, var.defaults.working_directory, null)
55 | }
56 |
--------------------------------------------------------------------------------
/wrappers/container-definition/outputs.tf:
--------------------------------------------------------------------------------
1 | output "wrapper" {
2 | description = "Map of outputs of a wrapper."
3 | value = module.wrapper
4 | # sensitive = false # No sensitive module output found
5 | }
6 |
--------------------------------------------------------------------------------
/wrappers/container-definition/variables.tf:
--------------------------------------------------------------------------------
1 | variable "defaults" {
2 | description = "Map of default values which will be used for each item."
3 | type = any
4 | default = {}
5 | }
6 |
7 | variable "items" {
8 | description = "Maps of items to create a wrapper from. Values are passed through to the module."
9 | type = any
10 | default = {}
11 | }
12 |
--------------------------------------------------------------------------------
/wrappers/container-definition/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/wrappers/main.tf:
--------------------------------------------------------------------------------
1 | module "wrapper" {
2 | source = "../"
3 |
4 | for_each = var.items
5 |
6 | autoscaling_capacity_providers = try(each.value.autoscaling_capacity_providers, var.defaults.autoscaling_capacity_providers, {})
7 | cloudwatch_log_group_kms_key_id = try(each.value.cloudwatch_log_group_kms_key_id, var.defaults.cloudwatch_log_group_kms_key_id, null)
8 | cloudwatch_log_group_name = try(each.value.cloudwatch_log_group_name, var.defaults.cloudwatch_log_group_name, null)
9 | cloudwatch_log_group_retention_in_days = try(each.value.cloudwatch_log_group_retention_in_days, var.defaults.cloudwatch_log_group_retention_in_days, 90)
10 | cloudwatch_log_group_tags = try(each.value.cloudwatch_log_group_tags, var.defaults.cloudwatch_log_group_tags, {})
11 | cluster_configuration = try(each.value.cluster_configuration, var.defaults.cluster_configuration, {})
12 | cluster_name = try(each.value.cluster_name, var.defaults.cluster_name, "")
13 | cluster_service_connect_defaults = try(each.value.cluster_service_connect_defaults, var.defaults.cluster_service_connect_defaults, {})
14 | cluster_settings = try(each.value.cluster_settings, var.defaults.cluster_settings, [
15 | {
16 | name = "containerInsights"
17 | value = "enabled"
18 | }
19 | ])
20 | cluster_tags = try(each.value.cluster_tags, var.defaults.cluster_tags, {})
21 | create = try(each.value.create, var.defaults.create, true)
22 | create_cloudwatch_log_group = try(each.value.create_cloudwatch_log_group, var.defaults.create_cloudwatch_log_group, true)
23 | create_task_exec_iam_role = try(each.value.create_task_exec_iam_role, var.defaults.create_task_exec_iam_role, false)
24 | create_task_exec_policy = try(each.value.create_task_exec_policy, var.defaults.create_task_exec_policy, true)
25 | default_capacity_provider_use_fargate = try(each.value.default_capacity_provider_use_fargate, var.defaults.default_capacity_provider_use_fargate, true)
26 | fargate_capacity_providers = try(each.value.fargate_capacity_providers, var.defaults.fargate_capacity_providers, {})
27 | services = try(each.value.services, var.defaults.services, {})
28 | tags = try(each.value.tags, var.defaults.tags, {})
29 | task_exec_iam_role_description = try(each.value.task_exec_iam_role_description, var.defaults.task_exec_iam_role_description, null)
30 | task_exec_iam_role_name = try(each.value.task_exec_iam_role_name, var.defaults.task_exec_iam_role_name, null)
31 | task_exec_iam_role_path = try(each.value.task_exec_iam_role_path, var.defaults.task_exec_iam_role_path, null)
32 | task_exec_iam_role_permissions_boundary = try(each.value.task_exec_iam_role_permissions_boundary, var.defaults.task_exec_iam_role_permissions_boundary, null)
33 | task_exec_iam_role_policies = try(each.value.task_exec_iam_role_policies, var.defaults.task_exec_iam_role_policies, {})
34 | task_exec_iam_role_tags = try(each.value.task_exec_iam_role_tags, var.defaults.task_exec_iam_role_tags, {})
35 | task_exec_iam_role_use_name_prefix = try(each.value.task_exec_iam_role_use_name_prefix, var.defaults.task_exec_iam_role_use_name_prefix, true)
36 | task_exec_iam_statements = try(each.value.task_exec_iam_statements, var.defaults.task_exec_iam_statements, {})
37 | task_exec_secret_arns = try(each.value.task_exec_secret_arns, var.defaults.task_exec_secret_arns, ["arn:aws:secretsmanager:*:*:secret:*"])
38 | task_exec_ssm_param_arns = try(each.value.task_exec_ssm_param_arns, var.defaults.task_exec_ssm_param_arns, ["arn:aws:ssm:*:*:parameter/*"])
39 | }
40 |
--------------------------------------------------------------------------------
/wrappers/outputs.tf:
--------------------------------------------------------------------------------
1 | output "wrapper" {
2 | description = "Map of outputs of a wrapper."
3 | value = module.wrapper
4 | # sensitive = false # No sensitive module output found
5 | }
6 |
--------------------------------------------------------------------------------
/wrappers/service/README.md:
--------------------------------------------------------------------------------
1 | # Wrapper for module: `modules/service`
2 |
3 | The configuration in this directory contains an implementation of a single module wrapper pattern, which allows managing several copies of a module in places where using the native Terraform 0.13+ `for_each` feature is not feasible (e.g., with Terragrunt).
4 |
5 | You may want to use a single Terragrunt configuration file to manage multiple resources without duplicating `terragrunt.hcl` files for each copy of the same module.
6 |
7 | This wrapper does not implement any extra functionality.
8 |
9 | ## Usage with Terragrunt
10 |
11 | `terragrunt.hcl`:
12 |
13 | ```hcl
14 | terraform {
15 | source = "tfr:///terraform-aws-modules/ecs/aws//wrappers/service"
16 | # Alternative source:
17 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-ecs.git//wrappers/service?ref=master"
18 | }
19 |
20 | inputs = {
21 | defaults = { # Default values
22 | create = true
23 | tags = {
24 | Terraform = "true"
25 | Environment = "dev"
26 | }
27 | }
28 |
29 | items = {
30 | my-item = {
31 | # omitted... can be any argument supported by the module
32 | }
33 | my-second-item = {
34 | # omitted... can be any argument supported by the module
35 | }
36 | # omitted...
37 | }
38 | }
39 | ```
40 |
41 | ## Usage with Terraform
42 |
43 | ```hcl
44 | module "wrapper" {
45 | source = "terraform-aws-modules/ecs/aws//wrappers/service"
46 |
47 | defaults = { # Default values
48 | create = true
49 | tags = {
50 | Terraform = "true"
51 | Environment = "dev"
52 | }
53 | }
54 |
55 | items = {
56 | my-item = {
57 | # omitted... can be any argument supported by the module
58 | }
59 | my-second-item = {
60 | # omitted... can be any argument supported by the module
61 | }
62 | # omitted...
63 | }
64 | }
65 | ```
66 |
67 | ## Example: Manage multiple S3 buckets in one Terragrunt layer
68 |
69 | `eu-west-1/s3-buckets/terragrunt.hcl`:
70 |
71 | ```hcl
72 | terraform {
73 | source = "tfr:///terraform-aws-modules/s3-bucket/aws//wrappers"
74 | # Alternative source:
75 | # source = "git::git@github.com:terraform-aws-modules/terraform-aws-s3-bucket.git//wrappers?ref=master"
76 | }
77 |
78 | inputs = {
79 | defaults = {
80 | force_destroy = true
81 |
82 | attach_elb_log_delivery_policy = true
83 | attach_lb_log_delivery_policy = true
84 | attach_deny_insecure_transport_policy = true
85 | attach_require_latest_tls_policy = true
86 | }
87 |
88 | items = {
89 | bucket1 = {
90 | bucket = "my-random-bucket-1"
91 | }
92 | bucket2 = {
93 | bucket = "my-random-bucket-2"
94 | tags = {
95 | Secure = "probably"
96 | }
97 | }
98 | }
99 | }
100 | ```
101 |
--------------------------------------------------------------------------------
/wrappers/service/main.tf:
--------------------------------------------------------------------------------
1 | module "wrapper" {
2 | source = "../../modules/service"
3 |
4 | for_each = var.items
5 |
6 | alarms = try(each.value.alarms, var.defaults.alarms, {})
7 | assign_public_ip = try(each.value.assign_public_ip, var.defaults.assign_public_ip, false)
8 | autoscaling_max_capacity = try(each.value.autoscaling_max_capacity, var.defaults.autoscaling_max_capacity, 10)
9 | autoscaling_min_capacity = try(each.value.autoscaling_min_capacity, var.defaults.autoscaling_min_capacity, 1)
10 | autoscaling_policies = try(each.value.autoscaling_policies, var.defaults.autoscaling_policies, {
11 | cpu = {
12 | policy_type = "TargetTrackingScaling"
13 |
14 | target_tracking_scaling_policy_configuration = {
15 | predefined_metric_specification = {
16 | predefined_metric_type = "ECSServiceAverageCPUUtilization"
17 | }
18 | }
19 | }
20 | memory = {
21 | policy_type = "TargetTrackingScaling"
22 |
23 | target_tracking_scaling_policy_configuration = {
24 | predefined_metric_specification = {
25 | predefined_metric_type = "ECSServiceAverageMemoryUtilization"
26 | }
27 | }
28 | }
29 | })
30 | autoscaling_scheduled_actions = try(each.value.autoscaling_scheduled_actions, var.defaults.autoscaling_scheduled_actions, {})
31 | capacity_provider_strategy = try(each.value.capacity_provider_strategy, var.defaults.capacity_provider_strategy, {})
32 | cluster_arn = try(each.value.cluster_arn, var.defaults.cluster_arn, "")
33 | container_definition_defaults = try(each.value.container_definition_defaults, var.defaults.container_definition_defaults, {})
34 | container_definitions = try(each.value.container_definitions, var.defaults.container_definitions, {})
35 | cpu = try(each.value.cpu, var.defaults.cpu, 1024)
36 | create = try(each.value.create, var.defaults.create, true)
37 | create_iam_role = try(each.value.create_iam_role, var.defaults.create_iam_role, true)
38 | create_security_group = try(each.value.create_security_group, var.defaults.create_security_group, true)
39 | create_service = try(each.value.create_service, var.defaults.create_service, true)
40 | create_task_definition = try(each.value.create_task_definition, var.defaults.create_task_definition, true)
41 | create_task_exec_iam_role = try(each.value.create_task_exec_iam_role, var.defaults.create_task_exec_iam_role, true)
42 | create_task_exec_policy = try(each.value.create_task_exec_policy, var.defaults.create_task_exec_policy, true)
43 | create_tasks_iam_role = try(each.value.create_tasks_iam_role, var.defaults.create_tasks_iam_role, true)
44 | deployment_circuit_breaker = try(each.value.deployment_circuit_breaker, var.defaults.deployment_circuit_breaker, {})
45 | deployment_controller = try(each.value.deployment_controller, var.defaults.deployment_controller, {})
46 | deployment_maximum_percent = try(each.value.deployment_maximum_percent, var.defaults.deployment_maximum_percent, 200)
47 | deployment_minimum_healthy_percent = try(each.value.deployment_minimum_healthy_percent, var.defaults.deployment_minimum_healthy_percent, 66)
48 | desired_count = try(each.value.desired_count, var.defaults.desired_count, 1)
49 | enable_autoscaling = try(each.value.enable_autoscaling, var.defaults.enable_autoscaling, true)
50 | enable_ecs_managed_tags = try(each.value.enable_ecs_managed_tags, var.defaults.enable_ecs_managed_tags, true)
51 | enable_execute_command = try(each.value.enable_execute_command, var.defaults.enable_execute_command, false)
52 | ephemeral_storage = try(each.value.ephemeral_storage, var.defaults.ephemeral_storage, {})
53 | external_id = try(each.value.external_id, var.defaults.external_id, null)
54 | family = try(each.value.family, var.defaults.family, null)
55 | force_delete = try(each.value.force_delete, var.defaults.force_delete, null)
56 | force_new_deployment = try(each.value.force_new_deployment, var.defaults.force_new_deployment, true)
57 | health_check_grace_period_seconds = try(each.value.health_check_grace_period_seconds, var.defaults.health_check_grace_period_seconds, null)
58 | iam_role_arn = try(each.value.iam_role_arn, var.defaults.iam_role_arn, null)
59 | iam_role_description = try(each.value.iam_role_description, var.defaults.iam_role_description, null)
60 | iam_role_name = try(each.value.iam_role_name, var.defaults.iam_role_name, null)
61 | iam_role_path = try(each.value.iam_role_path, var.defaults.iam_role_path, null)
62 | iam_role_permissions_boundary = try(each.value.iam_role_permissions_boundary, var.defaults.iam_role_permissions_boundary, null)
63 | iam_role_statements = try(each.value.iam_role_statements, var.defaults.iam_role_statements, {})
64 | iam_role_tags = try(each.value.iam_role_tags, var.defaults.iam_role_tags, {})
65 | iam_role_use_name_prefix = try(each.value.iam_role_use_name_prefix, var.defaults.iam_role_use_name_prefix, true)
66 | ignore_task_definition_changes = try(each.value.ignore_task_definition_changes, var.defaults.ignore_task_definition_changes, false)
67 | inference_accelerator = try(each.value.inference_accelerator, var.defaults.inference_accelerator, {})
68 | ipc_mode = try(each.value.ipc_mode, var.defaults.ipc_mode, null)
69 | launch_type = try(each.value.launch_type, var.defaults.launch_type, "FARGATE")
70 | load_balancer = try(each.value.load_balancer, var.defaults.load_balancer, {})
71 | memory = try(each.value.memory, var.defaults.memory, 2048)
72 | name = try(each.value.name, var.defaults.name, null)
73 | network_mode = try(each.value.network_mode, var.defaults.network_mode, "awsvpc")
74 | ordered_placement_strategy = try(each.value.ordered_placement_strategy, var.defaults.ordered_placement_strategy, {})
75 | pid_mode = try(each.value.pid_mode, var.defaults.pid_mode, null)
76 | placement_constraints = try(each.value.placement_constraints, var.defaults.placement_constraints, {})
77 | platform_version = try(each.value.platform_version, var.defaults.platform_version, null)
78 | propagate_tags = try(each.value.propagate_tags, var.defaults.propagate_tags, null)
79 | proxy_configuration = try(each.value.proxy_configuration, var.defaults.proxy_configuration, {})
80 | requires_compatibilities = try(each.value.requires_compatibilities, var.defaults.requires_compatibilities, ["FARGATE"])
81 | runtime_platform = try(each.value.runtime_platform, var.defaults.runtime_platform, {
82 | operating_system_family = "LINUX"
83 | cpu_architecture = "X86_64"
84 | })
85 | scale = try(each.value.scale, var.defaults.scale, {})
86 | scheduling_strategy = try(each.value.scheduling_strategy, var.defaults.scheduling_strategy, null)
87 | security_group_description = try(each.value.security_group_description, var.defaults.security_group_description, null)
88 | security_group_ids = try(each.value.security_group_ids, var.defaults.security_group_ids, [])
89 | security_group_name = try(each.value.security_group_name, var.defaults.security_group_name, null)
90 | security_group_rules = try(each.value.security_group_rules, var.defaults.security_group_rules, {})
91 | security_group_tags = try(each.value.security_group_tags, var.defaults.security_group_tags, {})
92 | security_group_use_name_prefix = try(each.value.security_group_use_name_prefix, var.defaults.security_group_use_name_prefix, true)
93 | service_connect_configuration = try(each.value.service_connect_configuration, var.defaults.service_connect_configuration, {})
94 | service_registries = try(each.value.service_registries, var.defaults.service_registries, {})
95 | service_tags = try(each.value.service_tags, var.defaults.service_tags, {})
96 | skip_destroy = try(each.value.skip_destroy, var.defaults.skip_destroy, null)
97 | subnet_ids = try(each.value.subnet_ids, var.defaults.subnet_ids, [])
98 | tags = try(each.value.tags, var.defaults.tags, {})
99 | task_definition_arn = try(each.value.task_definition_arn, var.defaults.task_definition_arn, null)
100 | task_definition_placement_constraints = try(each.value.task_definition_placement_constraints, var.defaults.task_definition_placement_constraints, {})
101 | task_exec_iam_policy_path = try(each.value.task_exec_iam_policy_path, var.defaults.task_exec_iam_policy_path, null)
102 | task_exec_iam_role_arn = try(each.value.task_exec_iam_role_arn, var.defaults.task_exec_iam_role_arn, null)
103 | task_exec_iam_role_description = try(each.value.task_exec_iam_role_description, var.defaults.task_exec_iam_role_description, null)
104 | task_exec_iam_role_max_session_duration = try(each.value.task_exec_iam_role_max_session_duration, var.defaults.task_exec_iam_role_max_session_duration, null)
105 | task_exec_iam_role_name = try(each.value.task_exec_iam_role_name, var.defaults.task_exec_iam_role_name, null)
106 | task_exec_iam_role_path = try(each.value.task_exec_iam_role_path, var.defaults.task_exec_iam_role_path, null)
107 | task_exec_iam_role_permissions_boundary = try(each.value.task_exec_iam_role_permissions_boundary, var.defaults.task_exec_iam_role_permissions_boundary, null)
108 | task_exec_iam_role_policies = try(each.value.task_exec_iam_role_policies, var.defaults.task_exec_iam_role_policies, {})
109 | task_exec_iam_role_tags = try(each.value.task_exec_iam_role_tags, var.defaults.task_exec_iam_role_tags, {})
110 | task_exec_iam_role_use_name_prefix = try(each.value.task_exec_iam_role_use_name_prefix, var.defaults.task_exec_iam_role_use_name_prefix, true)
111 | task_exec_iam_statements = try(each.value.task_exec_iam_statements, var.defaults.task_exec_iam_statements, {})
112 | task_exec_secret_arns = try(each.value.task_exec_secret_arns, var.defaults.task_exec_secret_arns, ["arn:aws:secretsmanager:*:*:secret:*"])
113 | task_exec_ssm_param_arns = try(each.value.task_exec_ssm_param_arns, var.defaults.task_exec_ssm_param_arns, ["arn:aws:ssm:*:*:parameter/*"])
114 | task_tags = try(each.value.task_tags, var.defaults.task_tags, {})
115 | tasks_iam_role_arn = try(each.value.tasks_iam_role_arn, var.defaults.tasks_iam_role_arn, null)
116 | tasks_iam_role_description = try(each.value.tasks_iam_role_description, var.defaults.tasks_iam_role_description, null)
117 | tasks_iam_role_name = try(each.value.tasks_iam_role_name, var.defaults.tasks_iam_role_name, null)
118 | tasks_iam_role_path = try(each.value.tasks_iam_role_path, var.defaults.tasks_iam_role_path, null)
119 | tasks_iam_role_permissions_boundary = try(each.value.tasks_iam_role_permissions_boundary, var.defaults.tasks_iam_role_permissions_boundary, null)
120 | tasks_iam_role_policies = try(each.value.tasks_iam_role_policies, var.defaults.tasks_iam_role_policies, {})
121 | tasks_iam_role_statements = try(each.value.tasks_iam_role_statements, var.defaults.tasks_iam_role_statements, {})
122 | tasks_iam_role_tags = try(each.value.tasks_iam_role_tags, var.defaults.tasks_iam_role_tags, {})
123 | tasks_iam_role_use_name_prefix = try(each.value.tasks_iam_role_use_name_prefix, var.defaults.tasks_iam_role_use_name_prefix, true)
124 | timeouts = try(each.value.timeouts, var.defaults.timeouts, {})
125 | triggers = try(each.value.triggers, var.defaults.triggers, {})
126 | volume = try(each.value.volume, var.defaults.volume, {})
127 | wait_for_steady_state = try(each.value.wait_for_steady_state, var.defaults.wait_for_steady_state, null)
128 | wait_until_stable = try(each.value.wait_until_stable, var.defaults.wait_until_stable, null)
129 | wait_until_stable_timeout = try(each.value.wait_until_stable_timeout, var.defaults.wait_until_stable_timeout, null)
130 | }
131 |
--------------------------------------------------------------------------------
/wrappers/service/outputs.tf:
--------------------------------------------------------------------------------
1 | output "wrapper" {
2 | description = "Map of outputs of a wrapper."
3 | value = module.wrapper
4 | # sensitive = false # No sensitive module output found
5 | }
6 |
--------------------------------------------------------------------------------
/wrappers/service/variables.tf:
--------------------------------------------------------------------------------
1 | variable "defaults" {
2 | description = "Map of default values which will be used for each item."
3 | type = any
4 | default = {}
5 | }
6 |
7 | variable "items" {
8 | description = "Maps of items to create a wrapper from. Values are passed through to the module."
9 | type = any
10 | default = {}
11 | }
12 |
--------------------------------------------------------------------------------
/wrappers/service/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/wrappers/variables.tf:
--------------------------------------------------------------------------------
1 | variable "defaults" {
2 | description = "Map of default values which will be used for each item."
3 | type = any
4 | default = {}
5 | }
6 |
7 | variable "items" {
8 | description = "Maps of items to create a wrapper from. Values are passed through to the module."
9 | type = any
10 | default = {}
11 | }
12 |
--------------------------------------------------------------------------------
/wrappers/versions.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | required_version = ">= 1.0"
3 |
4 | required_providers {
5 | aws = {
6 | source = "hashicorp/aws"
7 | version = ">= 4.66.1"
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------