Skip to content

Commit

Permalink
feat(aws): add rds-mysql
Browse files Browse the repository at this point in the history
  • Loading branch information
fredleger committed May 16, 2024
1 parent 6d9ee99 commit 3f98b74
Show file tree
Hide file tree
Showing 8 changed files with 511 additions and 0 deletions.
26 changes: 26 additions & 0 deletions aws/rds-mysql-cluster/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions aws/rds-mysql-cluster/.tflint.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugin "terraform" {
enabled = true
preset = "recommended"
}

plugin "aws" {
enabled = true
version = "0.30.0"
source = "github.com/terraform-linters/tflint-ruleset-aws"
}
85 changes: 85 additions & 0 deletions aws/rds-mysql-cluster/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# RDS mysql cluster

Create an RDS cluster in AWS with any number of instances.

- Supports only Aurora MySQL
- Supports serverless clusters

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Requirements

| Name | Version |
|------|---------|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | ~> 1.3 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 4.30.0, < 5.0.0 |
| <a name="requirement_time"></a> [time](#requirement\_time) | ~> 0.9.1 |
| <a name="requirement_tls"></a> [tls](#requirement\_tls) | ~> 4.0.3 |

## Providers

| Name | Version |
|------|---------|
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 4.30.0, < 5.0.0 |
| <a name="provider_time"></a> [time](#provider\_time) | ~> 0.9.1 |

## Modules

No modules.

## Resources

| Name | Type |
|------|------|
| [aws_db_subnet_group.subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource |
| [aws_rds_cluster.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | resource |
| [aws_rds_cluster_instance.instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | resource |
| [aws_rds_cluster_parameter_group.params](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
| [time_static.last_update](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/static) | resource |

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_apply_immediately"></a> [apply\_immediately](#input\_apply\_immediately) | Specifies whether any database modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no |
| <a name="input_auto_minor_version_upgrade"></a> [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window | `bool` | `true` | no |
| <a name="input_backup_retention_period"></a> [backup\_retention\_period](#input\_backup\_retention\_period) | The days to retain backups for | `number` | `7` | no |
| <a name="input_copy_tags_to_snapshot"></a> [copy\_tags\_to\_snapshot](#input\_copy\_tags\_to\_snapshot) | On delete, copy all Instance tags to the final snapshot | `bool` | `true` | no |
| <a name="input_customer"></a> [customer](#input\_customer) | Customer for the current deployment | `string` | `""` | no |
| <a name="input_database_name"></a> [database\_name](#input\_database\_name) | The name of the database to create when the DB instance is created | `string` | `null` | no |
| <a name="input_db_parameter_group_family"></a> [db\_parameter\_group\_family](#input\_db\_parameter\_group\_family) | The family of the DB parameter group | `string` | `"aurora-mysql5.7"` | no |
| <a name="input_db_parameter_group_parameters"></a> [db\_parameter\_group\_parameters](#input\_db\_parameter\_group\_parameters) | A list of DB parameters to apply | <pre>list(object({<br> name = string<br> value = string<br> }))</pre> | `null` | no |
| <a name="input_default_instance_class"></a> [default\_instance\_class](#input\_default\_instance\_class) | The default instance class to use for instances | `string` | `"db.t3.small"` | no |
| <a name="input_deletion_protection"></a> [deletion\_protection](#input\_deletion\_protection) | If the DB instance should have deletion protection enabled | `bool` | `false` | no |
| <a name="input_enabled_cloudwatch_logs_exports"></a> [enabled\_cloudwatch\_logs\_exports](#input\_enabled\_cloudwatch\_logs\_exports) | A list of log types that need to be enabled for exporting to CloudWatch Logs. Note that this is not supported on serverless engine. | `list(string)` | `null` | no |
| <a name="input_engine"></a> [engine](#input\_engine) | The database engine to use | `string` | `"aurora-mysql"` | no |
| <a name="input_engine_mode"></a> [engine\_mode](#input\_engine\_mode) | The database engine mode to use | `string` | `"serverless"` | no |
| <a name="input_engine_version"></a> [engine\_version](#input\_engine\_version) | The engine version to use | `string` | `"8.0.mysql_aurora.3.02.2"` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | Environment for the current deployment | `string` | `""` | no |
| <a name="input_iam_database_authentication_enabled"></a> [iam\_database\_authentication\_enabled](#input\_iam\_database\_authentication\_enabled) | Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled | `bool` | `false` | no |
| <a name="input_iam_roles"></a> [iam\_roles](#input\_iam\_roles) | A list of ARNs for the IAM roles to associate with the DB instance | `list(string)` | `null` | no |
| <a name="input_instances"></a> [instances](#input\_instances) | A list of DB instances to create | <pre>list(object({<br> name = string<br> instance_class = string<br> publicly_accessible = bool<br> availability_zone = string<br> }))</pre> | `null` | no |
| <a name="input_name"></a> [name](#input\_name) | The name of the launch template | `string` | n/a | yes |
| <a name="input_password"></a> [password](#input\_password) | Password for the master DB user | `string` | `"root"` | no |
| <a name="input_performance_insights_enabled"></a> [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | Specifies whether Performance Insights is enabled | `bool` | `true` | no |
| <a name="input_port"></a> [port](#input\_port) | The port on which the DB accepts connections | `number` | `3306` | no |
| <a name="input_preferred_backup_window"></a> [preferred\_backup\_window](#input\_preferred\_backup\_window) | The daily time range (in UTC) during which automated backups are created if they are enabled | `string` | `"02:00-03:00"` | no |
| <a name="input_preferred_maintenance_window"></a> [preferred\_maintenance\_window](#input\_preferred\_maintenance\_window) | The weekly time range (in UTC) during which system maintenance can occur | `string` | `"sun:03:00-sun:04:00"` | no |
| <a name="input_rds_enhanced_monitoring_interval"></a> [rds\_enhanced\_monitoring\_interval](#input\_rds\_enhanced\_monitoring\_interval) | The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance | `number` | `0` | no |
| <a name="input_rds_enhanced_monitoring_role_arn"></a> [rds\_enhanced\_monitoring\_role\_arn](#input\_rds\_enhanced\_monitoring\_role\_arn) | The ARN of the IAM role that allows Amazon RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no |
| <a name="input_scaling_configuration"></a> [scaling\_configuration](#input\_scaling\_configuration) | A scaling configuration block | `any` | `null` | no |
| <a name="input_security_group_ids"></a> [security\_group\_ids](#input\_security\_group\_ids) | A list of VPC security groups to associate | `list(string)` | `null` | no |
| <a name="input_serverlessv2_scaling_configuration"></a> [serverlessv2\_scaling\_configuration](#input\_serverlessv2\_scaling\_configuration) | remember it's only valid when engine mode is set to "provisioned" | `any` | `null` | no |
| <a name="input_storage_encrypted"></a> [storage\_encrypted](#input\_storage\_encrypted) | Specifies whether the DB instance is encrypted | `bool` | `true` | no |
| <a name="input_subnet_ids"></a> [subnet\_ids](#input\_subnet\_ids) | A list of VPC subnet IDs | `list(string)` | `null` | no |
| <a name="input_tags"></a> [tags](#input\_tags) | Default tags to add to resources | `map(any)` | `{}` | no |
| <a name="input_username"></a> [username](#input\_username) | Username for the master DB user | `string` | `"root"` | no |

## Outputs

| Name | Description |
|------|-------------|
| <a name="output_arn"></a> [arn](#output\_arn) | n/a |
| <a name="output_endpoint"></a> [endpoint](#output\_endpoint) | n/a |
| <a name="output_id"></a> [id](#output\_id) | n/a |
| <a name="output_reader_endpoint"></a> [reader\_endpoint](#output\_reader\_endpoint) | n/a |
<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
17 changes: 17 additions & 0 deletions aws/rds-mysql-cluster/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
locals {
# tflint-ignore: terraform_unused_declarations
interpolated_tags = merge({
"Name" = var.name,
"Customer" = var.customer,
"Environment" = var.environment,
"ManagedBy" = "Terraform",
"LastModifiedAt" = time_static.last_update.rfc3339,
},
var.tags
)
instances_lenght = var.instances == null ? 0 : length(var.instances)
instances_count = var.engine_mode == "serverless" ? 0 : local.instances_lenght
}

resource "time_static" "last_update" {
}
15 changes: 15 additions & 0 deletions aws/rds-mysql-cluster/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "id" {
value = aws_rds_cluster.cluster.id
}

output "arn" {
value = aws_rds_cluster.cluster.arn
}

output "endpoint" {
value = aws_rds_cluster.cluster.endpoint
}

output "reader_endpoint" {
value = aws_rds_cluster.cluster.reader_endpoint
}
17 changes: 17 additions & 0 deletions aws/rds-mysql-cluster/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
terraform {
required_version = "~> 1.3"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 4.30.0, < 5.0.0"
}
time = {
source = "hashicorp/time"
version = "~> 0.9.1"
}
tls = {
source = "hashicorp/tls"
version = "~> 4.0.3"
}
}
}
114 changes: 114 additions & 0 deletions aws/rds-mysql-cluster/rds.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
resource "aws_db_subnet_group" "subnet_group" {
name = var.name
subnet_ids = var.subnet_ids
tags = local.interpolated_tags
}

resource "aws_rds_cluster_parameter_group" "params" {
name = var.name
family = var.db_parameter_group_family
description = "${var.name} parameters group"
dynamic "parameter" {
for_each = var.db_parameter_group_parameters == null ? [] : var.db_parameter_group_parameters

content {
name = parameter.value.name
value = parameter.value.value
}
}

tags = local.interpolated_tags
}

#trivy:ignore:aws-rds-encrypt-cluster-storage-data
#trivy:ignore:AVD-AWS-0343 protection is activated by default
resource "aws_rds_cluster" "cluster" {
#checkov:skip=CKV2_AWS_8:it's not module responsibility to create a backup plan
#checkov:skip=CKV_AWS_20:RDS cluster is encrypted
#checkov:skip=CKV_AWS_118:we don't want enhanced monitoring for now
#checkov:skip=CKV_AWS_128:we don't want to deal with IAM authentication
#checkov:skip=CKV_AWS_139:deletion protection is activated by default
#checkov:skip=CKV_AWS_162:we don't want to deal with IAM authentication
#checkov:skip=CKV_AWS_324:we don't want log capture
#checkov:skip=CKV_AWS_327:we don't want using kms key
#checkov:skip=CKV_AWS_354:we don't need performance insights

cluster_identifier = var.name
engine = var.engine
engine_mode = var.engine_mode
engine_version = var.engine_version
database_name = var.database_name
master_username = var.username
master_password = var.password
final_snapshot_identifier = "${var.name}-final-snapshot"
skip_final_snapshot = false
deletion_protection = var.deletion_protection
backup_retention_period = var.backup_retention_period
preferred_backup_window = var.preferred_backup_window
preferred_maintenance_window = var.preferred_maintenance_window
port = var.port
db_subnet_group_name = aws_db_subnet_group.subnet_group.name
vpc_security_group_ids = var.security_group_ids
storage_encrypted = var.storage_encrypted
apply_immediately = var.apply_immediately
db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.params.name
iam_database_authentication_enabled = var.iam_database_authentication_enabled
copy_tags_to_snapshot = var.copy_tags_to_snapshot
iam_roles = var.iam_roles
enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports

dynamic "scaling_configuration" {
for_each = var.scaling_configuration != null ? [var.scaling_configuration] : []

content {
auto_pause = lookup(scaling_configuration.value, "auto_pause", null)
max_capacity = lookup(scaling_configuration.value, "max_capacity", null)
min_capacity = lookup(scaling_configuration.value, "min_capacity", null)
seconds_until_auto_pause = lookup(scaling_configuration.value, "seconds_until_auto_pause", null)
timeout_action = lookup(scaling_configuration.value, "timeout_action", null)
}
}

dynamic "serverlessv2_scaling_configuration" {
for_each = var.serverlessv2_scaling_configuration != null ? [var.serverlessv2_scaling_configuration] : []

content {
min_capacity = lookup(serverlessv2_scaling_configuration.value, "min_capacity", null)
max_capacity = lookup(serverlessv2_scaling_configuration.value, "max_capacity", null)
}
}

tags = local.interpolated_tags
}

resource "aws_rds_cluster_instance" "instance" {
#checkov:skip=CKV_AWS_118:we don't want enhanced monitoring for now
#checkov:skip=CKV_AWS_273:we don't use IAM users or SSO
#checkov:skip=CKV_AWS_354:we don't need performance insights

count = local.instances_count
identifier = var.instances[count.index].name
cluster_identifier = aws_rds_cluster.cluster.id
engine = aws_rds_cluster.cluster.engine
engine_version = aws_rds_cluster.cluster.engine_version
instance_class = lookup(var.instances[count.index], "instance_class", var.default_instance_class)
publicly_accessible = lookup(var.instances[count.index], "publicly_accessible", false)
availability_zone = lookup(var.instances[count.index], "availability_zone", null)
db_subnet_group_name = aws_db_subnet_group.subnet_group.name
apply_immediately = var.apply_immediately
monitoring_role_arn = var.rds_enhanced_monitoring_role_arn
monitoring_interval = var.rds_enhanced_monitoring_interval
auto_minor_version_upgrade = var.auto_minor_version_upgrade
performance_insights_enabled = var.performance_insights_enabled
copy_tags_to_snapshot = var.copy_tags_to_snapshot

# Updating engine version forces replacement of instances, and they shouldn't be replaced
# because cluster will update them if engine version is changed
lifecycle {
ignore_changes = [
engine_version
]
}

tags = local.interpolated_tags
}
Loading

0 comments on commit 3f98b74

Please sign in to comment.