Hi @mark.mcwiggins,
Again the formatting seems to have got messed up as you’ve transferred this into the forum, so I’m gonna post a tidied version so we can see what’s going on here:
resource "google_compute_backend_service" "default" {
provider = google-beta
for_each = var.backends
project = var.project
name = "${var.name}-backend-${each.key}"
description = lookup(each.value, "description", null)
connection_draining_timeout_sec = lookup(each.value, "connection_draining_timeout_sec", null)
enable_cdn = lookup(each.value, "enable_cdn", false)
custom_request_headers = lookup(each.value, "custom_request_headers", [])
custom_response_headers = lookup(each.value, "custom_response_headers", [])
# To achieve a null backend security_policy, set each.value.security_policy to "" (empty string), otherwise, it fallsback to var.security_policy.
security_policy = lookup(each.value, "security_policy") == "" ? null : (lookup(each.value, "security_policy") == null ? var.security_policy : each.value.security_policy)
dynamic "backend" {
for_each = toset(each.value["groups"])
content {
description = lookup(backend.value, "description", null)
group = lookup(backend.value, "group")
}
}
log_config {
enable = lookup(lookup(each.value, "log_config", {}), "enable", true)
sample_rate = lookup(lookup(each.value, "log_config", {}), "sample_rate", "1.0")
}
dynamic "iap" {
for_each = lookup(lookup(each.value, "iap_config", {}), "enable", false) ? [1] : []
content {
oauth2_client_id = lookup(lookup(each.value, "iap_config", {}), "oauth2_client_id", "")
oauth2_client_secret = lookup(lookup(each.value, "iap_config", {}), "oauth2_client_secret", "")
}
}
}
http_forward = true
https_redirect = true
create_address = true
project = "my-dev"
backends = {
"yobaby" = {
description = "my app"
enable_cdn = false
security_policy = ""
custom_request_headers = null
custom_response_headers = null
iap_config = {
enable = false
oauth2_client_id = ""
oauth2_client_secret = ""
}
log_config = {
enable = false
sample_rate = 0
}
groups = [
{
group = "google_compute_backend_service.default.id"
},
]
}
}
I’m guessing that the second block you included here is the content of a .tfvars
file you’re setting, or of a module
block where you called this module, and so the backends
map in there is what you’ve assigned to the resource for_each
in the first example.
I see inside your groups
list you’ve written a string containing something resembling a Terraform reference, but since it’s in quotes Terraform is just taking the literal string "google_compute_backend_service.default.id"
and assigning that to the group
argument, and so the remote API is rejecting it as an invalid URL.
I assume your intent here was to assign the value of the expression google_compute_backend_service.default.id
. If so, you’ll need to write that expression inside the module itself rather than inside the variables file, because the variables are outside the module, and so can’t refer to anything inside the module.
However, if I’m reading correctly then inlining that reference would cause the configuration of google_compute_backend_service.default
to be referring to itself, which isn’t possible because it requires Terraform to already know the result of creating that object before creating the object.
Given that, I think we need to take a step back here and first talk about the underlying problem you’re trying to solve. I’m afraid I’m not familiar with this resource type at all so I can’t infer from context why it would be necessary to use this object’s own ID as part of it’s own configuration; are you sure that’s the correct way to use this resource type? The documentation for this backend
block’s group
argument says:
group
- (Required) The fully-qualified URL of an Instance Group or Network Endpoint Group resource. In case of instance group this defines the list of instances that serve traffic. Member virtual machine instances from each instance group must live in the same zone as the instance group itself. No two backends in a backend service are allowed to use same Instance Group resource. For Network Endpoint Groups this defines list of endpoints. All endpoints of Network Endpoint Group must be hosted on instances located in the same zone as the Network Endpoint Group. Backend services cannot mix Instance Group and Network Endpoint Group backends. Note that you must specify an Instance Group or Network Endpoint Group resource using the fully-qualified URL, rather than a partial URL.
This suggests to me that this argument is expecting the URL/id of some other object… perhaps an instance of google_compute_instance_group
or of compute_network_endpoint_group
? If so, I think what you’d need to do here is make your variable include a lookup key for whatever other object it’s supposed to refer to, and then write an expression to look up the object using that key.
For example, perhaps inside your backends
variable you’d write something like this:
backends = {
"yobaby" = {
# (everything else unchanged)
groups = [
{
instance_group_key = "foo"
},
]
}
}
Then, in your resource configuration:
dynamic "backend" {
for_each = each.value["groups"]
content {
description = try(backend.value.description, null)
group = google_compute_instance_group.example[backend.value.instance_group_key].id
}
}
This assumes that you have a resource "google_compute_instance_group" "example"
block elsewhere in your module which also uses for_each
, and that “foo” is one of the keys in that resource’s for_each
expression. The input variable therefore specifies which of the instances of that resource to use, by including the lookup key by which we can find the corresponding id.