From aba0235e0afaa863662d0805a6e4c758a17e9ce7 Mon Sep 17 00:00:00 2001 From: aknysh Date: Thu, 4 Mar 2021 22:56:47 -0500 Subject: [PATCH 01/19] Init --- .github/mergify.yml | 7 + .github/workflows/auto-format.yml | 4 +- .github/workflows/auto-release.yml | 4 +- LICENSE | 2 +- README.md | 459 ++++++++++++++- README.yaml | 80 +++ context.tf | 202 +++++++ docs/targets.md | 12 + docs/terraform.md | 140 +++++ examples/complete/context.tf | 202 +++++++ examples/complete/fixtures.us-east-2.tfvars | 42 ++ examples/complete/main.tf | 81 +++ examples/complete/outputs.tf | 51 ++ examples/complete/variables.tf | 96 +++ examples/complete/versions.tf | 14 + main.tf | 2 + outputs.tf | 0 test/.gitignore | 1 + test/Makefile | 43 ++ test/Makefile.alpine | 5 + test/src/.gitignore | 2 + test/src/Makefile | 30 + test/src/examples_complete_test.go | 73 +++ test/src/go.mod | 8 + test/src/go.sum | 615 ++++++++++++++++++++ variables.tf | 5 + versions.tf | 14 + 27 files changed, 2188 insertions(+), 6 deletions(-) create mode 100644 README.yaml create mode 100644 context.tf create mode 100644 docs/targets.md create mode 100644 docs/terraform.md create mode 100644 examples/complete/context.tf create mode 100644 examples/complete/fixtures.us-east-2.tfvars create mode 100644 examples/complete/main.tf create mode 100644 examples/complete/outputs.tf create mode 100644 examples/complete/variables.tf create mode 100644 examples/complete/versions.tf create mode 100644 main.tf create mode 100644 outputs.tf create mode 100644 test/.gitignore create mode 100644 test/Makefile create mode 100644 test/Makefile.alpine create mode 100644 test/src/.gitignore create mode 100644 test/src/Makefile create mode 100644 test/src/examples_complete_test.go create mode 100644 test/src/go.mod create mode 100644 test/src/go.sum create mode 100644 variables.tf create mode 100644 versions.tf diff --git a/.github/mergify.yml b/.github/mergify.yml index b010656..ef15545 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -56,3 +56,10 @@ pull_request_rules: changes_requested: true approved: true message: "This Pull Request has been updated, so we're dismissing all reviews." + +- name: "close Pull Requests without files changed" + conditions: + - "#files=0" + actions: + close: + message: "This pull request has been automatically closed by Mergify because there are no longer any changes." diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 990abed..375d0fd 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -6,7 +6,7 @@ on: jobs: auto-format: runs-on: ubuntu-latest - container: cloudposse/build-harness:slim-latest + container: cloudposse/build-harness:latest steps: # Checkout the pull request branch # "An action in a workflow run can’t trigger a new workflow run. For example, if an action pushes code using @@ -29,6 +29,8 @@ jobs: - name: Auto Format if: github.event.pull_request.state == 'open' shell: bash + env: + GITHUB_TOKEN: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" run: make BUILD_HARNESS_PATH=/build-harness PACKAGES_PREFER_HOST=true -f /build-harness/templates/Makefile.build-harness pr/auto-format/host # Commit changes (if any) to the PR branch diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index c766b1f..3db508e 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -3,13 +3,13 @@ name: auto-release on: push: branches: - - master + - main jobs: publish: runs-on: ubuntu-latest steps: - # Get PR from merged commit to master + # Get PR from merged commit to main - uses: actions-ecosystem/action-get-merged-pull-request@v1 id: get-merged-pull-request with: diff --git a/LICENSE b/LICENSE index 79e5f89..c9f3176 100644 --- a/LICENSE +++ b/LICENSE @@ -178,7 +178,7 @@ 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 "[]" + 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 diff --git a/README.md b/README.md index 960686d..139ba31 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,459 @@ -# terraform-aws-rds-db-proxy + +# terraform-aws-rds-db-proxy [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-rds-db-proxy.svg)](https://github.com/cloudposse/terraform-aws-rds-db-proxy/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) + -Terraform module to provision an Amazon RDS Proxy. +[![README Header][readme_header_img]][readme_header_link] +[![Cloud Posse][logo]](https://cpco.io/homepage) + + + +Terraform module to provision an Amazon [RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) for MySQL or Postgres. + + +--- + +This project is part of our comprehensive ["SweetOps"](https://cpco.io/sweetops) approach towards DevOps. +[][share_email] +[][share_googleplus] +[][share_facebook] +[][share_reddit] +[][share_linkedin] +[][share_twitter] + + +[![Terraform Open Source Modules](https://docs.cloudposse.com/images/terraform-open-source-modules.svg)][terraform_modules] + + + +It's 100% Open Source and licensed under the [APACHE2](LICENSE). + + + + + + + +We literally have [*hundreds of terraform modules*][terraform_modules] that are Open Source and well-maintained. Check them out! + + + + + + + +## Security & Compliance [](https://bridgecrew.io/) + +Security scanning is graciously provided by Bridgecrew. Bridgecrew is the leading fully hosted, cloud-native solution providing continuous Terraform security and compliance. + +| Benchmark | Description | +|--------|---------------| +| [![Infrastructure Security](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/general)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=INFRASTRUCTURE+SECURITY) | Infrastructure Security Compliance | +| [![CIS KUBERNETES](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/cis_kubernetes)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=CIS+KUBERNETES+V1.5) | Center for Internet Security, KUBERNETES Compliance | +| [![CIS AWS](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/cis_aws)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=CIS+AWS+V1.2) | Center for Internet Security, AWS Compliance | +| [![CIS AZURE](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/cis_azure)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=CIS+AZURE+V1.1) | Center for Internet Security, AZURE Compliance | +| [![PCI-DSS](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/pci)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=PCI-DSS+V3.2) | Payment Card Industry Data Security Standards Compliance | +| [![NIST-800-53](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/nist)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=NIST-800-53) | National Institute of Standards and Technology Compliance | +| [![ISO27001](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/iso)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=ISO27001) | Information Security Management System, ISO/IEC 27001 Compliance | +| [![SOC2](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/soc2)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=SOC2)| Service Organization Control 2 Compliance | +| [![CIS GCP](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/cis_gcp)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=CIS+GCP+V1.1) | Center for Internet Security, GCP Compliance | +| [![HIPAA](https://www.bridgecrew.cloud/badges/github/cloudposse/terraform-aws-rds-db-proxy/hipaa)](https://www.bridgecrew.cloud/link/badge?vcs=github&fullRepo=cloudposse%2Fterraform-aws-rds-db-proxy&benchmark=HIPAA) | Health Insurance Portability and Accountability Compliance | + + + +## Usage + + +**IMPORTANT:** We do not pin modules to versions in our examples because of the +difficulty of keeping the versions in the documentation in sync with the latest released versions. +We highly recommend that in your code you pin the version to the exact version you are +using so that your infrastructure remains stable, and update versions in a +systematic way so that they do not catch you by surprise. + +Also, because of a bug in the Terraform registry ([hashicorp/terraform#21417](https://github.com/hashicorp/terraform/issues/21417)), +the registry shows many of our inputs as required when in fact they are optional. +The table below correctly indicates which inputs are required. + + + +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). + +```hcl +``` + + + + +## Examples + +Review the [complete example](examples/complete) to see how to use this module. + + + + +## Makefile Targets +```text +Available targets: + + help Help screen + help/all Display help for all targets + help/short This help short screen + lint Lint terraform code + +``` + + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 0.13.0 | +| aws | >= 3.1.15 | +| null | >= 2.0 | + +## Providers + +| Name | Version | +|------|---------| +| aws | >= 3.1.15 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| dns_master | cloudposse/route53-cluster-hostname/aws | 0.12.0 | +| dns_replicas | cloudposse/route53-cluster-hostname/aws | 0.12.0 | +| enhanced_monitoring_label | cloudposse/label/null | 0.24.1 | +| this | cloudposse/label/null | 0.24.1 | + +## Resources + +| Name | +|------| +| [aws_appautoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | +| [aws_appautoscaling_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | +| [aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | +| [aws_db_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | +| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | +| [aws_rds_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | +| [aws_rds_cluster_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | +| [aws_rds_cluster_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | +| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | +| [aws_security_group_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | +| admin\_password | (Required unless a snapshot\_identifier is provided) Password for the master DB user | `string` | `""` | no | +| admin\_user | (Required unless a snapshot\_identifier is provided) Username for the master DB user | `string` | `"admin"` | no | +| allowed\_cidr\_blocks | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no | +| apply\_immediately | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no | +| attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | +| 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 | Whether to enable cluster autoscaling | `bool` | `false` | no | +| autoscaling\_max\_capacity | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no | +| autoscaling\_min\_capacity | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no | +| autoscaling\_policy\_type | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no | +| 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 | 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 | The metrics type to use. If this value isn't provided the default is CPU utilization | `string` | `"RDSReaderAverageCPUUtilization"` | no | +| autoscaling\_target\_value | The target value to scale with respect to target metrics | `number` | `75` | no | +| 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 | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no | +| 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 | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no | +| cluster\_identifier | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no | +| cluster\_parameters | List of DB cluster parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | +| cluster\_size | Number of DB instances to create in the cluster | `number` | `2` | no | +| 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 | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| copy\_tags\_to\_snapshot | Copy tags to backup snapshots | `bool` | `false` | no | +| db\_name | Database name (default is not to create a database) | `string` | `""` | no | +| db\_port | Database port | `number` | `3306` | no | +| deletion\_protection | If the DB instance should have deletion protection enabled | `bool` | `false` | no | +| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| enable\_http\_endpoint | Enable HTTP endpoint (data API). Only valid when engine\_mode is set to serverless | `bool` | `false` | no | +| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| 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 | 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 | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no | +| engine\_version | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no | +| 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 | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| global\_cluster\_identifier | ID of the Aurora global cluster | `string` | `""` | no | +| 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 | Iam roles for the Aurora cluster | `list(string)` | `[]` | no | +| id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| instance\_availability\_zone | Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly | `string` | `""` | no | +| instance\_parameters | List of DB instance parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | +| instance\_type | Instance type to use | `string` | `"db.t2.small"` | no | +| 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 | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | +| maintenance\_window | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | +| performance\_insights\_enabled | Whether to enable Performance Insights | `bool` | `false` | no | +| 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 | +| publicly\_accessible | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no | +| 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 | The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no | +| 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 | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
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 | 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 | List point-in-time recovery options. Only valid actions are `source_cluster_identifier`, `restore_type` and `use_latest_restorable_time` |
list(object({
source_cluster_identifier = string
restore_type = string
use_latest_restorable_time = bool
}))
| `[]` | no | +| retention\_period | Number of days to retain backups for | `number` | `5` | no | +| 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 | 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 | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no | +| skip\_final\_snapshot | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no | +| snapshot\_identifier | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no | +| source\_region | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| 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 | +| subnets | List of VPC subnet IDs | `list(string)` | n/a | yes | +| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| 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 | +| vpc\_id | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes | +| 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 | Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| arn | Amazon Resource Name (ARN) of the cluster | +| cluster\_identifier | Cluster Identifier | +| cluster\_resource\_id | The region-unique, immutable identifie of the cluster | +| cluster\_security\_groups | Default RDS cluster security groups | +| database\_name | Database name | +| dbi\_resource\_ids | List of the region-unique, immutable identifiers for the DB instances in the cluster | +| endpoint | The DNS address of the RDS instance | +| master\_host | DB Master hostname | +| master\_username | Username for the master DB user | +| reader\_endpoint | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas | +| replicas\_host | Replicas hostname | +| security\_group\_arn | Security Group ARN | +| security\_group\_id | Security Group ID | +| security\_group\_name | Security Group name | + + + + +## Share the Love + +Like this project? Please give it a ★ on [our GitHub](https://github.com/cloudposse/terraform-aws-rds-db-proxy)! (it helps us **a lot**) + +Are you using this project or any of our other projects? Consider [leaving a testimonial][testimonial]. =) + + +## Related Projects + +Check out these related projects. + +- [terraform-aws-rds-cluster](https://github.com/cloudposse/terraform-aws-rds-cluster) - Terraform module to provision an RDS Aurora cluster for MySQL or Postgres. +- [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. +- [terraform-aws-rds-replica](https://github.com/cloudposse/terraform-aws-rds-replica) - Terraform module to provision AWS RDS replica instances. These are best suited for reporting purposes. +- [terraform-aws-backup](https://github.com/cloudposse/terraform-aws-backup) - Terraform module to provision AWS Backup, a fully managed backup service that makes it easy to centralize and automate the back up of data across AWS services such as Amazon EBS volumes, Amazon EC2 instances, Amazon RDS databases, Amazon DynamoDB tables, Amazon EFS file systems, and AWS Storage Gateway volumes. + + + +## Help + +**Got a question?** We got answers. + +File a GitHub [issue](https://github.com/cloudposse/terraform-aws-rds-db-proxy/issues), send us an [email][email] or join our [Slack Community][slack]. + +[![README Commercial Support][readme_commercial_support_img]][readme_commercial_support_link] + +## DevOps Accelerator for Startups + + +We are a [**DevOps Accelerator**][commercial_support]. We'll help you build your cloud infrastructure from the ground up so you can own it. Then we'll show you how to operate it and stick around for as long as you need us. + +[![Learn More](https://img.shields.io/badge/learn%20more-success.svg?style=for-the-badge)][commercial_support] + +Work directly with our team of DevOps experts via email, slack, and video conferencing. + +We deliver 10x the value for a fraction of the cost of a full-time engineer. Our track record is not even funny. If you want things done right and you need it done FAST, then we're your best bet. + +- **Reference Architecture.** You'll get everything you need from the ground up built using 100% infrastructure as code. +- **Release Engineering.** You'll have end-to-end CI/CD with unlimited staging environments. +- **Site Reliability Engineering.** You'll have total visibility into your apps and microservices. +- **Security Baseline.** You'll have built-in governance with accountability and audit logs for all changes. +- **GitOps.** You'll be able to operate your infrastructure via Pull Requests. +- **Training.** You'll receive hands-on training so your team can operate what we build. +- **Questions.** You'll have a direct line of communication between our teams via a Shared Slack channel. +- **Troubleshooting.** You'll get help to triage when things aren't working. +- **Code Reviews.** You'll receive constructive feedback on Pull Requests. +- **Bug Fixes.** We'll rapidly work with you to fix any bugs in our projects. + +## Slack Community + +Join our [Open Source Community][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. + +## Discourse Forums + +Participate in our [Discourse Forums][discourse]. Here you'll find answers to commonly asked questions. Most questions will be related to the enormous number of projects we support on our GitHub. Come here to collaborate on answers, find solutions, and get ideas about the products and services we value. It only takes a minute to get started! Just sign in with SSO using your GitHub account. + +## Newsletter + +Sign up for [our newsletter][newsletter] that covers everything on our technology radar. Receive updates on what we're up to on GitHub as well as awesome new projects we discover. + +## Office Hours + +[Join us every Wednesday via Zoom][office_hours] for our weekly "Lunch & Learn" sessions. It's **FREE** for everyone! + +[![zoom](https://img.cloudposse.com/fit-in/200x200/https://cloudposse.com/wp-content/uploads/2019/08/Powered-by-Zoom.png")][office_hours] + +## Contributing + +### Bug Reports & Feature Requests + +Please use the [issue tracker](https://github.com/cloudposse/terraform-aws-rds-db-proxy/issues) to report any bugs or file feature requests. + +### Developing + +If you are interested in being a contributor and want to get involved in developing this project or [help out](https://cpco.io/help-out) with our other projects, we would love to hear from you! Shoot us an [email][email]. + +In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. + + 1. **Fork** the repo on GitHub + 2. **Clone** the project to your own machine + 3. **Commit** changes to your own branch + 4. **Push** your work back up to your fork + 5. 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! + + +## Copyright + +Copyright © 2017-2021 [Cloud Posse, LLC](https://cpco.io/copyright) + + + +## License + +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +See [LICENSE](LICENSE) for full details. + +```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. + +## About + +This project is maintained and funded by [Cloud Posse, LLC][website]. Like it? Please let us know by [leaving a testimonial][testimonial]! + +[![Cloud Posse][logo]][website] + +We're a [DevOps Professional Services][hire] company based in Los Angeles, CA. We ❤️ [Open Source Software][we_love_open_source]. + +We offer [paid support][commercial_support] on all of our projects. + +Check out [our other projects][github], [follow us on twitter][twitter], [apply for a job][jobs], or [hire us][hire] to help with your cloud strategy and implementation. + + + +### Contributors + + +| [![Erik Osterman][osterman_avatar]][osterman_homepage]
[Erik Osterman][osterman_homepage] | [![Andriy Knysh][aknysh_avatar]][aknysh_homepage]
[Andriy Knysh][aknysh_homepage] | +|---|---| + + + [osterman_homepage]: https://github.com/osterman + [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png + [aknysh_homepage]: https://github.com/aknysh + [aknysh_avatar]: https://img.cloudposse.com/150x150/https://github.com/aknysh.png + +[![README Footer][readme_footer_img]][readme_footer_link] +[![Beacon][beacon]][website] + + [logo]: https://cloudposse.com/logo-300x69.svg + [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=docs + [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=website + [github]: https://cpco.io/github?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=github + [jobs]: https://cpco.io/jobs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=jobs + [hire]: https://cpco.io/hire?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=hire + [slack]: https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=slack + [linkedin]: https://cpco.io/linkedin?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=linkedin + [twitter]: https://cpco.io/twitter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=twitter + [testimonial]: https://cpco.io/leave-testimonial?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=testimonial + [office_hours]: https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=office_hours + [newsletter]: https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=newsletter + [discourse]: https://ask.sweetops.com/?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=discourse + [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=email + [commercial_support]: https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=commercial_support + [we_love_open_source]: https://cpco.io/we-love-open-source?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=we_love_open_source + [terraform_modules]: https://cpco.io/terraform-modules?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=terraform_modules + [readme_header_img]: https://cloudposse.com/readme/header/img + [readme_header_link]: https://cloudposse.com/readme/header/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=readme_header_link + [readme_footer_img]: https://cloudposse.com/readme/footer/img + [readme_footer_link]: https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=readme_footer_link + [readme_commercial_support_img]: https://cloudposse.com/readme/commercial-support/img + [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-rds-db-proxy&utm_content=readme_commercial_support_link + [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-aws-rds-db-proxy&url=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-aws-rds-db-proxy&url=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [share_reddit]: https://reddit.com/submit/?url=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [share_facebook]: https://facebook.com/sharer/sharer.php?u=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [share_googleplus]: https://plus.google.com/share?url=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [share_email]: mailto:?subject=terraform-aws-rds-db-proxy&body=https://github.com/cloudposse/terraform-aws-rds-db-proxy + [beacon]: https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-aws-rds-db-proxy?pixel&cs=github&cm=readme&an=terraform-aws-rds-db-proxy diff --git a/README.yaml b/README.yaml new file mode 100644 index 0000000..60af4ae --- /dev/null +++ b/README.yaml @@ -0,0 +1,80 @@ +name: terraform-aws-rds-db-proxy + +tags: + - aws + - terraform + - terraform-modules + - databases + - rds + - rds-database + - proxy + - proxy-pool + - database-proxy + - connection + - connections + - pool + - connection-pool + - aurora + - mysql + - postgres + - cluster + +categories: + - terraform-modules/databases + +license: APACHE2 + +github_repo: cloudposse/terraform-aws-rds-db-proxy + +badges: + - name: Latest Release + image: https://img.shields.io/github/release/cloudposse/terraform-aws-rds-db-proxy.svg + url: https://github.com/cloudposse/terraform-aws-rds-db-proxy/releases/latest + - name: Slack Community + image: https://slack.cloudposse.com/badge.svg + url: https://slack.cloudposse.com + +related: + - name: terraform-aws-rds-cluster + description: Terraform module to provision an RDS Aurora cluster for MySQL or Postgres. + url: https://github.com/cloudposse/terraform-aws-rds-cluster + - 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 + - name: terraform-aws-rds-replica + description: Terraform module to provision AWS RDS replica instances. These are best suited for reporting purposes. + url: https://github.com/cloudposse/terraform-aws-rds-replica + - name: terraform-aws-backup + description: Terraform module to provision AWS Backup, a fully managed backup service that makes it easy to centralize and automate + the back up of data across AWS services such as Amazon EBS volumes, Amazon EC2 instances, Amazon RDS databases, + Amazon DynamoDB tables, Amazon EFS file systems, and AWS Storage Gateway volumes. + url: https://github.com/cloudposse/terraform-aws-backup + +description: |- + Terraform module to provision an Amazon [RDS Proxy](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html) for MySQL or Postgres. + +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). + + ```hcl + ``` + +examples: |- + Review the [complete example](examples/complete) to see how to use this module. + +include: + - docs/targets.md + - docs/terraform.md + +contributors: + - name: Erik Osterman + github: osterman + - name: Andriy Knysh + github: aknysh diff --git a/context.tf b/context.tf new file mode 100644 index 0000000..81f99b4 --- /dev/null +++ b/context.tf @@ -0,0 +1,202 @@ +# +# 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. +# +# 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.24.1" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + 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 + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = 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 + } + 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 = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + 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 default, which is `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 + The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`. + 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 + The letter case of output label values (also used in `tags` and `id`). + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + 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`." + } +} +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/docs/targets.md b/docs/targets.md new file mode 100644 index 0000000..3dce8b3 --- /dev/null +++ b/docs/targets.md @@ -0,0 +1,12 @@ + +## Makefile Targets +```text +Available targets: + + help Help screen + help/all Display help for all targets + help/short This help short screen + lint Lint terraform code + +``` + diff --git a/docs/terraform.md b/docs/terraform.md new file mode 100644 index 0000000..72769b2 --- /dev/null +++ b/docs/terraform.md @@ -0,0 +1,140 @@ + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >= 0.13.0 | +| aws | >= 3.1.15 | +| null | >= 2.0 | + +## Providers + +| Name | Version | +|------|---------| +| aws | >= 3.1.15 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| dns_master | cloudposse/route53-cluster-hostname/aws | 0.12.0 | +| dns_replicas | cloudposse/route53-cluster-hostname/aws | 0.12.0 | +| enhanced_monitoring_label | cloudposse/label/null | 0.24.1 | +| this | cloudposse/label/null | 0.24.1 | + +## Resources + +| Name | +|------| +| [aws_appautoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | +| [aws_appautoscaling_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | +| [aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | +| [aws_db_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | +| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | +| [aws_rds_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | +| [aws_rds_cluster_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | +| [aws_rds_cluster_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | +| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | +| [aws_security_group_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | +| admin\_password | (Required unless a snapshot\_identifier is provided) Password for the master DB user | `string` | `""` | no | +| admin\_user | (Required unless a snapshot\_identifier is provided) Username for the master DB user | `string` | `"admin"` | no | +| allowed\_cidr\_blocks | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no | +| apply\_immediately | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no | +| attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | +| 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 | Whether to enable cluster autoscaling | `bool` | `false` | no | +| autoscaling\_max\_capacity | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no | +| autoscaling\_min\_capacity | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no | +| autoscaling\_policy\_type | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no | +| 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 | 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 | The metrics type to use. If this value isn't provided the default is CPU utilization | `string` | `"RDSReaderAverageCPUUtilization"` | no | +| autoscaling\_target\_value | The target value to scale with respect to target metrics | `number` | `75` | no | +| 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 | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no | +| 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 | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no | +| cluster\_identifier | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no | +| cluster\_parameters | List of DB cluster parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | +| cluster\_size | Number of DB instances to create in the cluster | `number` | `2` | no | +| 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 | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| copy\_tags\_to\_snapshot | Copy tags to backup snapshots | `bool` | `false` | no | +| db\_name | Database name (default is not to create a database) | `string` | `""` | no | +| db\_port | Database port | `number` | `3306` | no | +| deletion\_protection | If the DB instance should have deletion protection enabled | `bool` | `false` | no | +| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| enable\_http\_endpoint | Enable HTTP endpoint (data API). Only valid when engine\_mode is set to serverless | `bool` | `false` | no | +| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| 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 | 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 | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no | +| engine\_version | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no | +| 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 | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| global\_cluster\_identifier | ID of the Aurora global cluster | `string` | `""` | no | +| 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 | Iam roles for the Aurora cluster | `list(string)` | `[]` | no | +| id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| instance\_availability\_zone | Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly | `string` | `""` | no | +| instance\_parameters | List of DB instance parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | +| instance\_type | Instance type to use | `string` | `"db.t2.small"` | no | +| 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 | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | +| maintenance\_window | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no | +| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | +| performance\_insights\_enabled | Whether to enable Performance Insights | `bool` | `false` | no | +| 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 | +| publicly\_accessible | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no | +| 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 | The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no | +| 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 | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
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 | 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 | List point-in-time recovery options. Only valid actions are `source_cluster_identifier`, `restore_type` and `use_latest_restorable_time` |
list(object({
source_cluster_identifier = string
restore_type = string
use_latest_restorable_time = bool
}))
| `[]` | no | +| retention\_period | Number of days to retain backups for | `number` | `5` | no | +| 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 | 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 | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no | +| skip\_final\_snapshot | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no | +| snapshot\_identifier | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no | +| source\_region | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no | +| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| 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 | +| subnets | List of VPC subnet IDs | `list(string)` | n/a | yes | +| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| 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 | +| vpc\_id | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes | +| 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 | Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas | `string` | `""` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| arn | Amazon Resource Name (ARN) of the cluster | +| cluster\_identifier | Cluster Identifier | +| cluster\_resource\_id | The region-unique, immutable identifie of the cluster | +| cluster\_security\_groups | Default RDS cluster security groups | +| database\_name | Database name | +| dbi\_resource\_ids | List of the region-unique, immutable identifiers for the DB instances in the cluster | +| endpoint | The DNS address of the RDS instance | +| master\_host | DB Master hostname | +| master\_username | Username for the master DB user | +| reader\_endpoint | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas | +| replicas\_host | Replicas hostname | +| security\_group\_arn | Security Group ARN | +| security\_group\_id | Security Group ID | +| security\_group\_name | Security Group name | + diff --git a/examples/complete/context.tf b/examples/complete/context.tf new file mode 100644 index 0000000..81f99b4 --- /dev/null +++ b/examples/complete/context.tf @@ -0,0 +1,202 @@ +# +# 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. +# +# 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.24.1" # requires Terraform >= 0.13.0 + + enabled = var.enabled + namespace = var.namespace + 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 + + context = var.context +} + +# Copy contents of cloudposse/terraform-null-label/variables.tf here + +variable "context" { + type = any + default = { + enabled = true + namespace = 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 + } + 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 = "Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp'" +} + +variable "environment" { + type = string + default = null + description = "Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT'" +} + +variable "stage" { + type = string + default = null + description = "Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release'" +} + +variable "name" { + type = string + default = null + description = "Solution name, e.g. 'app' or 'jenkins'" +} + +variable "delimiter" { + type = string + default = null + description = <<-EOT + Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`. + Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. + EOT +} + +variable "attributes" { + type = list(string) + default = [] + description = "Additional attributes (e.g. `1`)" +} + +variable "tags" { + type = map(string) + default = {} + description = "Additional tags (e.g. `map('BusinessUnit','XYZ')`" +} + +variable "additional_tag_map" { + type = map(string) + default = {} + description = "Additional tags for appending to tags_as_list_of_maps. Not added to `tags`." +} + +variable "label_order" { + type = list(string) + default = null + description = <<-EOT + The naming order of the id output and Name tag. + Defaults to ["namespace", "environment", "stage", "name", "attributes"]. + You can omit any of the 5 elements, but at least one must be present. + EOT +} + +variable "regex_replace_chars" { + type = string + default = null + description = <<-EOT + Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`. + 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 default, which is `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 + The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`. + 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 + The letter case of output label values (also used in `tags` and `id`). + Possible values: `lower`, `title`, `upper` and `none` (no transformation). + 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`." + } +} +#### End of copy of cloudposse/terraform-null-label/variables.tf diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars new file mode 100644 index 0000000..e8e4554 --- /dev/null +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -0,0 +1,42 @@ +region = "us-east-2" + +availability_zones = ["us-east-2a", "us-east-2b"] + +namespace = "eg" + +stage = "test" + +name = "rds-proxy" + +deletion_protection = false + +database_name = "test_db" + +database_user = "admin_user" + +database_port = 5432 + +multi_az = false + +storage_type = "standard" + +storage_encrypted = false + +allocated_storage = 5 + +publicly_accessible = false + +apply_immediately = true + +# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html +# https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_WorkingWithParamGroups.html +# aws rds describe-db-engine-versions --engine postgres --region=us-east-1 +# aws rds describe-db-engine-versions --query "DBEngineVersions[].DBParameterGroupFamily" --engine postgres --region=us-east-1 +engine = "postgres" + +engine_version = "11.10" + +db_parameter_group = "postgres11" + +# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html +instance_class = "db.t2.small" diff --git a/examples/complete/main.tf b/examples/complete/main.tf new file mode 100644 index 0000000..6fbf4e2 --- /dev/null +++ b/examples/complete/main.tf @@ -0,0 +1,81 @@ +provider "aws" { + region = var.region +} + +module "vpc" { + source = "cloudposse/vpc/aws" + version = "0.21.1" + + cidr_block = "172.16.0.0/16" + + context = module.this.context +} + +module "subnets" { + source = "cloudposse/dynamic-subnets/aws" + version = "0.38.0" + + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = false + nat_instance_enabled = false + + context = module.this.context +} + +resource "random_password" "admin_password" { + count = var.database_password == "" || var.database_password == null ? 1 : 0 + length = 33 + # Leave special characters out to avoid quoting and other issues. + # Special characters have no additional security compared to increasing length. + special = false + override_special = "!#$%^&*()<>-_" +} + +locals { + database_password = var.database_password != "" && var.database_password != null ? var.database_password : join("", random_password.admin_password.*.result) + + username_password = { + username = var.database_user + password = local.database_password + } +} + +module "rds_instance" { + source = "cloudposse/rds/aws" + version = "0.34.0" + + database_name = var.database_name + database_user = var.database_user + database_password = local.database_password + database_port = var.database_port + multi_az = var.multi_az + storage_type = var.storage_type + allocated_storage = var.allocated_storage + storage_encrypted = var.storage_encrypted + engine = var.engine + engine_version = var.engine_version + instance_class = var.instance_class + db_parameter_group = var.db_parameter_group + publicly_accessible = var.publicly_accessible + vpc_id = module.vpc.vpc_id + subnet_ids = module.subnets.private_subnet_ids + security_group_ids = [module.vpc.vpc_default_security_group_id] + apply_immediately = var.apply_immediately + + context = module.this.context +} + +resource "aws_secretsmanager_secret" "rds_username_and_password" { + name = module.this.id + description = "RDS username and password" + recovery_window_in_days = 0 + tags = module.this.tags +} + +resource "aws_secretsmanager_secret_version" "rds_username_and_password" { + secret_id = aws_secretsmanager_secret.rds_username_and_password.id + secret_string = jsonencode(local.username_password) +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf new file mode 100644 index 0000000..989b967 --- /dev/null +++ b/examples/complete/outputs.tf @@ -0,0 +1,51 @@ +output "instance_id" { + value = module.rds_instance.instance_id + description = "ID of the instance" +} + +output "instance_address" { + value = module.rds_instance.instance_address + description = "Address of the instance" +} + +output "instance_endpoint" { + value = module.rds_instance.instance_endpoint + description = "DNS Endpoint of the instance" +} + +output "subnet_group_id" { + value = module.rds_instance.subnet_group_id + description = "ID of the Subnet Group" +} + +output "security_group_id" { + value = module.rds_instance.security_group_id + description = "ID of the Security Group" +} + +output "parameter_group_id" { + value = module.rds_instance.parameter_group_id + description = "ID of the Parameter Group" +} + +output "option_group_id" { + value = module.rds_instance.option_group_id + description = "ID of the Option Group" +} + +output "hostname" { + value = module.rds_instance.hostname + description = "DNS host name of the instance" +} + +output "public_subnet_cidrs" { + value = module.subnets.public_subnet_cidrs +} + +output "private_subnet_cidrs" { + value = module.subnets.private_subnet_cidrs +} + +output "vpc_cidr" { + value = module.vpc.vpc_cidr_block +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf new file mode 100644 index 0000000..7ac5604 --- /dev/null +++ b/examples/complete/variables.tf @@ -0,0 +1,96 @@ +variable "region" { + type = string + description = "AWS region" +} + +variable "availability_zones" { + type = list(string) +} + +variable "database_name" { + type = string + description = "The name of the database to create when the DB instance is created" +} + +variable "database_user" { + type = string + description = "Username for the master DB user" +} + +variable "database_password" { + type = string + description = "Password for the master DB user" + default = "" +} + +variable "database_port" { + type = number + description = "Database port (_e.g._ `3306` for `MySQL`). Used in the DB Security Group to allow access to the DB instance from the provided `security_group_ids`" +} + +variable "deletion_protection" { + type = bool + description = "Set to true to enable deletion protection on the RDS instance" +} + +variable "multi_az" { + type = bool + description = "Set to true if multi AZ deployment must be supported" +} + +variable "storage_type" { + type = string + description = "One of 'standard' (magnetic), 'gp2' (general purpose SSD), or 'io1' (provisioned IOPS SSD)" +} + +variable "storage_encrypted" { + type = bool + description = "(Optional) Specifies whether the DB instance is encrypted. The default is false if not specified" +} + +variable "allocated_storage" { + type = number + description = "The allocated storage in GB" +} + +variable "engine" { + type = string + description = "Database engine type" + # - mysql + # - postgres + # - oracle-* + # - sqlserver-* +} + +variable "engine_version" { + type = string + description = "Database engine version, depends on engine type" +} + +variable "major_engine_version" { + type = string + description = "Database MAJOR engine version, depends on engine type" +} + +variable "instance_class" { + type = string + description = "Class of RDS instance" + # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html +} + +variable "db_parameter_group" { + type = string + description = "Parameter group, depends on DB engine used" + # "mysql5.6" + # "postgres9.5" +} + +variable "publicly_accessible" { + type = bool + description = "Determines if database can be publicly available (NOT recommended)" +} + +variable "apply_immediately" { + type = bool + description = "Specifies whether any database modifications are applied immediately, or during the next maintenance window" +} diff --git a/examples/complete/versions.tf b/examples/complete/versions.tf new file mode 100644 index 0000000..971ae24 --- /dev/null +++ b/examples/complete/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 0.13.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 2.0" + } + null = { + source = "hashicorp/null" + version = ">= 2.0" + } + } +} diff --git a/main.tf b/main.tf new file mode 100644 index 0000000..54a975c --- /dev/null +++ b/main.tf @@ -0,0 +1,2 @@ +locals { +} diff --git a/outputs.tf b/outputs.tf new file mode 100644 index 0000000..e69de29 diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..442804a --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.test-harness diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..17b2fe7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,43 @@ +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 get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions +module: deps + $(call RUN_TESTS, ../) + +## Run tests against example +examples/complete: export TESTS ?= installed lint get-modules get-plugins validate +examples/complete: deps + $(call RUN_TESTS, ../$@) diff --git a/test/Makefile.alpine b/test/Makefile.alpine new file mode 100644 index 0000000..7925b18 --- /dev/null +++ b/test/Makefile.alpine @@ -0,0 +1,5 @@ +ifneq (,$(wildcard /sbin/apk)) +## Install all dependencies for alpine +deps:: init + @apk add --update terraform-docs@cloudposse json2hcl@cloudposse +endif diff --git a/test/src/.gitignore b/test/src/.gitignore new file mode 100644 index 0000000..31b0219 --- /dev/null +++ b/test/src/.gitignore @@ -0,0 +1,2 @@ +.gopath +vendor/ diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 0000000..2707cd2 --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,30 @@ +export TF_CLI_ARGS_init ?= -get-plugins=true +export TERRAFORM_VERSION ?= $(shell curl -s https://checkpoint-api.hashicorp.com/v1/check/terraform | jq -r -M '.current_version' | cut -d. -f1-2) + +.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 + go test -v -timeout 60m -run TestExamplesComplete + +## 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 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* diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go new file mode 100644 index 0000000..75ba771 --- /dev/null +++ b/test/src/examples_complete_test.go @@ -0,0 +1,73 @@ +package test + +import ( + "math/rand" + "strconv" + "testing" + "time" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +// Test the Terraform module in examples/complete using Terratest. +func TestExamplesComplete(t *testing.T) { + t.Parallel() + + rand.Seed(time.Now().UnixNano()) + + randId := strconv.Itoa(rand.Intn(100000)) + attributes := []string{randId} + + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/complete", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.us-east-2.tfvars"}, + Vars: map[string]interface{}{ + "attributes": attributes, + }, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // 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 + instanceId := terraform.Output(t, terraformOptions, "instance_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-rds-proxy-"+randId, instanceId) + + // Run `terraform output` to get the value of an output variable + optionGroupId := terraform.Output(t, terraformOptions, "option_group_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-rds-proxy-"+randId, optionGroupId) + + // Run `terraform output` to get the value of an output variable + parameterGroupId := terraform.Output(t, terraformOptions, "parameter_group_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-rds-proxy"+randId, parameterGroupId) + + // Run `terraform output` to get the value of an output variable + subnetGroupId := terraform.Output(t, terraformOptions, "subnet_group_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-rds-proxy"+randId, subnetGroupId) +} diff --git a/test/src/go.mod b/test/src/go.mod new file mode 100644 index 0000000..37777f2 --- /dev/null +++ b/test/src/go.mod @@ -0,0 +1,8 @@ +module github.com/cloudposse/terraform-aws-rds + +go 1.15 + +require ( + github.com/gruntwork-io/terratest v0.32.8 + github.com/stretchr/testify v1.7.0 +) diff --git a/test/src/go.sum b/test/src/go.sum new file mode 100644 index 0000000..fe66908 --- /dev/null +++ b/test/src/go.sum @@ -0,0 +1,615 @@ +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.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v46.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= +github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= +github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.5/go.mod h1:foo3aIXRQ90zFve3r0QiDsrjGDUwWhKl0ZOQy1CT14k= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.1/go.mod h1:ea90/jvmnAwDrSooLH4sRIehEPtG/EPUXavDh31MnA4= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= +github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +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/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= +github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= +github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= +github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= +github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +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/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/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +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/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +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/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= +github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +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/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/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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.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/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/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 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= +github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= +github.com/gruntwork-io/terratest v0.32.8 h1:ccIRFH+e6zhSB5difg7baJec4FeOZNXpeIFlZZlKW2M= +github.com/gruntwork-io/terratest v0.32.8/go.mod h1:FckR+7ks472IJfSKUPfPvnJfSxV1LKGWGMJ9m/LHegE= +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-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +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/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY= +github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +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.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= +github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +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.2/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/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +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/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= +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.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +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.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= +github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/zclconf/go-cty v1.2.0 h1:sPHsy7ADcIZQP3vILvTjrh74ZA175TFP5vqiNK1UmlI= +github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +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.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +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-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +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-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +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-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +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/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/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-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/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-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +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/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/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/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-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/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-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/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 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +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/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190206041539-40960b6deb8e/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-20190614205625-5aca471b1d59/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-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +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-20190920225731-5eefd052ad72/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-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/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-20200113040837-eac381796e91/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= +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.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +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/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-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +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.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +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/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= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +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-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +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= +k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= +k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= +k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= +k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= +k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= +k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= +k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= +k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= +k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= +k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls= +k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= +k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= +k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= +k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= +sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/variables.tf b/variables.tf new file mode 100644 index 0000000..a40b89d --- /dev/null +++ b/variables.tf @@ -0,0 +1,5 @@ +variable "zone_id" { + type = string + default = "" + description = "Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas" +} diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..7fe4e99 --- /dev/null +++ b/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 0.13.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 3.1.15" + } + null = { + source = "hashicorp/null" + version = ">= 2.0" + } + } +} From 578b8a510eef190707d6dd7dabc647f34a34fec5 Mon Sep 17 00:00:00 2001 From: aknysh Date: Fri, 5 Mar 2021 20:55:44 -0500 Subject: [PATCH 02/19] Init --- README.md | 119 +++++++++-------------------------- docs/terraform.md | 119 +++++++++-------------------------- examples/complete/outputs.tf | 24 +++---- main.tf | 38 ++++++++++- outputs.tf | 59 +++++++++++++++++ variables.tf | 91 ++++++++++++++++++++++++++- 6 files changed, 256 insertions(+), 194 deletions(-) diff --git a/README.md b/README.md index 139ba31..9a8c1d4 100644 --- a/README.md +++ b/README.md @@ -143,126 +143,67 @@ Available targets: | Name | Source | Version | |------|--------|---------| -| dns_master | cloudposse/route53-cluster-hostname/aws | 0.12.0 | -| dns_replicas | cloudposse/route53-cluster-hostname/aws | 0.12.0 | -| enhanced_monitoring_label | cloudposse/label/null | 0.24.1 | | this | cloudposse/label/null | 0.24.1 | ## Resources | Name | |------| -| [aws_appautoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | -| [aws_appautoscaling_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | -| [aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | -| [aws_db_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | -| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | -| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | -| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | -| [aws_rds_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | -| [aws_rds_cluster_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | -| [aws_rds_cluster_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | -| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | -| [aws_security_group_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | +| [aws_db_proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | +| [aws_db_proxy_default_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | +| [aws_db_proxy_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| admin\_password | (Required unless a snapshot\_identifier is provided) Password for the master DB user | `string` | `""` | no | -| admin\_user | (Required unless a snapshot\_identifier is provided) Username for the master DB user | `string` | `"admin"` | no | -| allowed\_cidr\_blocks | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no | -| apply\_immediately | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| 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 | Whether to enable cluster autoscaling | `bool` | `false` | no | -| autoscaling\_max\_capacity | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no | -| autoscaling\_min\_capacity | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no | -| autoscaling\_policy\_type | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no | -| 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 | 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 | The metrics type to use. If this value isn't provided the default is CPU utilization | `string` | `"RDSReaderAverageCPUUtilization"` | no | -| autoscaling\_target\_value | The target value to scale with respect to target metrics | `number` | `75` | no | -| 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 | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no | -| 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 | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no | -| cluster\_identifier | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no | -| cluster\_parameters | List of DB cluster parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | -| cluster\_size | Number of DB instances to create in the cluster | `number` | `2` | no | -| 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 | +| auth | Configuration blocks with authorization mechanisms to connect to the associated database instances or clusters |
list(object({
auth_scheme = string
description = string
iam_auth = string
secret_arn = string
}))
| n/a | yes | +| connection\_borrow\_timeout | he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | -| copy\_tags\_to\_snapshot | Copy tags to backup snapshots | `bool` | `false` | no | -| db\_name | Database name (default is not to create a database) | `string` | `""` | no | -| db\_port | Database port | `number` | `3306` | no | -| deletion\_protection | If the DB instance should have deletion protection enabled | `bool` | `false` | no | +| db\_cluster\_identifier | DB cluster identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | +| db\_instance\_identifier | DB instance identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | +| debug\_logging | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | -| enable\_http\_endpoint | Enable HTTP endpoint (data API). Only valid when engine\_mode is set to serverless | `bool` | `false` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | -| 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 | 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 | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no | -| engine\_version | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no | -| 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 | +| engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| global\_cluster\_identifier | ID of the Aurora global cluster | `string` | `""` | no | -| 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 | Iam roles for the Aurora cluster | `list(string)` | `[]` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | -| instance\_availability\_zone | Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly | `string` | `""` | no | -| instance\_parameters | List of DB instance parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | -| instance\_type | Instance type to use | `string` | `"db.t2.small"` | no | -| 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 | +| idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | +| init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | | label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | -| maintenance\_window | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no | +| max\_connections\_percent | The maximum size of the connection pool for each target in a target group | `number` | `100` | no | +| max\_idle\_connections\_percent | Controls how actively the proxy closes idle database connections in the connection pool. A high value enables the proxy to leave a high percentage of idle connections open. A low value causes the proxy to close idle client connections and return the underlying database connections to the connection pool | `number` | `50` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| performance\_insights\_enabled | Whether to enable Performance Insights | `bool` | `false` | no | -| 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 | -| publicly\_accessible | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no | -| 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 | The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no | -| 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 | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
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 | 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 | List point-in-time recovery options. Only valid actions are `source_cluster_identifier`, `restore_type` and `use_latest_restorable_time` |
list(object({
source_cluster_identifier = string
restore_type = string
use_latest_restorable_time = bool
}))
| `[]` | no | -| retention\_period | Number of days to retain backups for | `number` | `5` | no | -| 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 | 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 | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no | -| skip\_final\_snapshot | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no | -| snapshot\_identifier | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no | -| source\_region | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no | +| require\_tls | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy | `bool` | `false` | no | +| role\_arn | he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | n/a | yes | +| session\_pinning\_filters | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | -| 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 | -| subnets | List of VPC subnet IDs | `list(string)` | n/a | yes | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| 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 | -| vpc\_id | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes | -| 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 | Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas | `string` | `""` | no | +| vpc\_security\_group\_ids | One or more VPC security group IDs to associate with the proxy | `set(string)` | n/a | yes | +| vpc\_subnet\_ids | One or more VPC subnet IDs to associate with the proxy | `set(string)` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| arn | Amazon Resource Name (ARN) of the cluster | -| cluster\_identifier | Cluster Identifier | -| cluster\_resource\_id | The region-unique, immutable identifie of the cluster | -| cluster\_security\_groups | Default RDS cluster security groups | -| database\_name | Database name | -| dbi\_resource\_ids | List of the region-unique, immutable identifiers for the DB instances in the cluster | -| endpoint | The DNS address of the RDS instance | -| master\_host | DB Master hostname | -| master\_username | Username for the master DB user | -| reader\_endpoint | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas | -| replicas\_host | Replicas hostname | -| security\_group\_arn | Security Group ARN | -| security\_group\_id | Security Group ID | -| security\_group\_name | Security Group name | +| proxy\_arn | Proxy ARN | +| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) representing the default target group | +| proxy\_default\_target\_group\_name | The name of the default target group | +| proxy\_endpoint | Proxy endpoint | +| proxy\_id | Proxy ID | +| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type | +| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`) | +| proxy\_target\_port | Port for the target RDS DB instance or Aurora DB cluster | +| proxy\_target\_rds\_resource\_id | Identifier representing the DB instance or DB cluster target | +| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster | +| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB instance target. Not returned unless manually importing an `RDS_INSTANCE` target that is part of a DB cluster | +| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` | diff --git a/docs/terraform.md b/docs/terraform.md index 72769b2..66c337a 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -17,124 +17,65 @@ | Name | Source | Version | |------|--------|---------| -| dns_master | cloudposse/route53-cluster-hostname/aws | 0.12.0 | -| dns_replicas | cloudposse/route53-cluster-hostname/aws | 0.12.0 | -| enhanced_monitoring_label | cloudposse/label/null | 0.24.1 | | this | cloudposse/label/null | 0.24.1 | ## Resources | Name | |------| -| [aws_appautoscaling_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_policy) | -| [aws_appautoscaling_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/appautoscaling_target) | -| [aws_db_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_parameter_group) | -| [aws_db_subnet_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_subnet_group) | -| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | -| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | -| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | -| [aws_rds_cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster) | -| [aws_rds_cluster_instance](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance) | -| [aws_rds_cluster_parameter_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_parameter_group) | -| [aws_security_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group) | -| [aws_security_group_rule](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule) | +| [aws_db_proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | +| [aws_db_proxy_default_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | +| [aws_db_proxy_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| admin\_password | (Required unless a snapshot\_identifier is provided) Password for the master DB user | `string` | `""` | no | -| admin\_user | (Required unless a snapshot\_identifier is provided) Username for the master DB user | `string` | `"admin"` | no | -| allowed\_cidr\_blocks | List of CIDR blocks allowed to access the cluster | `list(string)` | `[]` | no | -| apply\_immediately | Specifies whether any cluster modifications are applied immediately, or during the next maintenance window | `bool` | `true` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| 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 | Whether to enable cluster autoscaling | `bool` | `false` | no | -| autoscaling\_max\_capacity | Maximum number of instances to be maintained by the autoscaler | `number` | `5` | no | -| autoscaling\_min\_capacity | Minimum number of instances to be maintained by the autoscaler | `number` | `1` | no | -| autoscaling\_policy\_type | Autoscaling policy type. `TargetTrackingScaling` and `StepScaling` are supported | `string` | `"TargetTrackingScaling"` | no | -| 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 | 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 | The metrics type to use. If this value isn't provided the default is CPU utilization | `string` | `"RDSReaderAverageCPUUtilization"` | no | -| autoscaling\_target\_value | The target value to scale with respect to target metrics | `number` | `75` | no | -| 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 | Daily time range during which the backups happen | `string` | `"07:00-09:00"` | no | -| 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 | The family of the DB cluster parameter group | `string` | `"aurora5.6"` | no | -| cluster\_identifier | The RDS Cluster Identifier. Will use generated label ID if not supplied | `string` | `""` | no | -| cluster\_parameters | List of DB cluster parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | -| cluster\_size | Number of DB instances to create in the cluster | `number` | `2` | no | -| 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 | +| auth | Configuration blocks with authorization mechanisms to connect to the associated database instances or clusters |
list(object({
auth_scheme = string
description = string
iam_auth = string
secret_arn = string
}))
| n/a | yes | +| connection\_borrow\_timeout | he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | -| copy\_tags\_to\_snapshot | Copy tags to backup snapshots | `bool` | `false` | no | -| db\_name | Database name (default is not to create a database) | `string` | `""` | no | -| db\_port | Database port | `number` | `3306` | no | -| deletion\_protection | If the DB instance should have deletion protection enabled | `bool` | `false` | no | +| db\_cluster\_identifier | DB cluster identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | +| db\_instance\_identifier | DB instance identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | +| debug\_logging | Whether the proxy includes detailed information about SQL statements in its logs | `bool` | `false` | no | | delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | -| enable\_http\_endpoint | Enable HTTP endpoint (data API). Only valid when engine\_mode is set to serverless | `bool` | `false` | no | | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | -| 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 | 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 | The database engine mode. Valid values: `parallelquery`, `provisioned`, `serverless` | `string` | `"provisioned"` | no | -| engine\_version | The version of the database engine to use. See `aws rds describe-db-engine-versions` | `string` | `""` | no | -| 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 | +| engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| global\_cluster\_identifier | ID of the Aurora global cluster | `string` | `""` | no | -| 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 | Iam roles for the Aurora cluster | `list(string)` | `[]` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | -| instance\_availability\_zone | Optional parameter to place cluster instances in a specific availability zone. If left empty, will place randomly | `string` | `""` | no | -| instance\_parameters | List of DB instance parameters to apply |
list(object({
apply_method = string
name = string
value = string
}))
| `[]` | no | -| instance\_type | Instance type to use | `string` | `"db.t2.small"` | no | -| 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 | +| idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | +| init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | | label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | -| maintenance\_window | Weekly time range during which system maintenance can occur, in UTC | `string` | `"wed:03:00-wed:04:00"` | no | +| max\_connections\_percent | The maximum size of the connection pool for each target in a target group | `number` | `100` | no | +| max\_idle\_connections\_percent | Controls how actively the proxy closes idle database connections in the connection pool. A high value enables the proxy to leave a high percentage of idle connections open. A low value causes the proxy to close idle client connections and return the underlying database connections to the connection pool | `number` | `50` | no | | name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| performance\_insights\_enabled | Whether to enable Performance Insights | `bool` | `false` | no | -| 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 | -| publicly\_accessible | Set to true if you want your cluster to be publicly accessible (such as via QuickSight) | `bool` | `false` | no | -| 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 | The ARN for the IAM role that permits RDS to send enhanced monitoring metrics to CloudWatch Logs | `string` | `null` | no | -| 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 | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
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 | 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 | List point-in-time recovery options. Only valid actions are `source_cluster_identifier`, `restore_type` and `use_latest_restorable_time` |
list(object({
source_cluster_identifier = string
restore_type = string
use_latest_restorable_time = bool
}))
| `[]` | no | -| retention\_period | Number of days to retain backups for | `number` | `5` | no | -| 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 | 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 | List of security groups to be allowed to connect to the DB instance | `list(string)` | `[]` | no | -| skip\_final\_snapshot | Determines whether a final DB snapshot is created before the DB cluster is deleted | `bool` | `true` | no | -| snapshot\_identifier | Specifies whether or not to create this cluster from a snapshot | `string` | `null` | no | -| source\_region | Source Region of primary cluster, needed when using encrypted storage and region replicas | `string` | `""` | no | +| require\_tls | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy | `bool` | `false` | no | +| role\_arn | he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | n/a | yes | +| session\_pinning\_filters | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | -| 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 | -| subnets | List of VPC subnet IDs | `list(string)` | n/a | yes | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| 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 | -| vpc\_id | VPC ID to create the cluster in (e.g. `vpc-a22222ee`) | `string` | n/a | yes | -| 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 | Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas | `string` | `""` | no | +| vpc\_security\_group\_ids | One or more VPC security group IDs to associate with the proxy | `set(string)` | n/a | yes | +| vpc\_subnet\_ids | One or more VPC subnet IDs to associate with the proxy | `set(string)` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| arn | Amazon Resource Name (ARN) of the cluster | -| cluster\_identifier | Cluster Identifier | -| cluster\_resource\_id | The region-unique, immutable identifie of the cluster | -| cluster\_security\_groups | Default RDS cluster security groups | -| database\_name | Database name | -| dbi\_resource\_ids | List of the region-unique, immutable identifiers for the DB instances in the cluster | -| endpoint | The DNS address of the RDS instance | -| master\_host | DB Master hostname | -| master\_username | Username for the master DB user | -| reader\_endpoint | A read-only endpoint for the Aurora cluster, automatically load-balanced across replicas | -| replicas\_host | Replicas hostname | -| security\_group\_arn | Security Group ARN | -| security\_group\_id | Security Group ID | -| security\_group\_name | Security Group name | +| proxy\_arn | Proxy ARN | +| proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) representing the default target group | +| proxy\_default\_target\_group\_name | The name of the default target group | +| proxy\_endpoint | Proxy endpoint | +| proxy\_id | Proxy ID | +| proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type | +| proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`) | +| proxy\_target\_port | Port for the target RDS DB instance or Aurora DB cluster | +| proxy\_target\_rds\_resource\_id | Identifier representing the DB instance or DB cluster target | +| proxy\_target\_target\_arn | Amazon Resource Name (ARN) for the DB instance or DB cluster | +| proxy\_target\_tracked\_cluster\_id | DB Cluster identifier for the DB instance target. Not returned unless manually importing an `RDS_INSTANCE` target that is part of a DB cluster | +| proxy\_target\_type | Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER` | diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 989b967..d3cf8bb 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,3 +1,15 @@ +output "public_subnet_cidrs" { + value = module.subnets.public_subnet_cidrs +} + +output "private_subnet_cidrs" { + value = module.subnets.private_subnet_cidrs +} + +output "vpc_cidr" { + value = module.vpc.vpc_cidr_block +} + output "instance_id" { value = module.rds_instance.instance_id description = "ID of the instance" @@ -37,15 +49,3 @@ output "hostname" { value = module.rds_instance.hostname description = "DNS host name of the instance" } - -output "public_subnet_cidrs" { - value = module.subnets.public_subnet_cidrs -} - -output "private_subnet_cidrs" { - value = module.subnets.private_subnet_cidrs -} - -output "vpc_cidr" { - value = module.vpc.vpc_cidr_block -} diff --git a/main.tf b/main.tf index 54a975c..5747f59 100644 --- a/main.tf +++ b/main.tf @@ -1,2 +1,38 @@ -locals { +resource "aws_db_proxy" "this" { + name = module.this.id + debug_logging = var.debug_logging + engine_family = var.engine_family + idle_client_timeout = var.idle_client_timeout + require_tls = var.require_tls + role_arn = var.role_arn + vpc_security_group_ids = var.vpc_security_group_ids + vpc_subnet_ids = var.vpc_subnet_ids + auth = var.auth + tags = module.this.tags +} + +resource "aws_db_proxy_default_target_group" "this" { + db_proxy_name = aws_db_proxy.this.name + + dynamic "connection_pool_config" { + for_each = ( + var.connection_borrow_timeout != null || var.init_query != null || var.max_connections_percent != null || + var.max_idle_connections_percent != null || var.session_pinning_filters != null + ) ? ["true"] : [] + + content { + connection_borrow_timeout = var.connection_borrow_timeout + init_query = var.init_query + max_connections_percent = var.max_connections_percent + max_idle_connections_percent = var.max_idle_connections_percent + session_pinning_filters = var.session_pinning_filters + } + } +} + +resource "aws_db_proxy_target" "this" { + db_instance_identifier = var.db_instance_identifier + db_cluster_identifier = var.db_cluster_identifier + db_proxy_name = aws_db_proxy.this.name + target_group_name = aws_db_proxy_default_target_group.this.db_proxy_name } diff --git a/outputs.tf b/outputs.tf index e69de29..d25c4eb 100644 --- a/outputs.tf +++ b/outputs.tf @@ -0,0 +1,59 @@ +output "proxy_id" { + value = aws_db_proxy.this.id + description = "Proxy ID" +} + +output "proxy_arn" { + value = aws_db_proxy.this.arn + description = "Proxy ARN" +} + +output "proxy_endpoint" { + value = aws_db_proxy.this.endpoint + description = "Proxy endpoint" +} + +output "proxy_target_endpoint" { + value = aws_db_proxy_target.this.endpoint + description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type" +} + +output "proxy_target_id" { + value = aws_db_proxy_target.this.id + description = "Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`)" +} + +output "proxy_target_port" { + value = aws_db_proxy_target.this.port + description = "Port for the target RDS DB instance or Aurora DB cluster" +} + +output "proxy_target_rds_resource_id" { + value = aws_db_proxy_target.this.rds_resource_id + description = "Identifier representing the DB instance or DB cluster target" +} + +output "proxy_target_target_arn" { + value = aws_db_proxy_target.this.target_arn + description = "Amazon Resource Name (ARN) for the DB instance or DB cluster" +} + +output "proxy_target_tracked_cluster_id" { + value = aws_db_proxy_target.this.tracked_cluster_id + description = "DB Cluster identifier for the DB instance target. Not returned unless manually importing an `RDS_INSTANCE` target that is part of a DB cluster" +} + +output "proxy_target_type" { + value = aws_db_proxy_target.this.type + description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`" +} + +output "proxy_default_target_group_arn" { + value = aws_db_proxy_default_target_group.this.arn + description = "The Amazon Resource Name (ARN) representing the default target group" +} + +output "proxy_default_target_group_name" { + value = aws_db_proxy_default_target_group.this.name + description = "The name of the default target group" +} diff --git a/variables.tf b/variables.tf index a40b89d..3d45439 100644 --- a/variables.tf +++ b/variables.tf @@ -1,5 +1,90 @@ -variable "zone_id" { +variable "debug_logging" { + type = bool + default = false + description = "Whether the proxy includes detailed information about SQL statements in its logs" +} + +variable "engine_family" { + type = string + default = "MYSQL" + description = "The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL" +} + +variable "idle_client_timeout" { + type = number + default = 1800 + description = "The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it" +} + +variable "require_tls" { + type = bool + default = false + description = "A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy" +} + +variable "role_arn" { + type = string + description = "he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" +} + +variable "vpc_security_group_ids" { + type = set(string) + description = "One or more VPC security group IDs to associate with the proxy" +} + +variable "vpc_subnet_ids" { + type = set(string) + description = "One or more VPC subnet IDs to associate with the proxy" +} + +variable "auth" { + type = list(object({ + auth_scheme = string + description = string + iam_auth = string + secret_arn = string + })) + description = "Configuration blocks with authorization mechanisms to connect to the associated database instances or clusters" +} + +variable "db_instance_identifier" { + type = string + default = null + description = "DB instance identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together" +} + +variable "db_cluster_identifier" { type = string - default = "" - description = "Route53 parent zone ID. If provided (not empty), the module will create sub-domain DNS records for the DB master and replicas" + default = null + description = "DB cluster identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together" +} + +variable "connection_borrow_timeout" { + type = number + default = 120 + description = "he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" +} + +variable "init_query" { + type = string + default = null + description = "One or more SQL statements for the proxy to run when opening each new database connection" +} + +variable "max_connections_percent" { + type = number + default = 100 + description = "The maximum size of the connection pool for each target in a target group" +} + +variable "max_idle_connections_percent" { + type = number + default = 50 + description = "Controls how actively the proxy closes idle database connections in the connection pool. A high value enables the proxy to leave a high percentage of idle connections open. A low value causes the proxy to close idle client connections and return the underlying database connections to the connection pool" +} + +variable "session_pinning_filters" { + type = list(string) + default = null + description = "Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection" } From 2d97567a03b63f335c6d493f61ec63fc3c705585 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 10:20:55 -0500 Subject: [PATCH 03/19] Init --- README.md | 8 ++- docs/terraform.md | 8 ++- examples/complete/fixtures.us-east-2.tfvars | 4 +- examples/complete/main.tf | 30 ++++++++++ examples/complete/outputs.tf | 65 +++++++++++++++++++++ examples/complete/variables.tf | 60 +++++++++++++++++++ iam.tf | 53 +++++++++++++++++ main.tf | 2 +- outputs.tf | 5 ++ variables.tf | 11 ++-- 10 files changed, 237 insertions(+), 9 deletions(-) create mode 100644 iam.tf diff --git a/README.md b/README.md index 9a8c1d4..540bc9a 100644 --- a/README.md +++ b/README.md @@ -143,6 +143,7 @@ Available targets: | Name | Source | Version | |------|--------|---------| +| role_label | cloudposse/label/null | 0.24.1 | | this | cloudposse/label/null | 0.24.1 | ## Resources @@ -152,6 +153,10 @@ Available targets: | [aws_db_proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | | [aws_db_proxy_default_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | | [aws_db_proxy_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | +| [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | +| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | ## Inputs @@ -169,6 +174,7 @@ Available targets: | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| iam\_role\_attributes | Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `list(string)` | `null` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | @@ -181,7 +187,6 @@ Available targets: | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | | require\_tls | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy | `bool` | `false` | no | -| role\_arn | he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | n/a | yes | | session\_pinning\_filters | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | @@ -196,6 +201,7 @@ Available targets: | proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) representing the default target group | | proxy\_default\_target\_group\_name | The name of the default target group | | proxy\_endpoint | Proxy endpoint | +| proxy\_iam\_role\_arn | The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | | proxy\_id | Proxy ID | | proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type | | proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`) | diff --git a/docs/terraform.md b/docs/terraform.md index 66c337a..eb16263 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -17,6 +17,7 @@ | Name | Source | Version | |------|--------|---------| +| role_label | cloudposse/label/null | 0.24.1 | | this | cloudposse/label/null | 0.24.1 | ## Resources @@ -26,6 +27,10 @@ | [aws_db_proxy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy) | | [aws_db_proxy_default_target_group](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_default_target_group) | | [aws_db_proxy_target](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/db_proxy_target) | +| [aws_iam_policy](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_policy) | +| [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | +| [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | +| [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | ## Inputs @@ -43,6 +48,7 @@ | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| iam\_role\_attributes | Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `list(string)` | `null` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | @@ -55,7 +61,6 @@ | namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | | regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | | require\_tls | A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy | `bool` | `false` | no | -| role\_arn | he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `string` | n/a | yes | | session\_pinning\_filters | Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection | `list(string)` | `null` | no | | stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | @@ -70,6 +75,7 @@ | proxy\_default\_target\_group\_arn | The Amazon Resource Name (ARN) representing the default target group | | proxy\_default\_target\_group\_name | The name of the default target group | | proxy\_endpoint | Proxy endpoint | +| proxy\_iam\_role\_arn | The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | | proxy\_id | Proxy ID | | proxy\_target\_endpoint | Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type | | proxy\_target\_id | Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`) | diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index e8e4554..fb6c08d 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -1,6 +1,6 @@ region = "us-east-2" -availability_zones = ["us-east-2a", "us-east-2b"] +availability_zones = ["us-east-2a"] namespace = "eg" @@ -8,6 +8,8 @@ stage = "test" name = "rds-proxy" +iam_role_attributes = ["role"] + deletion_protection = false database_name = "test_db" diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 6fbf4e2..c9a2517 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -41,6 +41,15 @@ locals { username = var.database_user password = local.database_password } + + auth = [ + { + auth_scheme = "SECRETS" + description = "Access the database instance using username and password from Amazon Secrets Manager" + iam_auth = "DISABLED" + secret_arn = aws_secretsmanager_secret.rds_username_and_password.arn + } + ] } module "rds_instance" { @@ -79,3 +88,24 @@ resource "aws_secretsmanager_secret_version" "rds_username_and_password" { secret_id = aws_secretsmanager_secret.rds_username_and_password.id secret_string = jsonencode(local.username_password) } + +module "rds_proxy" { + source = "../../" + + db_instance_identifier = module.rds_instance.instance_id + auth = local.auth + vpc_security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_subnet_ids = module.subnets.public_subnet_ids + + debug_logging = var.debug_logging + engine_family = var.engine_family + idle_client_timeout = var.idle_client_timeout + require_tls = var.require_tls + connection_borrow_timeout = var.connection_borrow_timeout + init_query = var.init_query + max_connections_percent = var.max_connections_percent + max_idle_connections_percent = var.max_idle_connections_percent + session_pinning_filters = var.session_pinning_filters + + context = module.this.context +} diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index d3cf8bb..2775073 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -49,3 +49,68 @@ output "hostname" { value = module.rds_instance.hostname description = "DNS host name of the instance" } + +output "proxy_id" { + value = module.rds_proxy.proxy_id + description = "Proxy ID" +} + +output "proxy_arn" { + value = module.rds_proxy.proxy_arn + description = "Proxy ARN" +} + +output "proxy_endpoint" { + value = module.rds_proxy.proxy_endpoint + description = "Proxy endpoint" +} + +output "proxy_target_endpoint" { + value = module.rds_proxy.proxy_target_endpoint + description = "Hostname for the target RDS DB Instance. Only returned for `RDS_INSTANCE` type" +} + +output "proxy_target_id" { + value = module.rds_proxy.proxy_target_id + description = "Identifier of `db_proxy_name`, `target_group_name`, `target type` (e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`), and resource identifier separated by forward slashes (`/`)" +} + +output "proxy_target_port" { + value = module.rds_proxy.proxy_target_port + description = "Port for the target RDS DB instance or Aurora DB cluster" +} + +output "proxy_target_rds_resource_id" { + value = module.rds_proxy.proxy_target_rds_resource_id + description = "Identifier representing the DB instance or DB cluster target" +} + +output "proxy_target_target_arn" { + value = module.rds_proxy.proxy_target_target_arn + description = "Amazon Resource Name (ARN) for the DB instance or DB cluster" +} + +output "proxy_target_tracked_cluster_id" { + value = module.rds_proxy.proxy_target_tracked_cluster_id + description = "DB Cluster identifier for the DB instance target. Not returned unless manually importing an `RDS_INSTANCE` target that is part of a DB cluster" +} + +output "proxy_target_type" { + value = module.rds_proxy.proxy_target_type + description = "Type of target. e.g. `RDS_INSTANCE` or `TRACKED_CLUSTER`" +} + +output "proxy_default_target_group_arn" { + value = module.rds_proxy.proxy_default_target_group_arn + description = "The Amazon Resource Name (ARN) representing the default target group" +} + +output "proxy_default_target_group_name" { + value = module.rds_proxy.proxy_default_target_group_name + description = "The name of the default target group" +} + +output "proxy_iam_role_arn" { + value = module.rds_proxy.proxy_iam_role_arn + description = "The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" +} diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 7ac5604..570815b 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -94,3 +94,63 @@ variable "apply_immediately" { type = bool description = "Specifies whether any database modifications are applied immediately, or during the next maintenance window" } + +variable "debug_logging" { + type = bool + default = false + description = "Whether the proxy includes detailed information about SQL statements in its logs" +} + +variable "engine_family" { + type = string + default = "MYSQL" + description = "The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL" +} + +variable "idle_client_timeout" { + type = number + default = 1800 + description = "The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it" +} + +variable "require_tls" { + type = bool + default = false + description = "A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy" +} + +variable "connection_borrow_timeout" { + type = number + default = 120 + description = "he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" +} + +variable "init_query" { + type = string + default = null + description = "One or more SQL statements for the proxy to run when opening each new database connection" +} + +variable "max_connections_percent" { + type = number + default = 100 + description = "The maximum size of the connection pool for each target in a target group" +} + +variable "max_idle_connections_percent" { + type = number + default = 50 + description = "Controls how actively the proxy closes idle database connections in the connection pool. A high value enables the proxy to leave a high percentage of idle connections open. A low value causes the proxy to close idle client connections and return the underlying database connections to the connection pool" +} + +variable "session_pinning_filters" { + type = list(string) + default = null + description = "Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection" +} + +variable "iam_role_attributes" { + type = list(string) + default = null + description = "Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" +} diff --git a/iam.tf b/iam.tf new file mode 100644 index 0000000..c350bf3 --- /dev/null +++ b/iam.tf @@ -0,0 +1,53 @@ +# https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html + +locals { + asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) +} + +data "aws_iam_policy_document" "assume_role" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["rds.amazonaws.com"] + } + } +} + +data "aws_iam_policy_document" "this" { + statement { + sid = "AllowRdsToGetSecretValueFromAmazonSecretManager" + + actions = [ + "secretsmanager:GetSecretValue" + ] + + resources = local.asm_secret_arns + } +} + +module "role_label" { + source = "cloudposse/label/null" + version = "0.24.1" + + attributes = var.iam_role_attributes + context = module.this.context +} + +resource "aws_iam_policy" "this" { + name = module.role_label.id + policy = data.aws_iam_policy_document.this.json +} + +resource "aws_iam_role" "this" { + name = module.role_label.id + assume_role_policy = data.aws_iam_policy_document.assume_role.json + tags = module.this.tags +} + +resource "aws_iam_role_policy_attachment" "this" { + policy_arn = aws_iam_policy.this.arn + role = aws_iam_role.this.name +} diff --git a/main.tf b/main.tf index 5747f59..0a38f95 100644 --- a/main.tf +++ b/main.tf @@ -4,7 +4,7 @@ resource "aws_db_proxy" "this" { engine_family = var.engine_family idle_client_timeout = var.idle_client_timeout require_tls = var.require_tls - role_arn = var.role_arn + role_arn = aws_iam_role.this.arn vpc_security_group_ids = var.vpc_security_group_ids vpc_subnet_ids = var.vpc_subnet_ids auth = var.auth diff --git a/outputs.tf b/outputs.tf index d25c4eb..7f8166f 100644 --- a/outputs.tf +++ b/outputs.tf @@ -57,3 +57,8 @@ output "proxy_default_target_group_name" { value = aws_db_proxy_default_target_group.this.name description = "The name of the default target group" } + +output "proxy_iam_role_arn" { + value = aws_iam_role.this.arn + description = "The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" +} diff --git a/variables.tf b/variables.tf index 3d45439..f37dab7 100644 --- a/variables.tf +++ b/variables.tf @@ -22,11 +22,6 @@ variable "require_tls" { description = "A Boolean parameter that specifies whether Transport Layer Security (TLS) encryption is required for connections to the proxy. By enabling this setting, you can enforce encrypted TLS connections to the proxy" } -variable "role_arn" { - type = string - description = "he Amazon Resource Name (ARN) of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" -} - variable "vpc_security_group_ids" { type = set(string) description = "One or more VPC security group IDs to associate with the proxy" @@ -88,3 +83,9 @@ variable "session_pinning_filters" { default = null description = "Each item in the list represents a class of SQL operations that normally cause all later statements in a session using a proxy to be pinned to the same underlying database connection" } + +variable "iam_role_attributes" { + type = list(string) + default = null + description = "Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" +} From 73ff66694a22c3caa6d6d8495d908e4dfb093efb Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 10:32:24 -0500 Subject: [PATCH 04/19] Init --- README.md | 109 +++++++++++++++++++++++++++++++++ README.yaml | 108 ++++++++++++++++++++++++++++++++ docs/terraform.md | 1 + examples/complete/main.tf | 3 +- examples/complete/variables.tf | 6 ++ variables.tf | 6 ++ 6 files changed, 232 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 540bc9a..eab7a00 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,114 @@ For automated tests of the complete example using [bats](https://github.com/bats (which tests and deploys the example on AWS), see [test](test). ```hcl +module "vpc" { + source = "cloudposse/vpc/aws" + version = "0.21.1" + + cidr_block = "172.16.0.0/16" + + context = module.this.context +} + +module "subnets" { + source = "cloudposse/dynamic-subnets/aws" + version = "0.38.0" + + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = false + nat_instance_enabled = false + + context = module.this.context +} + +resource "random_password" "admin_password" { +count = var.database_password == "" || var.database_password == null ? 1 : 0 + length = 33 + special = false + override_special = "!#$%^&*()<>-_" +} + +locals { + database_password = var.database_password != "" && var.database_password != null ? var.database_password : join("", random_password.admin_password.*.result) + + username_password = { + username = var.database_user + password = local.database_password + } + + auth = [ + { + auth_scheme = "SECRETS" + description = "Access the database instance using username and password from AWS Secrets Manager" + iam_auth = "DISABLED" + secret_arn = aws_secretsmanager_secret.rds_username_and_password.arn + } + ] +} + +module "rds_instance" { + source = "cloudposse/rds/aws" + version = "0.34.0" + + database_name = var.database_name + database_user = var.database_user + database_password = local.database_password + database_port = var.database_port + multi_az = var.multi_az + storage_type = var.storage_type + allocated_storage = var.allocated_storage + storage_encrypted = var.storage_encrypted + engine = var.engine + engine_version = var.engine_version + instance_class = var.instance_class + db_parameter_group = var.db_parameter_group + publicly_accessible = var.publicly_accessible + vpc_id = module.vpc.vpc_id + subnet_ids = module.subnets.private_subnet_ids + security_group_ids = [module.vpc.vpc_default_security_group_id] + apply_immediately = var.apply_immediately + + context = module.this.context +} + +resource "aws_secretsmanager_secret" "rds_username_and_password" { + name = module.this.id + description = "RDS username and password" + recovery_window_in_days = 0 + tags = module.this.tags +} + +resource "aws_secretsmanager_secret_version" "rds_username_and_password" { + secret_id = aws_secretsmanager_secret.rds_username_and_password.id + secret_string = jsonencode(local.username_password) +} + +module "rds_proxy" { + source = "cloudposse/rds-db-proxy/aws" + version = "0.1.0" + + db_instance_identifier = module.rds_instance.instance_id + auth = local.auth + vpc_security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_subnet_ids = module.subnets.public_subnet_ids + + debug_logging = var.debug_logging + engine_family = var.engine_family + idle_client_timeout = var.idle_client_timeout + require_tls = var.require_tls + connection_borrow_timeout = var.connection_borrow_timeout + init_query = var.init_query + max_connections_percent = var.max_connections_percent + max_idle_connections_percent = var.max_idle_connections_percent + session_pinning_filters = var.session_pinning_filters + existing_iam_role_arn = var.existing_iam_role_arn + + context = module.this.context +} + ``` @@ -174,6 +282,7 @@ Available targets: | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| existing\_iam\_role\_arn | The ARN of an existing IAM role that the proxy can use to access secrets in AWS Secrets Manager. If not provided, the module will create a role to access secrets in Secrets Manager | `string` | `null` | no | | iam\_role\_attributes | Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `list(string)` | `null` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | diff --git a/README.yaml b/README.yaml index 60af4ae..f3651f2 100644 --- a/README.yaml +++ b/README.yaml @@ -64,6 +64,114 @@ usage: |2- (which tests and deploys the example on AWS), see [test](test). ```hcl + module "vpc" { + source = "cloudposse/vpc/aws" + version = "0.21.1" + + cidr_block = "172.16.0.0/16" + + context = module.this.context + } + + module "subnets" { + source = "cloudposse/dynamic-subnets/aws" + version = "0.38.0" + + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = false + nat_instance_enabled = false + + context = module.this.context + } + + resource "random_password" "admin_password" { + count = var.database_password == "" || var.database_password == null ? 1 : 0 + length = 33 + special = false + override_special = "!#$%^&*()<>-_" + } + + locals { + database_password = var.database_password != "" && var.database_password != null ? var.database_password : join("", random_password.admin_password.*.result) + + username_password = { + username = var.database_user + password = local.database_password + } + + auth = [ + { + auth_scheme = "SECRETS" + description = "Access the database instance using username and password from AWS Secrets Manager" + iam_auth = "DISABLED" + secret_arn = aws_secretsmanager_secret.rds_username_and_password.arn + } + ] + } + + module "rds_instance" { + source = "cloudposse/rds/aws" + version = "0.34.0" + + database_name = var.database_name + database_user = var.database_user + database_password = local.database_password + database_port = var.database_port + multi_az = var.multi_az + storage_type = var.storage_type + allocated_storage = var.allocated_storage + storage_encrypted = var.storage_encrypted + engine = var.engine + engine_version = var.engine_version + instance_class = var.instance_class + db_parameter_group = var.db_parameter_group + publicly_accessible = var.publicly_accessible + vpc_id = module.vpc.vpc_id + subnet_ids = module.subnets.private_subnet_ids + security_group_ids = [module.vpc.vpc_default_security_group_id] + apply_immediately = var.apply_immediately + + context = module.this.context + } + + resource "aws_secretsmanager_secret" "rds_username_and_password" { + name = module.this.id + description = "RDS username and password" + recovery_window_in_days = 0 + tags = module.this.tags + } + + resource "aws_secretsmanager_secret_version" "rds_username_and_password" { + secret_id = aws_secretsmanager_secret.rds_username_and_password.id + secret_string = jsonencode(local.username_password) + } + + module "rds_proxy" { + source = "cloudposse/rds-db-proxy/aws" + version = "0.1.0" + + db_instance_identifier = module.rds_instance.instance_id + auth = local.auth + vpc_security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_subnet_ids = module.subnets.public_subnet_ids + + debug_logging = var.debug_logging + engine_family = var.engine_family + idle_client_timeout = var.idle_client_timeout + require_tls = var.require_tls + connection_borrow_timeout = var.connection_borrow_timeout + init_query = var.init_query + max_connections_percent = var.max_connections_percent + max_idle_connections_percent = var.max_idle_connections_percent + session_pinning_filters = var.session_pinning_filters + existing_iam_role_arn = var.existing_iam_role_arn + + context = module.this.context + } + ``` examples: |- diff --git a/docs/terraform.md b/docs/terraform.md index eb16263..c458fb7 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -48,6 +48,7 @@ | enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | | engine\_family | The kinds of databases that the proxy can connect to. This value determines which database network protocol the proxy recognizes when it interprets network traffic to and from the database. The engine family applies to MySQL and PostgreSQL for both RDS and Aurora. Valid values are MYSQL and POSTGRESQL | `string` | `"MYSQL"` | no | | environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| existing\_iam\_role\_arn | The ARN of an existing IAM role that the proxy can use to access secrets in AWS Secrets Manager. If not provided, the module will create a role to access secrets in Secrets Manager | `string` | `null` | no | | iam\_role\_attributes | Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager | `list(string)` | `null` | no | | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index c9a2517..7b1d395 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -45,7 +45,7 @@ locals { auth = [ { auth_scheme = "SECRETS" - description = "Access the database instance using username and password from Amazon Secrets Manager" + description = "Access the database instance using username and password from AWS Secrets Manager" iam_auth = "DISABLED" secret_arn = aws_secretsmanager_secret.rds_username_and_password.arn } @@ -106,6 +106,7 @@ module "rds_proxy" { max_connections_percent = var.max_connections_percent max_idle_connections_percent = var.max_idle_connections_percent session_pinning_filters = var.session_pinning_filters + existing_iam_role_arn = var.existing_iam_role_arn context = module.this.context } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 570815b..176ddf3 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -154,3 +154,9 @@ variable "iam_role_attributes" { default = null description = "Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" } + +variable "existing_iam_role_arn" { + type = string + default = null + description = "The ARN of an existing IAM role that the proxy can use to access secrets in AWS Secrets Manager. If not provided, the module will create a role to access secrets in Secrets Manager" +} diff --git a/variables.tf b/variables.tf index f37dab7..93fdf75 100644 --- a/variables.tf +++ b/variables.tf @@ -89,3 +89,9 @@ variable "iam_role_attributes" { default = null description = "Additional attributes to add to the ID of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" } + +variable "existing_iam_role_arn" { + type = string + default = null + description = "The ARN of an existing IAM role that the proxy can use to access secrets in AWS Secrets Manager. If not provided, the module will create a role to access secrets in Secrets Manager" +} From 92c38431923074c94ae766518ace45d010f72d84 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 11:10:59 -0500 Subject: [PATCH 05/19] Init --- iam.tf | 21 +++++++++++++++------ outputs.tf | 2 +- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/iam.tf b/iam.tf index c350bf3..edfdde3 100644 --- a/iam.tf +++ b/iam.tf @@ -1,10 +1,13 @@ # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html locals { - asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) + iam_role_enabled = var.existing_iam_role_arn == mull || var.existing_iam_role_arn == "" ? true : false + asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) } data "aws_iam_policy_document" "assume_role" { + count = local.iam_role_enabled ? 1 : 0 + statement { effect = "Allow" actions = ["sts:AssumeRole"] @@ -17,8 +20,10 @@ data "aws_iam_policy_document" "assume_role" { } data "aws_iam_policy_document" "this" { + count = local.iam_role_enabled ? 1 : 0 + statement { - sid = "AllowRdsToGetSecretValueFromAmazonSecretManager" + sid = "AllowRdsToGetSecretValueFromSecretsManager" actions = [ "secretsmanager:GetSecretValue" @@ -32,22 +37,26 @@ module "role_label" { source = "cloudposse/label/null" version = "0.24.1" + enabled = local.iam_role_enabled attributes = var.iam_role_attributes context = module.this.context } resource "aws_iam_policy" "this" { + count = local.iam_role_enabled ? 1 : 0 name = module.role_label.id - policy = data.aws_iam_policy_document.this.json + policy = join("", data.aws_iam_policy_document.this.*.json) } resource "aws_iam_role" "this" { + count = local.iam_role_enabled ? 1 : 0 name = module.role_label.id - assume_role_policy = data.aws_iam_policy_document.assume_role.json - tags = module.this.tags + assume_role_policy = join("", data.aws_iam_policy_document.assume_role.*.json) + tags = module.role_label.tags } resource "aws_iam_role_policy_attachment" "this" { - policy_arn = aws_iam_policy.this.arn + count = local.iam_role_enabled ? 1 : 0 + policy_arn = join("", aws_iam_policy.this.*.arn) role = aws_iam_role.this.name } diff --git a/outputs.tf b/outputs.tf index 7f8166f..a991d8a 100644 --- a/outputs.tf +++ b/outputs.tf @@ -59,6 +59,6 @@ output "proxy_default_target_group_name" { } output "proxy_iam_role_arn" { - value = aws_iam_role.this.arn + value = var.existing_iam_role_arn == mull || var.existing_iam_role_arn == "" ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn description = "The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" } From 6bfc37e31fa15309528b231d60360e4380dda7fd Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 11:31:48 -0500 Subject: [PATCH 06/19] Init --- README.md | 3 +++ docs/terraform.md | 3 +++ iam.tf | 25 +++++++++++++++++++++++++ variables.tf | 6 ++++++ 4 files changed, 37 insertions(+) diff --git a/README.md b/README.md index eab7a00..5d08d3c 100644 --- a/README.md +++ b/README.md @@ -265,6 +265,8 @@ Available targets: | [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | | [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | | [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | +| [aws_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | +| [aws_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | ## Inputs @@ -287,6 +289,7 @@ Available targets: | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | +| kms\_key\_id | The ARN or Id of the AWS KMS customer master key (CMK) to encrypt the secret values in the versions stored in secrets. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default CMK (the one named `aws/secretsmanager`) | `string` | `null` | no | | label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | diff --git a/docs/terraform.md b/docs/terraform.md index c458fb7..57ba9db 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -31,6 +31,8 @@ | [aws_iam_policy_document](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | | [aws_iam_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | | [aws_iam_role_policy_attachment](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy_attachment) | +| [aws_kms_key](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/kms_key) | +| [aws_region](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | ## Inputs @@ -53,6 +55,7 @@ | id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | | idle\_client\_timeout | The number of seconds that a connection to the proxy can be inactive before the proxy disconnects it | `number` | `1800` | no | | init\_query | One or more SQL statements for the proxy to run when opening each new database connection | `string` | `null` | no | +| kms\_key\_id | The ARN or Id of the AWS KMS customer master key (CMK) to encrypt the secret values in the versions stored in secrets. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default CMK (the one named `aws/secretsmanager`) | `string` | `null` | no | | label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | | label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | | label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | diff --git a/iam.tf b/iam.tf index edfdde3..db3445f 100644 --- a/iam.tf +++ b/iam.tf @@ -3,6 +3,15 @@ locals { iam_role_enabled = var.existing_iam_role_arn == mull || var.existing_iam_role_arn == "" ? true : false asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) + kms_key_id = data.aws_kms_key.this.id +} + +data "aws_region" "this" {} + +# Get information about the KMS Key used to encrypt secrets in AWS Secrets Manager +# If `kms_key_id` is not provided, use the AWS account's default CMK (the one named `aws/secretsmanager`) +data "aws_kms_key" "this" { + key_id = var.kms_key_id != null && var.kms_key_id != "" ? var.kms_key_id : "aws/secretsmanager" } data "aws_iam_policy_document" "assume_role" { @@ -31,6 +40,22 @@ data "aws_iam_policy_document" "this" { resources = local.asm_secret_arns } + + statement { + sid = "AllowRdsToUseKmsKeyToDecryptSecretValuesInSecretsManager" + + actions = [ + "kms:Decrypt" + ] + + resources = local.kms_key_id + + condition { + test = "StringEquals" + values = [format("secretsmanager.%s.amazonaws.com", data.aws_region.this.name)] + variable = "kms:ViaService" + } + } } module "role_label" { diff --git a/variables.tf b/variables.tf index 93fdf75..feb5bde 100644 --- a/variables.tf +++ b/variables.tf @@ -95,3 +95,9 @@ variable "existing_iam_role_arn" { default = null description = "The ARN of an existing IAM role that the proxy can use to access secrets in AWS Secrets Manager. If not provided, the module will create a role to access secrets in Secrets Manager" } + +variable "kms_key_id" { + type = string + default = null + description = "The ARN or Id of the AWS KMS customer master key (CMK) to encrypt the secret values in the versions stored in secrets. If you don't specify this value, then Secrets Manager defaults to using the AWS account's default CMK (the one named `aws/secretsmanager`)" +} From 12f56ae031f7b27d1ad64c4c50188474169624be Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 16:22:36 -0500 Subject: [PATCH 07/19] Init --- examples/complete/variables.tf | 5 ----- iam.tf | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 176ddf3..b6f5d59 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -67,11 +67,6 @@ variable "engine_version" { description = "Database engine version, depends on engine type" } -variable "major_engine_version" { - type = string - description = "Database MAJOR engine version, depends on engine type" -} - variable "instance_class" { type = string description = "Class of RDS instance" diff --git a/iam.tf b/iam.tf index db3445f..955b2d8 100644 --- a/iam.tf +++ b/iam.tf @@ -1,7 +1,7 @@ # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy.html locals { - iam_role_enabled = var.existing_iam_role_arn == mull || var.existing_iam_role_arn == "" ? true : false + iam_role_enabled = var.existing_iam_role_arn == null || var.existing_iam_role_arn == "" ? true : false asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) kms_key_id = data.aws_kms_key.this.id } From 7a2f006e2b829b0b30bc0c58d598f440ea86f3a3 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 16:23:02 -0500 Subject: [PATCH 08/19] Init --- outputs.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outputs.tf b/outputs.tf index a991d8a..16cd7fc 100644 --- a/outputs.tf +++ b/outputs.tf @@ -59,6 +59,6 @@ output "proxy_default_target_group_name" { } output "proxy_iam_role_arn" { - value = var.existing_iam_role_arn == mull || var.existing_iam_role_arn == "" ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn + value = var.existing_iam_role_arn == null || var.existing_iam_role_arn == "" ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn description = "The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" } From fd3a8250c94f42fcded96000d9a0039364419856 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 16:30:03 -0500 Subject: [PATCH 09/19] Init --- iam.tf | 3 ++- main.tf | 17 ++++++++++++++--- outputs.tf | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/iam.tf b/iam.tf index 955b2d8..292df7a 100644 --- a/iam.tf +++ b/iam.tf @@ -4,6 +4,7 @@ locals { iam_role_enabled = var.existing_iam_role_arn == null || var.existing_iam_role_arn == "" ? true : false asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) kms_key_id = data.aws_kms_key.this.id + iam_role_arn = local.iam_role_enabled ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn } data "aws_region" "this" {} @@ -83,5 +84,5 @@ resource "aws_iam_role" "this" { resource "aws_iam_role_policy_attachment" "this" { count = local.iam_role_enabled ? 1 : 0 policy_arn = join("", aws_iam_policy.this.*.arn) - role = aws_iam_role.this.name + role = join("", aws_iam_role.this.*.name) } diff --git a/main.tf b/main.tf index 0a38f95..077ac10 100644 --- a/main.tf +++ b/main.tf @@ -4,11 +4,22 @@ resource "aws_db_proxy" "this" { engine_family = var.engine_family idle_client_timeout = var.idle_client_timeout require_tls = var.require_tls - role_arn = aws_iam_role.this.arn + role_arn = local.iam_role_arn vpc_security_group_ids = var.vpc_security_group_ids vpc_subnet_ids = var.vpc_subnet_ids - auth = var.auth - tags = module.this.tags + + dynamic "auth" { + for_each = var.auth + + content { + auth_scheme = auth.value.auth_scheme + description = auth.value.description + iam_auth = auth.value.iam_auth + secret_arn = auth.value.secret_arn + } + } + + tags = module.this.tags } resource "aws_db_proxy_default_target_group" "this" { diff --git a/outputs.tf b/outputs.tf index 16cd7fc..b213da8 100644 --- a/outputs.tf +++ b/outputs.tf @@ -59,6 +59,6 @@ output "proxy_default_target_group_name" { } output "proxy_iam_role_arn" { - value = var.existing_iam_role_arn == null || var.existing_iam_role_arn == "" ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn + value = local.iam_role_arn description = "The ARN of the IAM role that the proxy uses to access secrets in AWS Secrets Manager" } From 066c9852755c95c6c31b8ebaebae52364d56cedc Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 16:33:17 -0500 Subject: [PATCH 10/19] Init --- iam.tf | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/iam.tf b/iam.tf index 292df7a..69dd4ef 100644 --- a/iam.tf +++ b/iam.tf @@ -12,7 +12,7 @@ data "aws_region" "this" {} # Get information about the KMS Key used to encrypt secrets in AWS Secrets Manager # If `kms_key_id` is not provided, use the AWS account's default CMK (the one named `aws/secretsmanager`) data "aws_kms_key" "this" { - key_id = var.kms_key_id != null && var.kms_key_id != "" ? var.kms_key_id : "aws/secretsmanager" + key_id = var.kms_key_id != null && var.kms_key_id != "" ? var.kms_key_id : "alias/aws/secretsmanager" } data "aws_iam_policy_document" "assume_role" { @@ -49,7 +49,9 @@ data "aws_iam_policy_document" "this" { "kms:Decrypt" ] - resources = local.kms_key_id + resources = [ + local.kms_key_id + ] condition { test = "StringEquals" From 49e2575f3fe56f22c7df2b0d366eba3154825a16 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 16:39:45 -0500 Subject: [PATCH 11/19] Init --- iam.tf | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/iam.tf b/iam.tf index 69dd4ef..86065a2 100644 --- a/iam.tf +++ b/iam.tf @@ -3,15 +3,18 @@ locals { iam_role_enabled = var.existing_iam_role_arn == null || var.existing_iam_role_arn == "" ? true : false asm_secret_arns = compact([for auth in var.auth : lookup(auth, "secret_arn", "")]) - kms_key_id = data.aws_kms_key.this.id + kms_key_arn = join("", data.aws_kms_key.this.*.arn) iam_role_arn = local.iam_role_enabled ? join("", aws_iam_role.this.*.arn) : var.existing_iam_role_arn } -data "aws_region" "this" {} +data "aws_region" "this" { + count = local.iam_role_enabled ? 1 : 0 +} # Get information about the KMS Key used to encrypt secrets in AWS Secrets Manager # If `kms_key_id` is not provided, use the AWS account's default CMK (the one named `aws/secretsmanager`) data "aws_kms_key" "this" { + count = local.iam_role_enabled ? 1 : 0 key_id = var.kms_key_id != null && var.kms_key_id != "" ? var.kms_key_id : "alias/aws/secretsmanager" } @@ -50,12 +53,12 @@ data "aws_iam_policy_document" "this" { ] resources = [ - local.kms_key_id + local.kms_key_arn ] condition { test = "StringEquals" - values = [format("secretsmanager.%s.amazonaws.com", data.aws_region.this.name)] + values = [format("secretsmanager.%s.amazonaws.com", join("", data.aws_region.this.*.name))] variable = "kms:ViaService" } } From e3394867052575c40d89628cfd9e21025e1e2d4f Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 17:02:46 -0500 Subject: [PATCH 12/19] Init --- examples/complete/fixtures.us-east-2.tfvars | 2 ++ examples/complete/main.tf | 29 +++------------------ examples/complete/sg.tf | 29 +++++++++++++++++++++ examples/complete/vpc.tf | 22 ++++++++++++++++ test/src/examples_complete_test.go | 4 +-- 5 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 examples/complete/sg.tf create mode 100644 examples/complete/vpc.tf diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index fb6c08d..c0c3188 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -16,6 +16,8 @@ database_name = "test_db" database_user = "admin_user" +database_password = "admin_password" + database_port = 5432 multi_az = false diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 7b1d395..b56643a 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -2,29 +2,6 @@ provider "aws" { region = var.region } -module "vpc" { - source = "cloudposse/vpc/aws" - version = "0.21.1" - - cidr_block = "172.16.0.0/16" - - context = module.this.context -} - -module "subnets" { - source = "cloudposse/dynamic-subnets/aws" - version = "0.38.0" - - availability_zones = var.availability_zones - vpc_id = module.vpc.vpc_id - igw_id = module.vpc.igw_id - cidr_block = module.vpc.vpc_cidr_block - nat_gateway_enabled = false - nat_instance_enabled = false - - context = module.this.context -} - resource "random_password" "admin_password" { count = var.database_password == "" || var.database_password == null ? 1 : 0 length = 33 @@ -50,6 +27,8 @@ locals { secret_arn = aws_secretsmanager_secret.rds_username_and_password.arn } ] + + security_group_id = aws_security_group.this.id } module "rds_instance" { @@ -71,7 +50,7 @@ module "rds_instance" { publicly_accessible = var.publicly_accessible vpc_id = module.vpc.vpc_id subnet_ids = module.subnets.private_subnet_ids - security_group_ids = [module.vpc.vpc_default_security_group_id] + security_group_ids = [local.security_group_id] apply_immediately = var.apply_immediately context = module.this.context @@ -94,7 +73,7 @@ module "rds_proxy" { db_instance_identifier = module.rds_instance.instance_id auth = local.auth - vpc_security_group_ids = [module.vpc.vpc_default_security_group_id] + vpc_security_group_ids = [local.security_group_id] vpc_subnet_ids = module.subnets.public_subnet_ids debug_logging = var.debug_logging diff --git a/examples/complete/sg.tf b/examples/complete/sg.tf new file mode 100644 index 0000000..d499c9d --- /dev/null +++ b/examples/complete/sg.tf @@ -0,0 +1,29 @@ +resource "aws_security_group" "this" { + name = module.this.id + description = "RDS Proxy Security Group" + revoke_rules_on_delete = true + vpc_id = module.vpc.vpc_id + tags = module.this.tags +} + +resource "aws_security_group_rule" "egress" { + description = "Allow all egress traffic" + type = "egress" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + security_group_id = aws_security_group.this.id +} + +resource "aws_security_group_rule" "ingress" { + description = "Allow all ingress traffic" + type = "ingress" + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + ipv6_cidr_blocks = ["::/0"] + security_group_id = aws_security_group.this.id +} diff --git a/examples/complete/vpc.tf b/examples/complete/vpc.tf new file mode 100644 index 0000000..4c4fab6 --- /dev/null +++ b/examples/complete/vpc.tf @@ -0,0 +1,22 @@ +module "vpc" { + source = "cloudposse/vpc/aws" + version = "0.21.1" + + cidr_block = "172.16.0.0/16" + + context = module.this.context +} + +module "subnets" { + source = "cloudposse/dynamic-subnets/aws" + version = "0.38.0" + + availability_zones = var.availability_zones + vpc_id = module.vpc.vpc_id + igw_id = module.vpc.igw_id + cidr_block = module.vpc.vpc_cidr_block + nat_gateway_enabled = false + nat_instance_enabled = false + + context = module.this.context +} diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 75ba771..0c54f4c 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -44,12 +44,12 @@ func TestExamplesComplete(t *testing.T) { // 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) + assert.Equal(t, []string{"172.16.0.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) + assert.Equal(t, []string{"172.16.96.0/19"}, publicSubnetCidrs) // Run `terraform output` to get the value of an output variable instanceId := terraform.Output(t, terraformOptions, "instance_id") From 019a4a1a40024a1cf3eac7f92d7c868912dddd92 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 17:10:47 -0500 Subject: [PATCH 13/19] Init --- examples/complete/fixtures.us-east-2.tfvars | 2 +- examples/complete/sg.tf | 12 ++++++++++-- test/src/examples_complete_test.go | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index c0c3188..a23acc5 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -1,6 +1,6 @@ region = "us-east-2" -availability_zones = ["us-east-2a"] +availability_zones = ["us-east-2a", "us-east-2b"] namespace = "eg" diff --git a/examples/complete/sg.tf b/examples/complete/sg.tf index d499c9d..6dd1dd8 100644 --- a/examples/complete/sg.tf +++ b/examples/complete/sg.tf @@ -1,9 +1,17 @@ +module "sg_label" { + source = "cloudposse/label/null" + version = "0.24.1" + + attributes = ["all", "traffic"] + context = module.this.context +} + resource "aws_security_group" "this" { - name = module.this.id + name = module.sg_label.id description = "RDS Proxy Security Group" revoke_rules_on_delete = true vpc_id = module.vpc.vpc_id - tags = module.this.tags + tags = module.sg_label.tags } resource "aws_security_group_rule" "egress" { diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 0c54f4c..75ba771 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -44,12 +44,12 @@ func TestExamplesComplete(t *testing.T) { // 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"}, privateSubnetCidrs) + 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"}, publicSubnetCidrs) + 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 instanceId := terraform.Output(t, terraformOptions, "instance_id") From f5912fd05f9cb3178d9fdf4b1a92b13fe390daea Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 17:17:22 -0500 Subject: [PATCH 14/19] Init --- .gitignore | 2 ++ examples/complete/fixtures.us-east-2.tfvars | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index b6abc3c..553a21b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ # Compiled files *.tfstate *.tfstate.backup +**.terraform.lock.hcl +**.terraform.tfstate.lock.info # Module directory .terraform diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index a23acc5..63eb201 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -44,3 +44,5 @@ db_parameter_group = "postgres11" # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Concepts.DBInstanceClass.html instance_class = "db.t2.small" + +engine_family = "POSTGRESQL" From be2111aada1d11cbd69a5cc45bb4b9c928b6e203 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 17:22:55 -0500 Subject: [PATCH 15/19] Init --- examples/complete/sg.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/complete/sg.tf b/examples/complete/sg.tf index 6dd1dd8..d6f5d0b 100644 --- a/examples/complete/sg.tf +++ b/examples/complete/sg.tf @@ -26,10 +26,10 @@ resource "aws_security_group_rule" "egress" { } resource "aws_security_group_rule" "ingress" { - description = "Allow all ingress traffic" + description = "Allow ingress traffic" type = "ingress" - from_port = 0 - to_port = 0 + from_port = var.database_port + to_port = var.database_port protocol = "-1" cidr_blocks = ["0.0.0.0/0"] ipv6_cidr_blocks = ["::/0"] From 65e8b98ea126e52ed0622a1c0cb996b70ac4ca56 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 19:11:11 -0500 Subject: [PATCH 16/19] Init --- examples/complete/variables.tf | 2 +- main.tf | 2 +- variables.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index b6f5d59..53ba73e 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -117,7 +117,7 @@ variable "require_tls" { variable "connection_borrow_timeout" { type = number default = 120 - description = "he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" + description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" } variable "init_query" { diff --git a/main.tf b/main.tf index 077ac10..49d1277 100644 --- a/main.tf +++ b/main.tf @@ -45,5 +45,5 @@ resource "aws_db_proxy_target" "this" { db_instance_identifier = var.db_instance_identifier db_cluster_identifier = var.db_cluster_identifier db_proxy_name = aws_db_proxy.this.name - target_group_name = aws_db_proxy_default_target_group.this.db_proxy_name + target_group_name = aws_db_proxy_default_target_group.this.name } diff --git a/variables.tf b/variables.tf index feb5bde..73bbe04 100644 --- a/variables.tf +++ b/variables.tf @@ -57,7 +57,7 @@ variable "db_cluster_identifier" { variable "connection_borrow_timeout" { type = number default = 120 - description = "he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" + description = "The number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions" } variable "init_query" { From b081871d2e7ccc31d67e28febc675f5dad3af2ab Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 20:52:31 -0500 Subject: [PATCH 17/19] Init --- examples/complete/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/complete/main.tf b/examples/complete/main.tf index b56643a..29e0cb3 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -49,7 +49,7 @@ module "rds_instance" { db_parameter_group = var.db_parameter_group publicly_accessible = var.publicly_accessible vpc_id = module.vpc.vpc_id - subnet_ids = module.subnets.private_subnet_ids + subnet_ids = module.subnets.public_subnet_ids security_group_ids = [local.security_group_id] apply_immediately = var.apply_immediately From 7781c689978e61e0a96829594f59c9facd0aca10 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 21:57:32 -0500 Subject: [PATCH 18/19] Init --- README.md | 2 +- docs/terraform.md | 2 +- examples/complete/main.tf | 6 ++--- examples/complete/sg.tf | 37 ------------------------------ test/src/examples_complete_test.go | 16 +++++++++++++ 5 files changed, 21 insertions(+), 42 deletions(-) delete mode 100644 examples/complete/sg.tf diff --git a/README.md b/README.md index 5d08d3c..cd5b6e1 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,7 @@ Available targets: | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | auth | Configuration blocks with authorization mechanisms to connect to the associated database instances or clusters |
list(object({
auth_scheme = string
description = string
iam_auth = string
secret_arn = string
}))
| n/a | yes | -| connection\_borrow\_timeout | he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | +| connection\_borrow\_timeout | The number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | db\_cluster\_identifier | DB cluster identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | | db\_instance\_identifier | DB instance identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | diff --git a/docs/terraform.md b/docs/terraform.md index 57ba9db..dc71f03 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -41,7 +41,7 @@ | additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | | attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | | auth | Configuration blocks with authorization mechanisms to connect to the associated database instances or clusters |
list(object({
auth_scheme = string
description = string
iam_auth = string
secret_arn = string
}))
| n/a | yes | -| connection\_borrow\_timeout | he number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | +| connection\_borrow\_timeout | The number of seconds for a proxy to wait for a connection to become available in the connection pool. Only applies when the proxy has opened its maximum number of connections and all connections are busy with client sessions | `number` | `120` | no | | 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,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | | db\_cluster\_identifier | DB cluster identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | | db\_instance\_identifier | DB instance identifier. Either `db_instance_identifier` or `db_cluster_identifier` should be specified and both should not be specified together | `string` | `null` | no | diff --git a/examples/complete/main.tf b/examples/complete/main.tf index 29e0cb3..45c6afb 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -28,7 +28,7 @@ locals { } ] - security_group_id = aws_security_group.this.id + security_group_id = module.vpc.vpc_default_security_group_id } module "rds_instance" { @@ -49,7 +49,7 @@ module "rds_instance" { db_parameter_group = var.db_parameter_group publicly_accessible = var.publicly_accessible vpc_id = module.vpc.vpc_id - subnet_ids = module.subnets.public_subnet_ids + subnet_ids = module.subnets.private_subnet_ids security_group_ids = [local.security_group_id] apply_immediately = var.apply_immediately @@ -74,7 +74,7 @@ module "rds_proxy" { db_instance_identifier = module.rds_instance.instance_id auth = local.auth vpc_security_group_ids = [local.security_group_id] - vpc_subnet_ids = module.subnets.public_subnet_ids + vpc_subnet_ids = module.subnets.private_subnet_ids debug_logging = var.debug_logging engine_family = var.engine_family diff --git a/examples/complete/sg.tf b/examples/complete/sg.tf deleted file mode 100644 index d6f5d0b..0000000 --- a/examples/complete/sg.tf +++ /dev/null @@ -1,37 +0,0 @@ -module "sg_label" { - source = "cloudposse/label/null" - version = "0.24.1" - - attributes = ["all", "traffic"] - context = module.this.context -} - -resource "aws_security_group" "this" { - name = module.sg_label.id - description = "RDS Proxy Security Group" - revoke_rules_on_delete = true - vpc_id = module.vpc.vpc_id - tags = module.sg_label.tags -} - -resource "aws_security_group_rule" "egress" { - description = "Allow all egress traffic" - type = "egress" - from_port = 0 - to_port = 0 - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - ipv6_cidr_blocks = ["::/0"] - security_group_id = aws_security_group.this.id -} - -resource "aws_security_group_rule" "ingress" { - description = "Allow ingress traffic" - type = "ingress" - from_port = var.database_port - to_port = var.database_port - protocol = "-1" - cidr_blocks = ["0.0.0.0/0"] - ipv6_cidr_blocks = ["::/0"] - security_group_id = aws_security_group.this.id -} diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 75ba771..f90e592 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -70,4 +70,20 @@ func TestExamplesComplete(t *testing.T) { subnetGroupId := terraform.Output(t, terraformOptions, "subnet_group_id") // Verify we're getting back the outputs we expect assert.Equal(t, "eg-test-rds-proxy"+randId, subnetGroupId) + + // Run `terraform output` to get the value of an output variable + proxyId := terraform.Output(t, terraformOptions, "proxy_id") + // Verify we're getting back the outputs we expect + assert.Equal(t, "eg-test-rds-proxy"+randId, proxyId) + + // Run `terraform output` to get the value of an output variable + proxyEndpoint := terraform.Output(t, terraformOptions, "proxy_endpoint") + // Verify we're getting back the outputs we expect + assert.Contains(t, proxyEndpoint, "eg-test-rds-proxy"+randId) + + // Run `terraform output` to get the value of an output variable + proxyTargetEndpoint := terraform.Output(t, terraformOptions, "proxy_target_endpoint") + instanceAddress := terraform.Output(t, terraformOptions, "instance_address") + // Verify we're getting back the outputs we expect + assert.Equal(t, proxyTargetEndpoint, instanceAddress) } From 3c9bf2ff8f60761105ce62772a76ffa1fabc56c9 Mon Sep 17 00:00:00 2001 From: aknysh Date: Sat, 6 Mar 2021 22:23:20 -0500 Subject: [PATCH 19/19] Init --- test/src/examples_complete_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index f90e592..d1f1dba 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -64,22 +64,22 @@ func TestExamplesComplete(t *testing.T) { // Run `terraform output` to get the value of an output variable parameterGroupId := terraform.Output(t, terraformOptions, "parameter_group_id") // Verify we're getting back the outputs we expect - assert.Equal(t, "eg-test-rds-proxy"+randId, parameterGroupId) + assert.Equal(t, "eg-test-rds-proxy-"+randId, parameterGroupId) // Run `terraform output` to get the value of an output variable subnetGroupId := terraform.Output(t, terraformOptions, "subnet_group_id") // Verify we're getting back the outputs we expect - assert.Equal(t, "eg-test-rds-proxy"+randId, subnetGroupId) + assert.Equal(t, "eg-test-rds-proxy-"+randId, subnetGroupId) // Run `terraform output` to get the value of an output variable proxyId := terraform.Output(t, terraformOptions, "proxy_id") // Verify we're getting back the outputs we expect - assert.Equal(t, "eg-test-rds-proxy"+randId, proxyId) + assert.Equal(t, "eg-test-rds-proxy-"+randId, proxyId) // Run `terraform output` to get the value of an output variable proxyEndpoint := terraform.Output(t, terraformOptions, "proxy_endpoint") // Verify we're getting back the outputs we expect - assert.Contains(t, proxyEndpoint, "eg-test-rds-proxy"+randId) + assert.Contains(t, proxyEndpoint, "eg-test-rds-proxy-"+randId) // Run `terraform output` to get the value of an output variable proxyTargetEndpoint := terraform.Output(t, terraformOptions, "proxy_target_endpoint")