main 03c1ad7f1a8d cached
65 files
331.4 KB
117.8k tokens
7 symbols
1 requests
Download .txt
Showing preview only (351K chars total). Download the full file or copy to clipboard to get everything.
Repository: cloudposse/terraform-aws-rds-cluster
Branch: main
Commit: 03c1ad7f1a8d
Files: 65
Total size: 331.4 KB

Directory structure:
gitextract_4dy49v9r/

├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   ├── feature_request.yml
│   │   └── question.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── mergify.yml
│   ├── renovate.json
│   ├── settings.yml
│   └── workflows/
│       ├── branch.yml
│       ├── chatops.yml
│       ├── release.yml
│       └── scheduled.yml
├── .gitignore
├── LICENSE
├── README.md
├── README.yaml
├── atmos.yaml
├── context.tf
├── enhanced-monitoring.tf
├── examples/
│   ├── basic/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── complete/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── enhanced_monitoring/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── postgres/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── serverless_mysql/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── serverless_mysql57/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── serverlessv2_postgres/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   └── with_cluster_parameters/
│       ├── main.tf
│       └── outputs.tf
├── main.tf
├── outputs.tf
├── test/
│   ├── .gitignore
│   ├── Makefile
│   ├── Makefile.alpine
│   └── src/
│       ├── .gitignore
│       ├── Makefile
│       ├── examples_complete_test.go
│       ├── examples_postgres_test.go
│       ├── examples_serverlessv2_postgres_test.go
│       ├── go.mod
│       ├── go.sum
│       └── utils.go
├── variables.tf
└── versions.tf

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/CODEOWNERS
================================================
# Use this file to define individuals or teams that are responsible for code in a repository.
# Read more: <https://help.github.com/articles/about-codeowners/>
#
# Order is important: the last matching pattern has the highest precedence

# These owners will be the default owners for everything
*             @cloudposse/engineering @cloudposse/contributors

# Cloud Posse must review any changes to Makefiles
**/Makefile   @cloudposse/engineering
**/Makefile.* @cloudposse/engineering

# Cloud Posse must review any changes to GitHub actions
.github/*     @cloudposse/engineering

# Cloud Posse must review any changes to standard context definition,
# but some changes can be rubber-stamped.
**/*.tf       @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
README.yaml   @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
README.md     @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers
docs/*.md     @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers

# Cloud Posse Admins must review all changes to CODEOWNERS or the mergify configuration
.github/mergify.yml @cloudposse/admins
.github/CODEOWNERS  @cloudposse/admins


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''

---

Found a bug? Maybe our [Slack Community](https://slack.cloudposse.com) can help. 

[![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com)

## Describe the Bug
A clear and concise description of what the bug is.

## Expected Behavior
A clear and concise description of what you expected to happen.

## Steps to Reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Run '....'
3. Enter '....'
4. See error

## Screenshots
If applicable, add screenshots or logs to help explain your problem.

## Environment (please complete the following information):

Anything that will help us triage the bug will help. Here are some ideas:
 - OS: [e.g. Linux, OSX, WSL, etc]
 - Version [e.g. 10.15]

## Additional Context
Add any other context about the problem here.

================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.yml
================================================
---
name: Bug report
description: Create a report to help us improve
labels: ["bug"]
assignees: [""]
body:
  - type: markdown
    attributes:
      value: |
        Found a bug?
        
        Please checkout our [Slack Community](https://slack.cloudposse.com)
        or visit our [Slack Archive](https://archive.sweetops.com/).

        [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com)

  - type: textarea
    id: concise-description
    attributes:
      label: Describe the Bug
      description: A clear and concise description of what the bug is.
      placeholder: What is the bug about?
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected.
      placeholder: What happened?
    validations:
      required: true

  - type: textarea
    id: reproduction-steps
    attributes:
      label: Steps to Reproduce
      description: Steps to reproduce the behavior.
      placeholder: How do we reproduce it?
    validations:
      required: true

  - type: textarea
    id: screenshots
    attributes:
      label: Screenshots
      description: If applicable, add screenshots or logs to help explain.
    validations:
      required: false

  - type: textarea
    id: environment
    attributes:
      label: Environment
      description: Anything that will help us triage the bug.
      placeholder: |
        - OS: [e.g. Linux, OSX, WSL, etc]
        - Version [e.g. 10.15]
        - Module version
        - Terraform version
    validations:
      required: false

  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: |
        Add any other context about the problem here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false

contact_links:

  - name: Community Slack Team
    url: https://cloudposse.com/slack/
    about: |-
      Please ask and answer questions here.

  - name: Office Hours
    url: https://cloudposse.com/office-hours/
    about: |-
      Join us every Wednesday for FREE Office Hours (lunch & learn).

  - name: DevOps Accelerator Program
    url: https://cloudposse.com/accelerate/
    about: |-
      Own your infrastructure in record time. We build it. You drive it. 


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature Request
about: Suggest an idea for this project
title: ''
labels: 'feature request'
assignees: ''

---

Have a question? Please checkout our [Slack Community](https://slack.cloudposse.com) or visit our [Slack Archive](https://archive.sweetops.com/). 

[![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com)

## Describe the Feature

A clear and concise description of what the bug is. 

## Expected Behavior

A clear and concise description of what you expected to happen.

## Use Case

Is your feature request related to a problem/challenge you are trying to solve? Please provide some additional context of why this feature or capability will be valuable.

## Describe Ideal Solution

A clear and concise description of what you want to happen. If you don't know, that's okay.

## Alternatives Considered

Explain what alternative solutions or features you've considered.

## Additional Context

Add any other context or screenshots about the feature request here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.yml
================================================
---
name: Feature Request
description: Suggest an idea for this project
labels: ["feature request"]
assignees: [""]
body:
  - type: markdown
    attributes:
      value: |
        Have a question?
        
        Please checkout our [Slack Community](https://slack.cloudposse.com)
        or visit our [Slack Archive](https://archive.sweetops.com/).

        [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com)

  - type: textarea
    id: concise-description
    attributes:
      label: Describe the Feature
      description: A clear and concise description of what the feature is.
      placeholder: What is the feature about?
    validations:
      required: true

  - type: textarea
    id: expected
    attributes:
      label: Expected Behavior
      description: A clear and concise description of what you expected.
      placeholder: What happened?
    validations:
      required: true

  - type: textarea
    id: use-case
    attributes:
      label: Use Case
      description: |
        Is your feature request related to a problem/challenge you are trying
        to solve?
        
        Please provide some additional context of why this feature or
        capability will be valuable.
    validations:
      required: true

  - type: textarea
    id: ideal-solution
    attributes:
      label: Describe Ideal Solution
      description: A clear and concise description of what you want to happen.
    validations:
      required: true

  - type: textarea
    id: alternatives-considered
    attributes:
      label: Alternatives Considered
      description: Explain alternative solutions or features considered.
    validations:
      required: false

  - type: textarea
    id: additional
    attributes:
      label: Additional Context
      description: |
        Add any other context about the problem here.
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/question.md
================================================


================================================
FILE: .github/PULL_REQUEST_TEMPLATE.md
================================================
## what

<!--
- Describe high-level what changed as a result of these commits (i.e. in plain-english, what do these changes mean?)
- Use bullet points to be concise and to the point.
-->

## why

<!--
- Provide the justifications for the changes (e.g. business case). 
- Describe why these changes were made (e.g. why do these commits fix the problem?)
- Use bullet points to be concise and to the point.
-->

## references

<!--
- Link to any supporting github issues or helpful documentation to add some context (e.g. stackoverflow). 
- Use `closes #123`, if this PR closes a GitHub issue `#123`
-->


================================================
FILE: .github/mergify.yml
================================================
extends: .github


================================================
FILE: .github/renovate.json
================================================
{
  "extends": [
    "config:base",
    ":preserveSemverRanges",
    ":rebaseStalePrs"
  ],
  "baseBranches": ["main"],
  "labels": ["auto-update"],
  "dependencyDashboardAutoclose": true,
  "enabledManagers": ["terraform"],
  "terraform": {
    "ignorePaths": ["**/context.tf"]
  }
}


================================================
FILE: .github/settings.yml
================================================
# Upstream changes from _extends are only recognized when modifications are made to this file in the default branch.
_extends: .github
repository:
  name: terraform-aws-rds-cluster
  description: Terraform module to provision an RDS Aurora cluster for MySQL or Postgres
  homepage: https://cloudposse.com/accelerate
  topics: terraform, terraform-modules, rds, rds-database, aurora, aws, mysql, cluster, hcl2, terratest





