如何用Terraform实现3个VPC子网与7个CIDR的Client VPN路由?
The error you're seeing happens because the target_vpc_subnet_id argument in aws_ec2_client_vpn_route expects a single subnet ID string, but your code is passing a list of 3 subnet IDs (from data.aws_subnet.test_subnet.*.id). Terraform can't assign a list to a field that requires a single value, hence the type mismatch error.
To create a route for every combination of your 7 CIDRs and 3 subnets (total 21 routes), you need to generate all possible pairs of CIDRs and subnets, then create a route for each pair. Here's how to adjust your code:
Step 1: Generate All CIDR-Subnet Pairs
Use Terraform's setproduct function to create a list of every possible combination of your CIDR blocks and subnet IDs. Then convert this list into a map that can be used with for_each in the resource.
Add this locals block to your configuration:
locals { # Generate all pairs of CIDR blocks and subnet IDs cidr_subnet_pairs = { for pair in setproduct(keys(var.cidr_blocks), data.aws_subnet.test_subnet.*.id) : "${pair[0]}-${pair[1]}" => { cidr_block = pair[0] subnet_id = pair[1] } } }
Step 2: Update the Client VPN Route Resource
Modify your aws_ec2_client_vpn_route resource to iterate over the generated pairs instead of just the CIDR blocks:
resource "aws_ec2_client_vpn_route" "example" { for_each = local.cidr_subnet_pairs client_vpn_endpoint_id = aws_ec2_client_vpn_endpoint.test-vpn.id destination_cidr_block = each.value.cidr_block target_vpc_subnet_id = each.value.subnet_id }
What Changed?
setproduct: This function takes two lists (your CIDR keys and subnet IDs) and returns a list of all possible pairs (e.g.,["192.10.0.0/16", "subnet-abc123"],["192.10.0.0/16", "subnet-def456"], etc.).for_eachon the pairs: By iterating over the map of pairs, we create a separateaws_ec2_client_vpn_routeresource for each combination. Each route gets a unique CIDR and subnet ID, matching your requirement of every CIDR connected to every subnet.- Type correction: Now
target_vpc_subnet_idreceives a single subnet ID string per resource, which matches the expected attribute type.
Optional: Clean Up the Output
Your current output "subnet_cidr_blocks" is wrapping the subnet IDs in an extra list. You can simplify it to:
output "subnet_cidr_blocks" { value = data.aws_subnet.test_subnet.*.id }
This will output a flat list of subnet IDs instead of a list containing another list.
内容的提问来源于stack exchange,提问作者highfive

