I have two resources (Azure Function app) that need to set a variable setting depending on the other resource, like this:
resource "azurerm_function_app" "A" {
name = "A"
location = azurerm_resource_group.$(environment).location
resource_group_name = azurerm_resource_group.$(environment).name
app_service_plan_id = azurerm_app_service_plan.$(environment).id
version = "~3"
app_settings = {
"url" = "${azurerm_api_management.$(environment).gateway_url}/${azurerm_function_app.B.name}/"
}
}
resource "azurerm_function_app" "B" {
name = "B"
location = azurerm_resource_group.$(environment).location
resource_group_name = azurerm_resource_group.$(environment).name
app_service_plan_id = azurerm_app_service_plan.$(environment).id
version = "~3"
app_settings = {
"url" = "${azurerm_api_management.$(environment).gateway_url}/${azurerm_function_app.A.name}/"
}
}
is there any way to resolve this?
thanks.
Hi @Cesarfgc,
In order to look up objects by a dynamic key you will need to put them into a map and then access the map by key.
I’m not sure what exactly you intended “environment” to be here, so I expect there’s probably a less verbose way to get this done if you can share some more details about the context around this, but a direct answer to this would be a map like the following which groups together the objects by environment:
locals {
envs = tomap({
production = {
resource_group = azurerm_resource_group.production
app_service_plan = azurerm_app_service_plan.production
}
staging = {
resource_group = azurerm_resource_group.staging
app_service_plan = azurerm_app_service_plan.staging
}
})
}
If environment
here is intended to be an input variable then you could then access these with expressions like this:
local.envs[var.environment].resource_group
local.envs[var.environment].app_service_plan
If your intention was instead to create an azurerm_function_app
per environment then I would suggest a different approach, but I’ll wait for you to share some more details about what you are intending before I write all that out too.
Thanks @apparentlymart for quick response.
My example was not so clear I think.
The main problem is that resource A needs resource B name for url setting and resource B requires resource A name for url setting as well so both are depending each other.
So I was looking a way to first create both resource and then update url property if that is possible or there is any other option.
Thanks, regards.
Ahh, I’m sorry I misunderstood your question!
There isn’t any automatic way to deal with this sort of situation where two operations depend on one another. However, since it seems like the name
of each of those functions is set directly in your configuration rather than chosen by the remote system, you perhaps don’t need to access it via a reference like that. For example:
app_settings = {
url = "${azurerm_api_management.production.gateway_url}/B/"
}
Specifying the name directly like this, rather than using a dependency, does mean that there will necessarily be a brief period while initially creating these objects where one of the objects is configured with a URL that doesn’t work yet, so this may require some extra care elsewhere in your system to be resilient to that situation and wait for the system to reach a complete, valid state before beginning work. What exactly that means will of course depend on what exactly these apps do.
If in your real system these names are populated in a more complicated way than just a fixed name then you could get a similar effect by factoring them out into a local value:
locals {
app_names = tomap({
A = "A"
B = "B"
})
}
resource "azurerm_function_app" "A" {
name = local.app_names["A"]
# ...
app_settings = {
url = "${azurerm_api_management.production.gateway_url}/${local.app_names["B"]}/"
}
}
resource "azurerm_function_app" "B" {
name = local.app_names["B"]
# ...
app_settings = {
url = "${azurerm_api_management.production.gateway_url}/${local.app_names["A"]}/"
}
}
Here both of the resources depend on local.app_names
, avoiding the need to duplicate the expressions that define the two names, but they no longer depend on one another.
1 Like