From 7ccab8224ac18a0678c769d92b7682a05f21c465 Mon Sep 17 00:00:00 2001 From: Sunny-Mor Date: Thu, 2 Oct 2025 04:18:05 +0530 Subject: [PATCH 1/3] fix: add locals, variables and fix deprecated arguments --- examples/PostgreSQL/main.tf | 44 ++++++----- examples/complete-mysql/main.tf | 40 ++++++---- main.tf | 129 +++++++++++++++----------------- variables.tf | 50 +++++++++++-- 4 files changed, 158 insertions(+), 105 deletions(-) diff --git a/examples/PostgreSQL/main.tf b/examples/PostgreSQL/main.tf index 7c6e0ef..a172c2b 100644 --- a/examples/PostgreSQL/main.tf +++ b/examples/PostgreSQL/main.tf @@ -1,8 +1,15 @@ +locals { + name = "pgsql-new" + environment = "test" + region = "us-east-1" + label_order = ["name", "environment"] +} + ####---------------------------------------------------------------------------------- ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. ####---------------------------------------------------------------------------------- provider "aws" { - region = "ap-south-1" + region = local.region } ####---------------------------------------------------------------------------------- @@ -12,9 +19,9 @@ module "vpc" { source = "clouddrove/vpc/aws" version = "2.0.0" - name = "vpc" - environment = "test" - label_order = ["environment", "name"] + name = "${local.name}-vpc" + environment = local.environment + label_order = local.label_order cidr_block = "10.0.0.0/16" } @@ -23,16 +30,16 @@ module "vpc" { ## A subnet is a range of IP addresses in your VPC. ####---------------------------------------------------------------------------------- module "private_subnets" { - source = "clouddrove/subnet/aws" + source ="clouddrove/subnet/aws" version = "2.0.1" - name = "subnets" - environment = "test" - label_order = ["name", "environment"] + name = "${local.name}-subnets" + environment = local.environment + label_order = local.label_order nat_gateway_enabled = true - availability_zones = ["ap-south-1a", "ap-south-1b"] + availability_zones = ["${local.region}a", "${local.region}b"] vpc_id = module.vpc.vpc_id type = "public-private" igw_id = module.vpc.igw_id @@ -46,17 +53,17 @@ module "private_subnets" { module "postgresql" { source = "../../" - name = "postgresql" - environment = "test" - label_order = ["environment", "name"] + name = local.name + environment = local.environment + label_order = local.label_order engine = "postgres" - engine_version = "14.6" + engine_version = "17.6" instance_class = "db.t3.medium" allocated_storage = 50 engine_name = "postgres" storage_encrypted = true - family = "postgres14" + family = "postgres17" # DB Details db_name = "test" username = "dbname" @@ -75,19 +82,22 @@ module "postgresql" { allowed_ports = [5432] # disable backups to create DB faster - backup_retention_period = 0 + backup_retention_period = 7 enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"] + # disable creation of Read Replica + enabled_read_replica = false + # DB subnet group subnet_ids = module.private_subnets.public_subnet_id publicly_accessible = true # DB option group - major_engine_version = "14" + major_engine_version = "17" # Database Deletion Protection - deletion_protection = true + deletion_protection = false ###ssm parameter ssm_parameter_endpoint_enabled = true diff --git a/examples/complete-mysql/main.tf b/examples/complete-mysql/main.tf index 0a3eb49..6e4feef 100644 --- a/examples/complete-mysql/main.tf +++ b/examples/complete-mysql/main.tf @@ -1,8 +1,15 @@ +locals { + name = "mysql" + environment = "test" + region = "us-east-1" + label_order = ["name", "environment"] +} + ####---------------------------------------------------------------------------------- ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. ####---------------------------------------------------------------------------------- provider "aws" { - region = "ap-south-1" + region = local.region } ####---------------------------------------------------------------------------------- @@ -12,9 +19,9 @@ module "vpc" { source = "clouddrove/vpc/aws" version = "2.0.0" - name = "vpc" - environment = "test" - label_order = ["environment", "name"] + name = "${local.name}-vpc" + environment = local.environment + label_order = local.label_order cidr_block = "10.0.0.0/16" } @@ -22,14 +29,14 @@ module "vpc" { ## A subnet is a range of IP addresses in your VPC. ####---------------------------------------------------------------------------------- module "subnets" { - source = "clouddrove/subnet/aws" + source = "clouddrove/subnet/aws" version = "2.0.1" - name = "subnets" - environment = "test" - label_order = ["environment", "name"] + name = "${local.name}-subnets" + environment = local.environment + label_order = local.label_order - availability_zones = ["ap-south-1a", "ap-south-1b"] + availability_zones = ["${local.region}a", "${local.region}b"] vpc_id = module.vpc.vpc_id type = "public" igw_id = module.vpc.igw_id @@ -43,13 +50,13 @@ module "subnets" { module "mysql" { source = "../../" - name = "mysql" - environment = "test" - label_order = ["environment", "name"] + name = local.name + environment = local.environment + label_order = local.label_order engine = "mysql" - engine_version = "8.0.28" - instance_class = "db.t2.small" + engine_version = "8.0.43" + instance_class = "db.t3.small" allocated_storage = 5 ####---------------------------------------------------------------------------------- @@ -74,6 +81,9 @@ module "mysql" { enabled_cloudwatch_logs_exports = ["audit", "general"] + # disable creation of Read Replica + enabled_read_replica = true + # DB subnet group subnet_ids = module.subnets.public_subnet_id publicly_accessible = true @@ -85,7 +95,7 @@ module "mysql" { major_engine_version = "8.0" # Database Deletion Protection - deletion_protection = true + deletion_protection = false parameters = [ { diff --git a/main.tf b/main.tf index b0138e2..de4224f 100644 --- a/main.tf +++ b/main.tf @@ -1,11 +1,30 @@ +####---------------------------------------------------------------------------------- +## Locals +####---------------------------------------------------------------------------------- +locals { + identifier_prefix = var.use_identifier_prefix ? "${var.identifier}-" : null + db_subnet_group_name = var.enabled_db_subnet_group ? join("", aws_db_subnet_group.this[*].id) : var.db_subnet_group_name + db_parameter_group_name = var.enabled_parameter_group ? join("", aws_db_parameter_group.this[*].id) : var.parameter_group_name + db_option_group_name = var.enabled_option_group ? join("", aws_db_option_group.this[*].id) : var.option_group_name + + # Replicas will use source metadata + username = var.replicate_source_db != null ? null : var.username + password = var.password == "" ? join("", random_id.password[*].b64_url) : var.password + engine = var.replicate_source_db != null ? null : var.engine + engine_version = var.replicate_source_db != null ? null : var.engine_version + // name_prefix = var.use_name_prefix ? "${var.name}-" : null + description = coalesce(var.option_group_description, format("%s option group", var.name)) +} + ####---------------------------------------------------------------------------------- ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. ####---------------------------------------------------------------------------------- module "labels" { - source = "clouddrove/labels/aws" - version = "1.3.0" + source = "clouddrove/labels/aws" + version = "1.3.0" name = var.name + repository = var.repository environment = var.environment managedby = var.managedby label_order = var.label_order @@ -15,41 +34,17 @@ module "labels" { ## The resource random_id generates random numbers that are intended to be used as unique identifiers for other resources. ####---------------------------------------------------------------------------------- resource "random_id" "password" { - count = var.enabled ? 1 : 0 + count = var.enabled && var.enabled_custom_password == false ? 1 : 0 byte_length = 20 } -locals { - - identifier_prefix = var.use_identifier_prefix ? "${var.identifier}-" : null - db_subnet_group_name = var.enabled_db_subnet_group ? join("", aws_db_subnet_group.this[*].id) : var.db_subnet_group_name - - # Replicas will use source metadata - username = var.replicate_source_db != null ? null : var.username - password = var.password == "" ? join("", random_id.password[*].b64_url) : var.password - engine = var.replicate_source_db != null ? null : var.engine - engine_version = var.replicate_source_db != null ? null : var.engine_version - // name_prefix = var.use_name_prefix ? "${var.name}-" : null - description = coalesce(var.option_group_description, format("%s option group", var.name)) -} - -resource "random_id" "snapshot_identifier" { - count = var.enabled && !var.skip_final_snapshot ? 1 : 0 - - keepers = { - id = var.identifier - } - - byte_length = 4 -} - ####---------------------------------------------------------------------------------- ### a collection of subnets (typically private) that you create for a VPC and that you then designate for your DB instances. ####---------------------------------------------------------------------------------- resource "aws_db_subnet_group" "this" { count = var.enabled && var.enabled_db_subnet_group ? 1 : 0 name = module.labels.id - description = local.description + description = format("Subnet Group for %s", module.labels.id) subnet_ids = var.subnet_ids tags = merge( module.labels.tags, @@ -61,10 +56,10 @@ resource "aws_db_subnet_group" "this" { ### Provides an RDS DB parameter group resource. ####---------------------------------------------------------------------------------- resource "aws_db_parameter_group" "this" { - count = var.enabled ? 1 : 0 + count = var.enabled && var.enabled_parameter_group ? 1 : 0 name = module.labels.id - description = local.description + description = format("Parameter Group for %s", module.labels.id) family = var.family dynamic "parameter" { for_each = var.parameters @@ -90,10 +85,10 @@ resource "aws_db_parameter_group" "this" { ### Provides an RDS DB option group resource. ####---------------------------------------------------------------------------------- resource "aws_db_option_group" "this" { - count = var.enabled ? 1 : 0 + count = var.enabled && var.enabled_option_group ? 1:0 name = module.labels.id - option_group_description = local.description + option_group_description = format("Option group for %s", module.labels.id) engine_name = var.engine_name major_engine_version = var.major_engine_version dynamic "option" { @@ -148,33 +143,15 @@ resource "aws_cloudwatch_log_group" "this" { ) } -##----------------------------------------------------------------------------------- -### Generates an IAM policy document in JSON format for use with resources that expect policy documents such as aws_iam_policy. -##----------------------------------------------------------------------------------- - -data "aws_iam_policy_document" "enhanced_monitoring" { - statement { - actions = [ - "sts:AssumeRole", - ] - - principals { - type = "Service" - identifiers = ["monitoring.rds.amazonaws.com"] - } - } -} - ####---------------------------------------------------------------------------------- -### IAM - Manage Roles ### AWS Identity and Access Management (IAM) roles are entities you create and assign specific permissions to that allow trusted identities such as workforce identities and applications to perform actions in AWS ####---------------------------------------------------------------------------------- resource "aws_iam_role" "enhanced_monitoring" { - count = var.enabled_monitoring_role ? 1 : 0 + count = var.enabled && var.enabled_monitoring_role ? 1 : 0 name = module.labels.id - assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring.json - description = var.monitoring_role_description + assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring[count.index].json + description = format("RDS Monitoring role for %s", module.labels.id) permissions_boundary = var.monitoring_role_permissions_boundary tags = merge( @@ -187,21 +164,39 @@ resource "aws_iam_role" "enhanced_monitoring" { } resource "aws_iam_role_policy_attachment" "enhanced_monitoring" { - count = var.enabled_monitoring_role ? 1 : 0 + count = var.enabled && var.enabled_monitoring_role ? 1 : 0 role = aws_iam_role.enhanced_monitoring[0].name policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" } +##----------------------------------------------------------------------------------- +### Generates an IAM policy document in JSON format for use with resources that expect policy documents such as aws_iam_policy. +##----------------------------------------------------------------------------------- + +data "aws_iam_policy_document" "enhanced_monitoring" { + count = var.enabled && var.enabled_monitoring_role ? 1 : 0 + statement { + actions = [ + "sts:AssumeRole", + ] + + principals { + type = "Service" + identifiers = ["monitoring.rds.amazonaws.com"] + } + } +} + ##---------------------------------------------------------------------------------- ## Below resources will create SECURITY-GROUP and its components. ##---------------------------------------------------------------------------------- resource "aws_security_group" "default" { - count = var.enable_security_group && length(var.sg_ids) < 1 ? 1 : 0 + count = var.enabled && var.enable_security_group && length(var.sg_ids) < 1 ? 1 : 0 name = format("%s-sg", module.labels.id) vpc_id = var.vpc_id - description = var.sg_description + description = format("Security Group for %s", module.labels.id) tags = module.labels.tags lifecycle { create_before_destroy = true @@ -213,7 +208,7 @@ resource "aws_security_group" "default" { ##---------------------------------------------------------------------------------- #tfsec:ignore:aws-ec2-no-public-egress-sgr resource "aws_security_group_rule" "egress" { - count = (var.enable_security_group == true && length(var.sg_ids) < 1 && var.is_external == false && var.egress_rule == true) ? 1 : 0 + count = var.enabled && (var.enable_security_group == true && length(var.sg_ids) < 1 && var.is_external == false && var.egress_rule == true) ? 1 : 0 description = var.sg_egress_description type = "egress" @@ -225,7 +220,7 @@ resource "aws_security_group_rule" "egress" { } #tfsec:ignore:aws-ec2-no-public-egress-sgr resource "aws_security_group_rule" "egress_ipv6" { - count = (var.enable_security_group == true && length(var.sg_ids) < 1 && var.is_external == false) && var.egress_rule == true ? 1 : 0 + count = var.enabled && (var.enable_security_group == true && length(var.sg_ids) < 1 && var.is_external == false) && var.egress_rule == true ? 1 : 0 description = var.sg_egress_ipv6_description type = "egress" @@ -237,7 +232,7 @@ resource "aws_security_group_rule" "egress_ipv6" { } resource "aws_security_group_rule" "ingress" { - count = length(var.allowed_ip) > 0 == true && length(var.sg_ids) < 1 ? length(compact(var.allowed_ports)) : 0 + count = var.enabled && length(var.allowed_ip) > 0 == true && length(var.sg_ids) < 1 ? length(compact(var.allowed_ports)) : 0 description = var.sg_ingress_description type = "ingress" @@ -252,9 +247,9 @@ resource "aws_security_group_rule" "ingress" { ## Below resources will create KMS-KEY and its components. ##---------------------------------------------------------------------------------- resource "aws_kms_key" "default" { - count = var.kms_key_enabled && var.kms_key_id == "" ? 1 : 0 + count = var.enabled && var.kms_key_enabled && var.kms_key_id == "" ? 1 : 0 - description = var.kms_description + description = format("KMS Key for %s", module.labels.id) key_usage = var.key_usage deletion_window_in_days = var.deletion_window_in_days is_enabled = var.is_enabled @@ -266,7 +261,7 @@ resource "aws_kms_key" "default" { } resource "aws_kms_alias" "default" { - count = var.kms_key_enabled && var.kms_key_id == "" ? 1 : 0 + count = var.enabled && var.kms_key_enabled && var.kms_key_id == "" ? 1 : 0 name = coalesce(var.alias, format("alias/%v", module.labels.id)) target_key_id = var.kms_key_id == "" ? join("", aws_kms_key.default[*].id) : var.kms_key_id @@ -302,7 +297,7 @@ data "aws_iam_policy_document" "default" { ####---------------------------------------------------------------------------------- #tfsec:ignore:aws-rds-enable-performance-insights resource "aws_db_instance" "this" { - count = var.enabled && var.enabled_read_replica ? 1 : 0 + count = var.enabled ? 1 : 0 identifier = module.labels.id identifier_prefix = local.identifier_prefix @@ -391,7 +386,7 @@ resource "aws_db_instance" "this" { for_each = var.s3_import != null ? [var.s3_import] : [] content { - source_engine = "mysql" + source_engine = local.engine source_engine_version = s3_import.value.source_engine_version bucket_name = s3_import.value.bucket_name bucket_prefix = lookup(s3_import.value, "bucket_prefix", null) @@ -419,14 +414,14 @@ resource "aws_db_instance" "this" { ####---------------------------------------------------------------------------------- #tfsec:ignore:aws-rds-enable-performance-insights resource "aws_db_instance" "read" { - count = var.enabled && var.enabled_read_replica && var.enabled_replica ? 1 : 0 + count = var.enabled && var.enabled_read_replica ? 1 : 0 identifier = format("%s-replica", module.labels.id) identifier_prefix = local.identifier_prefix engine = null engine_version = null - instance_class = var.replica_instance_class + instance_class = var.instance_class allocated_storage = var.allocated_storage storage_type = var.storage_type storage_encrypted = var.storage_encrypted @@ -509,7 +504,7 @@ resource "aws_db_instance" "read" { for_each = var.s3_import != null ? [var.s3_import] : [] content { - source_engine = "mysql" + source_engine = local.engine source_engine_version = s3_import.value.source_engine_version bucket_name = s3_import.value.bucket_name bucket_prefix = lookup(s3_import.value, "bucket_prefix", null) diff --git a/variables.tf b/variables.tf index 570f217..fae7e0d 100644 --- a/variables.tf +++ b/variables.tf @@ -6,6 +6,18 @@ variable "name" { description = "Name (e.g. `app` or `cluster`)." } +variable "repository" { + type = string + default = "https://github.com/clouddrove/terraform-aws-ec2" + description = "Terraform current module repo" + + validation { + # regex(...) fails if it cannot find a match + condition = can(regex("^https://", var.repository)) + error_message = "The module-repo value must be a valid Git repo link." + } +} + variable "environment" { type = string default = "" @@ -42,6 +54,13 @@ variable "identifier" { description = "The name of the RDS instance" } +variable "enabled_custom_password" { + description = "Whether to use a custom password (true) or generate a random one (false)." + type = bool + default = false +} + + variable "custom_iam_instance_profile" { type = string default = null @@ -377,6 +396,12 @@ variable "cloudwatch_log_group_retention_in_days" { description = "The number of days to retain CloudWatch logs for the DB instance" } +variable "enabled_option_group" { + description = "Determines whether a cluster option group should be created or use existing" + type = bool + default = true +} + variable "option_group_description" { type = string default = null @@ -401,6 +426,13 @@ variable "options" { description = "A list of Options to apply" } +variable "option_group_name" { + description = "Existing DB option group name to use (if not creating a new one)." + type = string + default = null +} + + variable "timeouts" { type = map(string) default = {} @@ -419,6 +451,18 @@ variable "parameters" { default = [] } +variable "parameter_group_name" { + description = "Existing DB parameter group name to use (if not creating a new one)." + type = string + default = null +} + +variable "enabled_parameter_group" { + description = "Determines whether a cluster parameter should be created or use existing" + type = bool + default = true +} + variable "subnet_ids" { type = list(string) default = [] @@ -443,12 +487,6 @@ variable "enabled_read_replica" { description = "A list of enabled read replica" } -variable "enabled_replica" { - type = bool - default = false - description = "A list of enabled replica" -} - variable "db_subnet_group_tags" { type = map(any) default = {} From 550d85361278925aec15f2ce88f9c570f37fed14 Mon Sep 17 00:00:00 2001 From: Sunny-Mor Date: Wed, 8 Oct 2025 15:23:46 +0530 Subject: [PATCH 2/3] terraform format updated --- examples/PostgreSQL/main.tf | 12 ++++++------ examples/complete-mysql/main.tf | 12 ++++++------ main.tf | 6 +++--- variables.tf | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/examples/PostgreSQL/main.tf b/examples/PostgreSQL/main.tf index a172c2b..1989d64 100644 --- a/examples/PostgreSQL/main.tf +++ b/examples/PostgreSQL/main.tf @@ -1,9 +1,9 @@ locals { - name = "pgsql-new" - environment = "test" - region = "us-east-1" - label_order = ["name", "environment"] -} + name = "pgsql-new" + environment = "test" + region = "us-east-1" + label_order = ["name", "environment"] +} ####---------------------------------------------------------------------------------- ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. @@ -30,7 +30,7 @@ module "vpc" { ## A subnet is a range of IP addresses in your VPC. ####---------------------------------------------------------------------------------- module "private_subnets" { - source ="clouddrove/subnet/aws" + source = "clouddrove/subnet/aws" version = "2.0.1" name = "${local.name}-subnets" diff --git a/examples/complete-mysql/main.tf b/examples/complete-mysql/main.tf index 6e4feef..e07ae60 100644 --- a/examples/complete-mysql/main.tf +++ b/examples/complete-mysql/main.tf @@ -1,9 +1,9 @@ locals { - name = "mysql" - environment = "test" - region = "us-east-1" - label_order = ["name", "environment"] -} + name = "mysql" + environment = "test" + region = "us-east-1" + label_order = ["name", "environment"] +} ####---------------------------------------------------------------------------------- ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. @@ -29,7 +29,7 @@ module "vpc" { ## A subnet is a range of IP addresses in your VPC. ####---------------------------------------------------------------------------------- module "subnets" { - source = "clouddrove/subnet/aws" + source = "clouddrove/subnet/aws" version = "2.0.1" name = "${local.name}-subnets" diff --git a/main.tf b/main.tf index de4224f..f5124e0 100644 --- a/main.tf +++ b/main.tf @@ -20,8 +20,8 @@ locals { ## Provider block added, Use the Amazon Web Services (AWS) provider to interact with the many resources supported by AWS. ####---------------------------------------------------------------------------------- module "labels" { - source = "clouddrove/labels/aws" - version = "1.3.0" + source = "clouddrove/labels/aws" + version = "1.3.0" name = var.name repository = var.repository @@ -85,7 +85,7 @@ resource "aws_db_parameter_group" "this" { ### Provides an RDS DB option group resource. ####---------------------------------------------------------------------------------- resource "aws_db_option_group" "this" { - count = var.enabled && var.enabled_option_group ? 1:0 + count = var.enabled && var.enabled_option_group ? 1 : 0 name = module.labels.id option_group_description = format("Option group for %s", module.labels.id) diff --git a/variables.tf b/variables.tf index fae7e0d..cce1808 100644 --- a/variables.tf +++ b/variables.tf @@ -460,7 +460,7 @@ variable "parameter_group_name" { variable "enabled_parameter_group" { description = "Determines whether a cluster parameter should be created or use existing" type = bool - default = true + default = true } variable "subnet_ids" { From b79a59d9ffb23d24041b521ad54e0a64a4eb124d Mon Sep 17 00:00:00 2001 From: Sunny-Mor Date: Wed, 8 Oct 2025 15:27:11 +0530 Subject: [PATCH 3/3] fix replica-mysql example --- examples/replica-mysql/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/replica-mysql/main.tf b/examples/replica-mysql/main.tf index 2e89b7c..dfae804 100644 --- a/examples/replica-mysql/main.tf +++ b/examples/replica-mysql/main.tf @@ -45,7 +45,6 @@ module "mysql" { snapshot_identifier = "" kms_key_id = "" enabled_read_replica = true - enabled_replica = true # DB Details db_name = "replica"