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:
#
# 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.
[](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/).
[](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/).
[](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/).
[](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
## why
## references
================================================
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
================================================




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.
> Works with [Github Actions](https://atmos.tools/integrations/github-actions/), [Atlantis](https://atmos.tools/integrations/atlantis), or [Spacelift](https://atmos.tools/integrations/spacelift).
>
>
> Watch demo of using Atmos with Terraform
> 
> Example of running atmos to manage infrastructure from our Quick Start tutorial.
>
## 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.
## Requirements
| Name | Version |
| ---- | ------- |
| [terraform](#requirement\_terraform) | >= 1.0.0 |
| [aws](#requirement\_aws) | >= 5.81.0 |
| [null](#requirement\_null) | >= 2.0 |
| [random](#requirement\_random) | >= 2.0 |
## Providers
| Name | Version |
| ---- | ------- |
| [aws](#provider\_aws) | >= 5.81.0 |
| [random](#provider\_random) | >= 2.0 |
## Modules
| Name | Source | Version |
| ---- | ------ | ------- |
| [dns\_master](#module\_dns\_master) | cloudposse/route53-cluster-hostname/aws | 0.13.0 |
| [dns\_replicas](#module\_dns\_replicas) | cloudposse/route53-cluster-hostname/aws | 0.13.0 |
| [enhanced\_monitoring\_label](#module\_enhanced\_monitoring\_label) | cloudposse/label/null | 0.25.0 |
| [rds\_identifier](#module\_rds\_identifier) | cloudposse/label/null | 0.25.0 |
| [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 |
| ---- | ----------- | ---- | ------- | :------: |
| [activity\_stream\_enabled](#input\_activity\_stream\_enabled) | Whether to enable Activity Streams | `bool` | `false` | no |
| [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 |
| [activity\_stream\_mode](#input\_activity\_stream\_mode) | The mode for the Activity Streams. `async` and `sync` are supported. Defaults to `async` | `string` | `"async"` | no |
| [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`.
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. | `map(string)` | `{}` | no |
| [admin\_password](#input\_admin\_password) | Password for the master DB user. Ignored if snapshot\_identifier or replication\_source\_identifier is provided | `string` | `""` | no |
| [admin\_user](#input\_admin\_user) | Username for the master DB user. Ignored if snapshot\_identifier or replication\_source\_identifier is provided | `string` | `"admin"` | no |
| [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.
To use a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN.
If not specified, the default KMS key for your Amazon Web Services account is used. | `string` | `null` | no |
| [allocated\_storage](#input\_allocated\_storage) | The allocated storage in GBs | `number` | `null` | no |
| [allow\_major\_version\_upgrade](#input\_allow\_major\_version\_upgrade) | Enable to allow major engine version upgrades when changing engine versions. Defaults to false. | `bool` | `false` | no |
| [allowed\_cidr\_blocks](#input\_allowed\_cidr\_blocks) | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no |
| [allowed\_ipv6\_cidr\_blocks](#input\_allowed\_ipv6\_cidr\_blocks) | List of IPv6 CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no |
| [apply\_immediately](#input\_apply\_immediately) | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no |
| [attributes](#input\_attributes) | 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. | `list(string)` | `[]` | no |
| [auto\_minor\_version\_upgrade](#input\_auto\_minor\_version\_upgrade) | Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window | `bool` | `true` | no |
| [autoscaling\_enabled](#input\_autoscaling\_enabled) | Whether to enable cluster autoscaling | `bool` | `false` | no |
| [autoscaling\_max\_capacity](#input\_autoscaling\_max\_capacity) | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no |
| [autoscaling\_min\_capacity](#input\_autoscaling\_min\_capacity) | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no |
| [autoscaling\_policy\_type](#input\_autoscaling\_policy\_type) | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no |
| [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 |
| [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 |
| [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 |
| [autoscaling\_target\_value](#input\_autoscaling\_target\_value) | The target value to scale with respect to target metrics | `number` | `75` | no |
| [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 |
| [backup\_window](#input\_backup\_window) | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no |
| [ca\_cert\_identifier](#input\_ca\_cert\_identifier) | The identifier of the CA certificate for the DB instance | `string` | `null` | no |
| [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 |
| [cluster\_family](#input\_cluster\_family) | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no |
| [cluster\_identifier](#input\_cluster\_identifier) | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no |
| [cluster\_parameters](#input\_cluster\_parameters) | List of DB cluster parameters to apply | list(object({
apply_method = string
name = string
value = string
})) | `[]` | no |
| [cluster\_size](#input\_cluster\_size) | Number of DB instances to create in the cluster | `number` | `2` | no |
| [cluster\_type](#input\_cluster\_type) | Either `regional` or `global`.
If `regional` will be created as a normal, standalone DB.
If `global`, will be made part of a Global cluster (requires `global_cluster_identifier`). | `string` | `"regional"` | no |
| [context](#input\_context) | 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. | `any` | {
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"descriptor_formats": {},
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"labels_as_tags": [
"unset"
],
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {},
"tenant": null
} | no |
| [copy\_tags\_to\_snapshot](#input\_copy\_tags\_to\_snapshot) | Copy tags to backup snapshots | `bool` | `false` | no |
| [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 |
| [db\_cluster\_instance\_class](#input\_db\_cluster\_instance\_class) | This setting is required to create a provisioned Multi-AZ DB cluster | `string` | `null` | no |
| [db\_name](#input\_db\_name) | Database name (default is not to create a database) | `string` | `""` | no |
| [db\_parameter\_group\_name](#input\_db\_parameter\_group\_name) | The name to give to the created `aws_db_parameter_group` resource.
If omitted, the module will generate a name. | `string` | `""` | no |
| [db\_port](#input\_db\_port) | Database port | `number` | `3306` | no |
| [deletion\_protection](#input\_deletion\_protection) | If the DB instance should have deletion protection enabled | `bool` | `false` | no |
| [delimiter](#input\_delimiter) | Delimiter to be used between ID elements.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no |
| [descriptor\_formats](#input\_descriptor\_formats) | 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). | `any` | `{}` | no |
| [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 |
| [enable\_global\_write\_forwarding](#input\_enable\_global\_write\_forwarding) | Set to `true`, to forward writes to an associated global cluster. | `bool` | `null` | no |
| [enable\_http\_endpoint](#input\_enable\_http\_endpoint) | Enable HTTP endpoint (data API). | `bool` | `false` | no |
| [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 |
| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no |
| [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 |
| [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 |
| [engine\_mode](#input\_engine\_mode) | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no |
| [engine\_version](#input\_engine\_version) | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no |
| [enhanced\_monitoring\_attributes](#input\_enhanced\_monitoring\_attributes) | The attributes for the enhanced monitoring IAM role | `list(string)` | [
"enhanced-monitoring"
]
| no |
| [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 |
| [environment](#input\_environment) | ID element. Usually used for region e.g. 'uw2', 'us-west-2', OR role 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no |
| [global\_cluster\_identifier](#input\_global\_cluster\_identifier) | ID of the Aurora global cluster | `string` | `""` | no |
| [iam\_database\_authentication\_enabled](#input\_iam\_database\_authentication\_enabled) | Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled | `bool` | `false` | no |
| [iam\_roles](#input\_iam\_roles) | Iam roles for the Aurora cluster | `list(string)` | `[]` | no |
| [id\_length\_limit](#input\_id\_length\_limit) | 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`. | `number` | `null` | no |
| [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 |
| [instance\_identifier\_suffix](#input\_instance\_identifier\_suffix) | The suffix to append to DB instance identifiers.
If `null`, the module will generate a random suffix. If empty, no suffix will be appended. | `string` | `null` | no |
| [instance\_parameters](#input\_instance\_parameters) | List of DB instance parameters to apply | list(object({
apply_method = string
name = string
value = string
})) | `[]` | no |
| [instance\_type](#input\_instance\_type) | Instance type to use | `string` | `"db.t2.small"` | no |
| [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 |
| [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 |
| [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 |
| [label\_key\_case](#input\_label\_key\_case) | 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`. | `string` | `null` | no |
| [label\_order](#input\_label\_order) | 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. | `list(string)` | `null` | no |
| [label\_value\_case](#input\_label\_value\_case) | 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`. | `string` | `null` | no |
| [labels\_as\_tags](#input\_labels\_as\_tags) | 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. | `set(string)` | [
"default"
]
| no |
| [maintenance\_window](#input\_maintenance\_window) | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no |
| [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 |
| [name](#input\_name) | 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. | `string` | `null` | no |
| [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 |
| [network\_type](#input\_network\_type) | The network type of the cluster. Valid values: IPV4, DUAL. | `string` | `"IPV4"` | no |
| [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 |
| [performance\_insights\_enabled](#input\_performance\_insights\_enabled) | Whether to enable Performance Insights | `bool` | `false` | no |
| [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 |
| [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 |
| [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.
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 |
| [publicly\_accessible](#input\_publicly\_accessible) | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no |
| [rds\_cluster\_parameter\_group\_name](#input\_rds\_cluster\_parameter\_group\_name) | The name to give to the created `aws_rds_cluster_parameter_group` resource.
If omitted, the module will generate a name. | `string` | `""` | no |
| [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 |
| [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 |
| [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 |
| [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 |
| [rds\_ri\_reservation\_id](#input\_rds\_ri\_reservation\_id) | Customer-specified identifier to track the reservation of the reserved DB instance. | `string` | `null` | no |
| [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 |
| [regex\_replace\_chars](#input\_regex\_replace\_chars) | 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. | `string` | `null` | no |
| [replication\_source\_identifier](#input\_replication\_source\_identifier) | ARN of a source DB cluster or DB instance if this DB cluster is to be created as a Read Replica | `string` | `""` | no |
| [restore\_to\_point\_in\_time](#input\_restore\_to\_point\_in\_time) | List of point-in-time recovery options. Valid parameters are:
`source_cluster_identifier`
Identifier of the source database cluster from which to restore.
`restore_type`:
Type of restore to be performed. Valid options are "full-copy" and "copy-on-write".
`use_latest_restorable_time`:
Set to true to restore the database cluster to the latest restorable backup time. Conflicts with `restore_to_time`.
`restore_to_time`:
Date and time in UTC format to restore the database cluster to. Conflicts with `use_latest_restorable_time`. | list(object({
source_cluster_identifier = string
restore_type = optional(string, "copy-on-write")
use_latest_restorable_time = optional(bool, true)
restore_to_time = optional(string, null)
})) | `[]` | no |
| [retention\_period](#input\_retention\_period) | Number of days to retain backups for | `number` | `5` | no |
| [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. | object({
bucket_name = string
bucket_prefix = string
ingestion_role = string
source_engine = string
source_engine_version = string
}) | `null` | no |
| [scaling\_configuration](#input\_scaling\_configuration) | List of nested attributes with scaling properties. Only valid when `engine_mode` is set to `serverless` | list(object({
auto_pause = bool
max_capacity = number
min_capacity = number
seconds_until_auto_pause = number
timeout_action = string
})) | `[]` | no |
| [security\_groups](#input\_security\_groups) | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no |
| [serverlessv2\_scaling\_configuration](#input\_serverlessv2\_scaling\_configuration) | serverlessv2 scaling properties | object({
min_capacity = number
max_capacity = number
seconds_until_auto_pause = optional(number, null)
}) | `null` | no |
| [skip\_final\_snapshot](#input\_skip\_final\_snapshot) | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no |
| [snapshot\_identifier](#input\_snapshot\_identifier) | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no |
| [source\_region](#input\_source\_region) | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no |
| [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no |
| [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 |
| [storage\_type](#input\_storage\_type) | One of 'standard' (magnetic), 'gp2' (general purpose SSD), 'io1' (provisioned IOPS SSD), 'aurora', or 'aurora-iopt1' | `string` | `null` | no |
| [subnet\_group\_name](#input\_subnet\_group\_name) | Database subnet group name. Will use generated label ID if not supplied. | `string` | `""` | no |
| [subnets](#input\_subnets) | List of VPC subnet IDs | `list(string)` | n/a | yes |
| [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no |
| [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 |
| [timeouts\_configuration](#input\_timeouts\_configuration) | List of timeout values per action. Only valid actions are `create`, `update` and `delete` | list(object({
create = string
update = string
delete = string
})) | `[]` | no |
| [use\_reserved\_instances](#input\_use\_reserved\_instances) | WARNING: Observe your plans and applies carefully when using this feature.
It has potential to be very expensive if not used correctly.
Also, it is not clear what happens when the reservation expires.
Whether to use reserved instances. | `bool` | `false` | no |
| [vpc\_id](#input\_vpc\_id) | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes |
| [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 |
| [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.
If the list contains a single Zone ID, a custom DNS name will be pulished in that zone.
Can also be a plain string, but that use is DEPRECATED because of Terraform issues. | `any` | `[]` | no |
## Outputs
| Name | Description |
| ---- | ----------- |
| [activity\_stream\_arn](#output\_activity\_stream\_arn) | Activity Stream ARN |
| [activity\_stream\_name](#output\_activity\_stream\_name) | Activity Stream Name |
| [admin\_user\_secret](#output\_admin\_user\_secret) | The secret manager attributes for the managed admin user password (`master_user_secret`). |
| [arn](#output\_arn) | Amazon Resource Name (ARN) of the cluster |
| [cluster\_identifier](#output\_cluster\_identifier) | Cluster Identifier |
| [cluster\_resource\_id](#output\_cluster\_resource\_id) | The region-unique, immutable identifie of the cluster |
| [cluster\_security\_groups](#output\_cluster\_security\_groups) | Default RDS cluster security groups |
| [database\_name](#output\_database\_name) | Database name |
| [dbi\_resource\_ids](#output\_dbi\_resource\_ids) | List of the region-unique, immutable identifiers for the DB instances in the cluster |
| [endpoint](#output\_endpoint) | The DNS address of the RDS instance |
| [instance\_arns](#output\_instance\_arns) | List of ARNs of the DB instances in the cluster |
| [instance\_endpoints](#output\_instance\_endpoints) | List of DNS addresses for the DB instances in the cluster |
| [master\_host](#output\_master\_host) | DB Master hostname |
| [master\_username](#output\_master\_username) | Username for the master DB user |
| [port](#output\_port) | DB port |
| [reader\_endpoint](#output\_reader\_endpoint) | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas |
| [replicas\_host](#output\_replicas\_host) | Replicas hostname |
| [reserved\_instance](#output\_reserved\_instance) | All information about the reserved instance(s) if created. |
| [security\_group\_arn](#output\_security\_group\_arn) | Security Group ARN |
| [security\_group\_id](#output\_security\_group\_id) | Security Group ID |
| [security\_group\_name](#output\_security\_group\_name) | Security Group name |
## 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.
> ✅ Your team owns everything.
> ✅ 100% Open Source and backed by fanatical support.
>
>
> 📚 Learn More
>
>
>
> 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.
>
>
>
> #### 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.
>
>
>
## ✨ Contributing
This project is under active development, and we encourage contributions from our community.
Many thanks to our outstanding contributors:
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
[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
Preamble to the Apache License, Version 2.0
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.
```
## Trademarks
All other trademarks referenced herein are the property of their respective owners.
---
Copyright © 2017-2026 [Cloud Posse, LLC](https://cpco.io/copyright)
================================================
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.`,
# 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.`,
# 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.`,
# 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.`,
# 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_cluster_activity_stream.primary[*].kinesis_stream_name)
description = "Activity Stream Name"
}
output "reserved_instance" {
value = aws_rds_reserved_instance.default
description = "All information about the reserved instance(s) if created."
}
================================================
FILE: test/.gitignore
================================================
.test-harness
================================================
FILE: test/Makefile
================================================
TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git
TEST_HARNESS_BRANCH ?= master
TEST_HARNESS_PATH = $(realpath .test-harness)
BATS_ARGS ?= --tap
BATS_LOG ?= test.log
# Define a macro to run the tests
define RUN_TESTS
@echo "Running tests in $(1)"
@cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS)))
endef
default: all
-include Makefile.*
## Provision the test-harnesss
.test-harness:
[ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@
## Initialize the tests
init: .test-harness
## Install all dependencies (OS specific)
deps::
@exit 0
## Clean up the test harness
clean:
[ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH)
## Run all tests
all: module examples/complete
## Run basic sanity checks against the module itself
module: export TESTS ?= installed lint module-pinning provider-pinning validate terraform-docs input-descriptions output-descriptions
module: deps
$(call RUN_TESTS, ../)
## Run tests against example
examples/complete: export TESTS ?= installed lint validate
examples/complete: deps
$(call RUN_TESTS, ../$@)
================================================
FILE: test/Makefile.alpine
================================================
ifneq (,$(wildcard /sbin/apk))
## Install all dependencies for alpine
deps:: init
@apk add --update terraform-docs@cloudposse json2hcl@cloudposse
endif
================================================
FILE: test/src/.gitignore
================================================
.gopath
vendor/
================================================
FILE: test/src/Makefile
================================================
export TERRAFORM_VERSION ?= $(shell curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version' | cut -d. -f1)
export GOTOOLCHAIN = local
.DEFAULT_GOAL : all
.PHONY: all
## Default target
all: test
.PHONY : init
## Initialize tests
init:
@exit 0
.PHONY : test
## Run tests
test: init
go mod download
# Allow more parallel tests than there are CPU cores because most of the time tests are just waiting for AWS
go test -v -timeout 60m -parallel 8
## Run tests in docker container
docker/test:
docker run --name terratest --rm -it -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e GITHUB_TOKEN -e GOTOOLCHAIN \
-e PATH="/usr/local/terraform/$(TERRAFORM_VERSION)/bin:/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" \
-v $(CURDIR)/../../:/module/ cloudposse/test-harness:latest -C /module/test/src test
.PHONY : clean
## Clean up files
clean:
rm -rf ../../examples/complete/*.tfstate*
rm -rf ../../examples/serverlessv2_postgres/*.tfstate*
================================================
FILE: test/src/examples_complete_test.go
================================================
package test
import (
"regexp"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/gruntwork-io/terratest/modules/terraform"
testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
)
// Test the Terraform module in examples/complete using Terratest.
func TestExamplesComplete(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/complete"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
// Run `terraform output` to get the value of an output variable
vpcCidr := terraform.Output(t, terraformOptions, "vpc_cidr")
// Verify we're getting back the outputs we expect
assert.Equal(t, "172.16.0.0/16", vpcCidr)
// Run `terraform output` to get the value of an output variable
privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19"}, privateSubnetCidrs)
// Run `terraform output` to get the value of an output variable
publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19"}, publicSubnetCidrs)
// Run `terraform output` to get the value of an output variable
clusterIdentifier := terraform.Output(t, terraformOptions, "cluster_identifier")
expectedClusterIdentifier := "eg-test-rds-cluster-" + randID
// Verify we're getting back the outputs we expect
assert.Equal(t, expectedClusterIdentifier, clusterIdentifier)
// Run `terraform output` to get the value of an output variable
arn := terraform.Output(t, terraformOptions, "arn")
// Verify we're getting back the outputs we expect
assert.Contains(t, arn, ":cluster:eg-test-rds-cluster")
}
func TestExamplesCompleteDisabled(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/complete"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
"enabled": false,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
results := terraform.InitAndApply(t, terraformOptions)
// Should complete successfully without creating or changing any resources.
// Extract the "Resources:" section of the output to make the error message more readable.
re := regexp.MustCompile(`Resources: [^.]+\.`)
match := re.FindString(results)
assert.Equal(t, "Resources: 0 added, 0 changed, 0 destroyed.", match, "Re-applying the same configuration should not change any resources")
}
================================================
FILE: test/src/examples_postgres_test.go
================================================
package test
import (
"regexp"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/gruntwork-io/terratest/modules/terraform"
testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
)
// Test the Terraform module in examples/postgres using Terratest.
func TestExamplesPostgres(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/postgres"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
// Run `terraform output` to get the value of an output variable
vpcCidr := terraform.Output(t, terraformOptions, "vpc_cidr")
// Verify we're getting back the outputs we expect
assert.Equal(t, "172.16.0.0/16", vpcCidr)
// Run `terraform output` to get the value of an output variable
privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19", "172.16.64.0/19"}, privateSubnetCidrs)
// Run `terraform output` to get the value of an output variable
publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19", "172.16.160.0/19"}, publicSubnetCidrs)
// Run `terraform output` to get the value of an output variable
clusterIdentifier := terraform.Output(t, terraformOptions, "cluster_identifier")
expectedClusterIdentifier := "eg-test-rds-cluster-" + randID
// Verify we're getting back the outputs we expect
assert.Equal(t, expectedClusterIdentifier, clusterIdentifier)
// Run `terraform output` to get the value of an output variable
arn := terraform.Output(t, terraformOptions, "arn")
// Verify we're getting back the outputs we expect
assert.Contains(t, arn, ":cluster:eg-test-rds-cluster")
}
func TestExamplesPostgresDisabled(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/postgres"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
"enabled": false,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
results := terraform.InitAndApply(t, terraformOptions)
// Should complete successfully without creating or changing any resources.
// Extract the "Resources:" section of the output to make the error message more readable.
re := regexp.MustCompile(`Resources: [^.]+\.`)
match := re.FindString(results)
assert.Equal(t, "Resources: 0 added, 0 changed, 0 destroyed.", match, "Re-applying the same configuration should not change any resources")
}
================================================
FILE: test/src/examples_serverlessv2_postgres_test.go
================================================
package test
import (
"regexp"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/random"
"github.com/gruntwork-io/terratest/modules/terraform"
testStructure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
)
// Test the Terraform module in examples/serverlessv2_postgres using Terratest.
func TestExamplesServerlessV2Postgres(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/serverlessv2_postgres"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
// Run `terraform output` to get the value of an output variable
vpcCidr := terraform.Output(t, terraformOptions, "vpc_cidr")
// Verify we're getting back the outputs we expect
assert.Equal(t, "172.16.0.0/16", vpcCidr)
// Run `terraform output` to get the value of an output variable
privateSubnetCidrs := terraform.OutputList(t, terraformOptions, "private_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.0.0/19", "172.16.32.0/19"}, privateSubnetCidrs)
// Run `terraform output` to get the value of an output variable
publicSubnetCidrs := terraform.OutputList(t, terraformOptions, "public_subnet_cidrs")
// Verify we're getting back the outputs we expect
assert.Equal(t, []string{"172.16.96.0/19", "172.16.128.0/19"}, publicSubnetCidrs)
// Run `terraform output` to get the value of an output variable
clusterIdentifier := terraform.Output(t, terraformOptions, "cluster_identifier")
expectedClusterIdentifier := "eg-test-rds-cluster-" + randID
// Verify we're getting back the outputs we expect
assert.Equal(t, expectedClusterIdentifier, clusterIdentifier)
// Run `terraform output` to get the value of an output variable
arn := terraform.Output(t, terraformOptions, "arn")
// Verify we're getting back the outputs we expect
assert.Contains(t, arn, ":cluster:eg-test-rds-cluster")
}
func TestExamplesServerlessV2PostgresDisabled(t *testing.T) {
t.Parallel()
randID := strings.ToLower(random.UniqueId())
attributes := []string{randID}
rootFolder := "../../"
terraformFolderRelativeToRoot := "examples/serverlessv2_postgres"
varFiles := []string{"fixtures.us-east-2.tfvars"}
tempTestFolder := testStructure.CopyTerraformFolderToTemp(t, rootFolder, terraformFolderRelativeToRoot)
terraformOptions := &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: tempTestFolder,
Upgrade: true,
// Variables to pass to our Terraform code using -var-file options
VarFiles: varFiles,
Vars: map[string]interface{}{
"attributes": attributes,
"enabled": false,
},
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer cleanup(t, terraformOptions, tempTestFolder)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
results := terraform.InitAndApply(t, terraformOptions)
// Should complete successfully without creating or changing any resources.
// Extract the "Resources:" section of the output to make the error message more readable.
re := regexp.MustCompile(`Resources: [^.]+\.`)
match := re.FindString(results)
assert.Equal(t, "Resources: 0 added, 0 changed, 0 destroyed.", match, "Re-applying the same configuration should not change any resources")
}
================================================
FILE: test/src/go.mod
================================================
module github.com/cloudposse/terraform-aws-rds-cluster
go 1.24
toolchain go1.24.0
require (
github.com/gruntwork-io/terratest v0.46.15
github.com/stretchr/testify v1.8.4
)
require (
cloud.google.com/go v0.110.0 // indirect
cloud.google.com/go/compute v1.19.1 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
cloud.google.com/go/iam v0.13.0 // indirect
cloud.google.com/go/storage v1.28.1 // indirect
github.com/agext/levenshtein v1.2.3 // indirect
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
github.com/aws/aws-sdk-go v1.44.122 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-sql-driver/mysql v1.4.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
github.com/googleapis/gax-go/v2 v2.7.1 // indirect
github.com/gruntwork-io/go-commons v0.8.0 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter v1.7.4 // indirect
github.com/hashicorp/go-multierror v1.1.0 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl/v2 v2.9.1 // indirect
github.com/hashicorp/terraform-json v0.13.0 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.15.11 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/otp v1.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tmccombs/hcl2json v0.3.3 // indirect
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/urfave/cli v1.22.2 // indirect
github.com/zclconf/go-cty v1.9.1 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.114.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
google.golang.org/grpc v1.56.3 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.28.4 // indirect
k8s.io/apimachinery v0.28.4 // indirect
k8s.io/client-go v0.28.4 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
================================================
FILE: test/src/go.sum
================================================
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc=
cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34hIU=
cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA=
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
cloud.google.com/go/aiplatform v1.22.0/go.mod h1:ig5Nct50bZlzV6NvKaTwmplLLddFx0YReh9WfTO5jKw=
cloud.google.com/go/aiplatform v1.24.0/go.mod h1:67UUvRBKG6GTayHKV8DBv2RtR1t93YRu5B1P3x99mYY=
cloud.google.com/go/analytics v0.11.0/go.mod h1:DjEWCu41bVbYcKyvlws9Er60YE4a//bK6mnhWvQeFNI=
cloud.google.com/go/analytics v0.12.0/go.mod h1:gkfj9h6XRf9+TS4bmuhPEShsh3hH8PAZzm/41OOhQd4=
cloud.google.com/go/area120 v0.5.0/go.mod h1:DE/n4mp+iqVyvxHN41Vf1CR602GiHQjFPusMFW6bGR4=
cloud.google.com/go/area120 v0.6.0/go.mod h1:39yFJqWVgm0UZqWTOdqkLhjoC7uFfgXRC8g/ZegeAh0=
cloud.google.com/go/artifactregistry v1.6.0/go.mod h1:IYt0oBPSAGYj/kprzsBjZ/4LnG/zOcHyFHjWPCi6SAQ=
cloud.google.com/go/artifactregistry v1.7.0/go.mod h1:mqTOFOnGZx8EtSqK/ZWcsm/4U8B77rbcLP6ruDU2Ixk=
cloud.google.com/go/asset v1.5.0/go.mod h1:5mfs8UvcM5wHhqtSv8J1CtxxaQq3AdBxxQi2jGW/K4o=
cloud.google.com/go/asset v1.7.0/go.mod h1:YbENsRK4+xTiL+Ofoj5Ckf+O17kJtgp3Y3nn4uzZz5s=
cloud.google.com/go/asset v1.8.0/go.mod h1:mUNGKhiqIdbr8X7KNayoYvyc4HbbFO9URsjbytpUaW0=
cloud.google.com/go/assuredworkloads v1.5.0/go.mod h1:n8HOZ6pff6re5KYfBXcFvSViQjDwxFkAkmUFffJRbbY=
cloud.google.com/go/assuredworkloads v1.6.0/go.mod h1:yo2YOk37Yc89Rsd5QMVECvjaMKymF9OP+QXWlKXUkXw=
cloud.google.com/go/assuredworkloads v1.7.0/go.mod h1:z/736/oNmtGAyU47reJgGN+KVoYoxeLBoj4XkKYscNI=
cloud.google.com/go/automl v1.5.0/go.mod h1:34EjfoFGMZ5sgJ9EoLsRtdPSNZLcfflJR39VbVNS2M0=
cloud.google.com/go/automl v1.6.0/go.mod h1:ugf8a6Fx+zP0D59WLhqgTDsQI9w07o64uf/Is3Nh5p8=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA=
cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY=
cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s=
cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM=
cloud.google.com/go/binaryauthorization v1.2.0/go.mod h1:86WKkJHtRcv5ViNABtYMhhNWRrD1Vpi//uKEy7aYEfI=
cloud.google.com/go/cloudtasks v1.5.0/go.mod h1:fD92REy1x5woxkKEkLdvavGnPJGEn8Uic9nWuLzqCpY=
cloud.google.com/go/cloudtasks v1.6.0/go.mod h1:C6Io+sxuke9/KNRkbQpihnW93SWDU3uXt92nu85HkYI=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U=
cloud.google.com/go/compute v1.10.0/go.mod h1:ER5CLbMxl90o2jtNbGSbtfOpQKR0t15FOtRsugnLrlU=
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/containeranalysis v0.5.1/go.mod h1:1D92jd8gRR/c0fGMlymRgxWD3Qw9C1ff6/T7mLgVL8I=
cloud.google.com/go/containeranalysis v0.6.0/go.mod h1:HEJoiEIu+lEXM+k7+qLCci0h33lX3ZqoYFdmPcoO7s4=
cloud.google.com/go/datacatalog v1.3.0/go.mod h1:g9svFY6tuR+j+hrTw3J2dNcmI0dzmSiyOzm8kpLq0a0=
cloud.google.com/go/datacatalog v1.5.0/go.mod h1:M7GPLNQeLfWqeIm3iuiruhPzkt65+Bx8dAKvScX8jvs=
cloud.google.com/go/datacatalog v1.6.0/go.mod h1:+aEyF8JKg+uXcIdAmmaMUmZ3q1b/lKLtXCmXdnc0lbc=
cloud.google.com/go/dataflow v0.6.0/go.mod h1:9QwV89cGoxjjSR9/r7eFDqqjtvbKxAK2BaYU6PVk9UM=
cloud.google.com/go/dataflow v0.7.0/go.mod h1:PX526vb4ijFMesO1o202EaUmouZKBpjHsTlCtB4parQ=
cloud.google.com/go/dataform v0.3.0/go.mod h1:cj8uNliRlHpa6L3yVhDOBrUXH+BPAO1+KFMQQNSThKo=
cloud.google.com/go/dataform v0.4.0/go.mod h1:fwV6Y4Ty2yIFL89huYlEkwUPtS7YZinZbzzj5S9FzCE=
cloud.google.com/go/datalabeling v0.5.0/go.mod h1:TGcJ0G2NzcsXSE/97yWjIZO0bXj0KbVlINXMG9ud42I=
cloud.google.com/go/datalabeling v0.6.0/go.mod h1:WqdISuk/+WIGeMkpw/1q7bK/tFEZxsrFJOJdY2bXvTQ=
cloud.google.com/go/dataqna v0.5.0/go.mod h1:90Hyk596ft3zUQ8NkFfvICSIfHFh1Bc7C4cK3vbhkeo=
cloud.google.com/go/dataqna v0.6.0/go.mod h1:1lqNpM7rqNLVgWBJyk5NF6Uen2PHym0jtVJonplVsDA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/datastream v1.2.0/go.mod h1:i/uTP8/fZwgATHS/XFu0TcNUhuA0twZxxQ3EyCUQMwo=
cloud.google.com/go/datastream v1.3.0/go.mod h1:cqlOX8xlyYF/uxhiKn6Hbv6WjwPPuI9W2M9SAXwaLLQ=
cloud.google.com/go/dialogflow v1.15.0/go.mod h1:HbHDWs33WOGJgn6rfzBW1Kv807BE3O1+xGbn59zZWI4=
cloud.google.com/go/dialogflow v1.16.1/go.mod h1:po6LlzGfK+smoSmTBnbkIZY2w8ffjz/RcGSS+sh1el0=
cloud.google.com/go/dialogflow v1.17.0/go.mod h1:YNP09C/kXA1aZdBgC/VtXX74G/TKn7XVCcVumTflA+8=
cloud.google.com/go/documentai v1.7.0/go.mod h1:lJvftZB5NRiFSX4moiye1SMxHx0Bc3x1+p9e/RfXYiU=
cloud.google.com/go/documentai v1.8.0/go.mod h1:xGHNEB7CtsnySCNrCFdCyyMz44RhFEEX2Q7UD0c5IhU=
cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1wTxDeT4Y=
cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg=
cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk=
cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w=
cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk=
cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg=
cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM=
cloud.google.com/go/gaming v1.6.0/go.mod h1:YMU1GEvA39Qt3zWGyAVA9bpYz/yAhTvaQ1t2sK4KPUA=
cloud.google.com/go/gkeconnect v0.5.0/go.mod h1:c5lsNAg5EwAy7fkqX/+goqFsU1Da/jQFqArp+wGNr/o=
cloud.google.com/go/gkeconnect v0.6.0/go.mod h1:Mln67KyU/sHJEBY8kFZ0xTeyPtzbq9StAVvEULYK16A=
cloud.google.com/go/gkehub v0.9.0/go.mod h1:WYHN6WG8w9bXU0hqNxt8rm5uxnk8IH+lPY9J2TV7BK0=
cloud.google.com/go/gkehub v0.10.0/go.mod h1:UIPwxI0DsrpsVoWpLB0stwKCP+WFVG9+y977wO+hBH0=
cloud.google.com/go/grafeas v0.2.0/go.mod h1:KhxgtF2hb0P191HlY5besjYm6MqTSTj3LSI+M+ByZHc=
cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY=
cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3QpkUc=
cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k=
cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0=
cloud.google.com/go/language v1.4.0/go.mod h1:F9dRpNFQmJbkaop6g0JhSBXCNlO90e1KWx5iDdxbWic=
cloud.google.com/go/language v1.6.0/go.mod h1:6dJ8t3B+lUYfStgls25GusK04NLh3eDLQnWM3mdEbhI=
cloud.google.com/go/lifesciences v0.5.0/go.mod h1:3oIKy8ycWGPUyZDR/8RNnTOYevhaMLqh5vLUXs9zvT8=
cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6t/iPhY2Tyfu08=
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo=
cloud.google.com/go/mediatranslation v0.5.0/go.mod h1:jGPUhGTybqsPQn91pNXw0xVHfuJ3leR1wj37oU3y1f4=
cloud.google.com/go/mediatranslation v0.6.0/go.mod h1:hHdBCTYNigsBxshbznuIMFNe5QXEowAuNmmC7h8pu5w=
cloud.google.com/go/memcache v1.4.0/go.mod h1:rTOfiGZtJX1AaFUrOgsMHX5kAzaTQ8azHiuDoTPzNsE=
cloud.google.com/go/memcache v1.5.0/go.mod h1:dk3fCK7dVo0cUU2c36jKb4VqKPS22BTkf81Xq617aWM=
cloud.google.com/go/metastore v1.5.0/go.mod h1:2ZNrDcQwghfdtCwJ33nM0+GrBGlVuh8rakL3vdPY3XY=
cloud.google.com/go/metastore v1.6.0/go.mod h1:6cyQTls8CWXzk45G55x57DVQ9gWg7RiH65+YgPsNh9s=
cloud.google.com/go/networkconnectivity v1.4.0/go.mod h1:nOl7YL8odKyAOtzNX73/M5/mGZgqqMeryi6UPZTk/rA=
cloud.google.com/go/networkconnectivity v1.5.0/go.mod h1:3GzqJx7uhtlM3kln0+x5wyFvuVH1pIBJjhCpjzSt75o=
cloud.google.com/go/networksecurity v0.5.0/go.mod h1:xS6fOCoqpVC5zx15Z/MqkfDwH4+m/61A3ODiDV1xmiQ=
cloud.google.com/go/networksecurity v0.6.0/go.mod h1:Q5fjhTr9WMI5mbpRYEbiexTzROf7ZbDzvzCrNl14nyU=
cloud.google.com/go/notebooks v1.2.0/go.mod h1:9+wtppMfVPUeJ8fIWPOq1UnATHISkGXGqTkxeieQ6UY=
cloud.google.com/go/notebooks v1.3.0/go.mod h1:bFR5lj07DtCPC7YAAJ//vHskFBxA5JzYlH68kXVdk34=
cloud.google.com/go/osconfig v1.7.0/go.mod h1:oVHeCeZELfJP7XLxcBGTMBvRO+1nQ5tFG9VQTmYS2Fs=
cloud.google.com/go/osconfig v1.8.0/go.mod h1:EQqZLu5w5XA7eKizepumcvWx+m8mJUhEwiPqWiZeEdg=
cloud.google.com/go/oslogin v1.4.0/go.mod h1:YdgMXWRaElXz/lDk1Na6Fh5orF7gvmJ0FGLIs9LId4E=
cloud.google.com/go/oslogin v1.5.0/go.mod h1:D260Qj11W2qx/HVF29zBg+0fd6YCSjSqLUkY/qEenQU=
cloud.google.com/go/phishingprotection v0.5.0/go.mod h1:Y3HZknsK9bc9dMi+oE8Bim0lczMU6hrX0UpADuMefr0=
cloud.google.com/go/phishingprotection v0.6.0/go.mod h1:9Y3LBLgy0kDTcYET8ZH3bq/7qni15yVUoAxiFxnlSUA=
cloud.google.com/go/privatecatalog v0.5.0/go.mod h1:XgosMUvvPyxDjAVNDYxJ7wBW8//hLDDYmnsNcMGq1K0=
cloud.google.com/go/privatecatalog v0.6.0/go.mod h1:i/fbkZR0hLN29eEWiiwue8Pb+GforiEIBnV9yrRUOKI=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/recaptchaenterprise v1.3.1/go.mod h1:OdD+q+y4XGeAlxRaMn1Y7/GveP6zmq76byL6tjPE7d4=
cloud.google.com/go/recaptchaenterprise/v2 v2.1.0/go.mod h1:w9yVqajwroDNTfGuhmOjPDN//rZGySaf6PtFVcSCa7o=
cloud.google.com/go/recaptchaenterprise/v2 v2.2.0/go.mod h1:/Zu5jisWGeERrd5HnlS3EUGb/D335f9k51B/FVil0jk=
cloud.google.com/go/recaptchaenterprise/v2 v2.3.0/go.mod h1:O9LwGCjrhGHBQET5CA7dd5NwwNQUErSgEDit1DLNTdo=
cloud.google.com/go/recommendationengine v0.5.0/go.mod h1:E5756pJcVFeVgaQv3WNpImkFP8a+RptV6dDLGPILjvg=
cloud.google.com/go/recommendationengine v0.6.0/go.mod h1:08mq2umu9oIqc7tDy8sx+MNJdLG0fUi3vaSVbztHgJ4=
cloud.google.com/go/recommender v1.5.0/go.mod h1:jdoeiBIVrJe9gQjwd759ecLJbxCDED4A6p+mqoqDvTg=
cloud.google.com/go/recommender v1.6.0/go.mod h1:+yETpm25mcoiECKh9DEScGzIRyDKpZ0cEhWGo+8bo+c=
cloud.google.com/go/redis v1.7.0/go.mod h1:V3x5Jq1jzUcg+UNsRvdmsfuFnit1cfe3Z/PGyq/lm4Y=
cloud.google.com/go/redis v1.8.0/go.mod h1:Fm2szCDavWzBk2cDKxrkmWBqoCiL1+Ctwq7EyqBCA/A=
cloud.google.com/go/retail v1.8.0/go.mod h1:QblKS8waDmNUhghY2TI9O3JLlFk8jybHeV4BF19FrE4=
cloud.google.com/go/retail v1.9.0/go.mod h1:g6jb6mKuCS1QKnH/dpu7isX253absFl6iE92nHwlBUY=
cloud.google.com/go/scheduler v1.4.0/go.mod h1:drcJBmxF3aqZJRhmkHQ9b3uSSpQoltBPGPxGAWROx6s=
cloud.google.com/go/scheduler v1.5.0/go.mod h1:ri073ym49NW3AfT6DZi21vLZrG07GXr5p3H1KxN5QlI=
cloud.google.com/go/secretmanager v1.6.0/go.mod h1:awVa/OXF6IiyaU1wQ34inzQNc4ISIDIrId8qE5QGgKA=
cloud.google.com/go/security v1.5.0/go.mod h1:lgxGdyOKKjHL4YG3/YwIL2zLqMFCKs0UbQwgyZmfJl4=
cloud.google.com/go/security v1.7.0/go.mod h1:mZklORHl6Bg7CNnnjLH//0UlAlaXqiG7Lb9PsPXLfD0=
cloud.google.com/go/security v1.8.0/go.mod h1:hAQOwgmaHhztFhiQ41CjDODdWP0+AE1B3sX4OFlq+GU=
cloud.google.com/go/securitycenter v1.13.0/go.mod h1:cv5qNAqjY84FCN6Y9z28WlkKXyWsgLO832YiWwkCWcU=
cloud.google.com/go/securitycenter v1.14.0/go.mod h1:gZLAhtyKv85n52XYWt6RmeBdydyxfPeTrpToDPw4Auc=
cloud.google.com/go/servicedirectory v1.4.0/go.mod h1:gH1MUaZCgtP7qQiI+F+A+OpeKF/HQWgtAddhTbhL2bs=
cloud.google.com/go/servicedirectory v1.5.0/go.mod h1:QMKFL0NUySbpZJ1UZs3oFAmdvVxhhxB6eJ/Vlp73dfg=
cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM=
cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y=
cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc=
cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s=
cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y=
cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw=
cloud.google.com/go/talent v1.2.0/go.mod h1:MoNF9bhFQbiJ6eFD3uSsg0uBALw4n4gaCaEjBw9zo8g=
cloud.google.com/go/videointelligence v1.6.0/go.mod h1:w0DIDlVRKtwPCn/C4iwZIJdvC69yInhW0cfi+p546uU=
cloud.google.com/go/videointelligence v1.7.0/go.mod h1:k8pI/1wAhjznARtVT9U1llUaFNPh7muw8QyOUpavru4=
cloud.google.com/go/vision v1.2.0/go.mod h1:SmNwgObm5DpFBme2xpyOyasvBc1aPdjvMk2bBk0tKD0=
cloud.google.com/go/vision/v2 v2.2.0/go.mod h1:uCdV4PpN1S0jyCyq8sIM42v2Y6zOLkZs+4R9LrGYwFo=
cloud.google.com/go/vision/v2 v2.3.0/go.mod h1:UO61abBx9QRMFkNBbf1D8B1LXdS2cGiiCRx0vSpZoUo=
cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xXZmFiHmGE=
cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg=
cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0=
cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo=
github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE=
github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU=
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c=
github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo=
github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY=
github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A=
github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI=
github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/gruntwork-io/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
github.com/gruntwork-io/terratest v0.46.15 h1:qfqjTFveymaqe7aAWn3LjlK0SwVGpRfoOut5ggNyfQ8=
github.com/gruntwork-io/terratest v0.46.15/go.mod h1:9bd22zAojjBBiYdsp+AR1iyl2iB6bRUVm2Yf1AFhfrA=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-getter v1.7.4 h1:3yQjWuxICvSpYwqSayAdKRFcvBl1y/vogCxczWSmix0=
github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl/v2 v2.9.1 h1:eOy4gREY0/ZQHNItlfuEZqtcQbXIxzojlP301hDpnac=
github.com/hashicorp/hcl/v2 v2.9.1/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
github.com/hashicorp/terraform-json v0.13.0 h1:Li9L+lKD1FO5RVFRM1mMMIBDoUHslOniyEi5CM+FWGY=
github.com/hashicorp/terraform-json v0.13.0/go.mod h1:y5OdLBCT+rxbwnpxZs9kGL7R9ExU76+cpdY8zHwoazk=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o=
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg=
github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU=
github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE=
github.com/onsi/ginkgo/v2 v2.9.4/go.mod h1:gCQYp2Q+kSoIj7ykSVb9nskRSsR6PUj4AiLywzIhbKM=
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/tmccombs/hcl2json v0.3.3 h1:+DLNYqpWE0CsOQiEZu+OZm5ZBImake3wtITYxQ8uLFQ=
github.com/tmccombs/hcl2json v0.3.3/go.mod h1:Y2chtz2x9bAeRTvSibVRVgbLJhLJXKlUeIvjeVdnm4w=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.8.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty v1.9.1 h1:viqrgQwFl5UpSxc046qblj78wZXVDFnSOufaOTER+cc=
github.com/zclconf/go-cty v1.9.1/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE=
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg=
golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220624220833-87e55d714810/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw=
google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o=
google.golang.org/api v0.85.0/go.mod h1:AqZf8Ep9uZ2pyTvgL+x0D3Zt0eoT9b5E8fmzfu6FO2g=
google.golang.org/api v0.90.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
google.golang.org/api v0.93.0/go.mod h1:+Sem1dnrKlrXMR/X0bPnMWyluQe4RsNoYfmNLhOIkzw=
google.golang.org/api v0.95.0/go.mod h1:eADj+UBuxkh5zlrSntJghuNeg8HwQ1w5lTKkuqaETEI=
google.golang.org/api v0.96.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.97.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.98.0/go.mod h1:w7wJQLTM+wvQpNf5JyEcBoxK0RH7EDrh/L4qfsuJ13s=
google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70=
google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE=
google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220617124728-180714bec0ad/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220624142145-8cd45d7dbd1f/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220628213854-d9e0b6570c03/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA=
google.golang.org/genproto v0.0.0-20220722212130-b98a9ff5e252/go.mod h1:GkXuJDJ6aQ7lnJcRF+SJVgFdQhypqgl3LB1C9vabdRE=
google.golang.org/genproto v0.0.0-20220801145646-83ce21fca29f/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
google.golang.org/genproto v0.0.0-20220815135757-37a418bb8959/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220817144833-d7fd3f11b9b1/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220822174746-9e6da59bd2fc/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220829144015-23454907ede3/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220829175752-36a9c930ecbf/go.mod h1:dbqgFATTzChvnt+ujMdZwITVAJHFtfyN1qUhDqEiIlk=
google.golang.org/genproto v0.0.0-20220913154956-18f8339a66a5/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220914142337-ca0e39ece12f/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220915135415-7fd63a7952de/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220916172020-2692e8806bfa/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220919141832-68c03719ef51/go.mod h1:0Nb8Qy+Sk5eDzHnzlStwW3itdNaWoZA5XeSG+R3JHSo=
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
google.golang.org/genproto v0.0.0-20220926165614-551eb538f295/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
google.golang.org/genproto v0.0.0-20220926220553-6981cbe3cfce/go.mod h1:woMGP53BroOrRY3xTxlbr8Y3eB/nzAvvFM83q7kG2OI=
google.golang.org/genproto v0.0.0-20221010155953-15ba04fc1c0e/go.mod h1:3526vdqwhZAwq4wsRUaVG555sVgsNmIjRtO7t/JH29U=
google.golang.org/genproto v0.0.0-20221014173430-6e2ab493f96b/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a/go.mod h1:1vXfmgAz9N9Jx0QA82PqRVauvCz1SGSz739p0f183jM=
google.golang.org/genproto v0.0.0-20221025140454-527a21cfbd71/go.mod h1:9qHF0xnpdSfF6knlcsnpzUu5y+rpwgbvsyGAZPBMg4s=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc=
google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY=
k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0=
k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8=
k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg=
k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY=
k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
================================================
FILE: test/src/utils.go
================================================
package test
import (
"os"
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
)
func cleanup(t *testing.T, terraformOptions *terraform.Options, tempTestFolder string) {
terraform.Destroy(t, terraformOptions)
_ = os.RemoveAll(tempTestFolder)
}
================================================
FILE: variables.tf
================================================
variable "zone_id" {
type = any
default = []
description = <<-EOT
Route53 DNS Zone ID as list of string (0 or 1 items). If empty, no custom DNS name will be published.
If the list contains a single Zone ID, a custom DNS name will be pulished in that zone.
Can also be a plain string, but that use is DEPRECATED because of Terraform issues.
EOT
}
variable "security_groups" {
type = list(string)
default = []
description = "List of security groups to be allowed to connect to the DB instance"
}
variable "vpc_id" {
type = string
description = "VPC ID to create the cluster in (e.g. `vpc-a22222ee`)"
}
variable "subnets" {
type = list(string)
description = "List of VPC subnet IDs"
}
variable "instance_type" {
type = string
default = "db.t2.small"
description = "Instance type to use"
}
variable "cluster_identifier" {
type = string
default = ""
description = "The RDS Cluster Identifier. Will use generated label ID if not supplied"
}
variable "instance_identifier_suffix" {
type = string
default = null
nullable = true
description = <<-EOT
The suffix to append to DB instance identifiers.
If `null`, the module will generate a random suffix. If empty, no suffix will be appended.
EOT
}
variable "cluster_size" {
type = number
default = 2
description = "Number of DB instances to create in the cluster"
}
variable "snapshot_identifier" {
type = string
default = null
description = "Specifies whether or not to create this cluster from a snapshot"
}
variable "db_name" {
type = string
default = ""
description = "Database name (default is not to create a database)"
}
variable "db_port" {
type = number
default = 3306
description = "Database port"
}
variable "manage_admin_user_password" {
type = bool
default = false
nullable = false
description = "Set to true to allow RDS to manage the master user password in Secrets Manager. Cannot be set if master_password is provided"
}
variable "admin_user_secret_kms_key_id" {
type = string
default = null
description = <<-EOT
Amazon Web Services KMS key identifier is the key ARN, key ID, alias ARN, or alias name for the KMS key.
To use a KMS key in a different Amazon Web Services account, specify the key ARN or alias ARN.
If not specified, the default KMS key for your Amazon Web Services account is used.
EOT
}
variable "admin_user" {
type = string
default = "admin"
description = "Username for the master DB user. Ignored if snapshot_identifier or replication_source_identifier is provided"
}
variable "admin_password" {
type = string
default = ""
description = "Password for the master DB user. Ignored if snapshot_identifier or replication_source_identifier is provided"
}
variable "retention_period" {
type = number
default = 5
description = "Number of days to retain backups for"
}
variable "backup_window" {
type = string
default = "07:00-09:00"
description = "Daily time range during which the backups happen"
}
variable "maintenance_window" {
type = string
default = "wed:03:00-wed:04:00"
description = "Weekly time range during which system maintenance can occur, in UTC"
}
variable "cluster_parameters" {
type = list(object({
apply_method = string
name = string
value = string
}))
default = []
description = "List of DB cluster parameters to apply"
}
variable "rds_cluster_parameter_group_name" {
type = string
default = ""
description = <<-EOT
The name to give to the created `aws_rds_cluster_parameter_group` resource.
If omitted, the module will generate a name.
EOT
}
variable "instance_parameters" {
type = list(object({
apply_method = string
name = string
value = string
}))
default = []
description = "List of DB instance parameters to apply"
}
variable "db_parameter_group_name" {
type = string
default = ""
description = <<-EOT
The name to give to the created `aws_db_parameter_group` resource.
If omitted, the module will generate a name.
EOT
}
variable "db_cluster_instance_class" {
type = string
default = null
description = "This setting is required to create a provisioned Multi-AZ DB cluster"
}
variable "cluster_family" {
type = string
default = "aurora5.6"
description = "The family of the DB cluster parameter group"
}
variable "engine" {
type = string
default = "aurora"
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
default = "provisioned"
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 "allow_major_version_upgrade" {
type = bool
default = false
description = "Enable to allow major engine version upgrades when changing engine versions. Defaults to false."
}
variable "auto_minor_version_upgrade" {
type = bool
default = true
description = "Indicates that minor engine upgrades will be applied automatically to the DB instance during the maintenance window"
}
variable "s3_import" {
type = object({
bucket_name = string
bucket_prefix = string
ingestion_role = string
source_engine = string
source_engine_version = string
})
default = null
description = "Restore from a Percona Xtrabackup in S3. The `bucket_name` is required to be in the same region as the resource."
}
variable "scaling_configuration" {
type = list(object({
auto_pause = bool
max_capacity = number
min_capacity = number
seconds_until_auto_pause = number
timeout_action = string
}))
default = []
description = "List of nested attributes with scaling properties. Only valid when `engine_mode` is set to `serverless`"
}
variable "serverlessv2_scaling_configuration" {
type = object({
min_capacity = number
max_capacity = number
seconds_until_auto_pause = optional(number, null)
})
default = null
description = "serverlessv2 scaling properties"
}
variable "timeouts_configuration" {
type = list(object({
create = string
update = string
delete = string
}))
default = []
description = "List of timeout values per action. Only valid actions are `create`, `update` and `delete`"
}
variable "restore_to_point_in_time" {
type = list(object({
source_cluster_identifier = string
restore_type = optional(string, "copy-on-write")
use_latest_restorable_time = optional(bool, true)
restore_to_time = optional(string, null)
}))
default = []
description = <<-EOT
List of point-in-time recovery options. Valid parameters are:
`source_cluster_identifier`
Identifier of the source database cluster from which to restore.
`restore_type`:
Type of restore to be performed. Valid options are "full-copy" and "copy-on-write".
`use_latest_restorable_time`:
Set to true to restore the database cluster to the latest restorable backup time. Conflicts with `restore_to_time`.
`restore_to_time`:
Date and time in UTC format to restore the database cluster to. Conflicts with `use_latest_restorable_time`.
EOT
}
variable "allowed_cidr_blocks" {
type = list(string)
default = []
description = "List of CIDR blocks allowed to access the cluster"
}
variable "allowed_ipv6_cidr_blocks" {
type = list(string)
default = []
description = "List of IPv6 CIDR blocks allowed to access the cluster"
}
variable "publicly_accessible" {
type = bool
description = "Set to true if you want your cluster to be publicly accessible (such as via QuickSight)"
default = false
}
variable "storage_encrypted" {
type = bool
description = "Specifies whether the DB cluster is encrypted. The default is `false` for `provisioned` `engine_mode` and `true` for `serverless` `engine_mode`"
default = false
}
variable "storage_type" {
type = string
description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), 'io1' (provisioned IOPS SSD), 'aurora', or 'aurora-iopt1'"
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 "kms_key_arn" {
type = string
description = "The ARN for the KMS encryption key. When specifying `kms_key_arn`, `storage_encrypted` needs to be set to `true`"
default = ""
}
variable "skip_final_snapshot" {
type = bool
description = "Determines whether a final DB snapshot is created before the DB cluster is deleted"
default = true
}
variable "copy_tags_to_snapshot" {
type = bool
description = "Copy tags to backup snapshots"
default = false
}
variable "deletion_protection" {
type = bool
description = "If the DB instance should have deletion protection enabled"
default = false
}
variable "apply_immediately" {
type = bool
description = "Specifies whether any cluster modifications are applied immediately, or during the next maintenance window"
default = true
}
variable "iam_database_authentication_enabled" {
type = bool
description = "Specifies whether or mappings of AWS Identity and Access Management (IAM) accounts to database accounts is enabled"
default = false
}
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"
default = 0
}
variable "rds_monitoring_role_arn" {
type = string
description = "The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs"
default = null
}
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"
default = false
}
variable "replication_source_identifier" {
type = string
description = "ARN of a source DB cluster or DB instance if this DB cluster is to be created as a Read Replica"
default = ""
}
variable "enabled_cloudwatch_logs_exports" {
type = list(string)
description = "List of log types to export to cloudwatch. The following log types are supported: audit, error, general, slowquery"
default = []
}
variable "performance_insights_enabled" {
type = bool
default = false
description = "Whether to enable Performance Insights"
}
variable "performance_insights_kms_key_id" {
type = string
default = ""
description = "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"
}
variable "performance_insights_retention_period" {
description = "Amount of time in days to retain Performance Insights data. Either 7 (7 days) or 731 (2 years)"
type = number
default = null
}
variable "database_insights_mode" {
description = "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"
type = string
default = null
}
variable "promotion_tier" {
type = number
default = 0
description = <<-EOT
Failover Priority setting on instance level. The reader who has lower tier has higher priority to get promoted to writer.
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
EOT
}
variable "autoscaling_enabled" {
type = bool
default = false
description = "Whether to enable cluster autoscaling"
}
variable "autoscaling_policy_type" {
type = string
default = "TargetTrackingScaling"
description = "Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported"
}
variable "autoscaling_target_metrics" {
type = string
default = "RDSReaderAverageCPUUtilization"
description = "The metrics type to use. If this value isn't provided the default is CPU utilization"
}
variable "autoscaling_target_value" {
type = number
default = 75
description = "The target value to scale with respect to target metrics"
}
variable "autoscaling_scale_in_cooldown" {
type = number
default = 300
description = "The amount of time, in seconds, after a scaling activity completes and before the next scaling down activity can start. Default is 300s"
}
variable "autoscaling_scale_out_cooldown" {
type = number
default = 300
description = "The amount of time, in seconds, after a scaling activity completes and before the next scaling up activity can start. Default is 300s"
}
variable "autoscaling_min_capacity" {
type = number
default = 1
description = "Minimum number of instances to be maintained by the autoscaler"
}
variable "autoscaling_max_capacity" {
type = number
default = 5
description = "Maximum number of instances to be maintained by the autoscaler"
}
variable "instance_availability_zone" {
type = string
default = ""
description = "Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly"
}
variable "cluster_dns_name" {
type = string
description = "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`"
default = ""
}
variable "reader_dns_name" {
type = string
description = "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`"
default = ""
}
variable "cluster_type" {
type = string
description = <<-EOT
Either `regional` or `global`.
If `regional` will be created as a normal, standalone DB.
If `global`, will be made part of a Global cluster (requires `global_cluster_identifier`).
EOT
default = "regional"
validation {
condition = contains(["regional", "global"], var.cluster_type)
error_message = "Allowed values: `regional` (standalone), `global` (part of global cluster)."
}
}
variable "global_cluster_identifier" {
type = string
description = "ID of the Aurora global cluster"
default = ""
}
variable "source_region" {
type = string
description = "Source Region of primary cluster, needed when using encrypted storage and region replicas"
default = ""
}
variable "iam_roles" {
type = list(string)
description = "Iam roles for the Aurora cluster"
default = []
}
variable "backtrack_window" {
type = number
description = "The target backtrack window, in seconds. Only available for aurora engine currently. Must be between 0 and 259200 (72 hours)"
default = 0
}
variable "enable_http_endpoint" {
type = bool
description = "Enable HTTP endpoint (data API)."
default = false
}
variable "vpc_security_group_ids" {
type = list(string)
description = "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"
default = []
}
variable "ca_cert_identifier" {
description = "The identifier of the CA certificate for the DB instance"
type = string
default = null
}
variable "egress_enabled" {
description = "Whether or not to apply the egress security group rule to default security group, defaults to `true`"
type = bool
default = true
}
variable "enhanced_monitoring_attributes" {
description = "The attributes for the enhanced monitoring IAM role"
type = list(string)
default = ["enhanced-monitoring"]
}
variable "subnet_group_name" {
description = "Database subnet group name. Will use generated label ID if not supplied."
type = string
default = ""
}
variable "intra_security_group_traffic_enabled" {
type = bool
default = false
description = "Whether to allow traffic between resources inside the database's security group."
}
variable "activity_stream_enabled" {
type = bool
default = false
description = "Whether to enable Activity Streams"
}
variable "activity_stream_mode" {
type = string
default = "async"
description = "The mode for the Activity Streams. `async` and `sync` are supported. Defaults to `async`"
}
variable "activity_stream_kms_key_id" {
type = string
default = ""
description = "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"
}
variable "parameter_group_name_prefix_enabled" {
type = bool
default = true
description = "Set to `true` to use `name_prefix` to name the cluster and database parameter groups. Set to `false` to use `name` instead"
}
variable "enable_global_write_forwarding" {
type = bool
default = null
description = "Set to `true`, to forward writes to an associated global cluster."
}
variable "enable_local_write_forwarding" {
type = bool
default = null
description = "Set to `true`, to forward writes sent to a reader to the writer instance."
}
variable "network_type" {
type = string
default = "IPV4"
description = "The network type of the cluster. Valid values: IPV4, DUAL."
}
variable "use_reserved_instances" {
type = bool
default = false
description = <<-EOT
WARNING: Observe your plans and applies carefully when using this feature.
It has potential to be very expensive if not used correctly.
Also, it is not clear what happens when the reservation expires.
Whether to use reserved instances.
EOT
}
variable "rds_ri_offering_type" {
type = string
default = ""
description = "Offering type of reserved DB instances. Valid values are 'No Upfront', 'Partial Upfront', 'All Upfront'."
}
variable "rds_ri_duration" {
type = number
default = 1
description = "The number of years to reserve the instance. Values can be 1 or 3 (or in seconds, 31536000 or 94608000)"
}
variable "rds_ri_reservation_id" {
type = string
default = null
description = "Customer-specified identifier to track the reservation of the reserved DB instance."
}
================================================
FILE: versions.tf
================================================
terraform {
required_version = ">= 1.0.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.81.0"
}
null = {
source = "hashicorp/null"
version = ">= 2.0"
}
random = {
source = "hashicorp/random"
version = ">= 2.0"
}
}
}