diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 241026e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -addons: - apt: - packages: - - git - - make - - curl - -install: - - make init - -script: - - make terraform/install - - make terraform/get-plugins - - make terraform/get-modules - - make terraform/lint - - make terraform/validate diff --git a/README.md b/README.md index 3eaeb67..0bd29aa 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,50 @@ - + [![README Header][readme_header_img]][readme_header_link] [![Cloud Posse][logo]](https://cpco.io/homepage) # terraform-aws-vpc-peering-multi-account - [![Build Status](https://travis-ci.org/cloudposse/terraform-aws-vpc-peering-multi-account.svg?branch=master)](https://travis-ci.org/cloudposse/terraform-aws-vpc-peering-multi-account) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-vpc-peering-multi-account.svg)](https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) + [![Codefresh Build Status](https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-vpc-peering-multi-account?type=cf-1)](https://g.codefresh.io/public/accounts/cloudposse/pipelines/5e9f4c44c2b7b0abe4c11f63) [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-vpc-peering-multi-account.svg)](https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) Terraform module to create a peering connection between any two VPCs existing in different AWS accounts. @@ -55,6 +94,11 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are ## Usage +**IMPORTANT:** The `master` branch is used in `source` just as an example. In your code, do not pin to `master` because there may be breaking changes between releases. +Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest releases](https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/releases). + + + **IMPORTANT:** Do not pin to `master` because there may be breaking changes between releases. Instead pin to the release tag (e.g. `?ref=tags/x.y.z`) of one of our [latest releases](https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/releases). For a complete example, see [examples/complete](examples/complete) @@ -69,12 +113,12 @@ module "vpc_peering_cross_account" { requester_aws_assume_role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test" requester_region = "us-west-2" requester_vpc_id = "vpc-xxxxxxxx" - requester_allow_remote_vpc_dns_resolution = "true" + requester_allow_remote_vpc_dns_resolution = true accepter_aws_assume_role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test" accepter_region = "us-east-1" accepter_vpc_id = "vpc-yyyyyyyy" - accepter_allow_remote_vpc_dns_resolution = "true" + accepter_allow_remote_vpc_dns_resolution = true } ``` @@ -264,38 +308,6 @@ Available targets: lint Lint terraform code ``` -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|:----:|:-----:|:-----:| -| accepter_allow_remote_vpc_dns_resolution | Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC | string | `true` | no | -| accepter_aws_assume_role_arn | Accepter AWS Assume Role ARN | string | - | yes | -| accepter_region | Accepter AWS region | string | - | yes | -| accepter_vpc_id | Accepter VPC ID filter | string | `` | no | -| accepter_vpc_tags | Accepter VPC Tags filter | map | `` | no | -| attributes | Additional attributes (e.g. `a` or `b`) | list | `` | no | -| auto_accept | Automatically accept the peering | string | `true` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name`, and `attributes` | string | `-` | no | -| enabled | Set to false to prevent the module from creating or accessing any resources | string | `true` | no | -| name | Name (e.g. `app` or `cluster`) | string | - | yes | -| namespace | Namespace (e.g. `eg` or `cp`) | string | - | yes | -| requester_allow_remote_vpc_dns_resolution | Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC | string | `true` | no | -| requester_aws_assume_role_arn | Requester AWS Assume Role ARN | string | - | yes | -| requester_region | Requester AWS region | string | - | yes | -| requester_vpc_id | Requester VPC ID filter | string | `` | no | -| requester_vpc_tags | Requester VPC Tags filter | map | `` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | - | yes | -| tags | Additional tags (e.g. `{"BusinessUnit" = "XYZ"`) | map | `` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| accepter_accept_status | Accepter VPC peering connection request status | -| accepter_connection_id | Accepter VPC peering connection ID | -| requester_accept_status | Requester VPC peering connection request status | -| requester_connection_id | Requester VPC peering connection ID | - @@ -326,42 +338,51 @@ For additional context, refer to some of these links. ## Help -**Got a question?** +**Got a question?** We got answers. File a GitHub [issue](https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/issues), send us an [email][email] or join our [Slack Community][slack]. [![README Commercial Support][readme_commercial_support_img]][readme_commercial_support_link] -## Commercial Support +## DevOps Accelerator for Startups -Work directly with our team of DevOps experts via email, slack, and video conferencing. -We provide [*commercial support*][commercial_support] for all of our [Open Source][github] projects. As a *Dedicated Support* customer, you have access to our team of subject matter experts at a fraction of the cost of a full-time engineer. +We are a [**DevOps Accelerator**][commercial_support]. We'll help you build your cloud infrastructure from the ground up so you can own it. Then we'll show you how to operate it and stick around for as long as you need us. -[![E-Mail](https://img.shields.io/badge/email-hello@cloudposse.com-blue.svg)][email] +[![Learn More](https://img.shields.io/badge/learn%20more-success.svg?style=for-the-badge)][commercial_support] -- **Questions.** We'll use a Shared Slack channel between your team and ours. -- **Troubleshooting.** We'll help you triage why things aren't working. -- **Code Reviews.** We'll review your Pull Requests and provide constructive feedback. -- **Bug Fixes.** We'll rapidly work to fix any bugs in our projects. -- **Build New Terraform Modules.** We'll [develop original modules][module_development] to provision infrastructure. -- **Cloud Architecture.** We'll assist with your cloud strategy and design. -- **Implementation.** We'll provide hands-on support to implement our reference architectures. +Work directly with our team of DevOps experts via email, slack, and video conferencing. +We deliver 10x the value for a fraction of the cost of a full-time engineer. Our track record is not even funny. If you want things done right and you need it done FAST, then we're your best bet. - -## Terraform Module Development - -Are you interested in custom Terraform module development? Submit your inquiry using [our form][module_development] today and we'll get back to you ASAP. - +- **Reference Architecture.** You'll get everything you need from the ground up built using 100% infrastructure as code. +- **Release Engineering.** You'll have end-to-end CI/CD with unlimited staging environments. +- **Site Reliability Engineering.** You'll have total visibility into your apps and microservices. +- **Security Baseline.** You'll have built-in governance with accountability and audit logs for all changes. +- **GitOps.** You'll be able to operate your infrastructure via Pull Requests. +- **Training.** You'll receive hands-on training so your team can operate what we build. +- **Questions.** You'll have a direct line of communication between our teams via a Shared Slack channel. +- **Troubleshooting.** You'll get help to triage when things aren't working. +- **Code Reviews.** You'll receive constructive feedback on Pull Requests. +- **Bug Fixes.** We'll rapidly work with you to fix any bugs in our projects. ## Slack Community Join our [Open Source Community][slack] on Slack. It's **FREE** for everyone! Our "SweetOps" community is where you get to talk with others who share a similar vision for how to rollout and manage infrastructure. This is the best place to talk shop, ask questions, solicit feedback, and work together as a community to build totally *sweet* infrastructure. +## Discourse Forums + +Participate in our [Discourse Forums][discourse]. Here you'll find answers to commonly asked questions. Most questions will be related to the enormous number of projects we support on our GitHub. Come here to collaborate on answers, find solutions, and get ideas about the products and services we value. It only takes a minute to get started! Just sign in with SSO using your GitHub account. + ## Newsletter -Signup for [our newsletter][newsletter] that covers everything on our technology radar. Receive updates on what we're up to on GitHub as well as awesome new projects we discover. +Sign up for [our newsletter][newsletter] that covers everything on our technology radar. Receive updates on what we're up to on GitHub as well as awesome new projects we discover. + +## Office Hours + +[Join us every Wednesday via Zoom][office_hours] for our weekly "Lunch & Learn" sessions. It's **FREE** for everyone! + +[![zoom](https://img.cloudposse.com/fit-in/200x200/https://cloudposse.com/wp-content/uploads/2019/08/Powered-by-Zoom.png")][office_hours] ## Contributing @@ -386,7 +407,7 @@ In general, PRs are welcome. We follow the typical "fork-and-pull" Git workflow. ## Copyright -Copyright © 2017-2019 [Cloud Posse, LLC](https://cpco.io/copyright) +Copyright © 2017-2020 [Cloud Posse, LLC](https://cpco.io/copyright) @@ -445,37 +466,36 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply |---|---| [aknysh_homepage]: https://github.com/aknysh - [aknysh_avatar]: https://github.com/aknysh.png?size=150 + [aknysh_avatar]: https://img.cloudposse.com/150x150/https://github.com/aknysh.png [osterman_homepage]: https://github.com/osterman - [osterman_avatar]: https://github.com/osterman.png?size=150 - - + [osterman_avatar]: https://img.cloudposse.com/150x150/https://github.com/osterman.png [![README Footer][readme_footer_img]][readme_footer_link] [![Beacon][beacon]][website] [logo]: https://cloudposse.com/logo-300x69.svg - [docs]: https://cpco.io/docs - [website]: https://cpco.io/homepage - [github]: https://cpco.io/github - [jobs]: https://cpco.io/jobs - [hire]: https://cpco.io/hire - [slack]: https://cpco.io/slack - [linkedin]: https://cpco.io/linkedin - [twitter]: https://cpco.io/twitter - [testimonial]: https://cpco.io/leave-testimonial - [newsletter]: https://cpco.io/newsletter - [email]: https://cpco.io/email - [commercial_support]: https://cpco.io/commercial-support - [we_love_open_source]: https://cpco.io/we-love-open-source - [module_development]: https://cpco.io/module-development - [terraform_modules]: https://cpco.io/terraform-modules - [readme_header_img]: https://cloudposse.com/readme/header/img?repo=cloudposse/terraform-aws-vpc-peering-multi-account - [readme_header_link]: https://cloudposse.com/readme/header/link?repo=cloudposse/terraform-aws-vpc-peering-multi-account - [readme_footer_img]: https://cloudposse.com/readme/footer/img?repo=cloudposse/terraform-aws-vpc-peering-multi-account - [readme_footer_link]: https://cloudposse.com/readme/footer/link?repo=cloudposse/terraform-aws-vpc-peering-multi-account - [readme_commercial_support_img]: https://cloudposse.com/readme/commercial-support/img?repo=cloudposse/terraform-aws-vpc-peering-multi-account - [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?repo=cloudposse/terraform-aws-vpc-peering-multi-account + [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=docs + [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=website + [github]: https://cpco.io/github?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=github + [jobs]: https://cpco.io/jobs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=jobs + [hire]: https://cpco.io/hire?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=hire + [slack]: https://cpco.io/slack?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=slack + [linkedin]: https://cpco.io/linkedin?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=linkedin + [twitter]: https://cpco.io/twitter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=twitter + [testimonial]: https://cpco.io/leave-testimonial?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=testimonial + [office_hours]: https://cloudposse.com/office-hours?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=office_hours + [newsletter]: https://cpco.io/newsletter?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=newsletter + [discourse]: https://ask.sweetops.com/?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=discourse + [email]: https://cpco.io/email?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=email + [commercial_support]: https://cpco.io/commercial-support?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=commercial_support + [we_love_open_source]: https://cpco.io/we-love-open-source?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=we_love_open_source + [terraform_modules]: https://cpco.io/terraform-modules?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=terraform_modules + [readme_header_img]: https://cloudposse.com/readme/header/img + [readme_header_link]: https://cloudposse.com/readme/header/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=readme_header_link + [readme_footer_img]: https://cloudposse.com/readme/footer/img + [readme_footer_link]: https://cloudposse.com/readme/footer/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=readme_footer_link + [readme_commercial_support_img]: https://cloudposse.com/readme/commercial-support/img + [readme_commercial_support_link]: https://cloudposse.com/readme/commercial-support/link?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-vpc-peering-multi-account&utm_content=readme_commercial_support_link [share_twitter]: https://twitter.com/intent/tweet/?text=terraform-aws-vpc-peering-multi-account&url=https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account [share_linkedin]: https://www.linkedin.com/shareArticle?mini=true&title=terraform-aws-vpc-peering-multi-account&url=https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account [share_reddit]: https://reddit.com/submit/?url=https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account diff --git a/README.yaml b/README.yaml index d839288..6c4e334 100644 --- a/README.yaml +++ b/README.yaml @@ -35,9 +35,9 @@ github_repo: cloudposse/terraform-aws-vpc-peering-multi-account # Badges to display badges: - - name: "Build Status" - image: "https://travis-ci.org/cloudposse/terraform-aws-vpc-peering-multi-account.svg?branch=master" - url: "https://travis-ci.org/cloudposse/terraform-aws-vpc-peering-multi-account" + - name: "Codefresh Build Status" + image: "https://g.codefresh.io/api/badges/pipeline/cloudposse/terraform-modules%2Fterraform-aws-vpc-peering-multi-account?type=cf-1" + url: "https://g.codefresh.io/public/accounts/cloudposse/pipelines/5e9f4c44c2b7b0abe4c11f63" - name: "Latest Release" image: "https://img.shields.io/github/release/cloudposse/terraform-aws-vpc-peering-multi-account.svg" url: "https://github.com/cloudposse/terraform-aws-vpc-peering-multi-account/releases/latest" @@ -82,12 +82,12 @@ usage: |- requester_aws_assume_role_arn = "arn:aws:iam::XXXXXXXX:role/cross-account-vpc-peering-test" requester_region = "us-west-2" requester_vpc_id = "vpc-xxxxxxxx" - requester_allow_remote_vpc_dns_resolution = "true" + requester_allow_remote_vpc_dns_resolution = true accepter_aws_assume_role_arn = "arn:aws:iam::YYYYYYYY:role/cross-account-vpc-peering-test" accepter_region = "us-east-1" accepter_vpc_id = "vpc-yyyyyyyy" - accepter_allow_remote_vpc_dns_resolution = "true" + accepter_allow_remote_vpc_dns_resolution = true } ``` diff --git a/accepter.tf b/accepter.tf index 9912e43..241e226 100644 --- a/accepter.tf +++ b/accepter.tf @@ -1,138 +1,125 @@ -variable "accepter_aws_assume_role_arn" { - description = "Accepter AWS Assume Role ARN" - type = "string" -} - -variable "accepter_region" { - type = "string" - description = "Accepter AWS region" -} - -variable "accepter_vpc_id" { - type = "string" - description = "Accepter VPC ID filter" - default = "" -} - -variable "accepter_vpc_tags" { - type = "map" - description = "Accepter VPC Tags filter" - default = {} -} - -variable "accepter_allow_remote_vpc_dns_resolution" { - default = "true" - description = "Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC" -} - # Accepter's credentials provider "aws" { - alias = "accepter" - region = "${var.accepter_region}" - version = ">= 1.25" - - assume_role { - role_arn = "${var.accepter_aws_assume_role_arn}" + alias = "accepter" + region = var.accepter_region + + dynamic "assume_role" { + for_each = var.accepter_aws_assume_role_arn != "" ? ["true"] : [] + content { + role_arn = var.accepter_aws_assume_role_arn + } } } locals { - accepter_attributes = "${concat(var.attributes, list("accepter"))}" - accepter_tags = "${merge(var.tags, map("Side", "accepter"))}" + accepter_attributes = concat(var.attributes, ["accepter"]) + accepter_tags = merge( + var.tags, + { + "Side" = "accepter" + }, + ) } module "accepter" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.3" - enabled = "${var.enabled}" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - delimiter = "${var.delimiter}" - attributes = "${local.accepter_attributes}" - tags = "${local.accepter_tags}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + enabled = var.enabled + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = local.accepter_attributes + tags = local.accepter_tags } data "aws_caller_identity" "accepter" { - count = "${local.count}" - provider = "aws.accepter" + count = local.count + provider = aws.accepter } data "aws_region" "accepter" { - count = "${local.count}" - provider = "aws.accepter" + count = local.count + provider = aws.accepter } # Lookup accepter's VPC so that we can reference the CIDR data "aws_vpc" "accepter" { - count = "${local.count}" - provider = "aws.accepter" - id = "${var.accepter_vpc_id}" - tags = "${var.accepter_vpc_tags}" + count = local.count + provider = aws.accepter + id = var.accepter_vpc_id + tags = var.accepter_vpc_tags } # Lookup accepter subnets data "aws_subnet_ids" "accepter" { - count = "${local.count}" - provider = "aws.accepter" - vpc_id = "${local.accepter_vpc_id}" + count = local.count + provider = aws.accepter + vpc_id = local.accepter_vpc_id } locals { - accepter_subnet_ids = "${distinct(sort(flatten(data.aws_subnet_ids.accepter.*.ids)))}" - accepter_subnet_ids_count = "${length(local.accepter_subnet_ids)}" - accepter_vpc_id = "${join("", data.aws_vpc.accepter.*.id)}" - accepter_account_id = "${join("", data.aws_caller_identity.accepter.*.account_id)}" - accepter_region = "${join("", data.aws_region.accepter.*.name)}" + accepter_subnet_ids = distinct(sort(flatten(data.aws_subnet_ids.accepter.*.ids))) + accepter_subnet_ids_count = length(local.accepter_subnet_ids) + accepter_vpc_id = join("", data.aws_vpc.accepter.*.id) + accepter_account_id = join("", data.aws_caller_identity.accepter.*.account_id) + accepter_region = join("", data.aws_region.accepter.*.name) } # Lookup accepter route tables data "aws_route_tables" "accepter" { - count = "${local.count}" - provider = "aws.accepter" - vpc_id = "${local.accepter_vpc_id}" + count = local.count + provider = aws.accepter + vpc_id = local.accepter_vpc_id } locals { - accepter_aws_route_table_ids = "${distinct(sort(data.aws_route_tables.accepter.ids))}" - accepter_aws_route_table_ids_count = "${length(local.accepter_aws_route_table_ids)}" - accepter_cidr_block_associations = "${flatten(data.aws_vpc.accepter.*.cidr_block_associations)}" - accepter_cidr_block_associations_count = "${length(local.accepter_cidr_block_associations)}" + accepter_aws_route_table_ids = distinct(sort(data.aws_route_tables.accepter[0].ids)) + accepter_aws_route_table_ids_count = length(local.accepter_aws_route_table_ids) + accepter_cidr_block_associations = flatten(data.aws_vpc.accepter.*.cidr_block_associations) + accepter_cidr_block_associations_count = length(local.accepter_cidr_block_associations) } # Create routes from accepter to requester resource "aws_route" "accepter" { - count = "${local.enabled ? local.accepter_aws_route_table_ids_count * local.requester_cidr_block_associations_count : 0}" - provider = "aws.accepter" - route_table_id = "${element(local.accepter_aws_route_table_ids, ceil(count.index / local.requester_cidr_block_associations_count))}" - destination_cidr_block = "${lookup(local.requester_cidr_block_associations[count.index % local.requester_cidr_block_associations_count], "cidr_block")}" - vpc_peering_connection_id = "${join("", aws_vpc_peering_connection.requester.*.id)}" - depends_on = ["data.aws_route_tables.accepter", "aws_vpc_peering_connection_accepter.accepter", "aws_vpc_peering_connection.requester"] + count = var.enabled ? local.accepter_aws_route_table_ids_count * local.requester_cidr_block_associations_count : 0 + provider = aws.accepter + route_table_id = local.accepter_aws_route_table_ids[ceil(count.index / local.requester_cidr_block_associations_count)] + destination_cidr_block = local.requester_cidr_block_associations[count.index % local.requester_cidr_block_associations_count]["cidr_block"] + vpc_peering_connection_id = join("", aws_vpc_peering_connection.requester.*.id) + depends_on = [ + data.aws_route_tables.accepter, + aws_vpc_peering_connection_accepter.accepter, + aws_vpc_peering_connection.requester, + ] } # Accepter's side of the connection. resource "aws_vpc_peering_connection_accepter" "accepter" { - count = "${local.count}" - provider = "aws.accepter" - vpc_peering_connection_id = "${join("", aws_vpc_peering_connection.requester.*.id)}" - auto_accept = "${var.auto_accept}" - tags = "${module.accepter.tags}" + count = local.count + provider = aws.accepter + vpc_peering_connection_id = join("", aws_vpc_peering_connection.requester.*.id) + auto_accept = var.auto_accept + tags = module.accepter.tags } resource "aws_vpc_peering_connection_options" "accepter" { - provider = "aws.accepter" - vpc_peering_connection_id = "${join("", aws_vpc_peering_connection.requester.*.id)}" + provider = aws.accepter + vpc_peering_connection_id = local.active_vpc_peering_connection_id accepter { - allow_remote_vpc_dns_resolution = "${var.accepter_allow_remote_vpc_dns_resolution}" + allow_remote_vpc_dns_resolution = var.accepter_allow_remote_vpc_dns_resolution } } output "accepter_connection_id" { - value = "${join("", aws_vpc_peering_connection_accepter.accepter.*.id)}" + value = join("", aws_vpc_peering_connection_accepter.accepter.*.id) description = "Accepter VPC peering connection ID" } output "accepter_accept_status" { - value = "${join("", aws_vpc_peering_connection_accepter.accepter.*.accept_status)}" + value = join( + "", + aws_vpc_peering_connection_accepter.accepter.*.accept_status, + ) description = "Accepter VPC peering connection request status" -} +} \ No newline at end of file diff --git a/codefresh/test.yml b/codefresh/test.yml new file mode 100644 index 0000000..420143a --- /dev/null +++ b/codefresh/test.yml @@ -0,0 +1,73 @@ +version: '1.0' +steps: + wait: + title: Wait + stage: Prepare + image: 'codefresh/cli:latest' + commands: + - >- + codefresh get builds --pipeline=${{CF_REPO_NAME}} --status running + --limit 1000 -o json | jq --arg id ${{CF_BUILD_ID}} -ser + 'flatten|.[-1].id==$id' + retry: + maxAttempts: 10 + delay: 20 + exponentialFactor: 1.1 + main_clone: + title: Clone repository + type: git-clone + stage: Prepare + description: Initialize + repo: '${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}' + git: CF-default + revision: '${{CF_REVISION}}' + clean_init: + title: Prepare build-harness and test-harness + image: '${{TEST_IMAGE}}' + stage: Prepare + commands: + - >- + cf_export + PATH="/usr/local/terraform/0.12/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" + - make init + - git -C build-harness checkout master + - make -C test/ clean init TEST_HARNESS_BRANCH=master + - make -C test/src clean init + - find . -type d -name '.terraform' | xargs rm -rf + - 'find . -type f -name ''terraform.tfstate*'' -exec rm -f {} \;' + test: + type: parallel + title: Run tests + description: Run all tests in parallel + stage: Test + steps: + test_readme_lint: + title: Test README.md updated + stage: Test + image: '${{TEST_IMAGE}}' + description: Test "readme/lint" + commands: + - make readme/lint + test_module: + title: Test module with bats + image: '${{TEST_IMAGE}}' + stage: Test + commands: + - make -C test/ module + test_examples_complete: + title: Test "examples/complete" with bats + image: '${{TEST_IMAGE}}' + stage: Test + commands: + - make -C test/ examples/complete + test_examples_complete_terratest: + title: Test "examples/complete" with terratest + image: '${{TEST_IMAGE}}' + stage: Test + commands: + - make -C test/src +stages: + - Prepare + - Test +services: {} +fail_fast: true diff --git a/docs/terraform.md b/docs/terraform.md index ea502a2..e69de29 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -1,32 +0,0 @@ -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|:----:|:-----:|:-----:| -| accepter_allow_remote_vpc_dns_resolution | Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC | string | `true` | no | -| accepter_aws_assume_role_arn | Accepter AWS Assume Role ARN | string | - | yes | -| accepter_region | Accepter AWS region | string | - | yes | -| accepter_vpc_id | Accepter VPC ID filter | string | `` | no | -| accepter_vpc_tags | Accepter VPC Tags filter | map | `` | no | -| attributes | Additional attributes (e.g. `a` or `b`) | list | `` | no | -| auto_accept | Automatically accept the peering | string | `true` | no | -| delimiter | Delimiter to be used between `namespace`, `stage`, `name`, and `attributes` | string | `-` | no | -| enabled | Set to false to prevent the module from creating or accessing any resources | string | `true` | no | -| name | Name (e.g. `app` or `cluster`) | string | - | yes | -| namespace | Namespace (e.g. `eg` or `cp`) | string | - | yes | -| requester_allow_remote_vpc_dns_resolution | Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC | string | `true` | no | -| requester_aws_assume_role_arn | Requester AWS Assume Role ARN | string | - | yes | -| requester_region | Requester AWS region | string | - | yes | -| requester_vpc_id | Requester VPC ID filter | string | `` | no | -| requester_vpc_tags | Requester VPC Tags filter | map | `` | no | -| stage | Stage (e.g. `prod`, `dev`, `staging`) | string | - | yes | -| tags | Additional tags (e.g. `{"BusinessUnit" = "XYZ"`) | map | `` | no | - -## Outputs - -| Name | Description | -|------|-------------| -| accepter_accept_status | Accepter VPC peering connection request status | -| accepter_connection_id | Accepter VPC peering connection ID | -| requester_accept_status | Requester VPC peering connection request status | -| requester_connection_id | Requester VPC peering connection ID | - diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars new file mode 100644 index 0000000..7e12171 --- /dev/null +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -0,0 +1,11 @@ +region = "us-east-2" +namespace = "eg" +stage = "test" +name = "vpc_peering_cross_account" +requester_aws_assume_role_arn = "" +requester_region = "us-east-2" +requester_allow_remote_vpc_dns_resolution = true +accepter_aws_assume_role_arn = "" +accepter_region = "us-east-2" +accepter_allow_remote_vpc_dns_resolution = true +availability_zones = ["us-east-2b"] \ No newline at end of file diff --git a/examples/complete/main.tf b/examples/complete/main.tf index c1a939f..a1a1399 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -1,20 +1,20 @@ provider "aws" { - region = "${var.region}" + region = var.region } module "vpc_peering_cross_account" { source = "../../" - namespace = "${var.namespace}" - stage = "${var.stage}" - name = "${var.name}" + namespace = var.namespace + stage = var.stage + name = var.name - requester_aws_assume_role_arn = "${var.requester_aws_assume_role_arn}" - requester_region = "${var.requester_region}" - requester_vpc_id = "${var.requester_vpc_id}" - requester_allow_remote_vpc_dns_resolution = "${var.requester_allow_remote_vpc_dns_resolution}" + requester_aws_assume_role_arn = var.requester_aws_assume_role_arn + requester_region = var.requester_region + requester_vpc_id = var.requester_vpc_id + requester_allow_remote_vpc_dns_resolution = var.requester_allow_remote_vpc_dns_resolution - accepter_aws_assume_role_arn = "${var.accepter_aws_assume_role_arn}" - accepter_region = "${var.accepter_region}" - accepter_vpc_id = "${var.accepter_vpc_id}" - accepter_allow_remote_vpc_dns_resolution = "${var.accepter_allow_remote_vpc_dns_resolution}" + accepter_aws_assume_role_arn = var.accepter_aws_assume_role_arn + accepter_region = var.accepter_region + accepter_vpc_id = var.accepter_vpc_id + accepter_allow_remote_vpc_dns_resolution = var.accepter_allow_remote_vpc_dns_resolution } diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index bda6a06..ddbe8ba 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -1,19 +1,19 @@ output "requester_connection_id" { - value = "${module.vpc_peering_cross_account.requester_connection_id}" + value = module.vpc_peering_cross_account.requester_connection_id description = "Requester VPC peering connection ID" } output "requester_accept_status" { - value = "${module.vpc_peering_cross_account.requester_accept_status}" + value = module.vpc_peering_cross_account.requester_accept_status description = "Requester VPC peering connection request status" } output "accepter_connection_id" { - value = "${module.vpc_peering_cross_account.accepter_connection_id}" + value = module.vpc_peering_cross_account.accepter_connection_id description = "Accepter VPC peering connection ID" } output "accepter_accept_status" { - value = "${module.vpc_peering_cross_account.accepter_accept_status}" + value = module.vpc_peering_cross_account.accepter_accept_status description = "Accepter VPC peering connection request status" } diff --git a/examples/complete/variables.tf b/examples/complete/variables.tf index 2b39058..b5b742c 100644 --- a/examples/complete/variables.tf +++ b/examples/complete/variables.tf @@ -1,67 +1,72 @@ variable "region" { - type = "string" + type = string description = "AWS Region" default = "us-east-1" } variable "namespace" { - type = "string" + type = string description = "Namespace (e.g. `eg` or `cp`)" default = "eg" } variable "stage" { - type = "string" + type = string description = "Stage (e.g. `prod`, `dev`, `staging`)" default = "testing" } variable "name" { - type = "string" + type = string description = "Name of the application" default = "vpc-peering" } variable "requester_aws_assume_role_arn" { - type = "string" + type = string description = "Requester AWS Assume Role ARN" } variable "requester_region" { - type = "string" + type = string description = "Requester AWS region" default = "us-west-2" } variable "requester_vpc_id" { - type = "string" + type = string description = "Requester VPC ID filter" } variable "requester_allow_remote_vpc_dns_resolution" { - type = "string" + type = bool description = "Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC" - default = "true" + default = true } variable "accepter_aws_assume_role_arn" { - type = "string" + type = string description = "Accepter AWS Assume Role ARN" } variable "accepter_region" { - type = "string" + type = string description = "Accepter AWS region" default = "us-east-1" } variable "accepter_vpc_id" { - type = "string" + type = string description = "Accepter VPC ID filter" } variable "accepter_allow_remote_vpc_dns_resolution" { - type = "string" + type = bool description = "Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC" - default = "true" + default = true +} + +variable "availability_zones" { + type = list(string) + description = "Availability zone IDs" } diff --git a/examples/vpc-only/fixtures.us-east-2.tfvars b/examples/vpc-only/fixtures.us-east-2.tfvars new file mode 100644 index 0000000..85f7024 --- /dev/null +++ b/examples/vpc-only/fixtures.us-east-2.tfvars @@ -0,0 +1,5 @@ +region = "us-east-2" +namespace = "eg" +stage = "test" +name = "vpc_peering_cross_account" +availability_zones = ["us-east-2c"] \ No newline at end of file diff --git a/examples/vpc-only/main.tf b/examples/vpc-only/main.tf new file mode 100644 index 0000000..b9054cb --- /dev/null +++ b/examples/vpc-only/main.tf @@ -0,0 +1,45 @@ +provider "aws" { + region = var.region +} + +module "requester_vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + cidr_block = "172.16.0.0/16" +} + +module "requester_subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.18.1" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + vpc_id = module.requester_vpc.vpc_id + igw_id = module.requester_vpc.igw_id + cidr_block = module.requester_vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false +} + +module "accepter_vpc" { + source = "git::https://github.com/cloudposse/terraform-aws-vpc.git?ref=tags/0.8.1" + namespace = var.namespace + stage = var.stage + name = var.name + cidr_block = "172.17.0.0/16" +} + +module "accepter_subnets" { + source = "git::https://github.com/cloudposse/terraform-aws-dynamic-subnets.git?ref=tags/0.18.1" + availability_zones = var.availability_zones + namespace = var.namespace + stage = var.stage + name = var.name + vpc_id = module.accepter_vpc.vpc_id + igw_id = module.accepter_vpc.igw_id + cidr_block = module.accepter_vpc.vpc_cidr_block + nat_gateway_enabled = true + nat_instance_enabled = false +} diff --git a/examples/vpc-only/outputs.tf b/examples/vpc-only/outputs.tf new file mode 100644 index 0000000..77de76b --- /dev/null +++ b/examples/vpc-only/outputs.tf @@ -0,0 +1,9 @@ +output "accepter_vpc_id" { + value = module.accepter_vpc.vpc_id + description = "Accepter VPC id" +} + +output "requester_vpc_id" { + value = module.requester_vpc.vpc_id + description = "Requester VPC id" +} diff --git a/examples/vpc-only/variables.tf b/examples/vpc-only/variables.tf new file mode 100644 index 0000000..191150b --- /dev/null +++ b/examples/vpc-only/variables.tf @@ -0,0 +1,28 @@ +variable "region" { + type = string + description = "AWS Region" + default = "us-east-1" +} + +variable "namespace" { + type = string + description = "Namespace (e.g. `eg` or `cp`)" + default = "eg" +} + +variable "stage" { + type = string + description = "Stage (e.g. `prod`, `dev`, `staging`)" + default = "testing" +} + +variable "name" { + type = string + description = "Name of the application" + default = "vpc-peering" +} + +variable "availability_zones" { + type = list(string) + description = "Availability zone IDs" +} diff --git a/examples/vpc-only/versions.tf b/examples/vpc-only/versions.tf new file mode 100644 index 0000000..029affa --- /dev/null +++ b/examples/vpc-only/versions.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 0.12" + + required_providers { + aws = "~> 2.0" + null = "~> 2.0" + local = "~> 1.2" + template = "~> 2.0" + } +} diff --git a/main.tf b/main.tf index 137d31e..12380ab 100644 --- a/main.tf +++ b/main.tf @@ -1,4 +1,4 @@ locals { - enabled = "${var.enabled == "true"}" - count = "${local.enabled ? 1 : 0}" + count = var.enabled ? 1 : 0 } + diff --git a/outputs.tf b/outputs.tf deleted file mode 100644 index 8b13789..0000000 --- a/outputs.tf +++ /dev/null @@ -1 +0,0 @@ - diff --git a/requester.tf b/requester.tf index efbb29f..a451aff 100644 --- a/requester.tf +++ b/requester.tf @@ -1,141 +1,162 @@ variable "requester_aws_assume_role_arn" { description = "Requester AWS Assume Role ARN" - type = "string" + type = string } variable "requester_region" { - type = "string" + type = string description = "Requester AWS region" } variable "requester_vpc_id" { - type = "string" + type = string description = "Requester VPC ID filter" default = "" } variable "requester_vpc_tags" { - type = "map" + type = map(string) description = "Requester VPC Tags filter" default = {} } variable "requester_allow_remote_vpc_dns_resolution" { - default = "true" + type = bool + default = true description = "Allow requester VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the accepter VPC" } # Requestors's credentials provider "aws" { alias = "requester" - region = "${var.requester_region}" + region = var.requester_region - assume_role { - role_arn = "${var.requester_aws_assume_role_arn}" + dynamic "assume_role" { + for_each = var.requester_aws_assume_role_arn != "" ? ["true"] : [] + content { + role_arn = var.requester_aws_assume_role_arn + } } + } locals { - requester_attributes = "${concat(var.attributes, list("requester"))}" - requester_tags = "${merge(var.tags, map("Side", "requester"))}" + requester_attributes = concat(var.attributes, ["requester"]) + requester_tags = merge( + var.tags, + { + "Side" = "requester" + }, + ) } module "requester" { - source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.3.3" - enabled = "${var.enabled}" - namespace = "${var.namespace}" - name = "${var.name}" - stage = "${var.stage}" - delimiter = "${var.delimiter}" - attributes = "${local.requester_attributes}" - tags = "${local.requester_tags}" + source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=tags/0.16.0" + enabled = var.enabled + namespace = var.namespace + name = var.name + stage = var.stage + delimiter = var.delimiter + attributes = local.requester_attributes + tags = local.requester_tags } data "aws_caller_identity" "requester" { - count = "${local.count}" - provider = "aws.requester" + count = local.count + provider = aws.requester } data "aws_region" "requester" { - count = "${local.count}" - provider = "aws.requester" + count = local.count + provider = aws.requester } # Lookup requester VPC so that we can reference the CIDR data "aws_vpc" "requester" { - count = "${local.count}" - provider = "aws.requester" - id = "${var.requester_vpc_id}" - tags = "${var.requester_vpc_tags}" + count = local.count + provider = aws.requester + id = var.requester_vpc_id + tags = var.requester_vpc_tags } # Lookup requester subnets data "aws_subnet_ids" "requester" { - count = "${local.count}" - provider = "aws.requester" - vpc_id = "${local.requester_vpc_id}" + count = local.count + provider = aws.requester + vpc_id = local.requester_vpc_id } locals { - requester_subnet_ids = "${distinct(sort(flatten(data.aws_subnet_ids.requester.*.ids)))}" - requester_subnet_ids_count = "${length(local.requester_subnet_ids)}" - requester_vpc_id = "${join("", data.aws_vpc.requester.*.id)}" + requester_subnet_ids = distinct(sort(flatten(data.aws_subnet_ids.requester.*.ids))) + requester_subnet_ids_count = length(local.requester_subnet_ids) + requester_vpc_id = join("", data.aws_vpc.requester.*.id) } # Lookup requester route tables data "aws_route_table" "requester" { - count = "${local.enabled ? local.requester_subnet_ids_count : 0}" - provider = "aws.requester" - subnet_id = "${element(local.requester_subnet_ids, count.index)}" + count = var.enabled ? local.requester_subnet_ids_count : 0 + provider = aws.requester + subnet_id = element(local.requester_subnet_ids, count.index) } resource "aws_vpc_peering_connection" "requester" { - count = "${local.count}" - provider = "aws.requester" - vpc_id = "${local.requester_vpc_id}" - peer_vpc_id = "${local.accepter_vpc_id}" - peer_owner_id = "${local.accepter_account_id}" - peer_region = "${local.accepter_region}" + count = local.count + provider = aws.requester + vpc_id = local.requester_vpc_id + peer_vpc_id = local.accepter_vpc_id + peer_owner_id = local.accepter_account_id + peer_region = local.accepter_region auto_accept = false - tags = "${module.requester.tags}" + tags = module.requester.tags +} + +# Options can't be set until the connection has been accepted and is active, +# so create an explicit dependency on the accepter when setting options. +locals { + active_vpc_peering_connection_id = join("", aws_vpc_peering_connection_accepter.accepter.*.id) } resource "aws_vpc_peering_connection_options" "requester" { - provider = "aws.requester" + provider = aws.requester # As options can't be set until the connection has been accepted # create an explicit dependency on the accepter. - vpc_peering_connection_id = "${join("", aws_vpc_peering_connection.requester.*.id)}" + vpc_peering_connection_id = local.active_vpc_peering_connection_id requester { - allow_remote_vpc_dns_resolution = "${var.requester_allow_remote_vpc_dns_resolution}" + allow_remote_vpc_dns_resolution = var.requester_allow_remote_vpc_dns_resolution } } locals { - requester_aws_route_table_ids = "${distinct(sort(data.aws_route_table.requester.*.route_table_id))}" - requester_aws_route_table_ids_count = "${length(local.requester_aws_route_table_ids)}" - requester_cidr_block_associations = "${flatten(data.aws_vpc.requester.*.cidr_block_associations)}" - requester_cidr_block_associations_count = "${length(local.requester_cidr_block_associations)}" + requester_aws_route_table_ids = distinct(sort(data.aws_route_table.requester.*.route_table_id)) + requester_aws_route_table_ids_count = length(local.requester_aws_route_table_ids) + requester_cidr_block_associations = flatten(data.aws_vpc.requester.*.cidr_block_associations) + requester_cidr_block_associations_count = length(local.requester_cidr_block_associations) } # Create routes from requester to accepter resource "aws_route" "requester" { - count = "${local.enabled ? local.requester_aws_route_table_ids_count * local.accepter_cidr_block_associations_count : 0}" - provider = "aws.requester" - route_table_id = "${element(local.requester_aws_route_table_ids, ceil(count.index/local.accepter_cidr_block_associations_count))}" - destination_cidr_block = "${lookup(local.accepter_cidr_block_associations[count.index % local.accepter_cidr_block_associations_count], "cidr_block")}" - vpc_peering_connection_id = "${join("", aws_vpc_peering_connection.requester.*.id)}" - depends_on = ["data.aws_route_table.requester", "aws_vpc_peering_connection.requester", "aws_vpc_peering_connection_accepter.accepter"] + count = var.enabled ? local.requester_aws_route_table_ids_count * local.accepter_cidr_block_associations_count : 0 + provider = aws.requester + route_table_id = local.requester_aws_route_table_ids[ceil(count.index / local.accepter_cidr_block_associations_count)] + destination_cidr_block = local.accepter_cidr_block_associations[count.index % local.accepter_cidr_block_associations_count]["cidr_block"] + vpc_peering_connection_id = join("", aws_vpc_peering_connection.requester.*.id) + depends_on = [ + data.aws_route_table.requester, + aws_vpc_peering_connection.requester, + aws_vpc_peering_connection_accepter.accepter, + ] } output "requester_connection_id" { - value = "${join("", aws_vpc_peering_connection.requester.*.id)}" + value = join("", aws_vpc_peering_connection.requester.*.id) description = "Requester VPC peering connection ID" } output "requester_accept_status" { - value = "${join("", aws_vpc_peering_connection.requester.*.accept_status)}" + value = join("", aws_vpc_peering_connection.requester.*.accept_status) description = "Requester VPC peering connection request status" } + diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..442804a --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.test-harness diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..17b2fe7 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,43 @@ +TEST_HARNESS ?= https://github.com/cloudposse/test-harness.git +TEST_HARNESS_BRANCH ?= master +TEST_HARNESS_PATH = $(realpath .test-harness) +BATS_ARGS ?= --tap +BATS_LOG ?= test.log + +# Define a macro to run the tests +define RUN_TESTS +@echo "Running tests in $(1)" +@cd $(1) && bats $(BATS_ARGS) $(addsuffix .bats,$(addprefix $(TEST_HARNESS_PATH)/test/terraform/,$(TESTS))) +endef + +default: all + +-include Makefile.* + +## Provision the test-harnesss +.test-harness: + [ -d $@ ] || git clone --depth=1 -b $(TEST_HARNESS_BRANCH) $(TEST_HARNESS) $@ + +## Initialize the tests +init: .test-harness + +## Install all dependencies (OS specific) +deps:: + @exit 0 + +## Clean up the test harness +clean: + [ "$(TEST_HARNESS_PATH)" == "/" ] || rm -rf $(TEST_HARNESS_PATH) + +## Run all tests +all: module examples/complete + +## Run basic sanity checks against the module itself +module: export TESTS ?= installed lint get-modules module-pinning get-plugins provider-pinning validate terraform-docs input-descriptions output-descriptions +module: deps + $(call RUN_TESTS, ../) + +## Run tests against example +examples/complete: export TESTS ?= installed lint get-modules get-plugins validate +examples/complete: deps + $(call RUN_TESTS, ../$@) diff --git a/test/Makefile.alpine b/test/Makefile.alpine new file mode 100644 index 0000000..7925b18 --- /dev/null +++ b/test/Makefile.alpine @@ -0,0 +1,5 @@ +ifneq (,$(wildcard /sbin/apk)) +## Install all dependencies for alpine +deps:: init + @apk add --update terraform-docs@cloudposse json2hcl@cloudposse +endif diff --git a/test/src/.gitignore b/test/src/.gitignore new file mode 100644 index 0000000..31b0219 --- /dev/null +++ b/test/src/.gitignore @@ -0,0 +1,2 @@ +.gopath +vendor/ diff --git a/test/src/Gopkg.lock b/test/src/Gopkg.lock new file mode 100644 index 0000000..87bb6bd --- /dev/null +++ b/test/src/Gopkg.lock @@ -0,0 +1,92 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" + name = "github.com/davecgh/go-spew" + packages = ["spew"] + pruneopts = "UT" + revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73" + version = "v1.1.1" + +[[projects]] + digest = "1:75d6042fc66aebc974cc49b0c6c7cc3b9adb5f8130fbfa0dbec0820d990afa25" + name = "github.com/gruntwork-io/terratest" + packages = [ + "modules/collections", + "modules/customerrors", + "modules/files", + "modules/logger", + "modules/retry", + "modules/shell", + "modules/ssh", + "modules/terraform", + ] + pruneopts = "UT" + revision = "892abb2c35878d0808101bbfe6559e931dc2d354" + version = "v0.16.0" + +[[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "UT" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + digest = "1:5da8ce674952566deae4dbc23d07c85caafc6cfa815b0b3e03e41979cedb8750" + name = "github.com/stretchr/testify" + packages = [ + "assert", + "require", + ] + pruneopts = "UT" + revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053" + version = "v1.3.0" + +[[projects]] + branch = "master" + digest = "1:831470c2758c8b733941144f2803a0ccad0632c5a767415b777ebd296b5f463e" + name = "golang.org/x/crypto" + packages = [ + "curve25519", + "ed25519", + "ed25519/internal/edwards25519", + "internal/chacha20", + "internal/subtle", + "poly1305", + "ssh", + "ssh/agent", + ] + pruneopts = "UT" + revision = "22d7a77e9e5f409e934ed268692e56707cd169e5" + +[[projects]] + branch = "master" + digest = "1:76ee51c3f468493aff39dbacc401e8831fbb765104cbf613b89bef01cf4bad70" + name = "golang.org/x/net" + packages = ["context"] + pruneopts = "UT" + revision = "f3200d17e092c607f615320ecaad13d87ad9a2b3" + +[[projects]] + branch = "master" + digest = "1:181f3fd33e620b958b5ab77da177cf775cdcccd7db82963607875fbd09ae995e" + name = "golang.org/x/sys" + packages = [ + "cpu", + "unix", + ] + pruneopts = "UT" + revision = "9cd6430ef91e39e1a0ec0470cf1321a33ef1b887" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + input-imports = [ + "github.com/gruntwork-io/terratest/modules/terraform", + "github.com/stretchr/testify/assert", + ] + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/test/src/Gopkg.toml b/test/src/Gopkg.toml new file mode 100644 index 0000000..995bac5 --- /dev/null +++ b/test/src/Gopkg.toml @@ -0,0 +1,7 @@ +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.2.2" + +[prune] + go-tests = true + unused-packages = true diff --git a/test/src/Makefile b/test/src/Makefile new file mode 100644 index 0000000..151f01b --- /dev/null +++ b/test/src/Makefile @@ -0,0 +1,50 @@ +PACKAGE = terraform-aws-vpc-peering-multi-account +GOEXE ?= /usr/bin/go +GOPATH = $(CURDIR)/.gopath +GOBIN = $(GOPATH)/bin +BASE = $(GOPATH)/src/$(PACKAGE) +PATH := $(PATH):$(GOBIN) + +export TF_DATA_DIR ?= $(CURDIR)/.terraform +export TF_CLI_ARGS_init ?= -get-plugins=true +export GOPATH + +.PHONY: all +## Default target +all: test + +ifneq (,$(wildcard /sbin/apk)) +## Install go, if not installed +$(GOEXE): + apk add --update go +endif + +ifeq ($(shell uname -s),Linux) +## Install all `dep`, if not installed +$(GOBIN)/dep: + @mkdir -p $(GOBIN) + @curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh +endif + +## Prepare the GOPATH +$(BASE): $(GOEXE) + @mkdir -p $(dir $@) + @ln -sf $(CURDIR) $@ + +## Download vendor dependencies to vendor/ +$(BASE)/vendor: $(BASE) $(GOBIN)/dep + cd $(BASE) && dep ensure + +.PHONY : init +## Initialize tests +init: $(BASE)/vendor + +.PHONY : test +## Run tests +test: init + cd $(BASE) && go test -v -timeout 30m -run TestExamplesComplete + +.PHONY : clean +## Clean up files +clean: + rm -rf .gopath/ vendor/ $(TF_DATA_DIR) diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go new file mode 100644 index 0000000..40cc0b1 --- /dev/null +++ b/test/src/examples_complete_test.go @@ -0,0 +1,69 @@ +package test + +import ( + "testing" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/assert" +) + +// Test the Terraform module in examples/complete using Terratest. +func TestExamplesComplete(t *testing.T) { + terraformVpcOnlyOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/vpc-only", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.us-east-2.tfvars"}, + Targets: []string{"module.requester_vpc", "module.requester_subnets", "module.accepter_vpc", "module.accepter_subnets"}, + } + + defer func() { + terraform.Init(t, terraformVpcOnlyOptions) + terraform.Destroy(t, terraformVpcOnlyOptions) + }() + + // This will run `terraform init` and `terraform apply` to create VPCs and subnets, required for the test + terraform.InitAndApply(t, terraformVpcOnlyOptions) + requesterVpcId := terraform.Output(t, terraformVpcOnlyOptions, "requester_vpc_id") + acceptorVpcId := terraform.Output(t, terraformVpcOnlyOptions, "accepter_vpc_id") + + terraformOptions := &terraform.Options{ + // The path to where our Terraform code is located + TerraformDir: "../../examples/complete", + Upgrade: true, + // Variables to pass to our Terraform code using -var-file options + VarFiles: []string{"fixtures.us-east-2.tfvars"}, + Vars: map[string]interface{}{ + "requester_vpc_id": requesterVpcId, + "accepter_vpc_id": acceptorVpcId, + }, + } + + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + println(terraform.OutputAll(t, terraformOptions)) + + // Run `terraform output` to get the value of an output variable + requesterConnectionId := terraform.Output(t, terraformOptions, "requester_connection_id") + // Verify we're getting back the outputs we expect + assert.Contains(t, requesterConnectionId, "pcx-") + + // Run `terraform output` to get the value of an output variable + acceptorConnectionId := terraform.Output(t, terraformOptions, "accepter_connection_id") + // Verify we're getting back the outputs we expect + assert.Contains(t, acceptorConnectionId, "pcx-") + + // Run `terraform output` to get the value of an output variable + acceptorAcceptStatus := terraform.Output(t, terraformOptions, "accepter_accept_status") + // Verify we're getting back the outputs we expect + assert.Equal(t, "active", acceptorAcceptStatus) + + // Run `terraform output` to get the value of an output variable + requesterAcceptStatus := terraform.Output(t, terraformOptions, "requester_accept_status") + // Verify we're getting back the outputs we expect + assert.Equal(t, "pending-acceptance", requesterAcceptStatus) +} diff --git a/variables.tf b/variables.tf index 07d0df3..ef128a3 100644 --- a/variables.tf +++ b/variables.tf @@ -1,42 +1,72 @@ variable "enabled" { - default = "true" + type = bool + default = true description = "Set to false to prevent the module from creating or accessing any resources" } variable "namespace" { description = "Namespace (e.g. `eg` or `cp`)" - type = "string" + type = string } variable "stage" { description = "Stage (e.g. `prod`, `dev`, `staging`)" - type = "string" + type = string } variable "name" { description = "Name (e.g. `app` or `cluster`)" - type = "string" + type = string } variable "delimiter" { - type = "string" + type = string default = "-" description = "Delimiter to be used between `namespace`, `stage`, `name`, and `attributes`" } variable "attributes" { - type = "list" + type = list(string) default = [] description = "Additional attributes (e.g. `a` or `b`)" } variable "tags" { - type = "map" + type = map(string) default = {} description = "Additional tags (e.g. `{\"BusinessUnit\" = \"XYZ\"`)" } variable "auto_accept" { - default = "true" + type = bool + default = true description = "Automatically accept the peering" } + +variable "accepter_aws_assume_role_arn" { + description = "Accepter AWS Assume Role ARN" + type = string +} + +variable "accepter_region" { + type = string + description = "Accepter AWS region" +} + +variable "accepter_vpc_id" { + type = string + description = "Accepter VPC ID filter" + default = "" +} + +variable "accepter_vpc_tags" { + type = map(string) + description = "Accepter VPC Tags filter" + default = {} +} + +variable "accepter_allow_remote_vpc_dns_resolution" { + type = bool + default = true + description = "Allow accepter VPC to resolve public DNS hostnames to private IP addresses when queried from instances in the requester VPC" +} \ No newline at end of file diff --git a/versions.tf b/versions.tf new file mode 100644 index 0000000..f8750ad --- /dev/null +++ b/versions.tf @@ -0,0 +1,8 @@ +terraform { + required_version = ">= 0.12" + + required_providers { + aws = "~> 2.0" + null = "~> 2.0" + } +}