Skip to content

Commit 3d23857

Browse files
committed
feat: prepare aws-ecs and aws-rds to EUSC AWS partition, migrate Terragrunt cli usage, update Datadog ECS/Postres check configueration
1 parent 898be18 commit 3d23857

File tree

19 files changed

+440
-79
lines changed

19 files changed

+440
-79
lines changed

terraform/aws/aws-ecs/Makefile

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,37 @@ SHELL := /usr/bin/env bash
44
DEBUG := false
55
ifeq ($(strip $(DEBUG)),true)
66
TF_LOG := DEBUG
7-
TG_FLAGS := --terragrunt-debug
7+
TG_FLAGS := --inputs-debug
88
endif
99

1010
MODE := apply
1111
ifeq ($(strip $(MODE)),apply)
12-
MODE_STR := apply -auto-approve
12+
MODE_STR := --non-interactive -- apply -auto-approve
1313
else ifeq ($(strip $(MODE)),destroy)
14-
MODE_STR := destroy -auto-approve
14+
MODE_STR := --non-interactive -- destroy -auto-approve
1515
else
16-
MODE_STR := plan
16+
MODE_STR := --non-interactive -- plan
1717
endif
1818

19+
PARTITION := aws
20+
1921
ENV := dev
2022

23+
ifeq ($(strip $(PARTITION)),eusc)
24+
DEPLOY_PATH := stage/eusc/$(ENV)
25+
else
26+
DEPLOY_PATH := stage/$(ENV)
27+
endif
28+
2129
init:
22-
cd stage/$(ENV) && terragrunt init -upgrade=true --backend-bootstrap --non-interactive
30+
cd $(DEPLOY_PATH) && terragrunt run -- init -upgrade=true
2331

2432
run: init ## setup ECS services: make run [ENV=dev] [MODE=apply]
25-
@cd stage/$(ENV) && terragrunt validate && terragrunt $(MODE_STR) --non-interactive $(TG_FLAGS)
33+
@cd $(DEPLOY_PATH) && terragrunt run validate && terragrunt run $(MODE_STR) $(TG_FLAGS)
2634

2735

2836
show-state: ## show state
29-
cd stage/$(ENV) && terragrunt state list && terragrunt show
37+
cd $(DEPLOY_PATH) && terragrunt state list && terragrunt show
3038

3139
clean: ## clean cached plugins and data
3240
find . -name ".terra*" -exec rm -rf {} +

