77 Commits

Author SHA1 Message Date
Eugene Kolnick
42aeb4ade7 [skip ci] Refactor contexts (#82) 2023-03-29 09:34:08 -07:00
Ana Krivokapić
a7dd44730b Remove infraredgirl from CODEOWNERS (#80) 2022-08-19 14:28:14 +02:00
Rho
b08d79317e [skip ci] Remove dep from readme (#79) 2022-08-15 15:14:33 -07:00
Etiene Dalcol
922e6ca0a8 Add gruntwork-io/maintenance-tier-3-orion to CODEOWNERS (#76) 2022-01-26 18:18:01 +00:00
Etiene Dalcol
06fc8b53e6 Add sunset notice to README.md (#77) 2022-01-23 17:59:00 +00:00
Rob Morgan
fe2baced0f Add GitHub PR & Issue Templates (#73) 2021-11-19 16:23:28 +08:00
Marina
dbbdd5bdb3 Update CODEOWNERS (#70) 2021-11-04 13:55:26 +08:00
Ben Whaley
5134a7b36d Update to Terraform 1.x (#68)
* Bump tf to version 1.0
* Bump terraform-aws-ci
* Mark private key output as sensitive
* remove deprecated list() function
2021-08-23 14:19:02 +08:00
Zack Proser
6128b76064 Implement Terraform validate test (#63) 2021-07-14 13:01:51 -04:00
Ina Stoyanova
ceaf70539d replace gofmt with goimports (#64)
Co-authored-by: Marina Limeira <marina@gruntwork.io>
2021-07-14 15:58:47 +02:00
Marina
3984f43e18 Use ubuntu image and remove gcloud update (#65) 2021-07-14 14:58:45 +02:00
Rob Morgan
7a02a34de8 Terraform v0.14 update (#60) 2021-04-22 08:10:13 +08:00
Gruntwork CI
ad56d7b782 Update all repo names (#58)
Co-authored-by: Yevgeniy Brikman <brikis98@users.noreply.github.com>
2021-04-01 12:13:16 +01:00
Rob Morgan
0b560e6d0e Support instance deletion protection (#56)
also bump google provider version to 3.57.0
2021-02-23 11:49:03 +08:00
Rob Morgan
f2a6c5d401 add the circleci gcp context (#52) 2021-01-13 14:23:51 +08:00
Max Voitko
767e758db9 Add point in time recovery option in backend configuration (#50)
* Add point in time recovery option in backend coniguration

* Fix condition
2020-12-11 11:40:13 +08:00
Rob Morgan
e258f1468d Merge pull request #51 from gruntwork-io/tf13
Update repo to work with Terraform 0.13.x
2020-11-24 10:02:39 +08:00
Rob Morgan
30b3d6bbdc remove gae inputs and only apply location_preference if vars are specified 2020-11-13 11:15:41 +08:00
Rob Morgan
4c4ac71eaf bump google provider to version 3.43.0 2020-11-12 15:23:36 +08:00
Rob Morgan
9624bdaab8 update modules and examples for tf 0.13 2020-11-12 15:19:24 +08:00
Rob Morgan
f10e79399c update test deps 2020-11-12 15:18:54 +08:00
Rob Morgan
ffd50fab41 update circleci config 2020-11-12 15:09:42 +08:00
Rob Morgan
2a96df906e cleanup README 2020-11-12 13:05:12 +08:00
Rob Morgan
6210f1bd2d update precommit hook 2020-11-12 13:04:50 +08:00
Rob Morgan
3ca0fcd843 Merge pull request #47 from tomholford/master
Fix: remove deprecated quoted references
2020-11-12 12:53:33 +08:00
tomholford
c2dd590bb0 Fix: remove deprecated quoted references
Addresses this warning:

> In this context, references are expected literally rather than in quotes.
Terraform 0.11 and earlier required quotes, but quoted references are now
deprecated and will be removed in a future version of Terraform. Remove the
quotes surrounding this reference to silence this warning.
2020-07-23 18:36:59 +09:00
Yoriyasu Yano
18d024176a Merge pull request #45 from gruntwork-io/yori-fix-build
Fix build
2020-05-06 08:38:29 -05:00
Yoriyasu Yano
d125008281 bump terratest to version supporting go modules 2020-05-05 14:28:07 -05:00
Yoriyasu Yano
adc4c21a70 Fix pre-commit 2020-05-05 14:24:26 -05:00
Yoriyasu Yano
c936688983 Merge pull request #44 from BlueMedoraPublic/master
output service_account_email_address
2020-05-05 14:21:14 -05:00
Joseph Sirianni
34fd490821 output service_account_email_address 2020-04-28 16:23:29 -04:00
Petri Autero
010bf1820e [skip ci] Merge pull request #42 from gruntwork-io/autero1-patch-1
Update CODEOWNERS
2020-01-22 16:20:04 +02:00
Petri Autero
d627bc4c4c Update CODEOWNERS 2020-01-22 11:53:34 +02:00
autero1
44cfc53660 [skip ci] Merge pull request #41 from gruntwork-io/service_catalog
Add DB-specific readme's
2019-12-17 11:59:54 +02:00
autero1
ed2528a01b Merge pull request #40 from gruntwork-io/service_catalog
README updates
2019-12-17 11:55:36 +02:00
Petri Autero
a05c27d0dc [skip ci] Add DB-specific readme's 2019-12-17 11:53:47 +02:00
Petri Autero
5d1ab21f93 [skip ci] Prod deployment notes 2019-11-28 13:06:32 +02:00
Petri Autero
a1aac03fe8 [skip ci] Absolute link 2019-11-27 15:05:52 +02:00
Petri Autero
9dcc25b36d [skip ci] Restore tag badge 2019-11-27 14:55:07 +02:00
Petri Autero
fb90c4fae9 [skip ci] Change to open-source license 2019-11-27 14:54:20 +02:00
Petri Autero
d589e4ca5b [skip ci] Remove know issues from core concepts 2019-11-26 13:36:03 +02:00
Petri Autero
5c9645249c [skip ci] README updates 2019-11-26 13:31:40 +02:00
Rob Morgan
3b18b91411 Merge pull request #38 from gruntwork-io/tf12
Upgrade to Terraform 0.12
2019-06-26 16:38:38 +02:00
Rob Morgan
cb93ed3983 reorder cleanup funcs 2019-06-26 13:30:22 +02:00
Rob Morgan
62fcb11062 fix bug caught by tests and yoris feedback 2019-06-26 12:57:15 +02:00
Rob Morgan
b8e137b0bd fix syntax 2019-06-26 12:54:00 +02:00
Rob Morgan
81b187580c improve docs 2019-06-26 11:58:17 +02:00
Rob Morgan
fd76dce436 test against tf 0.12.2 2019-06-26 10:20:22 +02:00
Rob Morgan
925924a298 fix code 2019-06-25 18:08:10 +02:00
Rob Morgan
f25a4c7c8b fix root example 2019-06-25 18:03:00 +02:00
Rob Morgan
188cdfb0d7 fix dependency chain 2019-06-25 17:36:42 +02:00
Rob Morgan
5dc807e2f3 use nulls instead of empty strings 2019-06-25 17:35:52 +02:00
Rob Morgan
2a46a70ee8 improve syntax a bit 2019-06-25 17:23:38 +02:00
Rob Morgan
edd30bcea5 use nulls 2019-06-25 17:23:28 +02:00
Rob Morgan
0dfd8e28cf fix module deps 2019-06-25 16:55:10 +02:00
Rob Morgan
bb152b218d fix a few issues from the tests. bump version in docs 2019-06-25 16:42:31 +02:00
Rob Morgan
7713a67db3 change tests to use different options for non-replica and replica tests 2019-06-25 14:23:20 +02:00
Rob Morgan
1fdb587e0b fix a few things from tests 2019-06-25 13:53:18 +02:00
Rob Morgan
d5554b29f4 bump terratest version 2019-06-25 13:20:16 +02:00
Rob Morgan
1364203502 more tf12 changes 2019-06-25 12:15:46 +02:00
Rob Morgan
213f6e2e3a start modifying code 2019-06-21 18:23:15 +02:00
Rob Morgan
11a459bba1 bump required version 2019-06-21 17:54:45 +02:00
Rob Morgan
f91123778c bump tf ver on circleci 2019-06-21 17:52:36 +02:00
Rob Morgan
d5324fdc80 clean up readme a bit and add badge 2019-06-21 17:52:17 +02:00
Riley Karson
6aebe49bb0 Bump refs, use https (#37) 2019-06-05 09:59:44 -07:00
Rob Morgan
5f896dd55a Merge pull request #35 from gruntwork-io/version-bump
Bump version to a 0.12-compatible one.
2019-05-24 09:31:13 +02:00
Riley Karson
de09c6223a Bump version to a 0.12-compatible one. 2019-05-23 13:52:41 -07:00
autero1
400d8b6e13 [skip ci] Merge pull request #34 from gruntwork-io/fix_links
[skip ci] Fix links
2019-05-09 20:29:44 +03:00
Petri Autero
73a2344d6e [skip ci] Fix missing links 2019-05-09 19:53:22 +03:00
Petri Autero
6e2f52d9f6 [skip ci] Fix links 2019-05-09 17:56:33 +03:00
autero1
fdcd2e0c91 [skip ci] Merge pull request #33 from gruntwork-io/yorinasub17-patch-1
Update README.md
2019-05-09 17:08:17 +03:00
Yoriyasu Yano
33032faf64 Update README.md 2019-05-08 10:27:17 -07:00
autero1
24cb0ec259 Merge pull request #32 from gruntwork-io/module_dependencies
Standardizing dependencies to a list input
2019-05-04 09:03:41 +03:00
Petri Autero
2d11fdcf21 Revert back to local-exec 2019-05-03 11:50:42 +03:00
Riley Karson
7367df3e1e Update README to match Network module, add root example. (#31)
Update README to match Network module, add root example.
2019-05-02 09:05:25 -07:00
Petri Autero
efe37a1e64 Try to fix test failures 2019-05-02 14:22:52 +03:00
Petri Autero
6312a707c7 Standardizing to a list input 2019-05-02 10:34:20 +03:00
64 changed files with 2081 additions and 1138 deletions

View File

@@ -1,79 +1,66 @@
version: 2.1
defaults: &defaults
machine: true
machine:
image: ubuntu-2004:202104-01
env: &env
environment:
GRUNTWORK_INSTALLER_VERSION: v0.0.21
TERRATEST_LOG_PARSER_VERSION: v0.13.24
MODULE_CI_VERSION: v0.13.3
TERRAFORM_VERSION: 0.11.8
GRUNTWORK_INSTALLER_VERSION: v0.0.30
TERRATEST_LOG_PARSER_VERSION: v0.30.4
MODULE_CI_VERSION: v0.38.4
TERRAFORM_VERSION: 1.0.3
TERRAGRUNT_VERSION: NONE
PACKER_VERSION: NONE
GOLANG_VERSION: 1.11.2
GOLANG_VERSION: 1.16
GO111MODULE: auto
install_gruntwork_utils: &install_gruntwork_utils
name: install gruntwork utils
command: |
curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version "${GRUNTWORK_INSTALLER_VERSION}"
gruntwork-install --module-name "gruntwork-module-circleci-helpers" --repo "https://github.com/gruntwork-io/module-ci" --tag "${MODULE_CI_VERSION}"
gruntwork-install --binary-name "terratest_log_parser" --repo "https://github.com/gruntwork-io/terratest" --tag "${TERRATEST_LOG_PARSER_VERSION}"
configure-environment-for-gruntwork-module \
--circle-ci-2-machine-executor \
--terraform-version ${TERRAFORM_VERSION} \
--terragrunt-version ${TERRAGRUNT_VERSION} \
--packer-version ${PACKER_VERSION} \
--use-go-dep \
--go-version ${GOLANG_VERSION} \
--go-src-path test
version: 2
jobs:
build:
<<: *defaults
precommit:
<<: *env
docker:
- image: circleci/python:3.8.1
steps:
- checkout
- restore_cache:
keys:
- dep-v1-{{ checksum "test/Gopkg.lock" }}
# Install gruntwork utilities
- run:
<<: *install_gruntwork_utils
- save_cache:
key: dep-v1-{{ checksum "test/Gopkg.lock" }}
paths:
- ./test/vendor
name: install dependencies
command: |
curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version "${GRUNTWORK_INSTALLER_VERSION}"
gruntwork-install --module-name "gruntwork-module-circleci-helpers" --repo "https://github.com/gruntwork-io/terraform-aws-ci" --tag "${MODULE_CI_VERSION}"
configure-environment-for-gruntwork-module \
--terraform-version ${TERRAFORM_VERSION} \
--terragrunt-version NONE \
--packer-version NONE \
--go-version ${GOLANG_VERSION}
# Fail the build if the pre-commit hooks don't pass. Note: if you run pre-commit install locally, these hooks will
# execute automatically every time before you commit, ensuring the build never fails at this step!
- run: pip install pre-commit==1.11.2
- run: pre-commit install
- run: pre-commit run --all-files
- persist_to_workspace:
root: /home/circleci
paths:
- project
- terraform
- packer
- run:
command: |
pip install pre-commit==1.21.0 cfgv==2.0.1 zipp==1.1.0 yapf
go get golang.org/x/tools/cmd/goimports
export GOPATH=~/go/bin && export PATH=$PATH:$GOPATH
pre-commit install
pre-commit run --all-files
test:
<<: *defaults
<<: *env
steps:
- attach_workspace:
at: /home/circleci
- checkout
- run: echo 'export PATH=$HOME/terraform:$HOME/packer:$PATH' >> $BASH_ENV
- run:
<<: *install_gruntwork_utils
- run:
name: update gcloud
- run: &install_gruntwork_tooling
name: install gruntwork tooling
command: |
sudo apt-get remove -y google-cloud-sdk
sudo /opt/google-cloud-sdk/bin/gcloud --quiet components update
sudo /opt/google-cloud-sdk/bin/gcloud --quiet components update beta
sudo apt-get -y update
curl -Ls https://raw.githubusercontent.com/gruntwork-io/gruntwork-installer/master/bootstrap-gruntwork-installer.sh | bash /dev/stdin --version "${GRUNTWORK_INSTALLER_VERSION}"
gruntwork-install --module-name "gruntwork-module-circleci-helpers" --repo "https://github.com/gruntwork-io/terraform-aws-ci" --tag "${MODULE_CI_VERSION}"
gruntwork-install --module-name "git-helpers" --repo "https://github.com/gruntwork-io/terraform-aws-ci" --tag "${MODULE_CI_VERSION}"
gruntwork-install --binary-name "terratest_log_parser" --repo "https://github.com/gruntwork-io/terratest" --tag "${TERRATEST_LOG_PARSER_VERSION}"
configure-environment-for-gruntwork-module --go-src-path ./test --terraform-version ${TERRAFORM_VERSION} --terragrunt-version ${TERRAGRUNT_VERSION} --packer-version ${PACKER_VERSION} --go-version ${GOLANG_VERSION}
- run:
name: run tests
command: |
mkdir -p /tmp/logs
# required for gcloud to authenticate correctly
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=-
gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
@@ -82,11 +69,15 @@ jobs:
echo $GCLOUD_SERVICE_KEY > /tmp/gcloud.json
export GOOGLE_APPLICATION_CREDENTIALS="/tmp/gcloud.json"
# run the tests
run-go-tests --path test --timeout 60m | tee /tmp/logs/all.log
no_output_timeout: 3600s
mkdir -p /tmp/logs
run-go-tests --path test --timeout 2h | tee /tmp/logs/all.log
no_output_timeout: 1h
- run:
name: parse test output
command: terratest_log_parser --testlog /tmp/logs/all.log --outputdir /tmp/logs
when: always
- store_artifacts:
path: /tmp/logs
- store_test_results:
@@ -94,9 +85,21 @@ jobs:
workflows:
version: 2
build-and-test:
test:
jobs:
- build
- precommit:
context:
- GCP__automated-tests
- GITHUB__PAT__gruntwork-ci
filters:
tags:
only: /^v.*/
- test:
context:
- GCP__automated-tests
- GITHUB__PAT__gruntwork-ci
requires:
- build
- precommit
filters:
tags:
only: /^v.*/

33
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,33 @@
---
name: Bug report
about: Create a bug report to help us improve.
title: ''
labels: bug
assignees: ''
---
<!--
Have any questions? Check out the contributing docs at https://gruntwork.notion.site/Gruntwork-Coding-Methodology-02fdcd6e4b004e818553684760bf691e,
or ask in this issue and a Gruntwork core maintainer will be happy to help :)
-->
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior including the relevant Terraform/Terragrunt/Packer version number and any code snippets and module inputs you used.
```hcl
// paste code snippets here
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Nice to have**
- [ ] Terminal output
- [ ] Screenshots
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,22 @@
---
name: Feature request
about: Submit a feature request for this repo.
title: ''
labels: enhancement
assignees: ''
---
<!--
Have any questions? Check out the contributing docs at https://gruntwork.notion.site/Gruntwork-Coding-Methodology-02fdcd6e4b004e818553684760bf691e,
or ask in this issue and a Gruntwork core maintainer will be happy to help :)
-->
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

43
.github/pull_request_template.md vendored Normal file
View File

@@ -0,0 +1,43 @@
<!--
Have any questions? Check out the contributing docs at https://gruntwork.notion.site/Gruntwork-Coding-Methodology-02fdcd6e4b004e818553684760bf691e,
or ask in this Pull Request and a Gruntwork core maintainer will be happy to help :)
Note: Remember to add '[WIP]' to the beginning of the title if this PR is still a work-in-progress. Remove it when it is ready for review!
-->
## Description
<!-- Write a brief description of the changes introduced by this PR -->
### Documentation
<!--
If this is a feature PR, then where is it documented?
- If docs exist:
- Update any references, if relevant.
- If no docs exist:
- Create a stub for documentation including bullet points for how to use the feature, code snippets (including from happy path tests), etc.
-->
<!-- Important: Did you make any backward incompatible changes? If yes, then you must write a migration guide! -->
## TODOs
Please ensure all of these TODOs are completed before asking for a review.
- [ ] Ensure the branch is named correctly with the issue number. e.g: `feature/new-vpc-endpoints-955` or `bug/missing-count-param-434`.
- [ ] Update the docs.
- [ ] Keep the changes backward compatible where possible.
- [ ] Run the pre-commit checks successfully.
- [ ] Run the relevant tests successfully.
- [ ] Ensure any 3rd party code adheres with our [license policy](https://www.notion.so/gruntwork/Gruntwork-licenses-and-open-source-usage-policy-f7dece1f780341c7b69c1763f22b1378) or delete this line if its not applicable.
## Related Issues
<!--
Link to related issues, and issues fixed or partially addressed by this PR.
e.g. Fixes #1234
e.g. Addresses #1234
e.g. Related to #1234
-->

5
.gitignore vendored
View File

@@ -25,4 +25,7 @@ vendor
#VIM swap files
*.swp
.test-data
.test-data
# Ignore Terraform lock files, as we want to test the Terraform code in these repos with the latest provider
# versions.
.terraform.lock.hcl

View File

@@ -1,6 +1,7 @@
repos:
- repo: https://github.com/gruntwork-io/pre-commit
rev: v0.0.4
rev: v0.1.10
hooks:
- id: terraform-fmt
#
- id: goimports

View File

@@ -1 +1 @@
* @autero1 @robmorgan @yorinasub17
* @marinalimeira @robmorgan @ina-stoyanova @gruntwork-io/maintenance-tier-3-orion

View File

@@ -1,5 +1,9 @@
# Contribution Guidelines
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
Contributions to this Module are very welcome! We follow a fairly standard [pull request process](
https://help.github.com/articles/about-pull-requests/) for contributions, subject to the following guidelines:

120
README.md
View File

@@ -1,94 +1,110 @@
[![Maintained by Gruntwork.io](https://img.shields.io/badge/maintained%20by-gruntwork.io-%235849a6.svg)](https://gruntwork.io/?ref=repo_google_cloudsql)
### Sunset notice
We believe there is an opportunity to create a truly outstanding developer experience for deploying to the cloud, however developing this vision requires that we temporarily limit our focus to just one cloud. Gruntwork has hundreds of customers currently using AWS, so we have temporarily suspended our maintenance efforts on this repo. Once we have implemented and validated our vision for the developer experience on the cloud, we look forward to picking this up. In the meantime, you are welcome to use this code in accordance with the open source license, however we will not be responding to GitHub Issues or Pull Requests.
If you wish to be the maintainer for this project, we are open to considering that. Please contact us at support@gruntwork.io.
---
<!--
:type: service
:name: Google Cloud SQL
:description: Run MySQL or PostgreSQL on Google's Cloud SQL Service. Supports read replicas, multi-zone automatic failover, and automatic backup.
:icon: /_docs/cloud-sql-icon.png
:category: database
:cloud: gcp
:tags: database, mysql, postgresql
:license: open-source
:built-with: terraform
-->
# Cloud SQL Modules
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gruntwork-io/terraform-google-sql.svg?label=latest)](http://github.com/gruntwork-io/terraform-google-sql/releases/latest)
![Terraform Version](https://img.shields.io/badge/tf-%3E%3D1.0.x-blue.svg)
This repo contains modules for running relational databases such as MySQL and PostgreSQL on
[Google Cloud Platform (GCP)](https://cloud.google.com/) using [Cloud SQL](https://cloud.google.com/sql/).
## Quickstart
## Cloud SQL Architecture
If you want to quickly spin up a Cloud SQL database, you can run the example that is in the root of this repo. Check out
[postgres-private-ip example documentation](https://github.com/gruntwork-io/terraform-google-sql/blob/master/examples/postgres-private-ip)
for instructions.
![Cloud SQL Architecture](https://github.com/gruntwork-io/terraform-google-sql/blob/master/_docs/cloud-sql.png "Cloud SQL Architecture")
## What's in this repo
## Features
- Deploy a fully-managed relational database
- Supports MySQL and PostgreSQL
- Optional failover instances
- Optional read replicas
## Learn
This repo is a part of [the Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/), a collection of reusable, battle-tested, production ready infrastructure code. If youve never used the Infrastructure as Code Library before, make sure to read [How to use the Gruntwork Infrastructure as Code Library](https://gruntwork.io/guides/foundations/how-to-use-gruntwork-infrastructure-as-code-library/)!
### Core concepts
- [What is Cloud SQL](https://github.com/gruntwork-io/terraform-google-sql/blob/master/modules/cloud-sql/core-concepts.md#what-is-cloud-sql)
- [Cloud SQL documentation](https://cloud.google.com/sql/docs/)
- **[Designing Data Intensive Applications](https://dataintensive.net/)**: the best book weve found for understanding data systems, including relational databases, NoSQL, replication, sharding, consistency, and so on.
### Repo organisation
This repo has the following folder structure:
* [root](https://github.com/gruntwork-io/terraform-google-sql/tree/master): The root folder contains an example of how
- [root](https://github.com/gruntwork-io/terraform-google-sql/tree/master): The root folder contains an example of how
to deploy a private PostgreSQL instance in Cloud SQL. See [postgres-private-ip](https://github.com/gruntwork-io/terraform-google-sql/blob/master/examples/postgres-private-ip)
for the documentation.
* [modules](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules): This folder contains the
- [modules](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules): This folder contains the
main implementation code for this Module, broken down into multiple standalone submodules.
The primary module is:
* [cloud-sql](/modules/cloud-sql): Deploy a Cloud SQL [MySQL](https://cloud.google.com/sql/docs/mysql/) or
[PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database.
- [cloud-sql](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql): Deploy a Cloud SQL [MySQL](https://cloud.google.com/sql/docs/mysql/) or [PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database.
* [examples](https://github.com/gruntwork-io/terraform-google-sql/tree/master/examples): This folder contains
- [examples](https://github.com/gruntwork-io/terraform-google-sql/tree/master/examples): This folder contains
examples of how to use the submodules.
* [test](https://github.com/gruntwork-io/terraform-google-sql/tree/master/test): Automated tests for the submodules
- [test](https://github.com/gruntwork-io/terraform-google-sql/tree/master/test): Automated tests for the submodules
and examples.
## What is Cloud SQL?
## Deploy
Cloud SQL is Google's fully-managed database service that makes it easy to set up, maintain, manage, and administer
your relational databases on Google Cloud Platform. Cloud SQL automatically includes:
### Non-production deployment (quick start for learning)
* Data replication between multiple zones with automatic failover.
* Automated and on-demand backups, and point-in-time recovery.
* Data encryption on networks, database tables, temporary files, and backups.
* Secure external connections with the [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) or with the SSL/TLS protocol.
If you just want to try this repo out for experimenting and learning, check out the following resources:
You can learn more about Cloud SQL from [the official documentation](https://cloud.google.com/sql/docs/).
- [examples folder](https://github.com/gruntwork-io/terraform-google-sql/blob/master/examples): The `examples` folder contains sample code optimized for learning, experimenting, and testing (but not production usage).
## What's a Module?
### Production deployment
A Module is a canonical, reusable, best-practices definition for how to run a single piece of infrastructure, such
as a database or server cluster. Each Module is written using a combination of [Terraform](https://www.terraform.io/)
and scripts (mostly bash) and include automated tests, documentation, and examples. It is maintained both by the open
source community and companies that provide commercial support.
If you want to deploy this repo in production, check out the following resources:
Instead of figuring out the details of how to run a piece of infrastructure from scratch, you can reuse
existing code that has been proven in production. And instead of maintaining all that infrastructure code yourself,
you can leverage the work of the Module community to pick up infrastructure improvements through
a version number bump.
- [cloud-sql module in the GCP Reference Architecture](https://github.com/gruntwork-io/infrastructure-modules-google/tree/master/data-stores/cloud-sql):
Production-ready sample code from the GCP Reference Architecture. Note that the repository is private and accessible only with
Gruntwork subscription. To get access, [subscribe now](https://www.gruntwork.io/pricing/) or contact us at [support@gruntwork.io](mailto:support@gruntwork.io) for more information.
## Who maintains this Module?
## Manage
This Module and its Submodules are maintained by [Gruntwork](http://www.gruntwork.io/). Read the [Gruntwork Philosophy](/GRUNTWORK_PHILOSOPHY.md) document to learn more about how Gruntwork builds production grade infrastructure code. If you are looking for help or
commercial support, send an email to
[support@gruntwork.io](mailto:support@gruntwork.io?Subject=Google%20SQL%20Module).
### Day-to-day operations
Gruntwork can help with:
- [How to connect to a Cloud SQL instance](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-connect-to-the-database)
- [How to configure high availability](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-configure-high-availability)
- [How to secure the database instance](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-secure-the-database)
- [How to scale the database](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-secure-the-database)
* Setup, customization, and support for this Module.
* Modules and submodules for other types of infrastructure, such as VPCs, Docker clusters, databases, and continuous
integration.
* Modules and Submodules that meet compliance requirements, such as HIPAA.
* Consulting & Training on GCP, AWS, Terraform, and DevOps.
## Support
If you need help with this repo or anything else related to infrastructure or DevOps, Gruntwork offers [Commercial Support](https://gruntwork.io/support/) via Slack, email, and phone/video. If youre already a Gruntwork customer, hop on Slack and ask away! If not, [subscribe now](https://www.gruntwork.io/pricing/). If youre not sure, feel free to email us at [support@gruntwork.io](mailto:support@gruntwork.io).
## How do I contribute to this Module?
## Contributions
Contributions are very welcome! Check out the [Contribution Guidelines](/CONTRIBUTING.md) for instructions.
## How is this Module versioned?
This Module follows the principles of [Semantic Versioning](http://semver.org/). You can find each new release, along
with the changelog, in the [Releases Page](../../releases).
During initial development, the major version will be 0 (e.g., `0.x.y`), which indicates the code does not yet have a
stable API. Once we hit `1.0.0`, we will make every effort to maintain a backwards compatible API and use the MAJOR,
MINOR, and PATCH versions on each release to indicate any incompatibilities.
Contributions to this repo are very welcome and appreciated! If you find a bug or want to add a new feature or even contribute an entirely new module, we are very happy to accept pull requests, provide feedback, and run your changes through our automated test suite.
Please see [Contributing to the Gruntwork Infrastructure as Code Library](https://gruntwork.io/guides/foundations/how-to-use-gruntwork-infrastructure-as-code-library/#contributing-to-the-gruntwork-infrastructure-as-code-library) for instructions.
## License
Please see [LICENSE](/LICENSE) for how the code in this repo is licensed.
Please see [LICENSE](https://github.com/gruntwork-io/terraform-google-sql/blob/master/LICENSE.txt) for details on how the code in this repo is licensed.
Copyright &copy; 2019 Gruntwork, Inc.

BIN
_docs/cloud-sql-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
_docs/cloud-sql.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
_docs/mysql.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
_docs/postgresql.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -13,7 +13,7 @@ Creating the certificate while there are other operations ongoing will result in
To run this example, you need to:
1. Install [Terraform](https://www.terraform.io/).
1. Open up `vars.tf` and set secrets at the top of the file as environment variables and fill in any other variables in
1. Open up `variables.tf` and set secrets at the top of the file as environment variables and fill in any other variables in
the file that don't have defaults.
1. `terraform init`.
1. `terraform plan`.

View File

@@ -7,14 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -22,7 +30,7 @@ terraform {
# ------------------------------------------------------------------------------
resource "google_sql_ssl_cert" "client_cert" {
provider = "google-beta"
common_name = "${var.common_name}"
instance = "${var.database_instance_name}"
provider = google-beta
common_name = var.common_name
instance = var.database_instance_name
}

View File

@@ -4,11 +4,12 @@
output "client_ca_cert" {
description = "Certificate data for the client certificate."
value = "${google_sql_ssl_cert.client_cert.cert}"
value = google_sql_ssl_cert.client_cert.cert
}
# In real-world cases, the output for the private key should always be encrypted
output "client_private_key" {
description = "Private key associated with the client certificate."
value = "${google_sql_ssl_cert.client_cert.private_key}"
value = google_sql_ssl_cert.client_cert.private_key
sensitive = true
}

View File

@@ -5,17 +5,21 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "common_name" {
description = "The common name to be used in the certificate to identify the client. Constrained to [a-zA-Z.-_ ]+. Changing this forces a new resource to be created."
type = string
}
variable "database_instance_name" {
description = "The name of the Cloud SQL instance. Changing this forces a new resource to be created."
type = string
}

View File

@@ -1,6 +1,6 @@
# MySQL Cloud SQL Private IP Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
[MySQL](https://cloud.google.com/sql/docs/mysql/) database instance with a [private IP address](https://cloud.google.com/sql/docs/mysql/private-ip).
## How do you run this example?
@@ -18,4 +18,4 @@ When the templates are applied, Terraform will output the IP address of the inst
and the instance path for [connecting using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy).
Note that you cannot connect to the private IP instance from outside Google Cloud Platform.
If you want to experiment with connecting from your own workstation, see the [public IP example](../mysql-public-ip)
If you want to experiment with connecting from your own workstation, see the [public IP example](https://github.com/gruntwork-io/terraform-google-sql/tree/master/examples/mysql-public-ip)

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
private_network_name = "private-network-${random_id.name.hex}"
private_ip_name = "private-ip-${random_id.name.hex}"
}
@@ -39,26 +46,26 @@ locals {
# Simple network, auto-creates subnetworks
resource "google_compute_network" "private_network" {
provider = "google-beta"
name = "${local.private_network_name}"
provider = google-beta
name = local.private_network_name
}
# Reserve global internal address range for the peering
resource "google_compute_global_address" "private_ip_address" {
provider = "google-beta"
name = "${local.private_ip_name}"
provider = google-beta
name = local.private_ip_name
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = "${google_compute_network.private_network.self_link}"
network = google_compute_network.private_network.self_link
}
# Establish VPC network peering connection using the reserved address range
resource "google_service_networking_connection" "private_vpc_connection" {
provider = "google-beta"
network = "${google_compute_network.private_network.self_link}"
provider = google-beta
network = google_compute_network.private_network.self_link
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = ["${google_compute_global_address.private_ip_address.name}"]
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}
# ------------------------------------------------------------------------------
@@ -68,31 +75,36 @@ resource "google_service_networking_connection" "private_vpc_connection" {
module "mysql" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.mysql_version}"
machine_type = "${var.machine_type}"
engine = var.mysql_version
machine_type = var.machine_type
# To make it easier to test this example, we are disabling deletion protection so we can destroy the databases
# during the tests. By default, we recommend setting deletion_protection to true, to ensure database instances are
# not inadvertently destroyed.
deletion_protection = false
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = "${var.master_user_name}"
master_user_name = var.master_user_name
master_user_host = "%"
# Pass the private network link to the module
private_network = "${google_compute_network.private_network.self_link}"
private_network = google_compute_network.private_network.self_link
# Wait for the vpc connection to complete
wait_for = "${google_service_networking_connection.private_vpc_connection.network}"
dependencies = [google_service_networking_connection.private_vpc_connection.network]
# Set auto-increment flags to test the
# feature during automated testing

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.mysql.master_instance_name}"
value = module.mysql.master_instance_name
}
output "master_ip_addresses" {
description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${module.mysql.master_ip_addresses}"
value = module.mysql.master_ip_addresses
}
output "master_private_ip" {
description = "The private IPv4 address of the master instance."
value = "${module.mysql.master_private_ip_address}"
value = module.mysql.master_private_ip_address
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.mysql.master_instance}"
value = module.mysql.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.mysql.master_proxy_connection}"
value = module.mysql.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -33,10 +33,10 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.mysql.db_name}"
value = module.mysql.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.mysql.db}"
value = module.mysql.db
}

View File

@@ -5,45 +5,55 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "mysql_version" {
description = "The engine version of the database, e.g. `MYSQL_5_6` or `MYSQL_5_7`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
default = "MYSQL_5_7"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}

View File

@@ -1,6 +1,6 @@
# MySQL Cloud SQL Public IP Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
[MySQL](https://cloud.google.com/sql/docs/mysql/) database instance with a [public IP address](https://cloud.google.com/sql/docs/mysql/connect-external-app#appaccessIP).
## How do you run this example?

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
}
# ------------------------------------------------------------------------------
@@ -38,34 +45,37 @@ locals {
module "mysql" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.mysql_version}"
machine_type = "${var.machine_type}"
engine = var.mysql_version
machine_type = var.machine_type
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = "${var.master_user_name}"
master_user_name = var.master_user_name
master_user_host = "%"
# To make it easier to test this example, we are giving the servers public IP addresses and allowing inbound
# connections from anywhere. In real-world usage, your servers should live in private subnets, only have private IP
# addresses, and only allow access from specific trusted networks, servers or applications in your VPC.
# To make it easier to test this example, we are giving the instances public IP addresses and allowing inbound
# connections from anywhere. We also disable deletion protection so we can destroy the databases during the tests.
# In real-world usage, your instances should live in private subnets, only have private IP addresses, and only allow
# access from specific trusted networks, servers or applications in your VPC. By default, we recommend setting
# deletion_protection to true, to ensure database instances are not inadvertently destroyed.
enable_public_internet_access = true
deletion_protection = false
# Default setting for this is 'false' in 'variables.tf'
# In the test cases, we're setting this to true, to test forced SSL.
require_ssl = "${var.require_ssl}"
require_ssl = var.require_ssl
authorized_networks = [
{

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.mysql.master_instance_name}"
value = module.mysql.master_instance_name
}
output "master_public_ip" {
description = "The public IPv4 address of the master instance."
value = "${module.mysql.master_public_ip_address}"
value = module.mysql.master_public_ip_address
}
output "master_ca_cert" {
value = "${module.mysql.master_ca_cert}"
value = module.mysql.master_ca_cert
description = "The CA Certificate used to connect to the SQL Instance via SSL"
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.mysql.master_instance}"
value = module.mysql.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.mysql.master_proxy_connection}"
value = module.mysql.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -33,10 +33,10 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.mysql.db_name}"
value = module.mysql.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.mysql.db}"
value = module.mysql.db
}

View File

@@ -5,52 +5,63 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "mysql_version" {
description = "The engine version of the database, e.g. `MYSQL_5_6` or `MYSQL_5_7`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
default = "MYSQL_5_7"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}
# When configuring a public IP instance, you should only allow secure connections
# For testing purposes, we're initially allowing unsecured connections.
variable "require_ssl" {
description = "True if the instance should require SSL/TLS for users connecting over IP. Note: SSL/TLS is needed to provide security when you connect to Cloud SQL using IP addresses. If you are connecting to your instance only by using the Cloud SQL Proxy or the Java Socket Library, you do not need to configure your instance to use SSL/TLS."
type = bool
default = false
}

View File

@@ -1,6 +1,10 @@
# MySQL Cloud SQL HA Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [High Availability](https://cloud.google.com/sql/docs/mysql/configure-ha) [Google Cloud SQL](https://cloud.google.com/sql/)
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [High Availability](https://cloud.google.com/sql/docs/mysql/configure-ha) [Google Cloud SQL](https://cloud.google.com/sql/)
[MySQL](https://cloud.google.com/sql/docs/mysql/) database cluster with a [public IP](https://cloud.google.com/sql/docs/mysql/connect-external-app#appaccessIP) and failover and [read replicas](https://cloud.google.com/sql/docs/mysql/replication/).
## How do you run this example?

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
private_network_name = "private-network-${random_id.name.hex}"
private_ip_name = "private-ip-${random_id.name.hex}"
}
@@ -40,23 +47,26 @@ locals {
module "mysql" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.mysql_version}"
machine_type = "${var.machine_type}"
engine = var.mysql_version
machine_type = var.machine_type
master_zone = "${var.master_zone}"
master_zone = var.master_zone
# To make it easier to test this example, we are giving the servers public IP addresses and allowing inbound
# connections from anywhere. In real-world usage, your servers should live in private subnets, only have private IP
# addresses, and only allow access from specific trusted networks, servers or applications in your VPC.
# To make it easier to test this example, we are giving the instances public IP addresses and allowing inbound
# connections from anywhere. We also disable deletion protection so we can destroy the databases during the tests.
# In real-world usage, your instances should live in private subnets, only have private IP addresses, and only allow
# access from specific trusted networks, servers or applications in your VPC. By default, we recommend setting
# deletion_protection to true, to ensure database instances are not inadvertently destroyed.
enable_public_internet_access = true
deletion_protection = false
authorized_networks = [
{
@@ -67,19 +77,19 @@ module "mysql" {
# Indicate that we want to create a failover replica
enable_failover_replica = true
mysql_failover_replica_zone = "${var.failover_replica_zone}"
mysql_failover_replica_zone = var.failover_replica_zone
# Indicate we want read replicas to be created
num_read_replicas = "${var.num_read_replicas}"
read_replica_zones = ["${var.read_replica_zones}"]
num_read_replicas = var.num_read_replicas
read_replica_zones = var.read_replica_zones
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = "${var.master_user_name}"
master_user_name = var.master_user_name
master_user_host = "%"
# Set auto-increment flags to test the

View File

@@ -4,22 +4,22 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.mysql.master_instance_name}"
value = module.mysql.master_instance_name
}
output "master_public_ip" {
description = "The public IPv4 address of the master instance."
value = "${module.mysql.master_public_ip_address}"
value = module.mysql.master_public_ip_address
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.mysql.master_instance}"
value = module.mysql.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.mysql.master_proxy_connection}"
value = module.mysql.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -28,12 +28,12 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.mysql.db_name}"
value = module.mysql.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.mysql.db}"
value = module.mysql.db
}
# ------------------------------------------------------------------------------
@@ -42,22 +42,22 @@ output "db" {
output "failover_instance" {
description = "Self link to the failover instance"
value = "${module.mysql.failover_instance}"
value = module.mysql.failover_instance
}
output "failover_instance_name" {
description = "The name of the failover database instance"
value = "${module.mysql.failover_instance_name}"
value = module.mysql.failover_instance_name
}
output "failover_public_ip" {
description = "The public IPv4 address of the failover instance"
value = "${module.mysql.failover_public_ip_address}"
value = module.mysql.failover_public_ip_address
}
output "failover_proxy_connection" {
description = "Failover instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.mysql.failover_proxy_connection}"
value = module.mysql.failover_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -66,22 +66,22 @@ output "failover_proxy_connection" {
output "read_replica_instance_names" {
description = "List of names for the read replica instances"
value = ["${module.mysql.read_replica_instance_names}"]
value = module.mysql.read_replica_instance_names
}
output "read_replica_public_ips" {
description = "List of public IPv4 addresses of the read replica instances"
value = ["${module.mysql.read_replica_public_ip_addresses}"]
value = module.mysql.read_replica_public_ip_addresses
}
output "read_replica_instances" {
description = "List of self links to the read replica instances"
value = ["${module.mysql.read_replica_instances}"]
value = module.mysql.read_replica_instances
}
output "read_replica_proxy_connections" {
description = "List of read replica instance paths for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = ["${module.mysql.read_replica_proxy_connections}"]
value = module.mysql.read_replica_proxy_connections
}
# Although we don't use the values, this output highlights the JSON encoded output we use in certain
@@ -89,5 +89,5 @@ output "read_replica_proxy_connections" {
# See https://github.com/hashicorp/terraform/issues/17048
output "read_replica_server_ca_certs" {
description = "JSON encoded list of CA Certificates used to connect to the read replica instances via SSL"
value = "${module.mysql.read_replica_server_ca_certs}"
value = module.mysql.read_replica_server_ca_certs
}

View File

@@ -5,27 +5,32 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in (e.g. 'us-central1')."
type = string
}
variable "master_zone" {
description = "The preferred zone for the master instance (e.g. 'us-central1-a'). Must be different than 'failover_replica_zone'."
type = string
}
variable "failover_replica_zone" {
description = "The preferred zone for the failover instance (e.g. 'us-central1-b'). Must be different than 'master_zone'."
type = string
}
variable "num_read_replicas" {
description = "The number of read replicas to create. Cloud SQL will replicate all data from the master to these replicas, which you can use to horizontally scale read traffic."
type = number
}
variable "read_replica_zones" {
description = "A list of compute zones where read replicas should be created. List size should match 'num_read_replicas'"
type = "list"
type = list(string)
# Example:
# default = ["us-central1-b", "us-central1-c"]
@@ -34,36 +39,44 @@ variable "read_replica_zones" {
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "mysql_version" {
description = "The engine version of the database, e.g. `MYSQL_5_6` or `MYSQL_5_7`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
default = "MYSQL_5_7"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}

View File

@@ -1,6 +1,10 @@
# PostgreSQL Cloud SQL Private IP Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
[PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database instance with a [private IP address](https://cloud.google.com/sql/docs/postgres/private-ip).
## How do you run this example?
@@ -18,4 +22,4 @@ When the templates are applied, Terraform will output the IP address of the inst
and the instance path for [connecting using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/postgres/sql-proxy).
Note that you cannot connect to the private IP instance from outside Google Cloud Platform.
If you want to experiment with connecting from your own workstation, see the [public IP example](../postgres-public-ip)
If you want to experiment with connecting from your own workstation, see the [public IP example](https://github.com/gruntwork-io/terraform-google-sql/tree/master/examples/postgres-public-ip)

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
private_network_name = "private-network-${random_id.name.hex}"
private_ip_name = "private-ip-${random_id.name.hex}"
}
@@ -39,26 +46,26 @@ locals {
# Simple network, auto-creates subnetworks
resource "google_compute_network" "private_network" {
provider = "google-beta"
name = "${local.private_network_name}"
provider = google-beta
name = local.private_network_name
}
# Reserve global internal address range for the peering
resource "google_compute_global_address" "private_ip_address" {
provider = "google-beta"
name = "${local.private_ip_name}"
provider = google-beta
name = local.private_ip_name
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = "${google_compute_network.private_network.self_link}"
network = google_compute_network.private_network.self_link
}
# Establish VPC network peering connection using the reserved address range
resource "google_service_networking_connection" "private_vpc_connection" {
provider = "google-beta"
network = "${google_compute_network.private_network.self_link}"
provider = google-beta
network = google_compute_network.private_network.self_link
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = ["${google_compute_global_address.private_ip_address.name}"]
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}
# ------------------------------------------------------------------------------
@@ -68,31 +75,36 @@ resource "google_service_networking_connection" "private_vpc_connection" {
module "postgres" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.postgres_version}"
machine_type = "${var.machine_type}"
engine = var.postgres_version
machine_type = var.machine_type
# To make it easier to test this example, we are disabling deletion protection so we can destroy the databases
# during the tests. By default, we recommend setting deletion_protection to true, to ensure database instances are
# not inadvertently destroyed.
deletion_protection = false
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = "${var.master_user_name}"
master_user_name = var.master_user_name
master_user_host = "%"
# Pass the private network link to the module
private_network = "${google_compute_network.private_network.self_link}"
private_network = google_compute_network.private_network.self_link
# Wait for the vpc connection to complete
wait_for = "${google_service_networking_connection.private_vpc_connection.network}"
dependencies = [google_service_networking_connection.private_vpc_connection.network]
custom_labels = {
test-id = "postgres-private-ip-example"

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.postgres.master_instance_name}"
value = module.postgres.master_instance_name
}
output "master_ip_addresses" {
description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${module.postgres.master_ip_addresses}"
value = module.postgres.master_ip_addresses
}
output "master_private_ip" {
description = "The private IPv4 address of the master instance"
value = "${module.postgres.master_private_ip_address}"
value = module.postgres.master_private_ip_address
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.postgres.master_instance}"
value = module.postgres.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.postgres.master_proxy_connection}"
value = module.postgres.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -33,10 +33,10 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.postgres.db_name}"
value = module.postgres.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.postgres.db}"
value = module.postgres.db
}

View File

@@ -5,45 +5,55 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "postgres_version" {
description = "The engine version of the database, e.g. `POSTGRES_9_6`. See https://cloud.google.com/sql/docs/db-versions for supported versions."
type = string
default = "POSTGRES_9_6"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}

View File

@@ -1,6 +1,10 @@
# PostgreSQL Cloud SQL Public IP Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [Google Cloud SQL](https://cloud.google.com/sql/)
[PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database instance with a [public IP address](https://cloud.google.com/sql/docs/postgres/connect-external-app#appaccessIP).
## How do you run this example?

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
}
# ------------------------------------------------------------------------------
@@ -38,34 +45,35 @@ locals {
module "postgres" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.postgres_version}"
machine_type = "${var.machine_type}"
engine = var.postgres_version
machine_type = var.machine_type
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# 'master_user_name' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = var.master_user_name
master_user_name = "${var.master_user_name}"
master_user_host = "%"
# To make it easier to test this example, we are giving the servers public IP addresses and allowing inbound
# connections from anywhere. In real-world usage, your servers should live in private subnets, only have private IP
# addresses, and only allow access from specific trusted networks, servers or applications in your VPC.
# To make it easier to test this example, we are giving the instances public IP addresses and allowing inbound
# connections from anywhere. We also disable deletion protection so we can destroy the databases during the tests.
# In real-world usage, your instances should live in private subnets, only have private IP addresses, and only allow
# access from specific trusted networks, servers or applications in your VPC. By default, we recommend setting
# deletion_protection to true, to ensure database instances are not inadvertently destroyed.
enable_public_internet_access = true
deletion_protection = false
# Default setting for this is 'false' in 'variables.tf'
# In the test cases, we're setting this to true, to test forced SSL.
require_ssl = "${var.require_ssl}"
require_ssl = var.require_ssl
authorized_networks = [
{

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.postgres.master_instance_name}"
value = module.postgres.master_instance_name
}
output "master_public_ip" {
description = "The public IPv4 address of the master instance"
value = "${module.postgres.master_public_ip_address}"
value = module.postgres.master_public_ip_address
}
output "master_ca_cert" {
description = "The CA Certificate used to connect to the SQL Instance via SSL"
value = "${module.postgres.master_ca_cert}"
value = module.postgres.master_ca_cert
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.postgres.master_instance}"
value = module.postgres.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.postgres.master_proxy_connection}"
value = module.postgres.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -33,10 +33,10 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.postgres.db_name}"
value = module.postgres.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.postgres.db}"
value = module.postgres.db
}

View File

@@ -5,52 +5,63 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "postgres_version" {
description = "The engine version of the database, e.g. `POSTGRES_9_6`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
default = "POSTGRES_9_6"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}
# When configuring a public IP instance, you should only allow secure connections
# For testing purposes, we're initially allowing unsecured connections.
variable "require_ssl" {
description = "True if the instance should require SSL/TLS for users connecting over IP. Note: SSL/TLS is needed to provide security when you connect to Cloud SQL using IP addresses. If you are connecting to your instance only by using the Cloud SQL Proxy or the Java Socket Library, you do not need to configure your instance to use SSL/TLS."
type = bool
default = false
}

View File

@@ -1,6 +1,10 @@
# PostgreSQL Cloud SQL HA Example
This folder contains an example of how to use the [Cloud SQL module](/modules/cloud-sql) to create a [High Availability](https://cloud.google.com/sql/docs/postgres/high-availability) [Google Cloud SQL](https://cloud.google.com/sql/)
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
This folder contains an example of how to use the [Cloud SQL module](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql) to create a [High Availability](https://cloud.google.com/sql/docs/postgres/high-availability) [Google Cloud SQL](https://cloud.google.com/sql/)
[PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database cluster with a [public IP address](https://cloud.google.com/sql/docs/postgres/connect-external-app#appaccessIP) and a [read replica](https://cloud.google.com/sql/docs/postgres/replication/).
## How do you run this example?

View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = var.name_override == null ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
private_network_name = "private-network-${random_id.name.hex}"
private_ip_name = "private-ip-${random_id.name.hex}"
}
@@ -40,23 +47,26 @@ locals {
module "postgres" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "../../modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.postgres_version}"
machine_type = "${var.machine_type}"
engine = var.postgres_version
machine_type = var.machine_type
master_zone = "${var.master_zone}"
master_zone = var.master_zone
# To make it easier to test this example, we are giving the servers public IP addresses and allowing inbound
# connections from anywhere. In real-world usage, your servers should live in private subnets, only have private IP
# addresses, and only allow access from specific trusted networks, servers or applications in your VPC.
# To make it easier to test this example, we are giving the instances public IP addresses and allowing inbound
# connections from anywhere. We also disable deletion protection so we can destroy the databases during the tests.
# In real-world usage, your instances should live in private subnets, only have private IP addresses, and only allow
# access from specific trusted networks, servers or applications in your VPC. By default, we recommend setting
# deletion_protection to true, to ensure database instances are not inadvertently destroyed.
enable_public_internet_access = true
deletion_protection = false
authorized_networks = [
{
@@ -69,17 +79,15 @@ module "postgres" {
enable_failover_replica = true
# Indicate we want read replicas to be created
num_read_replicas = "${var.num_read_replicas}"
read_replica_zones = ["${var.read_replica_zones}"]
num_read_replicas = var.num_read_replicas
read_replica_zones = var.read_replica_zones
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# 'master_user_name' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_name = "${var.master_user_name}"
master_user_host = "%"
master_user_password = var.master_user_password
master_user_name = var.master_user_name
custom_labels = {
test-id = "postgres-replicas-example"

View File

@@ -4,22 +4,22 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.postgres.master_instance_name}"
value = module.postgres.master_instance_name
}
output "master_public_ip" {
description = "The public IPv4 address of the master instance"
value = "${module.postgres.master_public_ip_address}"
value = module.postgres.master_public_ip_address
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.postgres.master_instance}"
value = module.postgres.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.postgres.master_proxy_connection}"
value = module.postgres.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -28,12 +28,12 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.postgres.db_name}"
value = module.postgres.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.postgres.db}"
value = module.postgres.db
}
# ------------------------------------------------------------------------------
@@ -42,22 +42,22 @@ output "db" {
output "read_replica_instance_names" {
description = "List of names for the read replica instances"
value = ["${module.postgres.read_replica_instance_names}"]
value = module.postgres.read_replica_instance_names
}
output "read_replica_public_ips" {
description = "List of public IPv4 addresses of the read replica instances"
value = ["${module.postgres.read_replica_public_ip_addresses}"]
value = module.postgres.read_replica_public_ip_addresses
}
output "read_replica_instances" {
description = "List of self links to the read replica instances"
value = ["${module.postgres.read_replica_instances}"]
value = module.postgres.read_replica_instances
}
output "read_replica_proxy_connections" {
description = "List of read replica instance paths for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = ["${module.postgres.read_replica_proxy_connections}"]
value = module.postgres.read_replica_proxy_connections
}
# Although we don't use the values, this output highlights the JSON encoded output we use in certain
@@ -65,5 +65,5 @@ output "read_replica_proxy_connections" {
# See https://github.com/hashicorp/terraform/issues/17048
output "read_replica_server_ca_certs" {
description = "JSON encoded list of CA Certificates used to connect to the read replica instances via SSL"
value = "${module.postgres.read_replica_server_ca_certs}"
value = module.postgres.read_replica_server_ca_certs
}

View File

@@ -5,27 +5,32 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in (e.g. 'us-central1')."
type = string
}
variable "master_zone" {
description = "The preferred zone for the master instance (e.g. 'us-central1-a'). Must be different than 'failover_replica_zone'."
type = string
}
variable "failover_replica_zone" {
description = "The preferred zone for the failover instance (e.g. 'us-central1-b'). Must be different than 'master_zone'."
type = string
}
variable "num_read_replicas" {
description = "The number of read replicas to create. Cloud SQL will replicate all data from the master to these replicas, which you can use to horizontally scale read traffic."
type = number
}
variable "read_replica_zones" {
description = "A list of compute zones where read replicas should be created. List size should match 'num_read_replicas'"
type = "list"
type = list(string)
# Example:
# default = ["us-central1-b", "us-central1-c"]
@@ -34,36 +39,44 @@ variable "read_replica_zones" {
# Note, after a name db instance is used, it cannot be reused for up to one week.
variable "name_prefix" {
description = "The name prefix for the database instance. Will be appended with a random string. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
# OPTIONAL PARAMETERS
# Generally, these values won't need to be changed.
# ---------------------------------------------------------------------------------------------------------------------
variable "postgres_version" {
description = "The engine version of the database, e.g. `POSTGRES_9_6`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
default = "POSTGRES_9_6"
}
variable "machine_type" {
description = "The machine type to use, see https://cloud.google.com/sql/pricing for more details"
type = string
default = "db-f1-micro"
}
variable "db_name" {
description = "Name for the db"
type = string
default = "default"
}
variable "name_override" {
description = "You may optionally override the name_prefix + random string by specifying an override"
default = ""
type = string
default = null
}

59
main.tf
View File

@@ -7,15 +7,22 @@
# ------------------------------------------------------------------------------
provider "google-beta" {
version = "~> 2.1.0"
region = "${var.region}"
project = "${var.project}"
project = var.project
region = var.region
}
# Use Terraform 0.10.x so that we can take advantage of Terraform GCP functionality as a separate provider via
# https://github.com/terraform-providers/terraform-provider-google
terraform {
required_version = ">= 0.10.3"
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
required_providers {
google-beta = {
source = "hashicorp/google-beta"
version = "~> 3.57.0"
}
}
}
# ------------------------------------------------------------------------------
@@ -28,7 +35,7 @@ resource "random_id" "name" {
locals {
# If name_override is specified, use that - otherwise use the name_prefix with a random string
instance_name = "${length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override}"
instance_name = length(var.name_override) == 0 ? format("%s-%s", var.name_prefix, random_id.name.hex) : var.name_override
private_network_name = "private-network-${random_id.name.hex}"
private_ip_name = "private-ip-${random_id.name.hex}"
}
@@ -39,26 +46,26 @@ locals {
# Simple network, auto-creates subnetworks
resource "google_compute_network" "private_network" {
provider = "google-beta"
name = "${local.private_network_name}"
provider = google-beta
name = local.private_network_name
}
# Reserve global internal address range for the peering
resource "google_compute_global_address" "private_ip_address" {
provider = "google-beta"
name = "${local.private_ip_name}"
provider = google-beta
name = local.private_ip_name
purpose = "VPC_PEERING"
address_type = "INTERNAL"
prefix_length = 16
network = "${google_compute_network.private_network.self_link}"
network = google_compute_network.private_network.self_link
}
# Establish VPC network peering connection using the reserved address range
resource "google_service_networking_connection" "private_vpc_connection" {
provider = "google-beta"
network = "${google_compute_network.private_network.self_link}"
provider = google-beta
network = google_compute_network.private_network.self_link
service = "servicenetworking.googleapis.com"
reserved_peering_ranges = ["${google_compute_global_address.private_ip_address.name}"]
reserved_peering_ranges = [google_compute_global_address.private_ip_address.name]
}
# ------------------------------------------------------------------------------
@@ -68,31 +75,31 @@ resource "google_service_networking_connection" "private_vpc_connection" {
module "postgres" {
# When using these modules in your own templates, you will need to use a Git URL with a ref attribute that pins you
# to a specific version of the modules, such as the following example:
# source = "git::git@github.com:gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.1.0"
# source = "github.com/gruntwork-io/terraform-google-sql.git//modules/cloud-sql?ref=v0.2.0"
source = "./modules/cloud-sql"
project = "${var.project}"
region = "${var.region}"
name = "${local.instance_name}"
db_name = "${var.db_name}"
project = var.project
region = var.region
name = local.instance_name
db_name = var.db_name
engine = "${var.postgres_version}"
machine_type = "${var.machine_type}"
engine = var.postgres_version
machine_type = var.machine_type
# These together will construct the master_user privileges, i.e.
# 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'.
# These should typically be set as the environment variable TF_VAR_master_user_password, etc.
# so you don't check these into source control."
master_user_password = "${var.master_user_password}"
master_user_password = var.master_user_password
master_user_name = "${var.master_user_name}"
master_user_name = var.master_user_name
master_user_host = "%"
# Pass the private network link to the module
private_network = "${google_compute_network.private_network.self_link}"
private_network = google_compute_network.private_network.self_link
# Wait for the vpc connection to complete
wait_for = "${google_service_networking_connection.private_vpc_connection.network}"
dependencies = [google_service_networking_connection.private_vpc_connection.network]
custom_labels = {
test-id = "postgres-private-ip-example"

View File

@@ -0,0 +1,20 @@
<!--
:type: service
:name: MySQL
:description: Deploy and manage MySQL on GCP using Google's Cloud SQL Service
:icon: /_docs/mysql.png
:category: database
:cloud: gcp
:tags: data, database, sql, mysql
:license: open-source
:built-with: terraform
-->
# MySQL
[![Maintained by Gruntwork.io](https://img.shields.io/badge/maintained%20by-gruntwork.io-%235849a6.svg)](https://gruntwork.io/?ref=repo_google_cloudsql)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gruntwork-io/terraform-google-sql.svg?label=latest)](http://github.com/gruntwork-io/terraform-google-sql/releases/latest)
![Terraform Version](https://img.shields.io/badge/tf-%3E%3D1.0.x-blue.svg)
This module deploys MySQL on top of Google's Cloud SQL Service. The cluster is managed by GCP and automatically handles
standby failover, read replicas, backups, patching, and encryption.
[README.md](./README.md)

View File

@@ -0,0 +1,20 @@
<!--
:type: service
:name: PostgreSQL
:description: Deploy and manage PostgreSQL on GCP using Google's Cloud SQL Service
:icon: /_docs/postgresql.png
:category: database
:cloud: gcp
:tags: data, database, sql, postgresql
:license: open-source
:built-with: terraform
-->
# PostgreSQL
[![Maintained by Gruntwork.io](https://img.shields.io/badge/maintained%20by-gruntwork.io-%235849a6.svg)](https://gruntwork.io/?ref=repo_google_cloudsql)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gruntwork-io/terraform-google-sql.svg?label=latest)](http://github.com/gruntwork-io/terraform-google-sql/releases/latest)
![Terraform Version](https://img.shields.io/badge/tf-%3E%3D1.0.x-blue.svg)
This module deploys PostgreSQL on top of Google's Cloud SQL Service. The cluster is managed by GCP and automatically handles
standby failover, read replicas, backups, patching, and encryption.
[README.md](./README.md)

View File

@@ -1,84 +1,85 @@
# Cloud SQL Module
[![Maintained by Gruntwork.io](https://img.shields.io/badge/maintained%20by-gruntwork.io-%235849a6.svg)](https://gruntwork.io/?ref=repo_google_cloudsql)
[![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gruntwork-io/terraform-google-sql.svg?label=latest)](http://github.com/gruntwork-io/terraform-google-sql/releases/latest)
![Terraform Version](https://img.shields.io/badge/tf-%3E%3D1.0.x-blue.svg)
<!-- NOTE: We use absolute linking here instead of relative linking, because the terraform registry does not support
relative linking correctly.
-->
This module creates a [Google Cloud SQL](https://cloud.google.com/sql/) cluster.
The cluster is managed by Google, automating backups, replication, patches, and updates.
This module helps you run [MySQL](https://cloud.google.com/sql/docs/mysql/) and [PostgreSQL](https://cloud.google.com/sql/docs/postgres/) databases in [Google Cloud](https://cloud.google.com/).
## How do you use this module?
## Cloud SQL Architecture
See the [examples](/examples) folder for an example.
![Cloud SQL Architecture](https://github.com/gruntwork-io/terraform-google-sql/blob/master/_docs/cloud-sql.png "Cloud SQL Architecture")
## How do you configure this module?
## Features
This module allows you to configure a number of parameters, such as high availability, backup windows, maintenance window and replicas.
For a list of all available variables and their descriptions, see [variables.tf](./variables.tf).
- Deploy a fully-managed relational database
- Supports MySQL and PostgreSQL
- Optional failover instances
- Optional read replicas
## How do you connect to the database?
## Learn
**Cloud SQL instances are created in a producer network (a VPC network internal to Google). They are not created in your VPC network. See https://cloud.google.com/sql/docs/mysql/private-ip**
You can use both public IP and private IP to connect to a Cloud SQL instance.
Neither connection method affects the other; you must protect the public IP connection whether the instance is configured to use private IP or not.
This repo is a part of [the Gruntwork Infrastructure as Code Library](https://gruntwork.io/infrastructure-as-code-library/), a collection of reusable, battle-tested, production ready infrastructure code. If youve never used the Infrastructure as Code Library before, make sure to read [How to use the Gruntwork Infrastructure as Code Library](https://gruntwork.io/guides/foundations/how-to-use-gruntwork-infrastructure-as-code-library/)!
You can also use the [Cloud SQL Proxy for MySQL](https://cloud.google.com/sql/docs/mysql/sql-proxy) and [Cloud SQL Proxy for PostgreSQL](https://cloud.google.com/sql/docs/postgres/sql-proxy)
to connect to an instance that is also configured to use private IP. The proxy can connect using either the private IP address or a public IP address.
### Core concepts
This module provides the connection details as [Terraform output
variables](https://www.terraform.io/intro/getting-started/outputs.html). Use the public / private addresses depending on your configuration:
- [What is Cloud SQL](https://github.com/gruntwork-io/terraform-google-sql/blob/master/modules/cloud-sql/core-concepts.md#what-is-cloud-sql)
- [Cloud SQL documentation](https://cloud.google.com/sql/docs/)
- **[Designing Data Intensive Applications](https://dataintensive.net/)**: the best book weve found for understanding data systems, including relational databases, NoSQL, replication, sharding, consistency, and so on.
### Repo organisation
1. **Master Public IP Address** `master_public_ip_address`: The public IPv4 address of the master instance.
1. **Master Private IP Address** `master_private_ip_address`: The private IPv4 address of the master instance.
1. **Master Proxy connection** `master_proxy_connection`: Instance path for connecting with Cloud SQL Proxy; see [Connecting mysql Client Using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy).
1. **Read Replica Public IP Addresses** `read_replica_public_ip_addresses`: A list of read replica public IP addresses in the cluster. Use these addresses for reads (see "How do you scale this database?" below).
1. **Read Replica Private IP Addresses** `read_replica_private_ip_addresses`: A list of read replica private IP addresses in the cluster. Use these addresses for reads (see "How do you scale this database?" below).
1. **Read Replica Proxy Connections** `read_replica_proxy_connections`: A list of instance paths for connecting with Cloud SQL Proxy; see [Connecting Using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy).
This repo has the following folder structure:
- [root](https://github.com/gruntwork-io/terraform-google-sql/tree/master): The root folder contains an example of how
to deploy a private PostgreSQL instance in Cloud SQL. See [postgres-private-ip](https://github.com/gruntwork-io/terraform-google-sql/blob/master/examples/postgres-private-ip)
for the documentation.
You can programmatically extract these variables in your Terraform templates and pass them to other resources.
You'll also see the variables at the end of each `terraform apply` call or if you run `terraform output`.
- [modules](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules): This folder contains the
main implementation code for this Module, broken down into multiple standalone submodules.
For full connectivity options and detailed documentation, see [Connecting to Cloud SQL MySQL from External Applications](https://cloud.google.com/sql/docs/mysql/connect-external-app) and [Connecting to Cloud SQL PostgreSQL from External Applications](https://cloud.google.com/sql/docs/postgres/external-connection-methods).
The primary module is:
## How do you configure High Availability?
- [cloud-sql](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql): Deploy a Cloud SQL [MySQL](https://cloud.google.com/sql/docs/mysql/) or [PostgreSQL](https://cloud.google.com/sql/docs/postgres/) database.
- [examples](https://github.com/gruntwork-io/terraform-google-sql/tree/master/examples): This folder contains
examples of how to use the submodules.
You can enable High Availability using the `enable_failover_replica` input variable.
- [test](https://github.com/gruntwork-io/terraform-google-sql/tree/master/test): Automated tests for the submodules
and examples.
### High Availability for MySQL
## Deploy
The configuration is made up of a primary instance (master) in the primary zone (`master_zone` input variable) and a failover replica in the secondary zone (`failover_replica_zone` input variable).
The failover replica is configured with the same database flags, users and passwords, authorized applications and networks, and databases as the primary instance.
### Non-production deployment (quick start for learning)
For full details about MySQL High Availability, see https://cloud.google.com/sql/docs/mysql/high-availability
If you just want to try this repo out for experimenting and learning, check out the following resources:
### High Availability for PostgreSQL
- [examples folder](https://github.com/gruntwork-io/terraform-google-sql/blob/master/examples): The `examples` folder contains sample code optimized for learning, experimenting, and testing (but not production usage).
A Cloud SQL PostgreSQL instance configured for HA is also called a _regional instance_ and is located in a primary and secondary zone within the configured region. Within a regional instance,
the configuration is made up of a primary instance (master) and a standby instance. You control the primary zone for the master instance
with input variable `master_zone` and Google will automatically place the standby instance in another zone.
### Production deployment
For full details about PostgreSQL High Availability, see https://cloud.google.com/sql/docs/postgres/high-availability
If you want to deploy this repo in production, check out the following resources:
- [cloud-sql module in the GCP Reference Architecture](https://github.com/gruntwork-io/infrastructure-modules-google/tree/master/data-stores/cloud-sql):
Production-ready sample code from the GCP Reference Architecture. Note that the repository is private and accessible only with
Gruntwork subscription. To get access, [subscribe now](https://www.gruntwork.io/pricing/) or contact us at [support@gruntwork.io](mailto:support@gruntwork.io) for more information.
## How do you secure this database?
## Manage
Cloud SQL customer data is encrypted when stored in database tables, temporary files, and backups.
External connections can be encrypted by using SSL, or by using the Cloud SQL Proxy, which automatically encrypts traffic to and from the database.
If you do not use the proxy, you can enforce SSL for external connections using the `require_ssl` input variable.
### Day-to-day operations
For further information, see https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases and
https://cloud.google.com/sql/faq#encryption
## How do you scale this database?
* **Storage**: Cloud SQL manages storage for you, automatically growing cluster volume up to 10TB You can set the
initial disk size using the `disk_size` input variable.
* **Vertical scaling**: To scale vertically (i.e. bigger DB instances with more CPU and RAM), use the `machine_type`
input variable. For a list of Cloud SQL Machine Types, see [Cloud SQL Pricing](https://cloud.google.com/sql/pricing#2nd-gen-pricing).
* **Horizontal scaling**: To scale horizontally, you can add more replicas using the `num_read_replicas` and `read_replica_zones` input variables,
and the module will automatically deploy the new instances, sync them to the master, and make them available as read
replicas.
- [How to connect to a Cloud SQL instance](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-connect-to-the-database)
- [How to configure high availability](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-configure-high-availability)
- [How to secure the database instance](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-secure-the-database)
- [How to scale the database](https://github.com/gruntwork-io/terraform-google-sql/tree/master/modules/cloud-sql/core-concepts.md#how-do-you-secure-the-database)
## Known Issues
@@ -88,12 +89,18 @@ Due to limitations on the current `terraform` provider for Google, it is not pos
See https://github.com/terraform-providers/terraform-provider-google/issues/2446
### Read Replica and IP Addresses Outputs
## Support
Retrieving and outputting distinct values from list of maps is not possible with resources using `count` prior to `terraform 0.12`.
Instead we have to output the values JSON encoded - for example `read_replica_server_ca_certs`. For full details of the outputs and
their format, see [outputs.tf](./outputs.tf).
If you need help with this repo or anything else related to infrastructure or DevOps, Gruntwork offers [Commercial Support](https://gruntwork.io/support/) via Slack, email, and phone/video. If youre already a Gruntwork customer, hop on Slack and ask away! If not, [subscribe now](https://www.gruntwork.io/pricing/). If youre not sure, feel free to email us at [support@gruntwork.io](mailto:support@gruntwork.io).
See https://github.com/hashicorp/terraform/issues/17048
## Contributions
Contributions to this repo are very welcome and appreciated! If you find a bug or want to add a new feature or even contribute an entirely new module, we are very happy to accept pull requests, provide feedback, and run your changes through our automated test suite.
Please see [Contributing to the Gruntwork Infrastructure as Code Library](https://gruntwork.io/guides/foundations/how-to-use-gruntwork-infrastructure-as-code-library/#contributing-to-the-gruntwork-infrastructure-as-code-library) for instructions.
## License
Please see [LICENSE](https://github.com/gruntwork-io/terraform-google-sql/blob/master/LICENSE.txt) for details on how the code in this repo is licensed.
Copyright &copy; 2019 Gruntwork, Inc.

View File

@@ -8,14 +8,14 @@
locals {
# Replica proxy connection info
failover_proxy_connection = "${join("",data.template_file.failover_proxy_connection.*.rendered)}"
failover_proxy_connection = join("", data.template_file.failover_proxy_connection.*.rendered)
# Replica certificate info
failover_certificate = "${join("",data.template_file.failover_certificate.*.rendered)}"
failover_certificate_common_name = "${join("",data.template_file.failover_certificate_common_name.*.rendered)}"
failover_certificate_create_time = "${join("",data.template_file.failover_certificate_create_time.*.rendered)}"
failover_certificate_expiration_time = "${join("",data.template_file.failover_certificate_expiration_time.*.rendered)}"
failover_certificate_sha1_fingerprint = "${join("",data.template_file.failover_certificate_sha1_fingerprint.*.rendered)}"
failover_certificate = join("", data.template_file.failover_certificate.*.rendered)
failover_certificate_common_name = join("", data.template_file.failover_certificate_common_name.*.rendered)
failover_certificate_create_time = join("", data.template_file.failover_certificate_create_time.*.rendered)
failover_certificate_expiration_time = join("", data.template_file.failover_certificate_expiration_time.*.rendered)
failover_certificate_sha1_fingerprint = join("", data.template_file.failover_certificate_sha1_fingerprint.*.rendered)
}
# ------------------------------------------------------------------------------
@@ -23,7 +23,7 @@ locals {
# ------------------------------------------------------------------------------
data "template_file" "failover_proxy_connection" {
count = "${local.actual_failover_replica_count}"
count = local.actual_failover_replica_count
template = "${var.project}:${var.region}:${google_sql_database_instance.failover_replica.0.name}"
}
@@ -36,28 +36,28 @@ data "template_file" "failover_proxy_connection" {
# ------------------------------------------------------------------------------
data "template_file" "failover_certificate" {
count = "${local.actual_failover_replica_count}"
template = "${google_sql_database_instance.failover_replica.0.server_ca_cert.0.cert}"
count = local.actual_failover_replica_count
template = google_sql_database_instance.failover_replica.0.server_ca_cert.0.cert
}
data "template_file" "failover_certificate_common_name" {
count = "${local.actual_failover_replica_count}"
template = "${google_sql_database_instance.failover_replica.0.server_ca_cert.0.common_name}"
count = local.actual_failover_replica_count
template = google_sql_database_instance.failover_replica.0.server_ca_cert.0.common_name
}
data "template_file" "failover_certificate_create_time" {
count = "${local.actual_failover_replica_count}"
template = "${google_sql_database_instance.failover_replica.0.server_ca_cert.0.create_time}"
count = local.actual_failover_replica_count
template = google_sql_database_instance.failover_replica.0.server_ca_cert.0.create_time
}
data "template_file" "failover_certificate_expiration_time" {
count = "${local.actual_failover_replica_count}"
template = "${google_sql_database_instance.failover_replica.0.server_ca_cert.0.expiration_time}"
count = local.actual_failover_replica_count
template = google_sql_database_instance.failover_replica.0.server_ca_cert.0.expiration_time
}
data "template_file" "failover_certificate_sha1_fingerprint" {
count = "${local.actual_failover_replica_count}"
template = "${google_sql_database_instance.failover_replica.0.server_ca_cert.0.sha1_fingerprint}"
count = local.actual_failover_replica_count
template = google_sql_database_instance.failover_replica.0.server_ca_cert.0.sha1_fingerprint
}
# ------------------------------------------------------------------------------
@@ -65,6 +65,6 @@ data "template_file" "failover_certificate_sha1_fingerprint" {
# ------------------------------------------------------------------------------
data "template_file" "read_replica_proxy_connection" {
count = "${var.num_read_replicas}"
count = var.num_read_replicas
template = "${var.project}:${var.region}:${google_sql_database_instance.read_replica.*.name[count.index]}"
}

View File

@@ -0,0 +1,79 @@
# Core Cloud SQL Concepts
## What is Cloud SQL?
Cloud SQL is Google's fully-managed database service that makes it easy to set up, maintain, manage, and administer
your relational databases on Google Cloud Platform. Cloud SQL automatically includes:
- Data replication between multiple zones with automatic failover.
- Automated and on-demand backups, and point-in-time recovery.
- Data encryption on networks, database tables, temporary files, and backups.
- Secure external connections with the [Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/sql-proxy) or with the SSL/TLS protocol.
You can learn more about Cloud SQL from [the official documentation](https://cloud.google.com/sql/docs/).
## How do you connect to the database?
**Cloud SQL instances are created in a producer network (a VPC network internal to Google). They are not created in your VPC network. See https://cloud.google.com/sql/docs/mysql/private-ip**
You can use both public IP and private IP to connect to a Cloud SQL instance.
Neither connection method affects the other; you must protect the public IP connection whether the instance is configured to use private IP or not.
You can also use the [Cloud SQL Proxy for MySQL](https://cloud.google.com/sql/docs/mysql/sql-proxy) and [Cloud SQL Proxy for PostgreSQL](https://cloud.google.com/sql/docs/postgres/sql-proxy)
to connect to an instance that is also configured to use private IP. The proxy can connect using either the private IP address or a public IP address.
This module provides the connection details as [Terraform output
variables](https://www.terraform.io/intro/getting-started/outputs.html). Use the public / private addresses depending on your configuration:
1. **Master Public IP Address** `master_public_ip_address`: The public IPv4 address of the master instance.
1. **Master Private IP Address** `master_private_ip_address`: The private IPv4 address of the master instance.
1. **Master Proxy connection** `master_proxy_connection`: Instance path for connecting with Cloud SQL Proxy; see [Connecting mysql Client Using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy).
1. **Read Replica Public IP Addresses** `read_replica_public_ip_addresses`: A list of read replica public IP addresses in the cluster. Use these addresses for reads (see "How do you scale this database?" below).
1. **Read Replica Private IP Addresses** `read_replica_private_ip_addresses`: A list of read replica private IP addresses in the cluster. Use these addresses for reads (see "How do you scale this database?" below).
1. **Read Replica Proxy Connections** `read_replica_proxy_connections`: A list of instance paths for connecting with Cloud SQL Proxy; see [Connecting Using the Cloud SQL Proxy](https://cloud.google.com/sql/docs/mysql/connect-admin-proxy).
You can programmatically extract these variables in your Terraform templates and pass them to other resources.
You'll also see the variables at the end of each `terraform apply` call or if you run `terraform output`.
For full connectivity options and detailed documentation, see [Connecting to Cloud SQL MySQL from External Applications](https://cloud.google.com/sql/docs/mysql/connect-external-app) and [Connecting to Cloud SQL PostgreSQL from External Applications](https://cloud.google.com/sql/docs/postgres/external-connection-methods).
## How do you configure High Availability?
You can enable High Availability using the `enable_failover_replica` input variable.
### High Availability for MySQL
The configuration is made up of a primary instance (master) in the primary zone (`master_zone` input variable) and a failover replica in the secondary zone (`failover_replica_zone` input variable).
The failover replica is configured with the same database flags, users and passwords, authorized applications and networks, and databases as the primary instance.
For full details about MySQL High Availability, see https://cloud.google.com/sql/docs/mysql/high-availability
### High Availability for PostgreSQL
A Cloud SQL PostgreSQL instance configured for HA is also called a _regional instance_ and is located in a primary and secondary zone within the configured region. Within a regional instance,
the configuration is made up of a primary instance (master) and a standby instance. You control the primary zone for the master instance
with input variable `master_zone` and Google will automatically place the standby instance in another zone.
For full details about PostgreSQL High Availability, see https://cloud.google.com/sql/docs/postgres/high-availability
## How do you secure the database?
Cloud SQL customer data is encrypted when stored in database tables, temporary files, and backups.
External connections can be encrypted by using SSL, or by using the Cloud SQL Proxy, which automatically encrypts traffic to and from the database.
If you do not use the proxy, you can enforce SSL for external connections using the `require_ssl` input variable.
For further information, see https://cloud.google.com/blog/products/gcp/best-practices-for-securing-your-google-cloud-databases and
https://cloud.google.com/sql/faq#encryption
## How do you scale the database?
* **Storage**: Cloud SQL manages storage for you, automatically growing cluster volume up to 10TB You can set the
initial disk size using the `disk_size` input variable.
* **Vertical scaling**: To scale vertically (i.e. bigger DB instances with more CPU and RAM), use the `machine_type`
input variable. For a list of Cloud SQL Machine Types, see [Cloud SQL Pricing](https://cloud.google.com/sql/pricing#2nd-gen-pricing).
* **Horizontal scaling**: To scale horizontally, you can add more replicas using the `num_read_replicas` and `read_replica_zones` input variables,
and the module will automatically deploy the new instances, sync them to the master, and make them available as read
replicas.

View File

@@ -4,6 +4,13 @@
# election, replication, failover, backups, patching, and encryption.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
terraform {
# This module is now only being tested with Terraform 1.0.x. However, to make upgrading easier, we are setting
# 0.12.26 as the minimum version, as that version added support for required_providers with source URLs, making it
# forwards compatible with 1.0.x code.
required_version = ">= 0.12.26"
}
# ------------------------------------------------------------------------------
# PREPARE LOCALS
#
@@ -13,13 +20,13 @@
locals {
# Determine the engine type
is_postgres = "${replace(var.engine, "POSTGRES", "") != var.engine}"
is_mysql = "${replace(var.engine, "MYSQL", "") != var.engine}"
is_postgres = replace(var.engine, "POSTGRES", "") != var.engine
is_mysql = replace(var.engine, "MYSQL", "") != var.engine
# Calculate actuals, so we get expected behavior for each engine
actual_binary_log_enabled = "${local.is_postgres ? false : var.mysql_binary_log_enabled}"
actual_availability_type = "${local.is_postgres && var.enable_failover_replica ? "REGIONAL" : "ZONAL"}"
actual_failover_replica_count = "${local.is_postgres ? 0 : var.enable_failover_replica ? 1 : 0}"
actual_binary_log_enabled = local.is_postgres ? false : var.mysql_binary_log_enabled
actual_availability_type = local.is_postgres && var.enable_failover_replica ? "REGIONAL" : "ZONAL"
actual_failover_replica_count = local.is_postgres ? 0 : var.enable_failover_replica ? 1 : 0
}
# ------------------------------------------------------------------------------
@@ -30,59 +37,79 @@ locals {
# ------------------------------------------------------------------------------
resource "google_sql_database_instance" "master" {
depends_on = ["null_resource.wait_for"]
depends_on = [null_resource.dependency_getter]
provider = "google-beta"
name = "${var.name}"
project = "${var.project}"
region = "${var.region}"
database_version = "${var.engine}"
provider = google-beta
name = var.name
project = var.project
region = var.region
database_version = var.engine
# Whether or not to allow Terraform to destroy the instance.
deletion_protection = var.deletion_protection
settings {
tier = "${var.machine_type}"
activation_policy = "${var.activation_policy}"
authorized_gae_applications = ["${var.authorized_gae_applications}"]
disk_autoresize = "${var.disk_autoresize}"
tier = var.machine_type
activation_policy = var.activation_policy
disk_autoresize = var.disk_autoresize
ip_configuration {
authorized_networks = ["${var.authorized_networks}"]
ipv4_enabled = "${var.enable_public_internet_access}"
private_network = "${var.private_network}"
require_ssl = "${var.require_ssl}"
dynamic "authorized_networks" {
for_each = var.authorized_networks
content {
name = lookup(authorized_networks.value, "name", null)
value = authorized_networks.value.value
}
}
ipv4_enabled = var.enable_public_internet_access
private_network = var.private_network
require_ssl = var.require_ssl
}
location_preference {
follow_gae_application = "${var.follow_gae_application}"
zone = "${var.master_zone}"
dynamic "location_preference" {
for_each = var.master_zone == null ? [] : [var.master_zone]
content {
zone = location_preference.value
}
}
backup_configuration {
binary_log_enabled = "${local.actual_binary_log_enabled}"
enabled = "${var.backup_enabled}"
start_time = "${var.backup_start_time}"
binary_log_enabled = local.actual_binary_log_enabled
enabled = var.backup_enabled
start_time = var.backup_start_time
point_in_time_recovery_enabled = local.is_postgres ? var.postgres_point_in_time_recovery_enabled : null
}
maintenance_window {
day = "${var.maintenance_window_day}"
hour = "${var.maintenance_window_hour}"
update_track = "${var.maintenance_track}"
day = var.maintenance_window_day
hour = var.maintenance_window_hour
update_track = var.maintenance_track
}
disk_size = "${var.disk_size}"
disk_type = "${var.disk_type}"
database_flags = ["${var.database_flags}"]
availability_type = "${local.actual_availability_type}"
disk_size = var.disk_size
disk_type = var.disk_type
availability_type = local.actual_availability_type
user_labels = "${var.custom_labels}"
dynamic "database_flags" {
for_each = var.database_flags
content {
name = database_flags.value.name
value = database_flags.value.value
}
}
user_labels = var.custom_labels
}
# Default timeouts are 10 minutes, which in most cases should be enough.
# Sometimes the database creation can, however, take longer, so we
# increase the timeouts slightly.
timeouts {
create = "${var.resource_timeout}"
delete = "${var.resource_timeout}"
update = "${var.resource_timeout}"
create = var.resource_timeout
delete = var.resource_timeout
update = var.resource_timeout
}
}
@@ -91,31 +118,39 @@ resource "google_sql_database_instance" "master" {
# ------------------------------------------------------------------------------
resource "google_sql_database" "default" {
depends_on = ["google_sql_database_instance.master"]
depends_on = [google_sql_database_instance.master]
name = "${var.db_name}"
project = "${var.project}"
instance = "${google_sql_database_instance.master.name}"
charset = "${var.db_charset}"
collation = "${var.db_collation}"
name = var.db_name
project = var.project
instance = google_sql_database_instance.master.name
charset = var.db_charset
collation = var.db_collation
}
resource "google_sql_user" "default" {
depends_on = ["google_sql_database.default"]
depends_on = [google_sql_database.default]
name = "${var.master_user_name}"
project = "${var.project}"
instance = "${google_sql_database_instance.master.name}"
host = "${var.master_user_host}"
password = "${var.master_user_password}"
project = var.project
name = var.master_user_name
instance = google_sql_database_instance.master.name
# Postgres users don't have hosts, so the API will ignore this value which causes Terraform to attempt
# to recreate the user each time.
# See https://github.com/terraform-providers/terraform-provider-google/issues/1526 for more information.
host = local.is_postgres ? null : var.master_user_host
password = var.master_user_password
}
# ------------------------------------------------------------------------------
# CREATE A NULL RESOURCE TO EMULATE DEPENDENCIES
# SET MODULE DEPENDENCY RESOURCE
# This works around a terraform limitation where we can not specify module dependencies natively.
# See https://github.com/hashicorp/terraform/issues/1178 for more discussion.
# By resolving and computing the dependencies list, we are able to make all the resources in this module depend on the
# resources backing the values in the dependencies list.
# ------------------------------------------------------------------------------
resource "null_resource" "wait_for" {
triggers = {
instance = "${var.wait_for}"
resource "null_resource" "dependency_getter" {
provisioner "local-exec" {
command = "echo ${length(var.dependencies)}"
}
}
@@ -124,22 +159,25 @@ resource "null_resource" "wait_for" {
# ------------------------------------------------------------------------------
resource "google_sql_database_instance" "failover_replica" {
count = "${local.actual_failover_replica_count}"
count = local.actual_failover_replica_count
depends_on = [
"google_sql_database_instance.master",
"google_sql_database.default",
"google_sql_user.default",
google_sql_database_instance.master,
google_sql_database.default,
google_sql_user.default,
]
provider = "google-beta"
provider = google-beta
name = "${var.name}-failover"
project = "${var.project}"
region = "${var.region}"
database_version = "${var.engine}"
project = var.project
region = var.region
database_version = var.engine
# The name of the instance that will act as the master in the replication setup.
master_instance_name = "${google_sql_database_instance.master.name}"
master_instance_name = google_sql_database_instance.master.name
# Whether or not to allow Terraform to destroy the instance.
deletion_protection = var.deletion_protection
replica_configuration {
# Specifies that the replica is the failover target.
@@ -149,36 +187,52 @@ resource "google_sql_database_instance" "failover_replica" {
settings {
crash_safe_replication = true
tier = "${var.machine_type}"
authorized_gae_applications = ["${var.authorized_gae_applications}"]
disk_autoresize = "${var.disk_autoresize}"
tier = var.machine_type
disk_autoresize = var.disk_autoresize
ip_configuration {
authorized_networks = ["${var.authorized_networks}"]
ipv4_enabled = "${var.enable_public_internet_access}"
private_network = "${var.private_network}"
require_ssl = "${var.require_ssl}"
dynamic "authorized_networks" {
for_each = var.authorized_networks
content {
name = authorized_networks.value.name
value = authorized_networks.value.value
}
}
ipv4_enabled = var.enable_public_internet_access
private_network = var.private_network
require_ssl = var.require_ssl
}
location_preference {
follow_gae_application = "${var.follow_gae_application}"
zone = "${var.mysql_failover_replica_zone}"
dynamic "location_preference" {
for_each = var.mysql_failover_replica_zone == null ? [] : [var.mysql_failover_replica_zone]
content {
zone = location_preference.value
}
}
disk_size = "${var.disk_size}"
disk_type = "${var.disk_type}"
database_flags = ["${var.database_flags}"]
disk_size = var.disk_size
disk_type = var.disk_type
user_labels = "${var.custom_labels}"
dynamic "database_flags" {
for_each = var.database_flags
content {
name = database_flags.value.name
value = database_flags.value.value
}
}
user_labels = var.custom_labels
}
# Default timeouts are 10 minutes, which in most cases should be enough.
# Sometimes the database creation can, however, take longer, so we
# increase the timeouts slightly.
timeouts {
create = "${var.resource_timeout}"
delete = "${var.resource_timeout}"
update = "${var.resource_timeout}"
create = var.resource_timeout
delete = var.resource_timeout
update = var.resource_timeout
}
}
@@ -187,23 +241,26 @@ resource "google_sql_database_instance" "failover_replica" {
# ------------------------------------------------------------------------------
resource "google_sql_database_instance" "read_replica" {
count = "${var.num_read_replicas}"
count = var.num_read_replicas
depends_on = [
"google_sql_database_instance.master",
"google_sql_database_instance.failover_replica",
"google_sql_database.default",
"google_sql_user.default",
google_sql_database_instance.master,
google_sql_database_instance.failover_replica,
google_sql_database.default,
google_sql_user.default,
]
provider = "google-beta"
provider = google-beta
name = "${var.name}-read-${count.index}"
project = "${var.project}"
region = "${var.region}"
database_version = "${var.engine}"
project = var.project
region = var.region
database_version = var.engine
# The name of the instance that will act as the master in the replication setup.
master_instance_name = "${google_sql_database_instance.master.name}"
master_instance_name = google_sql_database_instance.master.name
# Whether or not to allow Terraform to destroy the instance.
deletion_protection = var.deletion_protection
replica_configuration {
# Specifies that the replica is not the failover target.
@@ -211,27 +268,39 @@ resource "google_sql_database_instance" "read_replica" {
}
settings {
tier = "${var.machine_type}"
authorized_gae_applications = ["${var.authorized_gae_applications}"]
disk_autoresize = "${var.disk_autoresize}"
tier = var.machine_type
disk_autoresize = var.disk_autoresize
ip_configuration {
authorized_networks = ["${var.authorized_networks}"]
ipv4_enabled = "${var.enable_public_internet_access}"
private_network = "${var.private_network}"
require_ssl = "${var.require_ssl}"
dynamic "authorized_networks" {
for_each = var.authorized_networks
content {
name = authorized_networks.value.name
value = authorized_networks.value.value
}
}
ipv4_enabled = var.enable_public_internet_access
private_network = var.private_network
require_ssl = var.require_ssl
}
location_preference {
follow_gae_application = "${var.follow_gae_application}"
zone = "${element(var.read_replica_zones, count.index)}"
zone = element(var.read_replica_zones, count.index)
}
disk_size = "${var.disk_size}"
disk_type = "${var.disk_type}"
database_flags = ["${var.database_flags}"]
disk_size = var.disk_size
disk_type = var.disk_type
user_labels = "${var.custom_labels}"
dynamic "database_flags" {
for_each = var.database_flags
content {
name = database_flags.value.name
value = database_flags.value.value
}
}
user_labels = var.custom_labels
}
# Read replica creation is initiated concurrently, but the provider creates
@@ -239,23 +308,24 @@ resource "google_sql_database_instance" "read_replica" {
# to allow successful creation of multiple read replicas without having to
# fear the operation timing out.
timeouts {
create = "${var.resource_timeout}"
delete = "${var.resource_timeout}"
update = "${var.resource_timeout}"
create = var.resource_timeout
delete = var.resource_timeout
update = var.resource_timeout
}
}
# ------------------------------------------------------------------------------
# CREATE A TEMPLATE FILE TO SIGNAL ALL RESOURCES HAVE BEEN CREATED
# ------------------------------------------------------------------------------
data "template_file" "complete" {
depends_on = [
"google_sql_database_instance.master",
"google_sql_database_instance.failover_replica",
"google_sql_database_instance.read_replica",
"google_sql_database.default",
"google_sql_user.default",
google_sql_database_instance.master,
google_sql_database_instance.failover_replica,
google_sql_database_instance.read_replica,
google_sql_database.default,
google_sql_user.default,
]
template = "true"
template = true
}

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the master database instance"
value = "${google_sql_database_instance.master.name}"
value = google_sql_database_instance.master.name
}
output "master_public_ip_address" {
description = "The public IPv4 address of the master instance."
value = "${google_sql_database_instance.master.public_ip_address}"
value = google_sql_database_instance.master.public_ip_address
}
output "master_private_ip_address" {
description = "The public IPv4 address of the master instance."
value = "${google_sql_database_instance.master.private_ip_address}"
value = google_sql_database_instance.master.private_ip_address
}
output "master_ip_addresses" {
description = "All IP addresses of the master instance JSON encoded, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${jsonencode(google_sql_database_instance.master.ip_address)}"
value = jsonencode(google_sql_database_instance.master.ip_address)
}
output "master_instance" {
description = "Self link to the master instance"
value = "${google_sql_database_instance.master.self_link}"
value = google_sql_database_instance.master.self_link
}
output "master_proxy_connection" {
@@ -38,27 +38,27 @@ output "master_proxy_connection" {
output "master_ca_cert" {
description = "The CA Certificate used to connect to the master instance via SSL"
value = "${google_sql_database_instance.master.server_ca_cert.0.cert}"
value = google_sql_database_instance.master.server_ca_cert.0.cert
}
output "master_ca_cert_common_name" {
description = "The CN valid for the master instance CA Cert"
value = "${google_sql_database_instance.master.server_ca_cert.0.common_name}"
value = google_sql_database_instance.master.server_ca_cert.0.common_name
}
output "master_ca_cert_create_time" {
description = "Creation time of the master instance CA Cert"
value = "${google_sql_database_instance.master.server_ca_cert.0.create_time}"
value = google_sql_database_instance.master.server_ca_cert.0.create_time
}
output "master_ca_cert_expiration_time" {
description = "Expiration time of the master instance CA Cert"
value = "${google_sql_database_instance.master.server_ca_cert.0.expiration_time}"
value = google_sql_database_instance.master.server_ca_cert.0.expiration_time
}
output "master_ca_cert_sha1_fingerprint" {
description = "SHA Fingerprint of the master instance CA Cert"
value = "${google_sql_database_instance.master.server_ca_cert.0.sha1_fingerprint}"
value = google_sql_database_instance.master.server_ca_cert.0.sha1_fingerprint
}
# ------------------------------------------------------------------------------
@@ -67,12 +67,12 @@ output "master_ca_cert_sha1_fingerprint" {
output "db" {
description = "Self link to the default database"
value = "${google_sql_database.default.self_link}"
value = google_sql_database.default.self_link
}
output "db_name" {
description = "Name of the default database"
value = "${google_sql_database.default.name}"
value = google_sql_database.default.name
}
# ------------------------------------------------------------------------------
@@ -81,32 +81,32 @@ output "db_name" {
output "failover_instance_name" {
description = "The name of the failover database instance"
value = "${join("", google_sql_database_instance.failover_replica.*.name)}"
value = join("", google_sql_database_instance.failover_replica.*.name)
}
output "failover_public_ip_address" {
description = "The public IPv4 address of the failover instance."
value = "${join("", google_sql_database_instance.failover_replica.*.public_ip_address)}"
value = join("", google_sql_database_instance.failover_replica.*.public_ip_address)
}
output "failover_private_ip_address" {
description = "The private IPv4 address of the failover instance."
value = "${join("", google_sql_database_instance.failover_replica.*.private_ip_address)}"
value = join("", google_sql_database_instance.failover_replica.*.private_ip_address)
}
output "failover_ip_addresses" {
description = "All IP addresses of the failover instance JSON encoded, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${jsonencode(google_sql_database_instance.failover_replica.*.ip_address)}"
value = jsonencode(google_sql_database_instance.failover_replica.*.ip_address)
}
output "failover_instance" {
description = "Self link to the failover instance"
value = "${join("", google_sql_database_instance.failover_replica.*.self_link)}"
value = join("", google_sql_database_instance.failover_replica.*.self_link)
}
output "failover_proxy_connection" {
description = "Failover instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${local.failover_proxy_connection}"
value = local.failover_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -115,27 +115,27 @@ output "failover_proxy_connection" {
output "failover_replica_ca_cert" {
description = "The CA Certificate used to connect to the failover instance via SSL"
value = "${local.failover_certificate}"
value = local.failover_certificate
}
output "failover_replica_ca_cert_common_name" {
description = "The CN valid for the failover instance CA Cert"
value = "${local.failover_certificate_common_name}"
value = local.failover_certificate_common_name
}
output "failover_replica_ca_cert_create_time" {
description = "Creation time of the failover instance CA Cert"
value = "${local.failover_certificate_create_time}"
value = local.failover_certificate_create_time
}
output "failover_replica_ca_cert_expiration_time" {
description = "Expiration time of the failover instance CA Cert"
value = "${local.failover_certificate_expiration_time}"
value = local.failover_certificate_expiration_time
}
output "failover_replica_ca_cert_sha1_fingerprint" {
description = "SHA Fingerprint of the failover instance CA Cert"
value = "${local.failover_certificate_sha1_fingerprint}"
value = local.failover_certificate_sha1_fingerprint
}
# ------------------------------------------------------------------------------
@@ -144,37 +144,37 @@ output "failover_replica_ca_cert_sha1_fingerprint" {
output "read_replica_instance_names" {
description = "List of names for the read replica instances"
value = ["${google_sql_database_instance.read_replica.*.name}"]
value = google_sql_database_instance.read_replica.*.name
}
output "read_replica_ip_addresses" {
description = "All IP addresses of the read replica instances JSON encoded, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${jsonencode(google_sql_database_instance.read_replica.*.ip_address)}"
value = jsonencode(google_sql_database_instance.read_replica.*.ip_address)
}
output "read_replica_public_ip_addresses" {
description = "List of public IPv4 addresses of the read replica instances."
value = ["${google_sql_database_instance.read_replica.*.public_ip_address}"]
value = google_sql_database_instance.read_replica.*.public_ip_address
}
output "read_replica_private_ip_addresses" {
description = "List of private IPv4 addresses of the read replica instances."
value = ["${google_sql_database_instance.read_replica.*.private_ip_address}"]
value = google_sql_database_instance.read_replica.*.private_ip_address
}
output "read_replica_instances" {
description = "List of self links to the read replica instances"
value = ["${google_sql_database_instance.read_replica.*.self_link}"]
value = google_sql_database_instance.read_replica.*.self_link
}
output "read_replica_proxy_connections" {
description = "List of read replica instance paths for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = ["${data.template_file.read_replica_proxy_connection.*.rendered}"]
value = data.template_file.read_replica_proxy_connection.*.rendered
}
output "read_replica_server_ca_certs" {
description = "JSON encoded list of CA Certificates used to connect to the read replica instances via SSL"
value = "${jsonencode(google_sql_database_instance.read_replica.*.server_ca_cert)}"
value = jsonencode(google_sql_database_instance.read_replica.*.server_ca_cert)
}
# ------------------------------------------------------------------------------
@@ -183,5 +183,10 @@ output "read_replica_server_ca_certs" {
output "complete" {
description = "Output signaling that all resources have been created"
value = "${data.template_file.complete.rendered}"
value = data.template_file.complete.rendered
}
output "service_account_email_address" {
description = "Service account email address associated with the CloudSQL instance"
value = google_sql_database_instance.master.service_account_email_address
}

View File

@@ -5,34 +5,42 @@
variable "project" {
description = "The project ID to host the database in."
type = string
}
variable "region" {
description = "The region to host the database in."
type = string
}
variable "name" {
description = "The name of the database instance. Note, after a name is used, it cannot be reused for up to one week. Use lowercase letters, numbers, and hyphens. Start with a letter."
type = string
}
variable "engine" {
description = "The engine version of the database, e.g. `MYSQL_5_6` or `MYSQL_5_7`. See https://cloud.google.com/sql/docs/features for supported versions."
type = string
}
variable "machine_type" {
description = "The machine type for the instances. See this page for supported tiers and pricing: https://cloud.google.com/sql/pricing"
type = string
}
variable "db_name" {
description = "Name of your database. Needs to follow MySQL identifier rules: https://dev.mysql.com/doc/refman/5.7/en/identifiers.html"
type = string
}
variable "master_user_name" {
description = "The username part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_name so you don't check it into source control."
type = string
}
variable "master_user_password" {
description = "The password part for the default user credentials, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. This should typically be set as the environment variable TF_VAR_master_user_password so you don't check it into source control."
type = string
}
# ---------------------------------------------------------------------------------------------------------------------
@@ -42,12 +50,13 @@ variable "master_user_password" {
variable "activation_policy" {
description = "This specifies when the instance should be active. Can be either `ALWAYS`, `NEVER` or `ON_DEMAND`."
type = string
default = "ALWAYS"
}
variable "authorized_networks" {
description = "A list of authorized CIDR-formatted IP address ranges that can connect to this DB. Only applies to public IP instances."
type = "list"
type = list(map(string))
default = []
# Example:
@@ -60,55 +69,63 @@ variable "authorized_networks" {
# ]
}
variable "authorized_gae_applications" {
description = "A list of Google App Engine (GAE) project names that are allowed to access this instance."
type = "list"
default = []
}
variable "backup_enabled" {
description = "Set to false if you want to disable backup."
type = bool
default = true
}
variable "backup_start_time" {
description = "HH:MM format (e.g. 04:00) time indicating when backup configuration starts. NOTE: Start time is randomly assigned if backup is enabled and 'backup_start_time' is not set"
type = string
default = "04:00"
}
variable "postgres_point_in_time_recovery_enabled" {
description = "Will restart database if enabled after instance creation - only applicable to PostgreSQL"
type = bool
default = false
}
variable "mysql_binary_log_enabled" {
description = "Set to false if you want to disable binary logs - only applicable to MySQL. Note, when using failover or read replicas, master and existing backups need to have binary_log_enabled=true set."
type = bool
default = true
}
variable "maintenance_window_day" {
description = "Day of week (1-7), starting on Monday, on which system maintenance can occur. Performance may be degraded or there may even be a downtime during maintenance windows."
type = number
default = 7
}
variable "maintenance_window_hour" {
description = "Hour of day (0-23) on which system maintenance can occur. Ignored if 'maintenance_window_day' not set. Performance may be degraded or there may even be a downtime during maintenance windows."
type = number
default = 7
}
variable "maintenance_track" {
description = "Receive updates earlier (canary) or later (stable)."
type = string
default = "stable"
}
variable "db_charset" {
description = "The charset for the default database."
default = ""
type = string
default = null
}
variable "db_collation" {
description = "The collation for the default database. Example for MySQL databases: 'utf8_general_ci'."
default = ""
type = string
default = null
}
variable "database_flags" {
description = "List of Cloud SQL flags that are applied to the database server"
type = "list"
type = list(any)
default = []
# Example:
@@ -127,68 +144,74 @@ variable "database_flags" {
variable "disk_autoresize" {
description = "Second Generation only. Configuration to increase storage size automatically."
type = bool
default = true
}
variable "disk_size" {
description = "Second generation only. The size of data disk, in GB. Size of a running instance cannot be reduced but can be increased."
type = number
default = 10
}
variable "disk_type" {
description = "The type of storage to use. Must be one of `PD_SSD` or `PD_HDD`."
type = string
default = "PD_SSD"
}
variable "follow_gae_application" {
description = "A GAE application whose zone to remain in. Must be in the same region as this instance."
default = ""
}
variable "master_zone" {
description = "Preferred zone for the master instance (e.g. 'us-central1-a'). 'region'. If empty, Google will auto-assign a zone."
default = ""
description = "Preferred zone for the master instance (e.g. 'us-central1-a'). 'region'. If null, Google will auto-assign a zone."
type = string
default = null
}
variable "master_user_host" {
description = "The host part for the default user, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password' "
description = "The host part for the default user, i.e. 'master_user_name'@'master_user_host' IDENTIFIED BY 'master_user_password'. Don't set this field for Postgres instances."
type = string
default = "%"
}
# In nearly all cases, databases should NOT be publicly accessible, however if you're migrating from a PAAS provider like Heroku to GCP, this needs to remain open to the internet.
variable "enable_public_internet_access" {
description = "WARNING: - In nearly all cases a database should NOT be publicly accessible. Only set this to true if you want the database open to the internet."
type = bool
default = false
}
variable "enable_failover_replica" {
description = "Set to true to enable failover replica."
type = bool
default = false
}
variable "mysql_failover_replica_zone" {
description = "The preferred zone for the failover instance (e.g. 'us-central1-b'). Must be different than 'master_zone'. Only applicable to MySQL, Postgres will determine this automatically."
default = ""
type = string
default = null
}
variable "require_ssl" {
description = "True if the instance should require SSL/TLS for users connecting over IP. Note: SSL/TLS is needed to provide security when you connect to Cloud SQL using IP addresses. If you are connecting to your instance only by using the Cloud SQL Proxy or the Java Socket Library, you do not need to configure your instance to use SSL/TLS."
type = bool
default = false
}
variable "private_network" {
description = "The resource link for the VPC network from which the Cloud SQL instance is accessible for private IP."
default = ""
type = string
default = null
}
variable "num_read_replicas" {
description = "The number of read replicas to create. Cloud SQL will replicate all data from the master to these replicas, which you can use to horizontally scale read traffic."
type = number
default = 0
}
variable "read_replica_zones" {
description = "A list of compute zones where read replicas should be created. List size should match 'num_read_replicas'"
type = "list"
type = list(string)
default = []
# Example:
@@ -197,7 +220,7 @@ variable "read_replica_zones" {
variable "custom_labels" {
description = "A map of custom labels to apply to the instance. The key is the label name and the value is the label value."
type = "map"
type = map(string)
default = {}
}
@@ -205,10 +228,28 @@ variable "custom_labels" {
# to not have the operations time out.
variable "resource_timeout" {
description = "Timeout for creating, updating and deleting database instances. Valid units of time are s, m, h."
type = string
default = "60m"
}
variable "wait_for" {
description = "By passing a value to this variable, you can effectively tell this module to wait to deploy until the given variable's value is resolved, which is a way to require that this module depend on some other module. Note that the actual value of this variable doesn't matter."
default = ""
# Whether or not to allow Terraform to destroy the instance.
variable "deletion_protection" {
description = "Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply command that deletes the instance will fail."
type = bool
default = "true"
}
# ---------------------------------------------------------------------------------------------------------------------
# MODULE DEPENDENCIES
# Workaround Terraform limitation where there is no module depends_on.
# See https://github.com/hashicorp/terraform/issues/1178 for more details.
# This can be used to make sure the module resources are created after other bootstrapping resources have been created.
# For example:
# dependencies = [google_service_networking_connection.private_vpc_connection.network]
# ---------------------------------------------------------------------------------------------------------------------
variable "dependencies" {
description = "Create a dependency between the resources in this module to the interpolated values in this list (and thus the source resources). In other words, the resources in this module will now depend on the resources backing the values in this list such that those resources need to be created before the resources in this module, and the resources in this module need to be destroyed before the resources in the list."
type = list(string)
default = []
}

View File

@@ -4,27 +4,27 @@
output "master_instance_name" {
description = "The name of the database instance"
value = "${module.postgres.master_instance_name}"
value = module.postgres.master_instance_name
}
output "master_ip_addresses" {
description = "All IP addresses of the instance as list of maps, see https://www.terraform.io/docs/providers/google/r/sql_database_instance.html#ip_address-0-ip_address"
value = "${module.postgres.master_ip_addresses}"
value = module.postgres.master_ip_addresses
}
output "master_private_ip" {
description = "The private IPv4 address of the master instance"
value = "${module.postgres.master_private_ip_address}"
value = module.postgres.master_private_ip_address
}
output "master_instance" {
description = "Self link to the master instance"
value = "${module.postgres.master_instance}"
value = module.postgres.master_instance
}
output "master_proxy_connection" {
description = "Instance path for connecting with Cloud SQL Proxy. Read more at https://cloud.google.com/sql/docs/mysql/sql-proxy"
value = "${module.postgres.master_proxy_connection}"
value = module.postgres.master_proxy_connection
}
# ------------------------------------------------------------------------------
@@ -33,10 +33,10 @@ output "master_proxy_connection" {
output "db_name" {
description = "Name of the default database"
value = "${module.postgres.db_name}"
value = module.postgres.db_name
}
output "db" {
description = "Self link to the default database"
value = "${module.postgres.db}"
value = module.postgres.db
}

439
test/Gopkg.lock generated
View File

@@ -1,439 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:8b95956b70e181b19025c7ba3578fdfd8efbec4ce916490700488afb9218972c"
name = "cloud.google.com/go"
packages = [
"compute/metadata",
"iam",
"internal",
"internal/optional",
"internal/trace",
"internal/version",
"storage",
]
pruneopts = ""
revision = "64a2037ec6be8a4b0c1d1f706ed35b428b989239"
version = "v0.26.0"
[[projects]]
digest = "1:5204bbf2acdc60904e9ed06b4364810bd8b16e2cd48e4c5cbb242c52d6fa1d5f"
name = "github.com/GoogleCloudPlatform/cloudsql-proxy"
packages = [
"logging",
"proxy/certs",
"proxy/dialers/mysql",
"proxy/dialers/postgres",
"proxy/proxy",
"proxy/util",
]
pruneopts = ""
revision = "ac834ce67862b7c4ed8bdbe86e664572f820c245"
version = "1.13"
[[projects]]
digest = "1:4b6ba994aa18b6c6a871cd700a66525a182f2c0cd78022e25e01508fc8559122"
name = "github.com/aws/aws-sdk-go"
packages = [
"aws",
"aws/awserr",
"aws/awsutil",
"aws/client",
"aws/client/metadata",
"aws/corehandlers",
"aws/credentials",
"aws/credentials/ec2rolecreds",
"aws/credentials/endpointcreds",
"aws/credentials/processcreds",
"aws/credentials/stscreds",
"aws/csm",
"aws/defaults",
"aws/ec2metadata",
"aws/endpoints",
"aws/request",
"aws/session",
"aws/signer/v4",
"internal/ini",
"internal/s3err",
"internal/sdkio",
"internal/sdkrand",
"internal/sdkuri",
"internal/shareddefaults",
"private/protocol",
"private/protocol/ec2query",
"private/protocol/eventstream",
"private/protocol/eventstream/eventstreamapi",
"private/protocol/json/jsonutil",
"private/protocol/jsonrpc",
"private/protocol/query",
"private/protocol/query/queryutil",
"private/protocol/rest",
"private/protocol/restxml",
"private/protocol/xml/xmlutil",
"service/acm",
"service/autoscaling",
"service/cloudwatchlogs",
"service/ec2",
"service/iam",
"service/kms",
"service/rds",
"service/s3",
"service/s3/s3iface",
"service/s3/s3manager",
"service/sns",
"service/sqs",
"service/sts",
]
pruneopts = ""
revision = "949cbce4e4443b72f6da12adbeb5d416dd506fbe"
version = "v1.16.27"
[[projects]]
digest = "1:b529f4bf748979caa18b599d40d13e8b6e591a74b340f315ce4f95e119c288c2"
name = "github.com/boombuler/barcode"
packages = [
".",
"qr",
"utils",
]
pruneopts = ""
revision = "3cfea5ab600ae37946be2b763b8ec2c1cf2d272d"
version = "v1.0.0"
[[projects]]
digest = "1:0deddd908b6b4b768cfc272c16ee61e7088a60f7fe2f06c547bd3d8e1f8b8e77"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = ""
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.1"
[[projects]]
digest = "1:e692d16fdfbddb94e9e4886aaf6c08bdbae5cb4ac80651445de9181b371c6e46"
name = "github.com/go-sql-driver/mysql"
packages = ["."]
pruneopts = ""
revision = "72cd26f257d44c1114970e19afddcd812016007e"
source = "git@github.com:go-sql-driver/mysql"
version = "v1.4.1"
[[projects]]
digest = "1:3dd078fda7500c341bc26cfbc6c6a34614f295a2457149fc1045cab767cbcf18"
name = "github.com/golang/protobuf"
packages = [
"proto",
"protoc-gen-go/descriptor",
"ptypes",
"ptypes/any",
"ptypes/duration",
"ptypes/timestamp",
]
pruneopts = ""
revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
version = "v1.2.0"
[[projects]]
digest = "1:c1d7e883c50a26ea34019320d8ae40fad86c9e5d56e63a1ba2cb618cef43e986"
name = "github.com/google/uuid"
packages = ["."]
pruneopts = ""
revision = "064e2069ce9c359c118179501254f67d7d37ba24"
version = "0.2"
[[projects]]
digest = "1:55c1b46a80db2baf4d762c1d0b5cb4946e46125baa02b8959310abab15b54aee"
name = "github.com/googleapis/gax-go"
packages = [
".",
"v2",
]
pruneopts = ""
revision = "c8a15bac9b9fe955bd9f900272f9a306465d28cf"
version = "v2.0.3"
[[projects]]
digest = "1:4b6c36dd91add683751cb4670cc26d63c7e7db259695ffd723670c666797c62c"
name = "github.com/gruntwork-io/terratest"
packages = [
"modules/aws",
"modules/collections",
"modules/customerrors",
"modules/environment",
"modules/files",
"modules/gcp",
"modules/logger",
"modules/packer",
"modules/random",
"modules/retry",
"modules/shell",
"modules/ssh",
"modules/terraform",
"modules/test-structure",
]
pruneopts = ""
revision = "425f7f1c2c72c607142c67aee02d1c14f874cf0a"
source = "git@github.com:gruntwork-io/terratest"
version = "v0.13.24"
[[projects]]
digest = "1:13fe471d0ed891e8544eddfeeb0471fd3c9f2015609a1c000aefdedf52a19d40"
name = "github.com/jmespath/go-jmespath"
packages = ["."]
pruneopts = ""
revision = "c2b33e84"
[[projects]]
digest = "1:29145d7af4adafd72a79df5e41456ac9e232d5a28c1cd4dacf3ff008a217fc10"
name = "github.com/lib/pq"
packages = [
".",
"oid",
]
pruneopts = ""
revision = "4ded0e9383f75c197b3a2aaa6d590ac52df6fd79"
version = "v1.0.0"
[[projects]]
digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = ""
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:d8c398c75a666d415196ba289402c3f52b595d8cede451a9e57278354e327a93"
name = "github.com/pquerna/otp"
packages = [
".",
"hotp",
"totp",
]
pruneopts = ""
revision = "be78767b3e392ce45ea73444451022a6fc32ad0d"
version = "v1.1.0"
[[projects]]
digest = "1:381bcbeb112a51493d9d998bbba207a529c73dbb49b3fd789e48c63fac1f192c"
name = "github.com/stretchr/testify"
packages = [
"assert",
"require",
]
pruneopts = ""
revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053"
version = "v1.3.0"
[[projects]]
digest = "1:b1bb9332f6cb7821a730e1681819b2813340eba5e873f05381815a7c6807d172"
name = "go.opencensus.io"
packages = [
".",
"exemplar",
"internal",
"internal/tagencoding",
"plugin/ochttp",
"plugin/ochttp/propagation/b3",
"stats",
"stats/internal",
"stats/view",
"tag",
"trace",
"trace/internal",
"trace/propagation",
"trace/tracestate",
]
pruneopts = ""
revision = "2b5032d79456124f42db6b7eb19ac6c155449dc2"
version = "v0.19.0"
[[projects]]
branch = "master"
digest = "1:cbc1ebc01ec2ceb2c3cc7b9e33357dbc3eff173335f02d9f01603f14102602a7"
name = "golang.org/x/crypto"
packages = [
"curve25519",
"ed25519",
"ed25519/internal/edwards25519",
"internal/chacha20",
"internal/subtle",
"poly1305",
"ssh",
"ssh/agent",
]
pruneopts = ""
revision = "b8fe1690c61389d7d2a8074a507d1d40c5d30448"
[[projects]]
branch = "master"
digest = "1:1e9704e5379e68ac473c28aeb3f7e7cd4036ae8a246bf0285b5ebdbb8e0cfacf"
name = "golang.org/x/net"
packages = [
"context",
"context/ctxhttp",
"http/httpguts",
"http2",
"http2/hpack",
"idna",
"internal/timeseries",
"trace",
]
pruneopts = ""
revision = "d26f9f9a57f3fab6a695bec0d84433c2c50f8bbf"
[[projects]]
digest = "1:b697592485cb412be4188c08ca0beed9aab87f36b86418e21acc4a3998f63734"
name = "golang.org/x/oauth2"
packages = [
".",
"google",
"internal",
"jws",
"jwt",
]
pruneopts = ""
revision = "d2e6202438beef2727060aa7cabdd924d92ebfd9"
[[projects]]
branch = "master"
digest = "1:489610147902fe0c7229218c749bb25a8a9ecce0d726ae4f8662517319f32554"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = ""
revision = "41f3e6584952bb034a481797859f6ab34b6803bd"
[[projects]]
digest = "1:5acd3512b047305d49e8763eef7ba423901e85d5dd2fd1e71778a0ea8de10bd4"
name = "golang.org/x/text"
packages = [
"collate",
"collate/build",
"internal/colltab",
"internal/gen",
"internal/tag",
"internal/triegen",
"internal/ucd",
"language",
"secure/bidirule",
"transform",
"unicode/bidi",
"unicode/cldr",
"unicode/norm",
"unicode/rangetable",
]
pruneopts = ""
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
branch = "master"
digest = "1:e53b3650fadc76377e90fa596a939233cff79f8606cae71e0b6c73e5e6829ecd"
name = "google.golang.org/api"
packages = [
"compute/v1",
"gensupport",
"googleapi",
"googleapi/internal/uritemplates",
"googleapi/transport",
"internal",
"iterator",
"option",
"sqladmin/v1beta4",
"storage/v1",
"transport/http",
"transport/http/internal/propagation",
]
pruneopts = ""
revision = "697424a9b4245c525a11d14a2460c76f35f8db55"
[[projects]]
digest = "1:bc09e719c4e2a15d17163f5272d9a3131c45d77542b7fdc53ff518815bc19ab3"
name = "google.golang.org/appengine"
packages = [
".",
"cloudsql",
"internal",
"internal/app_identity",
"internal/base",
"internal/datastore",
"internal/log",
"internal/modules",
"internal/remote_api",
"internal/urlfetch",
"urlfetch",
]
pruneopts = ""
revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.4.0"
[[projects]]
branch = "master"
digest = "1:91f75dc679abcf04b29b064a5b9c40a0b0561c86c322010fbf6fc08040cc48bc"
name = "google.golang.org/genproto"
packages = [
"googleapis/api/annotations",
"googleapis/iam/v1",
"googleapis/rpc/code",
"googleapis/rpc/status",
]
pruneopts = ""
revision = "4b09977fb92221987e99d190c8f88f2c92727a29"
[[projects]]
digest = "1:39d4d828b87d58d114fdc211f0638f32dcae84019fe17d6b48f9b697f4b60213"
name = "google.golang.org/grpc"
packages = [
".",
"balancer",
"balancer/base",
"balancer/roundrobin",
"binarylog/grpc_binarylog_v1",
"codes",
"connectivity",
"credentials",
"credentials/internal",
"encoding",
"encoding/proto",
"grpclog",
"internal",
"internal/backoff",
"internal/binarylog",
"internal/channelz",
"internal/envconfig",
"internal/grpcrand",
"internal/grpcsync",
"internal/syscall",
"internal/transport",
"keepalive",
"metadata",
"naming",
"peer",
"resolver",
"resolver/dns",
"resolver/passthrough",
"stats",
"status",
"tap",
]
pruneopts = ""
revision = "a02b0774206b209466313a0b525d2c738fe407eb"
version = "v1.18.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/mysql",
"github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres",
"github.com/go-sql-driver/mysql",
"github.com/gruntwork-io/terratest/modules/gcp",
"github.com/gruntwork-io/terratest/modules/logger",
"github.com/gruntwork-io/terratest/modules/terraform",
"github.com/gruntwork-io/terratest/modules/test-structure",
"github.com/lib/pq",
"github.com/stretchr/testify/assert",
"github.com/stretchr/testify/require",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,30 +0,0 @@
# Gopkg.toml example
#
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
[[constraint]]
name = "github.com/gruntwork-io/terratest"
source = "git@github.com:gruntwork-io/terratest"
version = "0.13.24"
[[constraint]]
name = "github.com/go-sql-driver/mysql"
source = "git@github.com:go-sql-driver/mysql"
version = "1.4.1"

View File

@@ -26,21 +26,10 @@ clean up.
### Prerequisites
- Install the latest version of [Go](https://golang.org/).
- Install [dep](https://github.com/golang/dep) for Go dependency management.
- Install [Terraform](https://www.terraform.io/downloads.html).
- Configure your Google credentials using one of the [options supported by GCP](https://cloud.google.com/docs/authentication/getting-started).
### One-time setup
Download Go dependencies using dep:
```
cd test
dep ensure
```
### Run all the tests
```bash
@@ -56,4 +45,4 @@ To run a specific test called `TestFoo`:
```bash
cd test
go test -v -timeout 60m -run TestFoo
```
```

View File

@@ -2,13 +2,14 @@ package test
import (
"fmt"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
"path/filepath"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
)
const NAME_PREFIX_PRIVATE = "mysql-private"
@@ -42,7 +43,7 @@ func TestMySqlPrivateIP(t *testing.T) {
test_structure.RunTestStage(t, "deploy", func() {
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_PRIVATE, "", "", 0, "")
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_PRIVATE)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)

View File

@@ -5,18 +5,19 @@ import (
"crypto/x509"
"database/sql"
"fmt"
"path/filepath"
"strings"
"testing"
"time"
mydialer "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/mysql"
"github.com/go-sql-driver/mysql"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"path/filepath"
"strings"
"testing"
"time"
)
const NAME_PREFIX_PUBLIC = "mysql-public"
@@ -65,7 +66,7 @@ func TestMySqlPublicIP(t *testing.T) {
test_structure.RunTestStage(t, "deploy", func() {
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_PUBLIC, "", "", 0, "")
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_PUBLIC)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)

View File

@@ -3,15 +3,16 @@ package test
import (
"database/sql"
"fmt"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"path/filepath"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const NAME_PREFIX_REPLICAS = "mysql-replicas"
@@ -58,7 +59,7 @@ func TestMySqlReplicas(t *testing.T) {
masterZone := test_structure.LoadString(t, exampleDir, KEY_MASTER_ZONE)
failoverReplicaZone := test_structure.LoadString(t, exampleDir, KEY_FAILOVER_REPLICA_ZONE)
readReplicaZone := test_structure.LoadString(t, exampleDir, KEY_READ_REPLICA_ZONE)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_REPLICAS, masterZone, failoverReplicaZone, 1, readReplicaZone)
terraformOptions := createTerratestOptionsForCloudSqlReplicas(projectId, region, exampleDir, NAME_PREFIX_REPLICAS, masterZone, failoverReplicaZone, 1, readReplicaZone)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)

View File

@@ -2,13 +2,14 @@ package test
import (
"fmt"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
"path/filepath"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/assert"
)
const NAME_PREFIX_POSTGRES_PRIVATE = "postgres-private"
@@ -42,7 +43,7 @@ func TestPostgresPrivateIP(t *testing.T) {
test_structure.RunTestStage(t, "deploy", func() {
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_PRIVATE, "", "", 0, "")
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_PRIVATE)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)

View File

@@ -3,18 +3,19 @@ package test
import (
"database/sql"
"fmt"
_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"os"
"path/filepath"
"strings"
"testing"
_ "github.com/GoogleCloudPlatform/cloudsql-proxy/proxy/dialers/postgres"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const NAME_PREFIX_POSTGRES_PUBLIC = "postgres-public"
@@ -62,7 +63,7 @@ func TestPostgresPublicIP(t *testing.T) {
test_structure.RunTestStage(t, "deploy", func() {
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_PUBLIC, "", "", 0, "")
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_PUBLIC)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
@@ -137,7 +138,7 @@ func TestPostgresPublicIP(t *testing.T) {
logger.Logf(t, "Connecting to: %s via Cloud SQL Proxy", proxyConn)
// Use the Cloud SQL Proxy for queries
// See https://cloud.google.com/sql/docs/mysql/sql-proxy
// See https://cloud.google.com/sql/docs/postgres/sql-proxy
// Note that sslmode=disable is required it does not mean that the connection
// is unencrypted. All connections via the proxy are completely encrypted.
@@ -245,5 +246,11 @@ func TestPostgresPublicIP(t *testing.T) {
if err = db.Ping(); err != nil {
t.Fatalf("Failed to ping DB with forced SSL: %v", err)
}
// Drop the test table if it exists
logger.Logf(t, "Drop table: %s", POSTGRES_DROP_TEST_TABLE)
if _, err = db.Exec(POSTGRES_DROP_TEST_TABLE); err != nil {
t.Fatalf("Failed to drop table: %v", err)
}
})
}

View File

@@ -3,16 +3,17 @@ package test
import (
"database/sql"
"fmt"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/gruntwork-io/terratest/modules/test-structure"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"path/filepath"
"strings"
"testing"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/logger"
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
_ "github.com/lib/pq"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
const NAME_PREFIX_POSTGRES_REPLICAS = "postgres-replicas"
@@ -51,12 +52,35 @@ func TestPostgresReplicas(t *testing.T) {
terraform.Destroy(t, terraformOptions)
})
// AT THE END OF THE TESTS, CLEAN UP ANY POSTGRES OBJECTS THAT WERE CREATED
defer test_structure.RunTestStage(t, "cleanup_postgres_objects", func() {
terraformOptions := test_structure.LoadTerraformOptions(t, exampleDir)
publicIp := terraform.Output(t, terraformOptions, OUTPUT_MASTER_PUBLIC_IP)
connectionString := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=disable", DB_USER, DB_PASS, publicIp, DB_NAME)
// Does not actually open up the connection - just returns a DB ref
logger.Logf(t, "Connecting to: %s", publicIp)
db, err := sql.Open("postgres", connectionString)
require.NoError(t, err, "Failed to open DB connection")
// Make sure we clean up properly
defer db.Close()
// Drop table if it exists
logger.Logf(t, "Drop table: %s", POSTGRES_DROP_TEST_TABLE)
if _, err = db.Exec(POSTGRES_DROP_TEST_TABLE); err != nil {
t.Fatalf("Failed to drop table: %v", err)
}
})
test_structure.RunTestStage(t, "deploy", func() {
region := test_structure.LoadString(t, exampleDir, KEY_REGION)
projectId := test_structure.LoadString(t, exampleDir, KEY_PROJECT)
masterZone := test_structure.LoadString(t, exampleDir, KEY_MASTER_ZONE)
readReplicaZone := test_structure.LoadString(t, exampleDir, KEY_READ_REPLICA_ZONE)
terraformOptions := createTerratestOptionsForCloudSql(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_REPLICAS, masterZone, "", 1, readReplicaZone)
terraformOptions := createTerratestOptionsForCloudSqlReplicas(projectId, region, exampleDir, NAME_PREFIX_POSTGRES_REPLICAS, masterZone, "", 1, readReplicaZone)
test_structure.SaveTerraformOptions(t, exampleDir, terraformOptions)
terraform.InitAndApply(t, terraformOptions)

11
test/go.mod Normal file
View File

@@ -0,0 +1,11 @@
module github.com/gruntwork-io/terraform-google-sql/test
go 1.14
require (
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20200504171905-7e668d9ad0ba
github.com/go-sql-driver/mysql v1.5.0
github.com/gruntwork-io/terratest v0.37.5
github.com/lib/pq v1.5.1
github.com/stretchr/testify v1.5.1
)

803
test/go.sum Normal file
View File

@@ -0,0 +1,803 @@
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0 h1:xE3CPsOgttP4ACBePh79zTKALtXwn/Edhcr16R5hMWU=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
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 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
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/cloudsql-proxy v0.0.0-20200504171905-7e668d9ad0ba h1:NVn+yVWfQPI68bbhVI6zI63eh7TJefiGT4ZEyCxo9dQ=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20200504171905-7e668d9ad0ba/go.mod h1:JaTTAYKXdMsyO5t+knEPNeaonOxMb/+0wYbO0pbiGuo=
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 h1:MXnqY6SlWySaZAqNnXThOvjRFdiiOuKtC6i7baFdNdU=
github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.38.28 h1:2ZzgEupSluR18ClxUnHwXKyuADheZpMblXRAsHqF0tI=
github.com/aws/aws-sdk-go v1.38.28/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
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 h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/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 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
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 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.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 h1:2EQbDt6zX40xsToT0KdsmAm4wfA+fPJfv9Yk/PwTxZk=
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 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE=
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 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ=
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 h1:ZfSZ3P3BedhKGUhzj7BQlPSU4OvT6tfOKe3DVHzOA7s=
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 h1:yY9rWGoXv1U5pl4gxqlULARMQD7x0QG85lqEXTWysik=
github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM=
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.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/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 h1:skJKxRtNmevLqnayafdLe2AsenqRupVmzZSqrvb5caU=
github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-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 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
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-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
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 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
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/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
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.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
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 h1:lvfj3UTMJS9ZD1T4mUjvZTe24RqIe9fYUqpeOza+0Hs=
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 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/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 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
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 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
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 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
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/go-commons v0.8.0 h1:k/yypwrPqSeYHevLlEDmvmgQzcyTwrlZGRaxEM6G0ro=
github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78=
github.com/gruntwork-io/terratest v0.37.5 h1:W93EhxcxDApa5Xyj/TOpDXx+i5IssTopy5LbEUJkPuA=
github.com/gruntwork-io/terratest v0.37.5/go.mod h1:CSHpZNJdqYQ+TUrigM100jcahRUV5X6w7K2kZJ8iylY=
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/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04x7iNw=
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/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/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw=
github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI=
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 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
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 h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/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 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
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/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.5.1 h1:Jn6HYxiYrtQ92CopqJLvfPCJUrrruw1+1cn0jM9dKrI=
github.com/lib/pq v1.5.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
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 h1:ofNAzWCcyTALn2Zv40+8XitdzCgXY6e9qvXwN9W0YXg=
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/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-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/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 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 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
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 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok=
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 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
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/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
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.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
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 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
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/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8=
github.com/zclconf/go-cty v1.2.1/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.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/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-20200420201142-3c4aac89819a/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-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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-20190724013045-ca1201d0de80/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-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-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/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
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 h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
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/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/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-20190726091711-fc99dfbffb4e/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-20191001151750-bb3f8db39f24/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-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/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/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 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 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
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-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-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-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20201110201400-7099162a900a h1:5E6TPwSBG74zT8xSrVc8W59K4ch4NFobVTnh2BYzHyU=
golang.org/x/tools v0.0.0-20201110201400-7099162a900a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.21.0 h1:zS+Q/CJJnVlXpXQVIz+lH0ZT2lBuT2ac7XD8Y/3w6hY=
google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
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 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM=
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-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200420144010-e5e8543f8aeb/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
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.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k=
google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
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 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
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 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
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 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
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=
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI=
k8s.io/api v0.19.3 h1:GN6ntFnv44Vptj/b+OnMW7FmzkpDoIDLZRvKX3XH9aU=
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 h1:bpIQXlKjB4cB/oNpnNnV+BybGPR7iP5oYpsOTEJ4hgc=
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 h1:ctqR1nQ52NUs6LpI0w+a5U+xjYwflFwA13OJKcicMxg=
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 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
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 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A=
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 h1:uJmqzgNWG7XyClnU/mLPBWwfKKF1K8Hf8whTseBgJcg=
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=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/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 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU=
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 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA=
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 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -1,12 +1,13 @@
package test
import (
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/require"
"io/ioutil"
"os"
"testing"
"github.com/gruntwork-io/terratest/modules/gcp"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/require"
)
const DB_NAME = "testdb"
@@ -43,6 +44,7 @@ const SQL_QUERY_ROW_COUNT = "SELECT count(*) FROM test"
const POSTGRES_CREATE_TEST_TABLE_WITH_SERIAL = "CREATE TABLE IF NOT EXISTS test (id SERIAL, name varchar(10) NOT NULL, PRIMARY KEY (ID))"
const POSTGRES_INSERT_TEST_ROW = "INSERT INTO test(name) VALUES('Grunty') RETURNING id"
const POSTGRES_DROP_TEST_TABLE = "DROP TABLE IF EXISTS test"
func getRandomRegion(t *testing.T, projectID string) string {
approvedRegions := []string{"europe-north1", "europe-west1", "europe-west2", "europe-west3", "us-central1", "us-east1", "us-west1"}
@@ -63,8 +65,24 @@ func getTwoDistinctRandomZonesForRegion(t *testing.T, projectID string, region s
return firstZone, secondZone
}
func createTerratestOptionsForCloudSql(projectId string, region string, exampleDir string, namePrefix string, masterZone string, failoverReplicaZone string, numReadReplicas int, readReplicaZone string) *terraform.Options {
func createTerratestOptionsForCloudSql(projectId string, region string, exampleDir string, namePrefix string) *terraform.Options {
terratestOptions := &terraform.Options{
// The path to where your Terraform code is located
TerraformDir: exampleDir,
Vars: map[string]interface{}{
"region": region,
"project": projectId,
"name_prefix": namePrefix,
"db_name": DB_NAME,
"master_user_name": DB_USER,
"master_user_password": DB_PASS,
},
}
return terratestOptions
}
func createTerratestOptionsForCloudSqlReplicas(projectId string, region string, exampleDir string, namePrefix string, masterZone string, failoverReplicaZone string, numReadReplicas int, readReplicaZone string) *terraform.Options {
terratestOptions := &terraform.Options{
// The path to where your Terraform code is located
TerraformDir: exampleDir,

View File

@@ -0,0 +1,25 @@
package testvalidate
import (
"os"
"path/filepath"
"testing"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
"github.com/stretchr/testify/require"
)
// TestValidateAllTerraformModulesAndExamples recursively finds all modules and examples (by default) subdirectories in
// the repo and runs Terraform InitAndValidate on them to flush out missing variables, typos, unused vars, etc
func TestValidateAllTerraformModulesAndExamples(t *testing.T) {
t.Parallel()
cwd, err := os.Getwd()
require.NoError(t, err)
opts, optsErr := test_structure.NewValidationOptions(filepath.Join(cwd, "../.."), []string{}, []string{})
require.NoError(t, optsErr)
test_structure.ValidateAllTerraformModules(t, opts)
}