Skip to content

Commit 9bd4853

Browse files
committed
feat: Add support for per subnet tags
1 parent a0307d4 commit 9bd4853

File tree

5 files changed

+240
-2
lines changed

5 files changed

+240
-2
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ No modules.
401401
| <a name="input_database_subnet_private_dns_hostname_type_on_launch"></a> [database\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_database\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
402402
| <a name="input_database_subnet_suffix"></a> [database\_subnet\_suffix](#input\_database\_subnet\_suffix) | Suffix to append to database subnets name | `string` | `"db"` | no |
403403
| <a name="input_database_subnet_tags"></a> [database\_subnet\_tags](#input\_database\_subnet\_tags) | Additional tags for the database subnets | `map(string)` | `{}` | no |
404+
| <a name="input_database_subnet_tags_by_name"></a> [database\_subnet\_tags\_by\_name](#input\_database\_subnet\_tags\_by\_name) | Additional tags for the database subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
404405
| <a name="input_database_subnets"></a> [database\_subnets](#input\_database\_subnets) | A list of database subnets inside the VPC | `list(string)` | `[]` | no |
405406
| <a name="input_default_network_acl_egress"></a> [default\_network\_acl\_egress](#input\_default\_network\_acl\_egress) | List of maps of egress rules to set on the Default Network ACL | `list(map(string))` | <pre>[<br/> {<br/> "action": "allow",<br/> "cidr_block": "0.0.0.0/0",<br/> "from_port": 0,<br/> "protocol": "-1",<br/> "rule_no": 100,<br/> "to_port": 0<br/> },<br/> {<br/> "action": "allow",<br/> "from_port": 0,<br/> "ipv6_cidr_block": "::/0",<br/> "protocol": "-1",<br/> "rule_no": 101,<br/> "to_port": 0<br/> }<br/>]</pre> | no |
406407
| <a name="input_default_network_acl_ingress"></a> [default\_network\_acl\_ingress](#input\_default\_network\_acl\_ingress) | List of maps of ingress rules to set on the Default Network ACL | `list(map(string))` | <pre>[<br/> {<br/> "action": "allow",<br/> "cidr_block": "0.0.0.0/0",<br/> "from_port": 0,<br/> "protocol": "-1",<br/> "rule_no": 100,<br/> "to_port": 0<br/> },<br/> {<br/> "action": "allow",<br/> "from_port": 0,<br/> "ipv6_cidr_block": "::/0",<br/> "protocol": "-1",<br/> "rule_no": 101,<br/> "to_port": 0<br/> }<br/>]</pre> | no |
@@ -442,6 +443,7 @@ No modules.
442443
| <a name="input_elasticache_subnet_private_dns_hostname_type_on_launch"></a> [elasticache\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_elasticache\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
443444
| <a name="input_elasticache_subnet_suffix"></a> [elasticache\_subnet\_suffix](#input\_elasticache\_subnet\_suffix) | Suffix to append to elasticache subnets name | `string` | `"elasticache"` | no |
444445
| <a name="input_elasticache_subnet_tags"></a> [elasticache\_subnet\_tags](#input\_elasticache\_subnet\_tags) | Additional tags for the elasticache subnets | `map(string)` | `{}` | no |
446+
| <a name="input_elasticache_subnet_tags_by_name"></a> [elasticache\_subnet\_tags\_by\_name](#input\_elasticache\_subnet\_tags\_by\_name) | Additional tags for the elasticache subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
445447
| <a name="input_elasticache_subnets"></a> [elasticache\_subnets](#input\_elasticache\_subnets) | A list of elasticache subnets inside the VPC | `list(string)` | `[]` | no |
446448
| <a name="input_enable_dhcp_options"></a> [enable\_dhcp\_options](#input\_enable\_dhcp\_options) | Should be true if you want to specify a DHCP options set with a custom domain name, DNS servers, NTP servers, netbios servers, and/or netbios server type | `bool` | `false` | no |
447449
| <a name="input_enable_dns_hostnames"></a> [enable\_dns\_hostnames](#input\_enable\_dns\_hostnames) | Should be true to enable DNS hostnames in the VPC | `bool` | `true` | no |
@@ -488,6 +490,7 @@ No modules.
488490
| <a name="input_intra_subnet_private_dns_hostname_type_on_launch"></a> [intra\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_intra\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
489491
| <a name="input_intra_subnet_suffix"></a> [intra\_subnet\_suffix](#input\_intra\_subnet\_suffix) | Suffix to append to intra subnets name | `string` | `"intra"` | no |
490492
| <a name="input_intra_subnet_tags"></a> [intra\_subnet\_tags](#input\_intra\_subnet\_tags) | Additional tags for the intra subnets | `map(string)` | `{}` | no |
493+
| <a name="input_intra_subnet_tags_by_name"></a> [intra\_subnet\_tags\_by\_name](#input\_intra\_subnet\_tags\_by\_name) | Additional tags for the intra subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
491494
| <a name="input_intra_subnets"></a> [intra\_subnets](#input\_intra\_subnets) | A list of intra subnets inside the VPC | `list(string)` | `[]` | no |
492495
| <a name="input_ipv4_ipam_pool_id"></a> [ipv4\_ipam\_pool\_id](#input\_ipv4\_ipam\_pool\_id) | (Optional) The ID of an IPv4 IPAM pool you want to use for allocating this VPC's CIDR | `string` | `null` | no |
493496
| <a name="input_ipv4_netmask_length"></a> [ipv4\_netmask\_length](#input\_ipv4\_netmask\_length) | (Optional) The netmask length of the IPv4 CIDR you want to allocate to this VPC. Requires specifying a ipv4\_ipam\_pool\_id | `number` | `null` | no |
@@ -522,6 +525,7 @@ No modules.
522525
| <a name="input_outpost_subnet_private_dns_hostname_type_on_launch"></a> [outpost\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_outpost\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
523526
| <a name="input_outpost_subnet_suffix"></a> [outpost\_subnet\_suffix](#input\_outpost\_subnet\_suffix) | Suffix to append to outpost subnets name | `string` | `"outpost"` | no |
524527
| <a name="input_outpost_subnet_tags"></a> [outpost\_subnet\_tags](#input\_outpost\_subnet\_tags) | Additional tags for the outpost subnets | `map(string)` | `{}` | no |
528+
| <a name="input_outpost_subnet_tags_by_name"></a> [outpost\_subnet\_tags\_by\_name](#input\_outpost\_subnet\_tags\_by\_name) | Additional tags for the outpost subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
525529
| <a name="input_outpost_subnets"></a> [outpost\_subnets](#input\_outpost\_subnets) | A list of outpost subnets inside the VPC | `list(string)` | `[]` | no |
526530
| <a name="input_private_acl_tags"></a> [private\_acl\_tags](#input\_private\_acl\_tags) | Additional tags for the private subnets network ACL | `map(string)` | `{}` | no |
527531
| <a name="input_private_dedicated_network_acl"></a> [private\_dedicated\_network\_acl](#input\_private\_dedicated\_network\_acl) | Whether to use dedicated network ACL (not default) and custom rules for private subnets | `bool` | `false` | no |
@@ -538,6 +542,7 @@ No modules.
538542
| <a name="input_private_subnet_private_dns_hostname_type_on_launch"></a> [private\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_private\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
539543
| <a name="input_private_subnet_suffix"></a> [private\_subnet\_suffix](#input\_private\_subnet\_suffix) | Suffix to append to private subnets name | `string` | `"private"` | no |
540544
| <a name="input_private_subnet_tags"></a> [private\_subnet\_tags](#input\_private\_subnet\_tags) | Additional tags for the private subnets | `map(string)` | `{}` | no |
545+
| <a name="input_private_subnet_tags_by_name"></a> [private\_subnet\_tags\_by\_name](#input\_private\_subnet\_tags\_by\_name) | Additional tags for the private subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
541546
| <a name="input_private_subnet_tags_per_az"></a> [private\_subnet\_tags\_per\_az](#input\_private\_subnet\_tags\_per\_az) | Additional tags for the private subnets where the primary key is the AZ | `map(map(string))` | `{}` | no |
542547
| <a name="input_private_subnets"></a> [private\_subnets](#input\_private\_subnets) | A list of private subnets inside the VPC | `list(string)` | `[]` | no |
543548
| <a name="input_propagate_intra_route_tables_vgw"></a> [propagate\_intra\_route\_tables\_vgw](#input\_propagate\_intra\_route\_tables\_vgw) | Should be true if you want route table propagation | `bool` | `false` | no |
@@ -559,6 +564,7 @@ No modules.
559564
| <a name="input_public_subnet_suffix"></a> [public\_subnet\_suffix](#input\_public\_subnet\_suffix) | Suffix to append to public subnets name | `string` | `"public"` | no |
560565
| <a name="input_public_subnet_tags"></a> [public\_subnet\_tags](#input\_public\_subnet\_tags) | Additional tags for the public subnets | `map(string)` | `{}` | no |
561566
| <a name="input_public_subnet_tags_per_az"></a> [public\_subnet\_tags\_per\_az](#input\_public\_subnet\_tags\_per\_az) | Additional tags for the public subnets where the primary key is the AZ | `map(map(string))` | `{}` | no |
567+
| <a name="input_public_subnet_tags_by_name"></a> [public\_subnet\_tags\_by\_name](#input\_public\_subnet\_tags\_by\_name) | Additional tags for the public subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
562568
| <a name="input_public_subnets"></a> [public\_subnets](#input\_public\_subnets) | A list of public subnets inside the VPC | `list(string)` | `[]` | no |
563569
| <a name="input_putin_khuylo"></a> [putin\_khuylo](#input\_putin\_khuylo) | Do you agree that Putin doesn't respect Ukrainian sovereignty and territorial integrity? More info: https://en.wikipedia.org/wiki/Putin_khuylo! | `bool` | `true` | no |
564570
| <a name="input_redshift_acl_tags"></a> [redshift\_acl\_tags](#input\_redshift\_acl\_tags) | Additional tags for the redshift subnets network ACL | `map(string)` | `{}` | no |
@@ -578,6 +584,7 @@ No modules.
578584
| <a name="input_redshift_subnet_private_dns_hostname_type_on_launch"></a> [redshift\_subnet\_private\_dns\_hostname\_type\_on\_launch](#input\_redshift\_subnet\_private\_dns\_hostname\_type\_on\_launch) | 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. For dual-stack and IPv4-only subnets, you can specify whether DNS names use the instance IPv4 address or the instance ID. Valid values: `ip-name`, `resource-name` | `string` | `null` | no |
579585
| <a name="input_redshift_subnet_suffix"></a> [redshift\_subnet\_suffix](#input\_redshift\_subnet\_suffix) | Suffix to append to redshift subnets name | `string` | `"redshift"` | no |
580586
| <a name="input_redshift_subnet_tags"></a> [redshift\_subnet\_tags](#input\_redshift\_subnet\_tags) | Additional tags for the redshift subnets | `map(string)` | `{}` | no |
587+
| <a name="input_redshift_subnet_tags_by_name"></a> [redshift\_subnet\_tags\_by\_name](#input\_redshift\_subnet\_tags\_by\_name) | Additional tags for the redshift subnets where the primary key is the subnet name | `map(map(string))` | `{}` | no |
581588
| <a name="input_redshift_subnets"></a> [redshift\_subnets](#input\_redshift\_subnets) | A list of redshift subnets inside the VPC | `list(string)` | `[]` | no |
582589
| <a name="input_reuse_nat_ips"></a> [reuse\_nat\_ips](#input\_reuse\_nat\_ips) | Should be true if you don't want EIPs to be created for your NAT Gateways and will instead pass them in via the 'external\_nat\_ip\_ids' variable | `bool` | `false` | no |
583590
| <a name="input_secondary_cidr_blocks"></a> [secondary\_cidr\_blocks](#input\_secondary\_cidr\_blocks) | List of secondary CIDR blocks to associate with the VPC to extend the IP Address pool | `list(string)` | `[]` | no |

examples/per-subnet-tags/main.tf

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
provider "aws" {
2+
region = local.region
3+
}
4+
5+
data "aws_availability_zones" "available" {}
6+
7+
locals {
8+
name = "ex-${basename(path.cwd)}"
9+
region = "eu-west-1"
10+
11+
vpc_cidr = "10.0.0.0/16"
12+
azs = slice(data.aws_availability_zones.available.names, 0, 3)
13+
14+
public_subnet_names = [
15+
"puba", "pubb", "pubc",
16+
]
17+
public_subnet_tags_by_name = {
18+
"puba" = { "test" = "puba", "custom" = "foobar" },
19+
"pubb" = { "test" = "pubb" },
20+
"pubc" = { "test" = "pubc" },
21+
}
22+
23+
private_subnet_names = [
24+
"priva", "privb", "privc",
25+
"privd", "prive", "privf",
26+
]
27+
private_subnet_tags_by_name = {
28+
"priva" = { "test" = "priva" },
29+
"privb" = { "test" = "privb", "custom" = "private-b-tag" },
30+
"privc" = { "test" = "privc" },
31+
}
32+
33+
database_subnet_names = ["dba", "dbb", "dbc"]
34+
database_subnet_tags_by_name = {
35+
"dba" = { "test" = "dba" }
36+
"dbb" = { "test" = "dbb" }
37+
"dbc" = { "test" = "dbc", "custom" = "more-tests" }
38+
}
39+
40+
elasticache_subnet_names = ["eca", "ecb", "ecc", "ecd", "ece", "ecf"]
41+
elasticache_subnet_tags_by_name = {
42+
"eca" = { "test" = "eca" },
43+
"ecb" = { "test" = "ecb" },
44+
"ecc" = { "test" = "ecc", "custom" = "elasticache-test" },
45+
}
46+
47+
intra_subnet_names = ["inta", "intb", "intc"]
48+
intra_subnet_tags_by_name = {
49+
"inta" = { "test" = "inta", "custom" = "intra-subnet-tag" },
50+
"intb" = { "test" = "intb" },
51+
"intc" = { "test" = "intc" },
52+
}
53+
54+
tags = {
55+
Example = local.name
56+
GithubRepo = "terraform-aws-vpc"
57+
GithubOrg = "terraform-aws-modules"
58+
}
59+
}
60+
61+
################################################################################
62+
# VPC Module
63+
################################################################################
64+
65+
module "vpc" {
66+
source = "../../"
67+
68+
name = local.name
69+
cidr = local.vpc_cidr
70+
71+
azs = local.azs
72+
73+
private_subnet_names = local.private_subnet_names
74+
private_subnets = [for k, v in local.private_subnet_names : cidrsubnet(local.vpc_cidr, 4, k)]
75+
private_subnet_tags_by_name = local.private_subnet_tags_by_name
76+
77+
public_subnet_names = local.public_subnet_names
78+
public_subnets = [for k, v in local.public_subnet_names : cidrsubnet(local.vpc_cidr, 4, k)]
79+
public_subnet_tags_by_name = local.public_subnet_tags_by_name
80+
81+
database_subnet_names = local.database_subnet_names
82+
database_subnets = [for k, v in local.database_subnet_names : cidrsubnet(local.vpc_cidr, 4, k)]
83+
database_subnet_tags_by_name = local.database_subnet_tags_by_name
84+
85+
elasticache_subnet_names = local.elasticache_subnet_names
86+
elasticache_subnets = [for k, v in local.elasticache_subnet_names : cidrsubnet(local.vpc_cidr, 4, k)]
87+
elasticache_subnet_tags_by_name = local.elasticache_subnet_tags_by_name
88+
89+
intra_subnet_names = local.intra_subnet_names
90+
intra_subnets = [for k, v in local.intra_subnet_names : cidrsubnet(local.vpc_cidr, 4, k)]
91+
intra_subnet_tags_by_name = local.intra_subnet_tags_by_name
92+
93+
tags = local.tags
94+
}

examples/per-subnet-tags/versions.tf

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
terraform {
2+
required_version = ">= 1.0"
3+
4+
required_providers {
5+
aws = {
6+
source = "hashicorp/aws"
7+
version = ">= 6.0"
8+
}
9+
}
10+
}

main.tf

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,19 @@ resource "aws_subnet" "public" {
153153
},
154154
var.tags,
155155
var.public_subnet_tags,
156-
lookup(var.public_subnet_tags_per_az, element(var.azs, count.index), {})
156+
lookup(var.public_subnet_tags_per_az, element(var.azs, count.index), {}),
157+
try(
158+
# lookup any tags we have configured for subnet
159+
var.public_subnet_tags_by_name[
160+
# determine the name of this subnet (same as above Name = try(..) block)
161+
try(
162+
var.public_subnet_names[count.index],
163+
format("${var.name}-${var.public_subnet_suffix}-%s", element(var.azs, count.index))
164+
)
165+
],
166+
# default to {} if none are found
167+
{}
168+
)
157169
)
158170
}
159171

@@ -288,7 +300,19 @@ resource "aws_subnet" "private" {
288300
},
289301
var.tags,
290302
var.private_subnet_tags,
291-
lookup(var.private_subnet_tags_per_az, element(var.azs, count.index), {})
303+
lookup(var.private_subnet_tags_per_az, element(var.azs, count.index), {}),
304+
try(
305+
# lookup any tags we have configured for subnet
306+
var.private_subnet_tags_by_name[
307+
# determine the name of this subnet (same as above Name = try(..) block)
308+
try(
309+
var.private_subnet_names[count.index],
310+
format("${var.name}-${var.private_subnet_suffix}-%s", element(var.azs, count.index))
311+
)
312+
],
313+
# default to {} if none are found
314+
{}
315+
)
292316
)
293317
}
294318

@@ -408,6 +432,18 @@ resource "aws_subnet" "database" {
408432
},
409433
var.tags,
410434
var.database_subnet_tags,
435+
try(
436+
# lookup any tags we have configured for subnet
437+
var.database_subnet_tags_by_name[
438+
# determine the name of this subnet (same as above Name = try(..) block)
439+
try(
440+
var.database_subnet_names[count.index],
441+
format("${var.name}-${var.database_subnet_suffix}-%s", element(var.azs, count.index))
442+
)
443+
],
444+
# default to {} if none are found
445+
{}
446+
)
411447
)
412448
}
413449

@@ -590,6 +626,18 @@ resource "aws_subnet" "redshift" {
590626
},
591627
var.tags,
592628
var.redshift_subnet_tags,
629+
try(
630+
# lookup any tags we have configured for subnet
631+
var.redshift_subnet_tags_by_name[
632+
# determine the name of this subnet (same as above Name = try(..) block)
633+
try(
634+
var.redshift_subnet_names[count.index],
635+
format("${var.name}-${var.redshift_subnet_suffix}-%s", element(var.azs, count.index))
636+
)
637+
],
638+
# default to {} if none are found
639+
{}
640+
)
593641
)
594642
}
595643

@@ -727,6 +775,18 @@ resource "aws_subnet" "elasticache" {
727775
},
728776
var.tags,
729777
var.elasticache_subnet_tags,
778+
try(
779+
# lookup any tags we have configured for subnet
780+
var.elasticache_subnet_tags_by_name[
781+
# determine the name of this subnet (same as above Name = try(..) block)
782+
try(
783+
var.elasticache_subnet_names[count.index],
784+
format("${var.name}-${var.elasticache_subnet_suffix}-%s", element(var.azs, count.index))
785+
)
786+
],
787+
# default to {} if none are found
788+
{}
789+
)
730790
)
731791
}
732792

@@ -856,6 +916,18 @@ resource "aws_subnet" "intra" {
856916
},
857917
var.tags,
858918
var.intra_subnet_tags,
919+
try(
920+
# lookup any tags we have configured for subnet
921+
var.intra_subnet_tags_by_name[
922+
# determine the name of this subnet (same as above Name = try(..) block)
923+
try(
924+
var.intra_subnet_names[count.index],
925+
format("${var.name}-${var.intra_subnet_suffix}-%s", element(var.azs, count.index))
926+
)
927+
],
928+
# default to {} if none are found
929+
{}
930+
)
859931
)
860932
}
861933

@@ -976,6 +1048,18 @@ resource "aws_subnet" "outpost" {
9761048
},
9771049
var.tags,
9781050
var.outpost_subnet_tags,
1051+
try(
1052+
# lookup any tags we have configured for subnet
1053+
var.outpost_subnet_tags_by_name[
1054+
# determine the name of this subnet (same as above Name = try(..) block)
1055+
try(
1056+
var.outpost_subnet_names[count.index],
1057+
format("${var.name}-${var.outpost_subnet_suffix}-%s", element(var.azs, count.index))
1058+
)
1059+
],
1060+
# default to {} if none are found
1061+
{}
1062+
)
9791063
)
9801064
}
9811065

0 commit comments

Comments
 (0)