1

How to use local value in variables.tf?

I need to assign dynamically value to threshold for two of netapp volume metric alert and I get an error: Error: Variables not allowed. Each NetApp Volume has different storage quota in GB, that's why it needs to be dynamic.

NetApp Volume code:

main.tf

locals {
  iops_80 = format("%.0f", (var.storage_quota_in_gb * 1.6))
}

resource "azurerm_netapp_volume" "netapp_volume" {
  name                = var.netapp_vol_name
  resource_group_name = var.resource_group_name
  location            = var.location
  account_name        = var.account_name
  pool_name           = var.pool_name
  volume_path         = var.volume_path
  service_level       = var.service_level
  subnet_id           = var.subnet_id
  storage_quota_in_gb = var.storage_quota_in_gb
  protocols           = var.protocols

  dynamic "export_policy_rule" {
    for_each = var.export_policy_rules
    content {
      rule_index        = export_policy_rule.value.rule_index
      allowed_clients   = export_policy_rule.value.allowed_clients
      protocols_enabled = export_policy_rule.value.protocols_enabled
      unix_read_only    = export_policy_rule.value.unix_read_only
      unix_read_write   = export_policy_rule.value.unix_read_write
    }
  }

  tags = var.tags
}

resource "azurerm_monitor_metric_alert" "alert" {
  depends_on = [azurerm_netapp_volume.netapp_volume]

  count               = length(var.criteria)
  name                = "HPG-ALRT-${var.netapp_vol_name}-001-${element(keys(var.criteria), count.index)}"
  resource_group_name = var.resource_group_name
  scopes              = [azurerm_netapp_volume.netapp_volume.id]
  enabled             = var.enabled
  auto_mitigate       = var.auto_mitigate
  description         = lookup(var.criteria, element(keys(var.criteria), count.index), null)["description"]
  frequency           = var.frequency
  severity            = lookup(var.criteria, element(keys(var.criteria), count.index), null)["severity"]
  window_size         = var.window_size

  criteria {
    metric_namespace = lookup(var.criteria, element(keys(var.criteria), count.index), null)["metric_namespace"]
    metric_name      = lookup(var.criteria, element(keys(var.criteria), count.index), null)["metric_name"]
    aggregation      = lookup(var.criteria, element(keys(var.criteria), count.index), null)["aggregation"]
    operator         = lookup(var.criteria, element(keys(var.criteria), count.index), null)["operator"]
    threshold        = lookup(var.criteria, element(keys(var.criteria), count.index), null)["threshold"]
  }

  action {
    action_group_id = var.action_group_id
  }
}

variables.tf

    variable "criteria" {
  type = map
  default = {
    "ReadLATENCY5" = {
      metric_namespace = "Microsoft.NetApp/netAppAccounts/capacityPools/volumes"
      metric_name      = "AverageReadLatency"
      aggregation      = "Average"
      operator         = "GreaterThan"
      threshold        = 5
      description      = "NetApp: Volume Read Latency over 5ms"
      severity         = 2
    },
    "ReadIOPS80" = {
      metric_namespace = "Microsoft.NetApp/netAppAccounts/capacityPools/volumes"
      metric_name      = "ReadIops"
      aggregation      = "Average"
      operator         = "GreaterThan"
      threshold        = local.iops_80
      description      = "NetApp: Volume Read IOPS over TBD"
      severity         = 2
    },
    "WriteIops80" = {
      metric_namespace = "Microsoft.NetApp/netAppAccounts/capacityPools/volumes"
      metric_name      = "WriteIops"
      aggregation      = "Average"
      operator         = "GreaterThan"
      threshold        = local.iops_80
      description      = "NetApp: Volume Write IOPS over TBD"
      severity         = 2
    },
  }
}

One way is to do another criteria map to define only alerts with iops_80 value and assign it in main.tf but is there any other way to do it?

Bater55
  • 73
  • 1
  • 9
  • What I did for temporary solution is I added a conditional statement `threshold = (element(keys(var.criteria), count.index) == "ReadIOPS80" || element(keys(var.criteria), count.index) == "WriteIOPS80") ? (lookup(var.criteria, element(keys(var.criteria), count.index), null)["threshold"] + local.iops_80) : lookup(var.criteria, element(keys(var.criteria), count.index), null)["threshold"]` – Bater55 Dec 09 '20 at 15:55
  • Are you ever setting `var.criteria` with `terraform.tfvars` or `TF_VAR_criteria`? If not you could make that a local as well. – ydaetskcoR Dec 09 '20 at 16:29
  • Do you mean you want to use the local in the variables.tf? – Charles Xu Dec 10 '20 at 01:33
  • @ydaetskcoR it is a module, I don't use terraform.tfvars there. – Bater55 Dec 10 '20 at 12:07
  • @CharlesXu Yes, exactly. – Bater55 Dec 10 '20 at 12:07
  • Then do you ever override that default with the module inputs? – ydaetskcoR Dec 10 '20 at 12:14
  • No. I use default values of 'criteria' map. I do not override this, it is like a template. – Bater55 Dec 10 '20 at 12:56
  • Any more updates on this question? Does it solve your problem? If it solves your problem please accept it. – Charles Xu Dec 24 '20 at 09:33
  • No, it doesn't. If I have a solution, I'll post it. – Bater55 Dec 28 '20 at 14:58

1 Answers1

0

It seems you cannot use the local values in the variables file. What you can do is that use the variables in the local, and use the local value and variables in the resource block. And you can also use the local values in another local.

So I think you need to use the variables to set the input and things would be changed. And quote the variables in the local or quote the local in another local. For example, maybe you can use the local to set the criteria instead of using a variable.

Charles Xu
  • 29,862
  • 2
  • 22
  • 39