From 9c9b6e582070409fffbd3e67496b91b595e5c3f8 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Tue, 18 Jun 2019 14:59:37 -0700 Subject: [PATCH 01/15] Modify to use terraform 0.12 This reverts commit 8cfafd7b7508372afe4b19eff553dff662a2fb7b. --- main.tf | 38 +++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/main.tf b/main.tf index d456769..38b30eb 100644 --- a/main.tf +++ b/main.tf @@ -273,7 +273,7 @@ resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { from_port = "${var.container_port}" to_port = "${var.container_port}" protocol = "tcp" - cidr_blocks = ["${var.nlb_subnet_cidr_blocks}"] + cidr_blocks = "${var.nlb_subnet_cidr_blocks}" } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { @@ -286,7 +286,7 @@ resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { from_port = "${var.container_health_check_port}" to_port = "${var.container_health_check_port}" protocol = "tcp" - cidr_blocks = ["${var.nlb_subnet_cidr_blocks}"] + cidr_blocks = "${var.nlb_subnet_cidr_blocks}" } # @@ -354,7 +354,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { "ecr:BatchGetImage", ] - resources = ["${var.ecr_repo_arns}"] + resources = "${var.ecr_repo_arns}" } } @@ -363,7 +363,7 @@ resource "aws_iam_role_policy" "instance_role_policy" { name = "${var.ecs_instance_role}-policy" role = "${var.ecs_instance_role}" - policy = "${data.aws_iam_policy_document.instance_role_policy_doc.json}" + policy = "${data.aws_iam_policy_document.instance_role_policy_doc[count.index].json}" } # @@ -406,7 +406,7 @@ data "aws_iam_policy_document" "task_execution_role_policy_doc" { "ecr:BatchGetImage", ] - resources = ["${var.ecr_repo_arns}"] + resources = "${var.ecr_repo_arns}" } } @@ -419,15 +419,15 @@ resource "aws_iam_role" "task_execution_role" { count = "${var.ecs_use_fargate ? 1 : 0}" name = "ecs-task-execution-role-${var.name}-${var.environment}" - assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" + assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy[count.index].json}" } resource "aws_iam_role_policy" "task_execution_role_policy" { count = "${var.ecs_use_fargate ? 1 : 0}" - name = "${aws_iam_role.task_execution_role.name}-policy" - role = "${aws_iam_role.task_execution_role.name}" - policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc.json}" + name = "${aws_iam_role.task_execution_role[count.index].name}-policy" + role = "${aws_iam_role.task_execution_role[count.index].name}" + policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc[count.index].json}" } # @@ -512,12 +512,16 @@ resource "aws_ecs_service" "main" { deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" deployment_maximum_percent = "${var.tasks_maximum_percent}" - ordered_placement_strategy = "${local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type]}" - placement_constraints = "${local.ecs_service_placement_constraints[local.ecs_service_launch_type]}" + ordered_placement_strategy { + local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + } + placement_constraints { + local.ecs_service_placement_constraints[local.ecs_service_launch_type] + } network_configuration { - subnets = ["${var.ecs_subnet_ids}"] - security_groups = ["${aws_security_group.ecs_sg.id}"] + subnets = "${var.ecs_subnet_ids}" + security_groups = "${aws_security_group.ecs_sg.id}" assign_public_ip = false } @@ -552,12 +556,12 @@ resource "aws_ecs_service" "main_no_lb" { deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" deployment_maximum_percent = "${var.tasks_maximum_percent}" - ordered_placement_strategy = "${local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type]}" - placement_constraints = "${local.ecs_service_placement_constraints[local.ecs_service_launch_type]}" + ordered_placement_strategy = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + placement_constraints = local.ecs_service_placement_constraints[local.ecs_service_launch_type] network_configuration { - subnets = ["${var.ecs_subnet_ids}"] - security_groups = ["${aws_security_group.ecs_sg.id}"] + subnets = "${var.ecs_subnet_ids}" + security_groups = "${aws_security_group.ecs_sg.id}" assign_public_ip = false } From 0785a5d7fdfb96c148001364191f8efa7f94ca13 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Tue, 18 Jun 2019 15:46:21 -0700 Subject: [PATCH 02/15] Use dynamic blocks for placements --- main.tf | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/main.tf b/main.tf index 38b30eb..1a43753 100644 --- a/main.tf +++ b/main.tf @@ -512,11 +512,18 @@ resource "aws_ecs_service" "main" { deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" deployment_maximum_percent = "${var.tasks_maximum_percent}" - ordered_placement_strategy { - local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + dynamic "ordered_placement_strategy" { + for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + content { + type = ordered_placement_strategy.value.type + field = ordered_placement_strategy.value.field + } } - placement_constraints { - local.ecs_service_placement_constraints[local.ecs_service_launch_type] + dynamic "placement_constraints" { + for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + content { + type = placement_constraints.value.type + } } network_configuration { @@ -556,8 +563,19 @@ resource "aws_ecs_service" "main_no_lb" { deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" deployment_maximum_percent = "${var.tasks_maximum_percent}" - ordered_placement_strategy = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] - placement_constraints = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + dynamic "ordered_placement_strategy" { + for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + content { + type = ordered_placement_strategy.value.type + field = ordered_placement_strategy.value.field + } + } + dynamic "placement_constraints" { + for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + content { + type = placement_constraints.value.type + } + } network_configuration { subnets = "${var.ecs_subnet_ids}" From 200af7d15f36e13ef2986e969664c0580b99561c Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Tue, 18 Jun 2019 15:50:30 -0700 Subject: [PATCH 03/15] Fix booleans --- main.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/main.tf b/main.tf index 1a43753..934095e 100644 --- a/main.tf +++ b/main.tf @@ -238,7 +238,7 @@ resource "aws_security_group_rule" "app_ecs_allow_outbound" { } resource "aws_security_group_rule" "app_ecs_allow_https_from_alb" { - count = "${var.associate_alb}" + count = "${var.associate_alb ? 1 : 0}" description = "Allow in ALB" security_group_id = "${aws_security_group.ecs_sg.id}" @@ -251,7 +251,7 @@ resource "aws_security_group_rule" "app_ecs_allow_https_from_alb" { } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_alb" { - count = "${var.associate_alb > 0 && var.container_health_check_port > 0 ? 1 : 0}" + count = "${var.associate_alb && var.container_health_check_port > 0 ? 1 : 0}" description = "Allow in health check from ALB" security_group_id = "${aws_security_group.ecs_sg.id}" @@ -264,7 +264,7 @@ resource "aws_security_group_rule" "app_ecs_allow_health_check_from_alb" { } resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { - count = "${var.associate_nlb}" + count = "${var.associate_nlb ? 1 : 0}" description = "Allow in NLB" security_group_id = "${aws_security_group.ecs_sg.id}" @@ -277,7 +277,7 @@ resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { - count = "${var.associate_nlb > 0 && var.container_health_check_port > 0 ? 1 : 0}" + count = "${var.associate_nlb && var.container_health_check_port > 0 ? 1 : 0}" description = "Allow in health check from NLB" security_group_id = "${aws_security_group.ecs_sg.id}" From cfd66eabfec404adc9898d9e20394de201cc3fa9 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Tue, 18 Jun 2019 16:28:26 -0700 Subject: [PATCH 04/15] Fixes --- main.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/main.tf b/main.tf index 934095e..080bece 100644 --- a/main.tf +++ b/main.tf @@ -419,7 +419,7 @@ resource "aws_iam_role" "task_execution_role" { count = "${var.ecs_use_fargate ? 1 : 0}" name = "ecs-task-execution-role-${var.name}-${var.environment}" - assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy[count.index].json}" + assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" } resource "aws_iam_role_policy" "task_execution_role_policy" { @@ -427,7 +427,7 @@ resource "aws_iam_role_policy" "task_execution_role_policy" { name = "${aws_iam_role.task_execution_role[count.index].name}-policy" role = "${aws_iam_role.task_execution_role[count.index].name}" - policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc[count.index].json}" + policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc.json}" } # @@ -528,7 +528,7 @@ resource "aws_ecs_service" "main" { network_configuration { subnets = "${var.ecs_subnet_ids}" - security_groups = "${aws_security_group.ecs_sg.id}" + security_groups = ["${aws_security_group.ecs_sg.id}"] assign_public_ip = false } From 1b909786e07d5b3ec3626b59f967df052d598064 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Tue, 18 Jun 2019 17:01:19 -0700 Subject: [PATCH 05/15] Use new terraform fmt --- .pre-commit-config.yaml | 3 +- main.tf | 120 ++++++++++++++++++++-------------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8d31e32..6bb132d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,8 +17,7 @@ repos: - id: markdownlint - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.12.0 + rev: v1.16.0 hooks: - id: terraform_docs - id: terraform_fmt - - id: terraform_validate_no_variables diff --git a/main.tf b/main.tf index 080bece..3bf5056 100644 --- a/main.tf +++ b/main.tf @@ -116,13 +116,13 @@ EOF # resource "aws_cloudwatch_log_group" "main" { - name = "${local.awslogs_group}" + name = "${local.awslogs_group}" retention_in_days = "${var.logs_cloudwatch_retention}" tags = { - Name = "${var.name}-${var.environment}" + Name = "${var.name}-${var.environment}" Environment = "${var.environment}" - Automation = "Terraform" + Automation = "Terraform" } } @@ -215,77 +215,77 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { # resource "aws_security_group" "ecs_sg" { - name = "ecs-${var.name}-${var.environment}" + name = "ecs-${var.name}-${var.environment}" description = "${var.name}-${var.environment} container security group" - vpc_id = "${var.ecs_vpc_id}" + vpc_id = "${var.ecs_vpc_id}" tags = { - Name = "ecs-${var.name}-${var.environment}" + Name = "ecs-${var.name}-${var.environment}" Environment = "${var.environment}" - Automation = "Terraform" + Automation = "Terraform" } } resource "aws_security_group_rule" "app_ecs_allow_outbound" { - description = "All outbound" + description = "All outbound" security_group_id = "${aws_security_group.ecs_sg.id}" - type = "egress" - from_port = 0 - to_port = 0 - protocol = "-1" + type = "egress" + from_port = 0 + to_port = 0 + protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } resource "aws_security_group_rule" "app_ecs_allow_https_from_alb" { count = "${var.associate_alb ? 1 : 0}" - description = "Allow in ALB" + description = "Allow in ALB" security_group_id = "${aws_security_group.ecs_sg.id}" - type = "ingress" - from_port = "${var.container_port}" - to_port = "${var.container_port}" - protocol = "tcp" + type = "ingress" + from_port = "${var.container_port}" + to_port = "${var.container_port}" + protocol = "tcp" source_security_group_id = "${var.alb_security_group}" } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_alb" { count = "${var.associate_alb && var.container_health_check_port > 0 ? 1 : 0}" - description = "Allow in health check from ALB" + description = "Allow in health check from ALB" security_group_id = "${aws_security_group.ecs_sg.id}" - type = "ingress" - from_port = "${var.container_health_check_port}" - to_port = "${var.container_health_check_port}" - protocol = "tcp" + type = "ingress" + from_port = "${var.container_health_check_port}" + to_port = "${var.container_health_check_port}" + protocol = "tcp" source_security_group_id = "${var.alb_security_group}" } resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { count = "${var.associate_nlb ? 1 : 0}" - description = "Allow in NLB" + description = "Allow in NLB" security_group_id = "${aws_security_group.ecs_sg.id}" - type = "ingress" - from_port = "${var.container_port}" - to_port = "${var.container_port}" - protocol = "tcp" + type = "ingress" + from_port = "${var.container_port}" + to_port = "${var.container_port}" + protocol = "tcp" cidr_blocks = "${var.nlb_subnet_cidr_blocks}" } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { count = "${var.associate_nlb && var.container_health_check_port > 0 ? 1 : 0}" - description = "Allow in health check from NLB" + description = "Allow in health check from NLB" security_group_id = "${aws_security_group.ecs_sg.id}" - type = "ingress" - from_port = "${var.container_health_check_port}" - to_port = "${var.container_health_check_port}" - protocol = "tcp" + type = "ingress" + from_port = "${var.container_health_check_port}" + to_port = "${var.container_health_check_port}" + protocol = "tcp" cidr_blocks = "${var.nlb_subnet_cidr_blocks}" } @@ -314,7 +314,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { resources = ["*"] condition { - test = "StringEquals" + test = "StringEquals" variable = "ecs:cluster" values = ["${data.aws_ecs_cluster.main.arn}"] } @@ -361,8 +361,8 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { resource "aws_iam_role_policy" "instance_role_policy" { count = "${var.ecs_instance_role != "" ? 1 : 0}" - name = "${var.ecs_instance_role}-policy" - role = "${var.ecs_instance_role}" + name = "${var.ecs_instance_role}-policy" + role = "${var.ecs_instance_role}" policy = "${data.aws_iam_policy_document.instance_role_policy_doc[count.index].json}" } @@ -375,7 +375,7 @@ data "aws_iam_policy_document" "ecs_assume_role_policy" { actions = ["sts:AssumeRole"] principals { - type = "Service" + type = "Service" identifiers = ["ecs-tasks.amazonaws.com"] } } @@ -411,22 +411,22 @@ data "aws_iam_policy_document" "task_execution_role_policy_doc" { } resource "aws_iam_role" "task_role" { - name = "ecs-task-role-${var.name}-${var.environment}" + name = "ecs-task-role-${var.name}-${var.environment}" assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" } resource "aws_iam_role" "task_execution_role" { count = "${var.ecs_use_fargate ? 1 : 0}" - name = "ecs-task-execution-role-${var.name}-${var.environment}" + name = "ecs-task-execution-role-${var.name}-${var.environment}" assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" } resource "aws_iam_role_policy" "task_execution_role_policy" { count = "${var.ecs_use_fargate ? 1 : 0}" - name = "${aws_iam_role.task_execution_role[count.index].name}-policy" - role = "${aws_iam_role.task_execution_role[count.index].name}" + name = "${aws_iam_role.task_execution_role[count.index].name}-policy" + role = "${aws_iam_role.task_execution_role[count.index].name}" policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc.json}" } @@ -439,15 +439,15 @@ data "aws_region" "current" {} # Create a task definition with a golang image so the ecs service can be easily # tested. We expect deployments will manage the future container definitions. resource "aws_ecs_task_definition" "main" { - family = "${var.name}-${var.environment}" - network_mode = "awsvpc" + family = "${var.name}-${var.environment}" + network_mode = "awsvpc" task_role_arn = "${aws_iam_role.task_role.arn}" # Fargate requirements requires_compatibilities = "${compact(list(var.ecs_use_fargate ? "FARGATE" : ""))}" - cpu = "${var.ecs_use_fargate ? var.fargate_task_cpu : ""}" - memory = "${var.ecs_use_fargate ? var.fargate_task_memory : ""}" - execution_role_arn = "${join("", aws_iam_role.task_execution_role.*.arn)}" + cpu = "${var.ecs_use_fargate ? var.fargate_task_cpu : ""}" + memory = "${var.ecs_use_fargate ? var.fargate_task_memory : ""}" + execution_role_arn = "${join("", aws_iam_role.task_execution_role.*.arn)}" container_definitions = "${var.container_definitions == "" ? local.default_container_definitions : var.container_definitions}" @@ -465,7 +465,7 @@ resource "aws_ecs_task_definition" "main" { # Create a data source to pull the latest active revision from data "aws_ecs_task_definition" "main" { task_definition = "${aws_ecs_task_definition.main.family}" - depends_on = ["aws_ecs_task_definition.main"] # ensures at least one task def exists + depends_on = ["aws_ecs_task_definition.main"] # ensures at least one task def exists } locals { @@ -474,11 +474,11 @@ locals { ecs_service_ordered_placement_strategy = { EC2 = [ { - type = "spread" + type = "spread" field = "attribute:ecs.availability-zone" }, { - type = "spread" + type = "spread" field = "instanceId" }, ] @@ -508,9 +508,9 @@ resource "aws_ecs_service" "main" { "${aws_ecs_task_definition.main.revision}", "${data.aws_ecs_task_definition.main.revision}")}" - desired_count = "${var.tasks_desired_count}" + desired_count = "${var.tasks_desired_count}" deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" - deployment_maximum_percent = "${var.tasks_maximum_percent}" + deployment_maximum_percent = "${var.tasks_maximum_percent}" dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] @@ -522,20 +522,20 @@ resource "aws_ecs_service" "main" { dynamic "placement_constraints" { for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] content { - type = placement_constraints.value.type + type = placement_constraints.value.type } } network_configuration { - subnets = "${var.ecs_subnet_ids}" - security_groups = ["${aws_security_group.ecs_sg.id}"] + subnets = "${var.ecs_subnet_ids}" + security_groups = ["${aws_security_group.ecs_sg.id}"] assign_public_ip = false } load_balancer { target_group_arn = "${var.lb_target_group}" - container_name = "${local.target_container_name}" - container_port = "${var.container_port}" + container_name = "${local.target_container_name}" + container_port = "${var.container_port}" } lifecycle { @@ -559,9 +559,9 @@ resource "aws_ecs_service" "main_no_lb" { "${aws_ecs_task_definition.main.revision}", "${data.aws_ecs_task_definition.main.revision}")}" - desired_count = "${var.tasks_desired_count}" + desired_count = "${var.tasks_desired_count}" deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" - deployment_maximum_percent = "${var.tasks_maximum_percent}" + deployment_maximum_percent = "${var.tasks_maximum_percent}" dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] @@ -573,13 +573,13 @@ resource "aws_ecs_service" "main_no_lb" { dynamic "placement_constraints" { for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] content { - type = placement_constraints.value.type + type = placement_constraints.value.type } } network_configuration { - subnets = "${var.ecs_subnet_ids}" - security_groups = "${aws_security_group.ecs_sg.id}" + subnets = "${var.ecs_subnet_ids}" + security_groups = "${aws_security_group.ecs_sg.id}" assign_public_ip = false } From 34bb1ccafcbe41b31557c7aa22457d9103640573 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Wed, 19 Jun 2019 09:15:14 -0700 Subject: [PATCH 06/15] Update module to terraform 0.12 syntax --- main.tf | 175 ++++++++++++++++++++++++++------------------------- outputs.tf | 17 ++--- variables.tf | 49 ++++++++------- 3 files changed, 124 insertions(+), 117 deletions(-) diff --git a/main.tf b/main.tf index 3bf5056..304420c 100644 --- a/main.tf +++ b/main.tf @@ -109,6 +109,7 @@ locals { } ] EOF + } # @@ -116,12 +117,12 @@ EOF # resource "aws_cloudwatch_log_group" "main" { - name = "${local.awslogs_group}" - retention_in_days = "${var.logs_cloudwatch_retention}" + name = local.awslogs_group + retention_in_days = var.logs_cloudwatch_retention tags = { Name = "${var.name}-${var.environment}" - Environment = "${var.environment}" + Environment = var.environment Automation = "Terraform" } } @@ -217,18 +218,18 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { resource "aws_security_group" "ecs_sg" { name = "ecs-${var.name}-${var.environment}" description = "${var.name}-${var.environment} container security group" - vpc_id = "${var.ecs_vpc_id}" + vpc_id = var.ecs_vpc_id tags = { Name = "ecs-${var.name}-${var.environment}" - Environment = "${var.environment}" + Environment = var.environment Automation = "Terraform" } } resource "aws_security_group_rule" "app_ecs_allow_outbound" { description = "All outbound" - security_group_id = "${aws_security_group.ecs_sg.id}" + security_group_id = aws_security_group.ecs_sg.id type = "egress" from_port = 0 @@ -238,55 +239,55 @@ resource "aws_security_group_rule" "app_ecs_allow_outbound" { } resource "aws_security_group_rule" "app_ecs_allow_https_from_alb" { - count = "${var.associate_alb ? 1 : 0}" + count = var.associate_alb ? 1 : 0 description = "Allow in ALB" - security_group_id = "${aws_security_group.ecs_sg.id}" + security_group_id = aws_security_group.ecs_sg.id type = "ingress" - from_port = "${var.container_port}" - to_port = "${var.container_port}" + from_port = var.container_port + to_port = var.container_port protocol = "tcp" - source_security_group_id = "${var.alb_security_group}" + source_security_group_id = var.alb_security_group } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_alb" { - count = "${var.associate_alb && var.container_health_check_port > 0 ? 1 : 0}" + count = var.associate_alb && var.container_health_check_port > 0 ? 1 : 0 description = "Allow in health check from ALB" - security_group_id = "${aws_security_group.ecs_sg.id}" + security_group_id = aws_security_group.ecs_sg.id type = "ingress" - from_port = "${var.container_health_check_port}" - to_port = "${var.container_health_check_port}" + from_port = var.container_health_check_port + to_port = var.container_health_check_port protocol = "tcp" - source_security_group_id = "${var.alb_security_group}" + source_security_group_id = var.alb_security_group } resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { - count = "${var.associate_nlb ? 1 : 0}" + count = var.associate_nlb ? 1 : 0 description = "Allow in NLB" - security_group_id = "${aws_security_group.ecs_sg.id}" + security_group_id = aws_security_group.ecs_sg.id type = "ingress" - from_port = "${var.container_port}" - to_port = "${var.container_port}" + from_port = var.container_port + to_port = var.container_port protocol = "tcp" - cidr_blocks = "${var.nlb_subnet_cidr_blocks}" + cidr_blocks = var.nlb_subnet_cidr_blocks } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { - count = "${var.associate_nlb && var.container_health_check_port > 0 ? 1 : 0}" + count = var.associate_nlb && var.container_health_check_port > 0 ? 1 : 0 description = "Allow in health check from NLB" - security_group_id = "${aws_security_group.ecs_sg.id}" + security_group_id = aws_security_group.ecs_sg.id type = "ingress" - from_port = "${var.container_health_check_port}" - to_port = "${var.container_health_check_port}" + from_port = var.container_health_check_port + to_port = var.container_health_check_port protocol = "tcp" - cidr_blocks = "${var.nlb_subnet_cidr_blocks}" + cidr_blocks = var.nlb_subnet_cidr_blocks } # @@ -294,7 +295,7 @@ resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { # data "aws_iam_policy_document" "instance_role_policy_doc" { - count = "${var.ecs_instance_role != "" ? 1 : 0}" + count = var.ecs_instance_role != "" ? 1 : 0 statement { actions = [ @@ -336,7 +337,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { "logs:PutLogEvents", ] - resources = ["${aws_cloudwatch_log_group.main.arn}"] + resources = [aws_cloudwatch_log_group.main.arn] } statement { @@ -354,16 +355,16 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { "ecr:BatchGetImage", ] - resources = "${var.ecr_repo_arns}" + resources = var.ecr_repo_arns } } resource "aws_iam_role_policy" "instance_role_policy" { - count = "${var.ecs_instance_role != "" ? 1 : 0}" + count = var.ecs_instance_role != "" ? 1 : 0 name = "${var.ecs_instance_role}-policy" - role = "${var.ecs_instance_role}" - policy = "${data.aws_iam_policy_document.instance_role_policy_doc[count.index].json}" + role = var.ecs_instance_role + policy = data.aws_iam_policy_document.instance_role_policy_doc[0].json } # @@ -388,7 +389,7 @@ data "aws_iam_policy_document" "task_execution_role_policy_doc" { "logs:PutLogEvents", ] - resources = ["${aws_cloudwatch_log_group.main.arn}"] + resources = [aws_cloudwatch_log_group.main.arn] } statement { @@ -406,70 +407,71 @@ data "aws_iam_policy_document" "task_execution_role_policy_doc" { "ecr:BatchGetImage", ] - resources = "${var.ecr_repo_arns}" + resources = var.ecr_repo_arns } } resource "aws_iam_role" "task_role" { name = "ecs-task-role-${var.name}-${var.environment}" - assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" + assume_role_policy = data.aws_iam_policy_document.ecs_assume_role_policy.json } resource "aws_iam_role" "task_execution_role" { - count = "${var.ecs_use_fargate ? 1 : 0}" + count = var.ecs_use_fargate ? 1 : 0 name = "ecs-task-execution-role-${var.name}-${var.environment}" - assume_role_policy = "${data.aws_iam_policy_document.ecs_assume_role_policy.json}" + assume_role_policy = data.aws_iam_policy_document.ecs_assume_role_policy.json } resource "aws_iam_role_policy" "task_execution_role_policy" { - count = "${var.ecs_use_fargate ? 1 : 0}" + count = var.ecs_use_fargate ? 1 : 0 - name = "${aws_iam_role.task_execution_role[count.index].name}-policy" - role = "${aws_iam_role.task_execution_role[count.index].name}" - policy = "${data.aws_iam_policy_document.task_execution_role_policy_doc.json}" + name = "${aws_iam_role.task_execution_role[0].name}-policy" + role = aws_iam_role.task_execution_role[0].name + policy = data.aws_iam_policy_document.task_execution_role_policy_doc.json } # # ECS # -data "aws_region" "current" {} +data "aws_region" "current" { +} # Create a task definition with a golang image so the ecs service can be easily # tested. We expect deployments will manage the future container definitions. resource "aws_ecs_task_definition" "main" { family = "${var.name}-${var.environment}" network_mode = "awsvpc" - task_role_arn = "${aws_iam_role.task_role.arn}" + task_role_arn = aws_iam_role.task_role.arn # Fargate requirements - requires_compatibilities = "${compact(list(var.ecs_use_fargate ? "FARGATE" : ""))}" - cpu = "${var.ecs_use_fargate ? var.fargate_task_cpu : ""}" - memory = "${var.ecs_use_fargate ? var.fargate_task_memory : ""}" - execution_role_arn = "${join("", aws_iam_role.task_execution_role.*.arn)}" + requires_compatibilities = compact([var.ecs_use_fargate ? "FARGATE" : ""]) + cpu = var.ecs_use_fargate ? var.fargate_task_cpu : "" + memory = var.ecs_use_fargate ? var.fargate_task_memory : "" + execution_role_arn = join("", aws_iam_role.task_execution_role.*.arn) - container_definitions = "${var.container_definitions == "" ? local.default_container_definitions : var.container_definitions}" + container_definitions = var.container_definitions == "" ? local.default_container_definitions : var.container_definitions lifecycle { ignore_changes = [ - "requires_compatibilities", - "cpu", - "memory", - "execution_role_arn", - "container_definitions", + requires_compatibilities, + cpu, + memory, + execution_role_arn, + container_definitions, ] } } # Create a data source to pull the latest active revision from data "aws_ecs_task_definition" "main" { - task_definition = "${aws_ecs_task_definition.main.family}" - depends_on = ["aws_ecs_task_definition.main"] # ensures at least one task def exists + task_definition = aws_ecs_task_definition.main.family + depends_on = [aws_ecs_task_definition.main] # ensures at least one task def exists } locals { - ecs_service_launch_type = "${var.ecs_use_fargate ? "FARGATE" : "EC2"}" + ecs_service_launch_type = var.ecs_use_fargate ? "FARGATE" : "EC2" ecs_service_ordered_placement_strategy = { EC2 = [ @@ -482,35 +484,36 @@ locals { field = "instanceId" }, ] - FARGATE = [] } ecs_service_placement_constraints = { - EC2 = [{ - type = "distinctInstance" - }] - + EC2 = [ + { + type = "distinctInstance" + }, + ] FARGATE = [] } } resource "aws_ecs_service" "main" { - count = "${var.associate_alb || var.associate_nlb ? 1 : 0}" + count = var.associate_alb || var.associate_nlb ? 1 : 0 name = "${var.name}" cluster = "${data.aws_ecs_cluster.main.arn}" - launch_type = "${local.ecs_service_launch_type}" + launch_type = local.ecs_service_launch_type # Use latest active revision task_definition = "${aws_ecs_task_definition.main.family}:${max( - "${aws_ecs_task_definition.main.revision}", - "${data.aws_ecs_task_definition.main.revision}")}" + aws_ecs_task_definition.main.revision, + data.aws_ecs_task_definition.main.revision, + )}" - desired_count = "${var.tasks_desired_count}" - deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" - deployment_maximum_percent = "${var.tasks_maximum_percent}" + desired_count = var.tasks_desired_count + deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent + deployment_maximum_percent = var.tasks_maximum_percent dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] @@ -527,41 +530,42 @@ resource "aws_ecs_service" "main" { } network_configuration { - subnets = "${var.ecs_subnet_ids}" - security_groups = ["${aws_security_group.ecs_sg.id}"] + subnets = var.ecs_subnet_ids + security_groups = [aws_security_group.ecs_sg.id] assign_public_ip = false } load_balancer { - target_group_arn = "${var.lb_target_group}" - container_name = "${local.target_container_name}" - container_port = "${var.container_port}" + target_group_arn = var.lb_target_group + container_name = local.target_container_name + container_port = var.container_port } lifecycle { - ignore_changes = ["task_definition"] + ignore_changes = [task_definition] } } -# XXX: We have to duplicate this resource with a count instead of parameterizing +# NOTE: We have to duplicate this resource with a count instead of parameterizing # the load_balancer argument due to this Terraform bug: # https://github.com/hashicorp/terraform/issues/16856 resource "aws_ecs_service" "main_no_lb" { - count = "${var.associate_alb || var.associate_nlb ? 0 : 1}" + count = var.associate_alb || var.associate_nlb ? 0 : 1 name = "${var.name}" cluster = "${data.aws_ecs_cluster.main.arn}" - launch_type = "${local.ecs_service_launch_type}" + launch_type = local.ecs_service_launch_type # Use latest active revision task_definition = "${aws_ecs_task_definition.main.family}:${max( - "${aws_ecs_task_definition.main.revision}", - "${data.aws_ecs_task_definition.main.revision}")}" + aws_ecs_task_definition.main.revision, + data.aws_ecs_task_definition.main.revision, + )}" - desired_count = "${var.tasks_desired_count}" - deployment_minimum_healthy_percent = "${var.tasks_minimum_healthy_percent}" - deployment_maximum_percent = "${var.tasks_maximum_percent}" + desired_count = var.tasks_desired_count + deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent + deployment_maximum_percent = var.tasks_maximum_percent dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] @@ -578,12 +582,13 @@ resource "aws_ecs_service" "main_no_lb" { } network_configuration { - subnets = "${var.ecs_subnet_ids}" - security_groups = "${aws_security_group.ecs_sg.id}" + subnets = var.ecs_subnet_ids + security_groups = aws_security_group.ecs_sg.id assign_public_ip = false } lifecycle { - ignore_changes = ["task_definition"] + ignore_changes = [task_definition] } } + diff --git a/outputs.tf b/outputs.tf index f477cf3..c98b233 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,39 +1,40 @@ output "ecs_security_group_id" { description = "Security Group ID assigned to the ECS tasks." - value = "${aws_security_group.ecs_sg.id}" + value = aws_security_group.ecs_sg.id } output "task_execution_role_arn" { description = "The ARN of the task execution role that the Amazon ECS container agent and the Docker daemon can assume." - value = "${join("", aws_iam_role.task_execution_role.*.arn)}" + value = join("", aws_iam_role.task_execution_role.*.arn) } output "task_role_arn" { description = "The ARN of the IAM role assumed by Amazon ECS container tasks." - value = "${aws_iam_role.task_role.arn}" + value = aws_iam_role.task_role.arn } output "task_role_name" { description = "The name of the IAM role assumed by Amazon ECS container tasks." - value = "${aws_iam_role.task_role.name}" + value = aws_iam_role.task_role.name } output "task_definition_arn" { description = "Full ARN of the Task Definition (including both family and revision)." - value = "${aws_ecs_task_definition.main.arn}" + value = aws_ecs_task_definition.main.arn } output "task_definition_family" { description = "The family of the Task Definition." - value = "${aws_ecs_task_definition.main.family}" + value = aws_ecs_task_definition.main.family } output "awslogs_group" { description = "Name of the CloudWatch Logs log group containers should use." - value = "${local.awslogs_group}" + value = local.awslogs_group } output "awslogs_group_arn" { description = "ARN of the CloudWatch Logs log group containers should use." - value = "${aws_cloudwatch_log_group.main.arn}" + value = aws_cloudwatch_log_group.main.arn } + diff --git a/variables.tf b/variables.tf index b9a9097..fd6662b 100644 --- a/variables.tf +++ b/variables.tf @@ -1,11 +1,11 @@ variable "name" { description = "The service name." - type = "string" + type = string } variable "environment" { description = "Environment tag, e.g prod." - type = "string" + type = string } variable "cloudwatch_alarm_name" { @@ -47,25 +47,25 @@ variable "cloudwatch_alarm_mem_threshold" { variable "logs_cloudwatch_retention" { description = "Number of days you want to retain log events in the log group." default = 90 - type = "string" + type = string } variable "logs_cloudwatch_group" { description = "CloudWatch log group to create and use. Default: /ecs/{name}-{environment}" default = "" - type = "string" + type = string } variable "ecr_repo_arns" { description = "The ARNs of the ECR repos. By default, allows all repositories." - type = "list" + type = list(string) default = ["*"] } variable "ecs_use_fargate" { description = "Whether to use Fargate for the task definition." default = false - type = "string" + type = string } variable "ecs_cluster_name" { @@ -76,105 +76,106 @@ variable "ecs_cluster_name" { variable "ecs_instance_role" { description = "The name of the ECS instance role." default = "" - type = "string" + type = string } variable "ecs_vpc_id" { description = "VPC ID to be used by ECS." - type = "string" + type = string } variable "ecs_subnet_ids" { description = "Subnet IDs for the ECS tasks." - type = "list" + type = list(string) } variable "fargate_task_cpu" { description = "Number of cpu units used in initial task definition. Default is minimum." default = 256 - type = "string" + type = string } variable "fargate_task_memory" { description = "Amount (in MiB) of memory used in initial task definition. Default is minimum." default = 512 - type = "string" + type = string } variable "tasks_desired_count" { description = "The number of instances of a task definition." default = 1 - type = "string" + type = string } variable "tasks_minimum_healthy_percent" { description = "Lower limit on the number of running tasks." default = "100" - type = "string" + type = string } variable "tasks_maximum_percent" { description = "Upper limit on the number of running tasks." default = "200" - type = "string" + type = string } variable "container_image" { description = "The image of the container." default = "golang:1.12.5-alpine" - type = "string" + type = string } variable "container_port" { description = "The port on which the container will receive traffic." default = 80 - type = "string" + type = string } variable "container_health_check_port" { description = "An additional port on which the container can receive a health check. Zero means the container port can only receive a health check on the port set by the container_port variable." default = 0 - type = "string" + type = string } variable "container_definitions" { description = "Container definitions provided as valid JSON document. Default uses golang:1.12.5-alpine running a simple hello world." default = "" - type = "string" + type = string } variable "target_container_name" { description = "Name of the container the Load Balancer should target. Default: {name}-{environment}" default = "" - type = "string" + type = string } variable "associate_alb" { description = "Whether to associate an Application Load Balancer (ALB) with the ECS service." default = false - type = "string" + type = string } variable "associate_nlb" { description = "Whether to associate a Network Load Balancer (NLB) with the ECS service." default = false - type = "string" + type = string } variable "alb_security_group" { description = "Application Load Balancer (ALB) security group ID to allow traffic from." default = "" - type = "string" + type = string } variable "lb_target_group" { description = "Either Application Load Balancer (ALB) or Network Load Balancer (NLB) target group ARN tasks will register with." default = "" - type = "string" + type = string } variable "nlb_subnet_cidr_blocks" { description = "List of Network Load Balancer (NLB) CIDR blocks to allow traffic from." default = [] - type = "list" + type = list(string) } + From 87ac43f13fc418b10b81febe83747a62aa9e69d5 Mon Sep 17 00:00:00 2001 From: Chris Gilmer Date: Wed, 19 Jun 2019 09:25:41 -0700 Subject: [PATCH 07/15] Update via pre-commit --- README.md | 65 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 8e26667..3e2d1ea 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,4 @@ -Creates an ECS service. - -Creates the following resources: - -* CloudWatch log group. -* Security Groups for the ECS service. -* ECS service. -* Task definition using `golang:1.12.5-alpine` (see below). -* Configurable associations with Network Load Balancers (NLB) and Application Load Balancers (ALB). - -We create an initial task definition using the `golang:1.12.5-alpine` image as a way -to validate the initial infrastructure is working: visiting the site shows -a simple Go hello world page. We expect deployments to manage the container -definitions going forward, not Terraform. - -## Usage - -### ECS service associated with an Application Load Balancer (ALB) - -```hcl -module "app_ecs_service" { - source = "trussworks/ecs-service/aws" - - name = "app" - environment = "prod" - - ecs_cluster_name = "cluster-name" - ecs_vpc_id = "${module.vpc.vpc_id}" - ecs_subnet_ids = "${module.vpc.private_subnets}" - tasks_desired_count = 2 - tasks_minimum_healthy_percent = 50 - tasks_maximum_percent = 200 - - associate_alb = true - alb_security_group = "${module.security_group.id}" - lb_target_group = "${module.target_group.id}" -} -``` - -### ECS Service associated with a Network Load Balancer(NLB) - -```hcl -module "app_ecs_service" { - source = "trussworks/ecs-service/aws" - - name = "app" - environment = "prod" - - ecs_cluster_name = "cluster-name" - ecs_vpc_id = "${module.vpc.vpc_id}" - ecs_subnet_ids = "${module.vpc.private_subnets}" - tasks_desired_count = 2 - tasks_minimum_healthy_percent = 50 - tasks_maximum_percent = 200 - - associate_nlb = true - nlb_subnet_cidr_blocks = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] - lb_target_group = "${module.target_group.id}" -} -``` - ## Inputs | Name | Description | Type | Default | Required | @@ -80,7 +19,7 @@ module "app_ecs_service" { | ecr\_repo\_arns | The ARNs of the ECR repos. By default, allows all repositories. | list | `[ "*" ]` | no | | ecs\_cluster\_name | The name of the ECS cluster. | string | n/a | yes | | ecs\_instance\_role | The name of the ECS instance role. | string | `""` | no | -| ecs\_subnet\_ids | Subnet IDs for the ECS tasks. | list | n/a | yes | +| ecs\_subnet\_ids | Subnet IDs for the ECS tasks. | list(string) | n/a | yes | | ecs\_use\_fargate | Whether to use Fargate for the task definition. | string | `"false"` | no | | ecs\_vpc\_id | VPC ID to be used by ECS. | string | n/a | yes | | environment | Environment tag, e.g prod. | string | n/a | yes | @@ -90,7 +29,7 @@ module "app_ecs_service" { | logs\_cloudwatch\_group | CloudWatch log group to create and use. Default: /ecs/{name}-{environment} | string | `""` | no | | logs\_cloudwatch\_retention | Number of days you want to retain log events in the log group. | string | `"90"` | no | | name | The service name. | string | n/a | yes | -| nlb\_subnet\_cidr\_blocks | List of Network Load Balancer (NLB) CIDR blocks to allow traffic from. | list | `[]` | no | +| nlb\_subnet\_cidr\_blocks | List of Network Load Balancer (NLB) CIDR blocks to allow traffic from. | list(string) | `[]` | no | | target\_container\_name | Name of the container the Load Balancer should target. Default: {name}-{environment} | string | `""` | no | | tasks\_desired\_count | The number of instances of a task definition. | string | `"1"` | no | | tasks\_maximum\_percent | Upper limit on the number of running tasks. | string | `"200"` | no | From c9efd0ba59c8cb5808751cbbdb2da0bd6b233de5 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Fri, 6 Sep 2019 08:29:16 -0700 Subject: [PATCH 08/15] rebase and terraform fmt --- main.tf | 120 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/main.tf b/main.tf index 304420c..156ad6b 100644 --- a/main.tf +++ b/main.tf @@ -117,13 +117,13 @@ EOF # resource "aws_cloudwatch_log_group" "main" { - name = local.awslogs_group + name = local.awslogs_group retention_in_days = var.logs_cloudwatch_retention tags = { - Name = "${var.name}-${var.environment}" + Name = "${var.name}-${var.environment}" Environment = var.environment - Automation = "Terraform" + Automation = "Terraform" } } @@ -216,77 +216,77 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { # resource "aws_security_group" "ecs_sg" { - name = "ecs-${var.name}-${var.environment}" + name = "ecs-${var.name}-${var.environment}" description = "${var.name}-${var.environment} container security group" - vpc_id = var.ecs_vpc_id + vpc_id = var.ecs_vpc_id tags = { - Name = "ecs-${var.name}-${var.environment}" + Name = "ecs-${var.name}-${var.environment}" Environment = var.environment - Automation = "Terraform" + Automation = "Terraform" } } resource "aws_security_group_rule" "app_ecs_allow_outbound" { - description = "All outbound" + description = "All outbound" security_group_id = aws_security_group.ecs_sg.id - type = "egress" - from_port = 0 - to_port = 0 - protocol = "-1" + type = "egress" + from_port = 0 + to_port = 0 + protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } resource "aws_security_group_rule" "app_ecs_allow_https_from_alb" { count = var.associate_alb ? 1 : 0 - description = "Allow in ALB" + description = "Allow in ALB" security_group_id = aws_security_group.ecs_sg.id - type = "ingress" - from_port = var.container_port - to_port = var.container_port - protocol = "tcp" + type = "ingress" + from_port = var.container_port + to_port = var.container_port + protocol = "tcp" source_security_group_id = var.alb_security_group } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_alb" { count = var.associate_alb && var.container_health_check_port > 0 ? 1 : 0 - description = "Allow in health check from ALB" + description = "Allow in health check from ALB" security_group_id = aws_security_group.ecs_sg.id - type = "ingress" - from_port = var.container_health_check_port - to_port = var.container_health_check_port - protocol = "tcp" + type = "ingress" + from_port = var.container_health_check_port + to_port = var.container_health_check_port + protocol = "tcp" source_security_group_id = var.alb_security_group } resource "aws_security_group_rule" "app_ecs_allow_tcp_from_nlb" { count = var.associate_nlb ? 1 : 0 - description = "Allow in NLB" + description = "Allow in NLB" security_group_id = aws_security_group.ecs_sg.id - type = "ingress" - from_port = var.container_port - to_port = var.container_port - protocol = "tcp" + type = "ingress" + from_port = var.container_port + to_port = var.container_port + protocol = "tcp" cidr_blocks = var.nlb_subnet_cidr_blocks } resource "aws_security_group_rule" "app_ecs_allow_health_check_from_nlb" { count = var.associate_nlb && var.container_health_check_port > 0 ? 1 : 0 - description = "Allow in health check from NLB" + description = "Allow in health check from NLB" security_group_id = aws_security_group.ecs_sg.id - type = "ingress" - from_port = var.container_health_check_port - to_port = var.container_health_check_port - protocol = "tcp" + type = "ingress" + from_port = var.container_health_check_port + to_port = var.container_health_check_port + protocol = "tcp" cidr_blocks = var.nlb_subnet_cidr_blocks } @@ -315,7 +315,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { resources = ["*"] condition { - test = "StringEquals" + test = "StringEquals" variable = "ecs:cluster" values = ["${data.aws_ecs_cluster.main.arn}"] } @@ -362,8 +362,8 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { resource "aws_iam_role_policy" "instance_role_policy" { count = var.ecs_instance_role != "" ? 1 : 0 - name = "${var.ecs_instance_role}-policy" - role = var.ecs_instance_role + name = "${var.ecs_instance_role}-policy" + role = var.ecs_instance_role policy = data.aws_iam_policy_document.instance_role_policy_doc[0].json } @@ -376,7 +376,7 @@ data "aws_iam_policy_document" "ecs_assume_role_policy" { actions = ["sts:AssumeRole"] principals { - type = "Service" + type = "Service" identifiers = ["ecs-tasks.amazonaws.com"] } } @@ -412,22 +412,22 @@ data "aws_iam_policy_document" "task_execution_role_policy_doc" { } resource "aws_iam_role" "task_role" { - name = "ecs-task-role-${var.name}-${var.environment}" + name = "ecs-task-role-${var.name}-${var.environment}" assume_role_policy = data.aws_iam_policy_document.ecs_assume_role_policy.json } resource "aws_iam_role" "task_execution_role" { count = var.ecs_use_fargate ? 1 : 0 - name = "ecs-task-execution-role-${var.name}-${var.environment}" + name = "ecs-task-execution-role-${var.name}-${var.environment}" assume_role_policy = data.aws_iam_policy_document.ecs_assume_role_policy.json } resource "aws_iam_role_policy" "task_execution_role_policy" { count = var.ecs_use_fargate ? 1 : 0 - name = "${aws_iam_role.task_execution_role[0].name}-policy" - role = aws_iam_role.task_execution_role[0].name + name = "${aws_iam_role.task_execution_role[0].name}-policy" + role = aws_iam_role.task_execution_role[0].name policy = data.aws_iam_policy_document.task_execution_role_policy_doc.json } @@ -441,15 +441,15 @@ data "aws_region" "current" { # Create a task definition with a golang image so the ecs service can be easily # tested. We expect deployments will manage the future container definitions. resource "aws_ecs_task_definition" "main" { - family = "${var.name}-${var.environment}" - network_mode = "awsvpc" + family = "${var.name}-${var.environment}" + network_mode = "awsvpc" task_role_arn = aws_iam_role.task_role.arn # Fargate requirements requires_compatibilities = compact([var.ecs_use_fargate ? "FARGATE" : ""]) - cpu = var.ecs_use_fargate ? var.fargate_task_cpu : "" - memory = var.ecs_use_fargate ? var.fargate_task_memory : "" - execution_role_arn = join("", aws_iam_role.task_execution_role.*.arn) + cpu = var.ecs_use_fargate ? var.fargate_task_cpu : "" + memory = var.ecs_use_fargate ? var.fargate_task_memory : "" + execution_role_arn = join("", aws_iam_role.task_execution_role.*.arn) container_definitions = var.container_definitions == "" ? local.default_container_definitions : var.container_definitions @@ -467,7 +467,7 @@ resource "aws_ecs_task_definition" "main" { # Create a data source to pull the latest active revision from data "aws_ecs_task_definition" "main" { task_definition = aws_ecs_task_definition.main.family - depends_on = [aws_ecs_task_definition.main] # ensures at least one task def exists + depends_on = [aws_ecs_task_definition.main] # ensures at least one task def exists } locals { @@ -476,11 +476,11 @@ locals { ecs_service_ordered_placement_strategy = { EC2 = [ { - type = "spread" + type = "spread" field = "attribute:ecs.availability-zone" }, { - type = "spread" + type = "spread" field = "instanceId" }, ] @@ -511,14 +511,14 @@ resource "aws_ecs_service" "main" { data.aws_ecs_task_definition.main.revision, )}" - desired_count = var.tasks_desired_count + desired_count = var.tasks_desired_count deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent - deployment_maximum_percent = var.tasks_maximum_percent + deployment_maximum_percent = var.tasks_maximum_percent dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] content { - type = ordered_placement_strategy.value.type + type = ordered_placement_strategy.value.type field = ordered_placement_strategy.value.field } } @@ -530,15 +530,15 @@ resource "aws_ecs_service" "main" { } network_configuration { - subnets = var.ecs_subnet_ids - security_groups = [aws_security_group.ecs_sg.id] + subnets = var.ecs_subnet_ids + security_groups = [aws_security_group.ecs_sg.id] assign_public_ip = false } load_balancer { target_group_arn = var.lb_target_group - container_name = local.target_container_name - container_port = var.container_port + container_name = local.target_container_name + container_port = var.container_port } lifecycle { @@ -563,14 +563,14 @@ resource "aws_ecs_service" "main_no_lb" { data.aws_ecs_task_definition.main.revision, )}" - desired_count = var.tasks_desired_count + desired_count = var.tasks_desired_count deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent - deployment_maximum_percent = var.tasks_maximum_percent + deployment_maximum_percent = var.tasks_maximum_percent dynamic "ordered_placement_strategy" { for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] content { - type = ordered_placement_strategy.value.type + type = ordered_placement_strategy.value.type field = ordered_placement_strategy.value.field } } @@ -582,8 +582,8 @@ resource "aws_ecs_service" "main_no_lb" { } network_configuration { - subnets = var.ecs_subnet_ids - security_groups = aws_security_group.ecs_sg.id + subnets = var.ecs_subnet_ids + security_groups = aws_security_group.ecs_sg.id assign_public_ip = false } From 6766a2dfb8b7a20ea75de438af6716e4911d27a5 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Fri, 6 Sep 2019 11:27:53 -0700 Subject: [PATCH 09/15] Some syntax/formatting fixing --- main.tf | 70 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 38 insertions(+), 32 deletions(-) diff --git a/main.tf b/main.tf index 156ad6b..e1c9c33 100644 --- a/main.tf +++ b/main.tf @@ -132,7 +132,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu" { alarm_name = "${local.cloudwatch_alarm_name}-cpu" alarm_description = "Monitors ECS CPU Utilization" - alarm_actions = ["${var.cloudwatch_alarm_actions}"] + alarm_actions = var.cloudwatch_alarm_actions comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -140,11 +140,11 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu" { namespace = "AWS/ECS" period = "120" statistic = "Average" - threshold = "${var.cloudwatch_alarm_cpu_threshold}" + threshold = var.cloudwatch_alarm_cpu_threshold dimensions = { - "ClusterName" = "${var.ecs_cluster_name}" - "ServiceName" = "${aws_ecs_service.main.name}" + "ClusterName" = var.ecs_cluster_name + "ServiceName" = aws_ecs_service.main[count.index].name } } @@ -153,7 +153,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem" { alarm_name = "${local.cloudwatch_alarm_name}-mem" alarm_description = "Monitors ECS CPU Utilization" - alarm_actions = ["${var.cloudwatch_alarm_actions}"] + alarm_actions = var.cloudwatch_alarm_actions comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -161,11 +161,11 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem" { namespace = "AWS/ECS" period = "120" statistic = "Average" - threshold = "${var.cloudwatch_alarm_mem_threshold}" + threshold = var.cloudwatch_alarm_mem_threshold dimensions = { - "ClusterName" = "${var.ecs_cluster_name}" - "ServiceName" = "${aws_ecs_service.main.name}" + "ClusterName" = var.ecs_cluster_name + "ServiceName" = aws_ecs_service.main[count.index].name } } @@ -174,7 +174,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu_no_lb" { alarm_name = "${local.cloudwatch_alarm_name}-cpu" alarm_description = "Monitors ECS CPU Utilization" - alarm_actions = ["${var.cloudwatch_alarm_actions}"] + alarm_actions = var.cloudwatch_alarm_actions comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -182,11 +182,11 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu_no_lb" { namespace = "AWS/ECS" period = "120" statistic = "Average" - threshold = "${var.cloudwatch_alarm_cpu_threshold}" + threshold = var.cloudwatch_alarm_cpu_threshold dimensions = { - "ClusterName" = "${var.ecs_cluster_name}" - "ServiceName" = "${aws_ecs_service.main_no_lb.name}" + "ClusterName" = var.ecs_cluster_name + "ServiceName" = aws_ecs_service.main_no_lb[count.index].name } } @@ -195,7 +195,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { alarm_name = "${local.cloudwatch_alarm_name}-mem" alarm_description = "Monitors ECS CPU Utilization" - alarm_actions = ["${var.cloudwatch_alarm_actions}"] + alarm_actions = var.cloudwatch_alarm_actions comparison_operator = "GreaterThanOrEqualToThreshold" evaluation_periods = "2" @@ -203,11 +203,11 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { namespace = "AWS/ECS" period = "120" statistic = "Average" - threshold = "${var.cloudwatch_alarm_mem_threshold}" + threshold = var.cloudwatch_alarm_mem_threshold dimensions = { - "ClusterName" = "${var.ecs_cluster_name}" - "ServiceName" = "${aws_ecs_service.main_no_lb.name}" + "ClusterName" = var.ecs_cluster_name + "ServiceName" = aws_ecs_service.main_no_lb[count.index].name } } @@ -500,8 +500,8 @@ locals { resource "aws_ecs_service" "main" { count = var.associate_alb || var.associate_nlb ? 1 : 0 - name = "${var.name}" - cluster = "${data.aws_ecs_cluster.main.arn}" + name = var.name + cluster = data.aws_ecs_cluster.main.arn launch_type = local.ecs_service_launch_type @@ -515,17 +515,20 @@ resource "aws_ecs_service" "main" { deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent deployment_maximum_percent = var.tasks_maximum_percent - dynamic "ordered_placement_strategy" { - for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + dynamic ordered_placement_strategy { + for_each = var.ecs_use_fargate ? [] : ["attribute:ecs.availability-zone", "instanceId"] + content { - type = ordered_placement_strategy.value.type - field = ordered_placement_strategy.value.field + type = "spread" + field = ordered_placement_strategy.value } } - dynamic "placement_constraints" { - for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + + dynamic placement_constraints { + for_each = var.ecs_use_fargate ? [] : ["distinctInstance"] + content { - type = placement_constraints.value.type + type = placement_constraints.value } } @@ -552,8 +555,8 @@ resource "aws_ecs_service" "main" { resource "aws_ecs_service" "main_no_lb" { count = var.associate_alb || var.associate_nlb ? 0 : 1 - name = "${var.name}" - cluster = "${data.aws_ecs_cluster.main.arn}" + name = var.name + cluster = data.aws_ecs_cluster.main.arn launch_type = local.ecs_service_launch_type @@ -568,16 +571,19 @@ resource "aws_ecs_service" "main_no_lb" { deployment_maximum_percent = var.tasks_maximum_percent dynamic "ordered_placement_strategy" { - for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + for_each = var.ecs_use_fargate ? [] : ["attribute:ecs.availability-zone", "instanceId"] + content { - type = ordered_placement_strategy.value.type - field = ordered_placement_strategy.value.field + type = spread + field = ordered_placement_strategy.value } } + dynamic "placement_constraints" { - for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + for_each = var.ecs_use_fargate ? [] : ["distinctInstance"] + content { - type = placement_constraints.value.type + type = placement_constraints.value } } From 980b4cf33cb2f4d281652daad5ec13dce97b4a67 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Fri, 6 Sep 2019 16:03:44 -0700 Subject: [PATCH 10/15] Updating readme and reverting to Chris' dynamic syntax --- .pre-commit-config.yaml | 2 +- README.md | 19 ++++++++----------- main.tf | 30 ++++++++++++++++-------------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6bb132d..3624c97 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: markdownlint - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.16.0 + rev: v1.17.0 hooks: - id: terraform_docs - id: terraform_fmt diff --git a/README.md b/README.md index 3e2d1ea..0d64370 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ | container\_health\_check\_port | An additional port on which the container can receive a health check. Zero means the container port can only receive a health check on the port set by the container_port variable. | string | `"0"` | no | | container\_image | The image of the container. | string | `"golang:1.12.5-alpine"` | no | | container\_port | The port on which the container will receive traffic. | string | `"80"` | no | -| ecr\_repo\_arns | The ARNs of the ECR repos. By default, allows all repositories. | list | `[ "*" ]` | no | +| ecr\_repo\_arns | The ARNs of the ECR repos. By default, allows all repositories. | list(string) | `[ "*" ]` | no | | ecs\_cluster\_name | The name of the ECS cluster. | string | n/a | yes | | ecs\_instance\_role | The name of the ECS instance role. | string | `""` | no | | ecs\_subnet\_ids | Subnet IDs for the ECS tasks. | list(string) | n/a | yes | @@ -52,15 +52,12 @@ ## Upgrade Path -### 1.14.0 to 1.15.0 +### 1.15.0 to 2.0.0 -In upgrading to this version you need to pass through the ECS Cluster Name and not the ECS Cluster ARN. -The difference would be changing `ecs_cluster_arn` to `ecs_cluster_name` and passing in the name info. -The module will take care of pulling the ARN from the ECS Cluster data resource on your behalf. +v2.0.0 of this module is built against Terraform v0.12. However, this +introduces a bug that prevents the creation of an ECS service with this +module prior to creation of the cluster which it is going to run on (see +). To work around +this, create the cluster first, and then add the call to this module once +the cluster exists. -If you decide you do not want metric alarms you can also set two more settings: - -```hcl - cloudwatch_alarm_cpu_enable = false - cloudwatch_alarm_mem_enable = false -``` diff --git a/main.tf b/main.tf index e1c9c33..9f6f73d 100644 --- a/main.tf +++ b/main.tf @@ -304,7 +304,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { "ecs:Submit*", ] - resources = ["${data.aws_ecs_cluster.main.arn}"] + resources = [data.aws_ecs_cluster.main.arn] } statement { @@ -317,7 +317,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { condition { test = "StringEquals" variable = "ecs:cluster" - values = ["${data.aws_ecs_cluster.main.arn}"] + values = [data.aws_ecs_cluster.main.arn] } } @@ -516,19 +516,19 @@ resource "aws_ecs_service" "main" { deployment_maximum_percent = var.tasks_maximum_percent dynamic ordered_placement_strategy { - for_each = var.ecs_use_fargate ? [] : ["attribute:ecs.availability-zone", "instanceId"] + for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] content { - type = "spread" - field = ordered_placement_strategy.value + type = ordered_placement_strategy.value.type + field = ordered_placement_strategy.value.field } } dynamic placement_constraints { - for_each = var.ecs_use_fargate ? [] : ["distinctInstance"] + for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] content { - type = placement_constraints.value + type = placement_constraints.value.type } } @@ -570,20 +570,22 @@ resource "aws_ecs_service" "main_no_lb" { deployment_minimum_healthy_percent = var.tasks_minimum_healthy_percent deployment_maximum_percent = var.tasks_maximum_percent - dynamic "ordered_placement_strategy" { - for_each = var.ecs_use_fargate ? [] : ["attribute:ecs.availability-zone", "instanceId"] + dynamic ordered_placement_strategy { + for_each = local.ecs_service_ordered_placement_strategy[local.ecs_service_launch_type] + # for_each = var.ecs_use_fargate ? [] : ["attribute:ecs.availability-zone", "instanceId"] content { - type = spread - field = ordered_placement_strategy.value + type = ordered_placement_strategy.value.type + field = ordered_placement_strategy.value.field } } - dynamic "placement_constraints" { - for_each = var.ecs_use_fargate ? [] : ["distinctInstance"] + dynamic placement_constraints { + for_each = local.ecs_service_placement_constraints[local.ecs_service_launch_type] + # for_each = var.ecs_use_fargate ? [] : ["distinctInstance"] content { - type = placement_constraints.value + type = placement_constraints.value.type } } From 078559a985803dda27f0dc9d304f3a377489efa1 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Fri, 6 Sep 2019 16:12:43 -0700 Subject: [PATCH 11/15] Updating circleci image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 73c8a10..f21d362 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: validate: docker: - - image: trussworks/circleci-docker-primary:a18ba9987556eec2e48354848a3c9fb4d5b69ac8 + - image: trussworks/circleci-docker-primary:4c1fd54273446484259597ae3da9deb2806498ed steps: - checkout - restore_cache: From 7906c22674da72e5a846d889596e152e20af43f7 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Fri, 6 Sep 2019 16:15:24 -0700 Subject: [PATCH 12/15] Pushing circleci to use the tf12 image --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f21d362..4b9b427 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2 jobs: validate: docker: - - image: trussworks/circleci-docker-primary:4c1fd54273446484259597ae3da9deb2806498ed + - image: trussworks/circleci-docker-primary:tf12-4c1fd54273446484259597ae3da9deb2806498ed steps: - checkout - restore_cache: From c7284da960daeb59c0d0f914761d95f4aa997848 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Mon, 9 Sep 2019 09:14:20 -0700 Subject: [PATCH 13/15] Updating for passing ecs_cluster as an object --- README.md | 2 +- main.tf | 38 +++++++++++++++++--------------------- variables.tf | 9 ++++++--- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 0d64370..ade644f 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ | container\_image | The image of the container. | string | `"golang:1.12.5-alpine"` | no | | container\_port | The port on which the container will receive traffic. | string | `"80"` | no | | ecr\_repo\_arns | The ARNs of the ECR repos. By default, allows all repositories. | list(string) | `[ "*" ]` | no | -| ecs\_cluster\_name | The name of the ECS cluster. | string | n/a | yes | +| ecs\_cluster | ECS cluster object for this task. | object | n/a | yes | | ecs\_instance\_role | The name of the ECS instance role. | string | `""` | no | | ecs\_subnet\_ids | Subnet IDs for the ECS tasks. | list(string) | n/a | yes | | ecs\_use\_fargate | Whether to use Fargate for the task definition. | string | `"false"` | no | diff --git a/main.tf b/main.tf index 9f6f73d..a32b689 100644 --- a/main.tf +++ b/main.tf @@ -25,16 +25,16 @@ * name = "app" * environment = "prod" * - * ecs_cluster_name = "cluster-name" - * ecs_vpc_id = "${module.vpc.vpc_id}" - * ecs_subnet_ids = "${module.vpc.private_subnets}" + * ecs_cluster = aws_ecs_cluster.mycluster + * ecs_vpc_id = module.vpc.vpc_id + * ecs_subnet_ids = module.vpc.private_subnets * tasks_desired_count = 2 * tasks_minimum_healthy_percent = 50 * tasks_maximum_percent = 200 * * associate_alb = true - * alb_security_group = "${module.security_group.id}" - * lb_target_group = "${module.target_group.id}" + * alb_security_group = module.security_group.id + * lb_target_group = module.target_group.id * } * ``` * @@ -47,24 +47,20 @@ * name = "app" * environment = "prod" * - * ecs_cluster_name = "cluster-name" - * ecs_vpc_id = "${module.vpc.vpc_id}" - * ecs_subnet_ids = "${module.vpc.private_subnets}" + * ecs_cluster = aws_ecs_cluster.mycluster + * ecs_vpc_id = module.vpc.vpc_id + * ecs_subnet_ids = module.vpc.private_subnets * tasks_desired_count = 2 * tasks_minimum_healthy_percent = 50 * tasks_maximum_percent = 200 * * associate_nlb = true * nlb_subnet_cidr_blocks = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] - * lb_target_group = "${module.target_group.id}" + * lb_target_group = module.target_group.id * } * ``` */ -data "aws_ecs_cluster" "main" { - cluster_name = "${var.ecs_cluster_name}" -} - locals { awslogs_group = "${var.logs_cloudwatch_group == "" ? "/ecs/${var.environment}/${var.name}" : var.logs_cloudwatch_group}" target_container_name = "${var.target_container_name == "" ? "${var.name}-${var.environment}" : var.target_container_name}" @@ -143,7 +139,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu" { threshold = var.cloudwatch_alarm_cpu_threshold dimensions = { - "ClusterName" = var.ecs_cluster_name + "ClusterName" = var.ecs_cluster.name "ServiceName" = aws_ecs_service.main[count.index].name } } @@ -164,7 +160,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem" { threshold = var.cloudwatch_alarm_mem_threshold dimensions = { - "ClusterName" = var.ecs_cluster_name + "ClusterName" = var.ecs_cluster.name "ServiceName" = aws_ecs_service.main[count.index].name } } @@ -185,7 +181,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_cpu_no_lb" { threshold = var.cloudwatch_alarm_cpu_threshold dimensions = { - "ClusterName" = var.ecs_cluster_name + "ClusterName" = var.ecs_cluster.name "ServiceName" = aws_ecs_service.main_no_lb[count.index].name } } @@ -206,7 +202,7 @@ resource "aws_cloudwatch_metric_alarm" "alarm_mem_no_lb" { threshold = var.cloudwatch_alarm_mem_threshold dimensions = { - "ClusterName" = var.ecs_cluster_name + "ClusterName" = var.ecs_cluster.name "ServiceName" = aws_ecs_service.main_no_lb[count.index].name } } @@ -304,7 +300,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { "ecs:Submit*", ] - resources = [data.aws_ecs_cluster.main.arn] + resources = [var.ecs_cluster.arn] } statement { @@ -317,7 +313,7 @@ data "aws_iam_policy_document" "instance_role_policy_doc" { condition { test = "StringEquals" variable = "ecs:cluster" - values = [data.aws_ecs_cluster.main.arn] + values = [var.ecs_cluster.arn] } } @@ -501,7 +497,7 @@ resource "aws_ecs_service" "main" { count = var.associate_alb || var.associate_nlb ? 1 : 0 name = var.name - cluster = data.aws_ecs_cluster.main.arn + cluster = var.ecs_cluster.arn launch_type = local.ecs_service_launch_type @@ -556,7 +552,7 @@ resource "aws_ecs_service" "main_no_lb" { count = var.associate_alb || var.associate_nlb ? 0 : 1 name = var.name - cluster = data.aws_ecs_cluster.main.arn + cluster = var.ecs_cluster.arn launch_type = local.ecs_service_launch_type diff --git a/variables.tf b/variables.tf index fd6662b..293144c 100644 --- a/variables.tf +++ b/variables.tf @@ -68,9 +68,12 @@ variable "ecs_use_fargate" { type = string } -variable "ecs_cluster_name" { - description = "The name of the ECS cluster." - type = "string" +variable "ecs_cluster" { + description = "ECS cluster object for this task." + type = object({ + arn = string + name = string + }) } variable "ecs_instance_role" { From 668fc1b8b63bc701ea52933a64d15e0bbcd031a3 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Mon, 9 Sep 2019 10:05:33 -0700 Subject: [PATCH 14/15] Bumping tf precommit hook version and updating README. --- .pre-commit-config.yaml | 2 +- README.md | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3624c97..5e17f67 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,7 +17,7 @@ repos: - id: markdownlint - repo: git://github.com/antonbabenko/pre-commit-terraform - rev: v1.17.0 + rev: v1.18.0 hooks: - id: terraform_docs - id: terraform_fmt diff --git a/README.md b/README.md index ade644f..6af7164 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,8 @@ ### 1.15.0 to 2.0.0 -v2.0.0 of this module is built against Terraform v0.12. However, this -introduces a bug that prevents the creation of an ECS service with this -module prior to creation of the cluster which it is going to run on (see -). To work around -this, create the cluster first, and then add the call to this module once -the cluster exists. - +v2.0.0 of this module is built against Terraform v0.12. In addition to +requiring this upgrade, the v1.15.0 version of the module took the name +of the ECS cluster as a parameter; v2.0.0 takes the actual object of the +ECS cluster as a parameter instead. You will need to update previous +instances of this module with the altered parameter. From 48e96a1f652eb36fc340fa3a688809e42457ff25 Mon Sep 17 00:00:00 2001 From: Chastity Blackwell Date: Mon, 9 Sep 2019 10:12:14 -0700 Subject: [PATCH 15/15] Adding README lines manually due to terraform_docs issues --- README.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/README.md b/README.md index 6af7164..d957475 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,64 @@ +Creates an ECS service. + +Creates the following resources: + +* CloudWatch log group. +* Security Groups for the ECS service. +* ECS service. +* Task definition using `golang:1.12.5-alpine` (see below). +* Configurable associations with Network Load Balancers (NLB) and Application Load Balancers (ALB). + +We create an initial task definition using the `golang:1.12.5-alpine` image as a way +to validate the initial infrastructure is working: visiting the site shows +a simple Go hello world page. We expect deployments to manage the container +definitions going forward, not Terraform. + +## Usage + +### ECS service associated with an Application Load Balancer (ALB) + +```hcl +module "app_ecs_service" { + source = "trussworks/ecs-service/aws" + + name = "app" + environment = "prod" + + ecs_cluster = aws_ecs_cluster.mycluster + ecs_vpc_id = module.vpc.vpc_id + ecs_subnet_ids = module.vpc.private_subnets + tasks_desired_count = 2 + tasks_minimum_healthy_percent = 50 + tasks_maximum_percent = 200 + + associate_alb = true + alb_security_group = module.security_group.id + lb_target_group = module.target_group.id +} +``` + +### ECS Service associated with a Network Load Balancer(NLB) + +```hcl +module "app_ecs_service" { + source = "trussworks/ecs-service/aws" + + name = "app" + environment = "prod" + + ecs_cluster = aws_ecs_cluster.mycluster + ecs_vpc_id = module.vpc.vpc_id + ecs_subnet_ids = module.vpc.private_subnets + tasks_desired_count = 2 + tasks_minimum_healthy_percent = 50 + tasks_maximum_percent = 200 + + associate_nlb = true + nlb_subnet_cidr_blocks = ["10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24"] + lb_target_group = module.target_group.id +} +``` + ## Inputs