Help: Invalid template interpolation value

I have a module that creates a role assignment as part of the deploy.
For the scope im trying to say:

  • If the function app has “acc” or “prd” in the name:
    • To grant the principal ID to the slot
  • If it is named anything else:
    • Grant the principal ID access to the function app itself

Here’s the code from the module:

resource "azurerm_role_assignment" "ra" {
  scope               = element(split("-", var.function_app_name), 1) == "acc" || element(split("-", var.function_app_name), 1) == "prd" ? join(azurerm_function_app.funcapp.id, "/slots/${var.function_app_name}-Stg") : azurerm_function_app.funcapp.id
  role_definition_id  = data.azurerm_role_definition.rd.id
  principal_id        = var.role_assignment_principal_id
  depends_on          = [azurerm_function_app.funcapp]
}

When i run terraform apply i get this error:

Error: Invalid template interpolation value: Cannot include the given value in a string template: string required.

Any suggestions on how to get it working?

My guess is it is this part that it does not like:
join(azurerm_function_app.funcapp.id, "/slots/${var.function_app_name}-Stg")

Hi @midacts!

Since the error message is talking about “template interpolation”, we can narrow the scope of the problem down to the only template interpolation sequence in your configuration snippet:

"/slots/${var.function_app_name}-Stg"

The ${var.function_app_name} part of this is the interpolation sequence, and so the “interpolation value” mentioned in the error message is the result of var.function_app_name. The error is reporting that the value of var.function_app_name is not a string or something that can convert automatically to a string.

However, the other thing that seems strange to me here is that both of your arguments to join seem to be strings, but Terraform requires the second argument to be a list. This makes me wonder if you were intending to join together some transformations of the elements of a list in var.function_app_name.

Could you show the declaration of var.function_app_name and maybe also what value you were hoping to get from join(azurerm_function_app.funcapp.id, "/slots/${var.function_app_name}-Stg"? Hopefully then I can suggest a different way to write it to get the behavior you are looking for. Thanks!

I am intending to join the function app’s ID with the function app’s slot name to get the ID of the function app slot.

It is a hack solution as function app slots (and technically function apps for that matter) currently are not working properly in production Terraform.

var.function_app_name would be something like “funcapp-test”

This works for regular web apps:

function app slots are not currently working. So i am having to use a local-exec provisioner to use PowerShell to create the slot after the function app.

Because of that I cannot use this:
azurerm_app_service_slot.slot.id : azurerm_app_service.appservice.id

resource "azurerm_app_service" "appservice" {
  name                    = var.app_service_name
  location                = data.azurerm_resource_group.rg.location
  resource_group_name     = data.azurerm_resource_group.rg.name
  app_service_plan_id     = data.azurerm_app_service_plan.asp.id
  client_affinity_enabled = var.client_affinity_enabled
  https_only              = var.https_only
  app_settings            = local.appsettings
  dynamic "connection_string" {
    for_each = var.connection_string
    content {
      name  = connection_string.value.name
      type  = connection_string.value.type
      value = connection_string.value.value
    }
  }
  tags       = var.tags
  depends_on = [azurerm_application_insights.ai]

  site_config {
    use_32_bit_worker_process = var.worker_32bit
    websockets_enabled        = var.websockets_enabled
    php_version               = "5.6"
  }
}

resource "azurerm_app_service_slot" "slot" {
  name                = "${var.app_service_name}-Stg"
  app_service_name    = azurerm_app_service.appservice.name
  location            = data.azurerm_resource_group.rg.location
  resource_group_name = data.azurerm_resource_group.rg.name
  app_service_plan_id = data.azurerm_app_service_plan.asp.id
  app_settings        = local.appsettings_slot
  dynamic "connection_string" {
    for_each = var.connection_string_slot
    content {
      name  = connection_string.value.name
      type  = connection_string.value.type
      value = connection_string.value.value
    }
  }
  tags       = var.tags
  depends_on = [azurerm_app_service.appservice]

  site_config {
    use_32_bit_worker_process = var.worker_32bit
    websockets_enabled        = var.websockets_enabled
    php_version               = "5.6"
  }
}

resource "azurerm_role_assignment" "ra" {
  scope               = element(split("-", var.app_service_name), 1) == "acc" || element(split("-", var.app_service_name), 1) == "prd" ? azurerm_app_service_slot.slot.id : azurerm_app_service.appservice.id
  role_definition_id  = data.azurerm_role_definition.rd.id
  principal_id        = var.role_assignment_principal_id
  depends_on          = [azurerm_app_service_slot.slot]
}