diff --git a/.github/labeler.yaml b/.github/labeler.yaml index bb352d2..bc6b780 100644 --- a/.github/labeler.yaml +++ b/.github/labeler.yaml @@ -11,5 +11,8 @@ ":floppy_disk: security-group": - modules/security-group/**/* +":floppy_disk: subnet-group": +- modules/subnet-group/**/* + ":floppy_disk: vpc": - modules/vpc/**/* diff --git a/examples/vpc-full/nat-gateways.tf b/examples/vpc-full/nat-gateways.tf new file mode 100644 index 0000000..3df103c --- /dev/null +++ b/examples/vpc-full/nat-gateways.tf @@ -0,0 +1,67 @@ +################################################### +# Elastic IP +################################################### + +module "elastic_ip" { + source = "tedilabs/ipam/aws//modules/elastic-ip" + version = "~> 0.3.0" + + name = "nat-gw-test-public/az2" + type = "AMAZON" + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# Public NAT Gateway +################################################### + +module "public_nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-public/az2" + is_private = false + subnet = module.public_subnet_group.subnets_by_az["use1-az2"][0].id + + + ## Primary IP Address + primary_ip_assignment = { + elastic_ip = module.elastic_ip.id + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} + + +################################################### +# Private NAT Gateway +################################################### + +module "private_nat_gateway" { + source = "../../modules/nat-gateway" + # source = "tedilabs/network/aws//modules/nat-gateway" + # version = "~> 0.2.0" + + name = "test-private/az2" + is_private = true + subnet = module.private_subnet_group.subnets_by_az["use1-az2"][0].id + + + ## Primary IP Address + primary_ip_assignment = { + private_ip = "10.0.200.7" + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/examples/vpc-full/outputs.tf b/examples/vpc-full/outputs.tf index cc46043..6bd50a8 100644 --- a/examples/vpc-full/outputs.tf +++ b/examples/vpc-full/outputs.tf @@ -2,3 +2,21 @@ output "vpc" { description = "The VPC." value = module.vpc } + +output "subnet_groups" { + description = "The Subnet Groups for the VPC." + value = { + private = module.private_subnet_group + public = module.public_subnet_group + } +} + +output "public_nat_gateways" { + description = "The NAT Gateways in public." + value = module.public_nat_gateway +} + +output "private_nat_gateways" { + description = "The NAT Gateways in private." + value = module.private_nat_gateway +} diff --git a/examples/vpc-full/subnet-groups.tf b/examples/vpc-full/subnet-groups.tf new file mode 100644 index 0000000..868f46a --- /dev/null +++ b/examples/vpc-full/subnet-groups.tf @@ -0,0 +1,138 @@ +################################################### +# Subnet Groups +################################################### + +module "private_subnet_group" { + source = "../../modules/subnet-group" + # source = "tedilabs/network/aws//modules/subnet-group" + # version = "~> 0.2.0" + + name = "test/private" + + vpc_id = module.vpc.id + + subnets = { + "test/private/az2" = { + availability_zone_id = "use1-az2" + ipv4_cidr = "10.0.200.0/24" + } + "test/private/az4" = { + availability_zone_id = "use1-az4" + ipv4_cidr = "10.0.201.0/24" + } + } + + + ## IP Assignments + public_ipv4_address_assignment = { + enabled = false + } + ipv6_address_assignment = { + enabled = false + } + customer_owned_ipv4_address_assignment = { + enabled = false + } + + + ## DNS Configurations + dns_config = { + hostname_type = "RESOURCE_NAME" + dns_resource_name_ipv4_enabled = true + dns_resource_name_ipv6_enabled = false + dns64_enabled = false + } + + ## Integrations + dax_subnet_group = { + enabled = true + name = "test-dax" + description = "Test DAX Subnet Group" + } + dms_replication_subnet_group = { + enabled = true + name = "test-dms-replication" + description = "Test DMS Replication Subnet Group" + } + docdb_subnet_group = { + enabled = true + name = "test-docdb" + description = "Test DocumentDB Subnet Group" + } + elasticache_subnet_group = { + enabled = true + name = "test-elasticache" + description = "Test ElastiCache Subnet Group" + } + memorydb_subnet_group = { + enabled = true + name = "test-memorydb" + description = "Test MemoryDB Subnet Group" + } + neptune_subnet_group = { + enabled = true + name = "test-neptune" + description = "Test Neptune Subnet Group" + } + rds_subnet_group = { + enabled = true + name = "test-rds" + description = "Test RDS Subnet Group" + } + redshift_subnet_group = { + enabled = true + name = "test-redshift" + description = "Test Redshift Subnet Group" + } + + tags = { + "project" = "terraform-aws-network-examples" + } +} + +module "public_subnet_group" { + source = "../../modules/subnet-group" + # source = "tedilabs/network/aws//modules/subnet-group" + # version = "~> 0.2.0" + + name = "test/public" + + vpc_id = module.vpc.id + + subnets = { + "test/public/az2" = { + availability_zone_id = "use1-az2" + ipv4_cidr = "10.0.100.0/24" + } + "test/public/az4" = { + availability_zone_id = "use1-az4" + ipv4_cidr = "10.0.101.0/24" + } + } + + + ## IP Assignments + public_ipv4_address_assignment = { + enabled = true + } + ipv6_address_assignment = { + enabled = false + } + customer_owned_ipv4_address_assignment = { + enabled = false + } + + + ## DNS Configurations + dns_config = { + hostname_type = "RESOURCE_NAME" + dns_resource_name_ipv4_enabled = true + dns_resource_name_ipv6_enabled = false + dns64_enabled = false + } + + + tags = { + "project" = "terraform-aws-network-examples" + } +} diff --git a/modules/subnet-group/README.md b/modules/subnet-group/README.md index b7f4c59..662fd10 100644 --- a/modules/subnet-group/README.md +++ b/modules/subnet-group/README.md @@ -3,13 +3,14 @@ This module creates following resources. - `aws_subnet` +- `aws_dax_subnet_group` (optional) - `aws_db_subnet_group` (optional) +- `aws_dms_replication_subnet_group` (optional) +- `aws_docdb_subnet_group` (optional) - `aws_elasticache_subnet_group` (optional) -- `aws_redshift_subnet_group` (optional) +- `aws_memorydb_subnet_group` (optional) - `aws_neptune_subnet_group` (optional) -- `aws_docdb_subnet_group` (optional) -- `aws_dax_subnet_group` (optional) -- `aws_dms_replication_subnet_group` (optional) +- `aws_redshift_subnet_group` (optional) ## Requirements @@ -23,7 +24,7 @@ This module creates following resources. | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.19.0 | +| [aws](#provider\_aws) | 5.22.0 | ## Modules @@ -44,40 +45,34 @@ This module creates following resources. | [aws_neptune_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/neptune_subnet_group) | resource | | [aws_redshift_subnet_group.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/redshift_subnet_group) | resource | | [aws_subnet.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/subnet) | resource | +| [aws_availability_zones.available](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/availability_zones) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [name](#input\_name) | The name of the subnet group. | `string` | n/a | yes | -| [subnets](#input\_subnets) | A map of subnet parameters to create subnets for the subnet group. | `map(map(any))` | n/a | yes | -| [vpc\_id](#input\_vpc\_id) | The ID of the VPC which the subnet group belongs to. | `string` | n/a | yes | -| [assign\_ipv6\_address\_on\_creation](#input\_assign\_ipv6\_address\_on\_creation) | Assign IPv6 address on subnet, must be disabled to change IPv6 CIDRs. This is the IPv6 equivalent of map\_public\_ip\_on\_launch. | `bool` | `false` | no | -| [cache\_subnet\_group\_enabled](#input\_cache\_subnet\_group\_enabled) | Controls if Elasticache Subnet Group should be created. | `bool` | `false` | no | -| [cache\_subnet\_group\_name](#input\_cache\_subnet\_group\_name) | Desired name for the Elasticache Subnet Group. | `string` | `""` | no | -| [customer\_owned\_ipv4\_pool](#input\_customer\_owned\_ipv4\_pool) | The customer owned IPv4 address pool. `outpost_arn` argument must be specified when configured. | `string` | `""` | no | -| [dax\_subnet\_group\_enabled](#input\_dax\_subnet\_group\_enabled) | Controls if DAX Subnet Group should be created. | `bool` | `false` | no | -| [dax\_subnet\_group\_name](#input\_dax\_subnet\_group\_name) | Desired name for the DAX Subnet Group. | `string` | `""` | no | -| [db\_subnet\_group\_enabled](#input\_db\_subnet\_group\_enabled) | Controls if RDS Subnet Group should be created. | `bool` | `false` | no | -| [db\_subnet\_group\_name](#input\_db\_subnet\_group\_name) | Desired name for the RDS Subnet Group. | `string` | `""` | no | -| [dms\_replication\_subnet\_group\_enabled](#input\_dms\_replication\_subnet\_group\_enabled) | Controls if DMS Replication Subnet Group should be created. | `bool` | `false` | no | -| [dms\_replication\_subnet\_group\_name](#input\_dms\_replication\_subnet\_group\_name) | Desired name for the DMS Replication Subnet Group. | `string` | `""` | no | -| [docdb\_subnet\_group\_enabled](#input\_docdb\_subnet\_group\_enabled) | Controls if DocumentDB Subnet Group should be created. | `bool` | `false` | no | -| [docdb\_subnet\_group\_name](#input\_docdb\_subnet\_group\_name) | Desired name for the DocumentDB Subnet Group. | `string` | `""` | no | -| [map\_customer\_owned\_ip\_on\_launch](#input\_map\_customer\_owned\_ip\_on\_launch) | Should be true if network interfaces created in the subnet should be assigned a customer owned IP address. | `bool` | `false` | no | -| [map\_public\_ip\_on\_launch](#input\_map\_public\_ip\_on\_launch) | Should be false if you do not want to auto-assign public IP on launch. | `bool` | `false` | no | -| [memorydb\_subnet\_group\_enabled](#input\_memorydb\_subnet\_group\_enabled) | Controls if MemoryDB Subnet Group should be created. | `bool` | `false` | no | -| [memorydb\_subnet\_group\_name](#input\_memorydb\_subnet\_group\_name) | Desired name for the MemoryDB Subnet Group. | `string` | `""` | no | -| [module\_tags\_enabled](#input\_module\_tags\_enabled) | Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | -| [neptune\_subnet\_group\_enabled](#input\_neptune\_subnet\_group\_enabled) | Controls if Neptune Subnet Group should be created. | `bool` | `false` | no | -| [neptune\_subnet\_group\_name](#input\_neptune\_subnet\_group\_name) | Desired name for the Neptune Subnet Group. | `string` | `""` | no | -| [outpost\_arn](#input\_outpost\_arn) | The ARN of the Outpost. | `string` | `""` | no | -| [redshift\_subnet\_group\_enabled](#input\_redshift\_subnet\_group\_enabled) | Controls if Redshift Subnet Group should be created. | `bool` | `false` | no | -| [redshift\_subnet\_group\_name](#input\_redshift\_subnet\_group\_name) | Desired name for the Redshift Subnet Group. | `string` | `""` | no | -| [resource\_group\_description](#input\_resource\_group\_description) | The description of Resource Group. | `string` | `"Managed by Terraform."` | no | -| [resource\_group\_enabled](#input\_resource\_group\_enabled) | Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | -| [resource\_group\_name](#input\_resource\_group\_name) | The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | -| [tags](#input\_tags) | A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [name](#input\_name) | (Required) The name of the subnet group. | `string` | n/a | yes | +| [subnets](#input\_subnets) | (Required) A configuration of subnets to create in the subnet group. Each block of `subnets` as defined below.
(Required) `type` - The type of subnet. Valid values are `DUALSTACK` and `IPV6`.
(Optional) `availability_zone` - The availability zone of the subnet. If the value of `availability_zone` and `availability_zone_id` are both not provided, the subnet will be created in random availability zone.
(Optional) `availability_zone_id` - The availability zone ID of the subnet. If the value of `availability_zone` and `availability_zone_id` are both not provided, the subnet will be created in random availability zone. |
map(object({
type = optional(string, "DUALSTACK")

availability_zone = optional(string)
availability_zone_id = optional(string)

ipv4_cidr = optional(string)
ipv6_cidr = optional(string)
}))
| n/a | yes | +| [vpc\_id](#input\_vpc\_id) | (Required) The ID of the VPC which the subnet group belongs to. | `string` | n/a | yes | +| [customer\_owned\_ipv4\_address\_assignment](#input\_customer\_owned\_ipv4\_address\_assignment) | (Optional) A configuration for Customer-owned IPv4 address assignment. `customer_owned_ipv4_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a Customer-owned IPv4 address for a new network interface in this subnet. Defaults to `false`.
(Optional) `outpost` - The Amazon Resource Name (ARN) of the Outpost.
(Optional) `pool` - The customer owned IPv4 address pool. |
object({
enabled = optional(bool, false)
outpost = optional(string)
pool = optional(string)
})
| `{}` | no | +| [dax\_subnet\_group](#input\_dax\_subnet\_group) | (Optional) A configuration of DAX Subnet Group. `dax_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DAX Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DAX Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DAX Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [dms\_replication\_subnet\_group](#input\_dms\_replication\_subnet\_group) | (Optional) A configuration of DMS Replication Subnet Group. `dms_replication_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DMS Replication Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DMS Replication Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DMS Replication Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [dns\_config](#input\_dns\_config) | (Optional) A configuration for DNS queries for the subnet. `dns_config` as defined below.
(Optional) `hostname_type` - The type of hostnames to assign to instances in the subnet at launch. For IPv6-only subnets, an instance DNS name must be based on the instance ID (`RESOURCE_NAME`). For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address (`IP_NAME`) or the instance ID (`RESOURCE_NAME`). Valid values are `IP_NAME`, `RESOURCE_NAME`. Defaults to `RESOURCE_NAME`.
(Optional) `dns_resource_name_ipv4_enabled` - Whether to respond to DNS queries for instance hostnames with DNS A records. Always `false` for IPv6 only subnet. Defaults to `false`.
(Optional) `dns_resource_name_ipv6_enabled` - Whether to respond to DNS queries for instance hostnames with DNS AAAA records. Always `true` for IPv6 only subnet. Defaults to `false`.
(Optional) `dns64_enabled` - Whether to enable DNS64 to allow IPv6-only services in Amazon VPC to communicate with IPv4-only services and networks. Defaults to `false`. |
object({
hostname_type = optional(string, "RESOURCE_NAME")
dns_resource_name_ipv4_enabled = optional(bool, false)
dns_resource_name_ipv6_enabled = optional(bool, false)
dns64_enabled = optional(bool, false)
})
| `{}` | no | +| [docdb\_subnet\_group](#input\_docdb\_subnet\_group) | (Optional) A configuration of DocumentDB Subnet Group. `docdb_subnet_group` as defined below.
(Optional) `enabled` - Whether to create DocumentDB Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the DocumentDB Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the DocumentDB Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [elasticache\_subnet\_group](#input\_elasticache\_subnet\_group) | (Optional) A configuration of ElastiCache Subnet Group. `elasticache_subnet_group` as defined below.
(Optional) `enabled` - Whether to create ElastiCache Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the ElastiCache Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the ElastiCache Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [ipv6\_address\_assignment](#input\_ipv6\_address\_assignment) | (Optional) A configuration for IPv6 address assignment. `ipv6_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a IPv6 address for a new network interface in this subnet. Defaults to `false`. |
object({
enabled = optional(bool, false)
})
| `{}` | no | +| [local\_network\_interface\_device\_index](#input\_local\_network\_interface\_device\_index) | (Optional) The device position for local network interfaces in this subnet. For example, `1` indicates local network interfaces in this subnet are the secondary network interface (eth1). A local network interface cannot be the primary network interface (eth0). | `number` | `null` | no | +| [memorydb\_subnet\_group](#input\_memorydb\_subnet\_group) | (Optional) A configuration of MemoryDB Subnet Group. `memorydb_subnet_group` as defined below.
(Optional) `enabled` - Whether to create MemoryDB Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the MemoryDB Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the MemoryDB Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [module\_tags\_enabled](#input\_module\_tags\_enabled) | (Optional) Whether to create AWS Resource Tags for the module informations. | `bool` | `true` | no | +| [neptune\_subnet\_group](#input\_neptune\_subnet\_group) | (Optional) A configuration of Neptune Subnet Group. `neptune_subnet_group` as defined below.
(Optional) `enabled` - Whether to create Neptune Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the Neptune Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the Neptune Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [public\_ipv4\_address\_assignment](#input\_public\_ipv4\_address\_assignment) | (Optional) A configuration for public IPv4 address assignment. `public_ipv4_address_assignment` as defined below.
(Optional) `enabled` - Whether to automatically request a public IPv4 address for a new network interface in this subnet. Defaults to `false`. |
object({
enabled = optional(bool, false)
})
| `{}` | no | +| [rds\_subnet\_group](#input\_rds\_subnet\_group) | (Optional) A configuration of RDS Subnet Group. `rds_subnet_group` as defined below.
(Optional) `enabled` - Whether to create RDS Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the RDS Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the RDS Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [redshift\_subnet\_group](#input\_redshift\_subnet\_group) | (Optional) A configuration of Redshift Subnet Group. `redshift_subnet_group` as defined below.
(Optional) `enabled` - Whether to create Redshift Subnet Group. Defaults to `false`.
(Optional) `name` - The name of the Redshift Subnet Group. If not provided, the value of `name` will be used.
(Optional) `description` - The description of the Redshift Subnet Group. |
object({
enabled = optional(bool, false)
name = optional(string)
description = optional(string, "Managed by Terraform.")
})
| `{}` | no | +| [resource\_group\_description](#input\_resource\_group\_description) | (Optional) The description of Resource Group. | `string` | `"Managed by Terraform."` | no | +| [resource\_group\_enabled](#input\_resource\_group\_enabled) | (Optional) Whether to create Resource Group to find and group AWS resources which are created by this module. | `bool` | `true` | no | +| [resource\_group\_name](#input\_resource\_group\_name) | (Optional) The name of Resource Group. A Resource Group name can have a maximum of 127 characters, including letters, numbers, hyphens, dots, and underscores. The name cannot start with `AWS` or `aws`. | `string` | `""` | no | +| [tags](#input\_tags) | (Optional) A map of tags to add to all resources. | `map(string)` | `{}` | no | +| [timeouts](#input\_timeouts) | (Optional) How long to wait for the subnet group to be created/deleted. |
object({
create = optional(string, "10m")
delete = optional(string, "20m")
})
| `{}` | no | ## Outputs @@ -86,23 +81,24 @@ This module creates following resources. | [arns](#output\_arns) | A list of ARNs of subnets | | [availability\_zone\_ids](#output\_availability\_zone\_ids) | A list of availability zone IDs which the subnet group uses. | | [availability\_zones](#output\_availability\_zones) | A list of availability zones which the subnet group uses. | -| [cache\_subnet\_group\_id](#output\_cache\_subnet\_group\_id) | The ID of the Elasticache Subnet Group. | -| [cidr\_blocks](#output\_cidr\_blocks) | The CIDR blocks of the subnet group. | -| [dax\_subnet\_group\_id](#output\_dax\_subnet\_group\_id) | The ID of the DAX Subnet Group. | -| [db\_subnet\_group\_arn](#output\_db\_subnet\_group\_arn) | The ARN of the RDS Subnet Group. | -| [db\_subnet\_group\_id](#output\_db\_subnet\_group\_id) | The ID of the RDS Subnet Group. | -| [dms\_replication\_subnet\_group\_id](#output\_dms\_replication\_subnet\_group\_id) | The ID of the DMS Replication Subnet Group. | -| [docdb\_subnet\_group\_arn](#output\_docdb\_subnet\_group\_arn) | The ARN of the DocumentDB Subnet Group. | -| [docdb\_subnet\_group\_id](#output\_docdb\_subnet\_group\_id) | The ID of the DocumentDB Subnet Group. | +| [customer\_owned\_ipv4\_address\_assignment](#output\_customer\_owned\_ipv4\_address\_assignment) | The configuration of Customer-owned IPv4 address assignment.
`enabled` - Whether to automatically assign Customer-owned IPv4 address to instances launched in the subnet group.
`outpost` - The ARN of the Outpost.
`pool` - The ID of the Customer-owned IPv4 address pool. | +| [dax\_subnet\_group](#output\_dax\_subnet\_group) | The configuration of DAX Subnet Group.
`id` - The ID of the DAX Subnet Group.
`name` - The name of the DAX Subnet Group.
`description` - The description of the DAX Subnet Group. | +| [dms\_replication\_subnet\_group](#output\_dms\_replication\_subnet\_group) | The configuration of DMS Replication Subnet Group.
`id` - The ID of the DMS Replication Subnet Group.
`arn` - The ARN of the DMS Replication Subnet Group.
`name` - The name of the DMS Replication Subnet Group.
`description` - The description of the DMS Replication Subnet Group. | +| [dns\_config](#output\_dns\_config) | The DNS configuration for the subnet group.
`id` - The ID of the DAX Subnet Group. | +| [docdb\_subnet\_group](#output\_docdb\_subnet\_group) | The configuration of DocumentDB Subnet Group.
`id` - The ID of the DocumentDB Subnet Group.
`arn` - The ARN of the DocumentDB Subnet Group.
`name` - The name of the DocumentDB Subnet Group.
`description` - The description of the DocumentDB Subnet Group. | +| [elasticache\_subnet\_group](#output\_elasticache\_subnet\_group) | The configuration of ElastiCache Subnet Group.
`id` - The ID of the ElastiCache Subnet Group.
`arn` - The ARN of the ElastiCache Subnet Group.
`name` - The name of the ElastiCache Subnet Group.
`description` - The description of the ElastiCache Subnet Group. | | [ids](#output\_ids) | A list of IDs of subnets | -| [ipv6\_cidr\_blocks](#output\_ipv6\_cidr\_blocks) | The IPv6 CIDR blocks of the subnet group. | -| [memorydb\_subnet\_group\_arn](#output\_memorydb\_subnet\_group\_arn) | The ARN of the MemoryDB Subnet Group. | -| [memorydb\_subnet\_group\_id](#output\_memorydb\_subnet\_group\_id) | The ID of the MemoryDB Subnet Group. | +| [ipv4\_cidrs](#output\_ipv4\_cidrs) | The IPv4 CIDR blocks of the subnet group. | +| [ipv6\_address\_assignment](#output\_ipv6\_address\_assignment) | The configuration of IPv6 address assignment.
`enabled` - Whether to automatically assign IPv6 address to instances launched in the subnet group. | +| [ipv6\_cidrs](#output\_ipv6\_cidrs) | The IPv6 CIDR blocks of the subnet group. | +| [local\_network\_interface\_device\_index](#output\_local\_network\_interface\_device\_index) | The device position for local network interfaces in this subnet. | +| [memorydb\_subnet\_group](#output\_memorydb\_subnet\_group) | The configuration of MemoryDB Subnet Group.
`id` - The ID of the MemoryDB Subnet Group.
`arn` - The ARN of the MemoryDB Subnet Group.
`name` - The name of the MemoryDB Subnet Group.
`description` - The description of the MemoryDB Subnet Group. | | [name](#output\_name) | The name of the subnet group. | -| [neptune\_subnet\_group\_arn](#output\_neptune\_subnet\_group\_arn) | The ARN of the Neptune Subnet Group. | -| [neptune\_subnet\_group\_id](#output\_neptune\_subnet\_group\_id) | The ID of the Neptune DB Subnet Group. | -| [redshift\_subnet\_group\_arn](#output\_redshift\_subnet\_group\_arn) | The ARN of the Redshift Subnet Group. | -| [redshift\_subnet\_group\_id](#output\_redshift\_subnet\_group\_id) | The ID of the Redshift Subnet Group. | +| [neptune\_subnet\_group](#output\_neptune\_subnet\_group) | The configuration of Neptune Subnet Group.
`id` - The ID of the Neptune Subnet Group.
`arn` - The ARN of the Neptune Subnet Group.
`name` - The name of the Neptune Subnet Group.
`description` - The description of the Neptune Subnet Group. | +| [owner](#output\_owner) | The ID of the AWS account that owns subnets in the subnet group. | +| [public\_ipv4\_address\_assignment](#output\_public\_ipv4\_address\_assignment) | The configuration of public IPv4 address assignment.
`enabled` - Whether to automatically assign public IPv4 address to instances launched in the subnet group. | +| [rds\_subnet\_group](#output\_rds\_subnet\_group) | The configuration of RDS Subnet Group.
`id` - The ID of the RDS Subnet Group.
`arn` - The ARN of the RDS Subnet Group.
`name` - The name of the RDS Subnet Group.
`description` - The description of the RDS Subnet Group. | +| [redshift\_subnet\_group](#output\_redshift\_subnet\_group) | The configuration of Redshift Subnet Group.
`id` - The ID of the Redshift Subnet Group.
`arn` - The ARN of the Redshift Subnet Group.
`name` - The name of the Redshift Subnet Group.
`description` - The description of the Redshift Subnet Group. | | [subnets](#output\_subnets) | A list of subnets of the subnet group. | | [subnets\_by\_az](#output\_subnets\_by\_az) | A map of subnets of the subnet group which are grouped by availability zone id. | | [vpc\_id](#output\_vpc\_id) | The ID of the VPC which the subnet group belongs to. | diff --git a/modules/subnet-group/integrations.tf b/modules/subnet-group/integrations.tf new file mode 100644 index 0000000..f1eae91 --- /dev/null +++ b/modules/subnet-group/integrations.tf @@ -0,0 +1,169 @@ +################################################### +# Subnet Group for DAX +################################################### + +resource "aws_dax_subnet_group" "this" { + count = var.dax_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.dax_subnet_group.name, var.name) + description = var.dax_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + # INFO: Not support resource tags + # tags = {} +} + + +################################################### +# Subnet Group for DMS Replication +################################################### + +resource "aws_dms_replication_subnet_group" "this" { + count = var.dms_replication_subnet_group.enabled ? 1 : 0 + + replication_subnet_group_id = coalesce(var.dms_replication_subnet_group.name, var.name) + replication_subnet_group_description = var.dms_replication_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.dms_replication_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for DocumentDB +################################################### + +resource "aws_docdb_subnet_group" "this" { + count = var.docdb_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.docdb_subnet_group.name, var.name) + description = var.docdb_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.docdb_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for ElastiCache +################################################### + +resource "aws_elasticache_subnet_group" "this" { + count = var.elasticache_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.elasticache_subnet_group.name, var.name) + description = var.elasticache_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.elasticache_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for MemoryDB +################################################### + +resource "aws_memorydb_subnet_group" "this" { + count = var.memorydb_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.memorydb_subnet_group.name, var.name) + description = var.memorydb_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.memorydb_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for Neptune +################################################### + +resource "aws_neptune_subnet_group" "this" { + count = var.neptune_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.neptune_subnet_group.name, var.name) + description = var.neptune_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.neptune_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for RDS +################################################### + +resource "aws_db_subnet_group" "this" { + count = var.rds_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.rds_subnet_group.name, var.name) + description = var.rds_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.rds_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} + + +################################################### +# Subnet Group for Redshift +################################################### + +resource "aws_redshift_subnet_group" "this" { + count = var.redshift_subnet_group.enabled ? 1 : 0 + + name = coalesce(var.redshift_subnet_group.name, var.name) + description = var.redshift_subnet_group.description + + subnet_ids = values(aws_subnet.this)[*].id + + tags = merge( + { + "Name" = coalesce(var.redshift_subnet_group.name, var.name) + }, + local.module_tags, + var.tags, + ) +} diff --git a/modules/subnet-group/main.tf b/modules/subnet-group/main.tf index 4d51a2a..4506fce 100644 --- a/modules/subnet-group/main.tf +++ b/modules/subnet-group/main.tf @@ -14,6 +14,25 @@ locals { } : {} } +data "aws_availability_zones" "available" { + state = "available" +} + +locals { + available_availablity_zones = data.aws_availability_zones.available.names + available_availablity_zone_ids = data.aws_availability_zones.available.zone_ids + + az = { + for idx, id in local.available_availablity_zone_ids : + id => local.available_availablity_zones[idx] + } + + hostname_types = { + "RESOURCE_NAME" = "resource-name" + "IP_NAME" = "ip-name" + } +} + locals { availability_zones = distinct( values(aws_subnet.this)[*].availability_zone @@ -21,9 +40,6 @@ locals { availability_zone_ids = distinct( values(aws_subnet.this)[*].availability_zone_id ) -} - -locals { subnets = [ for subnet in aws_subnet.this : { id = subnet.id @@ -39,149 +55,85 @@ locals { ] } -resource "aws_subnet" "this" { - for_each = var.subnets - - vpc_id = var.vpc_id - availability_zone = lookup(each.value, "availability_zone", null) - availability_zone_id = lookup(each.value, "availability_zone_id", null) - - cidr_block = lookup(each.value, "cidr_block", "") - ipv6_cidr_block = lookup(each.value, "ipv6_cidr_block", null) - - map_public_ip_on_launch = var.map_public_ip_on_launch - assign_ipv6_address_on_creation = var.assign_ipv6_address_on_creation - - outpost_arn = var.outpost_arn - customer_owned_ipv4_pool = var.customer_owned_ipv4_pool - map_customer_owned_ip_on_launch = var.map_customer_owned_ip_on_launch - - tags = merge( - { - "Name" = each.key - }, - local.module_tags, - var.tags, - ) -} - ################################################### -# Subnet Groups for Managed Data Services +# Subnets of the Subnet Group ################################################### -resource "aws_db_subnet_group" "this" { - count = var.db_subnet_group_enabled ? 1 : 0 - - name = var.db_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id +# INFO: Not supported attributes +# - `availability_zone_id` +resource "aws_subnet" "this" { + for_each = var.subnets - tags = merge( - { - "Name" = var.db_subnet_group_name - }, - local.module_tags, - var.tags, + vpc_id = var.vpc_id + availability_zone = (each.value.availability_zone != null + ? each.value.availability_zone + : (each.value.availability_zone_id != null + ? local.az[each.value.availability_zone_id] + : null + ) ) -} -resource "aws_elasticache_subnet_group" "this" { - count = var.cache_subnet_group_enabled ? 1 : 0 + enable_lni_at_device_index = var.local_network_interface_device_index - name = var.cache_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - tags = merge( - { - "Name" = var.cache_subnet_group_name - }, - local.module_tags, - var.tags, - ) -} + ## IP CIDR Blocks + ipv6_native = each.value.type == "IPV6" -resource "aws_redshift_subnet_group" "this" { - count = var.redshift_subnet_group_enabled ? 1 : 0 + cidr_block = each.value.ipv4_cidr + ipv6_cidr_block = each.value.ipv6_cidr - name = var.redshift_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - tags = merge( - { - "Name" = var.redshift_subnet_group_name - }, - local.module_tags, - var.tags, + ## IP Assignments + map_public_ip_on_launch = (each.value.type == "IPV6" + ? false + : var.public_ipv4_address_assignment.enabled ) -} - -resource "aws_neptune_subnet_group" "this" { - count = var.neptune_subnet_group_enabled ? 1 : 0 - - name = var.neptune_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.neptune_subnet_group_name - }, - local.module_tags, - var.tags, + assign_ipv6_address_on_creation = (each.value.type == "IPV6" + ? true + : var.ipv6_address_assignment.enabled ) -} - -resource "aws_docdb_subnet_group" "this" { - count = var.docdb_subnet_group_enabled ? 1 : 0 - - name = var.docdb_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - tags = merge( - { - "Name" = var.docdb_subnet_group_name - }, - local.module_tags, - var.tags, + map_customer_owned_ip_on_launch = (each.value.type == "IPV6" + ? null + : (var.customer_owned_ipv4_address_assignment.enabled + ? true + : null + ) + ) + outpost_arn = (var.customer_owned_ipv4_address_assignment.enabled + ? var.customer_owned_ipv4_address_assignment.outpost + : null + ) + customer_owned_ipv4_pool = (var.customer_owned_ipv4_address_assignment.enabled + ? var.customer_owned_ipv4_address_assignment.pool + : null ) -} - -resource "aws_dax_subnet_group" "this" { - count = var.dax_subnet_group_enabled ? 1 : 0 - - name = var.dax_subnet_group_name - subnet_ids = values(aws_subnet.this)[*].id - - # INFO: Not support resource tags - # tags = {} -} - -resource "aws_dms_replication_subnet_group" "this" { - count = var.dms_replication_subnet_group_enabled ? 1 : 0 - - replication_subnet_group_id = var.dms_replication_subnet_group_name - replication_subnet_group_description = "Managed by Terraform." - subnet_ids = values(aws_subnet.this)[*].id - tags = merge( - { - "Name" = var.dms_replication_subnet_group_name - }, - local.module_tags, - var.tags, + ## DNS Configurations + private_dns_hostname_type_on_launch = (each.value.type == "IPV6" + ? "resource-name" + : local.hostname_types[var.dns_config.hostname_type] ) -} + enable_resource_name_dns_a_record_on_launch = (each.value.type == "IPV6" + ? false + : var.dns_config.dns_resource_name_ipv4_enabled + ) + enable_resource_name_dns_aaaa_record_on_launch = (each.value.type == "IPV6" + ? true + : var.dns_config.dns_resource_name_ipv6_enabled + ) + enable_dns64 = var.dns_config.dns64_enabled -resource "aws_memorydb_subnet_group" "this" { - count = var.memorydb_subnet_group_enabled ? 1 : 0 - name = var.memorydb_subnet_group_name - description = "Managed by Terraform." - subnet_ids = values(aws_subnet.this)[*].id + timeouts { + create = var.timeouts.create + delete = var.timeouts.delete + } tags = merge( { - "Name" = var.memorydb_subnet_group_name + "Name" = each.key }, local.module_tags, var.tags, diff --git a/modules/subnet-group/outputs.tf b/modules/subnet-group/outputs.tf index 381c981..a9d00d0 100644 --- a/modules/subnet-group/outputs.tf +++ b/modules/subnet-group/outputs.tf @@ -5,7 +5,7 @@ output "name" { output "vpc_id" { description = "The ID of the VPC which the subnet group belongs to." - value = var.vpc_id + value = values(aws_subnet.this)[0].vpc_id } output "ids" { @@ -18,12 +18,17 @@ output "arns" { value = values(aws_subnet.this)[*].arn } -output "cidr_blocks" { - description = "The CIDR blocks of the subnet group." - value = values(aws_subnet.this)[*].cidr_block +output "owner" { + description = "The ID of the AWS account that owns subnets in the subnet group." + value = values(aws_subnet.this)[0].owner_id } -output "ipv6_cidr_blocks" { +output "ipv4_cidrs" { + description = "The IPv4 CIDR blocks of the subnet group." + value = compact(values(aws_subnet.this)[*].cidr_block) +} + +output "ipv6_cidrs" { description = "The IPv6 CIDR blocks of the subnet group." value = compact(values(aws_subnet.this)[*].ipv6_cidr_block) } @@ -51,85 +56,209 @@ output "subnets_by_az" { } } -output "db_subnet_group_id" { - description = "The ID of the RDS Subnet Group." - value = one(aws_db_subnet_group.this[*].id) +output "local_network_interface_device_index" { + description = "The device position for local network interfaces in this subnet." + value = var.local_network_interface_device_index } -output "db_subnet_group_arn" { - description = "The ARN of the RDS Subnet Group." - value = one(aws_db_subnet_group.this[*].arn) +output "public_ipv4_address_assignment" { + description = < k + }[values(aws_subnet.this)[0].private_dns_hostname_type_on_launch] + dns_resource_name_ipv4_enabled = values(aws_subnet.this)[0].enable_resource_name_dns_a_record_on_launch + dns_resource_name_ipv6_enabled = values(aws_subnet.this)[0].enable_resource_name_dns_aaaa_record_on_launch + dns64_enabled = values(aws_subnet.this)[0].enable_dns64 + } } -output "neptune_subnet_group_id" { - description = "The ID of the Neptune DB Subnet Group." - value = one(aws_neptune_subnet_group.this[*].id) +output "dax_subnet_group" { + description = < 0 + error_message = "At least one subnet must be provided." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + contains(["DUALSTACK", "IPV6"], subnet.type) + ]) + error_message = "Valid values for `type` of each subnet are `DUALSTACK` and `IPV6`." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + subnet.ipv4_cidr != null + if subnet.type == "DUALSTACK" + ]) + error_message = "IPv4 CIDR block must be provided for `DUALSTACK` subnet." + } + validation { + condition = alltrue([ + for subnet in values(var.subnets) : + subnet.ipv6_cidr != null && subnet.ipv4_cidr == null + if subnet.type == "IPV6" + ]) + error_message = "IPv6 CIDR block must be provided for `IPV6` subnet." + } } -variable "customer_owned_ipv4_pool" { - description = "The customer owned IPv4 address pool. `outpost_arn` argument must be specified when configured." - type = string - default = "" +variable "local_network_interface_device_index" { + description = <