diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 2537f2f..6f64b5a 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -15,8 +15,8 @@ # Cloud Posse must review any changes to standard context definition, # but some changes can be rubber-stamped. -**/*.tf @cloudposse/engineering @cloudposse/approvers -README.yaml @cloudposse/engineering @cloudposse/approvers +**/*.tf @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers +README.yaml @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers README.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers docs/*.md @cloudposse/engineering @cloudposse/contributors @cloudposse/approvers diff --git a/.github/auto-release.yml b/.github/auto-release.yml index c78a4d8..39a7f1e 100644 --- a/.github/auto-release.yml +++ b/.github/auto-release.yml @@ -46,7 +46,7 @@ template: | replacers: # Remove irrelevant information from Renovate bot -- search: '/---\s+^#.*Renovate configuration(?:.|\n)*?This PR has been generated .*/gm' +- search: '/(?<=---\s+)+^#.*(Renovate configuration|Configuration)(?:.|\n)*?This PR has been generated .*/gm' replace: '' # Remove Renovate bot banner image - search: '/\[!\[[^\]]*Renovate\][^\]]*\](\([^)]*\))?\s*\n+/gm' diff --git a/.github/mergify.yml b/.github/mergify.yml index b010656..ef15545 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -56,3 +56,10 @@ pull_request_rules: changes_requested: true approved: true message: "This Pull Request has been updated, so we're dismissing all reviews." + +- name: "close Pull Requests without files changed" + conditions: + - "#files=0" + actions: + close: + message: "This pull request has been automatically closed by Mergify because there are no longer any changes." diff --git a/.github/workflows/auto-format.yml b/.github/workflows/auto-format.yml index 990abed..375d0fd 100644 --- a/.github/workflows/auto-format.yml +++ b/.github/workflows/auto-format.yml @@ -6,7 +6,7 @@ on: jobs: auto-format: runs-on: ubuntu-latest - container: cloudposse/build-harness:slim-latest + container: cloudposse/build-harness:latest steps: # Checkout the pull request branch # "An action in a workflow run can’t trigger a new workflow run. For example, if an action pushes code using @@ -29,6 +29,8 @@ jobs: - name: Auto Format if: github.event.pull_request.state == 'open' shell: bash + env: + GITHUB_TOKEN: "${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }}" run: make BUILD_HARNESS_PATH=/build-harness PACKAGES_PREFER_HOST=true -f /build-harness/templates/Makefile.build-harness pr/auto-format/host # Commit changes (if any) to the PR branch diff --git a/.github/workflows/auto-release.yml b/.github/workflows/auto-release.yml index 3f48017..1d06d9b 100644 --- a/.github/workflows/auto-release.yml +++ b/.github/workflows/auto-release.yml @@ -3,17 +3,25 @@ name: auto-release on: push: branches: - - master + - main + - master + - production jobs: publish: runs-on: ubuntu-latest steps: - # Drafts your next Release notes as Pull Requests are merged into "master" - - uses: release-drafter/release-drafter@v5 - with: - publish: true - prerelease: false - config-name: auto-release.yml - env: - GITHUB_TOKEN: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + # Get PR from merged commit to master + - uses: actions-ecosystem/action-get-merged-pull-request@v1 + id: get-merged-pull-request + with: + github_token: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} + # Drafts your next Release notes as Pull Requests are merged into "main" + - uses: release-drafter/release-drafter@v5 + if: "!contains(steps.get-merged-pull-request.outputs.labels, 'no-release')" + with: + publish: true + prerelease: false + config-name: auto-release.yml + env: + GITHUB_TOKEN: ${{ secrets.PUBLIC_REPO_ACCESS_TOKEN }} diff --git a/.github/workflows/validate-codeowners.yml b/.github/workflows/validate-codeowners.yml index 386eb28..c5193b6 100644 --- a/.github/workflows/validate-codeowners.yml +++ b/.github/workflows/validate-codeowners.yml @@ -1,5 +1,7 @@ name: Validate Codeowners on: + workflow_dispatch: + pull_request: jobs: diff --git a/README.md b/README.md index 7c91942..ffa9a59 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ + # terraform-aws-multi-az-subnets [![Latest Release](https://img.shields.io/github/release/cloudposse/terraform-aws-multi-az-subnets.svg)](https://github.com/cloudposse/terraform-aws-multi-az-subnets/releases/latest) [![Slack Community](https://slack.cloudposse.com/badge.svg)](https://slack.cloudposse.com) @@ -39,7 +40,6 @@ The private subnets are routed to the NAT Gateways provided in the `var.az_ngw_i If you are creating subnets inside a VPC, consider using [cloudposse/terraform-aws-dynamic-subnets](https://github.com/cloudposse/terraform-aws-dynamic-subnets) instead. - --- This project is part of our comprehensive ["SweetOps"](https://cpco.io/sweetops) approach towards DevOps. @@ -67,8 +67,6 @@ We literally have [*hundreds of terraform modules*][terraform_modules] that are - - ## Screenshots @@ -267,61 +265,85 @@ Available targets: | Name | Version | |------|---------| -| terraform | >= 0.13.0 | -| aws | >= 2.0 | -| local | >= 1.2 | -| null | >= 2.0 | -| template | >= 2.0 | +| [terraform](#requirement\_terraform) | >= 0.13.0 | +| [aws](#requirement\_aws) | >= 3.0 | +| [local](#requirement\_local) | >= 1.2 | +| [null](#requirement\_null) | >= 2.0 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.0 | +| [aws](#provider\_aws) | >= 3.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [private\_label](#module\_private\_label) | cloudposse/label/null | 0.24.1 | +| [public\_label](#module\_public\_label) | cloudposse/label/null | 0.24.1 | +| [this](#module\_this) | cloudposse/label/null | 0.24.1 | + +## Resources + +| Name | Type | +|------|------| +| [aws_eip.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | +| [aws_nat_gateway.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource | +| [aws_network_acl.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource | +| [aws_network_acl.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource | +| [aws_route.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_route.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_route_table.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table_association.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| availability\_zones | List of Availability Zones (e.g. `['us-east-1a', 'us-east-1b', 'us-east-1c']`) | `list(string)` | n/a | yes | -| az\_ngw\_ids | Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets | `map(string)` | `{}` | no | -| cidr\_block | Base CIDR block which is divided into subnet CIDR blocks (e.g. `10.0.0.0/16`) | `string` | n/a | yes | -| context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | -| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | -| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | -| environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | -| igw\_id | Internet Gateway ID that is used as a default route when creating public subnets (e.g. `igw-9c26a123`) | `string` | `""` | no | -| label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | -| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | -| label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | -| max\_subnets | Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation | `string` | `"6"` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | -| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| nat\_gateway\_enabled | Flag to enable/disable NAT Gateways creation in public subnets | `string` | `"true"` | no | -| private\_network\_acl\_egress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| private\_network\_acl\_id | Network ACL ID that is added to the private subnets. If empty, a new ACL will be created | `string` | `""` | no | -| private\_network\_acl\_ingress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| public\_network\_acl\_egress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| public\_network\_acl\_id | Network ACL ID that is added to the public subnets. If empty, a new ACL will be created | `string` | `""` | no | -| public\_network\_acl\_ingress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | -| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | -| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| type | Type of subnets to create (`private` or `public`) | `string` | `"private"` | no | -| vpc\_id | VPC ID | `string` | n/a | yes | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | +| [attributes](#input\_attributes) | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | +| [availability\_zones](#input\_availability\_zones) | List of Availability Zones (e.g. `['us-east-1a', 'us-east-1b', 'us-east-1c']`) | `list(string)` | n/a | yes | +| [az\_ngw\_ids](#input\_az\_ngw\_ids) | Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets | `map(string)` | `{}` | no | +| [cidr\_block](#input\_cidr\_block) | Base CIDR block which is divided into subnet CIDR blocks (e.g. `10.0.0.0/16`) | `string` | n/a | yes | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| [delimiter](#input\_delimiter) | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [igw\_id](#input\_igw\_id) | Internet Gateway ID that is used as a default route when creating public subnets (e.g. `igw-9c26a123`) | `string` | `""` | no | +| [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | +| [max\_subnets](#input\_max\_subnets) | Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation | `string` | `"6"` | no | +| [name](#input\_name) | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| [namespace](#input\_namespace) | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | +| [nat\_gateway\_enabled](#input\_nat\_gateway\_enabled) | Flag to enable/disable NAT Gateways creation in public subnets | `string` | `"true"` | no | +| [private\_network\_acl\_egress](#input\_private\_network\_acl\_egress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [private\_network\_acl\_id](#input\_private\_network\_acl\_id) | Network ACL ID that is added to the private subnets. If empty, a new ACL will be created | `string` | `""` | no | +| [private\_network\_acl\_ingress](#input\_private\_network\_acl\_ingress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [public\_network\_acl\_egress](#input\_public\_network\_acl\_egress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [public\_network\_acl\_id](#input\_public\_network\_acl\_id) | Network ACL ID that is added to the public subnets. If empty, a new ACL will be created | `string` | `""` | no | +| [public\_network\_acl\_ingress](#input\_public\_network\_acl\_ingress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| [type](#input\_type) | Type of subnets to create (`private` or `public`) | `string` | `"private"` | no | +| [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| az\_ngw\_ids | Map of AZ names to NAT Gateway IDs (only for public subnets) | -| az\_route\_table\_ids | Map of AZ names to Route Table IDs | -| az\_subnet\_arns | Map of AZ names to subnet ARNs | -| az\_subnet\_ids | Map of AZ names to subnet IDs | - +| [az\_ngw\_ids](#output\_az\_ngw\_ids) | Map of AZ names to NAT Gateway IDs (only for public subnets) | +| [az\_route\_table\_ids](#output\_az\_route\_table\_ids) | Map of AZ names to Route Table IDs | +| [az\_subnet\_arns](#output\_az\_subnet\_arns) | Map of AZ names to subnet ARNs | +| [az\_subnet\_ids](#output\_az\_subnet\_ids) | Map of AZ names to subnet IDs | +| [az\_subnet\_map](#output\_az\_subnet\_map) | Map of AZ names to map of information about subnets | diff --git a/docs/terraform.md b/docs/terraform.md index b2e8460..14592b5 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -3,59 +3,83 @@ | Name | Version | |------|---------| -| terraform | >= 0.13.0 | -| aws | >= 2.0 | -| local | >= 1.2 | -| null | >= 2.0 | -| template | >= 2.0 | +| [terraform](#requirement\_terraform) | >= 0.13.0 | +| [aws](#requirement\_aws) | >= 3.0 | +| [local](#requirement\_local) | >= 1.2 | +| [null](#requirement\_null) | >= 2.0 | ## Providers | Name | Version | |------|---------| -| aws | >= 2.0 | +| [aws](#provider\_aws) | >= 3.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [private\_label](#module\_private\_label) | cloudposse/label/null | 0.24.1 | +| [public\_label](#module\_public\_label) | cloudposse/label/null | 0.24.1 | +| [this](#module\_this) | cloudposse/label/null | 0.24.1 | + +## Resources + +| Name | Type | +|------|------| +| [aws_eip.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eip) | resource | +| [aws_nat_gateway.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/nat_gateway) | resource | +| [aws_network_acl.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource | +| [aws_network_acl.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/network_acl) | resource | +| [aws_route.default](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_route.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_route_table.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table) | resource | +| [aws_route_table_association.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_route_table_association.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route_table_association) | resource | +| [aws_subnet.private](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_subnet.public](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| additional\_tag\_map | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | -| attributes | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | -| availability\_zones | List of Availability Zones (e.g. `['us-east-1a', 'us-east-1b', 'us-east-1c']`) | `list(string)` | n/a | yes | -| az\_ngw\_ids | Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets | `map(string)` | `{}` | no | -| cidr\_block | Base CIDR block which is divided into subnet CIDR blocks (e.g. `10.0.0.0/16`) | `string` | n/a | yes | -| context | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | -| delimiter | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | -| enabled | Set to false to prevent the module from creating any resources | `bool` | `null` | no | -| environment | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | -| id\_length\_limit | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | -| igw\_id | Internet Gateway ID that is used as a default route when creating public subnets (e.g. `igw-9c26a123`) | `string` | `""` | no | -| label\_key\_case | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | -| label\_order | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | -| label\_value\_case | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | -| max\_subnets | Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation | `string` | `"6"` | no | -| name | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | -| namespace | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | -| nat\_gateway\_enabled | Flag to enable/disable NAT Gateways creation in public subnets | `string` | `"true"` | no | -| private\_network\_acl\_egress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| private\_network\_acl\_id | Network ACL ID that is added to the private subnets. If empty, a new ACL will be created | `string` | `""` | no | -| private\_network\_acl\_ingress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| public\_network\_acl\_egress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| public\_network\_acl\_id | Network ACL ID that is added to the public subnets. If empty, a new ACL will be created | `string` | `""` | no | -| public\_network\_acl\_ingress | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | -| regex\_replace\_chars | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | -| stage | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | -| tags | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | -| type | Type of subnets to create (`private` or `public`) | `string` | `"private"` | no | -| vpc\_id | VPC ID | `string` | n/a | yes | +| [additional\_tag\_map](#input\_additional\_tag\_map) | Additional tags for appending to tags\_as\_list\_of\_maps. Not added to `tags`. | `map(string)` | `{}` | no | +| [attributes](#input\_attributes) | Additional attributes (e.g. `1`) | `list(string)` | `[]` | no | +| [availability\_zones](#input\_availability\_zones) | List of Availability Zones (e.g. `['us-east-1a', 'us-east-1b', 'us-east-1c']`) | `list(string)` | n/a | yes | +| [az\_ngw\_ids](#input\_az\_ngw\_ids) | Only for private subnets. Map of AZ names to NAT Gateway IDs that are used as default routes when creating private subnets | `map(string)` | `{}` | no | +| [cidr\_block](#input\_cidr\_block) | Base CIDR block which is divided into subnet CIDR blocks (e.g. `10.0.0.0/16`) | `string` | n/a | yes | +| [context](#input\_context) | Single object for setting entire context at once.
See description of individual variables for details.
Leave string and numeric variables as `null` to use default value.
Individual variable settings (non-null) override settings in context object,
except for attributes, tags, and additional\_tag\_map, which are merged. | `any` |
{
"additional_tag_map": {},
"attributes": [],
"delimiter": null,
"enabled": true,
"environment": null,
"id_length_limit": null,
"label_key_case": null,
"label_order": [],
"label_value_case": null,
"name": null,
"namespace": null,
"regex_replace_chars": null,
"stage": null,
"tags": {}
}
| no | +| [delimiter](#input\_delimiter) | Delimiter to be used between `namespace`, `environment`, `stage`, `name` and `attributes`.
Defaults to `-` (hyphen). Set to `""` to use no delimiter at all. | `string` | `null` | no | +| [enabled](#input\_enabled) | Set to false to prevent the module from creating any resources | `bool` | `null` | no | +| [environment](#input\_environment) | Environment, e.g. 'uw2', 'us-west-2', OR 'prod', 'staging', 'dev', 'UAT' | `string` | `null` | no | +| [id\_length\_limit](#input\_id\_length\_limit) | Limit `id` to this many characters (minimum 6).
Set to `0` for unlimited length.
Set to `null` for default, which is `0`.
Does not affect `id_full`. | `number` | `null` | no | +| [igw\_id](#input\_igw\_id) | Internet Gateway ID that is used as a default route when creating public subnets (e.g. `igw-9c26a123`) | `string` | `""` | no | +| [label\_key\_case](#input\_label\_key\_case) | The letter case of label keys (`tag` names) (i.e. `name`, `namespace`, `environment`, `stage`, `attributes`) to use in `tags`.
Possible values: `lower`, `title`, `upper`.
Default value: `title`. | `string` | `null` | no | +| [label\_order](#input\_label\_order) | The naming order of the id output and Name tag.
Defaults to ["namespace", "environment", "stage", "name", "attributes"].
You can omit any of the 5 elements, but at least one must be present. | `list(string)` | `null` | no | +| [label\_value\_case](#input\_label\_value\_case) | The letter case of output label values (also used in `tags` and `id`).
Possible values: `lower`, `title`, `upper` and `none` (no transformation).
Default value: `lower`. | `string` | `null` | no | +| [max\_subnets](#input\_max\_subnets) | Maximum number of subnets that can be created. The variable is used for CIDR blocks calculation | `string` | `"6"` | no | +| [name](#input\_name) | Solution name, e.g. 'app' or 'jenkins' | `string` | `null` | no | +| [namespace](#input\_namespace) | Namespace, which could be your organization name or abbreviation, e.g. 'eg' or 'cp' | `string` | `null` | no | +| [nat\_gateway\_enabled](#input\_nat\_gateway\_enabled) | Flag to enable/disable NAT Gateways creation in public subnets | `string` | `"true"` | no | +| [private\_network\_acl\_egress](#input\_private\_network\_acl\_egress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [private\_network\_acl\_id](#input\_private\_network\_acl\_id) | Network ACL ID that is added to the private subnets. If empty, a new ACL will be created | `string` | `""` | no | +| [private\_network\_acl\_ingress](#input\_private\_network\_acl\_ingress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [public\_network\_acl\_egress](#input\_public\_network\_acl\_egress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [public\_network\_acl\_id](#input\_public\_network\_acl\_id) | Network ACL ID that is added to the public subnets. If empty, a new ACL will be created | `string` | `""` | no | +| [public\_network\_acl\_ingress](#input\_public\_network\_acl\_ingress) | Egress network ACL rules | `list(map(string))` |
[
{
"action": "allow",
"cidr_block": "0.0.0.0/0",
"from_port": 0,
"protocol": "-1",
"rule_no": 100,
"to_port": 0
}
]
| no | +| [regex\_replace\_chars](#input\_regex\_replace\_chars) | Regex to replace chars with empty string in `namespace`, `environment`, `stage` and `name`.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | +| [stage](#input\_stage) | Stage, e.g. 'prod', 'staging', 'dev', OR 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | +| [tags](#input\_tags) | Additional tags (e.g. `map('BusinessUnit','XYZ')` | `map(string)` | `{}` | no | +| [type](#input\_type) | Type of subnets to create (`private` or `public`) | `string` | `"private"` | no | +| [vpc\_id](#input\_vpc\_id) | VPC ID | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| -| az\_ngw\_ids | Map of AZ names to NAT Gateway IDs (only for public subnets) | -| az\_route\_table\_ids | Map of AZ names to Route Table IDs | -| az\_subnet\_arns | Map of AZ names to subnet ARNs | -| az\_subnet\_ids | Map of AZ names to subnet IDs | - +| [az\_ngw\_ids](#output\_az\_ngw\_ids) | Map of AZ names to NAT Gateway IDs (only for public subnets) | +| [az\_route\_table\_ids](#output\_az\_route\_table\_ids) | Map of AZ names to Route Table IDs | +| [az\_subnet\_arns](#output\_az\_subnet\_arns) | Map of AZ names to subnet ARNs | +| [az\_subnet\_ids](#output\_az\_subnet\_ids) | Map of AZ names to subnet IDs | +| [az\_subnet\_map](#output\_az\_subnet\_map) | Map of AZ names to map of information about subnets | diff --git a/examples/complete/fixtures.disabled.tfvars b/examples/complete/fixtures.disabled.tfvars new file mode 100644 index 0000000..8ea7991 --- /dev/null +++ b/examples/complete/fixtures.disabled.tfvars @@ -0,0 +1 @@ +enabled = false \ No newline at end of file diff --git a/examples/complete/fixtures.enabled.tfvars b/examples/complete/fixtures.enabled.tfvars new file mode 100644 index 0000000..3477e9e --- /dev/null +++ b/examples/complete/fixtures.enabled.tfvars @@ -0,0 +1 @@ +enabled = true \ No newline at end of file diff --git a/examples/complete/fixtures.us-east-2.tfvars b/examples/complete/fixtures.us-east-2.tfvars index 78a0443..c5823f0 100644 --- a/examples/complete/fixtures.us-east-2.tfvars +++ b/examples/complete/fixtures.us-east-2.tfvars @@ -4,7 +4,7 @@ namespace = "eg" stage = "test" -name = "multi-az-subnets-only-private" +name = "multi-az-subnets" availability_zones = ["us-east-2a", "us-east-2b", "us-east-2c"] diff --git a/examples/complete/main.tf b/examples/complete/main.tf index c5037bc..2b8055a 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -9,7 +9,7 @@ locals { module "vpc" { source = "cloudposse/vpc/aws" - version = "0.18.1" + version = "0.21.1" cidr_block = var.cidr_block @@ -19,6 +19,7 @@ module "vpc" { module "public_subnets" { source = "../../" + enabled = var.enabled availability_zones = var.availability_zones vpc_id = module.vpc.vpc_id cidr_block = local.public_cidr_block @@ -32,6 +33,7 @@ module "public_subnets" { module "private_subnets" { source = "../../" + enabled = var.enabled availability_zones = var.availability_zones vpc_id = module.vpc.vpc_id cidr_block = local.private_cidr_block diff --git a/examples/complete/outputs.tf b/examples/complete/outputs.tf index 5bebf83..10b6e3f 100644 --- a/examples/complete/outputs.tf +++ b/examples/complete/outputs.tf @@ -6,6 +6,14 @@ output "public_az_subnet_ids" { value = module.public_subnets.az_subnet_ids } +output "private_az_subnet_arns" { + value = module.private_subnets.az_subnet_arns +} + +output "public_az_subnet_arns" { + value = module.public_subnets.az_subnet_arns +} + output "private_az_ngw_ids" { value = module.private_subnets.az_ngw_ids } diff --git a/main.tf b/main.tf index 8707ce4..2a0dd20 100644 --- a/main.tf +++ b/main.tf @@ -1,4 +1,15 @@ locals { - public_enabled = module.this.enabled && var.type == "public" - private_enabled = module.this.enabled && var.type == "private" + enabled = module.this.enabled + + public_enabled = local.enabled && var.type == "public" + private_enabled = local.enabled && var.type == "private" + availability_zones = local.enabled ? var.availability_zones : [] + + output_map = { for az in(local.enabled ? var.availability_zones : []) : az => { + subnet_id = local.public_enabled ? aws_subnet.public[az].id : aws_subnet.private[az].id + subnet_arn = local.public_enabled ? aws_subnet.public[az].arn : aws_subnet.private[az].arn + route_table_id = local.public_enabled ? aws_route_table.public[az].id : aws_route_table.private[az].id + ngw_id = local.public_enabled ? aws_nat_gateway.public[az].id : null + } + } } diff --git a/outputs.tf b/outputs.tf index 29ad773..8101ad6 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,32 +1,25 @@ output "az_subnet_ids" { - value = zipmap( - var.availability_zones, - coalescelist(aws_subnet.private.*.id, aws_subnet.public.*.id), - ) + value = { for az, m in local.output_map : az => m.subnet_id } description = "Map of AZ names to subnet IDs" } +output "az_subnet_arns" { + value = { for az, m in local.output_map : az => m.subnet_arn } + description = "Map of AZ names to subnet ARNs" +} + output "az_route_table_ids" { - value = zipmap( - var.availability_zones, - coalescelist(aws_route_table.private.*.id, aws_route_table.public.*.id), - ) + value = { for az, m in local.output_map : az => m.route_table_id } description = " Map of AZ names to Route Table IDs" } output "az_ngw_ids" { - value = zipmap( - var.availability_zones, - coalescelist(aws_nat_gateway.public.*.id, local.dummy_az_ngw_ids), - ) + # No ellipsis needed since this module makes either public or private subnets. See the TF 0.15 one function + value = { for az, m in local.output_map : az => m.ngw_id } description = "Map of AZ names to NAT Gateway IDs (only for public subnets)" } -output "az_subnet_arns" { - value = zipmap( - var.availability_zones, - coalescelist(aws_subnet.private.*.arn, aws_subnet.public.*.arn), - ) - description = "Map of AZ names to subnet ARNs" -} - +output "az_subnet_map" { + value = local.output_map + description = "Map of AZ names to map of information about subnets" +} \ No newline at end of file diff --git a/private.tf b/private.tf index c779665..a7dd91a 100644 --- a/private.tf +++ b/private.tf @@ -1,29 +1,27 @@ locals { - private_count = local.private_enabled ? length(var.availability_zones) : 0 - private_route_count = length(var.az_ngw_ids) + private_azs = local.private_enabled ? { for idx, az in var.availability_zones : az => idx } : {} } module "private_label" { source = "cloudposse/label/null" - version = "0.22.1" + version = "0.24.1" - attributes = compact(concat(var.attributes, ["private"])) + attributes = ["private"] context = module.this.context } resource "aws_subnet" "private" { - count = local.private_count + for_each = local.private_azs vpc_id = var.vpc_id - availability_zone = var.availability_zones[count.index] - cidr_block = cidrsubnet(var.cidr_block, ceil(log(var.max_subnets, 2)), count.index) + availability_zone = each.key + cidr_block = cidrsubnet(var.cidr_block, ceil(log(var.max_subnets, 2)), each.value) tags = merge( module.private_label.tags, { - "Name" = "${module.private_label.id}${module.this.delimiter}${element(var.availability_zones, count.index)}" - "AZ" = var.availability_zones[count.index] + "Name" = "${module.private_label.id}${module.this.delimiter}${each.key}" "Type" = var.type }, ) @@ -33,7 +31,7 @@ resource "aws_network_acl" "private" { count = local.private_enabled && var.private_network_acl_id == "" ? 1 : 0 vpc_id = var.vpc_id - subnet_ids = aws_subnet.private.*.id + subnet_ids = values(aws_subnet.private)[*].id dynamic "egress" { for_each = var.private_network_acl_egress content { @@ -67,25 +65,24 @@ resource "aws_network_acl" "private" { } resource "aws_route_table" "private" { - count = local.private_count + for_each = local.private_azs vpc_id = var.vpc_id tags = merge( module.private_label.tags, { - "Name" = "${module.private_label.id}${module.this.delimiter}${element(var.availability_zones, count.index)}" - "AZ" = element(var.availability_zones, count.index) + "Name" = "${module.private_label.id}${module.this.delimiter}${each.key}" "Type" = var.type }, ) } resource "aws_route_table_association" "private" { - count = local.private_count + for_each = local.private_azs - subnet_id = element(aws_subnet.private.*.id, count.index) - route_table_id = element(aws_route_table.private.*.id, count.index) + subnet_id = aws_subnet.private[each.key].id + route_table_id = aws_route_table.private[each.key].id depends_on = [ aws_subnet.private, aws_route_table.private, @@ -93,17 +90,10 @@ resource "aws_route_table_association" "private" { } resource "aws_route" "default" { - count = local.private_route_count + for_each = local.private_azs - route_table_id = zipmap( - var.availability_zones, - matchkeys( - aws_route_table.private.*.id, - aws_route_table.private.*.tags.AZ, - var.availability_zones, - ), - )[element(keys(var.az_ngw_ids), count.index)] - nat_gateway_id = var.az_ngw_ids[element(keys(var.az_ngw_ids), count.index)] + route_table_id = aws_route_table.private[each.key].id + nat_gateway_id = var.az_ngw_ids[each.key] destination_cidr_block = "0.0.0.0/0" depends_on = [aws_route_table.private] } diff --git a/public.tf b/public.tf index 69f2f13..8a62383 100644 --- a/public.tf +++ b/public.tf @@ -1,29 +1,28 @@ locals { - public_count = local.public_enabled ? length(var.availability_zones) : 0 - public_nat_gateways_count = local.public_enabled && var.nat_gateway_enabled ? length(var.availability_zones) : 0 + public_azs = local.public_enabled ? { for idx, az in var.availability_zones : az => idx } : {} + public_nat_gateway_azs = local.public_enabled && var.nat_gateway_enabled ? local.public_azs : {} } module "public_label" { source = "cloudposse/label/null" - version = "0.22.1" + version = "0.24.1" - attributes = compact(concat(var.attributes, ["public"])) + attributes = ["public"] context = module.this.context } resource "aws_subnet" "public" { - count = local.public_count + for_each = local.public_azs vpc_id = var.vpc_id - availability_zone = element(var.availability_zones, count.index) - cidr_block = cidrsubnet(var.cidr_block, ceil(log(var.max_subnets, 2)), count.index) + availability_zone = each.key + cidr_block = cidrsubnet(var.cidr_block, ceil(log(var.max_subnets, 2)), each.value) tags = merge( module.public_label.tags, { - "Name" = "${module.public_label.id}${module.this.delimiter}${element(var.availability_zones, count.index)}" - "AZ" = element(var.availability_zones, count.index) + "Name" = "${module.public_label.id}${module.this.delimiter}${each.key}" "Type" = var.type }, ) @@ -33,7 +32,8 @@ resource "aws_network_acl" "public" { count = local.public_enabled && var.public_network_acl_id == "" ? 1 : 0 vpc_id = var.vpc_id - subnet_ids = aws_subnet.public.*.id + subnet_ids = values(aws_subnet.public)[*].id + dynamic "egress" { for_each = var.public_network_acl_egress content { @@ -67,31 +67,32 @@ resource "aws_network_acl" "public" { } resource "aws_route_table" "public" { - count = local.public_count - vpc_id = var.vpc_id + for_each = local.public_azs + vpc_id = var.vpc_id tags = merge( module.public_label.tags, { - "Name" = "${module.public_label.id}${module.this.delimiter}${element(var.availability_zones, count.index)}" - "AZ" = element(var.availability_zones, count.index) + "Name" = "${module.public_label.id}${module.this.delimiter}${each.key}" "Type" = var.type }, ) } resource "aws_route" "public" { - count = local.public_count - route_table_id = element(aws_route_table.public.*.id, count.index) + for_each = local.public_azs + + route_table_id = aws_route_table.public[each.key].id gateway_id = var.igw_id destination_cidr_block = "0.0.0.0/0" depends_on = [aws_route_table.public] } resource "aws_route_table_association" "public" { - count = local.public_count - subnet_id = element(aws_subnet.public.*.id, count.index) - route_table_id = element(aws_route_table.public.*.id, count.index) + for_each = local.public_azs + + subnet_id = aws_subnet.public[each.key].id + route_table_id = aws_route_table.public[each.key].id depends_on = [ aws_subnet.public, aws_route_table.public, @@ -99,8 +100,8 @@ resource "aws_route_table_association" "public" { } resource "aws_eip" "public" { - count = local.public_nat_gateways_count - vpc = true + for_each = local.public_nat_gateway_azs + vpc = true lifecycle { create_before_destroy = true @@ -108,9 +109,10 @@ resource "aws_eip" "public" { } resource "aws_nat_gateway" "public" { - count = local.public_nat_gateways_count - allocation_id = element(aws_eip.public.*.id, count.index) - subnet_id = element(aws_subnet.public.*.id, count.index) + for_each = local.public_nat_gateway_azs + + allocation_id = aws_eip.public[each.key].id + subnet_id = aws_subnet.public[each.key].id depends_on = [aws_subnet.public] lifecycle { @@ -120,39 +122,8 @@ resource "aws_nat_gateway" "public" { tags = merge( module.public_label.tags, { - "Name" = "${module.public_label.id}${module.this.delimiter}${element(var.availability_zones, count.index)}" - "AZ" = element(var.availability_zones, count.index) + "Name" = "${module.public_label.id}${module.this.delimiter}${each.key}" "Type" = var.type }, ) } - -# Dummy list of NAT Gateway IDs to use in the outputs for private subnets and when `nat_gateway_enabled=false` for public subnets -# Needed due to Terraform limitation of not allowing using conditionals with maps and lists -locals { - dummy_az_ngw_ids = slice( - [ - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - "0", - ], - 0, - length(var.availability_zones), - ) -} - diff --git a/test/src/examples_complete_test.go b/test/src/examples_complete_test.go index 87a5c48..a83716f 100644 --- a/test/src/examples_complete_test.go +++ b/test/src/examples_complete_test.go @@ -24,7 +24,8 @@ func assertValueStartsWith(t *testing.T, m map[string]string, rx interface{}) { // Test the Terraform module in examples/complete using Terratest. func TestExamplesComplete(t *testing.T) { - t.Parallel() + // Init phase module download fails when run in parallel + //t.Parallel() terraformOptions := &terraform.Options{ // The path to where our Terraform code is located @@ -40,35 +41,35 @@ func TestExamplesComplete(t *testing.T) { // This will run `terraform init` and `terraform apply` and fail the test if there are any errors terraform.InitAndApply(t, terraformOptions) -/* - Outputs: - - private_az_route_table_ids = { - "us-east-2a" = "rtb-0489137a5c668e49b" - "us-east-2b" = "rtb-083c0e942abb4b8a1" - "us-east-2c" = "rtb-0c36484693db5e774" - } - private_az_subnet_ids = { - "us-east-2a" = "subnet-0f56deccfe81c0ea0" - "us-east-2b" = "subnet-05861d30d45e7b675" - "us-east-2c" = "subnet-036d747a2b46857ae" - } - public_az_ngw_ids = { - "us-east-2a" = "nat-0f5057f09b8cd8ddc" - "us-east-2b" = "nat-0971b2505ea6d03f1" - "us-east-2c" = "nat-0dc1cdf91010be057" - } - public_az_route_table_ids = { - "us-east-2a" = "rtb-0642afb4401f1eef1" - "us-east-2b" = "rtb-04f511a28a2d5a6a2" - "us-east-2c" = "rtb-05f0ee4e831b05697" - } - public_az_subnet_ids = { - "us-east-2a" = "subnet-0dcb9e32f1f02a367" - "us-east-2b" = "subnet-0b432a6748ca40638" - "us-east-2c" = "subnet-00a9a6636ca722474" - } - */ + /* + Outputs: + + private_az_route_table_ids = { + "us-east-2a" = "rtb-0489137a5c668e49b" + "us-east-2b" = "rtb-083c0e942abb4b8a1" + "us-east-2c" = "rtb-0c36484693db5e774" + } + private_az_subnet_ids = { + "us-east-2a" = "subnet-0f56deccfe81c0ea0" + "us-east-2b" = "subnet-05861d30d45e7b675" + "us-east-2c" = "subnet-036d747a2b46857ae" + } + public_az_ngw_ids = { + "us-east-2a" = "nat-0f5057f09b8cd8ddc" + "us-east-2b" = "nat-0971b2505ea6d03f1" + "us-east-2c" = "nat-0dc1cdf91010be057" + } + public_az_route_table_ids = { + "us-east-2a" = "rtb-0642afb4401f1eef1" + "us-east-2b" = "rtb-04f511a28a2d5a6a2" + "us-east-2c" = "rtb-05f0ee4e831b05697" + } + public_az_subnet_ids = { + "us-east-2a" = "subnet-0dcb9e32f1f02a367" + "us-east-2b" = "subnet-0b432a6748ca40638" + "us-east-2c" = "subnet-00a9a6636ca722474" + } + */ // Run `terraform output` to get the value of an output variable privateSubnetIds := terraform.OutputMap(t, terraformOptions, "private_az_subnet_ids") @@ -94,3 +95,36 @@ func TestExamplesComplete(t *testing.T) { assert.Equal(t, expectedAZs, getKeys(publicSubnetIds)) assertValueStartsWith(t, publicSubnetIds, "^subnet-.*") } + +func TestExamplesCompleteDisabledModule(t *testing.T) { + // Init phase module download fails when run in parallel + //t.Parallel() + + 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", "fixtures.disabled.tfvars"}, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + privateNATGateWayIds := terraform.OutputMap(t, terraformOptions, "private_az_ngw_ids") + privateSubnetIds := terraform.OutputMap(t, terraformOptions, "private_az_subnet_ids") + privateRouteTableIds := terraform.OutputMap(t, terraformOptions, "private_az_route_table_ids") + publicNATGateWayIds := terraform.OutputMap(t, terraformOptions, "public_az_ngw_ids") + publicRouteTableIds := terraform.OutputMap(t, terraformOptions, "public_az_route_table_ids") + publicSubnetIds := terraform.OutputMap(t, terraformOptions, "public_az_subnet_ids") + + assert.Empty(t, privateNATGateWayIds) + assert.Empty(t, privateSubnetIds) + assert.Empty(t, privateRouteTableIds) + assert.Empty(t, publicNATGateWayIds) + assert.Empty(t, publicSubnetIds) + assert.Empty(t, publicRouteTableIds) +} diff --git a/versions.tf b/versions.tf index 4c01ad9..16af5e5 100644 --- a/versions.tf +++ b/versions.tf @@ -4,11 +4,7 @@ terraform { required_providers { aws = { source = "hashicorp/aws" - version = ">= 2.0" - } - template = { - source = "hashicorp/template" - version = ">= 2.0" + version = ">= 3.0" } local = { source = "hashicorp/local"