Skip to content

Commit e26bfa0

Browse files
committed
tests(rds-scheduler): implement stop operation
This commit adds end-to-end testing to validate the AWS Lambda rds scheduler actually works expected. They key changes include: * Created a new test-execution module that: * Triggers the aws stop lambda * Waits appropriate time intervals before and after function execution * Retrieves the rds power states to verify function effectiveness
1 parent 25124d7 commit e26bfa0

File tree

10 files changed

+278
-7
lines changed

10 files changed

+278
-7
lines changed

examples/rds-scheduler/main.tf

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ resource "aws_subnet" "secondary" {
2121
}
2222

2323
resource "aws_db_subnet_group" "aurora" {
24-
name = "aurora-subnet"
24+
name = "aurora-subnet-${random_pet.suffix.id}"
2525
subnet_ids = [aws_subnet.primary.id, aws_subnet.secondary.id]
2626
}
2727

2828
resource "aws_rds_cluster" "aurora_scheduled" {
29-
cluster_identifier = "test-to-stop-${random_pet.suffix.id}"
29+
cluster_identifier = "test-to-stop-aurora-cluster-${random_pet.suffix.id}"
3030
engine = "aurora-mysql"
3131
db_subnet_group_name = aws_db_subnet_group.aurora.id
3232
database_name = "aurorawithtag"
@@ -40,7 +40,7 @@ resource "aws_rds_cluster" "aurora_scheduled" {
4040
}
4141

4242
resource "aws_rds_cluster_instance" "aurora_scheduled" {
43-
identifier = "test-to-stop-instance-${random_pet.suffix.id}"
43+
identifier = "test-to-stop-aurora-instance-${random_pet.suffix.id}"
4444
engine = aws_rds_cluster.aurora_scheduled.engine
4545
engine_version = aws_rds_cluster.aurora_scheduled.engine_version
4646
db_subnet_group_name = aws_db_subnet_group.aurora.id
@@ -52,9 +52,8 @@ resource "aws_rds_cluster_instance" "aurora_scheduled" {
5252
}
5353
}
5454

55-
# Create rds mariadb instance with tag
5655
resource "aws_db_instance" "mariadb_scheduled" {
57-
identifier = "test-to-stop-${random_pet.suffix.id}"
56+
identifier = "test-to-stop-mariadb-instance-${random_pet.suffix.id}"
5857
db_name = "mariadbwithtag"
5958
db_subnet_group_name = aws_db_subnet_group.aurora.id
6059
allocated_storage = 10
@@ -71,9 +70,8 @@ resource "aws_db_instance" "mariadb_scheduled" {
7170
}
7271
}
7372

74-
# Create rds mysql instance with tag
7573
resource "aws_db_instance" "mysql_not_scheduled" {
76-
identifier = "test-not-to-stop-${random_pet.suffix.id}"
74+
identifier = "test-not-to-stop-mysql-instance-${random_pet.suffix.id}"
7775
db_name = "mysqlwithouttag"
7876
db_subnet_group_name = aws_db_subnet_group.aurora.id
7977
allocated_storage = 10
@@ -124,3 +122,17 @@ module "rds-start-monday" {
124122
value = "true"
125123
}
126124
}
125+
126+
module "test-execution" {
127+
count = var.test_mode ? 1 : 0
128+
source = "./test-execution"
129+
130+
lambda_stop_name = module.rds-stop-friday.scheduler_lambda_name
131+
rds_aurora_cluster_to_scheduled_name = aws_rds_cluster.aurora_scheduled.cluster_identifier
132+
rds_mariadb_instance_to_scheduled_name = aws_db_instance.mariadb_scheduled.identifier
133+
rds_mysql_instance_to_not_scheduled_name = aws_db_instance.mysql_not_scheduled.identifier
134+
135+
depends_on = [
136+
aws_rds_cluster_instance.aurora_scheduled
137+
]
138+
}

examples/rds-scheduler/outputs.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,11 @@ output "lambda_start_name" {
1515
output "lambda_start_arn" {
1616
value = module.rds-start-monday.scheduler_lambda_arn
1717
}
18+
19+
output "rds_aurora_cluster_name" {
20+
value = aws_rds_cluster.aurora_scheduled.cluster_identifier
21+
}
22+
23+
output "rds_aurora_instance_name" {
24+
value = aws_rds_cluster_instance.aurora_scheduled.identifier
25+
}

examples/rds-scheduler/terraform.tftest.hcl

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
run "create_test_infrastructure" {
22
command = apply
33

4+
variables {
5+
test_mode = true
6+
}
7+
48
assert {
59
condition = module.rds-stop-friday.scheduler_lambda_name == "stop-rds-${random_pet.suffix.id}"
610
error_message = "Invalid Stop lambda name"
@@ -10,4 +14,34 @@ run "create_test_infrastructure" {
1014
condition = module.rds-start-monday.scheduler_lambda_name == "start-rds-${random_pet.suffix.id}"
1115
error_message = "Invalid Start lambda name"
1216
}
17+
18+
assert {
19+
condition = module.test-execution[0].rds_aurora_cluster_to_scheduled == "stopping\n"
20+
error_message = "Invalid RDS cluster instance state"
21+
}
22+
23+
assert {
24+
condition = module.test-execution[0].rds_mariadb_instance_to_scheduled == "stopping\n"
25+
error_message = "Invalid RDS instance state"
26+
}
27+
28+
assert {
29+
condition = module.test-execution[0].rds_mysql_instance_to_not_scheduled == "available\n"
30+
error_message = "Invalid RDS instance state"
31+
}
32+
}
33+
34+
# Add this cleanup step to restore the cluster to 'available' state before destruction
35+
run "cleanup_test_resources" {
36+
command = apply
37+
38+
variables {
39+
rds_aurora_cluster_name = run.create_test_infrastructure.rds_aurora_cluster_name
40+
rds_aurora_instance_name = run.create_test_infrastructure.rds_aurora_instance_name
41+
}
42+
43+
# This will start the stopped cluster to ensure proper deletion
44+
module {
45+
source = "./test-cleanup"
46+
}
1347
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
resource "null_resource" "start_rds_aurora_cluster" {
2+
provisioner "local-exec" {
3+
command = <<-EOT
4+
TIMEOUT=600
5+
START_TIME=$(date +%s)
6+
7+
echo "Waiting for rds aurora cluster ${var.rds_aurora_cluster_name} to reach 'stopped' state (timeout: $TIMEOUT seconds)..."
8+
9+
while true; do
10+
# Check the current state of the rds aurora cluster
11+
CURRENT_STATE=$(aws rds describe-db-clusters --db-cluster-identifier ${var.rds_aurora_cluster_name} --query 'DBClusters[0].Status' --output text)
12+
13+
# Get current elapsed time
14+
CURRENT_TIME=$(date +%s)
15+
ELAPSED=$((CURRENT_TIME - START_TIME))
16+
17+
# Check if cluster is stopped
18+
if [ "$CURRENT_STATE" = "stopped" ]; then
19+
aws rds start-db-cluster --db-cluster-identifier ${var.rds_aurora_cluster_name}
20+
exit 0
21+
fi
22+
23+
# Check if we've exceeded the timeout
24+
if [ $ELAPSED -ge $TIMEOUT ]; then
25+
echo "Timeout reached. rds aurora cluster did not reach 'stopped' state within $TIMEOUT seconds."
26+
exit 1
27+
fi
28+
29+
# Wait 10 seconds before checking again
30+
echo "Current state: $CURRENT_STATE (elapsed: $ELAPSED seconds/ $TIMEOUT seconds)..."
31+
sleep 10
32+
done
33+
EOT
34+
}
35+
}
36+
37+
resource "null_resource" "waiting_for_rds_aurora_cluster_to_start" {
38+
provisioner "local-exec" {
39+
command = <<-EOT
40+
TIMEOUT=600
41+
START_TIME=$(date +%s)
42+
43+
echo "Waiting for rds aurora cluster ${var.rds_aurora_cluster_name} to reach 'available' state (timeout: $TIMEOUT seconds)..."
44+
45+
while true; do
46+
# Check the current state of the rds aurora cluster
47+
CURRENT_STATE=$(aws rds describe-db-clusters --db-cluster-identifier ${var.rds_aurora_cluster_name} --query 'DBClusters[0].Status' --output text)
48+
49+
# Get current elapsed time
50+
CURRENT_TIME=$(date +%s)
51+
ELAPSED=$((CURRENT_TIME - START_TIME))
52+
53+
# Check if cluster is available
54+
if [ "$CURRENT_STATE" = "available" ]; then
55+
exit 0
56+
fi
57+
58+
# Check if we've exceeded the timeout
59+
if [ $ELAPSED -ge $TIMEOUT ]; then
60+
echo "Timeout reached. rds aurora cluster did not reach 'available' state within $TIMEOUT seconds."
61+
exit 1
62+
fi
63+
64+
# Wait 10 seconds before checking again
65+
echo "Current state: $CURRENT_STATE (elapsed: $ELAPSED seconds/ $TIMEOUT seconds)..."
66+
sleep 10
67+
done
68+
EOT
69+
}
70+
71+
depends_on = [null_resource.start_rds_aurora_cluster]
72+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
variable "rds_aurora_cluster_name" {
2+
description = "Name of the rds aurora cluster to start before deletion"
3+
type = string
4+
}
5+
6+
variable "rds_aurora_instance_name" {
7+
description = "Name of the rds aurora instance to start before deletion"
8+
type = string
9+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
resource "time_sleep" "before_stop_wait_60_seconds" {
2+
create_duration = "60s"
3+
}
4+
5+
resource "aws_lambda_invocation" "this" {
6+
function_name = var.lambda_stop_name
7+
8+
input = jsonencode({
9+
key1 = "value1"
10+
key2 = "value2"
11+
})
12+
13+
depends_on = [time_sleep.before_stop_wait_60_seconds]
14+
}
15+
16+
resource "time_sleep" "after_stop_wait_60_seconds" {
17+
create_duration = "60s"
18+
19+
depends_on = [aws_lambda_invocation.this]
20+
}
21+
22+
resource "null_resource" "rds_aurora_cluster_to_scheduled" {
23+
provisioner "local-exec" {
24+
command = <<-EOT
25+
aws rds describe-db-clusters \
26+
--db-cluster-identifier ${var.rds_aurora_cluster_to_scheduled_name} \
27+
--query 'DBClusters[0].Status' \
28+
--output text > ${path.module}/rds_aurora_cluster_to_scheduled.state
29+
EOT
30+
}
31+
32+
depends_on = [time_sleep.after_stop_wait_60_seconds]
33+
}
34+
35+
data "local_file" "rds_aurora_cluster_to_scheduled" {
36+
filename = "${path.module}/rds_aurora_cluster_to_scheduled.state"
37+
38+
depends_on = [null_resource.rds_aurora_cluster_to_scheduled]
39+
}
40+
41+
resource "null_resource" "rds_mariadb_instance_to_scheduled" {
42+
provisioner "local-exec" {
43+
command = <<-EOT
44+
aws rds describe-db-instances \
45+
--db-instance-identifier ${var.rds_mariadb_instance_to_scheduled_name} \
46+
--query 'DBInstances[0].DBInstanceStatus' \
47+
--output text > ${path.module}/rds_mariadb_instance_to_scheduled.state
48+
EOT
49+
}
50+
51+
depends_on = [time_sleep.after_stop_wait_60_seconds]
52+
}
53+
54+
data "local_file" "rds_mariadb_instance_to_scheduled" {
55+
filename = "${path.module}/rds_mariadb_instance_to_scheduled.state"
56+
57+
depends_on = [null_resource.rds_mariadb_instance_to_scheduled]
58+
}
59+
60+
resource "null_resource" "rds_mysql_instance_to_not_scheduled" {
61+
provisioner "local-exec" {
62+
command = <<-EOT
63+
aws rds describe-db-instances \
64+
--db-instance-identifier ${var.rds_mysql_instance_to_not_scheduled_name} \
65+
--query 'DBInstances[0].DBInstanceStatus' \
66+
--output text > ${path.module}/rds_mysql_instance_to_not_scheduled.state
67+
EOT
68+
}
69+
70+
depends_on = [time_sleep.after_stop_wait_60_seconds]
71+
}
72+
73+
data "local_file" "rds_mysql_instance_to_not_scheduled" {
74+
filename = "${path.module}/rds_mysql_instance_to_not_scheduled.state"
75+
76+
depends_on = [null_resource.rds_mysql_instance_to_not_scheduled]
77+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
output "rds_aurora_cluster_to_scheduled" {
2+
description = "The status of the RDS cluster"
3+
value = data.local_file.rds_aurora_cluster_to_scheduled.content
4+
}
5+
6+
output "rds_mariadb_instance_to_scheduled" {
7+
description = "The status of the RDS instance"
8+
value = data.local_file.rds_mariadb_instance_to_scheduled.content
9+
}
10+
11+
output "rds_mysql_instance_to_not_scheduled" {
12+
description = "The status of the RDS instance"
13+
value = data.local_file.rds_mysql_instance_to_not_scheduled.content
14+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
variable "lambda_stop_name" {
2+
description = "Name of the Lambda function used for stopping instances"
3+
type = string
4+
}
5+
6+
variable "rds_aurora_cluster_to_scheduled_name" {
7+
description = "rds cluster name to be scheduled"
8+
type = string
9+
}
10+
11+
variable "rds_mariadb_instance_to_scheduled_name" {
12+
description = "rds instance name to be scheduled"
13+
type = string
14+
}
15+
16+
variable "rds_mysql_instance_to_not_scheduled_name" {
17+
description = "rds instance name to not be scheduled"
18+
type = string
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
terraform {
2+
required_version = ">= 1.3.0"
3+
required_providers {
4+
aws = {
5+
source = "hashicorp/aws"
6+
version = ">= 5.94.1"
7+
}
8+
null = {
9+
source = "hashicorp/null"
10+
version = ">= 3.0.0, < 4.0"
11+
}
12+
local = {
13+
source = "hashicorp/local"
14+
version = ">= 2.0.0, < 3.0"
15+
}
16+
time = {
17+
source = "hashicorp/time"
18+
version = "0.13.0"
19+
}
20+
}
21+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
variable "test_mode" {
2+
description = "Whether to run in test mode"
3+
type = bool
4+
default = false
5+
}

0 commit comments

Comments
 (0)