================================================
FILE: .github/workflows/branch.yml
================================================
---
name: Branch
on:
  pull_request:
    branches:
      - main
      - release/**
    types: [opened, synchronize, reopened, labeled, unlabeled]
  push:
    branches:
      - main
      - release/v*
    paths-ignore:
      - '.github/**'
      - 'docs/**'
      - 'examples/**'
      - 'test/**'
      - 'README.md'

permissions: {}

jobs:
  terraform-module:
    uses: cloudposse/.github/.github/workflows/shared-terraform-module.yml@main
    secrets: inherit


================================================
FILE: .github/workflows/chatops.yml
================================================
---
name: chatops
on:
  issue_comment:
    types: [created]

permissions:
  pull-requests: write
  id-token: write
  contents: write
  statuses: write

jobs:
  test:
    uses: cloudposse/.github/.github/workflows/shared-terraform-chatops.yml@main
    if: ${{ github.event.issue.pull_request && contains(github.event.comment.body, '/terratest') }}
    secrets: inherit


================================================
FILE: .github/workflows/release.yml
================================================
---
name: release
on:
  release:
    types:
      - published

permissions:
  id-token: write
  contents: write
  pull-requests: write

jobs:
  terraform-module:
    uses: cloudposse/.github/.github/workflows/shared-release-branches.yml@main
    secrets: inherit


================================================
FILE: .github/workflows/scheduled.yml
================================================
---
name: scheduled
on:
  workflow_dispatch: { }  # Allows manually trigger this workflow
  schedule:
    - cron: "0 3 * * *"

permissions:
  pull-requests: write
  id-token: write
  contents: write

jobs:
  scheduled:
    uses: cloudposse/.github/.github/workflows/shared-terraform-scheduled.yml@main
    secrets: inherit


================================================
FILE: .gitignore
================================================
# Compiled files
*.tfstate
*.tfstate.backup

# Module directory
.terraform
.idea
*.iml

.build-harness
build-harness
.terraform.lock.hcl


================================================
FILE: LICENSE
================================================
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "{}"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright 2017-2023 Cloud Posse, LLC

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: README.md
================================================


<!-- markdownlint-disable -->
<a href="https://cpco.io/homepage"><img src="https://github.com/cloudposse/terraform-aws-rds-cluster/blob/main/.github/banner.png?raw=true" alt="Project Banner"/></a><br/>


<p align="right"><a href="https://github.com/cloudposse/terraform-aws-rds-cluster/releases/latest"><img src="https://img.shields.io/github/release/cloudposse/terraform-aws-rds-cluster.svg?style=for-the-badge" alt="Latest Release"/></a><a href="https://github.com/cloudposse/terraform-aws-rds-cluster/commits"><img src="https://img.shields.io/github/last-commit/cloudposse/terraform-aws-rds-cluster.svg?style=for-the-badge" alt="Last Updated"/></a><a href="https://cloudposse.com/slack"><img src="https://slack.cloudposse.com/for-the-badge.svg" alt="Slack Community"/></a><a href="https://cloudposse.com/support/"><img src="https://img.shields.io/badge/Get_Support-success.svg?style=for-the-badge" alt="Get Support"/></a>

</p>
<!-- markdownlint-restore -->

<!--




  ** DO NOT EDIT THIS FILE
  **
  ** This file was automatically generated by the `cloudposse/build-harness`.
  ** 1) Make all changes to `README.yaml`
  ** 2) Install [atmos](https://atmos.tools/install/) (you only need to do this once)
  ** 3) Run`atmos readme` to rebuild this file.
  **
  ** (We maintain HUNDREDS of open source projects. This is how we maintain our sanity.)
  **





-->

Terraform module to provision an [`RDS Aurora`](https://aws.amazon.com/rds/aurora) cluster for MySQL or Postgres.

Supports [Amazon Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/).


> [!TIP]
> #### 👽 Use Atmos with Terraform
> Cloud Posse uses [`atmos`](https://atmos.tools) to easily orchestrate multiple environments using Terraform. <br/>
> Works with [Github Actions](https://atmos.tools/integrations/github-actions/), [Atlantis](https://atmos.tools/integrations/atlantis), or [Spacelift](https://atmos.tools/integrations/spacelift).
>
> <details>
> <summary><strong>Watch demo of using Atmos with Terraform</strong></summary>
> <img src="https://github.com/cloudposse/atmos/blob/main/docs/demo.gif?raw=true"/><br/>
> <i>Example of running <a href="https://atmos.tools"><code>atmos</code></a> to manage infrastructure from our <a href="https://atmos.tools/quick-start/">Quick Start</a> tutorial.</i>
> </detalis>





## Usage


For a complete example, see [examples/complete](examples/complete).

For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test).

[Basic example](examples/basic)

```hcl
module "rds_cluster_aurora_postgres" {
  source = "cloudposse/rds-cluster/aws"
  # Cloud Posse recommends pinning every module to a specific version
  # version     = "x.x.x"

  name            = "postgres"
  engine          = "aurora-postgresql"
  cluster_family  = "aurora-postgresql9.6"
  # 1 writer, 1 reader
  cluster_size    = 2
  # 1 writer, 3 reader
  # cluster_size    = 4
  # 1 writer, 5 reader
  # cluster_size    = 6
  namespace       = "eg"
  stage           = "dev"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  db_port         = 5432
  instance_type   = "db.r4.large"
  vpc_id          = "vpc-xxxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"
}
```


[Serverless Aurora MySQL 5.6](examples/serverless_mysql)

```hcl
module "rds_cluster_aurora_mysql_serverless" {
  source = "cloudposse/rds-cluster/aws"
  # Cloud Posse recommends pinning every module to a specific version
  # version     = "x.x.x"
  namespace            = "eg"
  stage                = "dev"
  name                 = "db"
  engine               = "aurora"
  engine_mode          = "serverless"
  cluster_family       = "aurora5.6"
  cluster_size         = 0
  admin_user           = "admin1"
  admin_password       = "Test123456789"
  db_name              = "dbname"
  db_port              = 3306
  instance_type        = "db.t2.small"
  vpc_id               = "vpc-xxxxxxxx"
  security_groups      = ["sg-xxxxxxxx"]
  subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id              = "Zxxxxxxxx"
  enable_http_endpoint = true

  scaling_configuration = [
    {
      auto_pause               = true
      max_capacity             = 256
      min_capacity             = 2
      seconds_until_auto_pause = 300
    }
  ]
}
```

[Serverless Aurora 2.07.1 MySQL 5.7](examples/serverless_mysql57)

```hcl
module "rds_cluster_aurora_mysql_serverless" {
  source = "cloudposse/rds-cluster/aws"
  # Cloud Posse recommends pinning every module to a specific version
  # version     = "x.x.x"
  namespace            = "eg"
  stage                = "dev"
  name                 = "db"
  engine               = "aurora-mysql"
  engine_mode          = "serverless"
  engine_version       = "5.7.mysql_aurora.2.07.1"
  cluster_family       = "aurora-mysql5.7"
  cluster_size         = 0
  admin_user           = "admin1"
  admin_password       = "Test123456789"
  db_name              = "dbname"
  db_port              = 3306
  vpc_id               = "vpc-xxxxxxxx"
  security_groups      = ["sg-xxxxxxxx"]
  subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id              = "Zxxxxxxxx"
  enable_http_endpoint = true

  scaling_configuration = [
    {
      auto_pause               = true
      max_capacity             = 16
      min_capacity             = 1
      seconds_until_auto_pause = 300
      timeout_action           = "ForceApplyCapacityChange"
    }
  ]
}
```

[With cluster parameters](examples/with_cluster_parameters)

```hcl
module "rds_cluster_aurora_mysql" {
  source = "cloudposse/rds-cluster/aws"
  # Cloud Posse recommends pinning every module to a specific version
  # version     = "x.x.x"
  engine          = "aurora"
  cluster_family  = "aurora-mysql5.7"
  cluster_size    = 2
  namespace       = "eg"
  stage           = "dev"
  name            = "db"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  instance_type   = "db.t2.small"
  vpc_id          = "vpc-xxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"

  cluster_parameters = [
    {
      name  = "character_set_client"
      value = "utf8"
    },
    {
      name  = "character_set_connection"
      value = "utf8"
    },
    {
      name  = "character_set_database"
      value = "utf8"
    },
    {
      name  = "character_set_results"
      value = "utf8"
    },
    {
      name  = "character_set_server"
      value = "utf8"
    },
    {
      name  = "collation_connection"
      value = "utf8_bin"
    },
    {
      name  = "collation_server"
      value = "utf8_bin"
    },
    {
      name         = "lower_case_table_names"
      value        = "1"
      apply_method = "pending-reboot"
    },
    {
      name         = "skip-character-set-client-handshake"
      value        = "1"
      apply_method = "pending-reboot"
    }
  ]
}
```

[With enhanced monitoring](examples/enhanced_monitoring)

```hcl
# create IAM role for monitoring
resource "aws_iam_role" "enhanced_monitoring" {
  name               = "rds-cluster-example-1"
  assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring.json
}

# Attach Amazon's managed policy for RDS enhanced monitoring
resource "aws_iam_role_policy_attachment" "enhanced_monitoring" {
  role       = aws_iam_role.enhanced_monitoring.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
}

# allow rds to assume this role
data "aws_iam_policy_document" "enhanced_monitoring" {
  statement {
      actions = [
      "sts:AssumeRole",
    ]

    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["monitoring.rds.amazonaws.com"]
    }
  }
}

module "rds_cluster_aurora_postgres" {
  source = "cloudposse/rds-cluster/aws"
  # Cloud Posse recommends pinning every module to a specific version
  # version     = "x.x.x"
  engine          = "aurora-postgresql"
  cluster_family  = "aurora-postgresql9.6"
  cluster_size    = 2
  namespace       = "eg"
  stage           = "dev"
  name            = "db"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  db_port         = 5432
  instance_type   = "db.r4.large"
  vpc_id          = "vpc-xxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"

  # enable monitoring every 30 seconds
  rds_monitoring_interval = 30

  # reference iam role created above
  rds_monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn
}
```

> [!IMPORTANT]
> In Cloud Posse's examples, we avoid pinning modules to specific versions to prevent discrepancies between the documentation
> and the latest released versions. However, for your own projects, we strongly advise pinning each module to the exact version
> you're using. This practice ensures the stability of your infrastructure. Additionally, we recommend implementing a systematic
> approach for updating versions to avoid unexpected changes.





## Examples

Review the [complete example](examples/complete) to see how to use this module.




<!-- markdownlint-disable -->
## Requirements

| Name | Version |
| ---- | ------- |
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.0.0 |
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 5.81.0 |
| <a name="requirement_null"></a> [null](#requirement\_null) | >= 2.0 |
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 2.0 |

## Providers

| Name | Version |
| ---- | ------- |
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 5.81.0 |
| <a name="provider_random"></a> [random](#provider\_random) | >= 2.0 |

## Modules

| Name | Source | Version |
| ---- | ------ | ------- |
| <a name="module_dns_master"></a> [dns\_master](#module\_dns\_master) | cloudposse/route53-cluster-hostname/aws | 0.13.0 |
| <a name="module_dns_replicas"></a> [dns\_replicas](#module\_dns\_replicas) | cloudposse/route53-cluster-hostname/aws | 0.13.0 |
| <a name="module_enhanced_monitoring_label"></a> [enhanced\_monitoring\_label](#module\_enhanced\_monitoring\_label) | cloudposse/label/null | 0.25.0 |
| <a name="module_rds_identifier"></a> [rds\_identifier](#module\_rds\_identifier) | cloudposse/label/null | 0.25.0 |
| <a name="module_this"></a> [this](#module\_this) | cloudposse/label/null | 0.25.0 |

## Resources

| Name | Type |
| ---- | ---- |
| [aws_appautoscaling_policy.replicas](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | resource |
| [aws_appautoscaling_target.replicas](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | resource |
| [aws_db_parameter_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | resource |
| [aws_db_subnet_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | resource |
| [aws_iam_role.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource |
| [aws_iam_role_policy_attachment.enhanced_monitoring](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | resource |
| [aws_rds_cluster.primary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | resource |
| [aws_rds_cluster.secondary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | resource |
| [aws_rds_cluster_activity_stream.primary](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_activity_stream) | resource |
| [aws_rds_cluster_instance.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | resource |
| [aws_rds_cluster_parameter_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | resource |
| [aws_rds_reserved_instance.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_reserved_instance) | resource |
| [aws_security_group.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | resource |
| [aws_security_group_rule.egress](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.egress_ipv6](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.ingress_cidr_blocks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.ingress_ipv6_cidr_blocks](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.ingress_security_groups](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [aws_security_group_rule.traffic_inside_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | resource |
| [random_pet.instance](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource |
| [aws_iam_policy_document.enhanced_monitoring](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 |
| [aws_rds_reserved_instance_offering.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/rds_reserved_instance_offering) | data source |

## Inputs

| Name | Description | Type | Default | Required |
| ---- | ----------- | ---- | ------- | :------: |
| <a name="input_activity_stream_enabled"></a> [activity\_stream\_enabled](#input\_activity\_stream\_enabled) | Whether to enable Activity Streams | `bool` | `false` | no |
| <a name="input_activity_stream_kms_key_id"></a> [activity\_stream\_kms\_key\_id](#input\_activity\_stream\_kms\_key\_id) | The ARN for the KMS key to encrypt Activity Stream Data data. When specifying `activity_stream_kms_key_id`, `activity_stream_enabled` needs to be set to true | `string` | `""` | no |
| <a name="input_activity_stream_mode"></a> [activity\_stream\_mode](#input\_activity\_stream\_mode) | The mode for the Activity Streams. `async` and `sync` are supported. Defaults to `async` | `string` | `"async"` | no |
| <a name="input_additional_tag_map"></a> [additional\_tag\_map](#input\_additional\_tag\_map) | Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.<br/>This is for some rare cases where resources want additional configuration of tags<br/>and therefore take a list of maps with tag key, value, and additional configuration. | `map(string)` | `{}` | no |
| <a name="input_admin_password"></a> [admin\_password](#input\_admin\_password) | Password for the master DB user. Ignored if snapshot\_identifier or replication\_source\_identifier is provided | `string` | `""` | no |
| <a name="input_admin_user"></a> [admin\_user](#input\_admin\_user) | Username for the master DB user. Ignored if snapshot\_identifier or replication\_source\_identifier is provided | `string` | `"admin"` | no |
| <a name="input_admin_user_secret_kms_key_id"></a> [admin\_user\_secret\_kms\_key\_id](#input\_admin\_user\_secret\_kms\_key\_id) | Amazon Web Services KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key.<br/>To use a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN.<br/>If not specified, the default KMS key for your Amazon Web Services account is used. | `string` | `null` | no |
| <a name="input_allocated_storage"></a> [allocated\_storage](#input\_allocated\_storage) | The allocated storage in GBs | `number` | `null` | no |
| <a name="input_allow_major_version_upgrade"></a> [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 |
| <a name="input_allowed_cidr_blocks"></a> [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no |
| <a name="input_allowed_ipv6_cidr_blocks"></a> [allowed\_ipv6\_cidr\_blocks](#input\_allowed\_ipv6\_cidr\_blocks) | List of IPv6 CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no |
| <a name="input_apply_immediately"></a> [apply\_immediately](#input\_apply\_immediately) | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no |
| <a name="input_attributes"></a> [attributes](#input\_attributes) | ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,<br/>in the order they appear in the list. New attributes are appended to the<br/>end of the list. The elements of the list are joined by the `delimiter`<br/>and treated as a single ID element. | `list(string)` | `[]` | no |
| <a name="input_auto_minor_version_upgrade"></a> [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window | `bool` | `true` | no |
| <a name="input_autoscaling_enabled"></a> [autoscaling\_enabled](#input\_autoscaling\_enabled) | Whether to enable cluster autoscaling | `bool` | `false` | no |
| <a name="input_autoscaling_max_capacity"></a> [autoscaling\_max\_capacity](#input\_autoscaling\_max\_capacity) | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no |
| <a name="input_autoscaling_min_capacity"></a> [autoscaling\_min\_capacity](#input\_autoscaling\_min\_capacity) | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no |
| <a name="input_autoscaling_policy_type"></a> [autoscaling\_policy\_type](#input\_autoscaling\_policy\_type) | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no |
| <a name="input_autoscaling_scale_in_cooldown"></a> [autoscaling\_scale\_in\_cooldown](#input\_autoscaling\_scale\_in\_cooldown) | The amount of time, in seconds, after a scaling activity completes and before the next scaling down activity can start. Default is 300s | `number` | `300` | no |
| <a name="input_autoscaling_scale_out_cooldown"></a> [autoscaling\_scale\_out\_cooldown](#input\_autoscaling\_scale\_out\_cooldown) | The amount of time, in seconds, after a scaling activity completes and before the next scaling up activity can start. Default is 300s | `number` | `300` | no |
| <a name="input_autoscaling_target_metrics"></a> [autoscaling\_target\_metrics](#input\_autoscaling\_target\_metrics) | The metrics type to use. If this value isn't provided the default is CPU utilization | `string` | `"RDSReaderAverageCPUUtilization"` | no |
| <a name="input_autoscaling_target_value"></a> [autoscaling\_target\_value](#input\_autoscaling\_target\_value) | The target value to scale with respect to target metrics | `number` | `75` | no |
| <a name="input_backtrack_window"></a> [backtrack\_window](#input\_backtrack\_window) | The target backtrack window, in seconds. Only available for aurora engine currently. Must be between 0 and 259200 (72 hours) | `number` | `0` | no |
| <a name="input_backup_window"></a> [backup\_window](#input\_backup\_window) | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no |
| <a name="input_ca_cert_identifier"></a> [ca\_cert\_identifier](#input\_ca\_cert\_identifier) | The identifier of the CA certificate for the DB instance | `string` | `null` | no |
| <a name="input_cluster_dns_name"></a> [cluster\_dns\_name](#input\_cluster\_dns\_name) | Name of the cluster CNAME record to create in the parent DNS zone specified by `zone_id`. If left empty, the name will be auto-asigned using the format `master.var.name` | `string` | `""` | no |
| <a name="input_cluster_family"></a> [cluster\_family](#input\_cluster\_family) | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no |
| <a name="input_cluster_identifier"></a> [cluster\_identifier](#input\_cluster\_identifier) | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no |
| <a name="input_cluster_parameters"></a> [cluster\_parameters](#input\_cluster\_parameters) | List of DB cluster parameters to apply | <pre>list(object({<br/>    apply_method = string<br/>    name         = string<br/>    value        = string<br/>  }))</pre> | `[]` | no |
| <a name="input_cluster_size"></a> [cluster\_size](#input\_cluster\_size) | Number of DB instances to create in the cluster | `number` | `2` | no |
| <a name="input_cluster_type"></a> [cluster\_type](#input\_cluster\_type) | Either `regional` or `global`.<br/>If `regional` will be created as a normal, standalone DB.<br/>If `global`, will be made part of a Global cluster (requires `global_cluster_identifier`). | `string` | `"regional"` | no |
| <a name="input_context"></a> [context](#input\_context) | Single object for setting entire context at once.<br/>See description of individual variables for details.<br/>Leave string and numeric variables as `null` to use default value.<br/>Individual variable settings (non-null) override settings in context object,<br/>except for attributes, tags, and additional\_tag\_map, which are merged. | `any` | <pre>{<br/>  "additional_tag_map": {},<br/>  "attributes": [],<br/>  "delimiter": null,<br/>  "descriptor_formats": {},<br/>  "enabled": true,<br/>  "environment": null,<br/>  "id_length_limit": null,<br/>  "label_key_case": null,<br/>  "label_order": [],<br/>  "label_value_case": null,<br/>  "labels_as_tags": [<br/>    "unset"<br/>  ],<br/>  "name": null,<br/>  "namespace": null,<br/>  "regex_replace_chars": null,<br/>  "stage": null,<br/>  "tags": {},<br/>  "tenant": null<br/>}</pre> | no |
| <a name="input_copy_tags_to_snapshot"></a> [copy\_tags\_to\_snapshot](#input\_copy\_tags\_to\_snapshot) | Copy tags to backup snapshots | `bool` | `false` | no |
| <a name="input_database_insights_mode"></a> [database\_insights\_mode](#input\_database\_insights\_mode) | The database insights mode for the RDS cluster. Valid values are `standard`, `advanced`. See https://registry.terraform.io/providers/hashicorp/aws/6.16.0/docs/resources/rds_cluster#database_insights_mode-1 | `string` | `null` | no |
| <a name="input_db_cluster_instance_class"></a> [db\_cluster\_instance\_class](#input\_db\_cluster\_instance\_class) | This setting is required to create a provisioned Multi-AZ DB cluster | `string` | `null` | no |
| <a name="input_db_name"></a> [db\_name](#input\_db\_name) | Database name (default is not to create a database) | `string` | `""` | no |
| <a name="input_db_parameter_group_name"></a> [db\_parameter\_group\_name](#input\_db\_parameter\_group\_name) | The name to give to the created `aws_db_parameter_group` resource.<br/>If omitted, the module will generate a name. | `string` | `""` | no |
| <a name="input_db_port"></a> [db\_port](#input\_db\_port) | Database port | `number` | `3306` | no |
| <a name="input_deletion_protection"></a> [deletion\_protection](#input\_deletion\_protection) | If the DB instance should have deletion protection enabled | `bool` | `false` | no |
| <a name="input_delimiter"></a> [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.<br/>Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| <a name="input_descriptor_formats"></a> [descriptor\_formats](#input\_descriptor\_formats) | Describe additional descriptors to be output in the `descriptors` output map.<br/>Map of maps. Keys are names of descriptors. Values are maps of the form<br/>`{<br/>   format = string<br/>   labels = list(string)<br/>}`<br/>(Type is `any` so the map values can later be enhanced to provide additional options.)<br/>`format` is a Terraform format string to be passed to the `format()` function.<br/>`labels` is a list of labels, in order, to pass to `format()` function.<br/>Label values will be normalized before being passed to `format()` so they will be<br/>identical to how they appear in `id`.<br/>Default is `{}` (`descriptors` output will be empty). | `any` | `{}` | no |
| <a name="input_egress_enabled"></a> [egress\_enabled](#input\_egress\_enabled) | Whether or not to apply the egress security group rule to default security group, defaults to `true` | `bool` | `true` | no |
| <a name="input_enable_global_write_forwarding"></a> [enable\_global\_write\_forwarding](#input\_enable\_global\_write\_forwarding) | Set to `true`, to forward writes to an associated global cluster. | `bool` | `null` | no |
| <a name="input_enable_http_endpoint"></a> [enable\_http\_endpoint](#input\_enable\_http\_endpoint) | Enable HTTP endpoint (data API). | `bool` | `false` | no |
| <a name="input_enable_local_write_forwarding"></a> [enable\_local\_write\_forwarding](#input\_enable\_local\_write\_forwarding) | Set to `true`, to forward writes sent to a reader to the writer instance. | `bool` | `null` | no |
| <a name="input_enabled"></a> [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
| <a name="input_enabled_cloudwatch_logs_exports"></a> [enabled\_cloudwatch\_logs\_exports](#input\_enabled\_cloudwatch\_logs\_exports) | List of log types to export to cloudwatch. The following log types are supported: audit, error, general, slowquery | `list(string)` | `[]` | no |
| <a name="input_engine"></a> [engine](#input\_engine) | The name of the database engine to be used for this DB cluster. Valid values: `aurora`, `aurora-mysql`, `aurora-postgresql` | `string` | `"aurora"` | no |
| <a name="input_engine_mode"></a> [engine\_mode](#input\_engine\_mode) | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no |
| <a name="input_engine_version"></a> [engine\_version](#input\_engine\_version) | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no |
| <a name="input_enhanced_monitoring_attributes"></a> [enhanced\_monitoring\_attributes](#input\_enhanced\_monitoring\_attributes) | The attributes for the enhanced monitoring IAM role | `list(string)` | <pre>[<br/>  "enhanced-monitoring"<br/>]</pre> | no |
| <a name="input_enhanced_monitoring_role_enabled"></a> [enhanced\_monitoring\_role\_enabled](#input\_enhanced\_monitoring\_role\_enabled) | A boolean flag to enable/disable the creation of the enhanced monitoring IAM role. If set to `false`, the module will not create a new role and will use `rds_monitoring_role_arn` for enhanced monitoring | `bool` | `false` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| <a name="input_global_cluster_identifier"></a> [global\_cluster\_identifier](#input\_global\_cluster\_identifier) | ID of the Aurora global cluster | `string` | `""` | no |
| <a name="input_iam_database_authentication_enabled"></a> [iam\_database\_authentication\_enabled](#input\_iam\_database\_authentication\_enabled) | Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled | `bool` | `false` | no |
| <a name="input_iam_roles"></a> [iam\_roles](#input\_iam\_roles) | Iam roles for the Aurora cluster | `list(string)` | `[]` | no |
| <a name="input_id_length_limit"></a> [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).<br/>Set to `0` for unlimited length.<br/>Set to `null` for keep the existing setting, which defaults to `0`.<br/>Does not affect `id_full`. | `number` | `null` | no |
| <a name="input_instance_availability_zone"></a> [instance\_availability\_zone](#input\_instance\_availability\_zone) | Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly | `string` | `""` | no |
| <a name="input_instance_identifier_suffix"></a> [instance\_identifier\_suffix](#input\_instance\_identifier\_suffix) | The suffix to append to DB instance identifiers.<br/>If `null`, the module will generate a random suffix. If empty, no suffix will be appended. | `string` | `null` | no |
| <a name="input_instance_parameters"></a> [instance\_parameters](#input\_instance\_parameters) | List of DB instance parameters to apply | <pre>list(object({<br/>    apply_method = string<br/>    name         = string<br/>    value        = string<br/>  }))</pre> | `[]` | no |
| <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | Instance type to use | `string` | `"db.t2.small"` | no |
| <a name="input_intra_security_group_traffic_enabled"></a> [intra\_security\_group\_traffic\_enabled](#input\_intra\_security\_group\_traffic\_enabled) | Whether to allow traffic between resources inside the database's security group. | `bool` | `false` | no |
| <a name="input_iops"></a> [iops](#input\_iops) | The amount of provisioned IOPS. Setting this implies a storage\_type of 'io1'. This setting is required to create a Multi-AZ DB cluster. Check TF docs for values based on db engine | `number` | `null` | no |
| <a name="input_kms_key_arn"></a> [kms\_key\_arn](#input\_kms\_key\_arn) | The ARN for the KMS encryption key. When specifying `kms_key_arn`, `storage_encrypted` needs to be set to `true` | `string` | `""` | no |
| <a name="input_label_key_case"></a> [label\_key\_case](#input\_label\_key\_case) | Controls the letter case of the `tags` keys (label names) for tags generated by this module.<br/>Does not affect keys of tags passed in via the `tags` input.<br/>Possible values: `lower`, `title`, `upper`.<br/>Default value: `title`. | `string` | `null` | no |
| <a name="input_label_order"></a> [label\_order](#input\_label\_order) | The order in which the labels (ID elements) appear in the `id`.<br/>Defaults to ["namespace", "environment", "stage", "name", "attributes"].<br/>You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present. | `list(string)` | `null` | no |
| <a name="input_label_value_case"></a> [label\_value\_case](#input\_label\_value\_case) | Controls the letter case of ID elements (labels) as included in `id`,<br/>set as tag values, and output by this module individually.<br/>Does not affect values of tags passed in via the `tags` input.<br/>Possible values: `lower`, `title`, `upper` and `none` (no transformation).<br/>Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.<br/>Default value: `lower`. | `string` | `null` | no |
| <a name="input_labels_as_tags"></a> [labels\_as\_tags](#input\_labels\_as\_tags) | Set of labels (ID elements) to include as tags in the `tags` output.<br/>Default is to include all labels.<br/>Tags with empty values will not be included in the `tags` output.<br/>Set to `[]` to suppress all generated tags.<br/>**Notes:**<br/>  The value of the `name` tag, if included, will be the `id`, not the `name`.<br/>  Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be<br/>  changed in later chained modules. Attempts to change it will be silently ignored. | `set(string)` | <pre>[<br/>  "default"<br/>]</pre> | no |
| <a name="input_maintenance_window"></a> [maintenance\_window](#input\_maintenance\_window) | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no |
| <a name="input_manage_admin_user_password"></a> [manage\_admin\_user\_password](#input\_manage\_admin\_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` | `false` | no |
| <a name="input_name"></a> [name](#input\_name) | ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.<br/>This is the only ID element not also included as a `tag`.<br/>The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input. | `string` | `null` | no |
| <a name="input_namespace"></a> [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no |
| <a name="input_network_type"></a> [network\_type](#input\_network\_type) | The network type of the cluster. Valid values: IPV4, DUAL. | `string` | `"IPV4"` | no |
| <a name="input_parameter_group_name_prefix_enabled"></a> [parameter\_group\_name\_prefix\_enabled](#input\_parameter\_group\_name\_prefix\_enabled) | Set to `true` to use `name_prefix` to name the cluster and database parameter groups. Set to `false` to use `name` instead | `bool` | `true` | no |
| <a name="input_performance_insights_enabled"></a> [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | Whether to enable Performance Insights | `bool` | `false` | no |
| <a name="input_performance_insights_kms_key_id"></a> [performance\_insights\_kms\_key\_id](#input\_performance\_insights\_kms\_key\_id) | The ARN for the KMS key to encrypt Performance Insights data. When specifying `performance_insights_kms_key_id`, `performance_insights_enabled` needs to be set to true | `string` | `""` | no |
| <a name="input_performance_insights_retention_period"></a> [performance\_insights\_retention\_period](#input\_performance\_insights\_retention\_period) | Amount of time in days to retain Performance Insights data. Either 7 (7 days) or 731 (2 years) | `number` | `null` | no |
| <a name="input_promotion_tier"></a> [promotion\_tier](#input\_promotion\_tier) | Failover Priority setting on instance level. The reader who has lower tier has higher priority to get promoted to writer.<br/><br/>Readers in promotion tiers 0 and 1 scale at the same time as the writer. Readers in promotion tiers 2–15 scale independently from the writer. For more information, see: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html#aurora-serverless-v2.how-it-works.scaling | `number` | `0` | no |
| <a name="input_publicly_accessible"></a> [publicly\_accessible](#input\_publicly\_accessible) | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no |
| <a name="input_rds_cluster_parameter_group_name"></a> [rds\_cluster\_parameter\_group\_name](#input\_rds\_cluster\_parameter\_group\_name) | The name to give to the created `aws_rds_cluster_parameter_group` resource.<br/>If omitted, the module will generate a name. | `string` | `""` | no |
| <a name="input_rds_monitoring_interval"></a> [rds\_monitoring\_interval](#input\_rds\_monitoring\_interval) | The interval, in seconds, between points when enhanced monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60 | `number` | `0` | no |
| <a name="input_rds_monitoring_role_arn"></a> [rds\_monitoring\_role\_arn](#input\_rds\_monitoring\_role\_arn) | The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no |
| <a name="input_rds_ri_duration"></a> [rds\_ri\_duration](#input\_rds\_ri\_duration) | The number of years to reserve the instance. Values can be 1 or 3 (or in seconds, 31536000 or 94608000) | `number` | `1` | no |
| <a name="input_rds_ri_offering_type"></a> [rds\_ri\_offering\_type](#input\_rds\_ri\_offering\_type) | Offering type of reserved DB instances. Valid values are 'No Upfront', 'Partial Upfront', 'All Upfront'. | `string` | `""` | no |
| <a name="input_rds_ri_reservation_id"></a> [rds\_ri\_reservation\_id](#input\_rds\_ri\_reservation\_id) | Customer-specified identifier to track the reservation of the reserved DB instance. | `string` | `null` | no |
| <a name="input_reader_dns_name"></a> [reader\_dns\_name](#input\_reader\_dns\_name) | Name of the reader endpoint CNAME record to create in the parent DNS zone specified by `zone_id`. If left empty, the name will be auto-asigned using the format `replicas.var.name` | `string` | `""` | no |
| <a name="input_regex_replace_chars"></a> [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.<br/>Characters matching the regex will be removed from the ID elements.<br/>If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no |
| <a name="input_replication_source_identifier"></a> [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` | `""` | no |
| <a name="input_restore_to_point_in_time"></a> [restore\_to\_point\_in\_time](#input\_restore\_to\_point\_in\_time) | List of point-in-time recovery options. Valid parameters are:<br/><br/>`source_cluster_identifier`<br/>  Identifier of the source database cluster from which to restore.<br/>`restore_type`:<br/>  Type of restore to be performed. Valid options are "full-copy" and "copy-on-write".<br/>`use_latest_restorable_time`:<br/>  Set to true to restore the database cluster to the latest restorable backup time. Conflicts with `restore_to_time`.<br/>`restore_to_time`:<br/>  Date and time in UTC format to restore the database cluster to. Conflicts with `use_latest_restorable_time`. | <pre>list(object({<br/>    source_cluster_identifier  = string<br/>    restore_type               = optional(string, "copy-on-write")<br/>    use_latest_restorable_time = optional(bool, true)<br/>    restore_to_time            = optional(string, null)<br/>  }))</pre> | `[]` | no |
| <a name="input_retention_period"></a> [retention\_period](#input\_retention\_period) | Number of days to retain backups for | `number` | `5` | no |
| <a name="input_s3_import"></a> [s3\_import](#input\_s3\_import) | Restore from a Percona Xtrabackup in S3. The `bucket_name` is required to be in the same region as the resource. | <pre>object({<br/>    bucket_name           = string<br/>    bucket_prefix         = string<br/>    ingestion_role        = string<br/>    source_engine         = string<br/>    source_engine_version = string<br/>  })</pre> | `null` | no |
| <a name="input_scaling_configuration"></a> [scaling\_configuration](#input\_scaling\_configuration) | List of nested attributes with scaling properties. Only valid when `engine_mode` is set to `serverless` | <pre>list(object({<br/>    auto_pause               = bool<br/>    max_capacity             = number<br/>    min_capacity             = number<br/>    seconds_until_auto_pause = number<br/>    timeout_action           = string<br/>  }))</pre> | `[]` | no |
| <a name="input_security_groups"></a> [security\_groups](#input\_security\_groups) | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no |
| <a name="input_serverlessv2_scaling_configuration"></a> [serverlessv2\_scaling\_configuration](#input\_serverlessv2\_scaling\_configuration) | serverlessv2 scaling properties | <pre>object({<br/>    min_capacity             = number<br/>    max_capacity             = number<br/>    seconds_until_auto_pause = optional(number, null)<br/>  })</pre> | `null` | no |
| <a name="input_skip_final_snapshot"></a> [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no |
| <a name="input_snapshot_identifier"></a> [snapshot\_identifier](#input\_snapshot\_identifier) | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no |
| <a name="input_source_region"></a> [source\_region](#input\_source\_region) | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no |
| <a name="input_stage"></a> [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
| <a name="input_storage_encrypted"></a> [storage\_encrypted](#input\_storage\_encrypted) | Specifies whether the DB cluster is encrypted. The default is `false` for `provisioned` `engine_mode` and `true` for `serverless` `engine_mode` | `bool` | `false` | no |
| <a name="input_storage_type"></a> [storage\_type](#input\_storage\_type) | One of 'standard' (magnetic), 'gp2' (general purpose SSD), 'io1' (provisioned IOPS SSD), 'aurora', or 'aurora-iopt1' | `string` | `null` | no |
| <a name="input_subnet_group_name"></a> [subnet\_group\_name](#input\_subnet\_group\_name) | Database subnet group name. Will use generated label ID if not supplied. | `string` | `""` | no |
| <a name="input_subnets"></a> [subnets](#input\_subnets) | List of VPC subnet IDs | `list(string)` | n/a | yes |
| <a name="input_tags"></a> [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).<br/>Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no |
| <a name="input_tenant"></a> [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no |
| <a name="input_timeouts_configuration"></a> [timeouts\_configuration](#input\_timeouts\_configuration) | List of timeout values per action. Only valid actions are `create`, `update` and `delete` | <pre>list(object({<br/>    create = string<br/>    update = string<br/>    delete = string<br/>  }))</pre> | `[]` | no |
| <a name="input_use_reserved_instances"></a> [use\_reserved\_instances](#input\_use\_reserved\_instances) | WARNING: Observe your plans and applies carefully when using this feature.<br/>It has potential to be very expensive if not used correctly.<br/>Also, it is not clear what happens when the reservation expires.<br/><br/>Whether to use reserved instances. | `bool` | `false` | no |
| <a name="input_vpc_id"></a> [vpc\_id](#input\_vpc\_id) | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes |
| <a name="input_vpc_security_group_ids"></a> [vpc\_security\_group\_ids](#input\_vpc\_security\_group\_ids) | Additional security group IDs to apply to the cluster, in addition to the provisioned default security group with ingress traffic from existing CIDR blocks and existing security groups | `list(string)` | `[]` | no |
| <a name="input_zone_id"></a> [zone\_id](#input\_zone\_id) | Route53 DNS Zone ID as list of string (0 or 1 items). If empty, no custom DNS name will be published.<br/>If the list contains a single Zone ID, a custom DNS name will be pulished in that zone.<br/>Can also be a plain string, but that use is DEPRECATED because of Terraform issues. | `any` | `[]` | no |

## Outputs

| Name | Description |
| ---- | ----------- |
| <a name="output_activity_stream_arn"></a> [activity\_stream\_arn](#output\_activity\_stream\_arn) | Activity Stream ARN |
| <a name="output_activity_stream_name"></a> [activity\_stream\_name](#output\_activity\_stream\_name) | Activity Stream Name |
| <a name="output_admin_user_secret"></a> [admin\_user\_secret](#output\_admin\_user\_secret) | The secret manager attributes for the managed admin user password (`master_user_secret`). |
| <a name="output_arn"></a> [arn](#output\_arn) | Amazon Resource Name (ARN) of the cluster |
| <a name="output_cluster_identifier"></a> [cluster\_identifier](#output\_cluster\_identifier) | Cluster Identifier |
| <a name="output_cluster_resource_id"></a> [cluster\_resource\_id](#output\_cluster\_resource\_id) | The region-unique, immutable identifie of the cluster |
| <a name="output_cluster_security_groups"></a> [cluster\_security\_groups](#output\_cluster\_security\_groups) | Default RDS cluster security groups |
| <a name="output_database_name"></a> [database\_name](#output\_database\_name) | Database name |
| <a name="output_dbi_resource_ids"></a> [dbi\_resource\_ids](#output\_dbi\_resource\_ids) | List of the region-unique, immutable identifiers for the DB instances in the cluster |
| <a name="output_endpoint"></a> [endpoint](#output\_endpoint) | The DNS address of the RDS instance |
| <a name="output_instance_arns"></a> [instance\_arns](#output\_instance\_arns) | List of ARNs of the DB instances in the cluster |
| <a name="output_instance_endpoints"></a> [instance\_endpoints](#output\_instance\_endpoints) | List of DNS addresses for the DB instances in the cluster |
| <a name="output_master_host"></a> [master\_host](#output\_master\_host) | DB Master hostname |
| <a name="output_master_username"></a> [master\_username](#output\_master\_username) | Username for the master DB user |
| <a name="output_port"></a> [port](#output\_port) | DB port |
| <a name="output_reader_endpoint"></a> [reader\_endpoint](#output\_reader\_endpoint) | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas |
| <a name="output_replicas_host"></a> [replicas\_host](#output\_replicas\_host) | Replicas hostname |
| <a name="output_reserved_instance"></a> [reserved\_instance](#output\_reserved\_instance) | All information about the reserved instance(s) if created. |
| <a name="output_security_group_arn"></a> [security\_group\_arn](#output\_security\_group\_arn) | Security Group ARN |
| <a name="output_security_group_id"></a> [security\_group\_id](#output\_security\_group\_id) | Security Group ID |
| <a name="output_security_group_name"></a> [security\_group\_name](#output\_security\_group\_name) | Security Group name |
<!-- markdownlint-restore -->







## Related Projects

Check out these related projects.

- [terraform-aws-rds](https://github.com/cloudposse/terraform-aws-rds) - Terraform module to provision AWS RDS instances
- [terraform-aws-rds-cloudwatch-sns-alarms](https://github.com/cloudposse/terraform-aws-rds-cloudwatch-sns-alarms) - Terraform module that configures important RDS alerts using CloudWatch and sends them to an SNS topic


> [!TIP]
> #### Use Terraform Reference Architectures for AWS
>
> Use Cloud Posse's ready-to-go [terraform architecture blueprints](https://cloudposse.com/reference-architecture/) for AWS to get up and running quickly.
>
> ✅ We build it together with your team.<br/>
> ✅ Your team owns everything.<br/>
> ✅ 100% Open Source and backed by fanatical support.<br/>
>
> <a href="https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=commercial_support"><img alt="Request Quote" src="https://img.shields.io/badge/request%20quote-success.svg?style=for-the-badge"/></a>
> <details><summary>📚 <strong>Learn More</strong></summary>
>
> <br/>
>
> Cloud Posse is the leading [**DevOps Accelerator**](https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=commercial_support) for funded startups and enterprises.
>
> *Your team can operate like a pro today.*
>
> Ensure that your team succeeds by using Cloud Posse's proven process and turnkey blueprints. Plus, we stick around until you succeed.
> #### Day-0:  Your Foundation for Success
> - **Reference Architecture.** You'll get everything you need from the ground up built using 100% infrastructure as code.
> - **Deployment Strategy.** Adopt a proven deployment strategy with GitHub Actions, enabling automated, repeatable, and reliable software releases.
> - **Site Reliability Engineering.** Gain total visibility into your applications and services with Datadog, ensuring high availability and performance.
> - **Security Baseline.** Establish a secure environment from the start, with built-in governance, accountability, and comprehensive audit logs, safeguarding your operations.
> - **GitOps.** Empower your team to manage infrastructure changes confidently and efficiently through Pull Requests, leveraging the full power of GitHub Actions.
>
> <a href="https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=commercial_support"><img alt="Request Quote" src="https://img.shields.io/badge/request%20quote-success.svg?style=for-the-badge"/></a>
>
> #### Day-2: Your Operational Mastery
> - **Training.** Equip your team with the knowledge and skills to confidently manage the infrastructure, ensuring long-term success and self-sufficiency.
> - **Support.** Benefit from a seamless communication over Slack with our experts, ensuring you have the support you need, whenever you need it.
> - **Troubleshooting.** Access expert assistance to quickly resolve any operational challenges, minimizing downtime and maintaining business continuity.
> - **Code Reviews.** Enhance your team’s code quality with our expert feedback, fostering continuous improvement and collaboration.
> - **Bug Fixes.** Rely on our team to troubleshoot and resolve any issues, ensuring your systems run smoothly.
> - **Migration Assistance.** Accelerate your migration process with our dedicated support, minimizing disruption and speeding up time-to-value.
> - **Customer Workshops.** Engage with our team in weekly workshops, gaining insights and strategies to continuously improve and innovate.
>
> <a href="https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=commercial_support"><img alt="Request Quote" src="https://img.shields.io/badge/request%20quote-success.svg?style=for-the-badge"/></a>
> 
</details>

## ✨ Contributing

This project is under active development, and we encourage contributions from our community.



Many thanks to our outstanding contributors:

<a href="https://github.com/cloudposse/terraform-aws-rds-cluster/graphs/contributors">
  <img src="https://contrib.rocks/image?repo=cloudposse/terraform-aws-rds-cluster&max=24" />
</a>

For 🐛 bug reports & feature requests, please use the [issue tracker](https://github.com/cloudposse/terraform-aws-rds-cluster/issues).

In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow.
 1. Review our [Code of Conduct](https://github.com/cloudposse/terraform-aws-rds-cluster/?tab=coc-ov-file#code-of-conduct) and [Contributor Guidelines](https://github.com/cloudposse/.github/blob/main/CONTRIBUTING.md).
 2. **Fork** the repo on GitHub
 3. **Clone** the project to your own machine
 4. **Commit** changes to your own branch
 5. **Push** your work back up to your fork
 6. Submit a **Pull Request** so that we can review your changes

**NOTE:** Be sure to merge the latest changes from "upstream" before making a pull request!


## Running Terraform Tests

We use [Atmos](https://atmos.tools) to streamline how Terraform tests are run. It centralizes configuration and wraps common test workflows with easy-to-use commands.

All tests are located in the [`test/`](test) folder.

Under the hood, tests are powered by Terratest together with our internal [Test Helpers](https://github.com/cloudposse/test-helpers) library, providing robust infrastructure validation.

Setup dependencies:
- Install Atmos ([installation guide](https://atmos.tools/install/))
- Install Go [1.24+ or newer](https://go.dev/doc/install)
- Install Terraform or OpenTofu

To run tests:

- Run all tests:  
  ```sh
  atmos test run
  ```
- Clean up test artifacts:  
  ```sh
  atmos test clean
  ```
- Explore additional test options:  
  ```sh
  atmos test --help
  ```
The configuration for test commands is centrally managed. To review what's being imported, see the [`atmos.yaml`](https://raw.githubusercontent.com/cloudposse/.github/refs/heads/main/.github/atmos/terraform-module.yaml) file.

Learn more about our [automated testing in our documentation](https://docs.cloudposse.com/community/contribute/automated-testing/) or implementing [custom commands](https://atmos.tools/core-concepts/custom-commands/) with atmos.

### 🌎 Slack Community

Join our [Open Source Community](https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=slack) on Slack. It's **FREE** for everyone! Our "SweetOps" community is where you get to talk with others who share a similar vision for how to rollout and manage infrastructure. This is the best place to talk shop, ask questions, solicit feedback, and work together as a community to build totally *sweet* infrastructure.

### 📰 Newsletter

Sign up for [our newsletter](https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=newsletter) and join 3,000+ DevOps engineers, CTOs, and founders who get insider access to the latest DevOps trends, so you can always stay in the know.
Dropped straight into your Inbox every week — and usually a 5-minute read.

### 📆 Office Hours <a href="https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=office_hours"><img src="https://img.cloudposse.com/fit-in/200x200/https://cloudposse.com/wp-content/uploads/2019/08/Powered-by-Zoom.png" align="right" /></a>

[Join us every Wednesday via Zoom](https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=office_hours) for your weekly dose of insider DevOps trends, AWS news and Terraform insights, all sourced from our SweetOps community, plus a _live Q&A_ that you can’t find anywhere else.
It's **FREE** for everyone!
## License

<a href="https://opensource.org/licenses/Apache-2.0"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=for-the-badge" alt="License"></a>

<details>
<summary>Preamble to the Apache License, Version 2.0</summary>
<br/>
<br/>

Complete license is available in the [`LICENSE`](LICENSE) file.

```text
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

  https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
```
</details>

## Trademarks

All other trademarks referenced herein are the property of their respective owners.


---
Copyright © 2017-2026 [Cloud Posse, LLC](https://cpco.io/copyright)


<a href="https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-cluster&utm_content=readme_footer_link"><img alt="README footer" src="https://cloudposse.com/readme/footer/img"/></a>

<img alt="Beacon" width="0" src="https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-aws-rds-cluster?pixel&cs=github&cm=readme&an=terraform-aws-rds-cluster"/>


================================================
FILE: README.yaml
================================================
name: terraform-aws-rds-cluster

tags:
  - aws
  - terraform
  - terraform-modules
  - databases
  - rds
  - rds-database
  - aurora
  - mysql
  - cluster

categories:
  - terraform-modules/databases

license: APACHE2

github_repo: cloudposse/terraform-aws-rds-cluster

badges:
  - name: Latest Release
    image: https://img.shields.io/github/release/cloudposse/terraform-aws-rds-cluster.svg?style=for-the-badge
    url: https://github.com/cloudposse/terraform-aws-rds-cluster/releases/latest
  - name: Last Updated
    image: https://img.shields.io/github/last-commit/cloudposse/terraform-aws-rds-cluster.svg?style=for-the-badge
    url: https://github.com/cloudposse/terraform-aws-rds-cluster/commits
  - name: Slack Community
    image: https://slack.cloudposse.com/for-the-badge.svg
    url: https://cloudposse.com/slack

# List any related terraform modules that this module may be used with or that this module depends on.
related:
  - name: terraform-aws-rds
    description: Terraform module to provision AWS RDS instances
    url: https://github.com/cloudposse/terraform-aws-rds
  - name: terraform-aws-rds-cloudwatch-sns-alarms
    description: Terraform module that configures important RDS alerts using CloudWatch and sends them to an SNS topic
    url: https://github.com/cloudposse/terraform-aws-rds-cloudwatch-sns-alarms

description: |-
  Terraform module to provision an [`RDS Aurora`](https://aws.amazon.com/rds/aurora) cluster for MySQL or Postgres.

  Supports [Amazon Aurora Serverless](https://aws.amazon.com/rds/aurora/serverless/).

usage: |2-

  For a complete example, see [examples/complete](examples/complete).

  For automated tests of the complete example using [bats](https://github.com/bats-core/bats-core) and [Terratest](https://github.com/gruntwork-io/terratest) (which tests and deploys the example on AWS), see [test](test).

  [Basic example](examples/basic)

  ```hcl
  module "rds_cluster_aurora_postgres" {
    source = "cloudposse/rds-cluster/aws"
    # Cloud Posse recommends pinning every module to a specific version
    # version     = "x.x.x"

    name            = "postgres"
    engine          = "aurora-postgresql"
    cluster_family  = "aurora-postgresql9.6"
    # 1 writer, 1 reader
    cluster_size    = 2
    # 1 writer, 3 reader
    # cluster_size    = 4
    # 1 writer, 5 reader
    # cluster_size    = 6
    namespace       = "eg"
    stage           = "dev"
    admin_user      = "admin1"
    admin_password  = "Test123456789"
    db_name         = "dbname"
    db_port         = 5432
    instance_type   = "db.r4.large"
    vpc_id          = "vpc-xxxxxxxx"
    security_groups = ["sg-xxxxxxxx"]
    subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
    zone_id         = "Zxxxxxxxx"
  }
  ```


  [Serverless Aurora MySQL 5.6](examples/serverless_mysql)

  ```hcl
  module "rds_cluster_aurora_mysql_serverless" {
    source = "cloudposse/rds-cluster/aws"
    # Cloud Posse recommends pinning every module to a specific version
    # version     = "x.x.x"
    namespace            = "eg"
    stage                = "dev"
    name                 = "db"
    engine               = "aurora"
    engine_mode          = "serverless"
    cluster_family       = "aurora5.6"
    cluster_size         = 0
    admin_user           = "admin1"
    admin_password       = "Test123456789"
    db_name              = "dbname"
    db_port              = 3306
    instance_type        = "db.t2.small"
    vpc_id               = "vpc-xxxxxxxx"
    security_groups      = ["sg-xxxxxxxx"]
    subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
    zone_id              = "Zxxxxxxxx"
    enable_http_endpoint = true

    scaling_configuration = [
      {
        auto_pause               = true
        max_capacity             = 256
        min_capacity             = 2
        seconds_until_auto_pause = 300
      }
    ]
  }
  ```

  [Serverless Aurora 2.07.1 MySQL 5.7](examples/serverless_mysql57)

  ```hcl
  module "rds_cluster_aurora_mysql_serverless" {
    source = "cloudposse/rds-cluster/aws"
    # Cloud Posse recommends pinning every module to a specific version
    # version     = "x.x.x"
    namespace            = "eg"
    stage                = "dev"
    name                 = "db"
    engine               = "aurora-mysql"
    engine_mode          = "serverless"
    engine_version       = "5.7.mysql_aurora.2.07.1"
    cluster_family       = "aurora-mysql5.7"
    cluster_size         = 0
    admin_user           = "admin1"
    admin_password       = "Test123456789"
    db_name              = "dbname"
    db_port              = 3306
    vpc_id               = "vpc-xxxxxxxx"
    security_groups      = ["sg-xxxxxxxx"]
    subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
    zone_id              = "Zxxxxxxxx"
    enable_http_endpoint = true

    scaling_configuration = [
      {
        auto_pause               = true
        max_capacity             = 16
        min_capacity             = 1
        seconds_until_auto_pause = 300
        timeout_action           = "ForceApplyCapacityChange"
      }
    ]
  }
  ```

  [With cluster parameters](examples/with_cluster_parameters)

  ```hcl
  module "rds_cluster_aurora_mysql" {
    source = "cloudposse/rds-cluster/aws"
    # Cloud Posse recommends pinning every module to a specific version
    # version     = "x.x.x"
    engine          = "aurora"
    cluster_family  = "aurora-mysql5.7"
    cluster_size    = 2
    namespace       = "eg"
    stage           = "dev"
    name            = "db"
    admin_user      = "admin1"
    admin_password  = "Test123456789"
    db_name         = "dbname"
    instance_type   = "db.t2.small"
    vpc_id          = "vpc-xxxxxxx"
    security_groups = ["sg-xxxxxxxx"]
    subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
    zone_id         = "Zxxxxxxxx"

    cluster_parameters = [
      {
        name  = "character_set_client"
        value = "utf8"
      },
      {
        name  = "character_set_connection"
        value = "utf8"
      },
      {
        name  = "character_set_database"
        value = "utf8"
      },
      {
        name  = "character_set_results"
        value = "utf8"
      },
      {
        name  = "character_set_server"
        value = "utf8"
      },
      {
        name  = "collation_connection"
        value = "utf8_bin"
      },
      {
        name  = "collation_server"
        value = "utf8_bin"
      },
      {
        name         = "lower_case_table_names"
        value        = "1"
        apply_method = "pending-reboot"
      },
      {
        name         = "skip-character-set-client-handshake"
        value        = "1"
        apply_method = "pending-reboot"
      }
    ]
  }
  ```

  [With enhanced monitoring](examples/enhanced_monitoring)

  ```hcl
  # create IAM role for monitoring
  resource "aws_iam_role" "enhanced_monitoring" {
    name               = "rds-cluster-example-1"
    assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring.json
  }

  # Attach Amazon's managed policy for RDS enhanced monitoring
  resource "aws_iam_role_policy_attachment" "enhanced_monitoring" {
    role       = aws_iam_role.enhanced_monitoring.name
    policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
  }

  # allow rds to assume this role
  data "aws_iam_policy_document" "enhanced_monitoring" {
    statement {
        actions = [
        "sts:AssumeRole",
      ]

      effect = "Allow"

      principals {
        type        = "Service"
        identifiers = ["monitoring.rds.amazonaws.com"]
      }
    }
  }

  module "rds_cluster_aurora_postgres" {
    source = "cloudposse/rds-cluster/aws"
    # Cloud Posse recommends pinning every module to a specific version
    # version     = "x.x.x"
    engine          = "aurora-postgresql"
    cluster_family  = "aurora-postgresql9.6"
    cluster_size    = 2
    namespace       = "eg"
    stage           = "dev"
    name            = "db"
    admin_user      = "admin1"
    admin_password  = "Test123456789"
    db_name         = "dbname"
    db_port         = 5432
    instance_type   = "db.r4.large"
    vpc_id          = "vpc-xxxxxxx"
    security_groups = ["sg-xxxxxxxx"]
    subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
    zone_id         = "Zxxxxxxxx"

    # enable monitoring every 30 seconds
    rds_monitoring_interval = 30

    # reference iam role created above
    rds_monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn
  }
  ```

examples: |-
  Review the [complete example](examples/complete) to see how to use this module.

include: []
contributors: []


================================================
FILE: atmos.yaml
================================================
# Atmos Configuration — powered by https://atmos.tools
#
# This configuration enables centralized, DRY, and consistent project scaffolding using Atmos.
#
# Included features:
# - Organizational custom commands: https://atmos.tools/core-concepts/custom-commands
# - Automated README generation: https://atmos.tools/cli/commands/docs/generate
#

# Import shared configuration used by all modules
import:
  - https://raw.githubusercontent.com/cloudposse/.github/refs/heads/main/.github/atmos/terraform-module.yaml


================================================
FILE: context.tf
================================================
#
# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
# All other instances of this file should be a copy of that one
#
#
# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
# and then place it in your Terraform module to automatically get
# Cloud Posse's standard configuration inputs suitable for passing
# to Cloud Posse modules.
#
# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf
#
# Modules should access the whole context as `module.this.context`
# to get the input variables with nulls for defaults,
# for example `context = module.this.context`,
# and access individual variables as `module.this.<var>`,
# with final values filled in.
#
# For example, when using defaults, `module.this.context.delimiter`
# will be null, and `module.this.delimiter` will be `-` (hyphen).
#

module "this" {
  source  = "cloudposse/label/null"
  version = "0.25.0" # requires Terraform >= 0.13.0

  enabled             = var.enabled
  namespace           = var.namespace
  tenant              = var.tenant
  environment         = var.environment
  stage               = var.stage
  name                = var.name
  delimiter           = var.delimiter
  attributes          = var.attributes
  tags                = var.tags
  additional_tag_map  = var.additional_tag_map
  label_order         = var.label_order
  regex_replace_chars = var.regex_replace_chars
  id_length_limit     = var.id_length_limit
  label_key_case      = var.label_key_case
  label_value_case    = var.label_value_case
  descriptor_formats  = var.descriptor_formats
  labels_as_tags      = var.labels_as_tags

  context = var.context
}

# Copy contents of cloudposse/terraform-null-label/variables.tf here

variable "context" {
  type = any
  default = {
    enabled             = true
    namespace           = null
    tenant              = null
    environment         = null
    stage               = null
    name                = null
    delimiter           = null
    attributes          = []
    tags                = {}
    additional_tag_map  = {}
    regex_replace_chars = null
    label_order         = []
    id_length_limit     = null
    label_key_case      = null
    label_value_case    = null
    descriptor_formats  = {}
    # Note: we have to use [] instead of null for unset lists due to
    # https://github.com/hashicorp/terraform/issues/28137
    # which was not fixed until Terraform 1.0.0,
    # but we want the default to be all the labels in `label_order`
    # and we want users to be able to prevent all tag generation
    # by setting `labels_as_tags` to `[]`, so we need
    # a different sentinel to indicate "default"
    labels_as_tags = ["unset"]
  }
  description = <<-EOT
    Single object for setting entire context at once.
    See description of individual variables for details.
    Leave string and numeric variables as `null` to use default value.
    Individual variable settings (non-null) override settings in context object,
    except for attributes, tags, and additional_tag_map, which are merged.
  EOT

  validation {
    condition     = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }

  validation {
    condition     = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "enabled" {
  type        = bool
  default     = null
  description = "Set to false to prevent the module from creating any resources"
}

variable "namespace" {
  type        = string
  default     = null
  description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique"
}

variable "tenant" {
  type        = string
  default     = null
  description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for"
}

variable "environment" {
  type        = string
  default     = null
  description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'"
}

variable "stage" {
  type        = string
  default     = null
  description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'"
}

variable "name" {
  type        = string
  default     = null
  description = <<-EOT
    ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
    This is the only ID element not also included as a `tag`.
    The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input.
    EOT
}

variable "delimiter" {
  type        = string
  default     = null
  description = <<-EOT
    Delimiter to be used between ID elements.
    Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
  EOT
}

variable "attributes" {
  type        = list(string)
  default     = []
  description = <<-EOT
    ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
    in the order they appear in the list. New attributes are appended to the
    end of the list. The elements of the list are joined by the `delimiter`
    and treated as a single ID element.
    EOT
}

variable "labels_as_tags" {
  type        = set(string)
  default     = ["default"]
  description = <<-EOT
    Set of labels (ID elements) to include as tags in the `tags` output.
    Default is to include all labels.
    Tags with empty values will not be included in the `tags` output.
    Set to `[]` to suppress all generated tags.
    **Notes:**
      The value of the `name` tag, if included, will be the `id`, not the `name`.
      Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
      changed in later chained modules. Attempts to change it will be silently ignored.
    EOT
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
    Neither the tag keys nor the tag values will be modified by this module.
    EOT
}

variable "additional_tag_map" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
    This is for some rare cases where resources want additional configuration of tags
    and therefore take a list of maps with tag key, value, and additional configuration.
    EOT
}

variable "label_order" {
  type        = list(string)
  default     = null
  description = <<-EOT
    The order in which the labels (ID elements) appear in the `id`.
    Defaults to ["namespace", "environment", "stage", "name", "attributes"].
    You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.
    EOT
}

variable "regex_replace_chars" {
  type        = string
  default     = null
  description = <<-EOT
    Terraform regular expression (regex) string.
    Characters matching the regex will be removed from the ID elements.
    If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
  EOT
}

variable "id_length_limit" {
  type        = number
  default     = null
  description = <<-EOT
    Limit `id` to this many characters (minimum 6).
    Set to `0` for unlimited length.
    Set to `null` for keep the existing setting, which defaults to `0`.
    Does not affect `id_full`.
  EOT
  validation {
    condition     = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0
    error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length."
  }
}

variable "label_key_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of the `tags` keys (label names) for tags generated by this module.
    Does not affect keys of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper`.
    Default value: `title`.
  EOT

  validation {
    condition     = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case)
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }
}

variable "label_value_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of ID elements (labels) as included in `id`,
    set as tag values, and output by this module individually.
    Does not affect values of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper` and `none` (no transformation).
    Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
    Default value: `lower`.
  EOT

  validation {
    condition     = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case)
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "descriptor_formats" {
  type        = any
  default     = {}
  description = <<-EOT
    Describe additional descriptors to be output in the `descriptors` output map.
    Map of maps. Keys are names of descriptors. Values are maps of the form
    `{
       format = string
       labels = list(string)
    }`
    (Type is `any` so the map values can later be enhanced to provide additional options.)
    `format` is a Terraform format string to be passed to the `format()` function.
    `labels` is a list of labels, in order, to pass to `format()` function.
    Label values will be normalized before being passed to `format()` so they will be
    identical to how they appear in `id`.
    Default is `{}` (`descriptors` output will be empty).
    EOT
}

#### End of copy of cloudposse/terraform-null-label/variables.tf


================================================
FILE: enhanced-monitoring.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance#monitoring_role_arn

module "enhanced_monitoring_label" {
  source  = "cloudposse/label/null"
  version = "0.25.0"

  enabled    = module.this.enabled && var.enhanced_monitoring_role_enabled
  attributes = var.enhanced_monitoring_attributes

  context = module.this.context
}

# Create IAM role for enhanced monitoring
resource "aws_iam_role" "enhanced_monitoring" {
  count              = module.this.enabled && var.enhanced_monitoring_role_enabled ? 1 : 0
  name               = module.enhanced_monitoring_label.id
  assume_role_policy = join("", data.aws_iam_policy_document.enhanced_monitoring[*].json)
  tags               = module.enhanced_monitoring_label.tags
}

# Attach Amazon's managed policy for RDS enhanced monitoring
resource "aws_iam_role_policy_attachment" "enhanced_monitoring" {
  count      = module.this.enabled && var.enhanced_monitoring_role_enabled ? 1 : 0
  role       = join("", aws_iam_role.enhanced_monitoring[*].name)
  policy_arn = "arn:${local.partition}:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
}

# Allow RDS monitoring to assume the enhanced monitoring role
data "aws_iam_policy_document" "enhanced_monitoring" {
  count = module.this.enabled && var.enhanced_monitoring_role_enabled ? 1 : 0

  statement {
    actions = [
      "sts:AssumeRole"
    ]

    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["monitoring.rds.amazonaws.com"]
    }
  }
}


================================================
FILE: examples/basic/main.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html

provider "aws" {
  region = "us-west-1"
}

module "rds_cluster_aurora_postgres" {
  source          = "../../"
  name            = "postgres"
  engine          = "aurora-postgresql"
  cluster_family  = "aurora-postgresql9.6"
  cluster_size    = 2
  namespace       = "eg"
  stage           = "dev"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  db_port         = 5432
  instance_type   = "db.r4.large"
  vpc_id          = "vpc-xxxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"
}


================================================
FILE: examples/basic/outputs.tf
================================================
output "name" {
  value       = module.rds_cluster_aurora_postgres.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_postgres.master_username
  description = "Username for the master DB user"
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_postgres.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_postgres.arn
  description = "Amazon Resource Name (ARN) of cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_postgres.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_postgres.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_postgres.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_postgres.replicas_host
  description = "Replicas hostname"
}


================================================
FILE: examples/complete/context.tf
================================================
#
# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
# All other instances of this file should be a copy of that one
#
#
# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
# and then place it in your Terraform module to automatically get
# Cloud Posse's standard configuration inputs suitable for passing
# to Cloud Posse modules.
#
# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf
#
# Modules should access the whole context as `module.this.context`
# to get the input variables with nulls for defaults,
# for example `context = module.this.context`,
# and access individual variables as `module.this.<var>`,
# with final values filled in.
#
# For example, when using defaults, `module.this.context.delimiter`
# will be null, and `module.this.delimiter` will be `-` (hyphen).
#

module "this" {
  source  = "cloudposse/label/null"
  version = "0.25.0" # requires Terraform >= 0.13.0

  enabled             = var.enabled
  namespace           = var.namespace
  tenant              = var.tenant
  environment         = var.environment
  stage               = var.stage
  name                = var.name
  delimiter           = var.delimiter
  attributes          = var.attributes
  tags                = var.tags
  additional_tag_map  = var.additional_tag_map
  label_order         = var.label_order
  regex_replace_chars = var.regex_replace_chars
  id_length_limit     = var.id_length_limit
  label_key_case      = var.label_key_case
  label_value_case    = var.label_value_case
  descriptor_formats  = var.descriptor_formats
  labels_as_tags      = var.labels_as_tags

  context = var.context
}

# Copy contents of cloudposse/terraform-null-label/variables.tf here

variable "context" {
  type = any
  default = {
    enabled             = true
    namespace           = null
    tenant              = null
    environment         = null
    stage               = null
    name                = null
    delimiter           = null
    attributes          = []
    tags                = {}
    additional_tag_map  = {}
    regex_replace_chars = null
    label_order         = []
    id_length_limit     = null
    label_key_case      = null
    label_value_case    = null
    descriptor_formats  = {}
    # Note: we have to use [] instead of null for unset lists due to
    # https://github.com/hashicorp/terraform/issues/28137
    # which was not fixed until Terraform 1.0.0,
    # but we want the default to be all the labels in `label_order`
    # and we want users to be able to prevent all tag generation
    # by setting `labels_as_tags` to `[]`, so we need
    # a different sentinel to indicate "default"
    labels_as_tags = ["unset"]
  }
  description = <<-EOT
    Single object for setting entire context at once.
    See description of individual variables for details.
    Leave string and numeric variables as `null` to use default value.
    Individual variable settings (non-null) override settings in context object,
    except for attributes, tags, and additional_tag_map, which are merged.
  EOT

  validation {
    condition     = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }

  validation {
    condition     = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "enabled" {
  type        = bool
  default     = null
  description = "Set to false to prevent the module from creating any resources"
}

variable "namespace" {
  type        = string
  default     = null
  description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique"
}

variable "tenant" {
  type        = string
  default     = null
  description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for"
}

variable "environment" {
  type        = string
  default     = null
  description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'"
}

variable "stage" {
  type        = string
  default     = null
  description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'"
}

variable "name" {
  type        = string
  default     = null
  description = <<-EOT
    ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
    This is the only ID element not also included as a `tag`.
    The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input.
    EOT
}

variable "delimiter" {
  type        = string
  default     = null
  description = <<-EOT
    Delimiter to be used between ID elements.
    Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
  EOT
}

variable "attributes" {
  type        = list(string)
  default     = []
  description = <<-EOT
    ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
    in the order they appear in the list. New attributes are appended to the
    end of the list. The elements of the list are joined by the `delimiter`
    and treated as a single ID element.
    EOT
}

variable "labels_as_tags" {
  type        = set(string)
  default     = ["default"]
  description = <<-EOT
    Set of labels (ID elements) to include as tags in the `tags` output.
    Default is to include all labels.
    Tags with empty values will not be included in the `tags` output.
    Set to `[]` to suppress all generated tags.
    **Notes:**
      The value of the `name` tag, if included, will be the `id`, not the `name`.
      Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
      changed in later chained modules. Attempts to change it will be silently ignored.
    EOT
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
    Neither the tag keys nor the tag values will be modified by this module.
    EOT
}

variable "additional_tag_map" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
    This is for some rare cases where resources want additional configuration of tags
    and therefore take a list of maps with tag key, value, and additional configuration.
    EOT
}

variable "label_order" {
  type        = list(string)
  default     = null
  description = <<-EOT
    The order in which the labels (ID elements) appear in the `id`.
    Defaults to ["namespace", "environment", "stage", "name", "attributes"].
    You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.
    EOT
}

variable "regex_replace_chars" {
  type        = string
  default     = null
  description = <<-EOT
    Terraform regular expression (regex) string.
    Characters matching the regex will be removed from the ID elements.
    If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
  EOT
}

variable "id_length_limit" {
  type        = number
  default     = null
  description = <<-EOT
    Limit `id` to this many characters (minimum 6).
    Set to `0` for unlimited length.
    Set to `null` for keep the existing setting, which defaults to `0`.
    Does not affect `id_full`.
  EOT
  validation {
    condition     = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0
    error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length."
  }
}

variable "label_key_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of the `tags` keys (label names) for tags generated by this module.
    Does not affect keys of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper`.
    Default value: `title`.
  EOT

  validation {
    condition     = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case)
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }
}

variable "label_value_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of ID elements (labels) as included in `id`,
    set as tag values, and output by this module individually.
    Does not affect values of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper` and `none` (no transformation).
    Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
    Default value: `lower`.
  EOT

  validation {
    condition     = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case)
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "descriptor_formats" {
  type        = any
  default     = {}
  description = <<-EOT
    Describe additional descriptors to be output in the `descriptors` output map.
    Map of maps. Keys are names of descriptors. Values are maps of the form
    `{
       format = string
       labels = list(string)
    }`
    (Type is `any` so the map values can later be enhanced to provide additional options.)
    `format` is a Terraform format string to be passed to the `format()` function.
    `labels` is a list of labels, in order, to pass to `format()` function.
    Label values will be normalized before being passed to `format()` so they will be
    identical to how they appear in `id`.
    Default is `{}` (`descriptors` output will be empty).
    EOT
}

#### End of copy of cloudposse/terraform-null-label/variables.tf


================================================
FILE: examples/complete/fixtures.us-east-2.tfvars
================================================
region = "us-east-2"

availability_zones = ["us-east-2a", "us-east-2b"]

namespace = "eg"

stage = "test"

name = "rds-cluster"

# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.DBInstanceClass.html#Concepts.DBInstanceClass.SupportAurora
instance_type = "db.t3.medium"

cluster_family = "aurora-mysql8.0"

engine = "aurora-mysql"

engine_mode = "provisioned"

cluster_size = 1

deletion_protection = false

autoscaling_enabled = false

db_name = "test_db"

admin_user = "admin"

admin_password = "admin_password"

enhanced_monitoring_role_enabled = true

rds_monitoring_interval = 30

intra_security_group_traffic_enabled = true


================================================
FILE: examples/complete/main.tf
================================================
provider "aws" {
  region = var.region
}

module "vpc" {
  source  = "cloudposse/vpc/aws"
  version = "2.2.0"

  ipv4_primary_cidr_block = "172.16.0.0/16"

  context = module.this.context
}

module "subnets" {
  source  = "cloudposse/dynamic-subnets/aws"
  version = "2.4.2"

  availability_zones   = var.availability_zones
  vpc_id               = module.vpc.vpc_id
  igw_id               = [module.vpc.igw_id]
  ipv4_cidr_block      = [module.vpc.vpc_cidr_block]
  nat_gateway_enabled  = false
  nat_instance_enabled = false

  context = module.this.context
}

module "rds_cluster" {
  source = "../../"

  engine                               = var.engine
  engine_mode                          = var.engine_mode
  cluster_family                       = var.cluster_family
  cluster_size                         = var.cluster_size
  admin_user                           = var.admin_user
  admin_password                       = var.admin_password
  db_name                              = var.db_name
  instance_type                        = var.instance_type
  vpc_id                               = module.vpc.vpc_id
  subnets                              = module.subnets.private_subnet_ids
  security_groups                      = [module.vpc.vpc_default_security_group_id]
  deletion_protection                  = var.deletion_protection
  autoscaling_enabled                  = var.autoscaling_enabled
  storage_type                         = var.storage_type
  iops                                 = var.iops
  allocated_storage                    = var.allocated_storage
  intra_security_group_traffic_enabled = var.intra_security_group_traffic_enabled

  cluster_parameters = [
    {
      name         = "character_set_client"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_connection"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_database"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_results"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_server"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "collation_connection"
      value        = "utf8_bin"
      apply_method = "pending-reboot"
    },
    {
      name         = "collation_server"
      value        = "utf8_bin"
      apply_method = "pending-reboot"
    },
    {
      name         = "lower_case_table_names"
      value        = "1"
      apply_method = "pending-reboot"
    },
    {
      name         = "skip-character-set-client-handshake"
      value        = "1"
      apply_method = "pending-reboot"
    }
  ]

  context = module.this.context
}


================================================
FILE: examples/complete/outputs.tf
================================================
output "database_name" {
  value       = module.rds_cluster.database_name
  description = "Database name"
}

output "cluster_identifier" {
  value       = module.rds_cluster.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster.arn
  description = "Amazon Resource Name (ARN) of the cluster"
}

output "endpoint" {
  value       = module.rds_cluster.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster.replicas_host
  description = "Replicas hostname"
}

output "dbi_resource_ids" {
  value       = module.rds_cluster.dbi_resource_ids
  description = "List of the region-unique, immutable identifiers for the DB instances in the cluster"
}

output "cluster_resource_id" {
  value       = module.rds_cluster.cluster_resource_id
  description = "The region-unique, immutable identifie of the cluster"
}

output "public_subnet_cidrs" {
  value       = module.subnets.public_subnet_cidrs
  description = "Public subnet CIDR blocks"
}

output "private_subnet_cidrs" {
  value       = module.subnets.private_subnet_cidrs
  description = "Private subnet CIDR blocks"
}

output "vpc_cidr" {
  value       = module.vpc.vpc_cidr_block
  description = "VPC CIDR"
}

output "security_group_id" {
  value       = module.rds_cluster.security_group_id
  description = "Security Group ID"
}

output "security_group_arn" {
  value       = module.rds_cluster.security_group_arn
  description = "Security Group ARN"
}

output "security_group_name" {
  value       = module.rds_cluster.security_group_name
  description = "Security Group name"
}


================================================
FILE: examples/complete/variables.tf
================================================
variable "region" {
  type        = string
  description = "AWS region"
}

variable "availability_zones" {
  type        = list(string)
  description = "Availability zones"
}

variable "instance_type" {
  type        = string
  description = "Instance type to use"
}

variable "cluster_size" {
  type        = number
  description = "Number of DB instances to create in the cluster"
}

variable "db_name" {
  type        = string
  description = "Database name"
}

variable "admin_user" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Username for the master DB user"
}

variable "admin_password" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Password for the master DB user"
}

variable "cluster_family" {
  type        = string
  description = "The family of the DB cluster parameter group"
}

variable "engine" {
  type        = string
  description = "The name of the database engine to be used for this DB cluster. Valid values: `aurora`, `aurora-mysql`, `aurora-postgresql`"
}

variable "engine_mode" {
  type        = string
  description = "The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless`"
}

variable "deletion_protection" {
  type        = bool
  description = "If the DB instance should have deletion protection enabled"
}

variable "autoscaling_enabled" {
  type        = bool
  description = "Whether to enable cluster autoscaling"
}

variable "enhanced_monitoring_role_enabled" {
  type        = bool
  description = "A boolean flag to enable/disable the creation of the enhanced monitoring IAM role. If set to `false`, the module will not create a new role and will use `rds_monitoring_role_arn` for enhanced monitoring"
}

variable "rds_monitoring_interval" {
  type        = number
  description = "The interval, in seconds, between points when enhanced monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60"
}

variable "storage_type" {
  type        = string
  description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD)"
  default     = null
}

variable "iops" {
  type        = number
  description = "The amount of provisioned IOPS. Setting this implies a storage_type of 'io1'. This setting is required to create a Multi-AZ DB cluster. Check TF docs for values based on db engine"
  default     = null
}

variable "allocated_storage" {
  type        = number
  description = "The allocated storage in GBs"
  default     = null
}

variable "intra_security_group_traffic_enabled" {
  type        = bool
  default     = false
  description = "Whether to allow traffic between resources inside the database's security group."
}


================================================
FILE: examples/complete/versions.tf
================================================
terraform {
  required_version = ">= 1.1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.17.0"
    }
    null = {
      source  = "hashicorp/null"
      version = ">= 2.0"
    }
  }
}


================================================
FILE: examples/enhanced_monitoring/main.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html

provider "aws" {
  region = "us-west-1"
}

# create IAM role for monitoring
resource "aws_iam_role" "enhanced_monitoring" {
  name               = "rds-cluster-example-1"
  assume_role_policy = data.aws_iam_policy_document.enhanced_monitoring.json
}

# Attach Amazon's managed policy for RDS enhanced monitoring
resource "aws_iam_role_policy_attachment" "enhanced_monitoring" {
  role       = aws_iam_role.enhanced_monitoring.name
  policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole"
}

# allow rds to assume this role
data "aws_iam_policy_document" "enhanced_monitoring" {
  statement {
    actions = [
      "sts:AssumeRole",
    ]

    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["monitoring.rds.amazonaws.com"]
    }
  }
}

module "rds_cluster_aurora_postgres" {
  source          = "../../"
  engine          = "aurora-postgresql"
  cluster_family  = "aurora-postgresql9.6"
  cluster_size    = 2
  namespace       = "eg"
  stage           = "dev"
  name            = "db"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  db_port         = 5432
  instance_type   = "db.r4.large"
  vpc_id          = "vpc-xxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"

  # enable monitoring every 30 seconds
  rds_monitoring_interval = 30

  # reference iam role created above
  rds_monitoring_role_arn = aws_iam_role.enhanced_monitoring.arn
}


================================================
FILE: examples/enhanced_monitoring/outputs.tf
================================================
output "name" {
  value       = module.rds_cluster_aurora_postgres.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_postgres.master_username
  description = "Username for the master DB user"
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_postgres.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_postgres.arn
  description = "Amazon Resource Name (ARN) of cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_postgres.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_postgres.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_postgres.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_postgres.replicas_host
  description = "Replicas hostname"
}


================================================
FILE: examples/postgres/context.tf
================================================
#
# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
# All other instances of this file should be a copy of that one
#
#
# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
# and then place it in your Terraform module to automatically get
# Cloud Posse's standard configuration inputs suitable for passing
# to Cloud Posse modules.
#
# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf
#
# Modules should access the whole context as `module.this.context`
# to get the input variables with nulls for defaults,
# for example `context = module.this.context`,
# and access individual variables as `module.this.<var>`,
# with final values filled in.
#
# For example, when using defaults, `module.this.context.delimiter`
# will be null, and `module.this.delimiter` will be `-` (hyphen).
#

module "this" {
  source  = "cloudposse/label/null"
  version = "0.25.0" # requires Terraform >= 0.13.0

  enabled             = var.enabled
  namespace           = var.namespace
  tenant              = var.tenant
  environment         = var.environment
  stage               = var.stage
  name                = var.name
  delimiter           = var.delimiter
  attributes          = var.attributes
  tags                = var.tags
  additional_tag_map  = var.additional_tag_map
  label_order         = var.label_order
  regex_replace_chars = var.regex_replace_chars
  id_length_limit     = var.id_length_limit
  label_key_case      = var.label_key_case
  label_value_case    = var.label_value_case
  descriptor_formats  = var.descriptor_formats
  labels_as_tags      = var.labels_as_tags

  context = var.context
}

# Copy contents of cloudposse/terraform-null-label/variables.tf here

variable "context" {
  type = any
  default = {
    enabled             = true
    namespace           = null
    tenant              = null
    environment         = null
    stage               = null
    name                = null
    delimiter           = null
    attributes          = []
    tags                = {}
    additional_tag_map  = {}
    regex_replace_chars = null
    label_order         = []
    id_length_limit     = null
    label_key_case      = null
    label_value_case    = null
    descriptor_formats  = {}
    # Note: we have to use [] instead of null for unset lists due to
    # https://github.com/hashicorp/terraform/issues/28137
    # which was not fixed until Terraform 1.0.0,
    # but we want the default to be all the labels in `label_order`
    # and we want users to be able to prevent all tag generation
    # by setting `labels_as_tags` to `[]`, so we need
    # a different sentinel to indicate "default"
    labels_as_tags = ["unset"]
  }
  description = <<-EOT
    Single object for setting entire context at once.
    See description of individual variables for details.
    Leave string and numeric variables as `null` to use default value.
    Individual variable settings (non-null) override settings in context object,
    except for attributes, tags, and additional_tag_map, which are merged.
  EOT

  validation {
    condition     = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }

  validation {
    condition     = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "enabled" {
  type        = bool
  default     = null
  description = "Set to false to prevent the module from creating any resources"
}

variable "namespace" {
  type        = string
  default     = null
  description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique"
}

variable "tenant" {
  type        = string
  default     = null
  description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for"
}

variable "environment" {
  type        = string
  default     = null
  description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'"
}

variable "stage" {
  type        = string
  default     = null
  description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'"
}

variable "name" {
  type        = string
  default     = null
  description = <<-EOT
    ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
    This is the only ID element not also included as a `tag`.
    The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input.
    EOT
}

variable "delimiter" {
  type        = string
  default     = null
  description = <<-EOT
    Delimiter to be used between ID elements.
    Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
  EOT
}

variable "attributes" {
  type        = list(string)
  default     = []
  description = <<-EOT
    ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
    in the order they appear in the list. New attributes are appended to the
    end of the list. The elements of the list are joined by the `delimiter`
    and treated as a single ID element.
    EOT
}

variable "labels_as_tags" {
  type        = set(string)
  default     = ["default"]
  description = <<-EOT
    Set of labels (ID elements) to include as tags in the `tags` output.
    Default is to include all labels.
    Tags with empty values will not be included in the `tags` output.
    Set to `[]` to suppress all generated tags.
    **Notes:**
      The value of the `name` tag, if included, will be the `id`, not the `name`.
      Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
      changed in later chained modules. Attempts to change it will be silently ignored.
    EOT
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
    Neither the tag keys nor the tag values will be modified by this module.
    EOT
}

variable "additional_tag_map" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
    This is for some rare cases where resources want additional configuration of tags
    and therefore take a list of maps with tag key, value, and additional configuration.
    EOT
}

variable "label_order" {
  type        = list(string)
  default     = null
  description = <<-EOT
    The order in which the labels (ID elements) appear in the `id`.
    Defaults to ["namespace", "environment", "stage", "name", "attributes"].
    You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.
    EOT
}

variable "regex_replace_chars" {
  type        = string
  default     = null
  description = <<-EOT
    Terraform regular expression (regex) string.
    Characters matching the regex will be removed from the ID elements.
    If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
  EOT
}

variable "id_length_limit" {
  type        = number
  default     = null
  description = <<-EOT
    Limit `id` to this many characters (minimum 6).
    Set to `0` for unlimited length.
    Set to `null` for keep the existing setting, which defaults to `0`.
    Does not affect `id_full`.
  EOT
  validation {
    condition     = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0
    error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length."
  }
}

variable "label_key_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of the `tags` keys (label names) for tags generated by this module.
    Does not affect keys of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper`.
    Default value: `title`.
  EOT

  validation {
    condition     = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case)
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }
}

variable "label_value_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of ID elements (labels) as included in `id`,
    set as tag values, and output by this module individually.
    Does not affect values of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper` and `none` (no transformation).
    Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
    Default value: `lower`.
  EOT

  validation {
    condition     = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case)
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "descriptor_formats" {
  type        = any
  default     = {}
  description = <<-EOT
    Describe additional descriptors to be output in the `descriptors` output map.
    Map of maps. Keys are names of descriptors. Values are maps of the form
    `{
       format = string
       labels = list(string)
    }`
    (Type is `any` so the map values can later be enhanced to provide additional options.)
    `format` is a Terraform format string to be passed to the `format()` function.
    `labels` is a list of labels, in order, to pass to `format()` function.
    Label values will be normalized before being passed to `format()` so they will be
    identical to how they appear in `id`.
    Default is `{}` (`descriptors` output will be empty).
    EOT
}

#### End of copy of cloudposse/terraform-null-label/variables.tf


================================================
FILE: examples/postgres/fixtures.us-east-2.tfvars
================================================
region = "us-east-2"

availability_zones = ["us-east-2a", "us-east-2b", "us-east-2c"]

namespace = "eg"

stage = "test"

name = "rds-cluster"

# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Concepts.DBInstanceClass.html#Concepts.DBInstanceClass.SupportAurora
# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance
instance_type = "db.t3.large"

cluster_family = "aurora-postgresql15"

engine_version = "15.13"

engine = "aurora-postgresql"

engine_mode = "provisioned"

cluster_size = 1

deletion_protection = false

autoscaling_enabled = false

db_name = "test_db"

admin_user = "admin_test"

admin_password = "admin_password"

enhanced_monitoring_role_enabled = true

rds_monitoring_interval = 30


================================================
FILE: examples/postgres/main.tf
================================================
provider "aws" {
  region = var.region
}

module "vpc" {
  source  = "cloudposse/vpc/aws"
  version = "2.2.0"

  ipv4_primary_cidr_block = "172.16.0.0/16"

  context = module.this.context
}

module "subnets" {
  source  = "cloudposse/dynamic-subnets/aws"
  version = "2.4.2"

  availability_zones   = var.availability_zones
  vpc_id               = module.vpc.vpc_id
  igw_id               = [module.vpc.igw_id]
  ipv4_cidr_block      = [module.vpc.vpc_cidr_block]
  nat_gateway_enabled  = false
  nat_instance_enabled = false

  context = module.this.context
}

module "rds_cluster" {
  source = "../../"

  engine                    = var.engine
  engine_mode               = var.engine_mode
  engine_version            = var.engine_version
  cluster_family            = var.cluster_family
  cluster_size              = contains(regex("^(?:.*(aurora))?.*$", var.engine), "aurora") ? var.cluster_size : 0
  admin_user                = var.admin_user
  admin_password            = var.admin_password
  db_name                   = var.db_name
  instance_type             = var.instance_type
  db_cluster_instance_class = var.db_cluster_instance_class
  vpc_id                    = module.vpc.vpc_id
  subnets                   = module.subnets.private_subnet_ids
  security_groups           = [module.vpc.vpc_default_security_group_id]
  deletion_protection       = var.deletion_protection
  autoscaling_enabled       = var.autoscaling_enabled
  storage_type              = var.storage_type
  iops                      = var.iops
  allocated_storage         = var.allocated_storage

  context = module.this.context
}


================================================
FILE: examples/postgres/outputs.tf
================================================
output "database_name" {
  value       = module.rds_cluster.database_name
  description = "Database name"
}

output "cluster_identifier" {
  value       = module.rds_cluster.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster.arn
  description = "Amazon Resource Name (ARN) of the cluster"
}

output "endpoint" {
  value       = module.rds_cluster.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster.replicas_host
  description = "Replicas hostname"
}

output "dbi_resource_ids" {
  value       = module.rds_cluster.dbi_resource_ids
  description = "List of the region-unique, immutable identifiers for the DB instances in the cluster"
}

output "cluster_resource_id" {
  value       = module.rds_cluster.cluster_resource_id
  description = "The region-unique, immutable identifie of the cluster"
}

output "public_subnet_cidrs" {
  value       = module.subnets.public_subnet_cidrs
  description = "Public subnet CIDR blocks"
}

output "private_subnet_cidrs" {
  value       = module.subnets.private_subnet_cidrs
  description = "Private subnet CIDR blocks"
}

output "vpc_cidr" {
  value       = module.vpc.vpc_cidr_block
  description = "VPC CIDR"
}

output "security_group_id" {
  value       = module.rds_cluster.security_group_id
  description = "Security Group ID"
}

output "security_group_arn" {
  value       = module.rds_cluster.security_group_arn
  description = "Security Group ARN"
}

output "security_group_name" {
  value       = module.rds_cluster.security_group_name
  description = "Security Group name"
}


================================================
FILE: examples/postgres/variables.tf
================================================
variable "region" {
  type        = string
  description = "AWS region"
}

variable "availability_zones" {
  type        = list(string)
  description = "Availability Zones for the instance"
}

variable "instance_type" {
  type        = string
  description = "Instance type to use"
}

variable "cluster_size" {
  type        = number
  description = "Number of DB instances to create in the cluster"
}

variable "db_name" {
  type        = string
  description = "Database name"
}

variable "admin_user" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Username for the master DB user"
}

variable "admin_password" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Password for the master DB user"
}

variable "cluster_family" {
  type        = string
  description = "The family of the DB cluster parameter group"
}

variable "engine" {
  type        = string
  description = "The name of the database engine to be used for this DB cluster. Valid values: `aurora`, `aurora-mysql`, `aurora-postgresql`"
}

variable "engine_mode" {
  type        = string
  description = "The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless`"
}

variable "engine_version" {
  type        = string
  default     = ""
  description = "The version of the database engine to use. See `aws rds describe-db-engine-versions` "
}

variable "deletion_protection" {
  type        = bool
  description = "If the DB instance should have deletion protection enabled"
}

variable "autoscaling_enabled" {
  type        = bool
  description = "Whether to enable cluster autoscaling"
}

variable "enhanced_monitoring_role_enabled" {
  type        = bool
  description = "A boolean flag to enable/disable the creation of the enhanced monitoring IAM role. If set to `false`, the module will not create a new role and will use `rds_monitoring_role_arn` for enhanced monitoring"
}

variable "rds_monitoring_interval" {
  type        = number
  description = "The interval, in seconds, between points when enhanced monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60"
}

variable "storage_type" {
  type        = string
  description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD)"
  default     = null
}

variable "iops" {
  type        = number
  description = "The amount of provisioned IOPS. Setting this implies a storage_type of 'io1'. This setting is required to create a Multi-AZ DB cluster. Check TF docs for values based on db engine"
  default     = null
}

variable "allocated_storage" {
  type        = number
  description = "The allocated storage in GBs"
  default     = null
}

variable "db_cluster_instance_class" {
  type        = string
  default     = null
  description = "This setting is required to create a Multi-AZ RDS cluster (not Aurora)"
}


================================================
FILE: examples/postgres/versions.tf
================================================
terraform {
  required_version = ">= 1.1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.17.0"
    }
    null = {
      source  = "hashicorp/null"
      version = ">= 2.0"
    }
  }
}


================================================
FILE: examples/serverless_mysql/main.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.20180206.html
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html

provider "aws" {
  region = "us-west-1"
}

module "rds_cluster_aurora_mysql_serverless" {
  source               = "../../"
  namespace            = "eg"
  stage                = "dev"
  name                 = "db"
  engine               = "aurora"
  engine_mode          = "serverless"
  cluster_family       = "aurora5.6"
  cluster_size         = 0
  admin_user           = "admin1"
  admin_password       = "Test123456789"
  db_name              = "dbname"
  db_port              = 3306
  instance_type        = "db.t2.small"
  vpc_id               = "vpc-xxxxxxxx"
  security_groups      = ["sg-xxxxxxxx"]
  subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id              = "Zxxxxxxxx"
  enable_http_endpoint = true

  scaling_configuration = [
    {
      auto_pause               = true
      max_capacity             = 256
      min_capacity             = 2
      seconds_until_auto_pause = 300
    }
  ]
}


================================================
FILE: examples/serverless_mysql/outputs.tf
================================================
output "name" {
  value       = module.rds_cluster_aurora_mysql_serverless.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_mysql_serverless.master_username
  description = "Username for the master DB user"
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_mysql_serverless.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_mysql_serverless.arn
  description = "Amazon Resource Name (ARN) of cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_mysql_serverless.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_mysql_serverless.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_mysql_serverless.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_mysql_serverless.replicas_host
  description = "Replicas hostname"
}


================================================
FILE: examples/serverless_mysql57/main.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.serverless_2_07_01.html
# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html

provider "aws" {
  region = "us-west-1"
}

module "rds_cluster_aurora_mysql_serverless" {
  source               = "../.."
  namespace            = "eg"
  stage                = "dev"
  name                 = "db"
  engine               = "aurora-mysql"
  engine_mode          = "serverless"
  engine_version       = "5.7.mysql_aurora.2.07.1"
  cluster_family       = "aurora-mysql5.7"
  cluster_size         = 0
  admin_user           = "admin1"
  admin_password       = "Test123456789"
  db_name              = "dbname"
  db_port              = 3306
  vpc_id               = "vpc-xxxxxxxx"
  security_groups      = ["sg-xxxxxxxx"]
  subnets              = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id              = "Zxxxxxxxx"
  enable_http_endpoint = true

  scaling_configuration = [
    {
      auto_pause               = true
      max_capacity             = 16
      min_capacity             = 1
      seconds_until_auto_pause = 300
      timeout_action           = "ForceApplyCapacityChange"
    }
  ]
}


================================================
FILE: examples/serverless_mysql57/outputs.tf
================================================
output "name" {
  value       = module.rds_cluster_aurora_mysql_serverless.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_mysql_serverless.master_username
  description = "Username for the master DB user"
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_mysql_serverless.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_mysql_serverless.arn
  description = "Amazon Resource Name (ARN) of cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_mysql_serverless.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_mysql_serverless.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_mysql_serverless.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_mysql_serverless.replicas_host
  description = "Replicas hostname"
}


================================================
FILE: examples/serverlessv2_postgres/context.tf
================================================
#
# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label
# All other instances of this file should be a copy of that one
#
#
# Copy this file from https://github.com/cloudposse/terraform-null-label/blob/master/exports/context.tf
# and then place it in your Terraform module to automatically get
# Cloud Posse's standard configuration inputs suitable for passing
# to Cloud Posse modules.
#
# curl -sL https://raw.githubusercontent.com/cloudposse/terraform-null-label/master/exports/context.tf -o context.tf
#
# Modules should access the whole context as `module.this.context`
# to get the input variables with nulls for defaults,
# for example `context = module.this.context`,
# and access individual variables as `module.this.<var>`,
# with final values filled in.
#
# For example, when using defaults, `module.this.context.delimiter`
# will be null, and `module.this.delimiter` will be `-` (hyphen).
#

module "this" {
  source  = "cloudposse/label/null"
  version = "0.25.0" # requires Terraform >= 0.13.0

  enabled             = var.enabled
  namespace           = var.namespace
  tenant              = var.tenant
  environment         = var.environment
  stage               = var.stage
  name                = var.name
  delimiter           = var.delimiter
  attributes          = var.attributes
  tags                = var.tags
  additional_tag_map  = var.additional_tag_map
  label_order         = var.label_order
  regex_replace_chars = var.regex_replace_chars
  id_length_limit     = var.id_length_limit
  label_key_case      = var.label_key_case
  label_value_case    = var.label_value_case
  descriptor_formats  = var.descriptor_formats
  labels_as_tags      = var.labels_as_tags

  context = var.context
}

# Copy contents of cloudposse/terraform-null-label/variables.tf here

variable "context" {
  type = any
  default = {
    enabled             = true
    namespace           = null
    tenant              = null
    environment         = null
    stage               = null
    name                = null
    delimiter           = null
    attributes          = []
    tags                = {}
    additional_tag_map  = {}
    regex_replace_chars = null
    label_order         = []
    id_length_limit     = null
    label_key_case      = null
    label_value_case    = null
    descriptor_formats  = {}
    # Note: we have to use [] instead of null for unset lists due to
    # https://github.com/hashicorp/terraform/issues/28137
    # which was not fixed until Terraform 1.0.0,
    # but we want the default to be all the labels in `label_order`
    # and we want users to be able to prevent all tag generation
    # by setting `labels_as_tags` to `[]`, so we need
    # a different sentinel to indicate "default"
    labels_as_tags = ["unset"]
  }
  description = <<-EOT
    Single object for setting entire context at once.
    See description of individual variables for details.
    Leave string and numeric variables as `null` to use default value.
    Individual variable settings (non-null) override settings in context object,
    except for attributes, tags, and additional_tag_map, which are merged.
  EOT

  validation {
    condition     = lookup(var.context, "label_key_case", null) == null ? true : contains(["lower", "title", "upper"], var.context["label_key_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }

  validation {
    condition     = lookup(var.context, "label_value_case", null) == null ? true : contains(["lower", "title", "upper", "none"], var.context["label_value_case"])
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "enabled" {
  type        = bool
  default     = null
  description = "Set to false to prevent the module from creating any resources"
}

variable "namespace" {
  type        = string
  default     = null
  description = "ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique"
}

variable "tenant" {
  type        = string
  default     = null
  description = "ID element _(Rarely used, not included by default)_. A customer identifier, indicating who this instance of a resource is for"
}

variable "environment" {
  type        = string
  default     = null
  description = "ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT'"
}

variable "stage" {
  type        = string
  default     = null
  description = "ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release'"
}

variable "name" {
  type        = string
  default     = null
  description = <<-EOT
    ID element. Usually the component or solution name, e.g. 'app' or 'jenkins'.
    This is the only ID element not also included as a `tag`.
    The "name" tag is set to the full `id` string. There is no tag with the value of the `name` input.
    EOT
}

variable "delimiter" {
  type        = string
  default     = null
  description = <<-EOT
    Delimiter to be used between ID elements.
    Defaults to `-` (hyphen). Set to `""` to use no delimiter at all.
  EOT
}

variable "attributes" {
  type        = list(string)
  default     = []
  description = <<-EOT
    ID element. Additional attributes (e.g. `workers` or `cluster`) to add to `id`,
    in the order they appear in the list. New attributes are appended to the
    end of the list. The elements of the list are joined by the `delimiter`
    and treated as a single ID element.
    EOT
}

variable "labels_as_tags" {
  type        = set(string)
  default     = ["default"]
  description = <<-EOT
    Set of labels (ID elements) to include as tags in the `tags` output.
    Default is to include all labels.
    Tags with empty values will not be included in the `tags` output.
    Set to `[]` to suppress all generated tags.
    **Notes:**
      The value of the `name` tag, if included, will be the `id`, not the `name`.
      Unlike other `null-label` inputs, the initial setting of `labels_as_tags` cannot be
      changed in later chained modules. Attempts to change it will be silently ignored.
    EOT
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
    Neither the tag keys nor the tag values will be modified by this module.
    EOT
}

variable "additional_tag_map" {
  type        = map(string)
  default     = {}
  description = <<-EOT
    Additional key-value pairs to add to each map in `tags_as_list_of_maps`. Not added to `tags` or `id`.
    This is for some rare cases where resources want additional configuration of tags
    and therefore take a list of maps with tag key, value, and additional configuration.
    EOT
}

variable "label_order" {
  type        = list(string)
  default     = null
  description = <<-EOT
    The order in which the labels (ID elements) appear in the `id`.
    Defaults to ["namespace", "environment", "stage", "name", "attributes"].
    You can omit any of the 6 labels ("tenant" is the 6th), but at least one must be present.
    EOT
}

variable "regex_replace_chars" {
  type        = string
  default     = null
  description = <<-EOT
    Terraform regular expression (regex) string.
    Characters matching the regex will be removed from the ID elements.
    If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits.
  EOT
}

variable "id_length_limit" {
  type        = number
  default     = null
  description = <<-EOT
    Limit `id` to this many characters (minimum 6).
    Set to `0` for unlimited length.
    Set to `null` for keep the existing setting, which defaults to `0`.
    Does not affect `id_full`.
  EOT
  validation {
    condition     = var.id_length_limit == null ? true : var.id_length_limit >= 6 || var.id_length_limit == 0
    error_message = "The id_length_limit must be >= 6 if supplied (not null), or 0 for unlimited length."
  }
}

variable "label_key_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of the `tags` keys (label names) for tags generated by this module.
    Does not affect keys of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper`.
    Default value: `title`.
  EOT

  validation {
    condition     = var.label_key_case == null ? true : contains(["lower", "title", "upper"], var.label_key_case)
    error_message = "Allowed values: `lower`, `title`, `upper`."
  }
}

variable "label_value_case" {
  type        = string
  default     = null
  description = <<-EOT
    Controls the letter case of ID elements (labels) as included in `id`,
    set as tag values, and output by this module individually.
    Does not affect values of tags passed in via the `tags` input.
    Possible values: `lower`, `title`, `upper` and `none` (no transformation).
    Set this to `title` and set `delimiter` to `""` to yield Pascal Case IDs.
    Default value: `lower`.
  EOT

  validation {
    condition     = var.label_value_case == null ? true : contains(["lower", "title", "upper", "none"], var.label_value_case)
    error_message = "Allowed values: `lower`, `title`, `upper`, `none`."
  }
}

variable "descriptor_formats" {
  type        = any
  default     = {}
  description = <<-EOT
    Describe additional descriptors to be output in the `descriptors` output map.
    Map of maps. Keys are names of descriptors. Values are maps of the form
    `{
       format = string
       labels = list(string)
    }`
    (Type is `any` so the map values can later be enhanced to provide additional options.)
    `format` is a Terraform format string to be passed to the `format()` function.
    `labels` is a list of labels, in order, to pass to `format()` function.
    Label values will be normalized before being passed to `format()` so they will be
    identical to how they appear in `id`.
    Default is `{}` (`descriptors` output will be empty).
    EOT
}

#### End of copy of cloudposse/terraform-null-label/variables.tf


================================================
FILE: examples/serverlessv2_postgres/fixtures.us-east-2.tfvars
================================================
region = "us-east-2"

availability_zones = ["us-east-2a", "us-east-2b"]

namespace = "eg"

stage = "test"

name = "rds-cluster"

engine = "aurora-postgresql"

cluster_family = "aurora-postgresql15"

engine_version = "15.13"

instance_type = "db.serverless"

cluster_size = 1

deletion_protection = false

autoscaling_enabled = false

db_name = "test_db"

admin_user = "postgres"

admin_password = "admin_password"

enhanced_monitoring_role_enabled = true

rds_monitoring_interval = 30

max_capacity = 16

min_capacity = 0.5


================================================
FILE: examples/serverlessv2_postgres/main.tf
================================================
provider "aws" {
  region = var.region
}

module "vpc" {
  source  = "cloudposse/vpc/aws"
  version = "2.2.0"

  ipv4_primary_cidr_block = "172.16.0.0/16"

  context = module.this.context
}

module "subnets" {
  source  = "cloudposse/dynamic-subnets/aws"
  version = "2.4.2"

  availability_zones   = var.availability_zones
  vpc_id               = module.vpc.vpc_id
  igw_id               = [module.vpc.igw_id]
  ipv4_cidr_block      = [module.vpc.vpc_cidr_block]
  nat_gateway_enabled  = false
  nat_instance_enabled = false

  context = module.this.context
}

module "rds_cluster_aurora_serverlessv2_postgres_13" {
  source = "../../"

  instance_type       = var.instance_type
  engine              = var.engine
  cluster_family      = var.cluster_family
  engine_version      = var.engine_version
  cluster_size        = var.cluster_size
  admin_user          = var.admin_user
  admin_password      = var.admin_password
  db_name             = var.db_name
  vpc_id              = module.vpc.vpc_id
  subnets             = module.subnets.private_subnet_ids
  security_groups     = [module.vpc.vpc_default_security_group_id]
  deletion_protection = var.deletion_protection
  serverlessv2_scaling_configuration = {
    max_capacity = var.max_capacity
    min_capacity = var.min_capacity
  }

  context = module.this.context
}


================================================
FILE: examples/serverlessv2_postgres/outputs.tf
================================================
output "database_name" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.master_username
  description = "Username for the master DB user"
  sensitive   = true
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.arn
  description = "Amazon Resource Name (ARN) of the cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.replicas_host
  description = "Replicas hostname"
}

output "dbi_resource_ids" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.dbi_resource_ids
  description = "List of the region-unique, immutable identifiers for the DB instances in the cluster"
}

output "cluster_resource_id" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.cluster_resource_id
  description = "The region-unique, immutable identifie of the cluster"
}

output "public_subnet_cidrs" {
  value       = module.subnets.public_subnet_cidrs
  description = "Public subnet CIDR blocks"
}

output "private_subnet_cidrs" {
  value       = module.subnets.private_subnet_cidrs
  description = "Private subnet CIDR blocks"
}

output "vpc_cidr" {
  value       = module.vpc.vpc_cidr_block
  description = "VPC CIDR"
}

output "security_group_id" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.security_group_id
  description = "Security Group ID"
}

output "security_group_arn" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.security_group_arn
  description = "Security Group ARN"
}

output "security_group_name" {
  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.security_group_name
  description = "Security Group name"
}


================================================
FILE: examples/serverlessv2_postgres/variables.tf
================================================
variable "region" {
  type        = string
  description = "AWS region"
}

variable "availability_zones" {
  type        = list(string)
  description = "Availability zones"
}

variable "cluster_family" {
  type        = string
  description = "The family of the DB cluster parameter group"
}

variable "engine" {
  type        = string
  description = "The name of the database engine to be used for this DB cluster. Valid values: `aurora`, `aurora-mysql`, `aurora-postgresql`"
}

variable "engine_version" {
  type        = string
  default     = ""
  description = "The version of the database engine to use. See `aws rds describe-db-engine-versions` "
}

variable "instance_type" {
  type        = string
  description = "Instance type to use"
}

variable "cluster_size" {
  type        = number
  description = "Number of DB instances to create in the cluster"
}

variable "db_name" {
  type        = string
  description = "Database name"
}

variable "admin_user" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Username for the master DB user"
}

variable "admin_password" {
  type        = string
  description = "(Required unless a snapshot_identifier is provided) Password for the master DB user"
}

variable "max_capacity" {
  type        = number
  description = "The maximum capacity for an Aurora DB cluster in provisioned DB engine mode"
}

variable "min_capacity" {
  type        = number
  description = "The minimum capacity for an Aurora DB cluster in provisioned DB engine mode"
}

variable "deletion_protection" {
  type        = bool
  description = "If the DB instance should have deletion protection enabled"
}

variable "autoscaling_enabled" {
  type        = bool
  description = "Whether to enable cluster autoscaling"
}

variable "enhanced_monitoring_role_enabled" {
  type        = bool
  description = "A boolean flag to enable/disable the creation of the enhanced monitoring IAM role. If set to `false`, the module will not create a new role and will use `rds_monitoring_role_arn` for enhanced monitoring"
}

variable "rds_monitoring_interval" {
  type        = number
  description = "The interval, in seconds, between points when enhanced monitoring metrics are collected for the DB instance. To disable collecting Enhanced Monitoring metrics, specify 0. The default is 0. Valid Values: 0, 1, 5, 10, 15, 30, 60"
}


================================================
FILE: examples/serverlessv2_postgres/versions.tf
================================================
terraform {
  required_version = ">= 1.1.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 4.12"
    }
    null = {
      source  = "hashicorp/null"
      version = ">= 2.0"
    }
  }
}


================================================
FILE: examples/with_cluster_parameters/main.tf
================================================
# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html

provider "aws" {
  region = "us-west-1"
}

module "rds_cluster_aurora_mysql" {
  source          = "../../"
  engine          = "aurora-mysql"
  cluster_family  = "aurora-mysql5.7"
  cluster_size    = 2
  namespace       = "eg"
  stage           = "dev"
  name            = "db"
  admin_user      = "admin1"
  admin_password  = "Test123456789"
  db_name         = "dbname"
  instance_type   = "db.t2.small"
  vpc_id          = "vpc-xxxxxxx"
  security_groups = ["sg-xxxxxxxx"]
  subnets         = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  zone_id         = "Zxxxxxxxx"

  cluster_parameters = [
    {
      name         = "character_set_client"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_connection"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_database"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_results"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "character_set_server"
      value        = "utf8"
      apply_method = "pending-reboot"
    },
    {
      name         = "collation_connection"
      value        = "utf8_bin"
      apply_method = "pending-reboot"
    },
    {
      name         = "collation_server"
      value        = "utf8_bin"
      apply_method = "pending-reboot"
    },
    {
      name         = "lower_case_table_names"
      value        = "1"
      apply_method = "pending-reboot"
    },
    {
      name         = "skip-character-set-client-handshake"
      value        = "1"
      apply_method = "pending-reboot"
    }
  ]
}


================================================
FILE: examples/with_cluster_parameters/outputs.tf
================================================
output "name" {
  value       = module.rds_cluster_aurora_mysql.database_name
  description = "Database name"
}

output "master_username" {
  value       = module.rds_cluster_aurora_mysql.master_username
  description = "Username for the master DB user"
}

output "cluster_identifier" {
  value       = module.rds_cluster_aurora_mysql.cluster_identifier
  description = "Cluster Identifier"
}

output "arn" {
  value       = module.rds_cluster_aurora_mysql.arn
  description = "Amazon Resource Name (ARN) of cluster"
}

output "endpoint" {
  value       = module.rds_cluster_aurora_mysql.endpoint
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = module.rds_cluster_aurora_mysql.reader_endpoint
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "master_host" {
  value       = module.rds_cluster_aurora_mysql.master_host
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.rds_cluster_aurora_mysql.replicas_host
  description = "Replicas hostname"
}


================================================
FILE: main.tf
================================================
locals {
  enabled = module.this.enabled

  partition = one(data.aws_partition.current[*].partition)

  deployed_cluster_identifier = local.enabled ? coalesce(one(aws_rds_cluster.primary[*].id), one(aws_rds_cluster.secondary[*].id)) : ""
  db_subnet_group_name        = one(aws_db_subnet_group.default[*].name)
  instance_class              = var.serverlessv2_scaling_configuration != null ? "db.serverless" : var.instance_type
  instance_identifier_prefix  = var.cluster_identifier == "" ? module.this.id : var.cluster_identifier
  instance_identifier_suffix_fragment = var.instance_identifier_suffix == null ? null : (
    var.instance_identifier_suffix == "" ? "" : "${module.this.delimiter}${var.instance_identifier_suffix}"
  )
  instance_identifier = !local.enabled ? "" : (
    var.instance_identifier_suffix == null ? random_pet.instance[0].id : "${local.instance_identifier_prefix}${local.instance_identifier_suffix_fragment}"
  )

  cluster_instance_count   = local.enabled ? var.cluster_size : 0
  is_regional_cluster      = var.cluster_type == "regional"
  is_serverless            = var.engine_mode == "serverless"
  ignore_admin_credentials = var.replication_source_identifier != "" || var.snapshot_identifier != null
  reserved_instance_engine = var.engine
  use_reserved_instances   = var.use_reserved_instances && !local.is_serverless
}

data "aws_partition" "current" {
  count = local.enabled ? 1 : 0
}

# TODO: Use cloudposse/security-group module
resource "aws_security_group" "default" {
  count       = local.enabled ? 1 : 0
  name        = module.this.id
  description = "Allow inbound traffic from Security Groups and CIDRs"
  vpc_id      = var.vpc_id
  tags        = module.this.tags
}

resource "aws_security_group_rule" "ingress_security_groups" {
  count                    = local.enabled ? length(var.security_groups) : 0
  description              = "Allow inbound traffic from existing security groups"
  type                     = "ingress"
  from_port                = var.db_port
  to_port                  = var.db_port
  protocol                 = "tcp"
  source_security_group_id = var.security_groups[count.index]
  security_group_id        = join("", aws_security_group.default[*].id)
}

resource "aws_security_group_rule" "traffic_inside_security_group" {
  count             = local.enabled && var.intra_security_group_traffic_enabled ? 1 : 0
  description       = "Allow traffic between members of the database security group"
  type              = "ingress"
  from_port         = var.db_port
  to_port           = var.db_port
  protocol          = "tcp"
  self              = true
  security_group_id = join("", aws_security_group.default[*].id)
}

resource "aws_security_group_rule" "ingress_cidr_blocks" {
  count             = local.enabled && length(var.allowed_cidr_blocks) > 0 ? 1 : 0
  description       = "Allow inbound traffic from existing CIDR blocks"
  type              = "ingress"
  from_port         = var.db_port
  to_port           = var.db_port
  protocol          = "tcp"
  cidr_blocks       = var.allowed_cidr_blocks
  security_group_id = join("", aws_security_group.default[*].id)
}

resource "aws_security_group_rule" "ingress_ipv6_cidr_blocks" {
  count             = local.enabled && length(var.allowed_ipv6_cidr_blocks) > 0 ? 1 : 0
  description       = "Allow inbound traffic from existing CIDR blocks"
  type              = "ingress"
  from_port         = var.db_port
  to_port           = var.db_port
  protocol          = "tcp"
  ipv6_cidr_blocks  = var.allowed_ipv6_cidr_blocks
  security_group_id = join("", aws_security_group.default[*].id)
}

resource "aws_security_group_rule" "egress" {
  count             = local.enabled && var.egress_enabled ? 1 : 0
  description       = "Allow outbound traffic"
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = join("", aws_security_group.default[*].id)
}

resource "aws_security_group_rule" "egress_ipv6" {
  count             = local.enabled && var.egress_enabled ? 1 : 0
  description       = "Allow outbound ipv6 traffic"
  type              = "egress"
  from_port         = 0
  to_port           = 0
  protocol          = "-1"
  ipv6_cidr_blocks  = ["::/0"]
  security_group_id = join("", aws_security_group.default[*].id)
}

data "aws_rds_reserved_instance_offering" "default" {
  count               = local.use_reserved_instances ? 1 : 0
  db_instance_class   = var.instance_type
  duration            = var.rds_ri_duration
  multi_az            = startswith(local.reserved_instance_engine, "aurora") ? false : local.cluster_instance_count > 1 # Aurora options never available for multi AZ for Reserved Instances. Single Reserved Instances rates still apply. https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithReservedDBInstances.html
  offering_type       = var.rds_ri_offering_type
  product_description = local.reserved_instance_engine
}

# Note: I'm not sure what will happen when the db reservation expires, and this is not easy to test.
# It will either be recreated or will require manual intervention to recreate.
resource "aws_rds_reserved_instance" "default" {
  count = local.use_reserved_instances ? 1 : 0

  offering_id    = data.aws_rds_reserved_instance_offering.default[0].id
  instance_count = local.cluster_instance_count
  reservation_id = var.rds_ri_reservation_id

  lifecycle {
    # Once created, we want to avoid any case of accidentally re-creating.
    prevent_destroy = true
  }
}

# The name "primary" is poorly chosen. We actually mean standalone or regional.
# The primary cluster of a global database is actually created with the "secondary" cluster resource below.
resource "aws_rds_cluster" "primary" {
  count              = local.enabled && local.is_regional_cluster ? 1 : 0
  cluster_identifier = var.cluster_identifier == "" ? module.this.id : var.cluster_identifier
  database_name      = var.db_name
  # manage_master_user_password must be `null` or `true`. If it is `false`, and `master_password` is not `null`, a conflict occurs.
  manage_master_user_password           = var.manage_admin_user_password ? var.manage_admin_user_password : null
  master_user_secret_kms_key_id         = var.admin_user_secret_kms_key_id
  master_username                       = local.ignore_admin_credentials ? null : var.admin_user
  master_password                       = local.ignore_admin_credentials || var.manage_admin_user_password ? null : var.admin_password
  backup_retention_period               = var.retention_period
  preferred_backup_window               = var.backup_window
  copy_tags_to_snapshot                 = var.copy_tags_to_snapshot
  final_snapshot_identifier             = var.cluster_identifier == "" ? lower(module.this.id) : lower(var.cluster_identifier)
  skip_final_snapshot                   = var.skip_final_snapshot
  apply_immediately                     = var.apply_immediately
  db_cluster_instance_class             = local.is_serverless ? null : var.db_cluster_instance_class
  storage_encrypted                     = local.is_serverless ? null : var.storage_encrypted
  storage_type                          = var.storage_type
  iops                                  = var.iops
  allocated_storage                     = var.allocated_storage
  kms_key_id                            = var.kms_key_arn
  source_region                         = var.source_region
  snapshot_identifier                   = var.snapshot_identifier
  vpc_security_group_ids                = compact(flatten([join("", aws_security_group.default[*].id), var.vpc_security_group_ids]))
  preferred_maintenance_window          = var.maintenance_window
  network_type                          = var.network_type
  db_subnet_group_name                  = join("", aws_db_subnet_group.default[*].name)
  db_cluster_parameter_group_name       = join("", aws_rds_cluster_parameter_group.default[*].name)
  iam_database_authentication_enabled   = var.iam_database_authentication_enabled
  tags                                  = module.this.tags
  engine                                = var.engine
  engine_version                        = var.engine_version
  allow_major_version_upgrade           = var.allow_major_version_upgrade
  db_instance_parameter_group_name      = var.allow_major_version_upgrade ? join("", aws_db_parameter_group.default[*].name) : null
  engine_mode                           = var.engine_mode
  iam_roles                             = var.iam_roles
  backtrack_window                      = var.backtrack_window
  enable_http_endpoint                  = var.enable_http_endpoint
  port                                  = var.db_port
  enable_global_write_forwarding        = var.enable_global_write_forwarding
  enable_local_write_forwarding         = var.enable_local_write_forwarding
  performance_insights_enabled          = var.performance_insights_enabled
  performance_insights_kms_key_id       = var.performance_insights_kms_key_id
  performance_insights_retention_period = var.performance_insights_retention_period
  database_insights_mode                = var.database_insights_mode

  depends_on = [
    aws_db_subnet_group.default,
    aws_rds_cluster_parameter_group.default,
    aws_security_group.default,
  ]

  dynamic "s3_import" {
    for_each = var.s3_import[*]
    content {
      bucket_name           = lookup(s3_import.value, "bucket_name", null)
      bucket_prefix         = lookup(s3_import.value, "bucket_prefix", null)
      ingestion_role        = lookup(s3_import.value, "ingestion_role", null)
      source_engine         = lookup(s3_import.value, "source_engine", null)
      source_engine_version = lookup(s3_import.value, "source_engine_version", null)
    }
  }

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

  dynamic "serverlessv2_scaling_configuration" {
    for_each = var.serverlessv2_scaling_configuration[*]
    content {
      max_capacity             = serverlessv2_scaling_configuration.value.max_capacity
      min_capacity             = serverlessv2_scaling_configuration.value.min_capacity
      seconds_until_auto_pause = serverlessv2_scaling_configuration.value.seconds_until_auto_pause
    }
  }

  dynamic "timeouts" {
    for_each = var.timeouts_configuration
    content {
      create = lookup(timeouts.value, "create", "120m")
      update = lookup(timeouts.value, "update", "120m")
      delete = lookup(timeouts.value, "delete", "120m")
    }
  }

  dynamic "restore_to_point_in_time" {
    for_each = var.restore_to_point_in_time
    content {
      source_cluster_identifier = restore_to_point_in_time.value.source_cluster_identifier
      restore_type              = restore_to_point_in_time.value.restore_type
      # use_latest_restorable_time and restore_to_time are mutually exclusive.
      # If restore_to_time is given, then we ignore use_latest_restorable_time
      use_latest_restorable_time = restore_to_point_in_time.value.restore_to_time != null ? null : restore_to_point_in_time.value.use_latest_restorable_time
      restore_to_time            = restore_to_point_in_time.value.restore_to_time
    }
  }

  enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports
  deletion_protection             = var.deletion_protection
  replication_source_identifier   = var.replication_source_identifier
}

# https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#replication_source_identifier
resource "aws_rds_cluster" "secondary" {
  count              = local.enabled && !local.is_regional_cluster ? 1 : 0
  cluster_identifier = var.cluster_identifier == "" ? module.this.id : var.cluster_identifier
  database_name      = var.db_name
  # manage_master_user_password must be `null` or `true`. If it is `false`, and `master_password` is not `null`, a conflict occurs.
  manage_master_user_password         = var.manage_admin_user_password ? var.manage_admin_user_password : null
  master_user_secret_kms_key_id       = var.admin_user_secret_kms_key_id
  master_username                     = local.ignore_admin_credentials ? null : var.admin_user
  master_password                     = local.ignore_admin_credentials || var.manage_admin_user_password ? null : var.admin_password
  backup_retention_period             = var.retention_period
  preferred_backup_window             = var.backup_window
  copy_tags_to_snapshot               = var.copy_tags_to_snapshot
  final_snapshot_identifier           = var.cluster_identifier == "" ? lower(module.this.id) : lower(var.cluster_identifier)
  skip_final_snapshot                 = var.skip_final_snapshot
  apply_immediately                   = var.apply_immediately
  db_cluster_instance_class           = local.is_serverless ? null : var.db_cluster_instance_class
  storage_encrypted                   = var.storage_encrypted
  storage_type                        = var.storage_type
  kms_key_id                          = var.kms_key_arn
  source_region                       = var.source_region
  snapshot_identifier                 = var.snapshot_identifier
  vpc_security_group_ids              = compact(flatten([join("", aws_security_group.default[*].id), var.vpc_security_group_ids]))
  preferred_maintenance_window        = var.maintenance_window
  network_type                        = var.network_type
  db_subnet_group_name                = join("", aws_db_subnet_group.default[*].name)
  db_cluster_parameter_group_name     = join("", aws_rds_cluster_parameter_group.default[*].name)
  iam_database_authentication_enabled = var.iam_database_authentication_enabled
  tags                                = module.this.tags
  engine                              = var.engine
  engine_version                      = var.engine_version
  allow_major_version_upgrade         = var.allow_major_version_upgrade
  engine_mode                         = var.engine_mode
  iam_roles                           = var.iam_roles
  backtrack_window                    = var.backtrack_window
  enable_http_endpoint                = var.enable_http_endpoint
  port                                = var.db_port
  enable_global_write_forwarding      = var.enable_global_write_forwarding
  enable_local_write_forwarding       = var.enable_local_write_forwarding
  database_insights_mode              = var.database_insights_mode

  depends_on = [
    aws_db_subnet_group.default,
    aws_db_parameter_group.default,
    aws_rds_cluster_parameter_group.default,
    aws_security_group.default,
  ]

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

  dynamic "serverlessv2_scaling_configuration" {
    for_each = var.serverlessv2_scaling_configuration[*]
    content {
      max_capacity = serverlessv2_scaling_configuration.value.max_capacity
      min_capacity = serverlessv2_scaling_configuration.value.min_capacity
    }
  }

  dynamic "timeouts" {
    for_each = var.timeouts_configuration
    content {
      create = lookup(timeouts.value, "create", "120m")
      update = lookup(timeouts.value, "update", "120m")
      delete = lookup(timeouts.value, "delete", "120m")
    }
  }

  enabled_cloudwatch_logs_exports = var.enabled_cloudwatch_logs_exports
  deletion_protection             = var.deletion_protection

  global_cluster_identifier = var.global_cluster_identifier

  # https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster#replication_source_identifier
  # ARN of a source DB cluster or DB instance if this DB cluster is to be created as a Read Replica.
  # If DB Cluster is part of a Global Cluster, use the lifecycle configuration block ignore_changes argument
  # to prevent Terraform from showing differences for this argument instead of configuring this value.

  lifecycle {
    ignore_changes = [
      replication_source_identifier, # will be set/managed by Global Cluster
      snapshot_identifier,           # if created from a snapshot, will be non-null at creation, but null afterwards
    ]
  }
}

resource "random_pet" "instance" {
  count  = local.enabled && var.instance_identifier_suffix == null ? 1 : 0
  prefix = local.instance_identifier_prefix
  keepers = {
    cluster_family = var.cluster_family
    instance_class = var.serverlessv2_scaling_configuration != null ? "db.serverless" : var.instance_type
  }
}

module "rds_identifier" {
  count = local.enabled ? 1 : 0

  source  = "cloudposse/label/null"
  version = "0.25.0"

  name = local.instance_identifier
  # Max length of RDS identifier is 63 characters, but in `aws_rds_cluster_instance`
  # we append the instance index to the identifier
  # Setting the limit to 60 allow to use up to 99 instances, when only 16 is allowed
  # (1 writer + 15 readers)
  # https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Replication.html
  id_length_limit = 60
}

resource "aws_rds_cluster_instance" "default" {
  count                                 = local.cluster_instance_count
  identifier                            = "${module.rds_identifier[0].id}-${count.index + 1}"
  cluster_identifier                    = local.deployed_cluster_identifier
  instance_class                        = local.instance_class
  db_subnet_group_name                  = local.db_subnet_group_name
  db_parameter_group_name               = join("", aws_db_parameter_group.default[*].name)
  publicly_accessible                   = var.publicly_accessible
  tags                                  = module.this.tags
  engine                                = var.engine
  engine_version                        = var.engine_version
  auto_minor_version_upgrade            = var.auto_minor_version_upgrade
  monitoring_interval                   = var.rds_monitoring_interval
  monitoring_role_arn                   = var.enhanced_monitoring_role_enabled ? join("", aws_iam_role.enhanced_monitoring[*].arn) : var.rds_monitoring_role_arn
  performance_insights_enabled          = var.performance_insights_enabled
  performance_insights_kms_key_id       = var.performance_insights_kms_key_id
  performance_insights_retention_period = var.performance_insights_retention_period
  availability_zone                     = var.instance_availability_zone
  apply_immediately                     = var.apply_immediately
  preferred_maintenance_window          = var.maintenance_window
  copy_tags_to_snapshot                 = var.copy_tags_to_snapshot
  ca_cert_identifier                    = var.ca_cert_identifier
  promotion_tier                        = var.promotion_tier

  dynamic "timeouts" {
    for_each = var.timeouts_configuration
    content {
      create = lookup(timeouts.value, "create", "120m")
      update = lookup(timeouts.value, "update", "120m")
      delete = lookup(timeouts.value, "delete", "120m")
    }
  }

  depends_on = [
    aws_db_subnet_group.default,
    aws_db_parameter_group.default,
    aws_iam_role.enhanced_monitoring,
    aws_rds_cluster.secondary,
    aws_rds_cluster_parameter_group.default,
  ]

  lifecycle {
    ignore_changes        = [engine_version]
    create_before_destroy = true
  }
}

resource "aws_db_subnet_group" "default" {
  count       = local.enabled ? 1 : 0
  name        = try(length(var.subnet_group_name), 0) == 0 ? module.this.id : var.subnet_group_name
  description = "Allowed subnets for DB cluster instances"
  subnet_ids  = var.subnets
  tags        = module.this.tags
}

resource "aws_rds_cluster_parameter_group" "default" {
  count = local.enabled ? 1 : 0

  name_prefix = var.parameter_group_name_prefix_enabled ? "${coalesce(var.rds_cluster_parameter_group_name, module.this.id)}${module.this.delimiter}" : null
  name        = !var.parameter_group_name_prefix_enabled ? coalesce(var.rds_cluster_parameter_group_name, module.this.id) : null

  description = "DB cluster parameter group"
  family      = var.cluster_family

  dynamic "parameter" {
    for_each = var.cluster_parameters
    content {
      apply_method = lookup(parameter.value, "apply_method", null)
      name         = parameter.value.name
      value        = parameter.value.value
    }
  }

  tags = module.this.tags

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_db_parameter_group" "default" {
  count = local.enabled ? 1 : 0

  name_prefix = var.parameter_group_name_prefix_enabled ? "${coalesce(var.db_parameter_group_name, module.this.id)}${module.this.delimiter}" : null
  name        = !var.parameter_group_name_prefix_enabled ? coalesce(var.db_parameter_group_name, module.this.id) : null

  description = "DB instance parameter group"
  family      = var.cluster_family

  dynamic "parameter" {
    for_each = var.instance_parameters
    content {
      apply_method = lookup(parameter.value, "apply_method", null)
      name         = parameter.value.name
      value        = parameter.value.value
    }
  }

  tags = module.this.tags

  lifecycle {
    create_before_destroy = true
  }
}

locals {
  cluster_dns_name_default = "master.${module.this.name}"
  cluster_dns_name         = var.cluster_dns_name != "" ? var.cluster_dns_name : local.cluster_dns_name_default
  reader_dns_name_default  = "replicas.${module.this.name}"
  reader_dns_name          = var.reader_dns_name != "" ? var.reader_dns_name : local.reader_dns_name_default
}

module "dns_master" {
  source  = "cloudposse/route53-cluster-hostname/aws"
  version = "0.13.0"

  enabled  = local.enabled && length(var.zone_id) > 0
  dns_name = local.cluster_dns_name
  zone_id  = try(var.zone_id[0], tostring(var.zone_id), "")
  records  = coalescelist(aws_rds_cluster.primary[*].endpoint, aws_rds_cluster.secondary[*].endpoint, [""])

  context = module.this.context
}

module "dns_replicas" {
  source  = "cloudposse/route53-cluster-hostname/aws"
  version = "0.13.0"

  enabled  = local.enabled && length(var.zone_id) > 0 && !local.is_serverless && local.cluster_instance_count > 0
  dns_name = local.reader_dns_name
  zone_id  = try(var.zone_id[0], tostring(var.zone_id), "")
  records  = coalescelist(aws_rds_cluster.primary[*].reader_endpoint, aws_rds_cluster.secondary[*].reader_endpoint, [""])

  context = module.this.context
}

resource "aws_appautoscaling_target" "replicas" {
  count              = local.enabled && var.autoscaling_enabled ? 1 : 0
  service_namespace  = "rds"
  scalable_dimension = "rds:cluster:ReadReplicaCount"
  resource_id        = "cluster:${local.deployed_cluster_identifier}"
  min_capacity       = var.autoscaling_min_capacity
  max_capacity       = var.autoscaling_max_capacity
}

resource "aws_appautoscaling_policy" "replicas" {
  count              = local.enabled && var.autoscaling_enabled ? 1 : 0
  name               = module.this.id
  service_namespace  = join("", aws_appautoscaling_target.replicas[*].service_namespace)
  scalable_dimension = join("", aws_appautoscaling_target.replicas[*].scalable_dimension)
  resource_id        = join("", aws_appautoscaling_target.replicas[*].resource_id)
  policy_type        = var.autoscaling_policy_type

  target_tracking_scaling_policy_configuration {
    predefined_metric_specification {
      predefined_metric_type = var.autoscaling_target_metrics
    }

    disable_scale_in   = false
    target_value       = var.autoscaling_target_value
    scale_in_cooldown  = var.autoscaling_scale_in_cooldown
    scale_out_cooldown = var.autoscaling_scale_out_cooldown
  }
}

resource "aws_rds_cluster_activity_stream" "primary" {
  count = local.enabled && var.activity_stream_enabled ? 1 : 0

  resource_arn = join("", aws_rds_cluster.primary[*].arn)
  mode         = var.activity_stream_mode
  kms_key_id   = var.activity_stream_kms_key_id
}


================================================
FILE: outputs.tf
================================================
output "database_name" {
  value       = var.db_name
  description = "Database name"
}

output "master_username" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].master_username) : join("", aws_rds_cluster.secondary[*].master_username)
  description = "Username for the master DB user"
  sensitive   = true
}

output "cluster_identifier" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].cluster_identifier) : join("", aws_rds_cluster.secondary[*].cluster_identifier)
  description = "Cluster Identifier"
}

output "arn" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].arn) : join("", aws_rds_cluster.secondary[*].arn)
  description = "Amazon Resource Name (ARN) of the cluster"
}

output "endpoint" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].endpoint) : join("", aws_rds_cluster.secondary[*].endpoint)
  description = "The DNS address of the RDS instance"
}

output "reader_endpoint" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].reader_endpoint) : join("", aws_rds_cluster.secondary[*].reader_endpoint)
  description = "A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas"
}

output "port" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].port) : join("", aws_rds_cluster.secondary[*].port)
  description = "DB port"
}

# See: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster.html#master_user_secret
output "admin_user_secret" {
  value       = var.manage_admin_user_password ? concat(aws_rds_cluster.primary[*].master_user_secret) : []
  description = "The secret manager attributes for the managed admin user password (`master_user_secret`)."
}

output "master_host" {
  value       = module.dns_master.hostname
  description = "DB Master hostname"
}

output "replicas_host" {
  value       = module.dns_replicas.hostname
  description = "Replicas hostname"
}

output "dbi_resource_ids" {
  value       = aws_rds_cluster_instance.default[*].dbi_resource_id
  description = "List of the region-unique, immutable identifiers for the DB instances in the cluster"
}

output "instance_endpoints" {
  value       = aws_rds_cluster_instance.default[*].endpoint
  description = "List of DNS addresses for the DB instances in the cluster"
}

output "instance_arns" {
  value       = aws_rds_cluster_instance.default[*].arn
  description = "List of ARNs of the DB instances in the cluster"
}

output "cluster_resource_id" {
  value       = local.is_regional_cluster ? join("", aws_rds_cluster.primary[*].cluster_resource_id) : join("", aws_rds_cluster.secondary[*].cluster_resource_id)
  description = "The region-unique, immutable identifie of the cluster"
}

output "cluster_security_groups" {
  value       = coalescelist(aws_rds_cluster.primary[*].vpc_security_group_ids, aws_rds_cluster.secondary[*].vpc_security_group_ids, [""])
  description = "Default RDS cluster security groups"
}

output "security_group_id" {
  value       = join("", aws_security_group.default[*].id)
  description = "Security Group ID"
}

output "security_group_arn" {
  value       = join("", aws_security_group.default[*].arn)
  description = "Security Group ARN"
}

output "security_group_name" {
  value       = join("", aws_security_group.default[*].name)
  description = "Security Group name"
}

output "activity_stream_arn" {
  value       = join("", aws_rds_cluster_activity_stream.primary[*].id)
  description = "Activity Stream ARN"
}

output "activity_stream_name" {
  value       = join("", aws_rds_clu
Download .txt
gitextract_4dy49v9r/

├── .github/
│   ├── CODEOWNERS
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   ├── bug_report.yml
│   │   ├── config.yml
│   │   ├── feature_request.md
│   │   ├── feature_request.yml
│   │   └── question.md
│   ├── PULL_REQUEST_TEMPLATE.md
│   ├── mergify.yml
│   ├── renovate.json
│   ├── settings.yml
│   └── workflows/
│       ├── branch.yml
│       ├── chatops.yml
│       ├── release.yml
│       └── scheduled.yml
├── .gitignore
├── LICENSE
├── README.md
├── README.yaml
├── atmos.yaml
├── context.tf
├── enhanced-monitoring.tf
├── examples/
│   ├── basic/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── complete/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── enhanced_monitoring/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── postgres/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   ├── serverless_mysql/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── serverless_mysql57/
│   │   ├── main.tf
│   │   └── outputs.tf
│   ├── serverlessv2_postgres/
│   │   ├── context.tf
│   │   ├── fixtures.us-east-2.tfvars
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   ├── variables.tf
│   │   └── versions.tf
│   └── with_cluster_parameters/
│       ├── main.tf
│       └── outputs.tf
├── main.tf
├── outputs.tf
├── test/
│   ├── .gitignore
│   ├── Makefile
│   ├── Makefile.alpine
│   └── src/
│       ├── .gitignore
│       ├── Makefile
│       ├── examples_complete_test.go
│       ├── examples_postgres_test.go
│       ├── examples_serverlessv2_postgres_test.go
│       ├── go.mod
│       ├── go.sum
│       └── utils.go
├── variables.tf
└── versions.tf
Download .txt
SYMBOL INDEX (7 symbols across 4 files)

FILE: test/src/examples_complete_test.go
  function TestExamplesComplete (line 15) | func TestExamplesComplete(t *testing.T) {
  function TestExamplesCompleteDisabled (line 70) | func TestExamplesCompleteDisabled(t *testing.T) {

FILE: test/src/examples_postgres_test.go
  function TestExamplesPostgres (line 15) | func TestExamplesPostgres(t *testing.T) {
  function TestExamplesPostgresDisabled (line 70) | func TestExamplesPostgresDisabled(t *testing.T) {

FILE: test/src/examples_serverlessv2_postgres_test.go
  function TestExamplesServerlessV2Postgres (line 15) | func TestExamplesServerlessV2Postgres(t *testing.T) {
  function TestExamplesServerlessV2PostgresDisabled (line 70) | func TestExamplesServerlessV2PostgresDisabled(t *testing.T) {

FILE: test/src/utils.go
  function cleanup (line 10) | func cleanup(t *testing.T, terraformOptions *terraform.Options, tempTest...
Condensed preview — 65 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (355K chars).
[
  {
    "path": ".github/CODEOWNERS",
    "chars": 1201,
    "preview": "# Use this file to define individuals or teams that are responsible for code in a repository.\n# Read more: <https://help"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 902,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: 'bug'\nassignees: ''\n\n---\n\nFound a bug? "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yml",
    "chars": 1859,
    "preview": "---\nname: Bug report\ndescription: Create a report to help us improve\nlabels: [\"bug\"]\nassignees: [\"\"]\nbody:\n  - type: mar"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "chars": 496,
    "preview": "blank_issues_enabled: false\n\ncontact_links:\n\n  - name: Community Slack Team\n    url: https://cloudposse.com/slack/\n    a"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 1021,
    "preview": "---\nname: Feature Request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'feature request'\nassignees: ''\n\n---"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yml",
    "chars": 1914,
    "preview": "---\nname: Feature Request\ndescription: Suggest an idea for this project\nlabels: [\"feature request\"]\nassignees: [\"\"]\nbody"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "chars": 0,
    "preview": ""
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "chars": 602,
    "preview": "## what\n\n<!--\n- Describe high-level what changed as a result of these commits (i.e. in plain-english, what do these chan"
  },
  {
    "path": ".github/mergify.yml",
    "chars": 17,
    "preview": "extends: .github\n"
  },
  {
    "path": ".github/renovate.json",
    "chars": 285,
    "preview": "{\n  \"extends\": [\n    \"config:base\",\n    \":preserveSemverRanges\",\n    \":rebaseStalePrs\"\n  ],\n  \"baseBranches\": [\"main\"],\n"
  },
  {
    "path": ".github/settings.yml",
    "chars": 423,
    "preview": "# Upstream changes from _extends are only recognized when modifications are made to this file in the default branch.\n_ex"
  },
  {
    "path": ".github/workflows/branch.yml",
    "chars": 462,
    "preview": "---\nname: Branch\non:\n  pull_request:\n    branches:\n      - main\n      - release/**\n    types: [opened, synchronize, reop"
  },
  {
    "path": ".github/workflows/chatops.yml",
    "chars": 368,
    "preview": "---\nname: chatops\non:\n  issue_comment:\n    types: [created]\n\npermissions:\n  pull-requests: write\n  id-token: write\n  con"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 263,
    "preview": "---\nname: release\non:\n  release:\n    types:\n      - published\n\npermissions:\n  id-token: write\n  contents: write\n  pull-r"
  },
  {
    "path": ".github/workflows/scheduled.yml",
    "chars": 323,
    "preview": "---\nname: scheduled\non:\n  workflow_dispatch: { }  # Allows manually trigger this workflow\n  schedule:\n    - cron: \"0 3 *"
  },
  {
    "path": ".gitignore",
    "chars": 137,
    "preview": "# Compiled files\n*.tfstate\n*.tfstate.backup\n\n# Module directory\n.terraform\n.idea\n*.iml\n\n.build-harness\nbuild-harness\n.te"
  },
  {
    "path": "LICENSE",
    "chars": 11351,
    "preview": "                                 Apache License\n                           Version 2.0, January 2004\n                   "
  },
  {
    "path": "README.md",
    "chars": 56191,
    "preview": "\n\n<!-- markdownlint-disable -->\n<a href=\"https://cpco.io/homepage\"><img src=\"https://github.com/cloudposse/terraform-aws"
  },
  {
    "path": "README.yaml",
    "chars": 8639,
    "preview": "name: terraform-aws-rds-cluster\n\ntags:\n  - aws\n  - terraform\n  - terraform-modules\n  - databases\n  - rds\n  - rds-databas"
  },
  {
    "path": "atmos.yaml",
    "chars": 511,
    "preview": "# Atmos Configuration — powered by https://atmos.tools\n#\n# This configuration enables centralized, DRY, and consistent p"
  },
  {
    "path": "context.tf",
    "chars": 10101,
    "preview": "#\n# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label\n# All other instances of this file should be a cop"
  },
  {
    "path": "enhanced-monitoring.tf",
    "chars": 1621,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_Monitoring.OS.html\n# https://registry.terraform.io/provide"
  },
  {
    "path": "examples/basic/main.tf",
    "chars": 715,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html\n\nprovider \"aws\" {\n  r"
  },
  {
    "path": "examples/basic/outputs.tf",
    "chars": 1127,
    "preview": "output \"name\" {\n  value       = module.rds_cluster_aurora_postgres.database_name\n  description = \"Database name\"\n}\n\noutp"
  },
  {
    "path": "examples/complete/context.tf",
    "chars": 10101,
    "preview": "#\n# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label\n# All other instances of this file should be a cop"
  },
  {
    "path": "examples/complete/fixtures.us-east-2.tfvars",
    "chars": 652,
    "preview": "region = \"us-east-2\"\n\navailability_zones = [\"us-east-2a\", \"us-east-2b\"]\n\nnamespace = \"eg\"\n\nstage = \"test\"\n\nname = \"rds-c"
  },
  {
    "path": "examples/complete/main.tf",
    "chars": 2856,
    "preview": "provider \"aws\" {\n  region = var.region\n}\n\nmodule \"vpc\" {\n  source  = \"cloudposse/vpc/aws\"\n  version = \"2.2.0\"\n\n  ipv4_pr"
  },
  {
    "path": "examples/complete/outputs.tf",
    "chars": 1953,
    "preview": "output \"database_name\" {\n  value       = module.rds_cluster.database_name\n  description = \"Database name\"\n}\n\noutput \"clu"
  },
  {
    "path": "examples/complete/variables.tf",
    "chars": 2842,
    "preview": "variable \"region\" {\n  type        = string\n  description = \"AWS region\"\n}\n\nvariable \"availability_zones\" {\n  type       "
  },
  {
    "path": "examples/complete/versions.tf",
    "chars": 229,
    "preview": "terraform {\n  required_version = \">= 1.1.0\"\n\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      ve"
  },
  {
    "path": "examples/enhanced_monitoring/main.tf",
    "chars": 1642,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html\n\nprovider \"aws\" {\n  r"
  },
  {
    "path": "examples/enhanced_monitoring/outputs.tf",
    "chars": 1127,
    "preview": "output \"name\" {\n  value       = module.rds_cluster_aurora_postgres.database_name\n  description = \"Database name\"\n}\n\noutp"
  },
  {
    "path": "examples/postgres/context.tf",
    "chars": 10101,
    "preview": "#\n# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label\n# All other instances of this file should be a cop"
  },
  {
    "path": "examples/postgres/fixtures.us-east-2.tfvars",
    "chars": 759,
    "preview": "region = \"us-east-2\"\n\navailability_zones = [\"us-east-2a\", \"us-east-2b\", \"us-east-2c\"]\n\nnamespace = \"eg\"\n\nstage = \"test\"\n"
  },
  {
    "path": "examples/postgres/main.tf",
    "chars": 1616,
    "preview": "provider \"aws\" {\n  region = var.region\n}\n\nmodule \"vpc\" {\n  source  = \"cloudposse/vpc/aws\"\n  version = \"2.2.0\"\n\n  ipv4_pr"
  },
  {
    "path": "examples/postgres/outputs.tf",
    "chars": 1953,
    "preview": "output \"database_name\" {\n  value       = module.rds_cluster.database_name\n  description = \"Database name\"\n}\n\noutput \"clu"
  },
  {
    "path": "examples/postgres/variables.tf",
    "chars": 3016,
    "preview": "variable \"region\" {\n  type        = string\n  description = \"AWS region\"\n}\n\nvariable \"availability_zones\" {\n  type       "
  },
  {
    "path": "examples/postgres/versions.tf",
    "chars": 229,
    "preview": "terraform {\n  required_version = \">= 1.1.0\"\n\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      ve"
  },
  {
    "path": "examples/serverless_mysql/main.tf",
    "chars": 1218,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html\n# https://docs.aws.am"
  },
  {
    "path": "examples/serverless_mysql/outputs.tf",
    "chars": 1191,
    "preview": "output \"name\" {\n  value       = module.rds_cluster_aurora_mysql_serverless.database_name\n  description = \"Database name\""
  },
  {
    "path": "examples/serverless_mysql57/main.tf",
    "chars": 1310,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html\n# https://docs.aws.am"
  },
  {
    "path": "examples/serverless_mysql57/outputs.tf",
    "chars": 1191,
    "preview": "output \"name\" {\n  value       = module.rds_cluster_aurora_mysql_serverless.database_name\n  description = \"Database name\""
  },
  {
    "path": "examples/serverlessv2_postgres/context.tf",
    "chars": 10101,
    "preview": "#\n# ONLY EDIT THIS FILE IN github.com/cloudposse/terraform-null-label\n# All other instances of this file should be a cop"
  },
  {
    "path": "examples/serverlessv2_postgres/fixtures.us-east-2.tfvars",
    "chars": 524,
    "preview": "region = \"us-east-2\"\n\navailability_zones = [\"us-east-2a\", \"us-east-2b\"]\n\nnamespace = \"eg\"\n\nstage = \"test\"\n\nname = \"rds-c"
  },
  {
    "path": "examples/serverlessv2_postgres/main.tf",
    "chars": 1328,
    "preview": "provider \"aws\" {\n  region = var.region\n}\n\nmodule \"vpc\" {\n  source  = \"cloudposse/vpc/aws\"\n  version = \"2.2.0\"\n\n  ipv4_pr"
  },
  {
    "path": "examples/serverlessv2_postgres/outputs.tf",
    "chars": 2521,
    "preview": "output \"database_name\" {\n  value       = module.rds_cluster_aurora_serverlessv2_postgres_13.database_name\n  description "
  },
  {
    "path": "examples/serverlessv2_postgres/variables.tf",
    "chars": 2392,
    "preview": "variable \"region\" {\n  type        = string\n  description = \"AWS region\"\n}\n\nvariable \"availability_zones\" {\n  type       "
  },
  {
    "path": "examples/serverlessv2_postgres/versions.tf",
    "chars": 227,
    "preview": "terraform {\n  required_version = \">= 1.1.0\"\n\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      ve"
  },
  {
    "path": "examples/with_cluster_parameters/main.tf",
    "chars": 1828,
    "preview": "# https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBClusterParameterGroup.html\n\nprovider \"aws\" {\n  r"
  },
  {
    "path": "examples/with_cluster_parameters/outputs.tf",
    "chars": 1103,
    "preview": "output \"name\" {\n  value       = module.rds_cluster_aurora_mysql.database_name\n  description = \"Database name\"\n}\n\noutput "
  },
  {
    "path": "main.tf",
    "chars": 24708,
    "preview": "locals {\n  enabled = module.this.enabled\n\n  partition = one(data.aws_partition.current[*].partition)\n\n  deployed_cluster"
  },
  {
    "path": "outputs.tf",
    "chars": 3924,
    "preview": "output \"database_name\" {\n  value       = var.db_name\n  description = \"Database name\"\n}\n\noutput \"master_username\" {\n  val"
  },
  {
    "path": "test/.gitignore",
    "chars": 14,
    "preview": ".test-harness\n"
  },
  {
    "path": "test/Makefile",
    "chars": 1155,
    "preview": "TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git\nTEST_HARNESS_BRANCH ?= master\nTEST_HARNESS_PATH = $(realp"
  },
  {
    "path": "test/Makefile.alpine",
    "chars": 153,
    "preview": "ifneq (,$(wildcard /sbin/apk))\n## Install all dependencies for alpine\ndeps:: init\n\t@apk add --update terraform-docs@clou"
  },
  {
    "path": "test/src/.gitignore",
    "chars": 16,
    "preview": ".gopath\nvendor/\n"
  },
  {
    "path": "test/src/Makefile",
    "chars": 1046,
    "preview": "export TERRAFORM_VERSION ?= $(shell curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current"
  },
  {
    "path": "test/src/examples_complete_test.go",
    "chars": 4089,
    "preview": "package test\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gruntwork-io/terratest/modules/random\"\n\t\"github.com"
  },
  {
    "path": "test/src/examples_postgres_test.go",
    "chars": 4126,
    "preview": "package test\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gruntwork-io/terratest/modules/random\"\n\t\"github.com"
  },
  {
    "path": "test/src/examples_serverlessv2_postgres_test.go",
    "chars": 4152,
    "preview": "package test\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/gruntwork-io/terratest/modules/random\"\n\t\"github.com"
  },
  {
    "path": "test/src/go.mod",
    "chars": 4610,
    "preview": "module github.com/cloudposse/terraform-aws-rds-cluster\n\ngo 1.24\n\ntoolchain go1.24.0\n\nrequire (\n\tgithub.com/gruntwork-io/"
  },
  {
    "path": "test/src/go.sum",
    "chars": 106257,
    "preview": "cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=\ncloud.google.com/go v0.34.0/go.mod h1"
  },
  {
    "path": "test/src/utils.go",
    "chars": 264,
    "preview": "package test\n\nimport (\n\t\"os\"\n\t\"testing\"\n\n\t\"github.com/gruntwork-io/terratest/modules/terraform\"\n)\n\nfunc cleanup(t *testi"
  },
  {
    "path": "variables.tf",
    "chars": 20015,
    "preview": "variable \"zone_id\" {\n  type        = any\n  default     = []\n  description = <<-EOT\n    Route53 DNS Zone ID as list of st"
  },
  {
    "path": "versions.tf",
    "chars": 310,
    "preview": "terraform {\n  required_version = \">= 1.0.0\"\n\n  required_providers {\n    aws = {\n      source  = \"hashicorp/aws\"\n      ve"
  }
]

About this extraction

This page contains the full source code of the cloudposse/terraform-aws-rds-cluster GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 65 files (331.4 KB), approximately 117.8k tokens, and a symbol index with 7 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!