terraform/aws/aws-ecs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ aws configure
3535
```bash
3636

3737
# deploy ECS apps
38-
make run ENV=dev MODE=apply
38+
make run MODE=apply [ENV=dev] [PARTITION=aws]
3939

4040
# show Terraform state
4141
make show-state

terraform/aws/aws-ecs/module/alb.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ resource "aws_lb" "app" {
1414
load_balancer_type = "application"
1515
security_groups = [data.aws_security_group.app-security-group[each.key].id]
1616

17-
# TODO replace with subnet mapping to reserver EIP
17+
# TODO replace with subnet mapping to reserved EIP
1818
subnets = local.private_subnet_ids
1919
}
2020

@@ -29,7 +29,7 @@ resource "aws_lb_listener" "app" {
2929
# port = "443"
3030
# protocol = "HTTPS"
3131
# ssl_policy = "ELBSecurityPolicy-2016-08"
32-
# certificate_arn = "arn:aws:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"
32+
# certificate_arn = "arn:${var.partition}:iam::187416307283:server-certificate/test_cert_rab3wuqwgja25ct3n4jdj2tzu4"
3333

3434
default_action {
3535
type = "forward"

terraform/aws/aws-ecs/module/app.tf

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,10 @@ resource "aws_ecs_service" "app" {
109109
security_groups = [data.aws_security_group.app-security-group[each.key].id]
110110
}
111111

112-
deployment_maximum_percent = "200"
113-
deployment_minimum_healthy_percent = "50"
112+
deployment_maximum_percent = try(each.value.maximum_percent, 200)
113+
deployment_minimum_healthy_percent = try(each.value.minimum_healthy_percent, 50)
114114

115+
availability_zone_rebalancing = coalesce(each.value.maximum_percent, 200) > 100 ? "ENABLED" : "DISABLED"
115116

116117
dynamic "load_balancer" {
117118
for_each = each.value.port != 0 ? [1] : []

terraform/aws/aws-ecs/module/iam.tf

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ resource "aws_iam_role" "task-role" {
1515
"Action":"sts:AssumeRole",
1616
"Condition":{
1717
"ArnLike":{
18-
"aws:SourceArn":"arn:aws:ecs:${var.region}:${local.account_id}:*"
18+
"aws:SourceArn":"arn:${var.partition}:ecs:${var.region}:${local.account_id}:*"
1919
},
2020
"StringEquals":{
2121
"aws:SourceAccount":"${local.account_id}"
@@ -36,12 +36,20 @@ EOF
3636
{
3737
"Effect": "Allow",
3838
"Action": [
39-
"ssmmessages:CreateControlChannel",
40-
"ssmmessages:CreateDataChannel",
41-
"ssmmessages:OpenControlChannel",
42-
"ssmmessages:OpenDataChannel"
39+
"ssmmessages:CreateControlChannel",
40+
"ssmmessages:CreateDataChannel",
41+
"ssmmessages:OpenControlChannel",
42+
"ssmmessages:OpenDataChannel"
4343
],
4444
"Resource": "*"
45+
},
46+
{
47+
"Effect": "Allow",
48+
"Action": [
49+
"ecs:ListClusters",
50+
"ecs:ListContainerInstances",
51+
"ecs:DescribeContainerInstances"],
52+
"Resource": "*"
4553
}
4654
]
4755
}
@@ -88,9 +96,9 @@ EOF
8896
"kms:Decrypt"
8997
],
9098
"Resource": [
91-
"arn:aws:ssm:${var.region}:${local.account_id}:parameter/*",
92-
"arn:aws:secretsmanager:${var.region}:${local.account_id}:secret:*",
93-
"arn:aws:kms:${var.region}:${local.account_id}:key/*"
99+
"arn:${var.partition}:ssm:${var.region}:${local.account_id}:parameter/*",
100+
"arn:${var.partition}:secretsmanager:${var.region}:${local.account_id}:secret:*",
101+
"arn:${var.partition}:kms:${var.region}:${local.account_id}:key/*"
94102
]
95103
}
96104
]
@@ -103,5 +111,5 @@ EOF
103111

104112
resource "aws_iam_role_policy_attachment" "exec-role" {
105113
role = aws_iam_role.exec-role.name
106-
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
114+
policy_arn = "arn:${var.partition}:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
107115
}

terraform/aws/aws-ecs/module/variables.tf

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@ variable "zones" {
2424

2525
variable "apps" {
2626
type = map(object({
27-
name = string
28-
image = string
29-
memory = number
30-
cpu = number
31-
port = number
32-
protocol = string
33-
desired_instances = number
34-
security_group_name = string
35-
env_vars = list(map(string))
36-
docker_labels = map(string)
27+
name = string
28+
image = string
29+
memory = number
30+
cpu = number
31+
port = number
32+
protocol = string
33+
desired_instances = number
34+
security_group_name = string
35+
env_vars = list(map(string))
36+
docker_labels = map(string)
37+
maximum_percent = optional(number)
38+
minimum_healthy_percent = optional(number)
3739
}))
3840
description = "Map of apps to deploy as ECS tasks,"
3941
}
@@ -54,6 +56,11 @@ variable "zone" {
5456
}
5557

5658
# tflint-ignore: terraform_unused_declarations
59+
variable "partition" {
60+
type = string
61+
description = "The AWS partition in which to create resources"
62+
default = "aws"
63+
}
5764
variable "region" {
5865
default = "us-east-1"
5966
type = string
@@ -62,6 +69,6 @@ variable "region" {
6269

6370
# tflint-ignore: terraform_unused_declarations
6471
variable "aws_tags" {
65-
type = map(string)
72+
type = map(any)
6673
description = "AWS tags"
6774
}

terraform/aws/aws-ecs/module/versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ terraform {
55
version = "~> 6"
66
}
77
}
8-
required_version = ">= 1.0"
8+
required_version = ">= 1.9"
99
}

terraform/aws/aws-ecs/stage/dev/terragrunt.hcl

Lines changed: 35 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
locals {
2+
region = "us-east-1"
3+
dd_api_key = try(get_env("DD_API_KEY"), "")
4+
dd_rds_dns = try(get_env("DD_RDS_DNS"), "")
5+
dd_rds_password = try(get_env("DD_RDS_PASSWORD"), "")
6+
dd_db_instance_identifier = try(get_env("DD_DB_INSTANCE_IDENTIFIER"), "")
7+
}
8+
19
include "root" {
210
path = find_in_parent_folders("root.hcl")
311
}
@@ -10,14 +18,14 @@ terraform {
1018

1119
inputs = {
1220
env = "dev"
13-
region = "us-east-1"
14-
zone = "us-east-1a"
15-
vpc_name = "dev-us-east-1"
21+
region = local.region
22+
zone = "${local.region}a"
23+
vpc_name = "dev-${local.region}"
1624
aws_tags = {
1725
Env = "dev"
18-
Region = "us-east1"
26+
Region = local.region
1927
}
20-
zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
28+
zones = ["${local.region}a", "${local.region}b", "${local.region}c"]
2129
apps = {
2230
"nginx" : {
2331
name = "nginx",
@@ -27,13 +35,24 @@ inputs = {
2735
cpu = 1024,
2836
memory = 2048,
2937
port = 80,
30-
security_group_name = "dev-ssh-http-from-vpc"
38+
security_group_name = "dev-${local.region}-ssh-http-from-vpc"
3139
env_vars = []
3240
docker_labels = {}
3341
},
3442
# Datadog agent for RDS database monitoring
43+
# Configure PostgreSQL database: add user and grant permissions:
44+
# https://docs.datadoghq.com/database_monitoring/setup_postgres/rds?tab=postgres15#grant-the-agent-access
3545
# https://docs.datadoghq.com/database_monitoring/setup_postgres/aurora?tab=docker#install-the-agent
3646
#
47+
# To deploy and test:
48+
#
49+
# export DD_API_KEY="your_api_key"
50+
# export DD_RDS_DNS="dev.cluster-czk84imkkq6n.eusc-de-east-1.rds.amazonaws.eu"
51+
# export DD_RDS_PASSWORD="datadog"
52+
# export DD_DB_INSTANCE_IDENTIFIER="dev"
53+
#
54+
# And uncomment:
55+
#
3756
# "rds-datadog-agent" : {
3857
# name = "rds-datadog-agent",
3958
# image = "public.ecr.aws/datadog/agent:latest",
@@ -42,11 +61,18 @@ inputs = {
4261
# cpu = 256,
4362
# memory = 512,
4463
# port = 0, # do not expose via ALB
45-
# security_group_name = "dev-us-east-1-psql-from-vpc"
64+
# security_group_name = "dev-${local.region}-psql-from-vpc"
65+
# # to emulate Recreate deployment strategy
66+
# maximum_percent = 100,
67+
# minimum_healthy_percent = 0,
4668
# env_vars = [
4769
# {
4870
# "name": "DD_API_KEY",
49-
# "value": "<DD_API_KEY_HERE>"
71+
# "value": "${local.dd_api_key}"
72+
# },
73+
# {
74+
# "name": "DD_SITE",
75+
# "value": "datadoghq.com"
5076
# },
5177
# {
5278
# "name": "DD_HEALTH_PORT",
@@ -61,25 +87,8 @@ inputs = {
6187
# "value": "true"
6288
# },
6389
# ],
64-
#
65-
## TODO migrate DD checks/integration with format for Datadog Agent v7.36+:
66-
## Example on Redis check:
67-
##
68-
## labels:
69-
## com.datadoghq.ad.checks: '{"redisdb": {"instances": [{"host": "%%host%%","port":"6379","password":"%%env_REDIS_PASSWORD%%"}], "logs": [{"type": "file", "path": "/var/log/redis_6379.log", "source": "redis", "service": "redis_service"}]}}'
70-
##
71-
## For earlier Agent versions it was formatted like:
72-
##
73-
## labels:
74-
## com.datadoghq.ad.check_names: '["redisdb"]'
75-
## com.datadoghq.ad.init_configs: '[{}]'
76-
## com.datadoghq.ad.instances: '[{"host": "%%host%%","port":"6379","password":"%%env_REDIS_PASSWORD%%"}]'
77-
## com.datadoghq.ad.logs: '[{"type": "file", "path": "/var/log/redis_6379.log", "source": "redis", "service": "redis_service"}]'
78-
#
7990
# docker_labels = {
80-
# "com.datadoghq.ad.check_names": "[\"postgres\"]",
81-
# "com.datadoghq.ad.init_configs": "[{}]",
82-
# "com.datadoghq.ad.instances": "[{\"dbm\": true, \"host\": \"<RDS-DNS>\", \"port\": 5432, \"username\": \"datadog\", \"password\": \"<PASSWORD>\" }]"
91+
# "com.datadoghq.ad.checks": "{\"postgres\": {\"instances\": [{\"dbm\": true, \"host\": \"${local.dd_rds_dns}\", \"port\": 5432, \"username\": \"datadog\", \"password\": \"${local.dd_rds_password}\", \"database_autodiscovery\": {\"enabled\": true}, \"aws\": {\"instance_endpoint\": \"${local.dd_rds_dns}\", \"region\": \"${local.region}\"}, \"tags\": [\"dbinstanceidentifier:${local.dd_db_instance_identifier}\"] }]}}"
8392
# },
8493
# },
8594
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
locals {
2+
bucket = "${local.account}-terraform-state"
3+
account = "${run_cmd("--terragrunt-quiet", "aws", "sts", "get-caller-identity", "--query", "\"Account\"", "--output", "text")}"
4+
region = "eusc-de-east-1"
5+
zone = "eusc-de-east-1a"
6+
}
7+
8+
remote_state {
9+
backend = "s3"
10+
generate = {
11+
path = "state.tf"
12+
if_exists = "overwrite_terragrunt"
13+
}
14+
config = {
15+
bucket = local.bucket
16+
key = "${basename(abspath("${get_parent_terragrunt_dir()}/.."))}/${basename(get_parent_terragrunt_dir())}/${path_relative_to_include()}/terraform.tfstate"
17+
region = local.region
18+
# TODO play with it... maybe not in free tier
19+
# encrypt = true
20+
# dynamodb_table = "my-lock-table"
21+
}
22+
}
23+
24+
25+
generate "provider" {
26+
path = "provider.tf"
27+
if_exists = "overwrite_terragrunt"
28+
contents = <<EOF
29+
provider "aws" {
30+
region = var.region
31+
default_tags {
32+
tags = var.aws_tags
33+
}
34+
}
35+
EOF
36+
}
37+
38+
terraform {
39+
extra_arguments "common_vars" {
40+
commands = get_terraform_commands_that_need_vars()
41+
42+
env_vars = {
43+
TF_VAR_terraform_state_bucket = local.bucket
44+
}
45+
}
46+
}
47+
48+
inputs = {
49+
account = local.account
50+
region = local.region
51+
zone = local.zone
52+
53+
partition = "aws-eusc"
54+
55+
}

0 commit comments

Comments
 (0)