diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml new file mode 100644 index 00000000..d887a660 --- /dev/null +++ b/.github/workflows/lock.yml @@ -0,0 +1,21 @@ +name: 'Lock Threads' + +on: + schedule: + - cron: '50 1 * * *' + +jobs: + lock: + runs-on: ubuntu-latest + steps: + - uses: dessant/lock-threads@v3 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + issue-comment: > + I'm going to lock this issue because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. + If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. + issue-inactive-days: '30' + pr-comment: > + I'm going to lock this pull request because it has been closed for _30 days_ ⏳. This helps our maintainers find and focus on the active issues. + If you have found a problem that seems related to this change, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further. + pr-inactive-days: '30' diff --git a/.github/workflows/pr-title.yml b/.github/workflows/pr-title.yml index 168011c4..cb32a0f8 100644 --- a/.github/workflows/pr-title.yml +++ b/.github/workflows/pr-title.yml @@ -14,7 +14,7 @@ jobs: steps: # Please look up the latest version from # https://github.com/amannn/action-semantic-pull-request/releases - - uses: amannn/action-semantic-pull-request@v3.4.6 + - uses: amannn/action-semantic-pull-request@v5.0.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index b8f1b8a5..cb826713 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -8,6 +8,7 @@ on: env: TERRAFORM_DOCS_VERSION: v0.16.0 + TFLINT_VERSION: v0.44.1 jobs: collectInputs: @@ -17,11 +18,11 @@ jobs: directories: ${{ steps.dirs.outputs.directories }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Get root directories id: dirs - uses: clowdhaus/terraform-composite-actions/directories@v1.3.0 + uses: clowdhaus/terraform-composite-actions/directories@v1.8.3 preCommitMinVersions: name: Min TF pre-commit @@ -32,28 +33,30 @@ jobs: directory: ${{ fromJson(needs.collectInputs.outputs.directories) }} steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Terraform min/max versions id: minMax - uses: clowdhaus/terraform-min-max@v1.0.3 + uses: clowdhaus/terraform-min-max@v1.2.4 with: directory: ${{ matrix.directory }} - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} # Run only validate pre-commit check on min version supported if: ${{ matrix.directory != '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 with: terraform-version: ${{ steps.minMax.outputs.minVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} args: 'terraform_validate --color=always --show-diff-on-failure --files ${{ matrix.directory }}/*' - name: Pre-commit Terraform ${{ steps.minMax.outputs.minVersion }} # Run only validate pre-commit check on min version supported if: ${{ matrix.directory == '.' }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 with: terraform-version: ${{ steps.minMax.outputs.minVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} args: 'terraform_validate --color=always --show-diff-on-failure --files $(ls *.tf)' preCommitMaxVersion: @@ -62,17 +65,19 @@ jobs: needs: collectInputs steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.ref }} repository: ${{github.event.pull_request.head.repo.full_name}} - name: Terraform min/max versions id: minMax - uses: clowdhaus/terraform-min-max@v1.0.3 + uses: clowdhaus/terraform-min-max@v1.2.4 - name: Pre-commit Terraform ${{ steps.minMax.outputs.maxVersion }} - uses: clowdhaus/terraform-composite-actions/pre-commit@v1.3.0 + uses: clowdhaus/terraform-composite-actions/pre-commit@v1.8.3 with: terraform-version: ${{ steps.minMax.outputs.maxVersion }} + tflint-version: ${{ env.TFLINT_VERSION }} terraform-docs-version: ${{ env.TERRAFORM_DOCS_VERSION }} + install-hcledit: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7529cbaa..81f67474 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: if: github.repository_owner == 'terraform-aws-modules' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: persist-credentials: false fetch-depth: 0 diff --git a/.github/workflows/stale-actions.yaml b/.github/workflows/stale-actions.yaml index c09ae1d5..50379957 100644 --- a/.github/workflows/stale-actions.yaml +++ b/.github/workflows/stale-actions.yaml @@ -7,7 +7,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v4 + - uses: actions/stale@v6 with: repo-token: ${{ secrets.GITHUB_TOKEN }} # Staling issues and PR's diff --git a/README.md b/README.md index d627b7e6..6dce4d6d 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ module "cluster" { name = "test-aurora-db-postgres96" engine = "aurora-postgresql" - engine_version = "11.12" + engine_version = "14.5" instance_class = "db.r6g.large" instances = { one = {} @@ -32,19 +32,21 @@ module "cluster" { } } - vpc_id = "vpc-12345678" - subnets = ["subnet-12345678", "subnet-87654321"] - - allowed_security_groups = ["sg-12345678"] - allowed_cidr_blocks = ["10.20.0.0/20"] + vpc_id = "vpc-12345678" + db_subnet_group_name = "db-subnet-group" + security_group_rules = { + ex1_ingress = { + cidr_blocks = ["10.20.0.0/20"] + } + ex1_ingress = { + source_security_group_id = "sg-12345678" + } + } storage_encrypted = true apply_immediately = true monitoring_interval = 10 - db_parameter_group_name = "default" - db_cluster_parameter_group_name = "default" - enabled_cloudwatch_logs_exports = ["postgresql"] tags = { @@ -187,7 +189,7 @@ module "cluster" { source = "terraform-aws-modules/rds-aurora/aws" # Disable creation of cluster and all resources - create_cluster = false + create = false # Disable creation of subnet group - provide a subnet group create_db_subnet_group = false @@ -198,9 +200,6 @@ module "cluster" { # Disable creation of monitoring IAM role - provide a role ARN create_monitoring_role = false - # Disable creation of random password - AWS API provides the password - create_random_password = false - # ... omitted } ``` @@ -224,16 +223,14 @@ Terraform documentation is generated automatically using [pre-commit hooks](http | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | -| [random](#requirement\_random) | >= 2.2 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.30 | -| [random](#provider\_random) | >= 2.2 | +| [aws](#provider\_aws) | ~> 4.61 | ## Modules @@ -256,11 +253,7 @@ No modules. | [aws_rds_cluster_parameter_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | | [aws_rds_cluster_role_association.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_role_association) | resource | | [aws_security_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource | -| [aws_security_group_rule.cidr_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [aws_security_group_rule.default_ingress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | -| [random_id.snapshot_identifier](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | -| [random_password.master_password](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_security_group_rule.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource | | [aws_iam_policy_document.monitoring_rds_assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_partition.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/partition) | data source | @@ -270,8 +263,6 @@ No modules. |------|-------------|------|---------|:--------:| | [allocated\_storage](#input\_allocated\_storage) | The amount of storage in gibibytes (GiB) to allocate to each DB instance in the Multi-AZ DB cluster. (This setting is required to create a Multi-AZ DB cluster) | `number` | `null` | no | | [allow\_major\_version\_upgrade](#input\_allow\_major\_version\_upgrade) | Enable to allow major engine version upgrades when changing engine versions. Defaults to `false` | `bool` | `false` | no | -| [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | A list of CIDR blocks which are allowed to access the database | `list(string)` | `[]` | no | -| [allowed\_security\_groups](#input\_allowed\_security\_groups) | A list of Security Group ID's to allow access to | `list(string)` | `[]` | no | | [apply\_immediately](#input\_apply\_immediately) | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window. Default is `false` | `bool` | `null` | no | | [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. Default `true` | `bool` | `null` | no | | [autoscaling\_enabled](#input\_autoscaling\_enabled) | Determines whether autoscaling of the cluster read replicas is enabled | `bool` | `false` | no | @@ -293,13 +284,12 @@ No modules. | [cluster\_timeouts](#input\_cluster\_timeouts) | Create, update, and delete timeout configurations for the cluster | `map(string)` | `{}` | no | | [cluster\_use\_name\_prefix](#input\_cluster\_use\_name\_prefix) | Whether to use `name` as a prefix for the cluster | `bool` | `false` | no | | [copy\_tags\_to\_snapshot](#input\_copy\_tags\_to\_snapshot) | Copy all Cluster `tags` to snapshots | `bool` | `null` | no | +| [create](#input\_create) | Whether cluster should be created (affects nearly all resources) | `bool` | `true` | no | | [create\_cloudwatch\_log\_group](#input\_create\_cloudwatch\_log\_group) | Determines whether a CloudWatch log group is created for each `enabled_cloudwatch_logs_exports` | `bool` | `false` | no | -| [create\_cluster](#input\_create\_cluster) | Whether cluster should be created (affects nearly all resources) | `bool` | `true` | no | | [create\_db\_cluster\_parameter\_group](#input\_create\_db\_cluster\_parameter\_group) | Determines whether a cluster parameter should be created or use existing | `bool` | `false` | no | | [create\_db\_parameter\_group](#input\_create\_db\_parameter\_group) | Determines whether a DB parameter should be created or use existing | `bool` | `false` | no | -| [create\_db\_subnet\_group](#input\_create\_db\_subnet\_group) | Determines whether to create the database subnet group or use existing | `bool` | `true` | no | +| [create\_db\_subnet\_group](#input\_create\_db\_subnet\_group) | Determines whether to create the database subnet group or use existing | `bool` | `false` | no | | [create\_monitoring\_role](#input\_create\_monitoring\_role) | Determines whether to create the IAM role for RDS enhanced monitoring | `bool` | `true` | no | -| [create\_random\_password](#input\_create\_random\_password) | Determines whether to create random password for RDS primary cluster | `bool` | `true` | no | | [create\_security\_group](#input\_create\_security\_group) | Determines whether to create security group for RDS cluster | `bool` | `true` | no | | [database\_name](#input\_database\_name) | Name for an automatically created database on cluster creation | `string` | `null` | no | | [db\_cluster\_db\_instance\_parameter\_group\_name](#input\_db\_cluster\_db\_instance\_parameter\_group\_name) | Instance parameter group to associate with all instances of the DB cluster. The `db_cluster_db_instance_parameter_group_name` is only valid in combination with `allow_major_version_upgrade` | `string` | `null` | no | @@ -323,7 +313,7 @@ No modules. | [engine](#input\_engine) | The name of the database engine to be used for this DB cluster. Defaults to `aurora`. Valid Values: `aurora`, `aurora-mysql`, `aurora-postgresql` | `string` | `null` | no | | [engine\_mode](#input\_engine\_mode) | The database engine mode. Valid values: `global`, `multimaster`, `parallelquery`, `provisioned`, `serverless`. Defaults to: `provisioned` | `string` | `"provisioned"` | no | | [engine\_version](#input\_engine\_version) | The database engine version. Updating this argument results in an outage | `string` | `null` | no | -| [final\_snapshot\_identifier\_prefix](#input\_final\_snapshot\_identifier\_prefix) | The prefix name to use when creating a final snapshot on cluster destroy; a 8 random digits are appended to name to ensure it's unique | `string` | `"final"` | no | +| [final\_snapshot\_identifier](#input\_final\_snapshot\_identifier) | The name of your final DB snapshot when this DB cluster is deleted. If omitted, no final snapshot will be made | `string` | `null` | no | | [global\_cluster\_identifier](#input\_global\_cluster\_identifier) | The global cluster identifier specified on `aws_rds_global_cluster` | `string` | `null` | no | | [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` | `null` | no | | [iam\_role\_description](#input\_iam\_role\_description) | Description of the monitoring role | `string` | `null` | no | @@ -342,8 +332,10 @@ No modules. | [iops](#input\_iops) | The amount of Provisioned IOPS (input/output operations per second) to be initially allocated for each DB instance in the Multi-AZ DB cluster | `number` | `null` | no | | [is\_primary\_cluster](#input\_is\_primary\_cluster) | Determines whether cluster is primary cluster with writer instance (set to `false` for global cluster and replica clusters) | `bool` | `true` | no | | [kms\_key\_id](#input\_kms\_key\_id) | The ARN for the KMS encryption key. When specifying `kms_key_id`, `storage_encrypted` needs to be set to `true` | `string` | `null` | no | -| [master\_password](#input\_master\_password) | Password for the master DB user. Note - when specifying a value here, 'create\_random\_password' should be set to `false` | `string` | `null` | no | -| [master\_username](#input\_master\_username) | Username for the master DB user | `string` | `"root"` | no | +| [manage\_master\_user\_password](#input\_manage\_master\_user\_password) | Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if `master_password` is provided | `bool` | `true` | no | +| [master\_password](#input\_master\_password) | Password for the master DB user. Note that this may show up in logs, and it will be stored in the state file. Required unless `manage_master_user_password` is set to `true` or unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database | `string` | `null` | no | +| [master\_user\_secret\_kms\_key\_id](#input\_master\_user\_secret\_kms\_key\_id) | The Amazon Web Services KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key | `string` | `null` | no | +| [master\_username](#input\_master\_username) | Username for the master DB user. Required unless `manage_master_user_password` is set to `true` or unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database | `string` | `null` | no | | [monitoring\_interval](#input\_monitoring\_interval) | The interval, in seconds, between points when Enhanced Monitoring metrics are collected for instances. Set to `0` to disable. Default is `0` | `number` | `0` | no | | [monitoring\_role\_arn](#input\_monitoring\_role\_arn) | IAM role used by RDS to send enhanced monitoring metrics to CloudWatch | `string` | `""` | no | | [name](#input\_name) | Name used across resources created | `string` | `""` | no | @@ -355,17 +347,16 @@ No modules. | [predefined\_metric\_type](#input\_predefined\_metric\_type) | The metric type to scale on. Valid values are `RDSReaderAverageCPUUtilization` and `RDSReaderAverageDatabaseConnections` | `string` | `"RDSReaderAverageCPUUtilization"` | no | | [preferred\_backup\_window](#input\_preferred\_backup\_window) | The daily time range during which automated backups are created if automated backups are enabled using the `backup_retention_period` parameter. Time in UTC | `string` | `"02:00-03:00"` | no | | [preferred\_maintenance\_window](#input\_preferred\_maintenance\_window) | The weekly time range during which system maintenance can occur, in (UTC) | `string` | `"sun:05:00-sun:06:00"` | no | -| [publicly\_accessible](#input\_publicly\_accessible) | Determines whether instances are publicly accessible. Default false | `bool` | `null` | no | +| [publicly\_accessible](#input\_publicly\_accessible) | Determines whether instances are publicly accessible. Default `false` | `bool` | `null` | no | | [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no | -| [random\_password\_length](#input\_random\_password\_length) | Length of random password to create. Defaults to `10` | `number` | `10` | no | | [replication\_source\_identifier](#input\_replication\_source\_identifier) | ARN of a source DB cluster or DB instance if this DB cluster is to be created as a Read Replica | `string` | `null` | no | | [restore\_to\_point\_in\_time](#input\_restore\_to\_point\_in\_time) | Map of nested attributes for cloning Aurora cluster | `map(string)` | `{}` | no | | [s3\_import](#input\_s3\_import) | Configuration map used to restore from a Percona Xtrabackup in S3 (only MySQL is supported) | `map(string)` | `{}` | no | | [scaling\_configuration](#input\_scaling\_configuration) | Map of nested attributes with scaling properties. Only valid when `engine_mode` is set to `serverless` | `map(string)` | `{}` | no | | [security\_group\_description](#input\_security\_group\_description) | The description of the security group. If value is set to empty string it will contain cluster name in the description | `string` | `null` | no | -| [security\_group\_egress\_rules](#input\_security\_group\_egress\_rules) | A map of security group egress rule definitions to add to the security group created | `map(any)` | `{}` | no | +| [security\_group\_rules](#input\_security\_group\_rules) | Map of security group rules to add to the cluster security group created | `any` | `{}` | no | | [security\_group\_tags](#input\_security\_group\_tags) | Additional tags for the security group | `map(string)` | `{}` | no | -| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`name`) is used as a prefix | `bool` | `true` | no | +| [security\_group\_use\_name\_prefix](#input\_security\_group\_use\_name\_prefix) | Determines whether the security group name (`var.name`) is used as a prefix | `bool` | `true` | no | | [serverlessv2\_scaling\_configuration](#input\_serverlessv2\_scaling\_configuration) | Map of nested attributes with serverless v2 scaling properties. Only valid when `engine_mode` is set to `provisioned` | `map(string)` | `{}` | no | | [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | Determines whether a final snapshot is created before the cluster is deleted. If true is specified, no snapshot is created | `bool` | `false` | no | | [snapshot\_identifier](#input\_snapshot\_identifier) | Specifies whether or not to create this cluster from a snapshot. You can use either the name or ARN when specifying a DB cluster snapshot, or the ARN when specifying a DB snapshot | `string` | `null` | no | @@ -375,7 +366,7 @@ No modules. | [subnets](#input\_subnets) | List of subnet IDs used by database subnet group created | `list(string)` | `[]` | no | | [tags](#input\_tags) | A map of tags to add to all resources | `map(string)` | `{}` | no | | [vpc\_id](#input\_vpc\_id) | ID of the VPC where to create security group | `string` | `""` | no | -| [vpc\_security\_group\_ids](#input\_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 | +| [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | List of VPC security groups to associate to the cluster in addition to the security group created | `list(string)` | `[]` | no | ## Outputs @@ -390,6 +381,7 @@ No modules. | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | | [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | diff --git a/UPGRADE-8.0.md b/UPGRADE-8.0.md new file mode 100644 index 00000000..754cd5f6 --- /dev/null +++ b/UPGRADE-8.0.md @@ -0,0 +1,131 @@ +# Upgrade from v7.x to v8.x + +If you have any questions regarding this upgrade process, please consult the `examples` directory. +If you find a bug, please open an issue with supporting configuration to reproduce. + +## List of backwards incompatible changes + +- With RDS now supporting the [integration with SecretsManager to manage the master user password](https://aws.amazon.com/about-aws/whats-new/2022/12/amazon-rds-integration-aws-secrets-manager/), the ability to generate a random password has been removed from this module. This is the preferred and strongly recommended route to mange the password since it keeps the password out of the Terraform state and allows for the password to be rotated automatically. +- Support for generating a random snapshot identifier has been removed. The AWS provider has been updated to [enforce a conflict between `snapshot_identifier` and `global_cluster_identifier`](https://github.com/hashicorp/terraform-provider-aws/pull/30158) which makes this feature challenging to support; which it has already been challenging to support in the past and often catching users off guard. Instead, the module now defaults to `null` for both of these values and puts the control back in user's hands if they wish to set a value for one of these arguments. +- The default value for `create_db_subnet_group` has changed from `true` to `false` - typically, a common/shared DB subnet group is utilized since there are no real tangible benefits to creating a new one for each DB cluster +- `allowed_security_groups`, `allowed_cidr_blocks`, and `security_group_egress_rules` have been removed and replaced with a more generic `security_group_rules` variable which supports both ingress and egress rules to/from all supported resources/destinations (e.g. security groups, CIDR blocks, prefix lists, etc.) +- Minimum supported Terraform version is now 1.0 + +### Variable and output changes + +1. Removed variables: + + - `create_random_password` -> support for random password generation has been removed + - `random_password_length` -> support for random password generation has been removed + - `final_snapshot_identifier_prefix` -> support for random snapshot identifier generation has been removed + - `allowed_security_groups` replaced by `security_group_rules` + - `allowed_cidr_blocks` replaced by `security_group_rules` + - `security_group_egress_rules` replaced by `security_group_rules` + +2. Renamed variables: + + - `create_cluster` -> `create` + +3. Added variables: + + - `manage_master_user_password` + - `master_user_secret_kms_key_id` + - `security_group_rules` + +4. Removed outputs: + + - None + +5. Renamed outputs: + + - None + +6. Added outputs: + + - `cluster_master_user_secret` + +## Upgrade Migrations + +### Before 7.x Example + +```hcl +module "cluster_before" { + source = "terraform-aws-modules/rds-aurora/aws" + version = "~> 7.0" + + # Only the affected attributes are shown + creat_cluster = true + + master_username = "admin" + create_random_password = true + random_password_length = 16 + + create_db_subnet_group = false + db_subnet_group_name = module.vpc.database_subnet_group_name + + create_security_group = true + allowed_security_groups = ["sg-12345678"] + allowed_cidr_blocks = ["10.20.0.0/20"] + security_group_egress_rules = { + to_cidrs = { + cidr_blocks = ["10.33.0.0/28"] + description = "Egress to corporate printer closet" + } + } + + final_snapshot_identifier_prefix = "my-cluster-" + + tags = { + Environment = "dev" + Terraform = "true" + } +} +``` + +### After 8.x Example + +```hcl +module "cluster_after" { + source = "terraform-aws-modules/rds-aurora/aws" + version = "~> 8.0" + + # Only the affected attributes are shown + create = true + + manage_master_user_password = true + + db_subnet_group_name = module.vpc.database_subnet_group_name + + security_group_rules = { + cidr_ingress_ex = { + cidr_blocks = ["10.20.0.0/20"] + } + security_group_ingress_ex = { + source_security_group_id = "sg-12345678" + } + to_the_closet = { + cidr_blocks = ["10.33.0.0/28"] + description = "Egress to corporate printer closet" + } + } + + final_snapshot_identifier = "my-cluster-with-a-bit-of-something-unique" + + tags = { + Environment = "dev" + Terraform = "true" + } +} +``` + +### State Changes + +- None + +#### Security Group Rule(s) Migration + +To upgrade to v8.x, you will need to migrate your security group rules to the new `security_group_rules` variable and data structure. There are three potential avenues to accomplish this: + +1. Perform Terraform state moves `terraform state mv ...`. This has the downside of requiring manual intervention via the Terraform CLI but is still one possiblity. +2. Applying the changes as they are which will result in the old security group ruls being removed and the new rules being added. This has the downside of causing a brief interruption in service which may or may not be tolerable; this is left up to users to decided. +3. In addition to option 2, users can create a new, temporary security group that contains all of the same network access (or more) as the current v6.x security group. Before upgrading your cluster, add this security group to the cluster via the `vpc_security_group_ids` argument which "shadows" the same level of network access while upgrading. Once this security group has been added, you can now safely upgrade from v7.x to v8.x without any network disruption. Once the upgrade is complete, you can remove the temporary security group from the cluster and delete. diff --git a/examples/autoscaling/README.md b/examples/autoscaling/README.md index f984b22d..943a2325 100644 --- a/examples/autoscaling/README.md +++ b/examples/autoscaling/README.md @@ -19,14 +19,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.30 | +| [aws](#provider\_aws) | ~> 4.61 | ## Modules @@ -34,14 +34,13 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [aurora](#module\_aurora) | ../../ | n/a | | [disabled\_aurora](#module\_disabled\_aurora) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources | Name | Type | |------|------| -| [aws_db_parameter_group.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | -| [aws_rds_cluster_parameter_group.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs @@ -59,14 +58,17 @@ No inputs. | [cluster\_hosted\_zone\_id](#output\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | -| [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | -| [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | | [cluster\_reader\_endpoint](#output\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | | [cluster\_resource\_id](#output\_cluster\_resource\_id) | The RDS Cluster Resource ID | | [cluster\_role\_associations](#output\_cluster\_role\_associations) | A map of IAM roles associated with the cluster and their attributes | | [db\_cluster\_cloudwatch\_log\_groups](#output\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | +| [db\_cluster\_parameter\_group\_arn](#output\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created | +| [db\_cluster\_parameter\_group\_id](#output\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created | +| [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created | +| [db\_parameter\_group\_id](#output\_db\_parameter\_group\_id) | The ID of the DB parameter group created | | [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name | | [enhanced\_monitoring\_iam\_role\_arn](#output\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the enhanced monitoring role | | [enhanced\_monitoring\_iam\_role\_name](#output\_enhanced\_monitoring\_iam\_role\_name) | The name of the enhanced monitoring role | diff --git a/examples/autoscaling/main.tf b/examples/autoscaling/main.tf index 1e45c7ac..2c877b12 100644 --- a/examples/autoscaling/main.tf +++ b/examples/autoscaling/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -22,15 +27,17 @@ module "aurora" { name = local.name engine = "aurora-postgresql" - engine_version = "11.12" + engine_version = "14.5" instance_class = "db.r6g.large" instances = { 1 = {} } - vpc_id = module.vpc.vpc_id - db_subnet_group_name = module.vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } autoscaling_enabled = true autoscaling_min_capacity = 1 @@ -46,31 +53,15 @@ module "aurora" { apply_immediately = true skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example.id enabled_cloudwatch_logs_exports = ["postgresql"] tags = local.tags } -resource "aws_db_parameter_group" "example" { - name_prefix = "${local.name}-aurora-db-postgres11-parameter-group" - family = "aurora-postgresql11" - description = "${local.name}-aurora-db-postgres11-parameter-group" - tags = local.tags -} - -resource "aws_rds_cluster_parameter_group" "example" { - name_prefix = "${local.name}-aurora-postgres11-cluster-parameter-group" - family = "aurora-postgresql11" - description = "${local.name}-aurora-postgres11-cluster-parameter-group" - tags = local.tags -} - module "disabled_aurora" { source = "../../" - create_cluster = false + create = false } ################################################################################ @@ -79,20 +70,15 @@ module "disabled_aurora" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - enable_dns_support = true - enable_dns_hostnames = true - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - enable_nat_gateway = false # Disabled NAT to be able to run this example quicker + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/autoscaling/outputs.tf b/examples/autoscaling/outputs.tf index 1e887a1a..2deaba75 100644 --- a/examples/autoscaling/outputs.tf +++ b/examples/autoscaling/outputs.tf @@ -1,10 +1,16 @@ -# aws_db_subnet_group +################################################################################ +# DB Subnet Group +################################################################################ + output "db_subnet_group_name" { description = "The db subnet group name" value = module.aurora.db_subnet_group_name } -# aws_rds_cluster +################################################################################ +# Cluster +################################################################################ + output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora.cluster_arn @@ -40,7 +46,6 @@ output "cluster_engine_version_actual" { value = module.aurora.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora.cluster_database_name @@ -51,16 +56,9 @@ output "cluster_port" { value = module.aurora.cluster_port } -output "cluster_master_password" { - description = "The database master password" - value = module.aurora.cluster_master_password - sensitive = true -} - -output "cluster_master_username" { - description = "The database master username" - value = module.aurora.cluster_master_username - sensitive = true +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora.cluster_master_user_secret } output "cluster_hosted_zone_id" { @@ -68,25 +66,37 @@ output "cluster_hosted_zone_id" { value = module.aurora.cluster_hosted_zone_id } -# aws_rds_cluster_instances +################################################################################ +# Cluster Instance(s) +################################################################################ + output "cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora.cluster_instances } -# aws_rds_cluster_endpoint +################################################################################ +# Cluster Endpoint(s) +################################################################################ + output "additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora.additional_cluster_endpoints } -# aws_rds_cluster_role_association +################################################################################ +# Cluster IAM Roles +################################################################################ + output "cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora.cluster_role_associations } -# Enhanced monitoring role +################################################################################ +# Enhanced Monitoring +################################################################################ + output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora.enhanced_monitoring_iam_role_name @@ -102,13 +112,47 @@ output "enhanced_monitoring_iam_role_unique_id" { value = module.aurora.enhanced_monitoring_iam_role_unique_id } -# aws_security_group +################################################################################ +# Security Group +################################################################################ + output "security_group_id" { description = "The security group ID of the cluster" value = module.aurora.security_group_id } -# Cloudwatch log groups +################################################################################ +# Cluster Parameter Group +################################################################################ + +output "db_cluster_parameter_group_arn" { + description = "The ARN of the DB cluster parameter group created" + value = module.aurora.db_cluster_parameter_group_arn +} + +output "db_cluster_parameter_group_id" { + description = "The ID of the DB cluster parameter group created" + value = module.aurora.db_cluster_parameter_group_id +} + +################################################################################ +# DB Parameter Group +################################################################################ + +output "db_parameter_group_arn" { + description = "The ARN of the DB parameter group created" + value = module.aurora.db_parameter_group_arn +} + +output "db_parameter_group_id" { + description = "The ID of the DB parameter group created" + value = module.aurora.db_parameter_group_id +} + +################################################################################ +# CloudWatch Log Group +################################################################################ + output "db_cluster_cloudwatch_log_groups" { description = "Map of CloudWatch log groups created and their attributes" value = module.aurora.db_cluster_cloudwatch_log_groups diff --git a/examples/autoscaling/versions.tf b/examples/autoscaling/versions.tf index f23452ce..bda84dba 100644 --- a/examples/autoscaling/versions.tf +++ b/examples/autoscaling/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" + version = "~> 4.61" } } } diff --git a/examples/global-cluster/README.md b/examples/global-cluster/README.md index 00784618..d682bf01 100644 --- a/examples/global-cluster/README.md +++ b/examples/global-cluster/README.md @@ -19,15 +19,17 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | +| [random](#requirement\_random) | >= 2.2 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.30 | -| [aws.secondary](#provider\_aws.secondary) | >= 4.30 | +| [aws](#provider\_aws) | ~> 4.61 | +| [aws.secondary](#provider\_aws.secondary) | ~> 4.61 | +| [random](#provider\_random) | >= 2.2 | ## Modules @@ -35,8 +37,8 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [aurora\_primary](#module\_aurora\_primary) | ../../ | n/a | | [aurora\_secondary](#module\_aurora\_secondary) | ../../ | n/a | -| [primary\_vpc](#module\_primary\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | -| [secondary\_vpc](#module\_secondary\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [primary\_vpc](#module\_primary\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | +| [secondary\_vpc](#module\_secondary\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources @@ -45,6 +47,9 @@ Note that this example may create resources which cost money. Run `terraform des | [aws_kms_key.primary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_kms_key.secondary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/kms_key) | resource | | [aws_rds_global_cluster.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_global_cluster) | resource | +| [random_password.master](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_availability_zones.primary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | +| [aws_availability_zones.secondary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_iam_policy_document.rds](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -56,46 +61,52 @@ No inputs. | Name | Description | |------|-------------| -| [mysql\_additional\_cluster\_endpoints](#output\_mysql\_additional\_cluster\_endpoints) | A map of additional cluster endpoints and their attributes | -| [mysql\_cluster\_arn](#output\_mysql\_cluster\_arn) | Amazon Resource Name (ARN) of cluster | -| [mysql\_cluster\_cloudwatch\_log\_groups](#output\_mysql\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | -| [mysql\_cluster\_database\_name](#output\_mysql\_cluster\_database\_name) | Name for an automatically created database on cluster creation | -| [mysql\_cluster\_endpoint](#output\_mysql\_cluster\_endpoint) | Writer endpoint for the cluster | -| [mysql\_cluster\_engine\_version\_actual](#output\_mysql\_cluster\_engine\_version\_actual) | The running version of the cluster database | -| [mysql\_cluster\_hosted\_zone\_id](#output\_mysql\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | -| [mysql\_cluster\_id](#output\_mysql\_cluster\_id) | The RDS Cluster Identifier | -| [mysql\_cluster\_instances](#output\_mysql\_cluster\_instances) | A map of cluster instances and their attributes | -| [mysql\_cluster\_master\_password](#output\_mysql\_cluster\_master\_password) | The database master password | -| [mysql\_cluster\_master\_username](#output\_mysql\_cluster\_master\_username) | The database master username | -| [mysql\_cluster\_members](#output\_mysql\_cluster\_members) | List of RDS Instances that are a part of this cluster | -| [mysql\_cluster\_port](#output\_mysql\_cluster\_port) | The database port | -| [mysql\_cluster\_reader\_endpoint](#output\_mysql\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | -| [mysql\_cluster\_resource\_id](#output\_mysql\_cluster\_resource\_id) | The RDS Cluster Resource ID | -| [mysql\_cluster\_role\_associations](#output\_mysql\_cluster\_role\_associations) | A map of IAM roles associated with the cluster and their attributes | -| [mysql\_db\_subnet\_group\_name](#output\_mysql\_db\_subnet\_group\_name) | The db subnet group name | -| [mysql\_enhanced\_monitoring\_iam\_role\_arn](#output\_mysql\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the enhanced monitoring role | -| [mysql\_enhanced\_monitoring\_iam\_role\_name](#output\_mysql\_enhanced\_monitoring\_iam\_role\_name) | The name of the enhanced monitoring role | -| [mysql\_enhanced\_monitoring\_iam\_role\_unique\_id](#output\_mysql\_enhanced\_monitoring\_iam\_role\_unique\_id) | Stable and unique string identifying the enhanced monitoring role | -| [mysql\_security\_group\_id](#output\_mysql\_security\_group\_id) | The security group ID of the cluster | | [primary\_additional\_cluster\_endpoints](#output\_primary\_additional\_cluster\_endpoints) | A map of additional cluster endpoints and their attributes | | [primary\_cluster\_arn](#output\_primary\_cluster\_arn) | Amazon Resource Name (ARN) of cluster | -| [primary\_cluster\_cloudwatch\_log\_groups](#output\_primary\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | | [primary\_cluster\_database\_name](#output\_primary\_cluster\_database\_name) | Name for an automatically created database on cluster creation | | [primary\_cluster\_endpoint](#output\_primary\_cluster\_endpoint) | Writer endpoint for the cluster | | [primary\_cluster\_engine\_version\_actual](#output\_primary\_cluster\_engine\_version\_actual) | The running version of the cluster database | | [primary\_cluster\_hosted\_zone\_id](#output\_primary\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [primary\_cluster\_id](#output\_primary\_cluster\_id) | The RDS Cluster Identifier | | [primary\_cluster\_instances](#output\_primary\_cluster\_instances) | A map of cluster instances and their attributes | -| [primary\_cluster\_master\_password](#output\_primary\_cluster\_master\_password) | The database master password | -| [primary\_cluster\_master\_username](#output\_primary\_cluster\_master\_username) | The database master username | +| [primary\_cluster\_master\_user\_secret](#output\_primary\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [primary\_cluster\_members](#output\_primary\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [primary\_cluster\_port](#output\_primary\_cluster\_port) | The database port | | [primary\_cluster\_reader\_endpoint](#output\_primary\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | | [primary\_cluster\_resource\_id](#output\_primary\_cluster\_resource\_id) | The RDS Cluster Resource ID | | [primary\_cluster\_role\_associations](#output\_primary\_cluster\_role\_associations) | A map of IAM roles associated with the cluster and their attributes | +| [primary\_db\_cluster\_cloudwatch\_log\_groups](#output\_primary\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | +| [primary\_db\_cluster\_parameter\_group\_arn](#output\_primary\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created | +| [primary\_db\_cluster\_parameter\_group\_id](#output\_primary\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created | +| [primary\_db\_parameter\_group\_arn](#output\_primary\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created | +| [primary\_db\_parameter\_group\_id](#output\_primary\_db\_parameter\_group\_id) | The ID of the DB parameter group created | | [primary\_db\_subnet\_group\_name](#output\_primary\_db\_subnet\_group\_name) | The db subnet group name | | [primary\_enhanced\_monitoring\_iam\_role\_arn](#output\_primary\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the enhanced monitoring role | | [primary\_enhanced\_monitoring\_iam\_role\_name](#output\_primary\_enhanced\_monitoring\_iam\_role\_name) | The name of the enhanced monitoring role | | [primary\_enhanced\_monitoring\_iam\_role\_unique\_id](#output\_primary\_enhanced\_monitoring\_iam\_role\_unique\_id) | Stable and unique string identifying the enhanced monitoring role | | [primary\_security\_group\_id](#output\_primary\_security\_group\_id) | The security group ID of the cluster | +| [secondary\_additional\_cluster\_endpoints](#output\_secondary\_additional\_cluster\_endpoints) | A map of additional cluster endpoints and their attributes | +| [secondary\_cluster\_arn](#output\_secondary\_cluster\_arn) | Amazon Resource Name (ARN) of cluster | +| [secondary\_cluster\_database\_name](#output\_secondary\_cluster\_database\_name) | Name for an automatically created database on cluster creation | +| [secondary\_cluster\_endpoint](#output\_secondary\_cluster\_endpoint) | Writer endpoint for the cluster | +| [secondary\_cluster\_engine\_version\_actual](#output\_secondary\_cluster\_engine\_version\_actual) | The running version of the cluster database | +| [secondary\_cluster\_hosted\_zone\_id](#output\_secondary\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | +| [secondary\_cluster\_id](#output\_secondary\_cluster\_id) | The RDS Cluster Identifier | +| [secondary\_cluster\_instances](#output\_secondary\_cluster\_instances) | A map of cluster instances and their attributes | +| [secondary\_cluster\_master\_user\_secret](#output\_secondary\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | +| [secondary\_cluster\_members](#output\_secondary\_cluster\_members) | List of RDS Instances that are a part of this cluster | +| [secondary\_cluster\_port](#output\_secondary\_cluster\_port) | The database port | +| [secondary\_cluster\_reader\_endpoint](#output\_secondary\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | +| [secondary\_cluster\_resource\_id](#output\_secondary\_cluster\_resource\_id) | The RDS Cluster Resource ID | +| [secondary\_cluster\_role\_associations](#output\_secondary\_cluster\_role\_associations) | A map of IAM roles associated with the cluster and their attributes | +| [secondary\_db\_cluster\_cloudwatch\_log\_groups](#output\_secondary\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | +| [secondary\_db\_cluster\_parameter\_group\_arn](#output\_secondary\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created | +| [secondary\_db\_cluster\_parameter\_group\_id](#output\_secondary\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created | +| [secondary\_db\_parameter\_group\_arn](#output\_secondary\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created | +| [secondary\_db\_parameter\_group\_id](#output\_secondary\_db\_parameter\_group\_id) | The ID of the DB parameter group created | +| [secondary\_db\_subnet\_group\_name](#output\_secondary\_db\_subnet\_group\_name) | The db subnet group name | +| [secondary\_enhanced\_monitoring\_iam\_role\_arn](#output\_secondary\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the enhanced monitoring role | +| [secondary\_enhanced\_monitoring\_iam\_role\_name](#output\_secondary\_enhanced\_monitoring\_iam\_role\_name) | The name of the enhanced monitoring role | +| [secondary\_enhanced\_monitoring\_iam\_role\_unique\_id](#output\_secondary\_enhanced\_monitoring\_iam\_role\_unique\_id) | Stable and unique string identifying the enhanced monitoring role | +| [secondary\_security\_group\_id](#output\_secondary\_security\_group\_id) | The security group ID of the cluster | diff --git a/examples/global-cluster/main.tf b/examples/global-cluster/main.tf index 9f261330..7f911465 100644 --- a/examples/global-cluster/main.tf +++ b/examples/global-cluster/main.tf @@ -1,23 +1,28 @@ provider "aws" { - region = local.primary.region + region = local.primary_region } provider "aws" { alias = "secondary" - region = local.secondary.region + region = local.secondary_region +} + +data "aws_caller_identity" "current" {} +data "aws_availability_zones" "primary" {} +data "aws_availability_zones" "secondary" { + provider = aws.secondary } locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" - primary = { - region = "eu-west-1" - cidr_prefix = "10.99" - } - secondary = { - region = "us-east-1" - cidr_prefix = "10.98" - } + primary_region = "eu-west-1" + primary_vpc_cidr = "10.0.0.0/16" + primary_azs = slice(data.aws_availability_zones.primary.names, 0, 3) + + secondary_region = "us-east-1" + secondary_vpc_cidr = "10.1.0.0/16" + secondary_azs = slice(data.aws_availability_zones.secondary.names, 0, 3) tags = { Example = local.name @@ -26,8 +31,6 @@ locals { } } -data "aws_caller_identity" "current" {} - ################################################################################ # RDS Aurora Module ################################################################################ @@ -35,7 +38,7 @@ data "aws_caller_identity" "current" {} resource "aws_rds_global_cluster" "this" { global_cluster_identifier = local.name engine = "aurora-postgresql" - engine_version = "11.12" + engine_version = "14.5" database_name = "example_db" storage_encrypted = true } @@ -52,11 +55,16 @@ module "aurora_primary" { instances = { for i in range(2) : i => {} } kms_key_id = aws_kms_key.primary.arn - vpc_id = module.primary_vpc.vpc_id - db_subnet_group_name = module.primary_vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.primary_vpc.private_subnets_cidr_blocks + vpc_id = module.primary_vpc.vpc_id + db_subnet_group_name = module.primary_vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.primary_vpc.private_subnets_cidr_blocks + } + } + + # Global clusters do not support managed master user password + master_password = random_password.master.result skip_final_snapshot = true @@ -74,16 +82,21 @@ module "aurora_secondary" { engine = aws_rds_global_cluster.this.engine engine_version = aws_rds_global_cluster.this.engine_version global_cluster_identifier = aws_rds_global_cluster.this.id - source_region = local.primary.region + source_region = local.primary_region instance_class = "db.r6g.large" instances = { for i in range(2) : i => {} } kms_key_id = aws_kms_key.secondary.arn - vpc_id = module.secondary_vpc.vpc_id - db_subnet_group_name = module.secondary_vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.secondary_vpc.private_subnets_cidr_blocks + vpc_id = module.secondary_vpc.vpc_id + db_subnet_group_name = module.secondary_vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.secondary_vpc.private_subnets_cidr_blocks + } + } + + # Global clusters do not support managed master user password + master_password = random_password.master.result skip_final_snapshot = true @@ -98,34 +111,40 @@ module "aurora_secondary" { # Supporting Resources ################################################################################ +resource "random_password" "master" { + length = 20 + special = false +} + module "primary_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "${local.primary.cidr_prefix}.0.0/18" + cidr = local.primary_vpc_cidr - azs = ["${local.primary.region}a", "${local.primary.region}b", "${local.primary.region}c"] - public_subnets = ["${local.primary.cidr_prefix}.0.0/24", "${local.primary.cidr_prefix}.1.0/24", "${local.primary.cidr_prefix}.2.0/24"] - private_subnets = ["${local.primary.cidr_prefix}.3.0/24", "${local.primary.cidr_prefix}.4.0/24", "${local.primary.cidr_prefix}.5.0/24"] - database_subnets = ["${local.primary.cidr_prefix}.7.0/24", "${local.primary.cidr_prefix}.8.0/24", "${local.primary.cidr_prefix}.9.0/24"] + azs = local.primary_azs + public_subnets = [for k, v in local.primary_azs : cidrsubnet(local.primary_vpc_cidr, 8, k)] + private_subnets = [for k, v in local.primary_azs : cidrsubnet(local.primary_vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.primary_azs : cidrsubnet(local.primary_vpc_cidr, 8, k + 6)] tags = local.tags } + module "secondary_vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" providers = { aws = aws.secondary } name = local.name - cidr = "${local.secondary.cidr_prefix}.0.0/18" + cidr = local.secondary_vpc_cidr - azs = ["${local.secondary.region}a", "${local.secondary.region}b", "${local.secondary.region}c"] - public_subnets = ["${local.secondary.cidr_prefix}.0.0/24", "${local.secondary.cidr_prefix}.1.0/24", "${local.secondary.cidr_prefix}.2.0/24"] - private_subnets = ["${local.secondary.cidr_prefix}.3.0/24", "${local.secondary.cidr_prefix}.4.0/24", "${local.secondary.cidr_prefix}.5.0/24"] - database_subnets = ["${local.secondary.cidr_prefix}.7.0/24", "${local.secondary.cidr_prefix}.8.0/24", "${local.secondary.cidr_prefix}.9.0/24"] + azs = local.secondary_azs + public_subnets = [for k, v in local.secondary_azs : cidrsubnet(local.secondary_vpc_cidr, 8, k)] + private_subnets = [for k, v in local.secondary_azs : cidrsubnet(local.secondary_vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.secondary_azs : cidrsubnet(local.secondary_vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/global-cluster/outputs.tf b/examples/global-cluster/outputs.tf index ef08560d..19aac5dc 100644 --- a/examples/global-cluster/outputs.tf +++ b/examples/global-cluster/outputs.tf @@ -2,13 +2,11 @@ # RDS Aurora Module - Primary ################################################################################ -# aws_db_subnet_group output "primary_db_subnet_group_name" { description = "The db subnet group name" value = module.aurora_primary.db_subnet_group_name } -# aws_rds_cluster output "primary_cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora_primary.cluster_arn @@ -44,7 +42,6 @@ output "primary_cluster_engine_version_actual" { value = module.aurora_primary.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "primary_cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora_primary.cluster_database_name @@ -55,16 +52,9 @@ output "primary_cluster_port" { value = module.aurora_primary.cluster_port } -output "primary_cluster_master_password" { - description = "The database master password" - value = module.aurora_primary.cluster_master_password - sensitive = true -} - -output "primary_cluster_master_username" { - description = "The database master username" - value = module.aurora_primary.cluster_master_username - sensitive = true +output "primary_cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora_primary.cluster_master_user_secret } output "primary_cluster_hosted_zone_id" { @@ -72,25 +62,21 @@ output "primary_cluster_hosted_zone_id" { value = module.aurora_primary.cluster_hosted_zone_id } -# aws_rds_cluster_instances output "primary_cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora_primary.cluster_instances } -# aws_rds_cluster_endpoint output "primary_additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora_primary.additional_cluster_endpoints } -# aws_rds_cluster_role_association output "primary_cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora_primary.cluster_role_associations } -# Enhanced monitoring role output "primary_enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora_primary.enhanced_monitoring_iam_role_name @@ -106,14 +92,32 @@ output "primary_enhanced_monitoring_iam_role_unique_id" { value = module.aurora_primary.enhanced_monitoring_iam_role_unique_id } -# aws_security_group output "primary_security_group_id" { description = "The security group ID of the cluster" value = module.aurora_primary.security_group_id } -# Cloudwatch log groups -output "primary_cluster_cloudwatch_log_groups" { +output "primary_db_cluster_parameter_group_arn" { + description = "The ARN of the DB cluster parameter group created" + value = module.aurora_primary.db_cluster_parameter_group_arn +} + +output "primary_db_cluster_parameter_group_id" { + description = "The ID of the DB cluster parameter group created" + value = module.aurora_primary.db_cluster_parameter_group_id +} + +output "primary_db_parameter_group_arn" { + description = "The ARN of the DB parameter group created" + value = module.aurora_primary.db_parameter_group_arn +} + +output "primary_db_parameter_group_id" { + description = "The ID of the DB parameter group created" + value = module.aurora_primary.db_parameter_group_id +} + +output "primary_db_cluster_cloudwatch_log_groups" { description = "Map of CloudWatch log groups created and their attributes" value = module.aurora_primary.db_cluster_cloudwatch_log_groups } @@ -122,118 +126,122 @@ output "primary_cluster_cloudwatch_log_groups" { # RDS Aurora Module - Secondary ################################################################################ -# aws_db_subnet_group -output "mysql_db_subnet_group_name" { +output "secondary_db_subnet_group_name" { description = "The db subnet group name" value = module.aurora_secondary.db_subnet_group_name } -# aws_rds_cluster -output "mysql_cluster_arn" { +output "secondary_cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora_secondary.cluster_arn } -output "mysql_cluster_id" { +output "secondary_cluster_id" { description = "The RDS Cluster Identifier" value = module.aurora_secondary.cluster_id } -output "mysql_cluster_resource_id" { +output "secondary_cluster_resource_id" { description = "The RDS Cluster Resource ID" value = module.aurora_secondary.cluster_resource_id } -output "mysql_cluster_members" { +output "secondary_cluster_members" { description = "List of RDS Instances that are a part of this cluster" value = module.aurora_secondary.cluster_members } -output "mysql_cluster_endpoint" { +output "secondary_cluster_endpoint" { description = "Writer endpoint for the cluster" value = module.aurora_secondary.cluster_endpoint } -output "mysql_cluster_reader_endpoint" { +output "secondary_cluster_reader_endpoint" { description = "A read-only endpoint for the cluster, automatically load-balanced across replicas" value = module.aurora_secondary.cluster_reader_endpoint } -output "mysql_cluster_engine_version_actual" { +output "secondary_cluster_engine_version_actual" { description = "The running version of the cluster database" value = module.aurora_secondary.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output -output "mysql_cluster_database_name" { +output "secondary_cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora_secondary.cluster_database_name } -output "mysql_cluster_port" { +output "secondary_cluster_port" { description = "The database port" value = module.aurora_secondary.cluster_port } -output "mysql_cluster_master_password" { - description = "The database master password" - value = module.aurora_secondary.cluster_master_password - sensitive = true +output "secondary_cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora_secondary.cluster_master_user_secret } -output "mysql_cluster_master_username" { - description = "The database master username" - value = module.aurora_secondary.cluster_master_username - sensitive = true -} - -output "mysql_cluster_hosted_zone_id" { +output "secondary_cluster_hosted_zone_id" { description = "The Route53 Hosted Zone ID of the endpoint" value = module.aurora_secondary.cluster_hosted_zone_id } -# aws_rds_cluster_instances -output "mysql_cluster_instances" { +output "secondary_cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora_secondary.cluster_instances } -# aws_rds_cluster_endpoint -output "mysql_additional_cluster_endpoints" { +output "secondary_additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora_secondary.additional_cluster_endpoints } -# aws_rds_cluster_role_association -output "mysql_cluster_role_associations" { +output "secondary_cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora_secondary.cluster_role_associations } -# Enhanced monitoring role -output "mysql_enhanced_monitoring_iam_role_name" { +output "secondary_enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora_secondary.enhanced_monitoring_iam_role_name } -output "mysql_enhanced_monitoring_iam_role_arn" { +output "secondary_enhanced_monitoring_iam_role_arn" { description = "The Amazon Resource Name (ARN) specifying the enhanced monitoring role" value = module.aurora_secondary.enhanced_monitoring_iam_role_arn } -output "mysql_enhanced_monitoring_iam_role_unique_id" { +output "secondary_enhanced_monitoring_iam_role_unique_id" { description = "Stable and unique string identifying the enhanced monitoring role" value = module.aurora_secondary.enhanced_monitoring_iam_role_unique_id } -# aws_security_group -output "mysql_security_group_id" { +output "secondary_security_group_id" { description = "The security group ID of the cluster" value = module.aurora_secondary.security_group_id } -# Cloudwatch log group -output "mysql_cluster_cloudwatch_log_groups" { +output "secondary_db_cluster_parameter_group_arn" { + description = "The ARN of the DB cluster parameter group created" + value = module.aurora_secondary.db_cluster_parameter_group_arn +} + +output "secondary_db_cluster_parameter_group_id" { + description = "The ID of the DB cluster parameter group created" + value = module.aurora_secondary.db_cluster_parameter_group_id +} + +output "secondary_db_parameter_group_arn" { + description = "The ARN of the DB parameter group created" + value = module.aurora_secondary.db_parameter_group_arn +} + +output "secondary_db_parameter_group_id" { + description = "The ID of the DB parameter group created" + value = module.aurora_secondary.db_parameter_group_id +} + +output "secondary_db_cluster_cloudwatch_log_groups" { description = "Map of CloudWatch log groups created and their attributes" value = module.aurora_secondary.db_cluster_cloudwatch_log_groups } diff --git a/examples/global-cluster/versions.tf b/examples/global-cluster/versions.tf index f23452ce..2ed760f4 100644 --- a/examples/global-cluster/versions.tf +++ b/examples/global-cluster/versions.tf @@ -1,10 +1,15 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" + version = "~> 4.61" + } + + random = { + source = "hashicorp/random" + version = ">= 2.2" } } } diff --git a/examples/multi-az/README.md b/examples/multi-az/README.md index c52f7241..49fdab9d 100644 --- a/examples/multi-az/README.md +++ b/examples/multi-az/README.md @@ -19,23 +19,27 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers -No providers. +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 4.61 | ## Modules | Name | Source | Version | |------|--------|---------| | [aurora](#module\_aurora) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources -No resources. +| Name | Type | +|------|------| +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs @@ -53,8 +57,7 @@ No inputs. | [cluster\_hosted\_zone\_id](#output\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | -| [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | -| [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | | [cluster\_reader\_endpoint](#output\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | diff --git a/examples/multi-az/main.tf b/examples/multi-az/main.tf index 1cd04f21..8d61fd98 100644 --- a/examples/multi-az/main.tf +++ b/examples/multi-az/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -21,15 +26,13 @@ module "aurora" { source = "../../" name = local.name - engine = "postgres" # This uses RDS, not Aurora - engine_version = "13.7" + engine = "postgres" # This uses RDS engine, not Aurora + engine_version = "14.5" - vpc_id = module.vpc.vpc_id - subnets = module.vpc.private_subnets + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name - create_db_cluster_parameter_group = true - db_cluster_parameter_group_family = "postgres13" - enabled_cloudwatch_logs_exports = ["postgresql"] + enabled_cloudwatch_logs_exports = ["postgresql"] # Multi-AZ availability_zones = module.vpc.azs @@ -38,6 +41,8 @@ module "aurora" { iops = 2500 storage_type = "io1" + skip_final_snapshot = true + tags = local.tags } @@ -47,21 +52,15 @@ module "aurora" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - enable_dns_support = true - enable_dns_hostnames = true - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - create_database_subnet_group = false - enable_nat_gateway = false # Disabled NAT to be able to run this example quicker + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/multi-az/outputs.tf b/examples/multi-az/outputs.tf index a3304c60..2deaba75 100644 --- a/examples/multi-az/outputs.tf +++ b/examples/multi-az/outputs.tf @@ -1,10 +1,16 @@ -# aws_db_subnet_group +################################################################################ +# DB Subnet Group +################################################################################ + output "db_subnet_group_name" { description = "The db subnet group name" value = module.aurora.db_subnet_group_name } -# aws_rds_cluster +################################################################################ +# Cluster +################################################################################ + output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora.cluster_arn @@ -40,7 +46,6 @@ output "cluster_engine_version_actual" { value = module.aurora.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora.cluster_database_name @@ -51,16 +56,9 @@ output "cluster_port" { value = module.aurora.cluster_port } -output "cluster_master_password" { - description = "The database master password" - value = module.aurora.cluster_master_password - sensitive = true -} - -output "cluster_master_username" { - description = "The database master username" - value = module.aurora.cluster_master_username - sensitive = true +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora.cluster_master_user_secret } output "cluster_hosted_zone_id" { @@ -68,25 +66,37 @@ output "cluster_hosted_zone_id" { value = module.aurora.cluster_hosted_zone_id } -# aws_rds_cluster_instances +################################################################################ +# Cluster Instance(s) +################################################################################ + output "cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora.cluster_instances } -# aws_rds_cluster_endpoint +################################################################################ +# Cluster Endpoint(s) +################################################################################ + output "additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora.additional_cluster_endpoints } -# aws_rds_cluster_role_association +################################################################################ +# Cluster IAM Roles +################################################################################ + output "cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora.cluster_role_associations } -# Enhanced monitoring role +################################################################################ +# Enhanced Monitoring +################################################################################ + output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora.enhanced_monitoring_iam_role_name @@ -102,14 +112,17 @@ output "enhanced_monitoring_iam_role_unique_id" { value = module.aurora.enhanced_monitoring_iam_role_unique_id } -# aws_security_group +################################################################################ +# Security Group +################################################################################ + output "security_group_id" { description = "The security group ID of the cluster" value = module.aurora.security_group_id } ################################################################################ -# Parameter Group +# Cluster Parameter Group ################################################################################ output "db_cluster_parameter_group_arn" { @@ -122,6 +135,10 @@ output "db_cluster_parameter_group_id" { value = module.aurora.db_cluster_parameter_group_id } +################################################################################ +# DB Parameter Group +################################################################################ + output "db_parameter_group_arn" { description = "The ARN of the DB parameter group created" value = module.aurora.db_parameter_group_arn @@ -133,7 +150,7 @@ output "db_parameter_group_id" { } ################################################################################ -# Cloudwatch Log Group +# CloudWatch Log Group ################################################################################ output "db_cluster_cloudwatch_log_groups" { diff --git a/examples/multi-az/versions.tf b/examples/multi-az/versions.tf index f23452ce..bda84dba 100644 --- a/examples/multi-az/versions.tf +++ b/examples/multi-az/versions.tf @@ -1,10 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" + version = "~> 4.61" } } } diff --git a/examples/mysql/README.md b/examples/mysql/README.md index ce05e506..1c5c7d6f 100644 --- a/examples/mysql/README.md +++ b/examples/mysql/README.md @@ -19,28 +19,27 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | -| [random](#requirement\_random) | >= 2.2 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers | Name | Version | |------|---------| -| [random](#provider\_random) | >= 2.2 | +| [aws](#provider\_aws) | ~> 4.61 | ## Modules | Name | Source | Version | |------|--------|---------| | [aurora](#module\_aurora) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources | Name | Type | |------|------| -| [random_password.master](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs @@ -58,8 +57,7 @@ No inputs. | [cluster\_hosted\_zone\_id](#output\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | -| [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | -| [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | | [cluster\_reader\_endpoint](#output\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | diff --git a/examples/mysql/main.tf b/examples/mysql/main.tf index 50bb093e..bcd3ce2e 100644 --- a/examples/mysql/main.tf +++ b/examples/mysql/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -22,7 +27,7 @@ module "aurora" { name = local.name engine = "aurora-mysql" - engine_version = "5.7" + engine_version = "8.0" instances = { 1 = { instance_class = "db.r5.large" @@ -39,22 +44,20 @@ module "aurora" { } } - vpc_id = module.vpc.vpc_id - db_subnet_group_name = module.vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks - - iam_database_authentication_enabled = true - master_password = random_password.master.result - create_random_password = false + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } apply_immediately = true skip_final_snapshot = true create_db_cluster_parameter_group = true db_cluster_parameter_group_name = local.name - db_cluster_parameter_group_family = "aurora-mysql5.7" + db_cluster_parameter_group_family = "aurora-mysql8.0" db_cluster_parameter_group_description = "${local.name} example cluster parameter group" db_cluster_parameter_group_parameters = [ { @@ -98,7 +101,7 @@ module "aurora" { create_db_parameter_group = true db_parameter_group_name = local.name - db_parameter_group_family = "aurora-mysql5.7" + db_parameter_group_family = "aurora-mysql8.0" db_parameter_group_description = "${local.name} example DB parameter group" db_parameter_group_parameters = [ { @@ -137,7 +140,6 @@ module "aurora" { ] enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"] - security_group_use_name_prefix = false tags = local.tags } @@ -146,26 +148,17 @@ module "aurora" { # Supporting Resources ################################################################################ -resource "random_password" "master" { - length = 10 -} - module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - enable_dns_support = true - enable_dns_hostnames = true - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - enable_nat_gateway = false # Disabled NAT to be able to run this example quicker + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/mysql/outputs.tf b/examples/mysql/outputs.tf index a3304c60..2deaba75 100644 --- a/examples/mysql/outputs.tf +++ b/examples/mysql/outputs.tf @@ -1,10 +1,16 @@ -# aws_db_subnet_group +################################################################################ +# DB Subnet Group +################################################################################ + output "db_subnet_group_name" { description = "The db subnet group name" value = module.aurora.db_subnet_group_name } -# aws_rds_cluster +################################################################################ +# Cluster +################################################################################ + output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora.cluster_arn @@ -40,7 +46,6 @@ output "cluster_engine_version_actual" { value = module.aurora.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora.cluster_database_name @@ -51,16 +56,9 @@ output "cluster_port" { value = module.aurora.cluster_port } -output "cluster_master_password" { - description = "The database master password" - value = module.aurora.cluster_master_password - sensitive = true -} - -output "cluster_master_username" { - description = "The database master username" - value = module.aurora.cluster_master_username - sensitive = true +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora.cluster_master_user_secret } output "cluster_hosted_zone_id" { @@ -68,25 +66,37 @@ output "cluster_hosted_zone_id" { value = module.aurora.cluster_hosted_zone_id } -# aws_rds_cluster_instances +################################################################################ +# Cluster Instance(s) +################################################################################ + output "cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora.cluster_instances } -# aws_rds_cluster_endpoint +################################################################################ +# Cluster Endpoint(s) +################################################################################ + output "additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora.additional_cluster_endpoints } -# aws_rds_cluster_role_association +################################################################################ +# Cluster IAM Roles +################################################################################ + output "cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora.cluster_role_associations } -# Enhanced monitoring role +################################################################################ +# Enhanced Monitoring +################################################################################ + output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora.enhanced_monitoring_iam_role_name @@ -102,14 +112,17 @@ output "enhanced_monitoring_iam_role_unique_id" { value = module.aurora.enhanced_monitoring_iam_role_unique_id } -# aws_security_group +################################################################################ +# Security Group +################################################################################ + output "security_group_id" { description = "The security group ID of the cluster" value = module.aurora.security_group_id } ################################################################################ -# Parameter Group +# Cluster Parameter Group ################################################################################ output "db_cluster_parameter_group_arn" { @@ -122,6 +135,10 @@ output "db_cluster_parameter_group_id" { value = module.aurora.db_cluster_parameter_group_id } +################################################################################ +# DB Parameter Group +################################################################################ + output "db_parameter_group_arn" { description = "The ARN of the DB parameter group created" value = module.aurora.db_parameter_group_arn @@ -133,7 +150,7 @@ output "db_parameter_group_id" { } ################################################################################ -# Cloudwatch Log Group +# CloudWatch Log Group ################################################################################ output "db_cluster_cloudwatch_log_groups" { diff --git a/examples/mysql/versions.tf b/examples/mysql/versions.tf index 297a4912..bda84dba 100644 --- a/examples/mysql/versions.tf +++ b/examples/mysql/versions.tf @@ -1,15 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" - } - - random = { - source = "hashicorp/random" - version = ">= 2.2" + version = "~> 4.61" } } } diff --git a/examples/postgresql/README.md b/examples/postgresql/README.md index 4dd61afc..7cb2694b 100644 --- a/examples/postgresql/README.md +++ b/examples/postgresql/README.md @@ -19,28 +19,27 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | -| [random](#requirement\_random) | >= 2.2 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers | Name | Version | |------|---------| -| [random](#provider\_random) | >= 2.2 | +| [aws](#provider\_aws) | ~> 4.61 | ## Modules | Name | Source | Version | |------|--------|---------| | [aurora](#module\_aurora) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources | Name | Type | |------|------| -| [random_password.master](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs @@ -58,8 +57,7 @@ No inputs. | [cluster\_hosted\_zone\_id](#output\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | -| [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | -| [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | | [cluster\_reader\_endpoint](#output\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | diff --git a/examples/postgresql/main.tf b/examples/postgresql/main.tf index 7658bb26..4f8211ed 100644 --- a/examples/postgresql/main.tf +++ b/examples/postgresql/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -22,7 +27,7 @@ module "aurora" { name = local.name engine = "aurora-postgresql" - engine_version = "11.12" + engine_version = "14.5" instances = { 1 = { instance_class = "db.r5.2xlarge" @@ -54,28 +59,24 @@ module "aurora" { } } - vpc_id = module.vpc.vpc_id - db_subnet_group_name = module.vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks - security_group_egress_rules = { - to_cidrs = { + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + egress_example = { cidr_blocks = ["10.33.0.0/28"] description = "Egress to corporate printer closet" } } - iam_database_authentication_enabled = true - master_password = random_password.master.result - create_random_password = false - apply_immediately = true skip_final_snapshot = true create_db_cluster_parameter_group = true db_cluster_parameter_group_name = local.name - db_cluster_parameter_group_family = "aurora-postgresql11" + db_cluster_parameter_group_family = "aurora-postgresql14" db_cluster_parameter_group_description = "${local.name} example cluster parameter group" db_cluster_parameter_group_parameters = [ { @@ -91,7 +92,7 @@ module "aurora" { create_db_parameter_group = true db_parameter_group_name = local.name - db_parameter_group_family = "aurora-postgresql11" + db_parameter_group_family = "aurora-postgresql14" db_parameter_group_description = "${local.name} example DB parameter group" db_parameter_group_parameters = [ { @@ -111,26 +112,17 @@ module "aurora" { # Supporting Resources ################################################################################ -resource "random_password" "master" { - length = 10 -} - module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - enable_dns_support = true - enable_dns_hostnames = true - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - enable_nat_gateway = false # Disabled NAT to be able to run this example quicker + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/postgresql/outputs.tf b/examples/postgresql/outputs.tf index a3304c60..2deaba75 100644 --- a/examples/postgresql/outputs.tf +++ b/examples/postgresql/outputs.tf @@ -1,10 +1,16 @@ -# aws_db_subnet_group +################################################################################ +# DB Subnet Group +################################################################################ + output "db_subnet_group_name" { description = "The db subnet group name" value = module.aurora.db_subnet_group_name } -# aws_rds_cluster +################################################################################ +# Cluster +################################################################################ + output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora.cluster_arn @@ -40,7 +46,6 @@ output "cluster_engine_version_actual" { value = module.aurora.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora.cluster_database_name @@ -51,16 +56,9 @@ output "cluster_port" { value = module.aurora.cluster_port } -output "cluster_master_password" { - description = "The database master password" - value = module.aurora.cluster_master_password - sensitive = true -} - -output "cluster_master_username" { - description = "The database master username" - value = module.aurora.cluster_master_username - sensitive = true +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora.cluster_master_user_secret } output "cluster_hosted_zone_id" { @@ -68,25 +66,37 @@ output "cluster_hosted_zone_id" { value = module.aurora.cluster_hosted_zone_id } -# aws_rds_cluster_instances +################################################################################ +# Cluster Instance(s) +################################################################################ + output "cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora.cluster_instances } -# aws_rds_cluster_endpoint +################################################################################ +# Cluster Endpoint(s) +################################################################################ + output "additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora.additional_cluster_endpoints } -# aws_rds_cluster_role_association +################################################################################ +# Cluster IAM Roles +################################################################################ + output "cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora.cluster_role_associations } -# Enhanced monitoring role +################################################################################ +# Enhanced Monitoring +################################################################################ + output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora.enhanced_monitoring_iam_role_name @@ -102,14 +112,17 @@ output "enhanced_monitoring_iam_role_unique_id" { value = module.aurora.enhanced_monitoring_iam_role_unique_id } -# aws_security_group +################################################################################ +# Security Group +################################################################################ + output "security_group_id" { description = "The security group ID of the cluster" value = module.aurora.security_group_id } ################################################################################ -# Parameter Group +# Cluster Parameter Group ################################################################################ output "db_cluster_parameter_group_arn" { @@ -122,6 +135,10 @@ output "db_cluster_parameter_group_id" { value = module.aurora.db_cluster_parameter_group_id } +################################################################################ +# DB Parameter Group +################################################################################ + output "db_parameter_group_arn" { description = "The ARN of the DB parameter group created" value = module.aurora.db_parameter_group_arn @@ -133,7 +150,7 @@ output "db_parameter_group_id" { } ################################################################################ -# Cloudwatch Log Group +# CloudWatch Log Group ################################################################################ output "db_cluster_cloudwatch_log_groups" { diff --git a/examples/postgresql/versions.tf b/examples/postgresql/versions.tf index 297a4912..bda84dba 100644 --- a/examples/postgresql/versions.tf +++ b/examples/postgresql/versions.tf @@ -1,15 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" - } - - random = { - source = "hashicorp/random" - version = ">= 2.2" + version = "~> 4.61" } } } diff --git a/examples/s3-import/README.md b/examples/s3-import/README.md index d0691ef2..b03846d3 100644 --- a/examples/s3-import/README.md +++ b/examples/s3-import/README.md @@ -48,16 +48,14 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | -| [aws](#requirement\_aws) | >= 4.30 | -| [random](#requirement\_random) | >= 2.2 | +| [terraform](#requirement\_terraform) | >= 1.0 | +| [aws](#requirement\_aws) | ~> 4.61 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 4.30 | -| [random](#provider\_random) | >= 2.2 | +| [aws](#provider\_aws) | ~> 4.61 | ## Modules @@ -65,17 +63,15 @@ Note that this example may create resources which cost money. Run `terraform des |------|--------|---------| | [aurora](#module\_aurora) | ../../ | n/a | | [import\_s3\_bucket](#module\_import\_s3\_bucket) | terraform-aws-modules/s3-bucket/aws | ~> 3.0 | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources | Name | Type | |------|------| -| [aws_db_parameter_group.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | | [aws_iam_role.s3_import](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.s3_import](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | -| [aws_rds_cluster_parameter_group.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | -| [random_pet.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_iam_policy_document.s3_import](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.s3_import_assume](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -95,14 +91,17 @@ No inputs. | [cluster\_hosted\_zone\_id](#output\_cluster\_hosted\_zone\_id) | The Route53 Hosted Zone ID of the endpoint | | [cluster\_id](#output\_cluster\_id) | The RDS Cluster Identifier | | [cluster\_instances](#output\_cluster\_instances) | A map of cluster instances and their attributes | -| [cluster\_master\_password](#output\_cluster\_master\_password) | The database master password | -| [cluster\_master\_username](#output\_cluster\_master\_username) | The database master username | +| [cluster\_master\_user\_secret](#output\_cluster\_master\_user\_secret) | The generated database master user secret when `manage_master_user_password` is set to `true` | | [cluster\_members](#output\_cluster\_members) | List of RDS Instances that are a part of this cluster | | [cluster\_port](#output\_cluster\_port) | The database port | | [cluster\_reader\_endpoint](#output\_cluster\_reader\_endpoint) | A read-only endpoint for the cluster, automatically load-balanced across replicas | | [cluster\_resource\_id](#output\_cluster\_resource\_id) | The RDS Cluster Resource ID | | [cluster\_role\_associations](#output\_cluster\_role\_associations) | A map of IAM roles associated with the cluster and their attributes | | [db\_cluster\_cloudwatch\_log\_groups](#output\_db\_cluster\_cloudwatch\_log\_groups) | Map of CloudWatch log groups created and their attributes | +| [db\_cluster\_parameter\_group\_arn](#output\_db\_cluster\_parameter\_group\_arn) | The ARN of the DB cluster parameter group created | +| [db\_cluster\_parameter\_group\_id](#output\_db\_cluster\_parameter\_group\_id) | The ID of the DB cluster parameter group created | +| [db\_parameter\_group\_arn](#output\_db\_parameter\_group\_arn) | The ARN of the DB parameter group created | +| [db\_parameter\_group\_id](#output\_db\_parameter\_group\_id) | The ID of the DB parameter group created | | [db\_subnet\_group\_name](#output\_db\_subnet\_group\_name) | The db subnet group name | | [enhanced\_monitoring\_iam\_role\_arn](#output\_enhanced\_monitoring\_iam\_role\_arn) | The Amazon Resource Name (ARN) specifying the enhanced monitoring role | | [enhanced\_monitoring\_iam\_role\_name](#output\_enhanced\_monitoring\_iam\_role\_name) | The name of the enhanced monitoring role | diff --git a/examples/s3-import/main.tf b/examples/s3-import/main.tf index b552d72a..26b41e80 100644 --- a/examples/s3-import/main.tf +++ b/examples/s3-import/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -26,11 +31,13 @@ module "aurora" { instance_class = "db.r5.large" instances = { 1 = {} } - vpc_id = module.vpc.vpc_id - db_subnet_group_name = module.vpc.database_subnet_group_name - create_db_subnet_group = false - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } iam_roles = { s3_import = { @@ -48,49 +55,26 @@ module "aurora" { skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example.id enabled_cloudwatch_logs_exports = ["audit", "error", "general", "slowquery"] tags = local.tags } -resource "aws_db_parameter_group" "example" { - name = "${local.name}-aurora-db-57-parameter-group" - family = "aurora-mysql5.7" - description = "${local.name}-aurora-db-57-parameter-group" - tags = local.tags -} - -resource "aws_rds_cluster_parameter_group" "example" { - name = "${local.name}-aurora-57-cluster-parameter-group" - family = "aurora-mysql5.7" - description = "${local.name}-aurora-57-cluster-parameter-group" - tags = local.tags -} - ################################################################################ # Supporting Resources ################################################################################ -resource "random_pet" "this" { - length = 2 -} - module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - enable_dns_hostnames = true - enable_dns_support = true + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } @@ -99,7 +83,7 @@ module "import_s3_bucket" { source = "terraform-aws-modules/s3-bucket/aws" version = "~> 3.0" - bucket = "${local.name}-${random_pet.this.id}" + bucket_prefix = "${local.name}-" acl = "private" force_destroy = true @@ -120,7 +104,7 @@ data "aws_iam_policy_document" "s3_import_assume" { } resource "aws_iam_role" "s3_import" { - name = "${local.name}-${random_pet.this.id}" + name_prefix = "${local.name}-" description = "IAM role to allow RDS to import MySQL backup from S3" assume_role_policy = data.aws_iam_policy_document.s3_import_assume.json force_detach_policies = true @@ -152,9 +136,9 @@ data "aws_iam_policy_document" "s3_import" { } resource "aws_iam_role_policy" "s3_import" { - name = "${local.name}-${random_pet.this.id}" - role = aws_iam_role.s3_import.id - policy = data.aws_iam_policy_document.s3_import.json + name_prefix = "${local.name}-" + role = aws_iam_role.s3_import.id + policy = data.aws_iam_policy_document.s3_import.json # We need the files uploaded before the RDS instance is created, and the instance # also needs this role so this is an easy way of ensuring the backup is uploaded before diff --git a/examples/s3-import/outputs.tf b/examples/s3-import/outputs.tf index a06f22c8..2deaba75 100644 --- a/examples/s3-import/outputs.tf +++ b/examples/s3-import/outputs.tf @@ -1,10 +1,16 @@ -# aws_db_subnet_group +################################################################################ +# DB Subnet Group +################################################################################ + output "db_subnet_group_name" { description = "The db subnet group name" value = module.aurora.db_subnet_group_name } -# aws_rds_cluster +################################################################################ +# Cluster +################################################################################ + output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" value = module.aurora.cluster_arn @@ -40,7 +46,6 @@ output "cluster_engine_version_actual" { value = module.aurora.cluster_engine_version_actual } -# database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output output "cluster_database_name" { description = "Name for an automatically created database on cluster creation" value = module.aurora.cluster_database_name @@ -51,16 +56,9 @@ output "cluster_port" { value = module.aurora.cluster_port } -output "cluster_master_password" { - description = "The database master password" - value = module.aurora.cluster_master_password - sensitive = true -} - -output "cluster_master_username" { - description = "The database master username" - value = module.aurora.cluster_master_username - sensitive = true +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = module.aurora.cluster_master_user_secret } output "cluster_hosted_zone_id" { @@ -68,25 +66,37 @@ output "cluster_hosted_zone_id" { value = module.aurora.cluster_hosted_zone_id } -# aws_rds_cluster_instances +################################################################################ +# Cluster Instance(s) +################################################################################ + output "cluster_instances" { description = "A map of cluster instances and their attributes" value = module.aurora.cluster_instances } -# aws_rds_cluster_endpoint +################################################################################ +# Cluster Endpoint(s) +################################################################################ + output "additional_cluster_endpoints" { description = "A map of additional cluster endpoints and their attributes" value = module.aurora.additional_cluster_endpoints } -# aws_rds_cluster_role_association +################################################################################ +# Cluster IAM Roles +################################################################################ + output "cluster_role_associations" { description = "A map of IAM roles associated with the cluster and their attributes" value = module.aurora.cluster_role_associations } -# Enhanced monitoring role +################################################################################ +# Enhanced Monitoring +################################################################################ + output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" value = module.aurora.enhanced_monitoring_iam_role_name @@ -102,13 +112,47 @@ output "enhanced_monitoring_iam_role_unique_id" { value = module.aurora.enhanced_monitoring_iam_role_unique_id } -# aws_security_group +################################################################################ +# Security Group +################################################################################ + output "security_group_id" { description = "The security group ID of the cluster" value = module.aurora.security_group_id } -# Cloudwatch Log Groups +################################################################################ +# Cluster Parameter Group +################################################################################ + +output "db_cluster_parameter_group_arn" { + description = "The ARN of the DB cluster parameter group created" + value = module.aurora.db_cluster_parameter_group_arn +} + +output "db_cluster_parameter_group_id" { + description = "The ID of the DB cluster parameter group created" + value = module.aurora.db_cluster_parameter_group_id +} + +################################################################################ +# DB Parameter Group +################################################################################ + +output "db_parameter_group_arn" { + description = "The ARN of the DB parameter group created" + value = module.aurora.db_parameter_group_arn +} + +output "db_parameter_group_id" { + description = "The ID of the DB parameter group created" + value = module.aurora.db_parameter_group_id +} + +################################################################################ +# CloudWatch Log Group +################################################################################ + output "db_cluster_cloudwatch_log_groups" { description = "Map of CloudWatch log groups created and their attributes" value = module.aurora.db_cluster_cloudwatch_log_groups diff --git a/examples/s3-import/versions.tf b/examples/s3-import/versions.tf index 297a4912..bda84dba 100644 --- a/examples/s3-import/versions.tf +++ b/examples/s3-import/versions.tf @@ -1,15 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" - } - - random = { - source = "hashicorp/random" - version = ">= 2.2" + version = "~> 4.61" } } } diff --git a/examples/serverless/README.md b/examples/serverless/README.md index ec8ecd83..01187bc7 100644 --- a/examples/serverless/README.md +++ b/examples/serverless/README.md @@ -19,7 +19,7 @@ Note that this example may create resources which cost money. Run `terraform des | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 0.13 | +| [terraform](#requirement\_terraform) | >= 1.0 | | [aws](#requirement\_aws) | >= 4.30 | ## Providers @@ -36,20 +36,13 @@ Note that this example may create resources which cost money. Run `terraform des | [aurora\_mysql\_v2](#module\_aurora\_mysql\_v2) | ../../ | n/a | | [aurora\_postgresql](#module\_aurora\_postgresql) | ../../ | n/a | | [aurora\_postgresql\_v2](#module\_aurora\_postgresql\_v2) | ../../ | n/a | -| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 3.0 | +| [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | ~> 4.0 | ## Resources | Name | Type | |------|------| -| [aws_db_parameter_group.example_mysql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | -| [aws_db_parameter_group.example_mysql8](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | -| [aws_db_parameter_group.example_postgresql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | -| [aws_db_parameter_group.example_postgresql13](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource | -| [aws_rds_cluster_parameter_group.example_mysql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | -| [aws_rds_cluster_parameter_group.example_mysql8](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | -| [aws_rds_cluster_parameter_group.example_postgresql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | -| [aws_rds_cluster_parameter_group.example_postgresql13](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | | [aws_rds_engine_version.postgresql](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/rds_engine_version) | data source | ## Inputs diff --git a/examples/serverless/main.tf b/examples/serverless/main.tf index c732d29d..5ff2cb87 100644 --- a/examples/serverless/main.tf +++ b/examples/serverless/main.tf @@ -2,10 +2,15 @@ provider "aws" { region = local.region } +data "aws_availability_zones" "available" {} + locals { - name = "ex-${replace(basename(path.cwd), "_", "-")}" + name = "ex-${basename(path.cwd)}" region = "eu-west-1" + vpc_cidr = "10.0.0.0/16" + azs = slice(data.aws_availability_zones.available.names, 0, 3) + tags = { Example = local.name GithubRepo = "terraform-aws-rds-aurora" @@ -25,18 +30,19 @@ module "aurora_postgresql" { engine_mode = "serverless" storage_encrypted = true - vpc_id = module.vpc.vpc_id - subnets = module.vpc.database_subnets - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } monitoring_interval = 60 apply_immediately = true skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example_postgresql.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_postgresql.id # enabled_cloudwatch_logs_exports = # NOT SUPPORTED scaling_configuration = { @@ -46,20 +52,8 @@ module "aurora_postgresql" { seconds_until_auto_pause = 300 timeout_action = "ForceApplyCapacityChange" } -} -resource "aws_db_parameter_group" "example_postgresql" { - name = "${local.name}-aurora-db-postgres-parameter-group" - family = "aurora-postgresql10" - description = "${local.name}-aurora-db-postgres-parameter-group" - tags = local.tags -} - -resource "aws_rds_cluster_parameter_group" "example_postgresql" { - name = "${local.name}-aurora-postgres-cluster-parameter-group" - family = "aurora-postgresql10" - description = "${local.name}-aurora-postgres-cluster-parameter-group" - tags = local.tags + tags = local.tags } ################################################################################ @@ -74,18 +68,19 @@ module "aurora_mysql" { engine_mode = "serverless" storage_encrypted = true - vpc_id = module.vpc.vpc_id - subnets = module.vpc.database_subnets - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } monitoring_interval = 60 apply_immediately = true skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example_mysql.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_mysql.id # enabled_cloudwatch_logs_exports = # NOT SUPPORTED scaling_configuration = { @@ -95,20 +90,8 @@ module "aurora_mysql" { seconds_until_auto_pause = 300 timeout_action = "ForceApplyCapacityChange" } -} - -resource "aws_db_parameter_group" "example_mysql" { - name = "${local.name}-aurora-db-mysql-parameter-group" - family = "aurora-mysql5.7" - description = "${local.name}-aurora-db-mysql-parameter-group" - tags = local.tags -} -resource "aws_rds_cluster_parameter_group" "example_mysql" { - name = "${local.name}-aurora-mysql-cluster-parameter-group" - family = "aurora-mysql5.7" - description = "${local.name}-aurora-mysql-cluster-parameter-group" - tags = local.tags + tags = local.tags } ################################################################################ @@ -121,22 +104,22 @@ module "aurora_mysql_v2" { name = "${local.name}-mysqlv2" engine = "aurora-mysql" engine_mode = "provisioned" - engine_version = "8.0.mysql_aurora.3.02.0" + engine_version = "8.0" storage_encrypted = true - vpc_id = module.vpc.vpc_id - subnets = module.vpc.database_subnets - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } monitoring_interval = 60 apply_immediately = true skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example_mysql8.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_mysql8.id - serverlessv2_scaling_configuration = { min_capacity = 2 max_capacity = 10 @@ -147,20 +130,8 @@ module "aurora_mysql_v2" { one = {} two = {} } -} - -resource "aws_db_parameter_group" "example_mysql8" { - name = "${local.name}-aurora-db-mysql8-parameter-group" - family = "aurora-mysql8.0" - description = "${local.name}-aurora-db-mysql8-parameter-group" - tags = local.tags -} -resource "aws_rds_cluster_parameter_group" "example_mysql8" { - name = "${local.name}-aurora-mysql8-cluster-parameter-group" - family = "aurora-mysql8.0" - description = "${local.name}-aurora-mysql8-cluster-parameter-group" - tags = local.tags + tags = local.tags } ################################################################################ @@ -169,7 +140,7 @@ resource "aws_rds_cluster_parameter_group" "example_mysql8" { data "aws_rds_engine_version" "postgresql" { engine = "aurora-postgresql" - version = "13.6" + version = "14.5" } module "aurora_postgresql_v2" { @@ -181,19 +152,19 @@ module "aurora_postgresql_v2" { engine_version = data.aws_rds_engine_version.postgresql.version storage_encrypted = true - vpc_id = module.vpc.vpc_id - subnets = module.vpc.database_subnets - create_security_group = true - allowed_cidr_blocks = module.vpc.private_subnets_cidr_blocks + vpc_id = module.vpc.vpc_id + db_subnet_group_name = module.vpc.database_subnet_group_name + security_group_rules = { + vpc_ingress = { + cidr_blocks = module.vpc.private_subnets_cidr_blocks + } + } monitoring_interval = 60 apply_immediately = true skip_final_snapshot = true - db_parameter_group_name = aws_db_parameter_group.example_postgresql13.id - db_cluster_parameter_group_name = aws_rds_cluster_parameter_group.example_postgresql13.id - serverlessv2_scaling_configuration = { min_capacity = 2 max_capacity = 10 @@ -204,20 +175,8 @@ module "aurora_postgresql_v2" { one = {} two = {} } -} - -resource "aws_db_parameter_group" "example_postgresql13" { - name = "${local.name}-aurora-db-postgres13-parameter-group" - family = "aurora-postgresql13" - description = "${local.name}-aurora-db-postgres13-parameter-group" - tags = local.tags -} -resource "aws_rds_cluster_parameter_group" "example_postgresql13" { - name = "${local.name}-aurora-postgres13-cluster-parameter-group" - family = "aurora-postgresql13" - description = "${local.name}-aurora-postgres13-cluster-parameter-group" - tags = local.tags + tags = local.tags } ################################################################################ @@ -226,20 +185,15 @@ resource "aws_rds_cluster_parameter_group" "example_postgresql13" { module "vpc" { source = "terraform-aws-modules/vpc/aws" - version = "~> 3.0" + version = "~> 4.0" name = local.name - cidr = "10.99.0.0/18" - - enable_dns_support = true - enable_dns_hostnames = true - - azs = ["${local.region}a", "${local.region}b", "${local.region}c"] - public_subnets = ["10.99.0.0/24", "10.99.1.0/24", "10.99.2.0/24"] - private_subnets = ["10.99.3.0/24", "10.99.4.0/24", "10.99.5.0/24"] - database_subnets = ["10.99.7.0/24", "10.99.8.0/24", "10.99.9.0/24"] + cidr = local.vpc_cidr - enable_nat_gateway = false # Disabled NAT to be able to run this example quicker + azs = local.azs + public_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k)] + private_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 3)] + database_subnets = [for k, v in local.azs : cidrsubnet(local.vpc_cidr, 8, k + 6)] tags = local.tags } diff --git a/examples/serverless/versions.tf b/examples/serverless/versions.tf index f23452ce..34fcbc01 100644 --- a/examples/serverless/versions.tf +++ b/examples/serverless/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { diff --git a/main.tf b/main.tf index f434e87c..0f77c799 100644 --- a/main.tf +++ b/main.tf @@ -1,7 +1,7 @@ data "aws_partition" "current" {} locals { - create_cluster = var.create_cluster && var.putin_khuylo + create = var.create && var.putin_khuylo port = coalesce(var.port, (var.engine == "aurora-postgresql" || var.engine == "postgres" ? 5432 : 3306)) @@ -11,33 +11,9 @@ locals { cluster_parameter_group_name = try(coalesce(var.db_cluster_parameter_group_name, var.name), null) db_parameter_group_name = try(coalesce(var.db_parameter_group_name, var.name), null) - master_password = local.create_cluster && var.create_random_password ? random_password.master_password[0].result : var.master_password backtrack_window = (var.engine == "aurora-mysql" || var.engine == "aurora") && var.engine_mode != "serverless" ? var.backtrack_window : 0 is_serverless = var.engine_mode == "serverless" - - final_snapshot_identifier_prefix = "${var.final_snapshot_identifier_prefix}-${var.name}-${try(random_id.snapshot_identifier[0].hex, "")}" -} - -################################################################################ -# Random Password & Snapshot ID -################################################################################ - -resource "random_password" "master_password" { - count = local.create_cluster && var.create_random_password ? 1 : 0 - - length = var.random_password_length - special = false -} - -resource "random_id" "snapshot_identifier" { - count = local.create_cluster && !var.skip_final_snapshot ? 1 : 0 - - keepers = { - id = var.name - } - - byte_length = 4 } ################################################################################ @@ -45,7 +21,7 @@ resource "random_id" "snapshot_identifier" { ################################################################################ resource "aws_db_subnet_group" "this" { - count = local.create_cluster && var.create_db_subnet_group ? 1 : 0 + count = local.create && var.create_db_subnet_group ? 1 : 0 name = local.internal_db_subnet_group_name description = "For Aurora cluster ${var.name}" @@ -59,7 +35,7 @@ resource "aws_db_subnet_group" "this" { ################################################################################ resource "aws_rds_cluster" "this" { - count = local.create_cluster ? 1 : 0 + count = local.create ? 1 : 0 allocated_storage = var.allocated_storage allow_major_version_upgrade = var.allow_major_version_upgrade @@ -83,14 +59,16 @@ resource "aws_rds_cluster" "this" { engine = var.engine engine_mode = var.engine_mode engine_version = var.engine_version - final_snapshot_identifier = var.skip_final_snapshot ? null : local.final_snapshot_identifier_prefix + final_snapshot_identifier = var.final_snapshot_identifier global_cluster_identifier = var.global_cluster_identifier iam_database_authentication_enabled = var.iam_database_authentication_enabled # iam_roles has been removed from this resource and instead will be used with aws_rds_cluster_role_association below to avoid conflicts per docs iops = var.iops kms_key_id = var.kms_key_id - master_password = var.is_primary_cluster ? local.master_password : null - master_username = var.is_primary_cluster ? var.master_username : null + manage_master_user_password = var.global_cluster_identifier == null && var.manage_master_user_password ? var.manage_master_user_password : null + master_user_secret_kms_key_id = var.global_cluster_identifier == null && var.manage_master_user_password ? var.master_user_secret_kms_key_id : null + master_password = var.is_primary_cluster && !var.manage_master_user_password ? var.master_password : null + master_username = var.is_primary_cluster && !var.manage_master_user_password ? var.master_username : null network_type = var.network_type port = local.port preferred_backup_window = local.is_serverless ? null : var.preferred_backup_window @@ -162,6 +140,7 @@ resource "aws_rds_cluster" "this" { replication_source_identifier, # See docs here https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_global_cluster#new-global-cluster-from-existing-db-cluster global_cluster_identifier, + snapshot_identifier, ] } @@ -173,7 +152,7 @@ resource "aws_rds_cluster" "this" { ################################################################################ resource "aws_rds_cluster_instance" "this" { - for_each = { for k, v in var.instances : k => v if local.create_cluster && !local.is_serverless } + for_each = { for k, v in var.instances : k => v if local.create && !local.is_serverless } apply_immediately = try(each.value.apply_immediately, var.apply_immediately) auto_minor_version_upgrade = try(each.value.auto_minor_version_upgrade, var.auto_minor_version_upgrade) @@ -211,7 +190,7 @@ resource "aws_rds_cluster_instance" "this" { ################################################################################ resource "aws_rds_cluster_endpoint" "this" { - for_each = { for k, v in var.endpoints : k => v if local.create_cluster && !local.is_serverless } + for_each = { for k, v in var.endpoints : k => v if local.create && !local.is_serverless } cluster_endpoint_identifier = each.value.identifier cluster_identifier = aws_rds_cluster.this[0].id @@ -230,7 +209,7 @@ resource "aws_rds_cluster_endpoint" "this" { ################################################################################ resource "aws_rds_cluster_role_association" "this" { - for_each = { for k, v in var.iam_roles : k => v if local.create_cluster } + for_each = { for k, v in var.iam_roles : k => v if local.create } db_cluster_identifier = aws_rds_cluster.this[0].id feature_name = each.value.feature_name @@ -241,26 +220,32 @@ resource "aws_rds_cluster_role_association" "this" { # Enhanced Monitoring ################################################################################ +locals { + create_monitoring_role = local.create && var.create_monitoring_role && var.monitoring_interval > 0 +} + data "aws_iam_policy_document" "monitoring_rds_assume_role" { + count = local.create_monitoring_role ? 1 : 0 + statement { actions = ["sts:AssumeRole"] principals { type = "Service" - identifiers = ["monitoring.rds.amazonaws.com"] + identifiers = ["monitoring.rds.${data.aws_partition.current.dns_suffix}"] } } } resource "aws_iam_role" "rds_enhanced_monitoring" { - count = local.create_cluster && var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0 + count = local.create_monitoring_role ? 1 : 0 name = var.iam_role_use_name_prefix ? null : var.iam_role_name name_prefix = var.iam_role_use_name_prefix ? "${var.iam_role_name}-" : null description = var.iam_role_description path = var.iam_role_path - assume_role_policy = data.aws_iam_policy_document.monitoring_rds_assume_role.json + assume_role_policy = data.aws_iam_policy_document.monitoring_rds_assume_role[0].json managed_policy_arns = var.iam_role_managed_policy_arns permissions_boundary = var.iam_role_permissions_boundary force_detach_policies = var.iam_role_force_detach_policies @@ -270,7 +255,7 @@ resource "aws_iam_role" "rds_enhanced_monitoring" { } resource "aws_iam_role_policy_attachment" "rds_enhanced_monitoring" { - count = local.create_cluster && var.create_monitoring_role && var.monitoring_interval > 0 ? 1 : 0 + count = local.create_monitoring_role ? 1 : 0 role = aws_iam_role.rds_enhanced_monitoring[0].name policy_arn = "arn:${data.aws_partition.current.partition}:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole" @@ -281,7 +266,7 @@ resource "aws_iam_role_policy_attachment" "rds_enhanced_monitoring" { ################################################################################ resource "aws_appautoscaling_target" "this" { - count = local.create_cluster && var.autoscaling_enabled && !local.is_serverless ? 1 : 0 + count = local.create && var.autoscaling_enabled && !local.is_serverless ? 1 : 0 max_capacity = var.autoscaling_max_capacity min_capacity = var.autoscaling_min_capacity @@ -291,7 +276,7 @@ resource "aws_appautoscaling_target" "this" { } resource "aws_appautoscaling_policy" "this" { - count = local.create_cluster && var.autoscaling_enabled && !local.is_serverless ? 1 : 0 + count = local.create && var.autoscaling_enabled && !local.is_serverless ? 1 : 0 name = var.autoscaling_policy_name policy_type = "TargetTrackingScaling" @@ -319,7 +304,7 @@ resource "aws_appautoscaling_policy" "this" { ################################################################################ resource "aws_security_group" "this" { - count = local.create_cluster && var.create_security_group ? 1 : 0 + count = local.create && var.create_security_group ? 1 : 0 name = var.security_group_use_name_prefix ? null : var.name name_prefix = var.security_group_use_name_prefix ? "${var.name}-" : null @@ -333,42 +318,14 @@ resource "aws_security_group" "this" { } } -# TODO - change to map of ingress rules under one resource at next breaking change -resource "aws_security_group_rule" "default_ingress" { - count = local.create_cluster && var.create_security_group ? length(var.allowed_security_groups) : 0 - - description = "From allowed SGs" - - type = "ingress" - from_port = local.port - to_port = local.port - protocol = "tcp" - source_security_group_id = element(var.allowed_security_groups, count.index) - security_group_id = aws_security_group.this[0].id -} - -# TODO - change to map of ingress rules under one resource at next breaking change -resource "aws_security_group_rule" "cidr_ingress" { - count = local.create_cluster && var.create_security_group && length(var.allowed_cidr_blocks) > 0 ? 1 : 0 - - description = "From allowed CIDRs" - - type = "ingress" - from_port = local.port - to_port = local.port - protocol = "tcp" - cidr_blocks = var.allowed_cidr_blocks - security_group_id = aws_security_group.this[0].id -} - -resource "aws_security_group_rule" "egress" { - for_each = local.create_cluster && var.create_security_group ? var.security_group_egress_rules : {} +resource "aws_security_group_rule" "this" { + for_each = { for k, v in var.security_group_rules : k => v if local.create && var.create_security_group } # required - type = "egress" + type = try(each.value.type, "ingress") from_port = try(each.value.from_port, local.port) to_port = try(each.value.to_port, local.port) - protocol = "tcp" + protocol = try(each.value.protocol, "tcp") security_group_id = aws_security_group.this[0].id # optional @@ -384,7 +341,7 @@ resource "aws_security_group_rule" "egress" { ################################################################################ resource "aws_rds_cluster_parameter_group" "this" { - count = local.create_cluster && var.create_db_cluster_parameter_group ? 1 : 0 + count = local.create && var.create_db_cluster_parameter_group ? 1 : 0 name = var.db_cluster_parameter_group_use_name_prefix ? null : local.cluster_parameter_group_name name_prefix = var.db_cluster_parameter_group_use_name_prefix ? "${local.cluster_parameter_group_name}-" : null @@ -413,7 +370,7 @@ resource "aws_rds_cluster_parameter_group" "this" { ################################################################################ resource "aws_db_parameter_group" "this" { - count = local.create_cluster && var.create_db_parameter_group ? 1 : 0 + count = local.create && var.create_db_parameter_group ? 1 : 0 name = var.db_parameter_group_use_name_prefix ? null : local.db_parameter_group_name name_prefix = var.db_parameter_group_use_name_prefix ? "${local.db_parameter_group_name}-" : null @@ -443,7 +400,7 @@ resource "aws_db_parameter_group" "this" { # Log groups will not be created if using a cluster identifier prefix resource "aws_cloudwatch_log_group" "this" { - for_each = toset([for log in var.enabled_cloudwatch_logs_exports : log if local.create_cluster && var.create_cloudwatch_log_group && !var.cluster_use_name_prefix]) + for_each = toset([for log in var.enabled_cloudwatch_logs_exports : log if local.create && var.create_cloudwatch_log_group && !var.cluster_use_name_prefix]) name = "/aws/rds/cluster/${var.name}/${each.value}" retention_in_days = var.cloudwatch_log_group_retention_in_days diff --git a/outputs.tf b/outputs.tf index 2a9fe2bf..f3744c2a 100644 --- a/outputs.tf +++ b/outputs.tf @@ -13,37 +13,37 @@ output "db_subnet_group_name" { output "cluster_arn" { description = "Amazon Resource Name (ARN) of cluster" - value = try(aws_rds_cluster.this[0].arn, "") + value = try(aws_rds_cluster.this[0].arn, null) } output "cluster_id" { description = "The RDS Cluster Identifier" - value = try(aws_rds_cluster.this[0].id, "") + value = try(aws_rds_cluster.this[0].id, null) } output "cluster_resource_id" { description = "The RDS Cluster Resource ID" - value = try(aws_rds_cluster.this[0].cluster_resource_id, "") + value = try(aws_rds_cluster.this[0].cluster_resource_id, null) } output "cluster_members" { description = "List of RDS Instances that are a part of this cluster" - value = try(aws_rds_cluster.this[0].cluster_members, "") + value = try(aws_rds_cluster.this[0].cluster_members, null) } output "cluster_endpoint" { description = "Writer endpoint for the cluster" - value = try(aws_rds_cluster.this[0].endpoint, "") + value = try(aws_rds_cluster.this[0].endpoint, null) } output "cluster_reader_endpoint" { description = "A read-only endpoint for the cluster, automatically load-balanced across replicas" - value = try(aws_rds_cluster.this[0].reader_endpoint, "") + value = try(aws_rds_cluster.this[0].reader_endpoint, null) } output "cluster_engine_version_actual" { description = "The running version of the cluster database" - value = try(aws_rds_cluster.this[0].engine_version_actual, "") + value = try(aws_rds_cluster.this[0].engine_version_actual, null) } # database_name is not set on `aws_rds_cluster` resource if it was not specified, so can't be used in output @@ -54,24 +54,29 @@ output "cluster_database_name" { output "cluster_port" { description = "The database port" - value = try(aws_rds_cluster.this[0].port, "") + value = try(aws_rds_cluster.this[0].port, null) } output "cluster_master_password" { description = "The database master password" - value = try(aws_rds_cluster.this[0].master_password, "") + value = try(aws_rds_cluster.this[0].master_password, null) sensitive = true } output "cluster_master_username" { description = "The database master username" - value = try(aws_rds_cluster.this[0].master_username, "") + value = try(aws_rds_cluster.this[0].master_username, null) sensitive = true } +output "cluster_master_user_secret" { + description = "The generated database master user secret when `manage_master_user_password` is set to `true`" + value = try(aws_rds_cluster.this[0].master_user_secret, null) +} + output "cluster_hosted_zone_id" { description = "The Route53 Hosted Zone ID of the endpoint" - value = try(aws_rds_cluster.this[0].hosted_zone_id, "") + value = try(aws_rds_cluster.this[0].hosted_zone_id, null) } ################################################################################ @@ -107,17 +112,17 @@ output "cluster_role_associations" { output "enhanced_monitoring_iam_role_name" { description = "The name of the enhanced monitoring role" - value = try(aws_iam_role.rds_enhanced_monitoring[0].name, "") + value = try(aws_iam_role.rds_enhanced_monitoring[0].name, null) } output "enhanced_monitoring_iam_role_arn" { description = "The Amazon Resource Name (ARN) specifying the enhanced monitoring role" - value = try(aws_iam_role.rds_enhanced_monitoring[0].arn, "") + value = try(aws_iam_role.rds_enhanced_monitoring[0].arn, null) } output "enhanced_monitoring_iam_role_unique_id" { description = "Stable and unique string identifying the enhanced monitoring role" - value = try(aws_iam_role.rds_enhanced_monitoring[0].unique_id, "") + value = try(aws_iam_role.rds_enhanced_monitoring[0].unique_id, null) } ################################################################################ @@ -126,7 +131,7 @@ output "enhanced_monitoring_iam_role_unique_id" { output "security_group_id" { description = "The security group ID of the cluster" - value = try(aws_security_group.this[0].id, "") + value = try(aws_security_group.this[0].id, null) } ################################################################################ @@ -135,12 +140,12 @@ output "security_group_id" { output "db_cluster_parameter_group_arn" { description = "The ARN of the DB cluster parameter group created" - value = try(aws_rds_cluster_parameter_group.this[0].arn, "") + value = try(aws_rds_cluster_parameter_group.this[0].arn, null) } output "db_cluster_parameter_group_id" { description = "The ID of the DB cluster parameter group created" - value = try(aws_rds_cluster_parameter_group.this[0].id, "") + value = try(aws_rds_cluster_parameter_group.this[0].id, null) } ################################################################################ @@ -149,12 +154,12 @@ output "db_cluster_parameter_group_id" { output "db_parameter_group_arn" { description = "The ARN of the DB parameter group created" - value = try(aws_db_parameter_group.this[0].arn, "") + value = try(aws_db_parameter_group.this[0].arn, null) } output "db_parameter_group_id" { description = "The ID of the DB parameter group created" - value = try(aws_db_parameter_group.this[0].id, "") + value = try(aws_db_parameter_group.this[0].id, null) } ################################################################################ diff --git a/variables.tf b/variables.tf index ea194485..9011bdbe 100644 --- a/variables.tf +++ b/variables.tf @@ -1,3 +1,9 @@ +variable "create" { + description = "Whether cluster should be created (affects nearly all resources)" + type = bool + default = true +} + variable "name" { description = "Name used across resources created" type = string @@ -10,22 +16,6 @@ variable "tags" { default = {} } -################################################################################ -# Random Password & Snapshot ID -################################################################################ - -variable "create_random_password" { - description = "Determines whether to create random password for RDS primary cluster" - type = bool - default = true -} - -variable "random_password_length" { - description = "Length of random password to create. Defaults to `10`" - type = number - default = 10 -} - ################################################################################ # DB Subnet Group ################################################################################ @@ -33,7 +23,7 @@ variable "random_password_length" { variable "create_db_subnet_group" { description = "Determines whether to create the database subnet group or use existing" type = bool - default = true + default = false } variable "db_subnet_group_name" { @@ -48,22 +38,10 @@ variable "subnets" { default = [] } -variable "network_type" { - description = "The type of network stack to use (IPV4 or DUAL)" - type = string - default = null -} - ################################################################################ # Cluster ################################################################################ -variable "create_cluster" { - description = "Whether cluster should be created (affects nearly all resources)" - type = bool - default = true -} - variable "is_primary_cluster" { description = "Determines whether cluster is primary cluster with writer instance (set to `false` for global cluster and replica clusters)" type = bool @@ -184,10 +162,10 @@ variable "engine_version" { default = null } -variable "final_snapshot_identifier_prefix" { - description = "The prefix name to use when creating a final snapshot on cluster destroy; a 8 random digits are appended to name to ensure it's unique" +variable "final_snapshot_identifier" { + description = "The name of your final DB snapshot when this DB cluster is deleted. If omitted, no final snapshot will be made" type = string - default = "final" + default = null } variable "global_cluster_identifier" { @@ -214,16 +192,34 @@ variable "kms_key_id" { default = null } +variable "manage_master_user_password" { + description = "Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if `master_password` is provided" + type = bool + default = true +} + +variable "master_user_secret_kms_key_id" { + description = "The Amazon Web Services KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key" + type = string + default = null +} + variable "master_password" { - description = "Password for the master DB user. Note - when specifying a value here, 'create_random_password' should be set to `false`" + description = "Password for the master DB user. Note that this may show up in logs, and it will be stored in the state file. Required unless `manage_master_user_password` is set to `true` or unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database" type = string default = null } variable "master_username" { - description = "Username for the master DB user" + description = "Username for the master DB user. Required unless `manage_master_user_password` is set to `true` or unless `snapshot_identifier` or `replication_source_identifier` is provided or unless a `global_cluster_identifier` is provided when the cluster is the secondary cluster of a global database" type = string - default = "root" + default = null +} + +variable "network_type" { + description = "The type of network stack to use (IPV4 or DUAL)" + type = string + default = null } variable "port" { @@ -311,7 +307,7 @@ variable "cluster_tags" { } variable "vpc_security_group_ids" { - description = "List of VPC security groups to associate to the cluster in addition to the SG we create in this module" + description = "List of VPC security groups to associate to the cluster in addition to the security group created" type = list(string) default = [] } @@ -387,7 +383,7 @@ variable "performance_insights_retention_period" { } variable "publicly_accessible" { - description = "Determines whether instances are publicly accessible. Default false" + description = "Determines whether instances are publicly accessible. Default `false`" type = bool default = null } @@ -551,7 +547,7 @@ variable "create_security_group" { } variable "security_group_use_name_prefix" { - description = "Determines whether the security group name (`name`) is used as a prefix" + description = "Determines whether the security group name (`var.name`) is used as a prefix" type = bool default = true } @@ -568,21 +564,9 @@ variable "vpc_id" { default = "" } -variable "allowed_security_groups" { - description = "A list of Security Group ID's to allow access to" - type = list(string) - default = [] -} - -variable "allowed_cidr_blocks" { - description = "A list of CIDR blocks which are allowed to access the database" - type = list(string) - default = [] -} - -variable "security_group_egress_rules" { - description = "A map of security group egress rule definitions to add to the security group created" - type = map(any) +variable "security_group_rules" { + description = "Map of security group rules to add to the cluster security group created" + type = any default = {} } @@ -636,7 +620,6 @@ variable "db_cluster_parameter_group_parameters" { # DB Parameter Group ################################################################################ - variable "create_db_parameter_group" { description = "Determines whether a DB parameter should be created or use existing" type = bool diff --git a/versions.tf b/versions.tf index 297a4912..bda84dba 100644 --- a/versions.tf +++ b/versions.tf @@ -1,15 +1,10 @@ terraform { - required_version = ">= 0.13" + required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" - version = ">= 4.30" - } - - random = { - source = "hashicorp/random" - version = ">= 2.2" + version = "~> 4.61" } } }