Skip to content

Commit aa0c7b0

Browse files
authored
Merge pull request #9 from synapsestudios/replace-rds-module
Pull RDS module into this one since it is not reused elsewhere
2 parents 10bca56 + 2fb3436 commit aa0c7b0

8 files changed

+198
-18
lines changed

README.md

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ You can do this by commenting out the entire module, running a terraform apply,
2525

2626
| Name | Source | Version |
2727
|------|--------|---------|
28-
| <a name="module_database"></a> [database](#module\_database) | git::https://github.com/synapsestudios/terraform-aws-rds-aurora-cluster.git | v1.0.0 |
28+
| <a name="module_database"></a> [database](#module\_database) | ./rds_cluster | n/a |
2929
| <a name="module_service_container_definition"></a> [service\_container\_definition](#module\_service\_container\_definition) | cloudposse/ecs-container-definition/aws | 0.58.1 |
3030

3131
## Resources
@@ -58,9 +58,12 @@ You can do this by commenting out the entire module, running a terraform apply,
5858
| <a name="input_azs"></a> [azs](#input\_azs) | Availability zones | `list(string)` | n/a | yes |
5959
| <a name="input_cluster_arn"></a> [cluster\_arn](#input\_cluster\_arn) | ECS cluster to deploy into | `string` | n/a | yes |
6060
| <a name="input_command"></a> [command](#input\_command) | Container startup command | `list(string)` | n/a | yes |
61+
| <a name="input_container_image"></a> [container\_image](#input\_container\_image) | Image tag of the Docker container to use for this service | `string` | n/a | yes |
6162
| <a name="input_container_port"></a> [container\_port](#input\_container\_port) | Port exposed by the container | `number` | n/a | yes |
6263
| <a name="input_container_secrets"></a> [container\_secrets](#input\_container\_secrets) | The Secrets to Pass to the container. | <pre>list(object({<br> name = string<br> valueFrom = string<br> }))</pre> | `[]` | no |
63-
| <a name="input_ecr_host"></a> [ecr\_host](#input\_ecr\_host) | Hostname of the ECR repository with no trailing slash | `string` | n/a | yes |
64+
| <a name="input_db_instance_class"></a> [db\_instance\_class](#input\_db\_instance\_class) | Size of instances within the RDS cluster | `string` | `"db.t4g.medium"` | no |
65+
| <a name="input_db_instance_count"></a> [db\_instance\_count](#input\_db\_instance\_count) | How many RDS instances to create | `number` | `1` | no |
66+
| <a name="input_db_name"></a> [db\_name](#input\_db\_name) | Name of the postgres database to create, if creating an RDS cluster | `string` | `"main"` | no |
6467
| <a name="input_ecs_desired_count"></a> [ecs\_desired\_count](#input\_ecs\_desired\_count) | How many tasks to launch in ECS service | `number` | `1` | no |
6568
| <a name="input_environment_variables"></a> [environment\_variables](#input\_environment\_variables) | The environment variables to pass to the container. This is a list of maps. | <pre>list(object({<br> name = string<br> value = string<br> }))</pre> | `[]` | no |
6669
| <a name="input_health_check_path"></a> [health\_check\_path](#input\_health\_check\_path) | Path to use for health checks | `string` | n/a | yes |

alb_target_group.tf

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ resource "aws_lb_target_group" "this" {
55
protocol = "HTTP"
66
target_type = "ip"
77
vpc_id = var.vpc_id
8-
# tags = var.tags # TODO
98

109
lifecycle {
1110
create_before_destroy = true

db.tf

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
module "database" {
2-
count = var.use_database_cluster ? 1 : 0
3-
source = "git::https://github.com/synapsestudios/terraform-aws-rds-aurora-cluster.git?ref=v1.0.0"
4-
availability_zones = var.azs
5-
database_subnets = var.subnets
6-
db_cluster_parameter_group_name = "default.aurora-postgresql14"
7-
instance_class = "db.t4g.medium"
8-
name = "backend"
9-
vpc_id = var.vpc_id
10-
database_name = "backend"
2+
count = var.use_database_cluster ? 1 : 0
3+
source = "./rds_cluster"
4+
availability_zones = var.azs
5+
database_subnets = var.subnets
6+
instance_class = var.db_instance_class
7+
instance_count = var.db_instance_count
8+
name = var.service_name
9+
vpc_id = var.vpc_id
10+
database_name = var.db_name
1111
}

ecs_task_definitions.tf

+2-3
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,19 @@ resource "aws_ecs_task_definition" "service" {
88
memory = 2048
99
cpu = 1024
1010
requires_compatibilities = ["FARGATE"]
11-
# tags = var.tags # TODO
1211
}
1312

13+
#tfsec:ignore:aws-cloudwatch-log-group-customer-key
1414
resource "aws_cloudwatch_log_group" "service" {
1515
name_prefix = var.service_name
16-
# tags = var.tags # TODO
1716
}
1817

1918
module "service_container_definition" {
2019
source = "cloudposse/ecs-container-definition/aws"
2120
version = "0.58.1"
2221

2322
container_name = var.service_name
24-
container_image = "${var.ecr_host}/${var.service_name}:latest"
23+
container_image = var.container_image
2524
container_memory = 2048
2625
essential = true
2726
environment = var.environment_variables

ecs_task_security_group.tf

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ resource "aws_security_group" "ecs_task" {
22
description = "ECS Tasks traffic rules"
33
vpc_id = var.vpc_id
44
name_prefix = "${var.service_name}-ecs-task-default"
5-
# tags = merge(var.tags, { Name = "ECSTasks" }) # TODO
65

76
egress {
87
from_port = 0

rds_cluster/main.tf

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
resource "random_id" "final_snapshot_suffix" {
2+
byte_length = 8
3+
}
4+
5+
#tfsec:ignore:aws-rds-encrypt-cluster-storage-data
6+
resource "aws_rds_cluster" "this" {
7+
cluster_identifier_prefix = var.name
8+
engine = "aurora-postgresql"
9+
engine_version = "14.6"
10+
database_name = var.database_name
11+
skip_final_snapshot = false
12+
final_snapshot_identifier = "${var.name}-final-${random_id.final_snapshot_suffix.hex}"
13+
master_username = "root"
14+
master_password = aws_secretsmanager_secret_version.root_password.secret_string
15+
db_subnet_group_name = aws_db_subnet_group.this.name
16+
storage_encrypted = true
17+
availability_zones = var.availability_zones
18+
preferred_backup_window = "07:00-09:00"
19+
backup_retention_period = 30
20+
vpc_security_group_ids = concat([aws_security_group.this.id], var.additional_security_groups)
21+
tags = var.tags
22+
db_cluster_parameter_group_name = "default.aurora-postgresql14"
23+
deletion_protection = true
24+
}
25+
26+
resource "random_password" "password" {
27+
length = 32
28+
special = true
29+
min_special = 1
30+
override_special = "-._~" # URL-safe characters prevent parsing errors when using this password in a connection string
31+
}
32+
33+
#tfsec:ignore:aws-ssm-secret-use-customer-key
34+
resource "aws_secretsmanager_secret" "root_password" {
35+
name_prefix = "${var.name}-aurora-root-password"
36+
description = "Root password for the ${var.name} aurora cluster database"
37+
tags = var.tags
38+
}
39+
40+
resource "aws_secretsmanager_secret_version" "root_password" {
41+
secret_id = aws_secretsmanager_secret.root_password.id
42+
secret_string = random_password.password.result
43+
}
44+
45+
#tfsec:ignore:aws-ssm-secret-use-customer-key
46+
resource "aws_secretsmanager_secret" "connection_string" {
47+
name_prefix = "${var.name}-aurora-connection-string"
48+
description = "Connection String for the ${var.name} aurora cluster database"
49+
tags = var.tags
50+
}
51+
52+
resource "aws_secretsmanager_secret_version" "connection_string" {
53+
secret_id = aws_secretsmanager_secret.connection_string.id
54+
secret_string = "postgresql://${aws_rds_cluster.this.master_username}:${aws_secretsmanager_secret_version.root_password.secret_string}@${aws_rds_cluster.this.endpoint}:${aws_rds_cluster.this.port}/${aws_rds_cluster.this.database_name}"
55+
}
56+
57+
#tfsec:ignore:aws-rds-enable-performance-insights-encryption
58+
resource "aws_rds_cluster_instance" "this" {
59+
count = var.instance_count
60+
engine = "aurora-postgresql"
61+
engine_version = "14.6"
62+
identifier_prefix = "${var.name}-${count.index + 1}"
63+
performance_insights_enabled = true
64+
cluster_identifier = aws_rds_cluster.this.id
65+
instance_class = var.instance_class
66+
db_subnet_group_name = aws_db_subnet_group.this.name
67+
tags = var.tags
68+
}
69+
70+
resource "aws_db_subnet_group" "this" {
71+
name_prefix = var.name
72+
description = "${var.name} RDS Subnet Group"
73+
subnet_ids = var.database_subnets
74+
tags = var.tags
75+
}
76+
77+
resource "aws_security_group" "this" {
78+
name_prefix = "${var.name}-database-access"
79+
description = "Database traffic rules"
80+
vpc_id = var.vpc_id
81+
tags = merge(var.tags, { name = "database" })
82+
ingress {
83+
from_port = 5432
84+
to_port = 5432
85+
protocol = "tcp"
86+
cidr_blocks = [data.aws_vpc.database_vpc.cidr_block]
87+
description = "Database ingress"
88+
}
89+
egress {
90+
from_port = 5432
91+
to_port = 5432
92+
protocol = "tcp"
93+
cidr_blocks = [data.aws_vpc.database_vpc.cidr_block]
94+
description = "Database egress"
95+
}
96+
}
97+
98+
data "aws_vpc" "database_vpc" {
99+
id = var.vpc_id
100+
}
101+
102+
output "db_cluster_id" {
103+
value = aws_rds_cluster.this.cluster_identifier
104+
}
105+
106+
output "security_group_id" {
107+
value = aws_security_group.this.id
108+
}
109+
110+
output "root_password_secret_id" {
111+
value = aws_secretsmanager_secret.root_password.id
112+
}
113+
114+
output "connection_string_arn" {
115+
value = aws_secretsmanager_secret.connection_string.arn
116+
}

rds_cluster/variables.tf

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
variable "name" {
2+
type = string
3+
description = "Determines naming convention of assets. Generally follows DNS naming convention."
4+
}
5+
6+
variable "database_name" {
7+
type = string
8+
description = "Name of the default database to create"
9+
}
10+
11+
variable "vpc_id" {
12+
type = string
13+
description = "The ID of the vpc the database belongs to"
14+
}
15+
16+
variable "availability_zones" {
17+
type = list(string)
18+
description = "Availability zones for the database"
19+
}
20+
21+
variable "database_subnets" {
22+
type = list(string)
23+
description = "Subnets for the database"
24+
}
25+
26+
variable "additional_security_groups" {
27+
type = list(string)
28+
default = []
29+
description = "Any additional security groups the cluster should be added to"
30+
}
31+
32+
variable "tags" {
33+
type = map(string)
34+
description = "A mapping of tags to assign to the AWS resources."
35+
default = {}
36+
}
37+
38+
variable "instance_count" {
39+
type = number
40+
description = "How many RDS instances to create"
41+
}
42+
43+
variable "instance_class" {
44+
type = string
45+
description = "Instance class"
46+
}

variables.tf

+20-2
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ variable "subnets" {
1313
description = "List of subnet names the service will reside on."
1414
}
1515

16-
variable "ecr_host" {
16+
variable "container_image" {
1717
type = string
18-
description = "Hostname of the ECR repository with no trailing slash"
18+
description = "Image tag of the Docker container to use for this service"
1919
}
2020

2121
variable "azs" {
@@ -97,3 +97,21 @@ variable "ecs_desired_count" {
9797
default = 1
9898
description = "How many tasks to launch in ECS service"
9999
}
100+
101+
variable "db_name" {
102+
type = string
103+
default = "main"
104+
description = "Name of the postgres database to create, if creating an RDS cluster"
105+
}
106+
107+
variable "db_instance_class" {
108+
type = string
109+
default = "db.t4g.medium"
110+
description = "Size of instances within the RDS cluster"
111+
}
112+
113+
variable "db_instance_count" {
114+
type = number
115+
default = 1
116+
description = "How many RDS instances to create"
117+
}

0 commit comments

Comments
 (0)