├── .github ├── CODEOWNERS └── workflows │ └── main.yml ├── .gitignore ├── .pre-commit-config.yaml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── README.tfdoc.hcl ├── db_subnet_group.tf ├── elasticache_subnet_group.tf ├── examples ├── README.md └── complete-example │ ├── README.md │ └── main.tf ├── go.mod ├── go.sum ├── intra_routing.tf ├── main.tf ├── outputs.tf ├── private_routing.tf ├── public_routing.tf ├── subnets.tf ├── test ├── README.md ├── unit-complete │ └── main.tf ├── unit-disabled │ └── main.tf ├── unit-minimal │ └── main.tf ├── unit_complete_test.go ├── unit_disabled_test.go └── unit_minimal_test.go ├── variables.tf └── versions.tf /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mariux @mineiros-io/terraform-service-catalog 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI/CD Pipeline 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | 11 | env: 12 | AWS_SECRET_ACCESS_KEY: ${{ secrets.MINEIROS_TESTING_AWS_SECRET_ACCESS_KEY }} 13 | AWS_ACCESS_KEY_ID: ${{ secrets.MINEIROS_TESTING_AWS_ACCESS_KEY_ID }} 14 | 15 | jobs: 16 | pre-commit: 17 | runs-on: ubuntu-latest 18 | name: Static Analysis 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v2 22 | - name: Run pre-commit 23 | run: make test/pre-commit 24 | 25 | unit-tests: 26 | runs-on: ubuntu-latest 27 | name: Unit Tests 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v2 31 | - name: Run Unit Tests 32 | run: make test/unit-tests 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IntelliJ files 2 | .idea_modules 3 | *.iml 4 | *.iws 5 | *.ipr 6 | .idea/ 7 | build/ 8 | */build/ 9 | out/ 10 | 11 | # macOS files 12 | .history 13 | .DS_Store 14 | 15 | # Local .terraform directories 16 | **/.terraform/* 17 | 18 | # .tfstate files 19 | *.tfstate 20 | *.tfstate.* 21 | 22 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 23 | # .tfvars files are managed as part of configuration and so should be included in 24 | # version control. 25 | # 26 | # example.tfvars 27 | 28 | # Ignore override files as they are usually used to override resources locally and so 29 | # are not checked in 30 | override.tf 31 | override.tf.json 32 | *_override.tf 33 | *_override.tf.json 34 | 35 | # Include override files you do wish to add to version control using negated pattern 36 | # 37 | # !example_override.tf 38 | 39 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 40 | # example: *tfplan* 41 | 42 | # Go best practices dictate that libraries should not include the vendor directory 43 | vendor 44 | 45 | # Terratest directory used to store temporary data 46 | .test-data 47 | 48 | .terraform.lock.hcl 49 | 50 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/mineiros-io/pre-commit-hooks 3 | rev: v0.3.1 4 | hooks: 5 | - id: terraform-fmt 6 | - id: terraform-validate 7 | exclude: ^examples|.terraform/ 8 | - id: tflint 9 | - id: golangci-lint 10 | - id: phony-targets 11 | - id: markdown-link-check 12 | args: ['-p'] # When adding the -p flag, markdown-link-check will always with an exit code 0, even if dead links are found 13 | verbose: true # Forces the output of the hook to be printed even when the hook passes. 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## [0.7.1] 11 | 12 | ### Fixed 13 | 14 | - Fix calculation of zone name 15 | 16 | ## [0.7.0] 17 | 18 | ### Added 19 | 20 | - Add `nat_gateway_single_mode_zone` to be able to set a fixed zone for single NAT gateway deployments. 21 | - Add `nat_gateway_eip_allocation_ids` to allow bringing external EIPs instead of creating them with the module. 22 | 23 | ## [0.6.0] 24 | 25 | ### Added 26 | 27 | - Add tags for easier data-sourcing 28 | - Add support for elasticache subnet groups 29 | 30 | ## [0.5.0] 31 | 32 | ### Added 33 | 34 | - Add support for db subnet groups 35 | - Add support terraform `v1.x` 36 | 37 | ## [0.4.0] 38 | 39 | ### Added 40 | 41 | - Add terraform `v0.15` support 42 | 43 | ## [0.3.0] 44 | 45 | ### BREAKING CHANGES 46 | 47 | - updating will recreate routes to nat gateways using a new resource key as terraform address 48 | 49 | ### Added 50 | 51 | - Add support for terraform `v0.14` 52 | 53 | ### Fixed 54 | 55 | - BREAKING: Fix terraform route modification behavior when switching nat_gateway_mode 56 | 57 | ## [0.2.0] 58 | 59 | ### Added 60 | 61 | - Add support for Terraform AWS Provider v3.x 62 | - Add support for Terraform v0.13.x 63 | - Prepare support for Terraform v0.14.x 64 | 65 | ## [0.1.0] - 2020-07-06 66 | 67 | ### Added 68 | 69 | - THIS RELEASE IS BREAKING BACKWARD COMPATIBILITY. 70 | - Add support to move subnets between subnet classes without recreation (public, private, intra). 71 | - Add CHANGELOG.md, CONTIBUTING.md and test/README.md. 72 | - Add new input variables to support dynamic subnets. 73 | - Ensure cidr_blocks are align to network address. 74 | - Document all input arguments and output attributes. 75 | - Add minimal and module_enabled tests 76 | 77 | ### Changed 78 | 79 | - THIS RELEASE IS BREAKING BACKWARD COMPATIBILITY. 80 | - Refactor the full module while keeping the same basic feature set. 81 | - Refactor test to deploy VPC with all NAT gateway Modes (single, one_per_az, none). 82 | - Update build-system. 83 | 84 | ### Removed 85 | 86 | - THIS RELEASE IS BREAKING BACKWARD COMPATIBILITY. 87 | - Remove routing to the internet from subnets of class 'intra'. 88 | - Remove flags to allow and disallow internet access for private and intra subnets. 89 | - Remove support for static network classes. 90 | - Remove most input variables related to defining subnets. 91 | 92 | ## [0.0.3] - 2020-06-20 93 | 94 | ### Changed 95 | 96 | - Update build-system 97 | - Update documentation 98 | 99 | ### Fixed 100 | 101 | - Set tenancy to "default" 102 | - Instance tenancy defaulted to "dedicated" which is very costly when running instances in the VPC for non production workloads on scale. If you used v0.0.1 or v0.0.2 please check that you did not start any dedicated instances and review your costs and recreate any started instances to run on shared hardware with default tenenacy. Note: Those are still pre-releases and not meant to run workloads yet. 103 | 104 | ### Removed 105 | 106 | - Unpublish v0.0.1 and v0.0.2 due to expensive dedicated tenancy 107 | 108 | ## [0.0.2] - 2020-06-04 109 | 110 | ### Changed 111 | 112 | - Update build-system 113 | - Update documentation 114 | 115 | ## [0.0.1] - 2020-02-17 116 | 117 | ### Added 118 | 119 | - Add support for three subnet classes (public, private, intra) 120 | - Add support for multiple NAT gateway modes (none, single, one_per_az) 121 | - Implement support for `aws_vpc` resource 122 | - Implement support for `aws_subnet` resource 123 | - Implement support for `aws_route_table` resource 124 | - Implement support for `aws_route_table_association` resource 125 | - Implement support for `aws_route` resource 126 | - Implement support for `aws_internet_gateway` resource 127 | - Implement support for `aws_eip` resource 128 | - Implement support for `aws_nat_gateway` resource 129 | - Document the usage of the module in README.md 130 | - Document the usage of examples 131 | - Add unit tests for basic use cases 132 | 133 | [unreleased]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.7.1...HEAD 134 | [0.7.1]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.7.0...v0.7.1 135 | [0.7.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.6.0...v0.7.0 136 | [0.6.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.5.0...v0.6.0 137 | [0.5.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.4.0...v0.5.0 138 | [0.4.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.3.0...v0.4.0 139 | [0.3.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.2.0...v0.3.0 140 | [0.2.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.1.0...v0.2.0 141 | [0.1.0]: https://github.com/mineiros-io/terraform-aws-vpc/compare/v0.0.3...v0.1.0 142 | [0.0.3]: https://github.com/mineiros-io/terraform-aws-vpc/compare/55347bd0db3b37ad2d2bcebdf11ed1ea666ad788...v0.0.3 143 | [0.0.2]: https://github.com/mineiros-io/terraform-aws-vpc/compare/0608a9123de5d1c02a6fcd0a2ee8e4f5216c1a49...55347bd0db3b37ad2d2bcebdf11ed1ea666ad788 144 | [0.0.1]: https://github.com/mineiros-io/terraform-aws-vpc/commit/0608a9123de5d1c02a6fcd0a2ee8e4f5216c1a49 145 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | First and foremost, we'd like to express our gratitude to you for taking the time to contribute. 4 | We welcome and appreciate any and all contributions via 5 | [Pull Requests] along the [GitHub Flow]. 6 | 7 | 1. [Open a GitHub issue](#open-a-github-issue) 8 | 2. [Fork the repository on GitHub](#fork-the-repository-on-github) 9 | 3. [Install the pre-commit hooks](#install-the-pre-commit-hooks) 10 | 4. [Update the documentation](#update-the-documentation) 11 | 5. [Update the tests](#update-the-tests) 12 | 6. [Update the code](#update-the-code) 13 | 7. [Create a pull request](#create-a-pull-request) 14 | 8. [Merge and release](#merge-and-release) 15 | 16 | ## Open a GitHub issue 17 | 18 | For bug reports or requests, please submit your issue in the appropriate repository. 19 | 20 | We advise that you open an issue and ask the 21 | [CODEOWNERS] and community prior to starting a contribution. 22 | This is your chance to ask questions and receive feedback before 23 | writing (potentially wrong) code. We value the direct contact with our community 24 | a lot, so don't hesitate to ask any questions. 25 | 26 | ## Fork the repository on GitHub 27 | 28 | [Fork] the repository into your own GitHub account and [create a new branch] as 29 | described in the [GitHub Flow]. 30 | 31 | ## Install the pre-commit hooks 32 | 33 | If the repository you're working on ships with a 34 | [`.pre-commit-config.yaml`][pre-commit-file], 35 | make sure the necessary hooks have been installed before you begin working 36 | (e.g. a `pre-commit install`). 37 | 38 | ## Update the documentation 39 | 40 | We encourage you to update the documentation before writing any code (please see 41 | [Readme Driven Development]. This ensures the 42 | documentation stays up to date and allows you to think through the problem fully before you begin implementing any 43 | changes. 44 | 45 | ## Update the tests 46 | 47 | We also recommend updating the automated tests before updating any code 48 | (see [Test Driven Development]. 49 | 50 | That means that you should add or update a test case, run all tests and verify 51 | that the new test fails with a clear error message and then start implementing 52 | the code changes to get that test to pass. 53 | 54 | The test folder in every repository will have documentation on how to run the 55 | tests locally. 56 | 57 | ## Update the code 58 | 59 | At this point, make your code changes and constantly test again your new test case to make sure that everything working 60 | properly. Do [commit] early and often and make useful commit messages. 61 | 62 | If a backwards incompatible change cannot be avoided, please make sure to call that out when you submit a pull request, 63 | explaining why the change is absolutely necessary. 64 | 65 | ## Create a pull request 66 | 67 | [Create a pull request] with your changes. 68 | Please make sure to include the following: 69 | 70 | 1. A description of the change, including a link to your GitHub issue. 71 | 1. Any notes on backwards incompatibility or downtime. 72 | 73 | ## Merge and release 74 | 75 | The [CODEOWNERS] of the repository will review your code and provide feedback. 76 | If everything looks good, they will merge the code and release a new version while following the principles of [Semantic Versioning (SemVer)]. 77 | 78 | 79 | 80 | [Pull Requests]: https://github.com/mineiros-io/terraform-aws-vpc/pulls 81 | [pre-commit-file]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/.pre-commit-config.yaml 82 | 83 | [Github Flow]: https://guides.github.com/introduction/flow/ 84 | [CODEOWNERS]: https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners 85 | [Fork]: https://help.github.com/en/github/getting-started-with-github/fork-a-repo 86 | [create a new branch]: https://guides.github.com/introduction/flow/ 87 | [Readme Driven Development]: https://tom.preston-werner.com/2010/08/23/readme-driven-development.html 88 | [commit]: https://help.github.com/en/desktop/contributing-to-projects/committing-and-reviewing-changes-to-your-project 89 | [create a pull request]: https://help.github.com/articles/creating-a-pull-request/ 90 | [Semantic Versioning (SemVer)]: https://semver.org/ 91 | [Test Driven Development]: https://en.wikipedia.org/wiki/Test-driven_development 92 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2020] [Mineiros GmbH] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Set default shell to bash 2 | SHELL := /bin/bash -o pipefail 3 | 4 | BUILD_TOOLS_VERSION ?= v0.13.0 5 | BUILD_TOOLS_DOCKER_REPO ?= mineiros/build-tools 6 | BUILD_TOOLS_DOCKER_IMAGE ?= ${BUILD_TOOLS_DOCKER_REPO}:${BUILD_TOOLS_VERSION} 7 | 8 | # Some CI providers such as GitHub Actions, CircleCI, and TravisCI are setting 9 | # the CI environment variable to a non-empty value by default to indicate that 10 | # the current workflow is running in a Continuous Integration environment. 11 | # 12 | # If TF_IN_AUTOMATION is set to any non-empty value, Terraform adjusts its 13 | # output to avoid suggesting specific commands to run next. 14 | # https://www.terraform.io/docs/commands/environment-variables.html#tf_in_automation 15 | # 16 | # We are using GNU style quiet commands to disable set V to non-empty e.g. V=1 17 | # https://www.gnu.org/software/automake/manual/html_node/Debugging-Make-Rules.html 18 | # 19 | ifdef CI 20 | TF_IN_AUTOMATION ?= yes 21 | export TF_IN_AUTOMATION 22 | 23 | V ?= 1 24 | endif 25 | 26 | ifndef NOCOLOR 27 | GREEN := $(shell tput -Txterm setaf 2) 28 | YELLOW := $(shell tput -Txterm setaf 3) 29 | WHITE := $(shell tput -Txterm setaf 7) 30 | RESET := $(shell tput -Txterm sgr0) 31 | endif 32 | 33 | GIT_TOPLEVEl = $(shell git rev-parse --show-toplevel) 34 | 35 | # Generic docker run flags 36 | DOCKER_RUN_FLAGS += -v ${GIT_TOPLEVEl}:/build 37 | DOCKER_RUN_FLAGS += --rm 38 | DOCKER_RUN_FLAGS += -e TF_IN_AUTOMATION 39 | # If TF_VERSION is defined, TFSwitch will switch to the desired version on 40 | # container startup. If TF_VERSION is omitted, the default version installed 41 | # inside the docker image will be used. 42 | DOCKER_RUN_FLAGS += -e TF_VERSION 43 | 44 | # If SSH_AUTH_SOCK is set, we forward the SSH agent of the host system into 45 | # the docker container. This is useful when working with private repositories 46 | # and dependencies that might need to be cloned inside the container (e.g. 47 | # private Terraform modules). 48 | ifdef SSH_AUTH_SOCK 49 | DOCKER_SSH_FLAGS += -e SSH_AUTH_SOCK=/ssh-agent 50 | DOCKER_SSH_FLAGS += -v ${SSH_AUTH_SOCK}:/ssh-agent 51 | endif 52 | 53 | # If AWS_ACCESS_KEY_ID is defined, we are likely running inside an AWS provider 54 | # module. To enable AWS authentication inside the docker container, we inject 55 | # the relevant environment variables. 56 | ifdef AWS_ACCESS_KEY_ID 57 | DOCKER_AWS_FLAGS += -e AWS_ACCESS_KEY_ID 58 | DOCKER_AWS_FLAGS += -e AWS_SECRET_ACCESS_KEY 59 | DOCKER_AWS_FLAGS += -e AWS_SESSION_TOKEN 60 | endif 61 | 62 | # If GITHUB_OWNER is defined, we are likely running inside a GitHub provider 63 | # module. To enable GitHub authentication inside the docker container, 64 | # we inject the relevant environment variables. 65 | ifdef GITHUB_OWNER 66 | DOCKER_GITHUB_FLAGS += -e GITHUB_TOKEN 67 | DOCKER_GITHUB_FLAGS += -e GITHUB_OWNER 68 | endif 69 | 70 | .PHONY: default 71 | default: help 72 | 73 | # Not exposed as a callable target by `make help`, since this is a one-time shot to simplify the development of this module. 74 | .PHONY: template/adjust 75 | template/adjust: FILTER = -path ./.git -prune -a -type f -o -type f -not -name Makefile 76 | template/adjust: 77 | @find . $(FILTER) -exec sed -i -e "s,terraform-module-template,$${PWD##*/},g" {} \; 78 | 79 | ## Run pre-commit hooks inside a build-tools docker container. 80 | .PHONY: test/pre-commit 81 | test/pre-commit: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 82 | test/pre-commit: 83 | $(call docker-run,pre-commit run -a) 84 | 85 | ## Run all Go tests inside a build-tools docker container. This is complementary to running 'go test ./test/...'. 86 | .PHONY: test/unit-tests 87 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_SSH_FLAGS} 88 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_GITHUB_FLAGS} 89 | test/unit-tests: DOCKER_FLAGS += ${DOCKER_AWS_FLAGS} 90 | test/unit-tests: DOCKER_FLAGS += -e TF_DATA_DIR=.terratest 91 | test/unit-tests: TEST ?= "TestUnit" 92 | test/unit-tests: 93 | @echo "${YELLOW}[TEST] ${GREEN}Start Running Go Tests in Docker Container.${RESET}" 94 | $(call go-test,./test -run $(TEST)) 95 | 96 | ## Clean up cache and temporary files 97 | .PHONY: clean 98 | clean: 99 | $(call rm-command,.terraform) 100 | $(call rm-command,.terraform.lock.hcl) 101 | $(call rm-command,*.tfplan) 102 | $(call rm-command,*/*/.terraform) 103 | $(call rm-command,*/*/*.tfplan) 104 | $(call rm-command,*/*/.terraform.lock.hcl) 105 | 106 | ## Display help for all targets 107 | .PHONY: help 108 | help: 109 | @awk '/^.PHONY: / { \ 110 | msg = match(lastLine, /^## /); \ 111 | if (msg) { \ 112 | cmd = substr($$0, 9, 100); \ 113 | msg = substr(lastLine, 4, 1000); \ 114 | printf " ${GREEN}%-30s${RESET} %s\n", cmd, msg; \ 115 | } \ 116 | } \ 117 | { lastLine = $$0 }' $(MAKEFILE_LIST) 118 | 119 | ## Generate README.md with Terradoc 120 | .PHONY: terradoc 121 | terradoc: 122 | $(call quiet-command,terradoc -o README.md README.tfdoc.hcl) 123 | 124 | # Define helper functions 125 | DOCKER_FLAGS += ${DOCKER_RUN_FLAGS} 126 | DOCKER_RUN_CMD = docker run ${DOCKER_FLAGS} ${BUILD_TOOLS_DOCKER_IMAGE} 127 | 128 | quiet-command = $(if ${V},${1},$(if ${2},@echo ${2} && ${1}, @${1})) 129 | docker-run = $(call quiet-command,${DOCKER_RUN_CMD} ${1} | cat,"${YELLOW}[DOCKER RUN] ${GREEN}${1}${RESET}") 130 | go-test = $(call quiet-command,${DOCKER_RUN_CMD} go test -v -count 1 -timeout 45m -parallel 1 ${1} | cat,"${YELLOW}[TEST] ${GREEN}${1}${RESET}") 131 | rm-command = $(call quiet-command,rm -rf ${1},"${YELLOW}[CLEAN] ${GREEN}${1}${RESET}") 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](https://mineiros.io/?ref=terraform-aws-vpc) 2 | 3 | [![Build Status](https://github.com/mineiros-io/terraform-aws-vpc/workflows/CI/CD%20Pipeline/badge.svg)](https://github.com/mineiros-io/terraform-aws-vpc/actions) 4 | [![GitHub tag (latest SemVer)](https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-vpc.svg?label=latest&sort=semver)](https://github.com/mineiros-io/terraform-aws-vpc/releases) 5 | [![Terraform Version](https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform)](https://github.com/hashicorp/terraform/releases) 6 | [![AWS Provider Version](https://img.shields.io/badge/AWS-3%20and%202.45+-F8991D.svg?logo=terraform)](https://github.com/terraform-providers/terraform-provider-aws/releases) 7 | [![Join Slack](https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack)](https://mineiros.io/slack) 8 | 9 | # terraform-aws-vpc 10 | 11 | A [Terraform] base module for managing an 12 | [Amazon Virtual Private Cloud](https://aws.amazon.com/de/vpc/) on 13 | [Amazon Web Services (AWS)][aws]. 14 | 15 | ***This module supports Terraform v0.15, v0.14, v0.13, as well as v0.12.20 and above 16 | and is compatible with the terraform AWS provider v3 as well as v2.45 and above.*** 17 | 18 | This module is part of our Infrastructure as Code (IaC) framework 19 | that enables our users and customers to easily deploy and manage reusable, 20 | secure, and production-grade cloud infrastructure. 21 | 22 | 23 | - [Module Features](#module-features) 24 | - [Getting Started](#getting-started) 25 | - [Module Argument Reference](#module-argument-reference) 26 | - [Main Resource Configuration](#main-resource-configuration) 27 | - [VPC](#vpc) 28 | - [Extended Resource Configuration](#extended-resource-configuration) 29 | - [Subnets](#subnets) 30 | - [Internet Gateway](#internet-gateway) 31 | - [NAT Gateways](#nat-gateways) 32 | - [Subnet Routing](#subnet-routing) 33 | - [Module Configuration](#module-configuration) 34 | - [Module Outputs](#module-outputs) 35 | - [Computed Attributes](#computed-attributes) 36 | - [Full Resource Objects](#full-resource-objects) 37 | - [Module Attributes](#module-attributes) 38 | - [External Documentation](#external-documentation) 39 | - [AWS Documentation VPC](#aws-documentation-vpc) 40 | - [Terraform AWS Provider Documentation:](#terraform-aws-provider-documentation) 41 | - [Module Versioning](#module-versioning) 42 | - [Backwards compatibility in `0.0.z` and `0.y.z` version](#backwards-compatibility-in-00z-and-0yz-version) 43 | - [About Mineiros](#about-mineiros) 44 | - [Reporting Issues](#reporting-issues) 45 | - [Contributing](#contributing) 46 | - [Makefile Targets](#makefile-targets) 47 | - [License](#license) 48 | 49 | ## Module Features 50 | 51 | This module implements the following Terraform resources 52 | 53 | - `aws_region` 54 | - `aws_vpc` 55 | - `aws_subnet` 56 | - `aws_eip` 57 | - `aws_nat_gateway` 58 | - `aws_route_table` 59 | - `aws_route_table_association` 60 | - `aws_route` 61 | - `aws_internet_gateway` 62 | - `aws_route_table` 63 | - `aws_route_table_association` 64 | - `aws_route` 65 | - `aws_elasticache_subnet_group` 66 | - `aws_db_subnet_group` 67 | 68 | ## Getting Started 69 | 70 | Most basic usage just setting required arguments: 71 | 72 | ```hcl 73 | module "terraform-aws-vpc" { 74 | source = "mineiros-io/vpc/aws" 75 | version = "~> 0.7.0" 76 | } 77 | ``` 78 | 79 | ## Module Argument Reference 80 | 81 | See [variables.tf] and [examples/] for details and use-cases. 82 | 83 | ### Main Resource Configuration 84 | 85 | #### VPC 86 | 87 | - [**`vpc_name`**](#var-vpc_name): *(Optional `string`)* 88 | 89 | The name of the VPC. This will be used to tag resources with names 90 | by default. 91 | 92 | Default is `"main"`. 93 | 94 | - [**`cidr_block`**](#var-cidr_block): *(Optional `string`)* 95 | 96 | The CIDR block for the VPC. 97 | 98 | Default is `"10.0.0.0/16"`. 99 | 100 | - [**`instance_tenancy`**](#var-instance_tenancy): *(Optional `string`)* 101 | 102 | A tenancy option for instances launched into the VPC. 103 | Setting the tenancy to `dedicated` will create additional costs: See 104 | https://aws.amazon.com/ec2/pricing/dedicated-instances/ for details. 105 | 106 | Default is `"default"`. 107 | 108 | - [**`enable_dns_support`**](#var-enable_dns_support): *(Optional `bool`)* 109 | 110 | A boolean flag to enable/disable DNS support in the VPC. 111 | 112 | Default is `true`. 113 | 114 | - [**`enable_dns_hostnames`**](#var-enable_dns_hostnames): *(Optional `bool`)* 115 | 116 | A boolean flag to enable/disable DNS hostnames in the VPC. 117 | 118 | Default is `false`. 119 | 120 | - [**`enable_classiclink`**](#var-enable_classiclink): *(Optional `bool`)* 121 | 122 | A boolean flag to enable/disable ClassicLink for the VPC. Only valid 123 | in regions and accounts that support EC2 Classic. See the 124 | ClassicLink documentation for more information. 125 | 126 | Default is `false`. 127 | 128 | - [**`enable_classiclink_dns_support`**](#var-enable_classiclink_dns_support): *(Optional `bool`)* 129 | 130 | A boolean flag to enable/disable ClassicLink DNS Support for the 131 | VPC. Only valid in regions and accounts that support EC2 Classic. 132 | 133 | Default is `false`. 134 | 135 | - [**`assign_generated_ipv6_cidr_block`**](#var-assign_generated_ipv6_cidr_block): *(Optional `bool`)* 136 | 137 | Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length 138 | for the VPC. You cannot specify the range of IP addresses, or the 139 | size of the CIDR block. 140 | 141 | Default is `false`. 142 | 143 | - [**`vpc_tags`**](#var-vpc_tags): *(Optional `string`)* 144 | 145 | A map of tags to assign to the vpc resource. 146 | To set the Name and add the capability to be used in data sources 147 | the `vpc_tags` will always be merged with: 148 | 149 | Default is `"{}"`. 150 | 151 | Example: 152 | 153 | ```hcl 154 | { 155 | Name = "{vpc_name}" 156 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 157 | } 158 | ``` 159 | 160 | ### Extended Resource Configuration 161 | 162 | #### Subnets 163 | 164 | - [**`subnets`**](#var-subnets): *(Optional `list(subnet)`)* 165 | 166 | A List of `subnet` objects that defined the subnet setup within the 167 | VPC. 168 | 169 | Default is `[]`. 170 | 171 | Example: 172 | 173 | ```hcl 174 | subnets = [ 175 | { 176 | group = "main" 177 | class = "public" 178 | 179 | map_public_ip_on_launch = true 180 | 181 | cidr_block = cidrsubnet("10.0.0.0/16", 4, 0) 182 | newbits = 4 183 | 184 | netnums_by_az = { 185 | a = [0] # "10.0.0.0/24" 186 | b = [1] # "10.0.1.0/24" 187 | } 188 | tags = {} 189 | }, 190 | { 191 | group = "main" 192 | class = "private" 193 | 194 | map_public_ip_on_launch = false 195 | 196 | cidr_block = cidrsubnet("10.0.0.0/16", 4, 1) 197 | newbits = 4 198 | 199 | netnums_by_az = { 200 | a = [0] # "10.0.16.0/24" 201 | b = [1] # "10.0.17.0/24" 202 | } 203 | }, 204 | ] 205 | ``` 206 | 207 | Each `subnet` object in the list accepts the following attributes: 208 | 209 | - [**`group`**](#attr-subnets-group): *(Optional `string`)* 210 | 211 | A group name for the subnets. This can be any string. This 212 | information is used to group and tag resources within the subnets. 213 | The combination of `group` and `class` needs to be unique over all 214 | subnets defined. This can be changed at any time and will change 215 | the tags applied to resources by default. 216 | 217 | Default is `"main"`. 218 | 219 | - [**`class`**](#attr-subnets-class): *(Optional `string`)* 220 | 221 | The class of the subnet. This can be `"public"`, `"private"`, or 222 | "`intra`". This can be changed at any time and will change the 223 | routing of the subnet instead of recreating the subnet resource. 224 | 225 | - "public" defines a set of subnets where deployed components are 226 | reachable via the public Internet. 227 | - "private" defines a set of subnets where components are not 228 | publicly reachable but can reach the Internet. 229 | - "intra" defines a set of subnets that have no connectivity to 230 | the public Internet. 231 | 232 | Default is `"private"`. 233 | 234 | - [**`map_public_ip_on_launch`**](#attr-subnets-map_public_ip_on_launch): *(Optional `bool`)* 235 | 236 | Whether resources deployed into the subnet will be assigned a 237 | public IPv4 address when launched. 238 | 239 | Default is `true`. 240 | 241 | - [**`cidr_block`**](#attr-subnets-cidr_block): *(Optional `string`)* 242 | 243 | Define the base CIDR Block of the subnets and the parameters to 244 | calculate each CIDR Block. 245 | 246 | Default is the CIDR Block of the VPC (`cidr_block`). 247 | 248 | - [**`newbits`**](#attr-subnets-newbits): *(Optional `number`)* 249 | 250 | How many bits should be added when calculating the subnets CIDR 251 | Blocks. 252 | 253 | Default is `8`. 254 | 255 | - [**`netnums_by_az`**](#attr-subnets-netnums_by_az): *(**Required** `map(netnums_by_az)`)* 256 | 257 | Type is map(list(number)). 258 | 259 | A map of subnets keyed by availability zone suffix (a,b,c,d,e,f). 260 | The numbers define the network number with in the CIDR Block. 261 | See https://www.terraform.io/docs/configuration/functions/cidrsubnet.html 262 | for details on how this is calculated internally. 263 | 264 | Note: When adjusting cidr_block or newbits you might also need to 265 | adjust the netnums. 266 | The example shows how to deploy one subnet in availability zone 267 | `a` (`10.0.0.0/24`) and one subnet in availability zone `b` 268 | (`10.0.1.0/24`). 269 | 270 | Example: 271 | 272 | ```hcl 273 | cidr_block = "10.0.0.0/16" 274 | newbits = 8 275 | 276 | netnums_by_az = { 277 | a = [0] # "10.0.0.0/24" 278 | b = [1] # "10.0.1.0/24" 279 | } 280 | ``` 281 | 282 | - [**`db_subnet_group_name`**](#attr-subnets-db_subnet_group_name): *(Optional `string`)* 283 | 284 | The name of a db subnet group to create for all netnum ranges in 285 | this subnet. 286 | The `db_subnet_group_name` resource tags will be cloned from the 287 | subnets. 288 | 289 | - [**`elasticache_subnet_group_name`**](#attr-subnets-elasticache_subnet_group_name): *(Optional `string`)* 290 | 291 | The name of a elasticache subnet group to create for all netnum 292 | ranges in this subnet. 293 | The `elasticache_subnet_group_name` resource tags will be cloned 294 | from the subnets. 295 | 296 | - [**`tags`**](#attr-subnets-tags): *(Optional `map(string)`)* 297 | 298 | A map of tags that will be applied to each subnet in this 299 | group-class combination. 300 | Those tags will be merged with a `Name` tag, `module_tags`, 301 | `subnet_tags` and tags for the subnet class 302 | `public_subnet_tags`, `private_subnet_tags`, or 303 | `intra_subnet_tags`. 304 | 305 | To set the Name and add the capability to be used in data 306 | sources the `subnet_tags` will always be merged with: 307 | 308 | ```hcl 309 | { 310 | Name = "{vpc_name}-{subnet.group}-{subnet.class}-{az}-{idx}" 311 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 312 | "mineiros-io/aws/vpc/subnet-name" = "{vpc_name}-{subnet.group}-{subnet.class}-{az}-{idx}" 313 | "mineiros-io/aws/vpc/subnet-group" = "{subnet.group}" 314 | "mineiros-io/aws/vpc/subnet-class" = "{subnet.class}" 315 | } 316 | ``` 317 | 318 | Default is `{}`. 319 | 320 | - [**`subnet_tags`**](#var-subnet_tags): *(Optional `map(string)`)* 321 | 322 | Tags applied to each subnet resource. 323 | 324 | Default is `{}`. 325 | 326 | - [**`public_subnet_tags`**](#var-public_subnet_tags): *(Optional `map(string)`)* 327 | 328 | Tags applied to each public subnet. 329 | 330 | Default is `{}`. 331 | 332 | - [**`private_subnet_tags`**](#var-private_subnet_tags): *(Optional `map(string)`)* 333 | 334 | Tags applied to each private subnet. 335 | 336 | Default is `{}`. 337 | 338 | - [**`intra_subnet_tags`**](#var-intra_subnet_tags): *(Optional `map(string)`)* 339 | 340 | Tags applied to each intra subnet. 341 | 342 | Default is `{}`. 343 | 344 | #### Internet Gateway 345 | 346 | - [**`internet_gateway_tags`**](#var-internet_gateway_tags): *(Optional `map(string)`)* 347 | 348 | A map of tags to apply to the created Internet Gateway. 349 | An Internet Gateway is created if a public subnet is defined. 350 | All public egress and ingress traffic of all public subnets will be 351 | routed through the same Internet Gateway. 352 | 353 | To set the Name and add the capability to be used in data sources 354 | the `internet_gateway_tags` will always be merged with: 355 | 356 | ```hcl 357 | { 358 | Name = "{vpc_name}" 359 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 360 | "mineiros-io/aws/vpc/igw-name" = "{vpc_name}" 361 | } 362 | ``` 363 | 364 | Default is `{}`. 365 | 366 | #### NAT Gateways 367 | 368 | > **A Note on pricing:** AWS charges for each provisioned NAT 369 | Gateway. Please see https://aws.amazon.com/vpc/pricing/ for details. 370 | > To save costs you can use `nat_gateway_mode` to define the number 371 | of NAT Gateways you want to deploy. 372 | > The best practice is to deploy one NAT Gateway per Availability 373 | Zone for higher reliability on production environments 374 | (`one_per_az`), while you can save some costs on staging and testing 375 | environments by deploying a single NAT Gateway (`single`). 376 | 377 | - [**`nat_gateway_mode`**](#var-nat_gateway_mode): *(Optional `string`)* 378 | 379 | Set the mode for the NAT Gateways. NAT Gateways will only be created 380 | when private subnets are defined. 381 | Each private subnet needs at least one configured public subnet in 382 | the same availability zone. 383 | Each NAT gateway will be assigned an Elastic IP Address. 384 | When changing the mode, NAT Gateways and Elastic IP Addresses will 385 | be created or destroyed. 386 | All public egress traffic of all private subnets will be routed 387 | through the same set of NAT Gateways. 388 | Possible modes are `none`, `single`, or `one_per_az`. Choose 389 | 390 | - `"none"` to create no NAT Gateways at all (use for debugging only), 391 | - `"single"` to create a single NAT Gateway inside the first defined 392 | Public Subnet, or 393 | - `"one_per_az"` to create one NAT Gateway inside the first Public 394 | Subnet in each Availability Zone. 395 | 396 | Default is `"single"`. 397 | 398 | - [**`nat_gateway_single_mode_zone`**](#var-nat_gateway_single_mode_zone): *(Optional `string`)* 399 | 400 | Define the zone (short name) of the NAT gateway when nat_gateway_mode is "single" (e.g. "a", "b", or "c"). 401 | The AWS region will be added as a prefix. 402 | 403 | Default is `"a random zone"`. 404 | 405 | - [**`nat_gateway_eip_allocation_ids`**](#var-nat_gateway_eip_allocation_ids): *(Optional `map(string)`)* 406 | 407 | A map of EIP allocation ids to use for nat gateways keyed by short zone name (e.g. "a", "b", or "c"). 408 | If set no EIPs will be created by the module. If unset, the module will create the needed number of EIPs. 409 | 410 | Default is `{}`. 411 | 412 | - [**`nat_gateway_tags`**](#var-nat_gateway_tags): *(Optional `map(string)`)* 413 | 414 | A map of tags to apply to the created NAT Gateways. 415 | 416 | To set the Name and add the capability to be used in data sources 417 | the `nat_gateway_tags` will always be merged with: 418 | 419 | ```hcl 420 | { 421 | Name = "{vpc_name}-{zone}" 422 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 423 | "mineiros-io/aws/vpc/natgw-name" = "{vpc_name}-{zone}" 424 | } 425 | ``` 426 | 427 | Default is `{}`. 428 | 429 | - [**`eip_tags`**](#var-eip_tags): *(Optional `map(string)`)* 430 | 431 | A map of tags to apply to the created NAT Gateway Elastic IP 432 | Addresses. 433 | 434 | To set the Name and add the capability to be used in data sources 435 | the `eip_tags` will always be merged with: 436 | 437 | ```hcl 438 | { 439 | Name = "{vpc_name}-nat-private-{zone}" 440 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 441 | "mineiros-io/aws/vpc/natgw-name" = "{vpc_name}-{zone}" 442 | "mineiros-io/aws/vpc/eip-name" = "{vpc_name}-nat-private-{zone}" 443 | } 444 | ``` 445 | 446 | Default is `{}`. 447 | 448 | #### Subnet Routing 449 | 450 | - [**`route_table_tags`**](#var-route_table_tags): *(Optional `map(string)`)* 451 | 452 | A map of tags to apply to all created Route Tables. 453 | 454 | Default is `{}`. 455 | 456 | - [**`public_route_table_tags`**](#var-public_route_table_tags): *(Optional `map(string)`)* 457 | 458 | A map of tags to apply to the created Public Route Tables. 459 | 460 | To set the Name and add the capability to be used in data sources 461 | the `public_route_table_tags` will always be merged with: 462 | 463 | ```hcl 464 | { 465 | Name = "{vpc_name}-public-{group}" 466 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 467 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-public-{group}" 468 | "mineiros-io/aws/vpc/routetable-class" = "public" 469 | } 470 | ``` 471 | 472 | Default is `{}`. 473 | 474 | - [**`private_route_table_tags`**](#var-private_route_table_tags): *(Optional `map(string)`)* 475 | 476 | A map of tags to apply to the created Private Route Tables. 477 | 478 | To set the Name and add the capability to be used in data sources 479 | the `private_route_table_tags` will always be merged with: 480 | 481 | ```hcl 482 | { 483 | Name = "{vpc_name}-private-{group}-{zone}" 484 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 485 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-private-{group}-{zone}" 486 | "mineiros-io/aws/vpc/routetable-class" = "private" 487 | } 488 | ``` 489 | 490 | Default is `{}`. 491 | 492 | - [**`intra_route_table_tags`**](#var-intra_route_table_tags): *(Optional `map(string)`)* 493 | 494 | A map of tags to apply to the created Intra Route Tables. 495 | 496 | To set the Name and add the capability to be used in data sources 497 | the `intra_route_table_tags` will always be merged with: 498 | 499 | ```hcl 500 | { 501 | Name = "{vpc_name}-intra-{group}" 502 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 503 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-intra-{group}" 504 | "mineiros-io/aws/vpc/routetable-class" = "intra" 505 | } 506 | ``` 507 | 508 | Default is `{}`. 509 | 510 | ## Module Configuration 511 | 512 | - [**`module_enabled`**](#var-module_enabled): *(Optional `bool`)* 513 | 514 | Specifies whether resources in the module will be created. 515 | 516 | Default is `true`. 517 | 518 | - [**`module_tags`**](#var-module_tags): *(Optional `map(string)`)* 519 | 520 | A map of tags that will be applied to all created resources that 521 | accept tags. Tags defined with 'module_tags' can be 522 | overwritten by resource-specific tags. 523 | 524 | Default is `{}`. 525 | 526 | - [**`module_depends_on`**](#var-module_depends_on): *(Optional `list(dependency)`)* 527 | 528 | A list of dependencies. Any object can be _assigned_ to this list to 529 | define a hidden external dependency. 530 | 531 | ## Module Outputs 532 | 533 | The following attributes are exported by the module: 534 | 535 | ### Computed Attributes 536 | 537 | - [**`public_subnets_by_group`**](#output-public_subnets_by_group): *(`map(public_subnets_by_group)`)* 538 | 539 | A map of lists of public subnets keyed by group. (`aws_subnet`) 540 | 541 | - [**`public_route_table_ids_by_group`**](#output-public_route_table_ids_by_group): *(`map(public_route_table_ids_by_group)`)* 542 | 543 | A map of lists of public route table IDs keyed by group. 544 | 545 | - [**`public_subnet_ids_by_group`**](#output-public_subnet_ids_by_group): *(`map(public_subnet_ids_by_group)`)* 546 | 547 | A map of lists of public subnet IDs keyed by group. 548 | 549 | - [**`private_subnets_by_group`**](#output-private_subnets_by_group): *(`map(private_subnets_by_group)`)* 550 | 551 | A map of lists of private subnets keyed by group. (`aws_subnet`) 552 | 553 | - [**`private_route_table_ids_by_group`**](#output-private_route_table_ids_by_group): *(`map(private_route_table_ids_by_group)`)* 554 | 555 | A map of lists of private route table IDs keyed by group. 556 | 557 | - [**`private_subnet_ids_by_group`**](#output-private_subnet_ids_by_group): *(`map(private_subnet_ids_by_group)`)* 558 | 559 | A map of lists of private subnet IDs keyed by group. 560 | 561 | - [**`intra_subnets_by_group`**](#output-intra_subnets_by_group): *(`map(intra_subnets_by_group)`)* 562 | 563 | A map of lists of intra aws_subnet keyed by group. (`aws_subnet`) 564 | 565 | - [**`intra_route_table_ids_by_group`**](#output-intra_route_table_ids_by_group): *(`map(intra_route_table_ids_by_group)`)* 566 | 567 | A map of lists of intra route table IDs keyed by group. 568 | 569 | - [**`intra_subnet_ids_by_group`**](#output-intra_subnet_ids_by_group): *(`map(intra_subnet_ids_by_group)`)* 570 | 571 | A map of lists of intra subnet IDs keyed by group. 572 | 573 | ### Full Resource Objects 574 | 575 | - [**`vpc`**](#output-vpc): *(`object(vpc)`)* 576 | 577 | The VPC. (`aws_vpc`) 578 | 579 | - [**`intra_route_tables`**](#output-intra_route_tables): *(`map(intra_route_tables)`)* 580 | 581 | A map of intra route tables keyed by group. (`aws_route_table`) 582 | 583 | - [**`intra_route_table_associations`**](#output-intra_route_table_associations): *(`map(intra_route_table_associations)`)* 584 | 585 | A map of intra route table associations keyed by the subnets CIDR 586 | Blocks. (`aws_route_table_association`) 587 | 588 | - [**`eips`**](#output-eips): *(`map(eips)`)* 589 | 590 | A map of Elastic IP Adresses (EIPs) keyed by availability zone. 591 | (`aws_eip`) 592 | 593 | - [**`nat_gateways`**](#output-nat_gateways): *(`map(nat_gateways)`)* 594 | 595 | A map of NAT gatweways keyed by availability zone. 596 | (`aws_nat_gateway`) 597 | 598 | - [**`private_route_tables`**](#output-private_route_tables): *(`map(private_route_tables)`)* 599 | 600 | A map of private route tables keyed by group. (`aws_route_table`) 601 | 602 | - [**`private_route_table_associations`**](#output-private_route_table_associations): *(`map(private_route_table_associations)`)* 603 | 604 | A map of private route table associations keyed by the subnets CIDR 605 | Blocks. (`aws_route_table_association`) 606 | 607 | - [**`routes_to_nat_gateways`**](#output-routes_to_nat_gateways): *(`map(routes_to_nat_gateways)`)* 608 | 609 | A map of routes to the NAT Gateways keyed by group. (`aws_route`) 610 | 611 | - [**`internet_gateway`**](#output-internet_gateway): *(`object(internet_gateway)`)* 612 | 613 | The Internet Gateway. (`aws_internet_gateway`) 614 | 615 | - [**`public_route_tables`**](#output-public_route_tables): *(`map(public_route_tables)`)* 616 | 617 | A map of public route tables keyed by group. (`aws_route_table`) 618 | 619 | - [**`public_route_table_associations`**](#output-public_route_table_associations): *(`map(public_route_table_associations)`)* 620 | 621 | A map of public route table associations keyed by the subnets CIDR 622 | Blocks. (`aws_route_table_association`) 623 | 624 | - [**`routes_to_internet_gateway`**](#output-routes_to_internet_gateway): *(`map(routes_to_internet_gateway)`)* 625 | 626 | A map of routes to the Internet Gateway keyed by group. (`aws_route`) 627 | 628 | - [**`subnets`**](#output-subnets): *(`map(subnets)`)* 629 | 630 | A map of subnets keyed by CIDR Blocks. (`aws_subnet`) 631 | 632 | ### Module Attributes 633 | 634 | - [**`module_inputs`**](#output-module_inputs): *(`map(module_inputs)`)* 635 | 636 | A map of all module arguments. Set to the provided values or calculated default values. 637 | 638 | - [**`module_enabled`**](#output-module_enabled): *(`bool`)* 639 | 640 | Whether this module is enabled. 641 | 642 | - [**`module_tags`**](#output-module_tags): *(`map(string)`)* 643 | 644 | The map of tags that are being applied to all created resources that accept tags. 645 | 646 | ## External Documentation 647 | 648 | ### AWS Documentation VPC 649 | 650 | - https://aws.amazon.com/de/vpc/ 651 | 652 | ### Terraform AWS Provider Documentation: 653 | 654 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc 655 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet 656 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway 657 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway 658 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table 659 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association 660 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route 661 | 662 | ## Module Versioning 663 | 664 | This Module follows the principles of [Semantic Versioning (SemVer)]. 665 | 666 | Given a version number `MAJOR.MINOR.PATCH`, we increment the: 667 | 668 | 1. `MAJOR` version when we make incompatible changes, 669 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and 670 | 3. `PATCH` version when we make backwards compatible bug fixes. 671 | 672 | ### Backwards compatibility in `0.0.z` and `0.y.z` version 673 | 674 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) 675 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) 676 | 677 | ## About Mineiros 678 | 679 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany 680 | that solves development, automation and security challenges in cloud infrastructure. 681 | 682 | Our vision is to massively reduce time and overhead for teams to manage and 683 | deploy production-grade and secure cloud infrastructure. 684 | 685 | We offer commercial support for all of our modules and encourage you to reach out 686 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our 687 | [Community Slack channel][slack]. 688 | 689 | ## Reporting Issues 690 | 691 | We use GitHub [Issues] to track community reported issues and missing features. 692 | 693 | ## Contributing 694 | 695 | Contributions are always encouraged and welcome! For the process of accepting changes, we use 696 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines]. 697 | 698 | ## Makefile Targets 699 | 700 | This repository comes with a handy [Makefile]. 701 | Run `make help` to see details on each available target. 702 | 703 | ## License 704 | 705 | [![license][badge-license]][apache20] 706 | 707 | This module is licensed under the Apache License Version 2.0, January 2004. 708 | Please see [LICENSE] for full details. 709 | 710 | Copyright © 2019-2022 [Mineiros GmbH][homepage] 711 | 712 | 713 | 714 | 715 | [homepage]: https://mineiros.io/?ref=terraform-aws-vpc 716 | [hello@mineiros.io]: mailto:hello@mineiros.io 717 | [badge-build]: https://github.com/mineiros-io/terraform-aws-vpc/workflows/CI/CD%20Pipeline/badge.svg 718 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-vpc.svg?label=latest&sort=semver 719 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 720 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 721 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 722 | [build-status]: https://github.com/mineiros-io/terraform-aws-vpc/actions 723 | [releases-github]: https://github.com/mineiros-io/terraform-aws-vpc/releases 724 | [badge-tf-aws]: https://img.shields.io/badge/AWS-3%20and%202.45+-F8991D.svg?logo=terraform 725 | [releases-aws-provider]: https://github.com/terraform-providers/terraform-provider-aws/releases 726 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 727 | [apache20]: https://opensource.org/licenses/Apache-2.0 728 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 729 | [terraform]: https://www.terraform.io 730 | [aws]: https://aws.amazon.com/ 731 | [semantic versioning (semver)]: https://semver.org/ 732 | [variables.tf]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/variables.tf 733 | [examples/]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/examples 734 | [issues]: https://github.com/mineiros-io/terraform-aws-vpc/issues 735 | [license]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/LICENSE 736 | [makefile]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/Makefile 737 | [pull requests]: https://github.com/mineiros-io/terraform-aws-vpc/pulls 738 | [contribution guidelines]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/CONTRIBUTING.md 739 | -------------------------------------------------------------------------------- /README.tfdoc.hcl: -------------------------------------------------------------------------------- 1 | header { 2 | image = "https://raw.githubusercontent.com/mineiros-io/brand/3bffd30e8bdbbde32c143e2650b2faa55f1df3ea/mineiros-primary-logo.svg" 3 | url = "https://mineiros.io/?ref=terraform-aws-vpc" 4 | 5 | badge "build" { 6 | image = "https://github.com/mineiros-io/terraform-aws-vpc/workflows/CI/CD%20Pipeline/badge.svg" 7 | url = "https://github.com/mineiros-io/terraform-aws-vpc/actions" 8 | text = "Build Status" 9 | } 10 | 11 | badge "semver" { 12 | image = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-vpc.svg?label=latest&sort=semver" 13 | url = "https://github.com/mineiros-io/terraform-aws-vpc/releases" 14 | text = "GitHub tag (latest SemVer)" 15 | } 16 | 17 | badge "terraform" { 18 | image = "https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform" 19 | url = "https://github.com/hashicorp/terraform/releases" 20 | text = "Terraform Version" 21 | } 22 | 23 | badge "tf-aws-provider" { 24 | image = "https://img.shields.io/badge/AWS-3%20and%202.45+-F8991D.svg?logo=terraform" 25 | url = "https://github.com/terraform-providers/terraform-provider-aws/releases" 26 | text = "AWS Provider Version" 27 | } 28 | 29 | badge "slack" { 30 | image = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack" 31 | url = "https://mineiros.io/slack" 32 | text = "Join Slack" 33 | } 34 | } 35 | 36 | section { 37 | title = "terraform-aws-vpc" 38 | toc = true 39 | content = <<-END 40 | A [Terraform] base module for managing an 41 | [Amazon Virtual Private Cloud](https://aws.amazon.com/de/vpc/) on 42 | [Amazon Web Services (AWS)][aws]. 43 | 44 | ***This module supports Terraform v0.15, v0.14, v0.13, as well as v0.12.20 and above 45 | and is compatible with the terraform AWS provider v3 as well as v2.45 and above.*** 46 | 47 | This module is part of our Infrastructure as Code (IaC) framework 48 | that enables our users and customers to easily deploy and manage reusable, 49 | secure, and production-grade cloud infrastructure. 50 | END 51 | 52 | section { 53 | title = "Module Features" 54 | content = <<-END 55 | This module implements the following Terraform resources 56 | 57 | - `aws_region` 58 | - `aws_vpc` 59 | - `aws_subnet` 60 | - `aws_eip` 61 | - `aws_nat_gateway` 62 | - `aws_route_table` 63 | - `aws_route_table_association` 64 | - `aws_route` 65 | - `aws_internet_gateway` 66 | - `aws_route_table` 67 | - `aws_route_table_association` 68 | - `aws_route` 69 | - `aws_elasticache_subnet_group` 70 | - `aws_db_subnet_group` 71 | END 72 | } 73 | 74 | section { 75 | title = "Getting Started" 76 | content = <<-END 77 | Most basic usage just setting required arguments: 78 | 79 | ```hcl 80 | module "terraform-aws-vpc" { 81 | source = "mineiros-io/vpc/aws" 82 | version = "~> 0.7.0" 83 | } 84 | ``` 85 | END 86 | } 87 | 88 | section { 89 | title = "Module Argument Reference" 90 | content = <<-END 91 | See [variables.tf] and [examples/] for details and use-cases. 92 | END 93 | 94 | section { 95 | title = "Main Resource Configuration" 96 | 97 | section { 98 | title = "VPC" 99 | 100 | variable "vpc_name" { 101 | type = string 102 | default = "main" 103 | description = <<-END 104 | The name of the VPC. This will be used to tag resources with names 105 | by default. 106 | END 107 | } 108 | 109 | variable "cidr_block" { 110 | type = string 111 | default = "10.0.0.0/16" 112 | description = <<-END 113 | The CIDR block for the VPC. 114 | END 115 | } 116 | 117 | variable "instance_tenancy" { 118 | type = string 119 | default = "default" 120 | description = <<-END 121 | A tenancy option for instances launched into the VPC. 122 | Setting the tenancy to `dedicated` will create additional costs: See 123 | https://aws.amazon.com/ec2/pricing/dedicated-instances/ for details. 124 | END 125 | } 126 | 127 | variable "enable_dns_support" { 128 | type = bool 129 | default = true 130 | description = <<-END 131 | A boolean flag to enable/disable DNS support in the VPC. 132 | END 133 | } 134 | 135 | variable "enable_dns_hostnames" { 136 | type = bool 137 | default = false 138 | description = <<-END 139 | A boolean flag to enable/disable DNS hostnames in the VPC. 140 | END 141 | } 142 | 143 | variable "enable_classiclink" { 144 | type = bool 145 | default = false 146 | description = <<-END 147 | A boolean flag to enable/disable ClassicLink for the VPC. Only valid 148 | in regions and accounts that support EC2 Classic. See the 149 | ClassicLink documentation for more information. 150 | END 151 | } 152 | 153 | variable "enable_classiclink_dns_support" { 154 | type = bool 155 | default = false 156 | description = <<-END 157 | A boolean flag to enable/disable ClassicLink DNS Support for the 158 | VPC. Only valid in regions and accounts that support EC2 Classic. 159 | END 160 | } 161 | 162 | variable "assign_generated_ipv6_cidr_block" { 163 | type = bool 164 | default = false 165 | description = <<-END 166 | Requests an Amazon-provided IPv6 CIDR block with a /56 prefix length 167 | for the VPC. You cannot specify the range of IP addresses, or the 168 | size of the CIDR block. 169 | END 170 | } 171 | 172 | variable "vpc_tags" { 173 | type = string 174 | default = "{}" 175 | description = <<-END 176 | A map of tags to assign to the vpc resource. 177 | To set the Name and add the capability to be used in data sources 178 | the `vpc_tags` will always be merged with: 179 | END 180 | readme_example = <<-END 181 | { 182 | Name = "{vpc_name}" 183 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 184 | } 185 | END 186 | } 187 | } 188 | } 189 | 190 | section { 191 | title = "Extended Resource Configuration" 192 | 193 | section { 194 | title = "Subnets" 195 | 196 | variable "subnets" { 197 | type = list(subnet) 198 | default = [] 199 | description = <<-END 200 | A List of `subnet` objects that defined the subnet setup within the 201 | VPC. 202 | END 203 | readme_example = <<-END 204 | subnets = [ 205 | { 206 | group = "main" 207 | class = "public" 208 | 209 | map_public_ip_on_launch = true 210 | 211 | cidr_block = cidrsubnet("10.0.0.0/16", 4, 0) 212 | newbits = 4 213 | 214 | netnums_by_az = { 215 | a = [0] # "10.0.0.0/24" 216 | b = [1] # "10.0.1.0/24" 217 | } 218 | tags = {} 219 | }, 220 | { 221 | group = "main" 222 | class = "private" 223 | 224 | map_public_ip_on_launch = false 225 | 226 | cidr_block = cidrsubnet("10.0.0.0/16", 4, 1) 227 | newbits = 4 228 | 229 | netnums_by_az = { 230 | a = [0] # "10.0.16.0/24" 231 | b = [1] # "10.0.17.0/24" 232 | } 233 | }, 234 | ] 235 | END 236 | 237 | attribute "group" { 238 | type = string 239 | default = "main" 240 | description = <<-END 241 | A group name for the subnets. This can be any string. This 242 | information is used to group and tag resources within the subnets. 243 | The combination of `group` and `class` needs to be unique over all 244 | subnets defined. This can be changed at any time and will change 245 | the tags applied to resources by default. 246 | END 247 | } 248 | 249 | attribute "class" { 250 | type = string 251 | default = "private" 252 | description = <<-END 253 | The class of the subnet. This can be `"public"`, `"private"`, or 254 | "`intra`". This can be changed at any time and will change the 255 | routing of the subnet instead of recreating the subnet resource. 256 | 257 | - "public" defines a set of subnets where deployed components are 258 | reachable via the public Internet. 259 | - "private" defines a set of subnets where components are not 260 | publicly reachable but can reach the Internet. 261 | - "intra" defines a set of subnets that have no connectivity to 262 | the public Internet. 263 | END 264 | } 265 | 266 | attribute "map_public_ip_on_launch" { 267 | type = bool 268 | default = true 269 | description = <<-END 270 | Whether resources deployed into the subnet will be assigned a 271 | public IPv4 address when launched. 272 | END 273 | } 274 | 275 | attribute "cidr_block" { 276 | type = string 277 | description = <<-END 278 | Define the base CIDR Block of the subnets and the parameters to 279 | calculate each CIDR Block. 280 | 281 | Default is the CIDR Block of the VPC (`cidr_block`). 282 | END 283 | } 284 | 285 | attribute "newbits" { 286 | type = number 287 | default = 8 288 | description = <<-END 289 | How many bits should be added when calculating the subnets CIDR 290 | Blocks. 291 | END 292 | } 293 | 294 | attribute "netnums_by_az" { 295 | required = true 296 | type = map(netnums_by_az) 297 | description = <<-END 298 | Type is map(list(number)). 299 | 300 | A map of subnets keyed by availability zone suffix (a,b,c,d,e,f). 301 | The numbers define the network number with in the CIDR Block. 302 | See https://www.terraform.io/docs/configuration/functions/cidrsubnet.html 303 | for details on how this is calculated internally. 304 | 305 | Note: When adjusting cidr_block or newbits you might also need to 306 | adjust the netnums. 307 | The example shows how to deploy one subnet in availability zone 308 | `a` (`10.0.0.0/24`) and one subnet in availability zone `b` 309 | (`10.0.1.0/24`). 310 | END 311 | readme_example = <<-END 312 | cidr_block = "10.0.0.0/16" 313 | newbits = 8 314 | 315 | netnums_by_az = { 316 | a = [0] # "10.0.0.0/24" 317 | b = [1] # "10.0.1.0/24" 318 | } 319 | END 320 | } 321 | 322 | attribute "db_subnet_group_name" { 323 | type = string 324 | description = <<-END 325 | The name of a db subnet group to create for all netnum ranges in 326 | this subnet. 327 | The `db_subnet_group_name` resource tags will be cloned from the 328 | subnets. 329 | END 330 | } 331 | 332 | attribute "elasticache_subnet_group_name" { 333 | type = string 334 | description = <<-END 335 | The name of a elasticache subnet group to create for all netnum 336 | ranges in this subnet. 337 | The `elasticache_subnet_group_name` resource tags will be cloned 338 | from the subnets. 339 | END 340 | } 341 | 342 | attribute "tags" { 343 | type = map(string) 344 | default = {} 345 | description = <<-END 346 | A map of tags that will be applied to each subnet in this 347 | group-class combination. 348 | Those tags will be merged with a `Name` tag, `module_tags`, 349 | `subnet_tags` and tags for the subnet class 350 | `public_subnet_tags`, `private_subnet_tags`, or 351 | `intra_subnet_tags`. 352 | 353 | To set the Name and add the capability to be used in data 354 | sources the `subnet_tags` will always be merged with: 355 | 356 | ```hcl 357 | { 358 | Name = "{vpc_name}-{subnet.group}-{subnet.class}-{az}-{idx}" 359 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 360 | "mineiros-io/aws/vpc/subnet-name" = "{vpc_name}-{subnet.group}-{subnet.class}-{az}-{idx}" 361 | "mineiros-io/aws/vpc/subnet-group" = "{subnet.group}" 362 | "mineiros-io/aws/vpc/subnet-class" = "{subnet.class}" 363 | } 364 | ``` 365 | END 366 | } 367 | } 368 | 369 | variable "subnet_tags" { 370 | type = map(string) 371 | default = {} 372 | description = <<-END 373 | Tags applied to each subnet resource. 374 | END 375 | } 376 | 377 | variable "public_subnet_tags" { 378 | type = map(string) 379 | default = {} 380 | description = <<-END 381 | Tags applied to each public subnet. 382 | END 383 | } 384 | 385 | variable "private_subnet_tags" { 386 | type = map(string) 387 | default = {} 388 | description = <<-END 389 | Tags applied to each private subnet. 390 | END 391 | } 392 | 393 | variable "intra_subnet_tags" { 394 | type = map(string) 395 | default = {} 396 | description = <<-END 397 | Tags applied to each intra subnet. 398 | END 399 | } 400 | } 401 | 402 | section { 403 | title = "Internet Gateway" 404 | 405 | variable "internet_gateway_tags" { 406 | type = map(string) 407 | default = {} 408 | description = <<-END 409 | A map of tags to apply to the created Internet Gateway. 410 | An Internet Gateway is created if a public subnet is defined. 411 | All public egress and ingress traffic of all public subnets will be 412 | routed through the same Internet Gateway. 413 | 414 | To set the Name and add the capability to be used in data sources 415 | the `internet_gateway_tags` will always be merged with: 416 | 417 | ```hcl 418 | { 419 | Name = "{vpc_name}" 420 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 421 | "mineiros-io/aws/vpc/igw-name" = "{vpc_name}" 422 | } 423 | ``` 424 | END 425 | } 426 | } 427 | 428 | section { 429 | title = "NAT Gateways" 430 | content = <<-END 431 | > **A Note on pricing:** AWS charges for each provisioned NAT 432 | Gateway. Please see https://aws.amazon.com/vpc/pricing/ for details. 433 | > To save costs you can use `nat_gateway_mode` to define the number 434 | of NAT Gateways you want to deploy. 435 | > The best practice is to deploy one NAT Gateway per Availability 436 | Zone for higher reliability on production environments 437 | (`one_per_az`), while you can save some costs on staging and testing 438 | environments by deploying a single NAT Gateway (`single`). 439 | END 440 | 441 | variable "nat_gateway_mode" { 442 | type = string 443 | default = "single" 444 | description = <<-END 445 | Set the mode for the NAT Gateways. NAT Gateways will only be created 446 | when private subnets are defined. 447 | Each private subnet needs at least one configured public subnet in 448 | the same availability zone. 449 | Each NAT gateway will be assigned an Elastic IP Address. 450 | When changing the mode, NAT Gateways and Elastic IP Addresses will 451 | be created or destroyed. 452 | All public egress traffic of all private subnets will be routed 453 | through the same set of NAT Gateways. 454 | Possible modes are `none`, `single`, or `one_per_az`. Choose 455 | 456 | - `"none"` to create no NAT Gateways at all (use for debugging only), 457 | - `"single"` to create a single NAT Gateway inside the first defined 458 | Public Subnet, or 459 | - `"one_per_az"` to create one NAT Gateway inside the first Public 460 | Subnet in each Availability Zone. 461 | END 462 | } 463 | 464 | variable "nat_gateway_single_mode_zone" { 465 | type = string 466 | default = "a random zone" 467 | description = <<-END 468 | Define the zone (short name) of the NAT gateway when nat_gateway_mode is "single" (e.g. "a", "b", or "c"). 469 | The AWS region will be added as a prefix. 470 | END 471 | } 472 | 473 | variable "nat_gateway_eip_allocation_ids" { 474 | type = map(string) 475 | description = <<-END 476 | A map of EIP allocation ids to use for nat gateways keyed by short zone name (e.g. "a", "b", or "c"). 477 | If set no EIPs will be created by the module. If unset, the module will create the needed number of EIPs. 478 | END 479 | default = {} 480 | } 481 | 482 | variable "nat_gateway_tags" { 483 | type = map(string) 484 | default = {} 485 | description = <<-END 486 | A map of tags to apply to the created NAT Gateways. 487 | 488 | To set the Name and add the capability to be used in data sources 489 | the `nat_gateway_tags` will always be merged with: 490 | 491 | ```hcl 492 | { 493 | Name = "{vpc_name}-{zone}" 494 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 495 | "mineiros-io/aws/vpc/natgw-name" = "{vpc_name}-{zone}" 496 | } 497 | ``` 498 | END 499 | } 500 | 501 | variable "eip_tags" { 502 | type = map(string) 503 | default = {} 504 | description = <<-END 505 | A map of tags to apply to the created NAT Gateway Elastic IP 506 | Addresses. 507 | 508 | To set the Name and add the capability to be used in data sources 509 | the `eip_tags` will always be merged with: 510 | 511 | ```hcl 512 | { 513 | Name = "{vpc_name}-nat-private-{zone}" 514 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 515 | "mineiros-io/aws/vpc/natgw-name" = "{vpc_name}-{zone}" 516 | "mineiros-io/aws/vpc/eip-name" = "{vpc_name}-nat-private-{zone}" 517 | } 518 | ``` 519 | END 520 | } 521 | } 522 | 523 | section { 524 | title = "Subnet Routing" 525 | 526 | variable "route_table_tags" { 527 | type = map(string) 528 | default = {} 529 | description = <<-END 530 | A map of tags to apply to all created Route Tables. 531 | END 532 | } 533 | 534 | variable "public_route_table_tags" { 535 | type = map(string) 536 | default = {} 537 | description = <<-END 538 | A map of tags to apply to the created Public Route Tables. 539 | 540 | To set the Name and add the capability to be used in data sources 541 | the `public_route_table_tags` will always be merged with: 542 | 543 | ```hcl 544 | { 545 | Name = "{vpc_name}-public-{group}" 546 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 547 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-public-{group}" 548 | "mineiros-io/aws/vpc/routetable-class" = "public" 549 | } 550 | ``` 551 | END 552 | } 553 | 554 | variable "private_route_table_tags" { 555 | type = map(string) 556 | default = {} 557 | description = <<-END 558 | A map of tags to apply to the created Private Route Tables. 559 | 560 | To set the Name and add the capability to be used in data sources 561 | the `private_route_table_tags` will always be merged with: 562 | 563 | ```hcl 564 | { 565 | Name = "{vpc_name}-private-{group}-{zone}" 566 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 567 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-private-{group}-{zone}" 568 | "mineiros-io/aws/vpc/routetable-class" = "private" 569 | } 570 | ``` 571 | END 572 | } 573 | 574 | variable "intra_route_table_tags" { 575 | type = map(string) 576 | default = {} 577 | description = <<-END 578 | A map of tags to apply to the created Intra Route Tables. 579 | 580 | To set the Name and add the capability to be used in data sources 581 | the `intra_route_table_tags` will always be merged with: 582 | 583 | ```hcl 584 | { 585 | Name = "{vpc_name}-intra-{group}" 586 | "mineiros-io/aws/vpc/vpc-name" = "{vpc_name}" 587 | "mineiros-io/aws/vpc/routetable-name" = "{vpc_name}-intra-{group}" 588 | "mineiros-io/aws/vpc/routetable-class" = "intra" 589 | } 590 | ``` 591 | END 592 | } 593 | } 594 | } 595 | } 596 | 597 | section { 598 | title = "Module Configuration" 599 | 600 | variable "module_enabled" { 601 | type = bool 602 | default = true 603 | description = <<-END 604 | Specifies whether resources in the module will be created. 605 | END 606 | } 607 | 608 | variable "module_tags" { 609 | type = map(string) 610 | default = {} 611 | description = <<-END 612 | A map of tags that will be applied to all created resources that 613 | accept tags. Tags defined with 'module_tags' can be 614 | overwritten by resource-specific tags. 615 | END 616 | } 617 | 618 | variable "module_depends_on" { 619 | type = list(dependency) 620 | description = <<-END 621 | A list of dependencies. Any object can be _assigned_ to this list to 622 | define a hidden external dependency. 623 | END 624 | } 625 | } 626 | 627 | section { 628 | title = "Module Outputs" 629 | content = <<-END 630 | The following attributes are exported by the module: 631 | END 632 | 633 | section { 634 | title = "Computed Attributes" 635 | 636 | output "public_subnets_by_group" { 637 | type = map(public_subnets_by_group) 638 | description = <<-END 639 | A map of lists of public subnets keyed by group. (`aws_subnet`) 640 | END 641 | } 642 | 643 | output "public_route_table_ids_by_group" { 644 | type = map(public_route_table_ids_by_group) 645 | description = <<-END 646 | A map of lists of public route table IDs keyed by group. 647 | END 648 | } 649 | 650 | output "public_subnet_ids_by_group" { 651 | type = map(public_subnet_ids_by_group) 652 | description = <<-END 653 | A map of lists of public subnet IDs keyed by group. 654 | END 655 | } 656 | 657 | output "private_subnets_by_group" { 658 | type = map(private_subnets_by_group) 659 | description = <<-END 660 | A map of lists of private subnets keyed by group. (`aws_subnet`) 661 | END 662 | } 663 | 664 | output "private_route_table_ids_by_group" { 665 | type = map(private_route_table_ids_by_group) 666 | description = <<-END 667 | A map of lists of private route table IDs keyed by group. 668 | END 669 | } 670 | 671 | output "private_subnet_ids_by_group" { 672 | type = map(private_subnet_ids_by_group) 673 | description = <<-END 674 | A map of lists of private subnet IDs keyed by group. 675 | END 676 | } 677 | 678 | output "intra_subnets_by_group" { 679 | type = map(intra_subnets_by_group) 680 | description = <<-END 681 | A map of lists of intra aws_subnet keyed by group. (`aws_subnet`) 682 | END 683 | } 684 | 685 | output "intra_route_table_ids_by_group" { 686 | type = map(intra_route_table_ids_by_group) 687 | description = <<-END 688 | A map of lists of intra route table IDs keyed by group. 689 | END 690 | } 691 | 692 | output "intra_subnet_ids_by_group" { 693 | type = map(intra_subnet_ids_by_group) 694 | description = <<-END 695 | A map of lists of intra subnet IDs keyed by group. 696 | END 697 | } 698 | } 699 | 700 | section { 701 | title = "Full Resource Objects" 702 | 703 | output "vpc" { 704 | type = object(vpc) 705 | description = <<-END 706 | The VPC. (`aws_vpc`) 707 | END 708 | } 709 | 710 | output "intra_route_tables" { 711 | type = map(intra_route_tables) 712 | description = <<-END 713 | A map of intra route tables keyed by group. (`aws_route_table`) 714 | END 715 | } 716 | 717 | output "intra_route_table_associations" { 718 | type = map(intra_route_table_associations) 719 | description = <<-END 720 | A map of intra route table associations keyed by the subnets CIDR 721 | Blocks. (`aws_route_table_association`) 722 | END 723 | } 724 | 725 | output "eips" { 726 | type = map(eips) 727 | description = <<-END 728 | A map of Elastic IP Adresses (EIPs) keyed by availability zone. 729 | (`aws_eip`) 730 | END 731 | } 732 | 733 | output "nat_gateways" { 734 | type = map(nat_gateways) 735 | description = <<-END 736 | A map of NAT gatweways keyed by availability zone. 737 | (`aws_nat_gateway`) 738 | END 739 | } 740 | 741 | output "private_route_tables" { 742 | type = map(private_route_tables) 743 | description = <<-END 744 | A map of private route tables keyed by group. (`aws_route_table`) 745 | END 746 | } 747 | 748 | output "private_route_table_associations" { 749 | type = map(private_route_table_associations) 750 | description = <<-END 751 | A map of private route table associations keyed by the subnets CIDR 752 | Blocks. (`aws_route_table_association`) 753 | END 754 | } 755 | 756 | output "routes_to_nat_gateways" { 757 | type = map(routes_to_nat_gateways) 758 | description = <<-END 759 | A map of routes to the NAT Gateways keyed by group. (`aws_route`) 760 | END 761 | } 762 | 763 | output "internet_gateway" { 764 | type = object(internet_gateway) 765 | description = <<-END 766 | The Internet Gateway. (`aws_internet_gateway`) 767 | END 768 | } 769 | 770 | output "public_route_tables" { 771 | type = map(public_route_tables) 772 | description = <<-END 773 | A map of public route tables keyed by group. (`aws_route_table`) 774 | END 775 | } 776 | 777 | output "public_route_table_associations" { 778 | type = map(public_route_table_associations) 779 | description = <<-END 780 | A map of public route table associations keyed by the subnets CIDR 781 | Blocks. (`aws_route_table_association`) 782 | END 783 | } 784 | 785 | output "routes_to_internet_gateway" { 786 | type = map(routes_to_internet_gateway) 787 | description = <<-END 788 | A map of routes to the Internet Gateway keyed by group. (`aws_route`) 789 | END 790 | } 791 | 792 | output "subnets" { 793 | type = map(subnets) 794 | description = <<-END 795 | A map of subnets keyed by CIDR Blocks. (`aws_subnet`) 796 | END 797 | } 798 | } 799 | 800 | section { 801 | title = "Module Attributes" 802 | 803 | output "module_inputs" { 804 | type = map(module_inputs) 805 | description = <<-END 806 | A map of all module arguments. Set to the provided values or calculated default values. 807 | END 808 | } 809 | 810 | output "module_enabled" { 811 | type = bool 812 | description = <<-END 813 | Whether this module is enabled. 814 | END 815 | } 816 | 817 | output "module_tags" { 818 | type = map(string) 819 | description = <<-END 820 | The map of tags that are being applied to all created resources that accept tags. 821 | END 822 | } 823 | } 824 | } 825 | 826 | section { 827 | title = "External Documentation" 828 | 829 | section { 830 | title = "AWS Documentation VPC" 831 | content = <<-END 832 | - https://aws.amazon.com/de/vpc/ 833 | END 834 | } 835 | 836 | section { 837 | title = "Terraform AWS Provider Documentation:" 838 | content = <<-END 839 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/vpc 840 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet 841 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/internet_gateway 842 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway 843 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table 844 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association 845 | - https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route 846 | END 847 | } 848 | } 849 | 850 | section { 851 | title = "Module Versioning" 852 | content = <<-END 853 | This Module follows the principles of [Semantic Versioning (SemVer)]. 854 | 855 | Given a version number `MAJOR.MINOR.PATCH`, we increment the: 856 | 857 | 1. `MAJOR` version when we make incompatible changes, 858 | 2. `MINOR` version when we add functionality in a backwards compatible manner, and 859 | 3. `PATCH` version when we make backwards compatible bug fixes. 860 | END 861 | 862 | section { 863 | title = "Backwards compatibility in `0.0.z` and `0.y.z` version" 864 | content = <<-END 865 | - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) 866 | - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) 867 | END 868 | } 869 | } 870 | 871 | section { 872 | title = "About Mineiros" 873 | content = <<-END 874 | [Mineiros][homepage] is a remote-first company headquartered in Berlin, Germany 875 | that solves development, automation and security challenges in cloud infrastructure. 876 | 877 | Our vision is to massively reduce time and overhead for teams to manage and 878 | deploy production-grade and secure cloud infrastructure. 879 | 880 | We offer commercial support for all of our modules and encourage you to reach out 881 | if you have any questions or need help. Feel free to email us at [hello@mineiros.io] or join our 882 | [Community Slack channel][slack]. 883 | END 884 | } 885 | 886 | section { 887 | title = "Reporting Issues" 888 | content = <<-END 889 | We use GitHub [Issues] to track community reported issues and missing features. 890 | END 891 | } 892 | 893 | section { 894 | title = "Contributing" 895 | content = <<-END 896 | Contributions are always encouraged and welcome! For the process of accepting changes, we use 897 | [Pull Requests]. If you'd like more information, please see our [Contribution Guidelines]. 898 | END 899 | } 900 | 901 | section { 902 | title = "Makefile Targets" 903 | content = <<-END 904 | This repository comes with a handy [Makefile]. 905 | Run `make help` to see details on each available target. 906 | END 907 | } 908 | 909 | section { 910 | title = "License" 911 | content = <<-END 912 | [![license][badge-license]][apache20] 913 | 914 | This module is licensed under the Apache License Version 2.0, January 2004. 915 | Please see [LICENSE] for full details. 916 | 917 | Copyright © 2019-2022 [Mineiros GmbH][homepage] 918 | END 919 | } 920 | } 921 | 922 | references { 923 | ref "homepage" { 924 | value = "https://mineiros.io/?ref=terraform-aws-vpc" 925 | } 926 | ref "hello@mineiros.io" { 927 | value = "mailto:hello@mineiros.io" 928 | } 929 | ref "badge-build" { 930 | value = "https://github.com/mineiros-io/terraform-aws-vpc/workflows/CI/CD%20Pipeline/badge.svg" 931 | } 932 | ref "badge-semver" { 933 | value = "https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-vpc.svg?label=latest&sort=semver" 934 | } 935 | ref "badge-license" { 936 | value = "https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg" 937 | } 938 | ref "badge-terraform" { 939 | value = "https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform" 940 | } 941 | ref "badge-slack" { 942 | value = "https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack" 943 | } 944 | ref "build-status" { 945 | value = "https://github.com/mineiros-io/terraform-aws-vpc/actions" 946 | } 947 | ref "releases-github" { 948 | value = "https://github.com/mineiros-io/terraform-aws-vpc/releases" 949 | } 950 | ref "badge-tf-aws" { 951 | value = "https://img.shields.io/badge/AWS-3%20and%202.45+-F8991D.svg?logo=terraform" 952 | } 953 | ref "releases-aws-provider" { 954 | value = "https://github.com/terraform-providers/terraform-provider-aws/releases" 955 | } 956 | ref "releases-terraform" { 957 | value = "https://github.com/hashicorp/terraform/releases" 958 | } 959 | ref "apache20" { 960 | value = "https://opensource.org/licenses/Apache-2.0" 961 | } 962 | ref "slack" { 963 | value = "https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg" 964 | } 965 | ref "terraform" { 966 | value = "https://www.terraform.io" 967 | } 968 | ref "aws" { 969 | value = "https://aws.amazon.com/" 970 | } 971 | ref "semantic versioning (semver)" { 972 | value = "https://semver.org/" 973 | } 974 | ref "variables.tf" { 975 | value = "https://github.com/mineiros-io/terraform-aws-vpc/blob/master/variables.tf" 976 | } 977 | ref "examples/" { 978 | value = "https://github.com/mineiros-io/terraform-aws-vpc/blob/master/examples" 979 | } 980 | ref "issues" { 981 | value = "https://github.com/mineiros-io/terraform-aws-vpc/issues" 982 | } 983 | ref "license" { 984 | value = "https://github.com/mineiros-io/terraform-aws-vpc/blob/master/LICENSE" 985 | } 986 | ref "makefile" { 987 | value = "https://github.com/mineiros-io/terraform-aws-vpc/blob/master/Makefile" 988 | } 989 | ref "pull requests" { 990 | value = "https://github.com/mineiros-io/terraform-aws-vpc/pulls" 991 | } 992 | ref "contribution guidelines" { 993 | value = "https://github.com/mineiros-io/terraform-aws-vpc/blob/master/CONTRIBUTING.md" 994 | } 995 | } 996 | -------------------------------------------------------------------------------- /db_subnet_group.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | subnets_with_db_subnet_group = { for subnet in var.subnets : subnet.db_subnet_group_name => subnet if can(subnet.db_subnet_group_name) } 3 | } 4 | 5 | resource "aws_db_subnet_group" "db_subnet_group" { 6 | for_each = local.subnets_with_db_subnet_group 7 | 8 | name = each.key 9 | subnet_ids = [for subnet in local.subnets : aws_subnet.subnet[subnet.cidr_block].id if subnet.db_subnet_group_name == each.key] 10 | description = try(each.value.description, "Managed by mineiros-io/vpc/aws Terraform Module") 11 | 12 | tags = merge(var.module_tags, try(each.value.tags, {})) 13 | } 14 | -------------------------------------------------------------------------------- /elasticache_subnet_group.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | subnets_with_elasticache_subnet_group = { for subnet in var.subnets : subnet.elasticache_subnet_group_name => subnet if can(subnet.elasticache_subnet_group_name) } 3 | } 4 | 5 | resource "aws_elasticache_subnet_group" "elasticache_subnet_group" { 6 | for_each = local.subnets_with_elasticache_subnet_group 7 | 8 | name = each.key 9 | subnet_ids = [for subnet in local.subnets : aws_subnet.subnet[subnet.cidr_block].id if subnet.elasticache_subnet_group_name == each.key] 10 | description = try(each.value.description, "Managed by mineiros-io/vpc/aws Terraform Module") 11 | 12 | tags = merge(var.module_tags, try(each.value.tags, {})) 13 | } 14 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![GitHub tag (latest SemVer)][badge-semver]][releases-github] 4 | [![license][badge-license]][apache20] 5 | [![Terraform Version][badge-terraform]][releases-terraform] 6 | [![Join Slack][badge-slack]][slack] 7 | 8 | # Examples for using this Mineiros module 9 | 10 | - [complete-example/] Deploy a VPC with a private and public subnet spanned over two availability zones. 11 | 12 | 13 | [complete-example/]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/examples/complete-example 14 | 15 | [homepage]: https://mineiros.io/?ref=terraform-aws-vpc 16 | 17 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 18 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 19 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 20 | [badge-semver]: https://img.shields.io/github/v/tag/mineiros-io/terraform-aws-vpc.svg?label=latest&sort=semver 21 | 22 | [releases-github]: https://github.com/mineiros-io/terraform-aws-vpc/releases 23 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 24 | [apache20]: https://opensource.org/licenses/Apache-2.0 25 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 26 | -------------------------------------------------------------------------------- /examples/complete-example/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![license][badge-license]][apache20] 4 | [![Terraform Version][badge-terraform]][releases-terraform] 5 | [![Join Slack][badge-slack]][slack] 6 | 7 | # What this example shows 8 | 9 | This example shows how to deploy a VPC with a private and public subnet spanned over two availability zones. 10 | 11 | ## Basic usage 12 | 13 | See the code in [main.tf] to see the implementation details. 14 | 15 | ## Running the example 16 | 17 | ### Cloning the repository 18 | 19 | ```bash 20 | git clone https://github.com/mineiros-io/terraform-aws-vpc.git 21 | cd terraform-aws-vpc/examples/complete-example 22 | ``` 23 | 24 | ### Initializing Terraform 25 | 26 | Run `terraform init` to initialize the example and download providers and the module. 27 | 28 | ### Planning the example 29 | 30 | Run `terraform plan` to see a plan of the changes. 31 | 32 | ### Applying the example 33 | 34 | Run `terraform apply` to create the resources. 35 | You will see a plan of the changes and Terraform will prompt you for approval to actually apply the changes. 36 | 37 | ### Destroying the example 38 | 39 | Run `terraform destroy` to destroy all resources again. 40 | 41 | 42 | 43 | [main.tf]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/examples/complete-example/main.tf 44 | 45 | [homepage]: https://mineiros.io/?ref=terraform-aws-vpc 46 | 47 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 48 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 49 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 50 | 51 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 52 | [apache20]: https://opensource.org/licenses/Apache-2.0 53 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 54 | -------------------------------------------------------------------------------- /examples/complete-example/main.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # CREATE AN EXAMPLE VPC WITH SUBNETS, INTERNET- AND NAT GATEWAYS 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | cidr_block = "10.0.0.0/16" 7 | } 8 | 9 | module "vpc" { 10 | source = "mineiros-io/vpc/aws" 11 | version = "~> 0.7.0" 12 | 13 | module_enabled = true 14 | 15 | vpc_name = "main" 16 | cidr_block = local.cidr_block 17 | 18 | # Define a mode on how to deploy NAT gateways for private networks. 19 | # Valid values are: 20 | # - "single" to create a single NAT gateway in the first availability zone to route all private traffic to 21 | # - "one_per_az" to create a NAT gateway per availability zone that has a private subnet. This needs a public subnets in the same AZs. 22 | nat_gateway_mode = "single" 23 | 24 | nat_gateway_single_mode_zone = "a" 25 | 26 | subnets = [ 27 | { 28 | # define a group name for the subnets. This can be any string. Default is "main". 29 | group = "main" 30 | 31 | # Class of the subnet: Default is "private". 32 | # - "public" defines a set of subnets where deployed components can be reachable via the public internet. 33 | # - "private" defines a set subnets where components are not publicly reachable but can reach the internet. 34 | # - "intra" (in development) defines a set of subnets that has not connectivity to the public internet. 35 | class = "public" 36 | 37 | # defines whether components deployed into the subnet will be assigned a public IPv4 address when launched. 38 | map_public_ip_on_launch = true 39 | 40 | # Define the base CIDR Block of the subnets and the parameters to calculate each CIDR Block. Default is the VPC CIDR Block. 41 | # This example: devide the VPC CIDR Block into 2^4 = 16 blocks and use the first block as a base for all subnets 42 | # Add 4 bits to the prefix of "10.0.0.0/16" results in "10.0.0.0/20". 43 | cidr_block = cidrsubnet(local.cidr_block, 4, 0) 44 | 45 | # How many bits should be added when calculating the subnets CIDR Blocks. Default is 8. 46 | # This example: For each subnet add another 4 bits to the prefix, so each netnum will result in: 47 | # netnum=0 => subnet_cidr_block="10.0.0.0/24" 48 | # netnum=1 => subnet_cidr_block="10.0.1.0/24" 49 | # ... 50 | # netnum=15 => subnet_cidr_block="10.0.15.0/24" 51 | newbits = 4 52 | 53 | # A map of subnets keyed by availability zone suffix. The Number defined the network number with in the CIDR Block. 54 | # see https://www.terraform.io/docs/configuration/functions/cidrsubnet.html for details on how this is calculated internally 55 | # Note: When adjusting cidr_block or newbits you might also need to adjust the netnums. 56 | # This Example: Deploy one subnet in availability zone "a" ("10.0.0.0/24") and one subnet in availability zone "b" ("10.0.1.0/24") 57 | netnums_by_az = { 58 | a = [0] # "10.0.0.0/24" 59 | b = [1] # "10.0.1.0/24" 60 | } 61 | 62 | # A map of tags that will be applied to this Subnet. 63 | # A "Name" tag of the format '----' (idx is the index in the list of netnums) 64 | # will be applied automatically but can be overwritten. 65 | # The Name tag will be merged with var.module_tags, var.subnet_tags, tags 66 | tags = { 67 | } 68 | }, 69 | { 70 | group = "main" 71 | class = "private" 72 | 73 | # use the second network block for private subnets: "10.0.16.0/20" 74 | # 75 | cidr_block = cidrsubnet(local.cidr_block, 4, 1) 76 | 77 | # Add another 4 bits when calculatin actual subnet cidr blocks (see above) 78 | newbits = 4 79 | 80 | # create four private networks in three availability zones 81 | # AZ a: "10.0.16.0/24" 82 | # AZ b: "10.0.17.0/24" and "10.0.20.0/24" 83 | # AZ c: "10.0.18.0/24" 84 | netnums_by_az = { 85 | a = [0] 86 | b = [1, 4] 87 | c = [2] 88 | } 89 | }, 90 | ] 91 | } 92 | 93 | provider "aws" { 94 | region = "eu-west-1" 95 | } 96 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mineiros-io/terraform-module-vpc 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/gruntwork-io/terratest v0.37.0 7 | github.com/stretchr/testify v1.4.0 8 | ) 9 | 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= 9 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 10 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 11 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 12 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 13 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 14 | github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 15 | github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 16 | github.com/Azure/azure-sdk-for-go v46.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= 17 | github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= 18 | github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= 19 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 20 | github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= 21 | github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= 22 | github.com/Azure/go-autorest/autorest v0.11.0/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= 23 | github.com/Azure/go-autorest/autorest v0.11.5/go.mod h1:foo3aIXRQ90zFve3r0QiDsrjGDUwWhKl0ZOQy1CT14k= 24 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 25 | github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= 26 | github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= 27 | github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= 28 | github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= 29 | github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= 30 | github.com/Azure/go-autorest/autorest/azure/auth v0.5.1/go.mod h1:ea90/jvmnAwDrSooLH4sRIehEPtG/EPUXavDh31MnA4= 31 | github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= 32 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 33 | github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= 34 | github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= 35 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 36 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 37 | github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= 38 | github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= 39 | github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= 40 | github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= 41 | github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= 42 | github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= 43 | github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= 44 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 45 | github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= 46 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 47 | github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= 48 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 49 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 50 | github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= 51 | github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= 52 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 53 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 54 | github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 55 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 56 | github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 57 | github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= 58 | github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= 59 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 60 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 61 | github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= 62 | github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0= 63 | github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= 64 | github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0= 65 | github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec= 66 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 67 | github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= 68 | github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 69 | github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= 70 | github.com/aws/aws-sdk-go v1.38.28/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= 71 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 72 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 73 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= 74 | github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= 75 | github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= 76 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 77 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 78 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 79 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 80 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 81 | github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= 82 | github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 83 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 84 | github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= 85 | github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= 86 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 87 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 88 | github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 89 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 90 | github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 91 | github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 92 | github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= 93 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 94 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 95 | github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= 96 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 97 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 98 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 99 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 100 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 101 | github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= 102 | github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= 103 | github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 104 | github.com/docker/cli v0.0.0-20200109221225-a4f60165b7a3/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 105 | github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 106 | github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 107 | github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 108 | github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= 109 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 110 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 111 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 112 | github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 113 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 114 | github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 115 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 116 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 117 | github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 118 | github.com/elazarl/goproxy v0.0.0-20190911111923-ecfe977594f1/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= 119 | github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= 120 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 121 | github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 122 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 123 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 124 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 125 | github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 126 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 127 | github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= 128 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 129 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 130 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 131 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 132 | github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 133 | github.com/go-errors/errors v1.0.2-0.20180813162953-d98b870cc4e0/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= 134 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 135 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 136 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 137 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 138 | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= 139 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 140 | github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= 141 | github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 142 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 143 | github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= 144 | github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= 145 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 146 | github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= 147 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 148 | github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 149 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 150 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 151 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 152 | github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= 153 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 154 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 155 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 156 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 157 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 158 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 159 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 160 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 161 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 162 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 163 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 164 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 165 | github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 166 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 167 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 168 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 169 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 170 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 171 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 172 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 173 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 174 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 175 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 176 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 177 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 178 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 179 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 180 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 181 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 182 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 183 | github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= 184 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 185 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 186 | github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 187 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 188 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 189 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 190 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 191 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 192 | github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 193 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 194 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 195 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 196 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 197 | github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 198 | github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= 199 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 200 | github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= 201 | github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 202 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 203 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 204 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 205 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 206 | github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 207 | github.com/gruntwork-io/go-commons v0.8.0/go.mod h1:gtp0yTtIBExIZp7vyIV9I0XQkVwiQZze678hvDXof78= 208 | github.com/gruntwork-io/terratest v0.37.0 h1:sID4/hCjcF5vmjXiU0y71bMQVO458ylYFZk/mxDBTxo= 209 | github.com/gruntwork-io/terratest v0.37.0/go.mod h1:3zzDkmFBGDcSwQRaXS/LKnobwnff09oo5z/B6SVwRy8= 210 | github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= 211 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 212 | github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= 213 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 214 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 215 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 216 | github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 217 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 218 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 219 | github.com/hashicorp/hcl/v2 v2.8.2 h1:wmFle3D1vu0okesm8BTLVDyJ6/OL9DCLUwn0b2OptiY= 220 | github.com/hashicorp/hcl/v2 v2.8.2/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY= 221 | github.com/hashicorp/terraform-json v0.12.0 h1:8czPgEEWWPROStjkWPUnTQDXmpmZPlkQAwYYLETaTvw= 222 | github.com/hashicorp/terraform-json v0.12.0/go.mod h1:pmbq9o4EuL43db5+0ogX10Yofv1nozM+wskr/bGFJpI= 223 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 224 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 225 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 226 | github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 227 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 228 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a h1:zPPuIq2jAWWPTrGt70eK/BSch+gFAGrNzecsoENgu2o= 229 | github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= 230 | github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= 231 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 232 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 233 | github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= 234 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 235 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 236 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 237 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 238 | github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 239 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 240 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 241 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 242 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 243 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 244 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 245 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 246 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 247 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 248 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 249 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 250 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 251 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 252 | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= 253 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 254 | github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 255 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 256 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 257 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 258 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 259 | github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= 260 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 261 | github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 262 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 263 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 264 | github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 265 | github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 266 | github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 267 | github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= 268 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 269 | github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= 270 | github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 271 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 272 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 273 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= 274 | github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= 275 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 276 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 277 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 278 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 279 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 280 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 281 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 282 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 283 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 284 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 285 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 286 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 287 | github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= 288 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 289 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 290 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 291 | github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 292 | github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 293 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 294 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 295 | github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 296 | github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 297 | github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= 298 | github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= 299 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 300 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 301 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 302 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 303 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 304 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 305 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 306 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 307 | github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= 308 | github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= 309 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 310 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 311 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 312 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 313 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 314 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 315 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 316 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 317 | github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= 318 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 319 | github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= 320 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 321 | github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= 322 | github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= 323 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 324 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 325 | github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= 326 | github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= 327 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 328 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 329 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 330 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 331 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 332 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 333 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 334 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 335 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 336 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 337 | github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= 338 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 339 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 340 | github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 341 | github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 342 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 343 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 344 | github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= 345 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 346 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 347 | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= 348 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 349 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 350 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 351 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 352 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 353 | github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 354 | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= 355 | github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 356 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 357 | github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 358 | github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= 359 | github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= 360 | github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= 361 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 362 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 363 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 364 | github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 365 | github.com/zclconf/go-cty v1.2.1 h1:vGMsygfmeCl4Xb6OA5U5XVAaQZ69FvoG7X2jUtQujb8= 366 | github.com/zclconf/go-cty v1.2.1/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= 367 | go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 368 | go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= 369 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 370 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 371 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 372 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 373 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 374 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 375 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 376 | golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 377 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 378 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 379 | golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 380 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 381 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 382 | golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 383 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 384 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 385 | golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 386 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= 387 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 388 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 389 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 390 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 391 | golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 392 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 393 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 394 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 395 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 396 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 397 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 398 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 399 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 400 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 401 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 402 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 403 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 404 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 405 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 406 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 407 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 408 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 409 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 410 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 411 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 412 | golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 413 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 414 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 415 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 416 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 417 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 418 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 419 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 420 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 421 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 422 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 423 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 424 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 425 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 426 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 427 | golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 428 | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 429 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 430 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 431 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 432 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 433 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 434 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 435 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= 436 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 437 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 438 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 439 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 440 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 441 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 442 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 443 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 444 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 445 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 446 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 447 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 448 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 449 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 450 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 451 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 452 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 453 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 454 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 455 | golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 456 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 457 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 458 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 459 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 460 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 461 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 462 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 463 | golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 465 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 466 | golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 467 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 474 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= 479 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 481 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 482 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 483 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 484 | golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= 485 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 486 | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 487 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 488 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 489 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 490 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 491 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 492 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 493 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 494 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 495 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 496 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 497 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 498 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 499 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 500 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 501 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 502 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 503 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 504 | golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 505 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 506 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 507 | golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= 508 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 509 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 510 | golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 511 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 512 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 513 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 514 | golang.org/x/tools v0.0.0-20191205215504-7b8c8591a921/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 515 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 516 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 517 | golang.org/x/tools v0.0.0-20201110201400-7099162a900a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 518 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 519 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 520 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 521 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 522 | gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= 523 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 524 | gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= 525 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 526 | google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= 527 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 528 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 529 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 530 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 531 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 532 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 533 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 534 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 535 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 536 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 537 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 538 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 539 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 540 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 541 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 542 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 543 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 544 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 545 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 546 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 547 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 548 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 549 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 550 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 551 | google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= 552 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 553 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 554 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 555 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 556 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 557 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 558 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 559 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 560 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 561 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 562 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 563 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 564 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 565 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 566 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 567 | gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= 568 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 569 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 570 | gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= 571 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 572 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 573 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 574 | gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= 575 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 576 | gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= 577 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 578 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 579 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 580 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 581 | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= 582 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 583 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 584 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 585 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 586 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 587 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 588 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 589 | k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= 590 | k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= 591 | k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= 592 | k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= 593 | k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= 594 | k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= 595 | k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= 596 | k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= 597 | k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= 598 | k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= 599 | k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls= 600 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 601 | k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 602 | k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 603 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 604 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 605 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 606 | k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= 607 | k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= 608 | k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 609 | k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= 610 | k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= 611 | k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 612 | k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= 613 | modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= 614 | modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= 615 | modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= 616 | modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= 617 | modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= 618 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 619 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 620 | sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= 621 | sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= 622 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 623 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 624 | -------------------------------------------------------------------------------- /intra_routing.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # CREATE intra ROUTING AND AN INTERNET GATEWAY IF A intra SUBNETS IS DEFINED 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | intra_subnets = [for subnet in local.subnets : subnet if subnet.class == "intra"] 7 | 8 | intra_groups = try(distinct(local.intra_subnets.*.group), []) 9 | 10 | intra_subnets_by_group = { 11 | for group in local.intra_groups : group => [ 12 | for subnet in local.intra_subnets : subnet if subnet.group == group 13 | ] 14 | } 15 | } 16 | 17 | resource "aws_route_table" "intra" { 18 | for_each = var.module_enabled ? local.intra_subnets_by_group : {} 19 | 20 | vpc_id = aws_vpc.vpc[0].id 21 | 22 | # propagating_vgws = try(local.subnets[each.key].propagating_vgws, null) 23 | 24 | tags = merge( 25 | { 26 | Name = "${var.vpc_name}-intra-${each.key}" 27 | 28 | # special mineiros.io tags that can be used in data sources 29 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 30 | "mineiros-io/aws/vpc/routetable-name" = "${var.vpc_name}-intra-${each.key}" 31 | "mineiros-io/aws/vpc/routetable-class" = "intra" 32 | }, 33 | var.module_tags, 34 | var.route_table_tags, 35 | var.intra_route_table_tags, 36 | ) 37 | 38 | depends_on = [var.module_depends_on] 39 | } 40 | 41 | resource "aws_route_table_association" "intra" { 42 | for_each = var.module_enabled ? { 43 | for subnet in flatten(values(local.intra_subnets_by_group)) : subnet.cidr_block => subnet 44 | } : {} 45 | 46 | subnet_id = aws_subnet.subnet[each.key].id 47 | route_table_id = aws_route_table.intra[each.value.group].id 48 | 49 | depends_on = [var.module_depends_on] 50 | } 51 | -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # DEPLOY AND MANAGE A VPC 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | # --------------------------------------------------------------------------------------------------------------------- 6 | # When you create a VPC, we recommend that you specify a CIDR block (of /16 or smaller) from the private IPv4 address 7 | # ranges as specified in RFC 1918 (http://www.faqs.org/rfcs/rfc1918.html): 8 | # - 10.0.0.0 - 10.255.255.255 (10/8 prefix) 9 | # - 172.16.0.0 - 172.31.255.255 (172.16/12 prefix) 10 | # - 192.168.0.0 - 192.168.255.255 (192.168/16 prefix) 11 | # 12 | # The first four IP addresses and the last IP address in each subnet CIDR block are not available for you to use, and 13 | # cannot be assigned to an instance. For example, in a subnet with CIDR block 10.0.0.0/24, the following five IP 14 | # addresses are reserved: 15 | # - 10.0.0.0: Network address. 16 | # - 10.0.0.1: Reserved by AWS for the VPC router. 17 | # - 10.0.0.2: Reserved by AWS. The IP address of the DNS server is the base of the VPC network range plus two. 18 | # --------------------------------------------------------------------------------------------------------------------- 19 | 20 | data "aws_region" "region" { 21 | count = var.module_enabled ? 1 : 0 22 | } 23 | 24 | locals { 25 | region = try(data.aws_region.region[0].name, "") 26 | } 27 | 28 | resource "aws_vpc" "vpc" { 29 | count = var.module_enabled ? 1 : 0 30 | 31 | # We convert the cidr_block to its cannonical form because AWS would do it in the API anyway 32 | # and we want to ensure this is not showing a constant change when planning. 33 | # We will do the same for all created subnets. 34 | # We will do the same for all created routes. 35 | cidr_block = cidrsubnet(var.cidr_block, 0, 0) 36 | 37 | instance_tenancy = var.instance_tenancy 38 | enable_dns_support = var.enable_dns_support 39 | enable_dns_hostnames = var.enable_dns_hostnames 40 | enable_classiclink = var.enable_classiclink 41 | enable_classiclink_dns_support = var.enable_classiclink_dns_support 42 | assign_generated_ipv6_cidr_block = var.assign_generated_ipv6_cidr_block 43 | 44 | tags = merge( 45 | { 46 | Name = var.vpc_name 47 | 48 | # special mineiros.io tags that can be used in data sources 49 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 50 | }, 51 | var.module_tags, 52 | var.vpc_tags, 53 | ) 54 | 55 | depends_on = [var.module_depends_on] 56 | } 57 | -------------------------------------------------------------------------------- /outputs.tf: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------------------------------------------------- 2 | # OUTPUT CALCULATED VARIABLES (prefer full objects) 3 | # ---------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | public_aws_subnets_by_group = { 7 | for group, subnets in local.public_subnets_by_group : group => [ 8 | for subnet in aws_subnet.subnet : subnet if contains(subnets.*.cidr_block, subnet.cidr_block) 9 | ] 10 | } 11 | 12 | private_aws_subnets_by_group = { 13 | for group, subnets in local.private_subnets_by_group : group => [ 14 | for subnet in aws_subnet.subnet : subnet if contains(subnets.*.cidr_block, subnet.cidr_block) 15 | ] 16 | } 17 | 18 | intra_aws_subnets_by_group = { 19 | for group, subnets in local.intra_subnets_by_group : group => [ 20 | for subnet in aws_subnet.subnet : subnet if contains(subnets.*.cidr_block, subnet.cidr_block) 21 | ] 22 | } 23 | 24 | public_subnet_ids_by_group = { 25 | for group, subnets in local.public_aws_subnets_by_group : group => subnets.*.id 26 | } 27 | 28 | private_subnet_ids_by_group = { 29 | for group, subnets in local.private_aws_subnets_by_group : group => subnets.*.id 30 | } 31 | 32 | intra_subnet_ids_by_group = { 33 | for group, subnets in local.intra_aws_subnets_by_group : group => subnets.*.id 34 | } 35 | 36 | public_route_table_ids_by_group = { 37 | for group, subnet_ids in local.public_subnet_ids_by_group : group => distinct([ 38 | for rta in try(values(aws_route_table_association.public), []) : 39 | rta.route_table_id if contains(subnet_ids, rta.subnet_id) 40 | ]) 41 | } 42 | 43 | private_route_table_ids_by_group = { 44 | for group, subnet_ids in local.private_subnet_ids_by_group : group => distinct([ 45 | for rta in try(values(aws_route_table_association.private), []) : 46 | rta.route_table_id if contains(subnet_ids, rta.subnet_id) 47 | ]) 48 | } 49 | 50 | intra_route_table_ids_by_group = { 51 | for group, subnet_ids in local.intra_subnet_ids_by_group : group => distinct([ 52 | for rta in try(values(aws_route_table_association.intra), []) : 53 | rta.route_table_id if contains(subnet_ids, rta.subnet_id) 54 | ]) 55 | } 56 | } 57 | 58 | 59 | output "public_subnets_by_group" { 60 | description = "A map of lists of public subnets keyed by group. (aws_subnet)" 61 | value = local.public_aws_subnets_by_group 62 | } 63 | 64 | output "public_route_table_ids_by_group" { 65 | description = "A map of lists of public route table IDs keyed by group." 66 | value = local.public_route_table_ids_by_group 67 | } 68 | 69 | output "public_subnet_ids_by_group" { 70 | description = "A map of lists of public subnet IDs keyed by group." 71 | value = local.public_subnet_ids_by_group 72 | } 73 | 74 | output "private_subnets_by_group" { 75 | description = "A map of lists of private subnets keyed by group. (aws_subnet)" 76 | value = local.private_aws_subnets_by_group 77 | } 78 | 79 | output "private_route_table_ids_by_group" { 80 | description = "A map of lists of private route table IDs keyed by group." 81 | value = local.private_route_table_ids_by_group 82 | } 83 | 84 | output "private_subnet_ids_by_group" { 85 | description = "A map of lists of private subnet IDs keyed by group." 86 | value = local.private_subnet_ids_by_group 87 | } 88 | 89 | output "intra_subnets_by_group" { 90 | description = "A map of lists of intra aws_subnet keyed by group. (aws_subnet)" 91 | value = local.intra_aws_subnets_by_group 92 | } 93 | 94 | output "intra_route_table_ids_by_group" { 95 | description = "A map of lists of intra route table IDs keyed by group." 96 | value = local.intra_route_table_ids_by_group 97 | } 98 | 99 | output "intra_subnet_ids_by_group" { 100 | description = "A map of lists of intra subnet IDs keyed by group." 101 | value = local.intra_subnet_ids_by_group 102 | } 103 | 104 | # ---------------------------------------------------------------------------------------------------------------------- 105 | # OUTPUT ALL RESOURCES AS FULL OBJECTS 106 | # ---------------------------------------------------------------------------------------------------------------------- 107 | 108 | output "vpc" { 109 | description = "The VPC. (aws_vpc)" 110 | value = try(aws_vpc.vpc[0], null) 111 | } 112 | 113 | output "intra_route_tables" { 114 | description = "A map of intra route tables keyed by group. (aws_route_table)" 115 | value = try(aws_route_table.intra, null) 116 | } 117 | 118 | output "intra_route_table_associations" { 119 | description = "A map of intra route table associations keyed by the subnets CIDR Blocks. (aws_route_table_association)" 120 | value = try(aws_route_table_association.intra, null) 121 | } 122 | 123 | output "eips" { 124 | description = "A map of Elastic IP Adresses (EIPs) keyed by availability zone. (aws_eip)" 125 | value = try(aws_eip.eip, null) 126 | } 127 | 128 | output "nat_gateways" { 129 | description = "A map of NAT gatweways keyed by availability zone. (aws_nat_gateway)" 130 | value = try(aws_nat_gateway.nat_gateway, null) 131 | } 132 | 133 | output "private_route_tables" { 134 | description = "A map of private route tables keyed by group. (aws_route_table)" 135 | value = try(aws_route_table.private, null) 136 | } 137 | 138 | output "private_route_table_associations" { 139 | description = "A map of private route table associations keyed by the subnets CIDR Blocks. (aws_route_table_association)" 140 | value = try(aws_route_table_association.private, null) 141 | } 142 | 143 | output "routes_to_nat_gateways" { 144 | description = "A map of routes to the NAT Gateways keyed by group. (aws_route)" 145 | value = try(aws_route.nat_gateway, null) 146 | } 147 | 148 | output "internet_gateway" { 149 | description = "The Internet Gateway. (aws_internet_gateway)" 150 | value = try(aws_internet_gateway.internet_gateway[0], null) 151 | } 152 | 153 | output "public_route_tables" { 154 | description = "A map of public route tables keyed by group. (aws_route_table)" 155 | value = try(aws_route_table.public, null) 156 | } 157 | 158 | output "public_route_table_associations" { 159 | description = "A map of public route table associations keyed by the subnets CIDR Blocks. (aws_route_table_association)" 160 | value = try(aws_route_table_association.public, null) 161 | } 162 | 163 | output "routes_to_internet_gateway" { 164 | description = "A map of routes to the Internet Gateway keyed by group. (aws_route)" 165 | value = try(aws_route.internet_gateway, null) 166 | } 167 | 168 | output "subnets" { 169 | description = "A map of subnets keyed by CIDR Blocks. (aws_subnet)" 170 | value = try(aws_subnet.subnet, null) 171 | } 172 | 173 | # ---------------------------------------------------------------------------------------------------------------------- 174 | # OUTPUT ALL INPUT VARIABLES 175 | # ---------------------------------------------------------------------------------------------------------------------- 176 | 177 | output "module_inputs" { 178 | description = "A map of all module arguments. Set to the provided values or calculated default values." 179 | value = { 180 | vpc_name = var.vpc_name 181 | cidr_block = var.cidr_block 182 | assign_generated_ipv6_cidr_block = var.assign_generated_ipv6_cidr_block 183 | enable_classiclink = var.enable_classiclink 184 | enable_classiclink_dns_support = var.enable_classiclink_dns_support 185 | enable_dns_support = var.enable_dns_support 186 | enable_dns_hostnames = var.enable_dns_hostnames 187 | instance_tenancy = var.instance_tenancy 188 | 189 | subnets = var.subnets 190 | 191 | nat_gateway_mode = var.nat_gateway_mode 192 | 193 | vpc_tags = merge(var.module_tags, var.vpc_tags) 194 | internet_gateway_tags = merge(var.module_tags, var.internet_gateway_tags) 195 | eip_tags = merge(var.module_tags, var.eip_tags) 196 | nat_gateway_tags = merge(var.module_tags, var.nat_gateway_tags) 197 | 198 | subnet_tags = merge(var.module_tags, var.subnet_tags) 199 | public_subnet_tags = merge(var.module_tags, var.subnet_tags, var.public_subnet_tags) 200 | private_subnet_tags = merge(var.module_tags, var.subnet_tags, var.private_subnet_tags) 201 | intra_subnet_tags = merge(var.module_tags, var.subnet_tags, var.intra_subnet_tags) 202 | 203 | route_table_tags = merge(var.module_tags, var.route_table_tags) 204 | public_route_table_tags = merge(var.module_tags, var.route_table_tags, var.public_route_table_tags) 205 | private_route_table_tags = merge(var.module_tags, var.route_table_tags, var.private_route_table_tags) 206 | intra_route_table_tags = merge(var.module_tags, var.route_table_tags, var.intra_route_table_tags) 207 | } 208 | } 209 | 210 | # ---------------------------------------------------------------------------------------------------------------------- 211 | # OUTPUT MODULE CONFIGURATION 212 | # ---------------------------------------------------------------------------------------------------------------------- 213 | 214 | output "module_enabled" { 215 | description = "Whether the module is enabled." 216 | value = var.module_enabled 217 | } 218 | 219 | output "module_tags" { 220 | description = "A map of tags that will be applied to all created resources that accept tags." 221 | value = var.module_tags 222 | } 223 | -------------------------------------------------------------------------------- /private_routing.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # CREATE PRIVATE ROUTING AND NAT GATEWAYS IF A PRIVATE SUBNETS IS DEFINED 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | private_subnets = [for subnet in local.subnets : subnet if subnet.class == "private"] 7 | 8 | private_group_azs = try(distinct(local.private_subnets.*.group_az), []) 9 | 10 | public_azs = try(distinct(local.public_subnets.*.availability_zone), []) 11 | private_azs = try(distinct(local.private_subnets.*.availability_zone), []) 12 | 13 | private_groups = try(distinct(local.private_subnets.*.group), []) 14 | 15 | private_subnets_by_group = { 16 | for group in local.private_groups : group => [ 17 | for subnet in local.private_subnets : subnet if subnet.group == group 18 | ] 19 | } 20 | 21 | private_subnets_by_group_az = { 22 | for group_az in local.private_group_azs : group_az => [ 23 | for subnet in local.private_subnets : subnet if subnet.group_az == group_az 24 | ] 25 | } 26 | 27 | public_subnets_by_az = { 28 | for az in local.public_azs : az => [ 29 | for subnet in local.public_subnets : subnet if subnet.availability_zone == az 30 | ] 31 | } 32 | 33 | # hacky assertion 34 | assert_each_private_subnet_has_a_public_in_same_az = { 35 | for az in local.missing_public_subnet_azs[var.nat_gateway_mode] : "Missing public subnet in az" => local.public_subnets_by_az[az] 36 | } 37 | 38 | nat_gateway_single_zones = var.nat_gateway_single_mode_zone != null ? ["${local.region}${var.nat_gateway_single_mode_zone}"] : try([local.matching_azs[0]], []) 39 | 40 | matching_azs = sort(setintersection(local.public_azs, local.private_azs)) 41 | nat_azs = { 42 | one_per_az = local.matching_azs 43 | single = local.nat_gateway_single_zones 44 | none = [] 45 | } 46 | 47 | nat_azs_set = toset(local.nat_azs[var.nat_gateway_mode]) 48 | 49 | create_eips = length(keys(var.nat_gateway_eip_allocation_ids)) == 0 50 | 51 | missing_public_subnet_azs = { 52 | one_per_az = sort(setsubtract(local.private_azs, local.public_azs)) 53 | single = length(local.matching_azs) == 0 ? sort(setsubtract(local.private_azs, local.public_azs)) : [] 54 | none = [] 55 | } 56 | } 57 | 58 | resource "aws_eip" "eip" { 59 | for_each = var.module_enabled && local.create_eips ? local.nat_azs_set : [] 60 | 61 | vpc = true 62 | 63 | tags = merge( 64 | { 65 | Name = "${var.vpc_name}-nat-private-${each.key}" 66 | 67 | # special mineiros.io tags that can be used in data sources 68 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 69 | "mineiros-io/aws/vpc/natgw-name" = "${var.vpc_name}-${each.key}" 70 | "mineiros-io/aws/vpc/eip-name" = "${var.vpc_name}-nat-private-${each.key}" 71 | }, 72 | var.module_tags, 73 | var.eip_tags, 74 | ) 75 | 76 | depends_on = [var.module_depends_on] 77 | } 78 | 79 | locals { 80 | nat_gateway_eip_allocation_ids = { for k, v in var.nat_gateway_eip_allocation_ids : "${local.region}${k}" => v } 81 | 82 | eip_allocation_ids = { for k, v in aws_eip.eip : k => v.id } 83 | 84 | allocation_ids = local.create_eips ? local.eip_allocation_ids : local.nat_gateway_eip_allocation_ids 85 | } 86 | 87 | resource "aws_nat_gateway" "nat_gateway" { 88 | for_each = var.module_enabled ? local.nat_azs_set : [] 89 | 90 | allocation_id = local.allocation_ids[each.key] 91 | subnet_id = aws_subnet.subnet[local.public_subnets_by_az[each.key][0].cidr_block].id 92 | 93 | tags = merge( 94 | { 95 | Name = "${var.vpc_name}-${each.key}" 96 | 97 | # special mineiros.io tags that can be used in data sources 98 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 99 | "mineiros-io/aws/vpc/natgw-name" = "${var.vpc_name}-${each.key}" 100 | }, 101 | var.module_tags, 102 | var.nat_gateway_tags, 103 | ) 104 | 105 | depends_on = [var.module_depends_on] 106 | } 107 | 108 | resource "aws_route_table" "private" { 109 | for_each = var.module_enabled ? local.private_subnets_by_group_az : {} 110 | 111 | vpc_id = aws_vpc.vpc[0].id 112 | 113 | # propagating_vgws = try(local.subnets[each.key].propagating_vgws, null) 114 | 115 | tags = merge( 116 | { 117 | Name = "${var.vpc_name}-private-${each.key}" 118 | 119 | # special mineiros.io tags that can be used in data sources 120 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 121 | "mineiros-io/aws/vpc/routetable-name" = "${var.vpc_name}-private-${each.key}" 122 | "mineiros-io/aws/vpc/routetable-class" = "private" 123 | }, 124 | var.module_tags, 125 | var.route_table_tags, 126 | var.private_route_table_tags, 127 | ) 128 | 129 | depends_on = [var.module_depends_on] 130 | } 131 | 132 | resource "aws_route_table_association" "private" { 133 | for_each = var.module_enabled ? { 134 | for subnet in flatten(values(local.private_subnets_by_group_az)) : subnet.cidr_block => subnet 135 | } : {} 136 | 137 | subnet_id = aws_subnet.subnet[each.key].id 138 | route_table_id = aws_route_table.private[each.value.group_az].id 139 | 140 | depends_on = [var.module_depends_on] 141 | } 142 | 143 | locals { 144 | nat_routes = { for k, v in aws_route_table.private : "${var.nat_gateway_mode}/${k}" => v } 145 | } 146 | 147 | resource "aws_route" "nat_gateway" { 148 | for_each = length(local.nat_azs_set) > 0 ? local.nat_routes : {} 149 | 150 | route_table_id = each.value.id 151 | destination_cidr_block = "0.0.0.0/0" 152 | nat_gateway_id = try( 153 | aws_nat_gateway.nat_gateway[local.private_subnets_by_group_az[each.key][0].availability_zone].id, 154 | element(values(aws_nat_gateway.nat_gateway)[*].id, 0), 155 | null, 156 | ) 157 | 158 | # Workaround for https://github.com/terraform-providers/terraform-provider-aws/issues/338 159 | timeouts { 160 | create = "10m" 161 | } 162 | 163 | # we depend on nat gateways to be available for setting and updating routes 164 | # the implicit dependency does not work, when changing nat gateway mode as we will 165 | # only depend on the new gateway implictly and not on the one being removed. 166 | # (e.g. when switching nat_gateway_mode) 167 | depends_on = [ 168 | var.module_depends_on, 169 | aws_nat_gateway.nat_gateway, 170 | ] 171 | } 172 | -------------------------------------------------------------------------------- /public_routing.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # CREATE PUBLIC ROUTING AND AN INTERNET GATEWAY IF A PUBLIC SUBNET IS DEFINED 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | public_subnets = [for subnet in local.subnets : subnet if subnet.class == "public"] 7 | 8 | public_groups = try(distinct(local.public_subnets.*.group), []) 9 | 10 | public_subnets_by_group = { 11 | for group in local.public_groups : group => [ 12 | for subnet in local.public_subnets : subnet if subnet.group == group 13 | ] 14 | } 15 | } 16 | 17 | resource "aws_internet_gateway" "internet_gateway" { 18 | count = var.module_enabled && length(local.public_subnets) > 0 ? 1 : 0 19 | 20 | vpc_id = aws_vpc.vpc[0].id 21 | 22 | tags = merge( 23 | { 24 | Name = var.vpc_name 25 | 26 | # special mineiros.io tags that can be used in data sources 27 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 28 | "mineiros-io/aws/vpc/igw-name" = var.vpc_name 29 | }, 30 | var.module_tags, 31 | var.internet_gateway_tags, 32 | ) 33 | 34 | depends_on = [var.module_depends_on] 35 | } 36 | 37 | resource "aws_route_table" "public" { 38 | for_each = var.module_enabled ? local.public_subnets_by_group : {} 39 | 40 | vpc_id = aws_vpc.vpc[0].id 41 | 42 | # propagating_vgws = try(local.subnets[each.key].propagating_vgws, null) 43 | 44 | tags = merge( 45 | { 46 | Name = "${var.vpc_name}-public-${each.key}" 47 | 48 | # special mineiros.io tags that can be used in data sources 49 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 50 | "mineiros-io/aws/vpc/routetable-name" = "${var.vpc_name}-public-${each.key}" 51 | "mineiros-io/aws/vpc/routetable-class" = "public" 52 | }, 53 | var.module_tags, 54 | var.route_table_tags, 55 | var.public_route_table_tags, 56 | ) 57 | 58 | depends_on = [var.module_depends_on] 59 | } 60 | 61 | resource "aws_route_table_association" "public" { 62 | for_each = var.module_enabled ? { 63 | for subnet in flatten(values(local.public_subnets_by_group)) : subnet.cidr_block => subnet 64 | } : {} 65 | 66 | subnet_id = aws_subnet.subnet[each.key].id 67 | route_table_id = aws_route_table.public[each.value.group].id 68 | 69 | depends_on = [var.module_depends_on] 70 | } 71 | 72 | resource "aws_route" "internet_gateway" { 73 | for_each = aws_route_table.public 74 | 75 | route_table_id = each.value.id 76 | destination_cidr_block = "0.0.0.0/0" 77 | gateway_id = aws_internet_gateway.internet_gateway[0].id 78 | 79 | # Workaround for https://github.com/terraform-providers/terraform-provider-aws/issues/338 80 | timeouts { 81 | create = "10m" 82 | } 83 | 84 | depends_on = [var.module_depends_on] 85 | } 86 | -------------------------------------------------------------------------------- /subnets.tf: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------------------------------------------- 2 | # CREATE PUBLIC, PRIVATE, AND INTRA SUBNETS WITHIN THE VPC 3 | # --------------------------------------------------------------------------------------------------------------------- 4 | 5 | locals { 6 | 7 | # hacky assertion 8 | assert_subnet_have_unique_group_class_combination = { 9 | for subnet in var.subnets : 10 | "${subnet.group}-${subnet.class}" => "class/group combination must be unique in all subnets. See the module's README.md for details." 11 | } 12 | 13 | subnet_tags = { 14 | public = var.public_subnet_tags 15 | private = var.private_subnet_tags 16 | intra = var.intra_subnet_tags 17 | } 18 | 19 | # The following creates a list of subnets by constructing multi-level lists and flattening them in the end. 20 | subnets_tmp = flatten( 21 | [ 22 | for subnet in var.subnets : [ 23 | for az, netnums in subnet.netnums_by_az : [ 24 | for idx, netnum in netnums : { 25 | cidr_block = cidrsubnet(try(subnet.cidr_block, var.cidr_block), try(subnet.newbits, 8), netnum) 26 | availability_zone = "${local.region}${az}" 27 | 28 | map_public_ip_on_launch = try(subnet.map_public_ip_on_launch, subnet.class == "public", false) 29 | 30 | group_az = "${try(subnet.group, "default")}-${local.region}${az}" 31 | 32 | group = try(subnet.group, "default") 33 | class = try(subnet.class, "private") 34 | 35 | db_subnet_group_name = try(subnet.db_subnet_group_name, null) 36 | elasticache_subnet_group_name = try(subnet.elasticache_subnet_group_name, null) 37 | 38 | # routes = try(subnet.routes, []) 39 | 40 | tags = merge( 41 | { 42 | Name = "${var.vpc_name}-${subnet.group}-${subnet.class}-${az}-${idx}" 43 | 44 | # special mineiros.io tags that can be used in data sources 45 | "mineiros-io/aws/vpc/vpc-name" = var.vpc_name 46 | "mineiros-io/aws/vpc/subnet-name" = "${var.vpc_name}-${try(subnet.group, "default")}-${try(subnet.class, "private")}-${az}-${idx}" 47 | "mineiros-io/aws/vpc/subnet-group" = try(subnet.group, "default") 48 | "mineiros-io/aws/vpc/subnet-class" = try(subnet.class, "private") 49 | }, 50 | local.subnet_tags[try(subnet.class, "private")], 51 | try(subnet.tags, {}), 52 | ) 53 | } 54 | ] 55 | ] 56 | ] 57 | ) 58 | 59 | subnets = { 60 | for subnet in local.subnets_tmp : subnet.cidr_block => subnet 61 | } 62 | } 63 | 64 | resource "aws_subnet" "subnet" { 65 | for_each = var.module_enabled ? local.subnets : {} 66 | 67 | vpc_id = aws_vpc.vpc[0].id 68 | 69 | # We convert the cidr_block to its cannonical form. This is actually not needed as we 70 | # already calculate the cidr_block, but to be future proof we do it again anyway. 71 | cidr_block = cidrsubnet(each.value.cidr_block, 0, 0) 72 | 73 | availability_zone = each.value.availability_zone 74 | map_public_ip_on_launch = each.value.map_public_ip_on_launch 75 | 76 | ipv6_cidr_block = try(cidrsubnet(each.value.ipv6_cidr_block, 0, 0), null) 77 | assign_ipv6_address_on_creation = try(each.value.assign_ipv6_address_on_creation, null) 78 | 79 | tags = merge( 80 | var.module_tags, 81 | var.subnet_tags, 82 | each.value.tags, 83 | ) 84 | 85 | depends_on = [var.module_depends_on] 86 | } 87 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | [][homepage] 2 | 3 | [![license][badge-license]][apache20] 4 | [![Terraform Version][badge-terraform]][releases-terraform] 5 | [![Join Slack][badge-slack]][slack] 6 | 7 | # Tests 8 | 9 | This directory contains a number of automated tests that cover the functionality 10 | of the modules that ship with this repository. 11 | 12 | ## Introduction 13 | 14 | We are using [Terratest] for automated tests that are located in the 15 | [`test/` directory][Testdirectory]. Terratest deploys _real_ infrastructure 16 | (e.g., servers) in a _real_ environment (e.g., AWS). 17 | 18 | The basic usage pattern for writing automated tests with Terratest is to: 19 | 20 | 1. Write tests using Go's built-in [package testing]: you create a file ending 21 | in `_test.go` and run tests with the `go test` command. 22 | 2. Use Terratest to execute your _real_ IaC tools (e.g., Terraform, Packer, etc.) 23 | to deploy _real_ infrastructure (e.g., servers) in a _real_ environment (e.g., AWS). 24 | 3. Validate that the infrastructure works correctly in that environment by 25 | making HTTP requests, API calls, SSH connections, etc. 26 | 4. Undeploy everything at the end of the test. 27 | 28 | **Note #1**: Many of these tests create real resources in an AWS account. 29 | That means they cost money to run, especially if you don't clean up after 30 | yourself. Please be considerate of the resources you create and take extra care 31 | to clean everything up when you're done! 32 | 33 | **Note #2**: Never hit `CTRL + C` or cancel a build once tests are running or 34 | the cleanup tasks won't run! 35 | 36 | **Note #3**: We set `-timeout 45m` on all tests not because they necessarily 37 | take 45 minutes, but because Go has a default test timeout of 10 minutes, after 38 | which it does a `SIGQUIT`, preventing the tests from properly cleaning up after 39 | themselves. Therefore, we set a timeout of 45 minutes to make sure all tests 40 | have enough time to finish and cleanup. 41 | 42 | ## How to run the tests 43 | 44 | This repository comes with a [Makefile], that helps you to run the 45 | tests in a convenient way. 46 | Alternatively, you can also run the tests without Docker. 47 | 48 | ### Run the tests with Docker 49 | 50 | 1. Install [Docker] 51 | 2. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` 52 | 3. Run `make docker-run-tests` 53 | 54 | ### Run the tests without Docker 55 | 56 | 1. Install the latest version of [Go]. 57 | 2. Install [Terraform]. 58 | 3. Set your AWS credentials as environment variables: `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` 59 | 4. Install go dependencies: `go mod download` 60 | 5. Run all tests: `go test -v -count 1 -timeout 45m -parallel 128 ./test/...` 61 | or use the convenient `make test/unit-tests` Makefile target. 62 | 6. Run a specific test: `go test -count 1 -v -timeout 45m -parallel 128 test/example_test.go` 63 | 64 | 65 | 66 | [Makefile]: https://github.com/mineiros-io/terraform-aws-vpc/blob/master/Makefile 67 | [Testdirectory]: https://github.com/mineiros-io/terraform-aws-vpc/tree/master/test 68 | 69 | [homepage]: https://mineiros.io/?ref=terraform-aws-vpc 70 | [Terratest]: https://github.com/gruntwork-io/terratest 71 | [package testing]: https://golang.org/pkg/testing/ 72 | [Docker]: https://docs.docker.com/get-started/ 73 | [Go]: https://golang.org/ 74 | [Terraform]: https://www.terraform.io/downloads.html 75 | [badge-license]: https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg 76 | [badge-terraform]: https://img.shields.io/badge/terraform-1.x%20|%200.15%20|%200.14%20|%200.13%20|%200.12.20+-623CE4.svg?logo=terraform 77 | [badge-slack]: https://img.shields.io/badge/slack-@mineiros--community-f32752.svg?logo=slack 78 | 79 | [releases-terraform]: https://github.com/hashicorp/terraform/releases 80 | [apache20]: https://opensource.org/licenses/Apache-2.0 81 | [slack]: https://join.slack.com/t/mineiros-community/shared_invite/zt-ehidestg-aLGoIENLVs6tvwJ11w9WGg 82 | -------------------------------------------------------------------------------- /test/unit-complete/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # COMPLETE FEATURES UNIT TEST 3 | # This module tests a complete set of most/all non-exclusive features 4 | # The purpose is to activate everything the module offers, but trying to keep execution time and costs minimal. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Optional) The AWS region in which all resources will be created." 9 | type = string 10 | default = "eu-west-1" 11 | } 12 | 13 | variable "module_enabled" { 14 | description = "(Optional) Test module_enabled feature. Can be true or false." 15 | type = bool 16 | default = true 17 | } 18 | 19 | variable "nat_gateway_mode" { 20 | description = "(Optional) Test nat_gateway_mode feature. Can be single, one_per_az, or none." 21 | type = string 22 | default = "single" 23 | } 24 | 25 | provider "aws" { 26 | region = var.aws_region 27 | } 28 | 29 | locals { 30 | cidr_block = "192.168.0.0/16" 31 | } 32 | 33 | module "test" { 34 | source = "../.." 35 | 36 | module_enabled = true 37 | 38 | vpc_name = "test" 39 | cidr_block = local.cidr_block 40 | nat_gateway_mode = var.nat_gateway_mode 41 | 42 | subnets = [ 43 | { 44 | group = "test" 45 | class = "public" 46 | 47 | netnums_by_az = { 48 | a = [0] 49 | b = [1] 50 | } 51 | }, 52 | { 53 | group = "test" 54 | class = "private" 55 | 56 | netnums_by_az = { 57 | a = [2] 58 | b = [3] 59 | } 60 | }, 61 | { 62 | group = "test" 63 | class = "intra" 64 | 65 | netnums_by_az = { 66 | a = [128] 67 | b = [129] 68 | } 69 | }, 70 | { 71 | group = "db" 72 | class = "intra" 73 | 74 | db_subnet_group_name = "my-db-subnet-group" 75 | 76 | tags = { 77 | "foo" = "bar" 78 | } 79 | 80 | netnums_by_az = { 81 | a = [130] 82 | b = [131] 83 | } 84 | }, 85 | ] 86 | 87 | module_tags = { 88 | Environment = "unknown" 89 | } 90 | 91 | module_depends_on = ["nothing"] 92 | } 93 | -------------------------------------------------------------------------------- /test/unit-disabled/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # EMPTY FEATURES (DISABLED) UNIT TEST 3 | # This module tests an empty set of features. 4 | # The purpose is to verify no resources are created when the module is disabled. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Required) The AWS region in which all resources will be created." 9 | type = string 10 | default = "eu-west-1" 11 | } 12 | 13 | provider "aws" { 14 | region = var.aws_region 15 | } 16 | 17 | module "test" { 18 | source = "../.." 19 | 20 | module_enabled = false 21 | } 22 | -------------------------------------------------------------------------------- /test/unit-minimal/main.tf: -------------------------------------------------------------------------------- 1 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2 | # MINIMAL FEATURES UNIT TEST 3 | # This module tests a minimal set of features. 4 | # The purpose is to test all defaults for optional arguments and just provide the required arguments. 5 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | variable "aws_region" { 8 | description = "(Optional) The AWS region in which all resources will be created." 9 | type = string 10 | default = "eu-west-1" 11 | } 12 | 13 | provider "aws" { 14 | region = var.aws_region 15 | } 16 | 17 | module "test" { 18 | source = "../.." 19 | } 20 | -------------------------------------------------------------------------------- /test/unit_complete_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestUnitComplete(t *testing.T) { 11 | t.Parallel() 12 | 13 | // deploy initial example with one nat gateway per az 14 | terraformOptions := &terraform.Options{ 15 | TerraformDir: "unit-complete", 16 | Upgrade: true, 17 | Vars: map[string]interface{}{ 18 | "nat_gateway_mode": "one_per_az", 19 | }, 20 | } 21 | 22 | defer terraform.Destroy(t, terraformOptions) 23 | 24 | terraform.InitAndPlan(t, terraformOptions) 25 | terraform.Apply(t, terraformOptions) 26 | 27 | stdout := terraform.Plan(t, terraformOptions) 28 | 29 | resourceCount := terraform.GetResourceCount(t, stdout) 30 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 31 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 32 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 33 | 34 | // deploy upgraded example with single nat gateway 35 | terraformOptions = &terraform.Options{ 36 | TerraformDir: "unit-complete", 37 | Upgrade: true, 38 | Vars: map[string]interface{}{ 39 | "nat_gateway_mode": "single", 40 | }, 41 | } 42 | terraform.Plan(t, terraformOptions) 43 | terraform.Apply(t, terraformOptions) 44 | 45 | stdout = terraform.Plan(t, terraformOptions) 46 | 47 | resourceCount = terraform.GetResourceCount(t, stdout) 48 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 49 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 50 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 51 | 52 | // deploy upgraded example with no nat gateways 53 | terraformOptions = &terraform.Options{ 54 | TerraformDir: "unit-complete", 55 | Upgrade: true, 56 | Vars: map[string]interface{}{ 57 | "nat_gateway_mode": "none", 58 | }, 59 | } 60 | terraform.Plan(t, terraformOptions) 61 | terraform.Apply(t, terraformOptions) 62 | 63 | stdout = terraform.Plan(t, terraformOptions) 64 | 65 | resourceCount = terraform.GetResourceCount(t, stdout) 66 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 67 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 68 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 69 | } 70 | -------------------------------------------------------------------------------- /test/unit_disabled_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestUnitDisabled(t *testing.T) { 11 | t.Parallel() 12 | 13 | terraformOptions := &terraform.Options{ 14 | TerraformDir: "unit-disabled", 15 | Vars: map[string]interface{}{ 16 | "aws_region": "eu-west-1", 17 | }, 18 | Upgrade: true, 19 | } 20 | 21 | defer terraform.Destroy(t, terraformOptions) 22 | 23 | terraform.InitAndPlan(t, terraformOptions) 24 | stdout := terraform.ApplyAndIdempotent(t, terraformOptions) 25 | 26 | resourceCount := terraform.GetResourceCount(t, stdout) 27 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 28 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 29 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 30 | } 31 | -------------------------------------------------------------------------------- /test/unit_minimal_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/gruntwork-io/terratest/modules/terraform" 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func TestUnitMinimal(t *testing.T) { 11 | t.Parallel() 12 | 13 | terraformOptions := &terraform.Options{ 14 | TerraformDir: "unit-minimal", 15 | Vars: map[string]interface{}{ 16 | "aws_region": "eu-west-1", 17 | }, 18 | Upgrade: true, 19 | } 20 | 21 | defer terraform.Destroy(t, terraformOptions) 22 | 23 | terraform.InitAndPlan(t, terraformOptions) 24 | terraform.Apply(t, terraformOptions) 25 | 26 | stdout := terraform.Plan(t, terraformOptions) 27 | 28 | resourceCount := terraform.GetResourceCount(t, stdout) 29 | assert.Equal(t, 0, resourceCount.Add, "No resources should have been created. Found %d instead.", resourceCount.Add) 30 | assert.Equal(t, 0, resourceCount.Change, "No resources should have been changed. Found %d instead.", resourceCount.Change) 31 | assert.Equal(t, 0, resourceCount.Destroy, "No resources should have been destroyed. Found %d instead.", resourceCount.Destroy) 32 | } 33 | -------------------------------------------------------------------------------- /variables.tf: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------------------------------------------------- 2 | # REQUIRED PARAMETERS 3 | # These variables must be set when using this module. 4 | # ---------------------------------------------------------------------------------------------------------------------- 5 | 6 | # ---------------------------------------------------------------------------------------------------------------------- 7 | # OPTIONAL PARAMETERS 8 | # These variables have defaults, but may be overridden. 9 | # ---------------------------------------------------------------------------------------------------------------------- 10 | 11 | variable "vpc_name" { 12 | description = "(Optional) The name of the VPC. Default is \"main\"." 13 | type = string 14 | default = "main" 15 | } 16 | 17 | variable "cidr_block" { 18 | description = "(Optional) The CIDR block for the VPC. The permissible size of the block ranges between a /16 netmask and a /28 netmask. We advice you to use a CIDR block reserved for private address space as recommended in RFC 1918 http://www.faqs.org/rfcs/rfc1918.html. Default is \"10.0.0.0/16\"" 19 | type = string 20 | default = "10.0.0.0/16" 21 | } 22 | 23 | variable "assign_generated_ipv6_cidr_block" { 24 | description = "(Optional) Requests an AWS-provided IPv6 CIDR block with a /56 prefix length for the VPC. You cannot specify the range of IP addresses, or the size of the CIDR block. Default is false." 25 | type = bool 26 | default = false 27 | } 28 | 29 | variable "enable_classiclink" { 30 | description = "(Optional) Whether or not to enable ClassicLink for the VPC. Only valid in regions and accounts that support EC2 Classic. Read more: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/vpc-classiclink.html. Default is false." 31 | type = bool 32 | default = false 33 | } 34 | 35 | variable "enable_classiclink_dns_support" { 36 | description = "(Optional) Whether or not to enable ClassicLink DNS Support for the VPC. Only valid in regions and accounts that support EC2 Classic. Default is false." 37 | type = bool 38 | default = false 39 | } 40 | 41 | variable "enable_dns_support" { 42 | description = "(Optional) Whether or not to enable DNS support in the VPC. Default is true." 43 | type = bool 44 | default = true 45 | } 46 | 47 | variable "enable_dns_hostnames" { 48 | description = "(Optional) Whether or not to enable DNS hostnames in the VPC. Default is false." 49 | type = bool 50 | default = false 51 | } 52 | 53 | variable "instance_tenancy" { 54 | description = "(Optional) A tenancy option for instances launched into the VPC. Default is \"default\"." 55 | type = string 56 | default = "default" 57 | } 58 | 59 | variable "vpc_tags" { 60 | description = "(Optional) A map of tags to apply to the created VPC. Default is {}." 61 | type = map(string) 62 | default = {} 63 | } 64 | 65 | variable "subnets" { 66 | description = "(Optional) List of subnet definitions. See README.md for details. Default is []." 67 | type = any 68 | default = [] 69 | } 70 | 71 | variable "subnet_tags" { 72 | description = "(Optional) A map of tags to apply to the created Subnet. Default is {}." 73 | type = map(string) 74 | default = {} 75 | } 76 | 77 | variable "public_subnet_tags" { 78 | description = "(Optional) A map of tags to apply to the created Public Subnets. Default is {}." 79 | type = map(string) 80 | default = {} 81 | } 82 | 83 | variable "private_subnet_tags" { 84 | description = "(Optional) A map of tags to apply to the created Private Subnets. Default is {}." 85 | type = map(string) 86 | default = {} 87 | } 88 | 89 | variable "intra_subnet_tags" { 90 | description = "(Optional) A map of tags to apply to the created Intra Subnets. Default is {}." 91 | type = map(string) 92 | default = {} 93 | } 94 | 95 | variable "route_table_tags" { 96 | description = "(Optional) A map of tags to apply to the created Public Route Table. Default is {}." 97 | type = map(string) 98 | default = {} 99 | } 100 | 101 | variable "public_route_table_tags" { 102 | description = "(Optional) A map of tags to apply to the created Public Route Table. Default is {}." 103 | type = map(string) 104 | default = {} 105 | } 106 | 107 | variable "private_route_table_tags" { 108 | description = "(Optional) A map of tags to apply to the created Private Route Table. Default is {}." 109 | type = map(string) 110 | default = {} 111 | } 112 | 113 | variable "intra_route_table_tags" { 114 | description = "(Optional) A map of tags to apply to the created Intra Route Table. Default is {}." 115 | type = map(string) 116 | default = {} 117 | } 118 | 119 | variable "nat_gateway_mode" { 120 | description = "(Optional) Set the mode for the NAT Gateways. Possible inputs are \"none\" (create no NAT Gateways at all), \"single\" (create a single NAT Gateway inside the first defined Public Subnet) and \"one_per_az\" (create one NAT Gateway inside the first Public Subnet in each Availability Zone). Default is \"single\"." 121 | type = string 122 | default = "single" 123 | } 124 | 125 | variable "nat_gateway_single_mode_zone" { 126 | description = "(Optional) Define the zone (short name) of the NAT gateway when nat_gateway_mode is \"single\" (e.g. \"a\", \"b\", or \"c\"). The AWS region will be added as a prefix. Defaults to a random zone." 127 | type = string 128 | default = null 129 | } 130 | 131 | variable "nat_gateway_eip_allocation_ids" { 132 | description = "(Optional) A map of EIP allocation ids to use for nat gateways keyed by short zone name (e.g. \"a\", \"b\", or \"c\")." 133 | type = map(string) 134 | default = {} 135 | } 136 | 137 | variable "nat_gateway_tags" { 138 | description = "(Optional) A map of tags to apply to the created NAT Gateways. Default is {}." 139 | type = map(string) 140 | default = {} 141 | } 142 | 143 | variable "eip_tags" { 144 | description = "(Optional) A map of tags to apply to the created NAT Gateway Elastic IP Addresses. Default is {}." 145 | type = map(string) 146 | default = {} 147 | } 148 | 149 | variable "internet_gateway_tags" { 150 | description = "(Optional) A map of tags to apply to the created Internet Gateway. Default is {}." 151 | type = map(string) 152 | default = {} 153 | } 154 | 155 | 156 | # ---------------------------------------------------------------------------------------------------------------------- 157 | # MODULE CONFIGURATION PARAMETERS 158 | # These variables are used to configure the module. 159 | # See https://medium.com/mineiros/the-ultimate-guide-on-how-to-write-terraform-modules-part-1-81f86d31f024 160 | # ---------------------------------------------------------------------------------------------------------------------- 161 | 162 | variable "module_enabled" { 163 | type = bool 164 | description = "(Optional) Whether to create resources within the module or not. Default is true." 165 | default = true 166 | } 167 | 168 | variable "module_depends_on" { 169 | type = any 170 | description = "(Optional) A list of external resources the module depends_on. Default is []." 171 | default = [] 172 | } 173 | 174 | variable "module_tags" { 175 | description = "(Optional) A map of default tags to apply to all resources created which support tags. Default is {}." 176 | type = map(string) 177 | default = {} 178 | } 179 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | # ---------------------------------------------------------------------------------------------------------------------- 2 | # SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE 3 | # ---------------------------------------------------------------------------------------------------------------------- 4 | 5 | terraform { 6 | required_version = ">= 0.12.20, < 2.0" 7 | 8 | required_providers { 9 | aws = { 10 | source = "hashicorp/aws" 11 | version = ">= 2.45, < 4.0" 12 | } 13 | } 14 | } 15 | --------------------------------------------------------------------------------