GCP Terraform: Unable to set subnets to be advertised via BGP on cloud router
I'm attempting to create a cloud router, with two network ranges being advertised from it, however I'm getting some very vague errors from terraform and I can't quite put my finger on what's wrong.
resource "google_compute_router" "router1" {
name = "${var.alias}-prod1-ha-vpn-cloud-router-1"
project = var.project_name
network = var.network1
region = var.region1
bgp {
asn = var.asn
advertise_mode = "CUSTOM"
dynamic "advertised_ip_ranges" {
for_each = var.advertised_ip_ranges_prod1
content {
range = advertised_ip_ranges_prod1.value["cidr"]
description = advertised_ip_ranges_prod1.value["desc"]
}
}
}
}
And the actual module code:
module "vpn-ha-gateway" {
source = "-----"
project_name = var.project_name
customer = var.customer
alias = var.alias
region1 = var.region1
count = (var.vpn_type == "ha-vpn" ? 1 : 0) ## Build if vpn_type is ha-vpn
network1 = module.prod1-vpc.self_link
customer_redundancy = var.customer_redundancy
customer_ha_vpn_peers = var.customer_ha_vpn_peers
shared_secret = var.shared_secret
asn = var.asn
cust_asn = var.cust_asn
advertised_ip_ranges_prod1 = var.advertised_ip_ranges_prod1
}
We define the advertised_ip_ranges_prod1 as a map, as we don't know how many there will be per module:
variable "advertised_ip_ranges_prod1" {
type = list(map(string))
description = "advertised by BGP on prod1"
default = [
{
cidr = "1.2.3.4/28" ## Prod1 advertised range
desc = "secondary range advertised via BGP"
},
{
cidr = "5.6.7.8/28" # Test advertised range
desc = "Test range advertised via BGP"
},
]
}
And while I have other modules built in the same way (with the for_each) working correctly, this one keeps throwing up these vague errors:
Error: Reference to undeclared resource
on .terraform\modules\vpn-ha\main.tf line 36, in resource "google_compute_router" "router1":
36: range = advertised_ip_ranges_prod1.value["cidr"]
A managed resource "advertised_ip_ranges_prod1" "value" has not been declared
in module.vpn-ha-gateway.
Error: Reference to undeclared resource
on .terraform\modules\vpn-ha-gateway\main.tf line 37, in resource "google_compute_router" "router1":
37: description = advertised_ip_ranges_prod1.value["desc"]
A managed resource "advertised_ip_ranges_prod1" "value" has not been declared
in module.vpn-ha-gateway.```
Solution 1:
So the issue (I think) is with how you reference the current iteration of the dynamic element from within the for_each
"block". In general, the name of the "variable" that you use to reference the current iterator value in the for_each
block is actually the name of the dynamic tag itself. As a result, I think you need to replace this:
resource "google_compute_router" "router1" {
name = "${var.alias}-prod1-ha-vpn-cloud-router-1"
project = var.project_name
network = var.network1
region = var.region1
bgp {
asn = var.asn
advertise_mode = "CUSTOM"
dynamic "advertised_ip_ranges" {
for_each = var.advertised_ip_ranges_prod1
content {
range = advertised_ip_ranges_prod1.value["cidr"]
description = advertised_ip_ranges_prod1.value["desc"]
}
}
}
}
With this:
resource "google_compute_router" "router1" {
name = "${var.alias}-prod1-ha-vpn-cloud-router-1"
project = var.project_name
network = var.network1
region = var.region1
bgp {
asn = var.asn
advertise_mode = "CUSTOM"
dynamic "advertised_ip_ranges" {
for_each = var.advertised_ip_ranges_prod1
content {
range = advertised_ip_ranges.value["cidr"]
description = advertised_ip_ranges.value["desc"]
}
}
}
}
e.g. s/advertised_ip_ranges_prod1/advertised_ip_ranges/
For reference, see the very first example on their documentation about this, which is the following:
resource "aws_elastic_beanstalk_environment" "tfenvtest" {
name = "tf-test-name"
application = "${aws_elastic_beanstalk_application.tftest.name}"
solution_stack_name = "64bit Amazon Linux 2018.03 v2.11.4 running Go 1.12.6"
dynamic "setting" {
for_each = var.settings
content {
namespace = setting.value["namespace"]
name = setting.value["name"]
value = setting.value["value"]
}
}
}
Note that they use setting.value
, even though the name of the variable is settings
. You're basically running into that exact same, rather confusing, difference.