From 71d55e04c01649048fa9e3590042d338a5d01dcb Mon Sep 17 00:00:00 2001 From: Rudransh Shrivastava Date: Tue, 13 Jan 2026 12:42:41 +0530 Subject: [PATCH 1/4] Add tests for cache module --- Makefile | 1 + infrastructure/Makefile | 10 ++ .../modules/cache/.terraform.lock.hcl | 45 ++++++ .../modules/cache/tests/cache.tftest.hcl | 128 ++++++++++++++++++ 4 files changed, 184 insertions(+) create mode 100644 infrastructure/Makefile create mode 100644 infrastructure/modules/cache/.terraform.lock.hcl create mode 100644 infrastructure/modules/cache/tests/cache.tftest.hcl diff --git a/Makefile b/Makefile index 2d29a5c668..1f19aa0a53 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ include backend/Makefile include cspell/Makefile include docs/Makefile include frontend/Makefile +include infrastructure/Makefile MAKEFLAGS += --no-print-directory diff --git a/infrastructure/Makefile b/infrastructure/Makefile new file mode 100644 index 0000000000..611ce4b64b --- /dev/null +++ b/infrastructure/Makefile @@ -0,0 +1,10 @@ +MODULES_DIR := infrastructure/modules + +test-infrastructure: + @for dir in $(MODULES_DIR)/*/; do \ + if [ -d "$$dir/tests" ]; then \ + echo "Testing $$dir..."; \ + terraform -chdir="$$dir" init -backend=false -input=false && \ + terraform -chdir="$$dir" test || exit 1; \ + fi \ + done diff --git a/infrastructure/modules/cache/.terraform.lock.hcl b/infrastructure/modules/cache/.terraform.lock.hcl new file mode 100644 index 0000000000..22df00b9db --- /dev/null +++ b/infrastructure/modules/cache/.terraform.lock.hcl @@ -0,0 +1,45 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "6.22.0" + constraints = "6.22.0" + hashes = [ + "h1:TV1UZ7DzioV1EUY/lMS+eIInU379DA1Q2QwnEGGZMks=", + "zh:0ed7ceb13bade9076021a14f995d07346d3063f4a419a904d5804d76e372bbda", + "zh:195dcde5a4b0def82bc3379053edc13941ff94ea5905808fe575f7c7bbd66693", + "zh:4047c4dba121d29859b72d2155c47f969b41d3c5768f73dff5d8a0cc55f74e52", + "zh:5694f37d6ea69b6f96dfb30d53e66f7a41c1aad214c212b6ffa54bdd799e3b27", + "zh:6cf8bb7d984b1fae9fd10d6ce1e62f6c10751a1040734b75a1f7286609782e49", + "zh:737d0e600dfe2626b4d6fc5dd2b24c0997fd983228a7a607b9176a1894a281a0", + "zh:7d328a195ce36b1170afe6758cf88223c8765620211f5cc0451bdd6899243b4e", + "zh:7edb4bc34baeba92889bd9ed50b34c04b3eeb3d8faa8bb72699c6335a2e95bab", + "zh:8e71836814e95454b00c51f3cb3e10fd78a59f7dc4c5362af64233fee989790d", + "zh:9367f63b23d9ddfab590b2247a8ff5ccf83410cbeca43c6e441c488c45efff4c", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a007de80ffde8539a73ee39fcfbe7ed12e025c98cd29b2110a7383b41a4aad39", + "zh:aae7b7aed8bf3a4bea80a9a2f08fef1adeb748beff236c4a54af93bb6c09a56c", + "zh:b5a16b59d4210c1eaf35c8c027ecdab9e074dd081d602f5112eecdebf2e1866d", + "zh:d479bad0a004e4893bf0ba6c6cd867fefd14000051bbe3de5b44a925e3d46cd5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.7.2" + constraints = "3.7.2" + hashes = [ + "h1:356j/3XnXEKr9nyicLUufzoF4Yr6hRy481KIxRVpK0c=", + "zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f", + "zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc", + "zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab", + "zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3", + "zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212", + "zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34", + "zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967", + "zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d", + "zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62", + "zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0", + ] +} diff --git a/infrastructure/modules/cache/tests/cache.tftest.hcl b/infrastructure/modules/cache/tests/cache.tftest.hcl new file mode 100644 index 0000000000..17d526c78e --- /dev/null +++ b/infrastructure/modules/cache/tests/cache.tftest.hcl @@ -0,0 +1,128 @@ +variables { + common_tags = { Environment = "test", Project = "nest" } + environment = "test" + project_name = "nest" + redis_engine_version = "7.0" + redis_node_type = "cache.t3.micro" + redis_num_cache_nodes = 1 + redis_port = 6379 + security_group_ids = ["sg-12345678"] + subnet_ids = ["subnet-12345678"] +} + +run "test_auth_token_generated" { + command = plan + + assert { + condition = length(random_password.redis_auth_token) == 1 + error_message = "Redis auth token must be generated." + } +} + +run "test_auth_token_length" { + command = plan + + assert { + condition = random_password.redis_auth_token[0].length == 32 + error_message = "Redis auth token must be 32 characters." + } +} + +run "test_encryption_enabled_at_rest" { + command = plan + + assert { + condition = aws_elasticache_replication_group.main.at_rest_encryption_enabled + error_message = "At-rest encryption must be enabled." + } +} + +run "test_encryption_enabled_in_transit" { + command = plan + + assert { + condition = aws_elasticache_replication_group.main.transit_encryption_enabled == true + error_message = "Transit encryption must be enabled." + } +} + +run "test_engine_is_redis" { + command = plan + + assert { + condition = aws_elasticache_replication_group.main.engine == "redis" + error_message = "Engine must be Redis." + } +} + +run "test_failover_disabled_for_single_node" { + command = plan + + assert { + condition = aws_elasticache_replication_group.main.automatic_failover_enabled == false + error_message = "Automatic failover must be disabled for single-node clusters." + } +} + +run "test_failover_enabled_for_multi_node" { + command = plan + + variables { + redis_num_cache_nodes = 2 + } + + assert { + condition = aws_elasticache_replication_group.main.automatic_failover_enabled == true + error_message = "Automatic failover must be enabled for multi-node clusters." + } +} + +run "test_log_groups_created" { + command = plan + + assert { + condition = aws_cloudwatch_log_group.engine_log.retention_in_days == var.log_retention_in_days + error_message = "Engine log group must be created with correct retention." + } + + assert { + condition = aws_cloudwatch_log_group.slow_log.retention_in_days == var.log_retention_in_days + error_message = "Slow log group must be created with correct retention." + } +} + +run "test_replication_group_id_format" { + command = plan + + assert { + condition = aws_elasticache_replication_group.main.replication_group_id == "${var.project_name}-${var.environment}-cache" + error_message = "Replication group ID must follow naming convention: {project}-{environment}-cache." + } +} + +run "test_ssm_parameter_is_secure_string" { + command = plan + + assert { + condition = aws_ssm_parameter.django_redis_password.type == "SecureString" + error_message = "Redis password must be stored as SecureString." + } +} + +run "test_ssm_parameter_path_format" { + command = plan + + assert { + condition = aws_ssm_parameter.django_redis_password.name == "/${var.project_name}/${var.environment}/DJANGO_REDIS_PASSWORD" + error_message = "SSM parameter must follow path: /{project}/{environment}/DJANGO_REDIS_PASSWORD." + } +} + +run "test_subnet_group_uses_provided_subnets" { + command = plan + + assert { + condition = tolist(aws_elasticache_subnet_group.main.subnet_ids) == var.subnet_ids + error_message = "Subnet group must use the provided subnet IDs." + } +} From 773ed3a4adb76a79ad5fdd76d625b971333485e7 Mon Sep 17 00:00:00 2001 From: Rudransh Shrivastava Date: Tue, 13 Jan 2026 13:11:46 +0530 Subject: [PATCH 2/4] Add validations for cache module --- infrastructure/modules/cache/variables.tf | 30 +++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/infrastructure/modules/cache/variables.tf b/infrastructure/modules/cache/variables.tf index fe13005897..4dc7af06e2 100644 --- a/infrastructure/modules/cache/variables.tf +++ b/infrastructure/modules/cache/variables.tf @@ -40,27 +40,52 @@ variable "redis_engine_version" { variable "redis_node_type" { description = "The node type for the Redis cache." type = string + + validation { + condition = can(regex("^cache\\.", var.redis_node_type)) + error_message = "redis_node_type must start with 'cache.' (e.g., cache.t3.micro, cache.r5.large)." + } } variable "redis_num_cache_nodes" { description = "The number of cache nodes in the Redis cluster." type = number + + validation { + condition = var.redis_num_cache_nodes >= 1 + error_message = "redis_num_cache_nodes must be at least 1." + } } variable "redis_port" { description = "The port for the Redis cache." type = number + + validation { + condition = var.redis_port > 0 && var.redis_port < 65536 + error_message = "redis_port must be between 1 and 65535." + } } variable "security_group_ids" { description = "A list of security group IDs to associate with the Redis cache." type = list(string) + + validation { + condition = length(var.security_group_ids) > 0 + error_message = "security_group_ids must contain at least one security group." + } } variable "snapshot_retention_limit" { description = "The number of days for which automatic snapshots are retained." type = number default = 5 + + validation { + condition = var.snapshot_retention_limit >= 0 && var.snapshot_retention_limit <= 30 + error_message = "snapshot_retention_limit must be between 0 and 30." + } } variable "snapshot_window" { @@ -72,4 +97,9 @@ variable "snapshot_window" { variable "subnet_ids" { description = "A list of subnet IDs for the cache subnet group." type = list(string) + + validation { + condition = length(var.subnet_ids) > 0 + error_message = "subnet_ids must contain at least one subnet." + } } From c4e68175bcbb755c5e0bc068c1eb9348c843df00 Mon Sep 17 00:00:00 2001 From: Rudransh Shrivastava Date: Tue, 13 Jan 2026 15:48:51 +0530 Subject: [PATCH 3/4] Add tests for database module --- .../modules/database/.terraform.lock.hcl | 45 ++++++ .../database/tests/database.tftest.hcl | 147 ++++++++++++++++++ infrastructure/modules/database/variables.tf | 40 +++++ 3 files changed, 232 insertions(+) create mode 100644 infrastructure/modules/database/.terraform.lock.hcl create mode 100644 infrastructure/modules/database/tests/database.tftest.hcl diff --git a/infrastructure/modules/database/.terraform.lock.hcl b/infrastructure/modules/database/.terraform.lock.hcl new file mode 100644 index 0000000000..22df00b9db --- /dev/null +++ b/infrastructure/modules/database/.terraform.lock.hcl @@ -0,0 +1,45 @@ +# This file is maintained automatically by "terraform init". +# Manual edits may be lost in future updates. + +provider "registry.terraform.io/hashicorp/aws" { + version = "6.22.0" + constraints = "6.22.0" + hashes = [ + "h1:TV1UZ7DzioV1EUY/lMS+eIInU379DA1Q2QwnEGGZMks=", + "zh:0ed7ceb13bade9076021a14f995d07346d3063f4a419a904d5804d76e372bbda", + "zh:195dcde5a4b0def82bc3379053edc13941ff94ea5905808fe575f7c7bbd66693", + "zh:4047c4dba121d29859b72d2155c47f969b41d3c5768f73dff5d8a0cc55f74e52", + "zh:5694f37d6ea69b6f96dfb30d53e66f7a41c1aad214c212b6ffa54bdd799e3b27", + "zh:6cf8bb7d984b1fae9fd10d6ce1e62f6c10751a1040734b75a1f7286609782e49", + "zh:737d0e600dfe2626b4d6fc5dd2b24c0997fd983228a7a607b9176a1894a281a0", + "zh:7d328a195ce36b1170afe6758cf88223c8765620211f5cc0451bdd6899243b4e", + "zh:7edb4bc34baeba92889bd9ed50b34c04b3eeb3d8faa8bb72699c6335a2e95bab", + "zh:8e71836814e95454b00c51f3cb3e10fd78a59f7dc4c5362af64233fee989790d", + "zh:9367f63b23d9ddfab590b2247a8ff5ccf83410cbeca43c6e441c488c45efff4c", + "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", + "zh:a007de80ffde8539a73ee39fcfbe7ed12e025c98cd29b2110a7383b41a4aad39", + "zh:aae7b7aed8bf3a4bea80a9a2f08fef1adeb748beff236c4a54af93bb6c09a56c", + "zh:b5a16b59d4210c1eaf35c8c027ecdab9e074dd081d602f5112eecdebf2e1866d", + "zh:d479bad0a004e4893bf0ba6c6cd867fefd14000051bbe3de5b44a925e3d46cd5", + ] +} + +provider "registry.terraform.io/hashicorp/random" { + version = "3.7.2" + constraints = "3.7.2" + hashes = [ + "h1:356j/3XnXEKr9nyicLUufzoF4Yr6hRy481KIxRVpK0c=", + "zh:14829603a32e4bc4d05062f059e545a91e27ff033756b48afbae6b3c835f508f", + "zh:1527fb07d9fea400d70e9e6eb4a2b918d5060d604749b6f1c361518e7da546dc", + "zh:1e86bcd7ebec85ba336b423ba1db046aeaa3c0e5f921039b3f1a6fc2f978feab", + "zh:24536dec8bde66753f4b4030b8f3ef43c196d69cccbea1c382d01b222478c7a3", + "zh:29f1786486759fad9b0ce4fdfbbfece9343ad47cd50119045075e05afe49d212", + "zh:4d701e978c2dd8604ba1ce962b047607701e65c078cb22e97171513e9e57491f", + "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", + "zh:7b8434212eef0f8c83f5a90c6d76feaf850f6502b61b53c329e85b3b281cba34", + "zh:ac8a23c212258b7976e1621275e3af7099e7e4a3d4478cf8d5d2a27f3bc3e967", + "zh:b516ca74431f3df4c6cf90ddcdb4042c626e026317a33c53f0b445a3d93b720d", + "zh:dc76e4326aec2490c1600d6871a95e78f9050f9ce427c71707ea412a2f2f1a62", + "zh:eac7b63e86c749c7d48f527671c7aee5b4e26c10be6ad7232d6860167f99dbb0", + ] +} diff --git a/infrastructure/modules/database/tests/database.tftest.hcl b/infrastructure/modules/database/tests/database.tftest.hcl new file mode 100644 index 0000000000..1b9a6a515c --- /dev/null +++ b/infrastructure/modules/database/tests/database.tftest.hcl @@ -0,0 +1,147 @@ +variables { + common_tags = { Environment = "test", Project = "nest" } + create_rds_proxy = false + db_allocated_storage = 20 + db_engine_version = "16.4" + db_instance_class = "db.t3.micro" + db_name = "nest_db" + db_subnet_ids = ["subnet-12345678"] + db_user = "nest_user" + environment = "test" + project_name = "nest" + proxy_security_group_ids = ["sg-proxy12345"] + security_group_ids = ["sg-12345678"] +} + +run "test_database_not_publicly_accessible" { + command = plan + + assert { + condition = aws_db_instance.main.publicly_accessible == false + error_message = "Database must not be publicly accessible." + } +} + +run "test_db_identifier_format" { + command = plan + + assert { + condition = aws_db_instance.main.identifier == lower("${var.project_name}-${var.environment}-db") + error_message = "Database identifier must follow naming convention: {project}-{environment}-db." + } +} + +run "test_deletion_protection_enabled" { + command = plan + + assert { + condition = aws_db_instance.main.deletion_protection + error_message = "Deletion protection must be enabled by default." + } +} + +run "test_engine_is_postgres" { + command = plan + + assert { + condition = aws_db_instance.main.engine == "postgres" + error_message = "Database engine must be postgres." + } +} + +run "test_password_generated_when_not_provided" { + command = plan + + assert { + condition = length(random_password.db_password) == 1 + error_message = "Database password must be generated when not provided." + } +} + +run "test_password_not_generated_when_provided" { + command = plan + + variables { + db_password = "test-password-123" + } + + assert { + condition = length(random_password.db_password) == 0 + error_message = "Database password must not be generated when provided." + } +} + +run "test_proxy_created_when_enabled" { + command = plan + + variables { + create_rds_proxy = true + } + + assert { + condition = length(aws_db_proxy.main) == 1 + error_message = "RDS proxy must be created when create_rds_proxy is true." + } +} + +run "test_proxy_engine_family" { + command = plan + + variables { + create_rds_proxy = true + } + + assert { + condition = aws_db_proxy.main[0].engine_family == "POSTGRESQL" + error_message = "RDS proxy engine family must be POSTGRESQL." + } +} + +run "test_proxy_not_created_when_disabled" { + command = plan + + assert { + condition = length(aws_db_proxy.main) == 0 + error_message = "RDS proxy must not be created when create_rds_proxy is false." + } +} + +run "test_proxy_requires_tls" { + command = plan + + variables { + create_rds_proxy = true + } + + assert { + condition = aws_db_proxy.main[0].require_tls + error_message = "RDS proxy must require TLS." + } +} + +run "test_ssm_parameter_is_secure_string" { + command = plan + + assert { + condition = aws_ssm_parameter.django_db_password.type == "SecureString" + error_message = "Database password must be stored as SecureString." + } +} + +run "test_ssm_parameter_path_format" { + command = plan + + assert { + condition = aws_ssm_parameter.django_db_password.name == "/${var.project_name}/${var.environment}/DJANGO_DB_PASSWORD" + error_message = "SSM parameter must follow path: /{project}/{environment}/DJANGO_DB_PASSWORD." + } +} + +run "test_storage_encrypted" { + command = plan + + assert { + condition = aws_db_instance.main.storage_encrypted + error_message = "Database storage must be encrypted." + } +} diff --git a/infrastructure/modules/database/variables.tf b/infrastructure/modules/database/variables.tf index d57e7f61ff..72f291dcfd 100644 --- a/infrastructure/modules/database/variables.tf +++ b/infrastructure/modules/database/variables.tf @@ -13,12 +13,22 @@ variable "create_rds_proxy" { variable "db_allocated_storage" { description = "The allocated storage for the RDS database in GB." type = number + + validation { + condition = var.db_allocated_storage >= 20 + error_message = "db_allocated_storage must be at least 20 GB." + } } variable "db_backup_retention_period" { description = "The number of days to retain backups for." type = number default = 7 + + validation { + condition = var.db_backup_retention_period >= 0 && var.db_backup_retention_period <= 35 + error_message = "db_backup_retention_period must be between 0 and 35." + } } variable "db_backup_window" { @@ -53,6 +63,11 @@ variable "db_engine_version" { variable "db_instance_class" { description = "The instance class for the RDS database." type = string + + validation { + condition = can(regex("^db\\.", var.db_instance_class)) + error_message = "db_instance_class must start with 'db.' (e.g., db.t3.micro, db.r5.large)." + } } variable "db_maintenance_window" { @@ -83,11 +98,21 @@ variable "db_storage_type" { description = "The storage type for the RDS database." type = string default = "gp3" + + validation { + condition = contains(["gp2", "gp3", "io1", "io2"], var.db_storage_type) + error_message = "db_storage_type must be one of: gp2, gp3, io1, io2." + } } variable "db_subnet_ids" { description = "A list of subnet IDs for the DB subnet group." type = list(string) + + validation { + condition = length(var.db_subnet_ids) > 0 + error_message = "db_subnet_ids must contain at least one subnet." + } } variable "db_user" { @@ -108,15 +133,30 @@ variable "project_name" { variable "proxy_security_group_ids" { description = "A list of security group IDs to associate with the RDS proxy." type = list(string) + + validation { + condition = length(var.proxy_security_group_ids) > 0 + error_message = "proxy_security_group_ids must contain at least one security group." + } } variable "secret_recovery_window_in_days" { description = "The number of days that Secrets Manager waits before it can delete the secret. Set to 0 to delete immediately." type = number default = 7 + + validation { + condition = var.secret_recovery_window_in_days >= 0 && var.secret_recovery_window_in_days <= 30 + error_message = "secret_recovery_window_in_days must be between 0 and 30." + } } variable "security_group_ids" { description = "A list of security group IDs to associate with the RDS database." type = list(string) + + validation { + condition = length(var.security_group_ids) > 0 + error_message = "security_group_ids must contain at least one security group." + } } From 814038bf426ab76c657612d902217075e3d89e3e Mon Sep 17 00:00:00 2001 From: Rudransh Shrivastava Date: Tue, 13 Jan 2026 19:48:35 +0530 Subject: [PATCH 4/4] Update code --- infrastructure/Makefile | 4 +- .../modules/cache/tests/cache.tftest.hcl | 3 +- infrastructure/modules/database/main.tf | 7 ++++ .../database/tests/database.tftest.hcl | 41 ++++++++++++------- infrastructure/modules/database/variables.tf | 10 ++--- 5 files changed, 39 insertions(+), 26 deletions(-) diff --git a/infrastructure/Makefile b/infrastructure/Makefile index 611ce4b64b..3c20d575b1 100644 --- a/infrastructure/Makefile +++ b/infrastructure/Makefile @@ -1,7 +1,5 @@ -MODULES_DIR := infrastructure/modules - test-infrastructure: - @for dir in $(MODULES_DIR)/*/; do \ + @for dir in infrastructure/modules/*/; do \ if [ -d "$$dir/tests" ]; then \ echo "Testing $$dir..."; \ terraform -chdir="$$dir" init -backend=false -input=false && \ diff --git a/infrastructure/modules/cache/tests/cache.tftest.hcl b/infrastructure/modules/cache/tests/cache.tftest.hcl index 17d526c78e..e006fe23ba 100644 --- a/infrastructure/modules/cache/tests/cache.tftest.hcl +++ b/infrastructure/modules/cache/tests/cache.tftest.hcl @@ -1,6 +1,7 @@ variables { common_tags = { Environment = "test", Project = "nest" } environment = "test" + log_retention_in_days = 30 project_name = "nest" redis_engine_version = "7.0" redis_node_type = "cache.t3.micro" @@ -122,7 +123,7 @@ run "test_subnet_group_uses_provided_subnets" { command = plan assert { - condition = tolist(aws_elasticache_subnet_group.main.subnet_ids) == var.subnet_ids + condition = toset(aws_elasticache_subnet_group.main.subnet_ids) == toset(var.subnet_ids) error_message = "Subnet group must use the provided subnet IDs." } } diff --git a/infrastructure/modules/database/main.tf b/infrastructure/modules/database/main.tf index 338fcecd6b..a926991079 100644 --- a/infrastructure/modules/database/main.tf +++ b/infrastructure/modules/database/main.tf @@ -145,6 +145,13 @@ resource "aws_db_proxy" "main" { }) vpc_security_group_ids = var.proxy_security_group_ids vpc_subnet_ids = var.db_subnet_ids + + lifecycle { + precondition { + condition = length(var.proxy_security_group_ids) > 0 + error_message = "proxy_security_group_ids must be provided when create_rds_proxy is true." + } + } } resource "aws_db_proxy_default_target_group" "main" { diff --git a/infrastructure/modules/database/tests/database.tftest.hcl b/infrastructure/modules/database/tests/database.tftest.hcl index 1b9a6a515c..2ba67474ac 100644 --- a/infrastructure/modules/database/tests/database.tftest.hcl +++ b/infrastructure/modules/database/tests/database.tftest.hcl @@ -1,16 +1,15 @@ variables { - common_tags = { Environment = "test", Project = "nest" } - create_rds_proxy = false - db_allocated_storage = 20 - db_engine_version = "16.4" - db_instance_class = "db.t3.micro" - db_name = "nest_db" - db_subnet_ids = ["subnet-12345678"] - db_user = "nest_user" - environment = "test" - project_name = "nest" - proxy_security_group_ids = ["sg-proxy12345"] - security_group_ids = ["sg-12345678"] + common_tags = { Environment = "test", Project = "nest" } + create_rds_proxy = false + db_allocated_storage = 20 + db_engine_version = "16.4" + db_instance_class = "db.t3.micro" + db_name = "nest_db" + db_subnet_ids = ["subnet-12345678"] + db_user = "nest_user" + environment = "test" + project_name = "nest" + security_group_ids = ["sg-12345678"] } run "test_database_not_publicly_accessible" { @@ -75,7 +74,8 @@ run "test_proxy_created_when_enabled" { command = plan variables { - create_rds_proxy = true + create_rds_proxy = true + proxy_security_group_ids = ["sg-proxy12345"] } assert { @@ -88,7 +88,8 @@ run "test_proxy_engine_family" { command = plan variables { - create_rds_proxy = true + create_rds_proxy = true + proxy_security_group_ids = ["sg-proxy12345"] } assert { @@ -110,7 +111,8 @@ run "test_proxy_requires_tls" { command = plan variables { - create_rds_proxy = true + create_rds_proxy = true + proxy_security_group_ids = ["sg-proxy12345"] } assert { @@ -145,3 +147,12 @@ run "test_storage_encrypted" { error_message = "Database storage must be encrypted." } } + +run "test_subnet_group_uses_provided_subnets" { + command = plan + + assert { + condition = toset(aws_db_subnet_group.main.subnet_ids) == toset(var.db_subnet_ids) + error_message = "Subnet group must use the provided subnet IDs." + } +} diff --git a/infrastructure/modules/database/variables.tf b/infrastructure/modules/database/variables.tf index 72f291dcfd..ce2779aa2f 100644 --- a/infrastructure/modules/database/variables.tf +++ b/infrastructure/modules/database/variables.tf @@ -133,11 +133,7 @@ variable "project_name" { variable "proxy_security_group_ids" { description = "A list of security group IDs to associate with the RDS proxy." type = list(string) - - validation { - condition = length(var.proxy_security_group_ids) > 0 - error_message = "proxy_security_group_ids must contain at least one security group." - } + default = [] } variable "secret_recovery_window_in_days" { @@ -146,8 +142,8 @@ variable "secret_recovery_window_in_days" { default = 7 validation { - condition = var.secret_recovery_window_in_days >= 0 && var.secret_recovery_window_in_days <= 30 - error_message = "secret_recovery_window_in_days must be between 0 and 30." + condition = var.secret_recovery_window_in_days == 0 || (var.secret_recovery_window_in_days >= 7 && var.secret_recovery_window_in_days <= 30) + error_message = "secret_recovery_window_in_days must be 0 or between 7 and 30." } }