From 4cc01df484c93eabbdea746267b3e3c4b1c7730b Mon Sep 17 00:00:00 2001 From: Bradley Sakdol <1362081+bsakdol@users.noreply.github.com> Date: Thu, 17 Nov 2022 19:07:03 -0700 Subject: [PATCH] feat: create tgw vpc attachment sub-module Provisions a Transit Gateway VPC attachment --- README.md | 7 +- examples/vpc_attachment/README.md | 59 ++++++++++++ examples/vpc_attachment/main.tf | 130 ++++++++++++++++++++++++++ examples/vpc_attachment/outputs.tf | 33 +++++++ examples/vpc_attachment/terraform.tf | 10 ++ examples/vpc_attachment/variables.tf | 0 modules/vpc-attachment/README.md | 133 +++++++++++++++++++++++++++ modules/vpc-attachment/main.tf | 56 +++++++++++ modules/vpc-attachment/outputs.tf | 36 ++++++++ modules/vpc-attachment/terraform.tf | 10 ++ modules/vpc-attachment/variables.tf | 109 ++++++++++++++++++++++ 11 files changed, 580 insertions(+), 3 deletions(-) create mode 100644 examples/vpc_attachment/README.md create mode 100644 examples/vpc_attachment/main.tf create mode 100644 examples/vpc_attachment/outputs.tf create mode 100644 examples/vpc_attachment/terraform.tf create mode 100644 examples/vpc_attachment/variables.tf create mode 100644 modules/vpc-attachment/README.md create mode 100644 modules/vpc-attachment/main.tf create mode 100644 modules/vpc-attachment/outputs.tf create mode 100644 modules/vpc-attachment/terraform.tf create mode 100644 modules/vpc-attachment/variables.tf diff --git a/README.md b/README.md index 5adcc7a..e5bbd94 100644 --- a/README.md +++ b/README.md @@ -24,9 +24,10 @@ module "vpc" { ## Examples -- [Complete](examples/complete/) -- [Simple](examples/simple/) -- [Transit Gateway Peering](example/transit_gateway_peering/) +- [Complete](./examples/complete/) +- [Simple](./examples/simple/) +- [Transit Gateway Peering](./example/transit_gateway_peering/) +- [Transit Gateway VPC Attachment](./example/vpc_attachment/) ## Requirements diff --git a/examples/vpc_attachment/README.md b/examples/vpc_attachment/README.md new file mode 100644 index 0000000..0d3cb34 --- /dev/null +++ b/examples/vpc_attachment/README.md @@ -0,0 +1,59 @@ +# Transit Gateway VPC Attachment Example + +This module builds Transit Gateway VPC attachment to a Transit Gateway in the `US-East-2` region of AWS. + +## Usage + +To provision the environment in this example, the following commands will need to be executed: + +```hcl +terraform init +terraform apply +``` + +When resources are no longer being used, run the following command to destroy them: + +```hcl +# terraform destroy +``` + +_NOTE: Resources in this example may cost money, so it is important to understand AWS pricing prior to provisioning._ + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.1 | +| [aws](#requirement\_aws) | >= 4.8 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [tgw\_vpc\_attachment](#module\_tgw\_vpc\_attachment) | ../../modules/vpc-attachment | n/a | +| [transit\_gateway](#module\_transit\_gateway) | ../../ | n/a | +| [vpc](#module\_vpc) | bsakdol/vpc/aws | 0.1.3 | + +## Resources + +No resources. + +## Inputs + +No inputs. + +## Outputs + +| Name | Description | +|------|-------------| +| [id](#output\_id) | EC2 Transit Gateway Attachment identifier. | +| [tags\_all](#output\_tags\_all) | A map of tags assigned to the resource, including those inherited from the
provider `default_tags` configuration block. | +| [transit\_gateway\_vpc\_attachment\_all](#output\_transit\_gateway\_vpc\_attachment\_all) | A map of Transit Gateway VPC attachment attributes. | +| [transit\_gateway\_vpc\_attachment\_routes\_all](#output\_transit\_gateway\_vpc\_attachment\_routes\_all) | A map of Transit Gateway VPC attachment routes attributes. | +| [vpc\_owner\_id](#output\_vpc\_owner\_id) | Identifier of the AWS account that owns the EC2 VPC. | + diff --git a/examples/vpc_attachment/main.tf b/examples/vpc_attachment/main.tf new file mode 100644 index 0000000..d4d9851 --- /dev/null +++ b/examples/vpc_attachment/main.tf @@ -0,0 +1,130 @@ +provider "aws" { + region = "us-east-2" +} + +################################################################################ +## TRANSIT GATEWAY VPC ATTACHMENT ## +################################################################################ +module "tgw_vpc_attachment" { + source = "../../modules/vpc-attachment" + + name = "useast2-vpc-example" + + # AWS recommends using an independent, smaller, subnet similar to a /28 for + # the attachment subnet IDs. For reference to the best practices: + # https://docs.aws.amazon.com/vpc/latest/tgw/tgw-best-design-practices.html + subnet_ids = [ + "subnet-0d34038511202d808", + "subnet-08dd167a7d8c8d2d8" + ] + + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_id = "vpc-0f8e1084eaf4f8484" + + transit_gateway_routes = [ + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-01ba195736fd69ad4" + }, + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-0a21aa3d237cfe378" + }, + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-09a519631e899a02a" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-01ba195736fd69ad4" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-0a21aa3d237cfe378" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-09a519631e899a02a" + }, + ] + + tags = { + Environment = "development" + Owner = "bsakdol" + Terraform = "true" + } +} + +################################################################################ +## DEPENDENCIES ## +################################################################################ +# Applied with resource targeting to simulate them being provisioned already: +# - terraform apply -target=module.vpc +# - terraform apply -target=module.transit_gateway +module "vpc" { + source = "bsakdol/vpc/aws" + version = "0.1.3" + + name = "useast2-vpc-example" + + cidr_block = "10.0.0.0/16" + enable_dns_hostnames = true + enable_dns_support = true + + internal_subnets = { + "10.0.255.0/28" = { + "availability_zone" = "us-east-2a" + }, + "10.0.255.16/28" = { + "availability_zone" = "us-east-2b" + } + } + + private_subnets = { + "10.0.10.0/24" = { + "availability_zone" = "us-east-2a" + }, + "10.0.11.0/24" = { + "availability_zone" = "us-east-2b" + } + } + + public_subnets = { + "10.0.20.0/24" = { + "availability_zone" = "us-east-2a" + "create_nat_gateway" = true + }, + "10.0.21.0/24" = { + "availability_zone" = "us-east-2b" + "create_nat_gateway" = true + } + } + + internal_subnets_tags = { Type = "internal" } + private_subnets_tags = { Type = "private" } + public_subnets_tags = { Type = "public" } + + tags = { + Environment = "development" + Owner = "bsakdol" + Terraform = "true" + } +} + +module "transit_gateway" { + source = "../../" + + name = "useast2-example" + + tags = { + "Environment" = "development" + "Owner" = "bsakdol" + "Terraform" = "true" + } +} diff --git a/examples/vpc_attachment/outputs.tf b/examples/vpc_attachment/outputs.tf new file mode 100644 index 0000000..fb7ec3d --- /dev/null +++ b/examples/vpc_attachment/outputs.tf @@ -0,0 +1,33 @@ +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ## +################################################################################ +output "id" { + description = "EC2 Transit Gateway Attachment identifier." + value = module.tgw_vpc_attachment.id +} + +output "tags_all" { + description = <<-EOT + A map of tags assigned to the resource, including those inherited from the + provider `default_tags` configuration block. + EOT + value = module.tgw_vpc_attachment.tags_all +} + +output "transit_gateway_vpc_attachment_all" { + description = "A map of Transit Gateway VPC attachment attributes." + value = module.tgw_vpc_attachment.transit_gateway_vpc_attachment_all +} + +output "vpc_owner_id" { + description = "Identifier of the AWS account that owns the EC2 VPC." + value = module.tgw_vpc_attachment.vpc_owner_id +} + +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ROUTES ## +################################################################################ +output "transit_gateway_vpc_attachment_routes_all" { + description = "A map of Transit Gateway VPC attachment routes attributes." + value = module.tgw_vpc_attachment.transit_gateway_vpc_attachment_routes_all +} diff --git a/examples/vpc_attachment/terraform.tf b/examples/vpc_attachment/terraform.tf new file mode 100644 index 0000000..6310b13 --- /dev/null +++ b/examples/vpc_attachment/terraform.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.8" + } + } +} diff --git a/examples/vpc_attachment/variables.tf b/examples/vpc_attachment/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/vpc-attachment/README.md b/modules/vpc-attachment/README.md new file mode 100644 index 0000000..e6713bf --- /dev/null +++ b/modules/vpc-attachment/README.md @@ -0,0 +1,133 @@ +# AWS Transit Gateway VPC Attachment Terraform Sub-Module + +Terraform module for managing AWS Transit Gateway VPC attachments and routing. + +## Usage + +**IMPORTANT NOTE:** The `main` branch is used as the module source for the usage examples, in place of the version. It is important to pin the release tag (e.g. `?ref=tags/x.y.z`) for the module to the source, when using any portion of this module to provision resources. The `main` branch may contain undocumented breaking changes. + +```hcl +module "tgw_vpc_attachment" { + source = "../../modules/vpc-attachment" + + subnet_ids = [ + "subnet-0d34038511202d808", + "subnet-08dd167a7d8c8d2d8" + ] + + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_id = "vpc-0f8e1084eaf4f8484" + + transit_gateway_routes = [ + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-01ba195736fd69ad4" + }, + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-0a21aa3d237cfe378" + }, + { + destination_cidr_block = "10.0.0.0/8" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-09a519631e899a02a" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-01ba195736fd69ad4" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-0a21aa3d237cfe378" + }, + { + destination_prefix_list_id = "pl-0af146abed9353978" + transit_gateway_id = "tgw-0b69e8c71693c44fb" + vpc_route_table_id = "rtb-09a519631e899a02a" + }, + ] + + tags = { + Environment = "development" + Name = "useast2-vpc-example" + Owner = "bsakdol" + Terraform = "true" + } +} + +``` + +## Peering Attachment Routing + +The `transit_gateway_routes` variable is a list of maps to define what routes should be populated in the VPC routing tables. While the `aws_route` resource has many options available, the ones available for use within this module are defined as: + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [destination\_cidr\_block](#destination\_cidr\_block) | The destination CIDR block. | `string` | `null` | no | +| [destination\_prefix\_list\_id](#destination\_prefix\_list\_id) | The ID of a managed prefix list destination. | `string` | `null` | no | +| [transit\_gateway\_id](#transit\_gateway\_id) | Identifier of an EC2 Transit Gateway. | `string` | `null` | yes | +| [vpc\_route\_table\_id](#vpc\_route\_table\_id) | Identifier of a VPC route table. | `string` | `null` | yes | + +_NOTE: Only specify one of `destination_cidr_block` or `destination_prefix_list_id` for a single peering attachment route. Do not define both attributes in the same map. However, `destination_cidr_block` should take priority over `destination_prefix_list_id` in the event both attributes are defined within the same map._ + +## Examples + +- [VPC Attachment](../../examples/vpc_attachment/) + + +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.1 | +| [aws](#requirement\_aws) | >= 4.8 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | >= 4.8 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [aws_ec2_transit_gateway_vpc_attachment.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ec2_transit_gateway_vpc_attachment) | resource | +| [aws_route.cidr_block](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | +| [aws_route.prefix_list](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/route) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [appliance\_mode\_support](#input\_appliance\_mode\_support) | Whether Appliance Mode support is enabled. If enabled, a traffic flow
between a source and destination uses the same Availability Zone for the VPC
attachment for the lifetime of that flow. | `bool` | `false` | no | +| [dns\_support](#input\_dns\_support) | Whether DNS support is enabled. | `bool` | `true` | no | +| [ipv6\_support](#input\_ipv6\_support) | Whether IPv6 support is enabled. | `bool` | `false` | no | +| [name](#input\_name) | Name to be used as an identifier of all managed resources. | `string` | `null` | no | +| [subnet\_ids](#input\_subnet\_ids) | List of EC2 Subnet Identifiers where the attachment will be provisioned.
Only one subnet ID is allowed for each availability zone. | `list(string)` | `[]` | no | +| [tags](#input\_tags) | A map of tags to assign to the resource. If configured with a provider
`default_tags` configuration block present, tags with matching keys will
overwrite those defined at the provider-level. | `map(string)` | `{}` | no | +| [transit\_gateway\_default\_route\_table\_association](#input\_transit\_gateway\_default\_route\_table\_association) | Boolean whether the VPC Attachment should be associated with the EC2
Transit Gateway association default route table. This cannot be configured
or perform drift detection with Resource Access Manager shared EC2 Transit
Gateways. | `bool` | `true` | no | +| [transit\_gateway\_default\_route\_table\_propagation](#input\_transit\_gateway\_default\_route\_table\_propagation) | Boolean whether the VPC Attachment should propagate routes with the EC2
Transit Gateway propagation default route table. This cannot be configured
or perform drift detection with Resource Access Manager shared EC2 Transit
Gateways. | `bool` | `true` | no | +| [transit\_gateway\_id](#input\_transit\_gateway\_id) | Identifier of EC2 Transit Gateway. | `string` | `null` | no | +| [transit\_gateway\_routes](#input\_transit\_gateway\_routes) | The routes to be configured in the VPC route tables. Either the
`destination_cidr_block` or `destination_prefix_list_id` must be configured
for each map of attributes. |
list(object({
destination_cidr_block = optional(string, null)
destination_prefix_list_id = optional(string, null)
transit_gateway_id = string
vpc_route_table_id = string
}))
|
[
{
"destination_cidr_block": null,
"destination_prefix_list_id": null,
"transit_gateway_id": null,
"vpc_route_table_id": null
}
]
| no | +| [vpc\_attachment\_tags](#input\_vpc\_attachment\_tags) | A map of tags to assign to the VPC attachment resource. Resource specific
tags will override all other tags. | `map(string)` | `{}` | no | +| [vpc\_id](#input\_vpc\_id) | Identifier of EC2 VPC. | `string` | `null` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [id](#output\_id) | EC2 Transit Gateway Attachment identifier. | +| [tags\_all](#output\_tags\_all) | A map of tags assigned to the resource, including those inherited from the
provider `default_tags` configuration block. | +| [transit\_gateway\_vpc\_attachment\_all](#output\_transit\_gateway\_vpc\_attachment\_all) | A map of Transit Gateway VPC attachment attributes. | +| [transit\_gateway\_vpc\_attachment\_routes\_all](#output\_transit\_gateway\_vpc\_attachment\_routes\_all) | A map of Transit Gateway VPC attachment routes attributes. | +| [vpc\_owner\_id](#output\_vpc\_owner\_id) | Identifier of the AWS account that owns the EC2 VPC. | + diff --git a/modules/vpc-attachment/main.tf b/modules/vpc-attachment/main.tf new file mode 100644 index 0000000..5e7a897 --- /dev/null +++ b/modules/vpc-attachment/main.tf @@ -0,0 +1,56 @@ +locals { + cidr_block_routes = [for x in var.transit_gateway_routes : x if x.destination_cidr_block != null] + prefix_list_routes = [for x in var.transit_gateway_routes : x if x.destination_prefix_list_id != null && x.destination_cidr_block == null] +} + +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ## +################################################################################ +resource "aws_ec2_transit_gateway_vpc_attachment" "this" { + subnet_ids = var.subnet_ids + transit_gateway_id = var.transit_gateway_id + vpc_id = var.vpc_id + + appliance_mode_support = var.appliance_mode_support ? "enable" : "disable" + dns_support = var.dns_support ? "enable" : "disable" + ipv6_support = var.ipv6_support ? "enable" : "disable" + transit_gateway_default_route_table_association = var.transit_gateway_default_route_table_association + transit_gateway_default_route_table_propagation = var.transit_gateway_default_route_table_propagation + + tags = merge( + var.tags, + { + "Name" = var.name + }, + var.vpc_attachment_tags + ) +} + +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ROUTES ## +################################################################################ +resource "aws_route" "cidr_block" { + for_each = length(local.cidr_block_routes) > 0 ? { for x in local.cidr_block_routes : format("%v-%v", x["vpc_route_table_id"], x["destination_cidr_block"]) => x } : {} + + route_table_id = each.value["vpc_route_table_id"] + transit_gateway_id = each.value["transit_gateway_id"] + + destination_cidr_block = each.value["destination_cidr_block"] + + depends_on = [ + aws_ec2_transit_gateway_vpc_attachment.this + ] +} + +resource "aws_route" "prefix_list" { + for_each = length(local.prefix_list_routes) > 0 ? { for x in local.prefix_list_routes : format("%v-%v", x["vpc_route_table_id"], x["destination_prefix_list_id"]) => x } : {} + + route_table_id = each.value["vpc_route_table_id"] + transit_gateway_id = each.value["transit_gateway_id"] + + destination_prefix_list_id = each.value["destination_prefix_list_id"] + + depends_on = [ + aws_ec2_transit_gateway_vpc_attachment.this + ] +} diff --git a/modules/vpc-attachment/outputs.tf b/modules/vpc-attachment/outputs.tf new file mode 100644 index 0000000..1193a72 --- /dev/null +++ b/modules/vpc-attachment/outputs.tf @@ -0,0 +1,36 @@ +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ## +################################################################################ +output "id" { + description = "EC2 Transit Gateway Attachment identifier." + value = try(aws_ec2_transit_gateway_vpc_attachment.this.id, null) +} + +output "tags_all" { + description = <<-EOT + A map of tags assigned to the resource, including those inherited from the + provider `default_tags` configuration block. + EOT + value = try(aws_ec2_transit_gateway_vpc_attachment.this.tags_all, null) +} + +output "transit_gateway_vpc_attachment_all" { + description = "A map of Transit Gateway VPC attachment attributes." + value = try(aws_ec2_transit_gateway_vpc_attachment.this, null) +} + +output "vpc_owner_id" { + description = "Identifier of the AWS account that owns the EC2 VPC." + value = try(aws_ec2_transit_gateway_vpc_attachment.this.vpc_owner_id, null) +} + +################################################################################ +## VPC TRANSIT GATEWAY ATTACHMENT ROUTES ## +################################################################################ +output "transit_gateway_vpc_attachment_routes_all" { + description = "A map of Transit Gateway VPC attachment routes attributes." + value = try(merge( + try(aws_route.cidr_block, null), + try(aws_route.prefix_list, null) + ), null) +} diff --git a/modules/vpc-attachment/terraform.tf b/modules/vpc-attachment/terraform.tf new file mode 100644 index 0000000..6310b13 --- /dev/null +++ b/modules/vpc-attachment/terraform.tf @@ -0,0 +1,10 @@ +terraform { + required_version = ">= 1.1" + + required_providers { + aws = { + source = "hashicorp/aws" + version = ">= 4.8" + } + } +} diff --git a/modules/vpc-attachment/variables.tf b/modules/vpc-attachment/variables.tf new file mode 100644 index 0000000..611dcdb --- /dev/null +++ b/modules/vpc-attachment/variables.tf @@ -0,0 +1,109 @@ +variable "appliance_mode_support" { + type = bool + default = false + description = <<-EOT + Whether Appliance Mode support is enabled. If enabled, a traffic flow + between a source and destination uses the same Availability Zone for the VPC + attachment for the lifetime of that flow. + EOT +} + +variable "dns_support" { + type = bool + default = true + description = "Whether DNS support is enabled." +} + +variable "ipv6_support" { + type = bool + default = false + description = "Whether IPv6 support is enabled." +} + +variable "name" { + type = string + default = null + description = "Name to be used as an identifier of all managed resources." +} + +variable "subnet_ids" { + type = list(string) + default = [] + description = <<-EOT + List of EC2 Subnet Identifiers where the attachment will be provisioned. + Only one subnet ID is allowed for each availability zone. + EOT +} + +variable "tags" { + type = map(string) + default = {} + description = <<-EOT + A map of tags to assign to the resource. If configured with a provider + `default_tags` configuration block present, tags with matching keys will + overwrite those defined at the provider-level. + EOT +} + +variable "transit_gateway_default_route_table_association" { + type = bool + default = true + description = <<-EOT + Boolean whether the VPC Attachment should be associated with the EC2 + Transit Gateway association default route table. This cannot be configured + or perform drift detection with Resource Access Manager shared EC2 Transit + Gateways. + EOT +} + +variable "transit_gateway_default_route_table_propagation" { + type = bool + default = true + description = <<-EOT + Boolean whether the VPC Attachment should propagate routes with the EC2 + Transit Gateway propagation default route table. This cannot be configured + or perform drift detection with Resource Access Manager shared EC2 Transit + Gateways. + EOT +} + +variable "transit_gateway_id" { + type = string + default = null + description = "Identifier of EC2 Transit Gateway." +} + +variable "transit_gateway_routes" { + type = list(object({ + destination_cidr_block = optional(string, null) + destination_prefix_list_id = optional(string, null) + transit_gateway_id = string + vpc_route_table_id = string + })) + default = [{ + destination_cidr_block = null + destination_prefix_list_id = null + transit_gateway_id = null + vpc_route_table_id = null + }] + description = <<-EOT + The routes to be configured in the VPC route tables. Either the + `destination_cidr_block` or `destination_prefix_list_id` must be configured + for each map of attributes. + EOT +} + +variable "vpc_attachment_tags" { + type = map(string) + default = {} + description = <<-EOT + A map of tags to assign to the VPC attachment resource. Resource specific + tags will override all other tags. + EOT +} + +variable "vpc_id" { + type = string + default = null + description = "Identifier of EC2 VPC." +}