Skip to content

Commit 59c1a78

Browse files
authored
feat: Added conditional creation of RDS Aurora cluster (#159)
1 parent b56e055 commit 59c1a78

11 files changed

Lines changed: 87 additions & 49 deletions

File tree

README.md

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,21 @@ module "db" {
5656
}
5757
```
5858

59+
## Conditional creation
60+
61+
Sometimes you need to have a way to create RDS Aurora resources conditionally but Terraform does not allow to use `count` inside `module` block, so the solution is to specify argument `create_cluster`.
62+
63+
```hcl
64+
# This RDS cluster will not be created
65+
module "db" {
66+
source = "terraform-aws-modules/rds-aurora/aws"
67+
version = "~> 2.0"
68+
69+
create_cluster = false
70+
# ... omitted
71+
}
72+
```
73+
5974
## Examples
6075

6176
- [PostgreSQL](examples/postgresql): A simple example with VPC and PostgreSQL cluster.
@@ -73,16 +88,16 @@ Terraform documentation is generated automatically using [pre-commit hooks](http
7388

7489
| Name | Version |
7590
|------|---------|
76-
| terraform | >= 0.12.6, < 0.14 |
77-
| aws | >= 2.45, < 4.0 |
78-
| random | ~> 2.2 |
91+
| terraform | >= 0.12.6 |
92+
| aws | >= 2.45 |
93+
| random | >= 2.2 |
7994

8095
## Providers
8196

8297
| Name | Version |
8398
|------|---------|
84-
| aws | >= 2.45, < 4.0 |
85-
| random | ~> 2.2 |
99+
| aws | >= 2.45 |
100+
| random | >= 2.2 |
86101

87102
## Inputs
88103

@@ -96,6 +111,7 @@ Terraform documentation is generated automatically using [pre-commit hooks](http
96111
| backup\_retention\_period | How long to keep backups for (in days) | `number` | `7` | no |
97112
| ca\_cert\_identifier | The identifier of the CA certificate for the DB instance | `string` | `"rds-ca-2019"` | no |
98113
| copy\_tags\_to\_snapshot | Copy all Cluster tags to snapshots. | `bool` | `false` | no |
114+
| create\_cluster | Controls if RDS cluster should be created (it affects almost all resources) | `bool` | `true` | no |
99115
| create\_monitoring\_role | Whether to create the IAM role for RDS enhanced monitoring | `bool` | `true` | no |
100116
| create\_security\_group | Whether to create security group for RDS cluster | `bool` | `true` | no |
101117
| database\_name | Name for an automatically created database on cluster creation | `string` | `""` | no |
@@ -112,13 +128,13 @@ Terraform documentation is generated automatically using [pre-commit hooks](http
112128
| global\_cluster\_identifier | The global cluster identifier specified on aws\_rds\_global\_cluster | `string` | `""` | no |
113129
| iam\_database\_authentication\_enabled | Specifies whether IAM Database authentication should be enabled or not. Not all versions and instances are supported. Refer to the AWS documentation to see which versions are supported. | `bool` | `false` | no |
114130
| iam\_roles | A List of ARNs for the IAM roles to associate to the RDS Cluster. | `list(string)` | `[]` | no |
115-
| instance\_type | Instance type to use at master instance. If instance\_type\_replica is not set it will use the same type for replica instances | `string` | n/a | yes |
131+
| instance\_type | Instance type to use at master instance. If instance\_type\_replica is not set it will use the same type for replica instances | `string` | `""` | no |
116132
| instance\_type\_replica | Instance type to use at replica instance | `string` | `null` | no |
117133
| instances\_parameters | Customized instance settings. Supported keys: instance\_name, instance\_type, instance\_promotion\_tier, publicly\_accessible | `list(map(string))` | `[]` | no |
118134
| kms\_key\_id | The ARN for the KMS encryption key if one is set to the cluster. | `string` | `""` | no |
119135
| monitoring\_interval | The interval (seconds) between points when Enhanced Monitoring metrics are collected | `number` | `0` | no |
120136
| monitoring\_role\_arn | IAM role for RDS to send enhanced monitoring metrics to CloudWatch | `string` | `""` | no |
121-
| name | Name given resources | `string` | n/a | yes |
137+
| name | Name given resources | `string` | `""` | no |
122138
| password | Master DB password | `string` | `""` | no |
123139
| performance\_insights\_enabled | Specifies whether Performance Insights is enabled or not. | `bool` | `false` | no |
124140
| performance\_insights\_kms\_key\_id | The ARN for the KMS key to encrypt Performance Insights data. | `string` | `""` | no |
@@ -146,7 +162,7 @@ Terraform documentation is generated automatically using [pre-commit hooks](http
146162
| subnets | List of subnet IDs to use | `list(string)` | `[]` | no |
147163
| tags | A map of tags to add to all resources. | `map(string)` | `{}` | no |
148164
| username | Master DB username | `string` | `"root"` | no |
149-
| vpc\_id | VPC ID | `string` | n/a | yes |
165+
| vpc\_id | VPC ID | `string` | `""` | no |
150166
| vpc\_security\_group\_ids | List of VPC security groups to associate to the cluster in addition to the SG we create in this module | `list(string)` | `[]` | no |
151167

152168
## Outputs

examples/advanced/versions.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
2-
required_version = ">= 0.12.6, < 0.14"
2+
required_version = ">= 0.12.6"
33

44
required_providers {
5-
aws = ">= 2.45, < 4.0"
5+
aws = ">= 2.45"
66
}
77
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
2-
required_version = ">= 0.12.6, < 0.14"
2+
required_version = ">= 0.12.6"
33

44
required_providers {
5-
aws = ">= 2.45, < 4.0"
5+
aws = ">= 2.45"
66
}
77
}

examples/mysql/main.tf

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,9 @@ resource "aws_iam_policy" "aurora_mysql_policy_iam_auth" {
8787
}
8888
POLICY
8989
}
90+
91+
module "disabled_aurora" {
92+
source = "../../"
93+
94+
create_cluster = false
95+
}

examples/mysql/versions.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
2-
required_version = ">= 0.12.6, < 0.14"
2+
required_version = ">= 0.12.6"
33

44
required_providers {
5-
aws = ">= 2.45, < 4.0"
5+
aws = ">= 2.45"
66
}
77
}

examples/postgresql/versions.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
2-
required_version = ">= 0.12.6, < 0.14"
2+
required_version = ">= 0.12.6"
33

44
required_providers {
5-
aws = ">= 2.45, < 4.0"
5+
aws = ">= 2.45"
66
}
77
}

examples/serverless/versions.tf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
terraform {
2-
required_version = ">= 0.12.6, < 0.14"
2+
required_version = ">= 0.12.6"
33

44
required_providers {
5-
aws = ">= 2.45, < 4.0"
5+
aws = ">= 2.45"
66
}
77
}

main.tf

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
locals {
22
port = var.port == "" ? var.engine == "aurora-postgresql" ? "5432" : "3306" : var.port
3-
master_password = var.password == "" ? random_password.master_password.result : var.password
3+
master_password = var.password == "" ? element(concat(random_password.master_password.*.result, [""]), 0) : var.password
44
db_subnet_group_name = var.db_subnet_group_name == "" ? join("", aws_db_subnet_group.this.*.name) : var.db_subnet_group_name
55
backtrack_window = (var.engine == "aurora-mysql" || var.engine == "aurora") && var.engine_mode != "serverless" ? var.backtrack_window : 0
66

@@ -14,12 +14,14 @@ locals {
1414

1515
# Random string to use as master password unless one is specified
1616
resource "random_password" "master_password" {
17+
count = var.create_cluster ? 1 : 0
18+
1719
length = 10
1820
special = false
1921
}
2022

2123
resource "aws_db_subnet_group" "this" {
22-
count = var.db_subnet_group_name == "" ? 1 : 0
24+
count = var.create_cluster && var.db_subnet_group_name == "" ? 1 : 0
2325

2426
name = var.name
2527
description = "For Aurora cluster ${var.name}"
@@ -31,6 +33,8 @@ resource "aws_db_subnet_group" "this" {
3133
}
3234

3335
resource "aws_rds_cluster" "this" {
36+
count = var.create_cluster ? 1 : 0
37+
3438
global_cluster_identifier = var.global_cluster_identifier
3539
cluster_identifier = var.name
3640
replication_source_identifier = var.replication_source_identifier
@@ -43,7 +47,7 @@ resource "aws_rds_cluster" "this" {
4347
database_name = var.database_name
4448
master_username = var.username
4549
master_password = local.master_password
46-
final_snapshot_identifier = "${var.final_snapshot_identifier_prefix}-${var.name}-${random_id.snapshot_identifier.hex}"
50+
final_snapshot_identifier = "${var.final_snapshot_identifier_prefix}-${var.name}-${element(concat(random_id.snapshot_identifier.*.hex, [""]), 0)}"
4751
skip_final_snapshot = var.skip_final_snapshot
4852
deletion_protection = var.deletion_protection
4953
backup_retention_period = var.backup_retention_period
@@ -79,10 +83,10 @@ resource "aws_rds_cluster" "this" {
7983
}
8084

8185
resource "aws_rds_cluster_instance" "this" {
82-
count = var.replica_scale_enabled ? var.replica_scale_min : var.replica_count
86+
count = var.create_cluster ? (var.replica_scale_enabled ? var.replica_scale_min : var.replica_count) : 0
8387

8488
identifier = length(var.instances_parameters) > count.index ? lookup(var.instances_parameters[count.index], "instance_name", "${var.name}-${count.index + 1}") : "${var.name}-${count.index + 1}"
85-
cluster_identifier = aws_rds_cluster.this.id
89+
cluster_identifier = element(concat(aws_rds_cluster.this.*.id, [""]), 0)
8690
engine = var.engine
8791
engine_version = var.engine_version
8892
instance_class = length(var.instances_parameters) > count.index ? lookup(var.instances_parameters[count.index], "instance_type", var.instance_type) : count.index > 0 ? coalesce(var.instance_type_replica, var.instance_type) : var.instance_type
@@ -111,6 +115,8 @@ resource "aws_rds_cluster_instance" "this" {
111115
}
112116

113117
resource "random_id" "snapshot_identifier" {
118+
count = var.create_cluster ? 1 : 0
119+
114120
keepers = {
115121
id = var.name
116122
}
@@ -130,7 +136,7 @@ data "aws_iam_policy_document" "monitoring_rds_assume_role" {
130136
}
131137

132138
resource "aws_iam_role" "rds_enhanced_monitoring" {
133-
count = var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0
139+
count = var.create_cluster && var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0
134140

135141
name = "rds-enhanced-monitoring-${var.name}"
136142
assume_role_policy = data.aws_iam_policy_document.monitoring_rds_assume_role.json
@@ -143,28 +149,28 @@ resource "aws_iam_role" "rds_enhanced_monitoring" {
143149
}
144150

145151
resource "aws_iam_role_policy_attachment" "rds_enhanced_monitoring" {
146-
count = var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0
152+
count = var.create_cluster && var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0
147153

148154
role = local.rds_enhanced_monitoring_name
149155
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
150156
}
151157

152158
resource "aws_appautoscaling_target" "read_replica_count" {
153-
count = var.replica_scale_enabled ? 1 : 0
159+
count = var.create_cluster && var.replica_scale_enabled ? 1 : 0
154160

155161
max_capacity = var.replica_scale_max
156162
min_capacity = var.replica_scale_min
157-
resource_id = "cluster:${aws_rds_cluster.this.cluster_identifier}"
163+
resource_id = "cluster:${element(concat(aws_rds_cluster.this.*.cluster_identifier, [""]), 0)}"
158164
scalable_dimension = "rds:cluster:ReadReplicaCount"
159165
service_namespace = "rds"
160166
}
161167

162168
resource "aws_appautoscaling_policy" "autoscaling_read_replica_count" {
163-
count = var.replica_scale_enabled ? 1 : 0
169+
count = var.create_cluster && var.replica_scale_enabled ? 1 : 0
164170

165171
name = "target-metric"
166172
policy_type = "TargetTrackingScaling"
167-
resource_id = "cluster:${aws_rds_cluster.this.cluster_identifier}"
173+
resource_id = "cluster:${element(concat(aws_rds_cluster.this.*.cluster_identifier, [""]), 0)}"
168174
scalable_dimension = "rds:cluster:ReadReplicaCount"
169175
service_namespace = "rds"
170176

@@ -182,7 +188,7 @@ resource "aws_appautoscaling_policy" "autoscaling_read_replica_count" {
182188
}
183189

184190
resource "aws_security_group" "this" {
185-
count = var.create_security_group ? 1 : 0
191+
count = var.create_cluster && var.create_security_group ? 1 : 0
186192

187193
name_prefix = "${var.name}-"
188194
vpc_id = var.vpc_id
@@ -195,26 +201,26 @@ resource "aws_security_group" "this" {
195201
}
196202

197203
resource "aws_security_group_rule" "default_ingress" {
198-
count = var.create_security_group ? length(var.allowed_security_groups) : 0
204+
count = var.create_cluster && var.create_security_group ? length(var.allowed_security_groups) : 0
199205

200206
description = "From allowed SGs"
201207

202208
type = "ingress"
203-
from_port = aws_rds_cluster.this.port
204-
to_port = aws_rds_cluster.this.port
209+
from_port = element(concat(aws_rds_cluster.this.*.port, [""]), 0)
210+
to_port = element(concat(aws_rds_cluster.this.*.port, [""]), 0)
205211
protocol = "tcp"
206212
source_security_group_id = element(var.allowed_security_groups, count.index)
207213
security_group_id = local.rds_security_group_id
208214
}
209215

210216
resource "aws_security_group_rule" "cidr_ingress" {
211-
count = var.create_security_group && length(var.allowed_cidr_blocks) > 0 ? 1 : 0
217+
count = var.create_cluster && var.create_security_group && length(var.allowed_cidr_blocks) > 0 ? 1 : 0
212218

213219
description = "From allowed CIDRs"
214220

215221
type = "ingress"
216-
from_port = aws_rds_cluster.this.port
217-
to_port = aws_rds_cluster.this.port
222+
from_port = element(concat(aws_rds_cluster.this.*.port, [""]), 0)
223+
to_port = element(concat(aws_rds_cluster.this.*.port, [""]), 0)
218224
protocol = "tcp"
219225
cidr_blocks = var.allowed_cidr_blocks
220226
security_group_id = local.rds_security_group_id

outputs.tf

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,32 @@
11
# aws_rds_cluster
22
output "this_rds_cluster_arn" {
33
description = "The ID of the cluster"
4-
value = aws_rds_cluster.this.arn
4+
value = element(concat(aws_rds_cluster.this.*.arn, [""]), 0)
55
}
66

77
output "this_rds_cluster_id" {
88
description = "The ID of the cluster"
9-
value = aws_rds_cluster.this.id
9+
value = element(concat(aws_rds_cluster.this.*.id, [""]), 0)
1010
}
1111

1212
output "this_rds_cluster_resource_id" {
1313
description = "The Resource ID of the cluster"
14-
value = aws_rds_cluster.this.cluster_resource_id
14+
value = element(concat(aws_rds_cluster.this.*.cluster_resource_id, [""]), 0)
1515
}
1616

1717
output "this_rds_cluster_endpoint" {
1818
description = "The cluster endpoint"
19-
value = aws_rds_cluster.this.endpoint
19+
value = element(concat(aws_rds_cluster.this.*.endpoint, [""]), 0)
2020
}
2121

2222
output "this_rds_cluster_engine_version" {
2323
description = "The cluster engine version"
24-
value = aws_rds_cluster.this.engine_version
24+
value = element(concat(aws_rds_cluster.this.*.engine_version, [""]), 0)
2525
}
2626

2727
output "this_rds_cluster_reader_endpoint" {
2828
description = "The cluster reader endpoint"
29-
value = aws_rds_cluster.this.reader_endpoint
29+
value = element(concat(aws_rds_cluster.this.*.reader_endpoint, [""]), 0)
3030
}
3131

3232
# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output
@@ -37,23 +37,24 @@ output "this_rds_cluster_database_name" {
3737

3838
output "this_rds_cluster_master_password" {
3939
description = "The master password"
40-
value = aws_rds_cluster.this.master_password
40+
value = element(concat(aws_rds_cluster.this.*.master_password, [""]), 0)
4141
sensitive = true
4242
}
4343

4444
output "this_rds_cluster_port" {
4545
description = "The port"
46-
value = aws_rds_cluster.this.port
46+
value = element(concat(aws_rds_cluster.this.*.port, [""]), 0)
4747
}
4848

4949
output "this_rds_cluster_master_username" {
5050
description = "The master username"
51-
value = aws_rds_cluster.this.master_username
51+
value = element(concat(aws_rds_cluster.this.*.master_username, [""]), 0)
5252
}
5353

5454
output "this_rds_cluster_hosted_zone_id" {
5555
description = "Route53 hosted zone id of the created cluster"
56-
value = aws_rds_cluster.this.hosted_zone_id
56+
value = element(concat(aws_rds_cluster.this.*.hosted_zone_id, [""]), 0)
57+
5758
}
5859

5960
# aws_rds_cluster_instance

variables.tf

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
variable "create_cluster" {
2+
description = "Controls if RDS cluster should be created (it affects almost all resources)"
3+
type = bool
4+
default = true
5+
}
6+
17
variable "create_security_group" {
28
description = "Whether to create security group for RDS cluster"
39
type = bool
@@ -7,6 +13,7 @@ variable "create_security_group" {
713
variable "name" {
814
description = "Name given resources"
915
type = string
16+
default = ""
1017
}
1118

1219
variable "subnets" {
@@ -36,6 +43,7 @@ variable "allowed_cidr_blocks" {
3643
variable "vpc_id" {
3744
description = "VPC ID"
3845
type = string
46+
default = ""
3947
}
4048

4149
variable "instance_type_replica" {
@@ -47,6 +55,7 @@ variable "instance_type_replica" {
4755
variable "instance_type" {
4856
description = "Instance type to use at master instance. If instance_type_replica is not set it will use the same type for replica instances"
4957
type = string
58+
default = ""
5059
}
5160

5261
variable "publicly_accessible" {

0 commit comments

Comments
 (0)