Error: Invalid expression

Hello,

I am looking for some inputs to fix below error using depend_on in the below configuration :-

error :

Error: Invalid expression

  on ../../modules/az-IOT/IOT.tf line 41, in resource "azurerm_iothub_shared_access_policy" "sap":
  41:     azurerm_iothub.IOTHubs["${each.value}"]

A single static variable reference is required: only attribute access and
indexing with constant keys. No calculations, function calls, template
expressions, etc are allowed here.

Configurations :


locals {
  apps = toset([
    "proj1",
    "proj2"
  ])
}

resource "azurerm_iothub_shared_access_policy" "sap" {
  name = "accesspolicy"

  for_each            = local.apps
  resource_group_name = "wp-${each.value}-${var.TF_VAR_system}"
  iothub_name         = "${each.key}-${var.TF_VAR_system}"

  registry_read   = true
  registry_write  = true
  service_connect = true
  device_connect  = true
  depends_on = [
    azurerm_iothub.IOTHubs["${each.value}"]
  ]
}

kindly suggest a way to do it , how to use depends_on in a loop .

Thanks !

Hi @Snehil03,

Dependencies in Terraform are between entire resources rather than individual instances of resources, so specifying a specific instance like you are trying here would not have any different effect than just depending on the resource as a whole:

  depends_on = [
    azurerm_iothub.IOTHubs,
  ]

Terraform resolves dependencies before it evaluates count or for_each, and so it’s not meaningful to declare a dependency on a specify instance of a resource: Terraform doesn’t know yet which instances will exist at the point when it’s building the dependency graph.

With that said, it seems like your azurerm_iothub_shared_access_policy has a natural dependency on the corresponding azurerm_iothub anyway, so in this situation I would prefer not to use depends_on and to use references within the main configuration instead:

resource "azurerm_iothub_shared_access_policy" "sap" {
  for_each = azurerm_iothub.IOTHubs

  name                = "accesspolicy"
  resource_group_name = each.value.resource_group_name
  iothub_name         = each.value.name
  # ....

  # NOTE: no depends_on needed here, because for_each
  # already declared the needed dependency.
}

The above is an example of chaining for_each between resources: it concisely says that there should be one azurerm_iothub_shared_access_policy for each instance of azurerm_iothub.IOTHubs, which both implicitly declares the dependency on azurerm_iothub.IOTHubs and allows you to use each.value to refer to the azurerm_iothub objects in a more straightforward way.

Hi @apparentlymart ,

Indeed , Ideally I should not use the depends_on because for_each is used but somehow when resources are getting created , I am creating resource_group, IOT hub and then the shared access policies on the hub , but when I executed the created plan it gave error at first :

resource_group not available, on re-execution it gave me error like IOT hub not available ,
hence planning to add the depends_on value as somehow dependency graph not able to get all the executed details .

additional details : 
terraform : 0.13.2
arurerm : 2.40.0

Hi @Snehil03,

From Terraform’s perspective there’s no significant difference between an implied and an explicit dependency, so I think something else must’ve caused the difference you observed, separately from the dependency declarations.

For example, perhaps the remote API behind these operations is not immediately consistent and so there was some undefined delay after the API reported the object created before a call to read the object would agree that the object existed. If so, that can cause intermittent errors that aren’t easy to reproduce, but writing the same dependency in a different way won’t change whether it’ll happen or not.

If this problem is related to consistency in the remote system then only a change to the provider code could potentially help with it, if there is some way for the API client in the provider to check when the remote API has achieved consistency.

1 Like