duuk
duuk

Reputation: 1

Terraform error when trying to get count.index from var, error [count.index is 3 local.metric_names is object with 4 attributes]

What i am trying to do is to create alarm on Cloud Watch with alarm names and metric names that are stored in list.

Make a notice for alarm_name and metric_name.

main.tf

locals {
  alarm_names = { for x in var.alarm_names_list : x.name => x }
}
locals {
  metric_names = { for x in var.metric_names_list : x.name => x }
}
resource "aws_cloudwatch_metric_alarm" "ec2_cpu" {
  count                     = length(local.alarm_names)
  alarm_name                = "${local.alarm_names[count.index].name}-${var.name_instance_outout}"
  comparison_operator       = "GreaterThanOrEqualToThreshold"
  evaluation_periods        = "2"
  metric_name               = local.metric_names[count.index].name
  namespace                 = "AWS/EC2"
  period                    = "120" #seconds
  statistic                 = "Average"
  threshold                 = "80"
  alarm_description         = "This metric monitors ec2 cpu utilization"
  insufficient_data_actions = []
  dimensions = {
    InstanceId = var.ec2_id_output
  }
}

variables.tf

variable "metric_names_list" {
  type = list(object({
    name = string
  }))
  default = [
    {
      name = "CPUUtilization"
    },
    {
      name = "DiskReadOps"
    },
    {
      name = "NetworkIn"
    },
    {
      name = "NetworkOut"
    }     
  ]
}
variable "alarm_names_list" {
  type = list(object({
    name = string
  }))
  default = [
    {
      name = "cpu-utilization-duk-test"
    },
    {
      name = "memory-utilization"
    },
    {
      name = "network-inbound"
    },
    {
      name = "network-outbound"
    }        
  ]
}

I made 2 locals and I don't know if it's possible to have 2 for_each loop separated not nested, because i will always have same number of items in list for alarm_name and metric_name so I think i will get it to work like this.

Initially I placed variables only as a type = list(string) and I thought if I put them as this list(object) I will avoid this error but unfortunately it still appears. Bellow is full error output.

│ Error: Invalid index
│
│   on modules/cloudwatch/main.tf line 31, in resource "aws_cloudwatch_metric_alarm" "ec2_cpu":
│   31:   metric_name               = local.metric_names[count.index].name
│     ├────────────────
│     │ count.index is 0
│     │ local.metric_names is object with 4 attributes
│
│
│   on modules/cloudwatch/main.tf line 31, in resource "aws_cloudwatch_metric_alarm" "ec2_cpu":
│   31:   metric_name               = local.metric_names[count.index].name
│     ├────────────────
│     │ count.index is 3
│     │ local.metric_names is object with 4 attributes
│
│ The given key does not identify an element in this collection value. An object only supports looking up attributes by name, not by numeric index.

Upvotes: 0

Views: 2611

Answers (1)

Marcin
Marcin

Reputation: 238319

Your local.alarm_names and local.alarm_names are maps, not list. To change them to list it should be:

locals {
  alarm_names = [ for x in var.alarm_names_list : x.name ]
}
locals {
  metric_names = [ for x in var.metric_names_list : x.name ]
}

then

resource "aws_cloudwatch_metric_alarm" "ec2_cpu" {
  count                     = length(local.alarm_names)
  alarm_name                = "${local.alarm_names[count.index]}-${var.name_instance_outout}"
  comparison_operator       = "GreaterThanOrEqualToThreshold"
  evaluation_periods        = "2"
  metric_name               = local.metric_names[count.index]
  namespace                 = "AWS/EC2"
  period                    = "120" #seconds
  statistic                 = "Average"
  threshold                 = "80"
  alarm_description         = "This metric monitors ec2 cpu utilization"
  insufficient_data_actions = []
  dimensions = {
    InstanceId = var.ec2_id_output
  }
}

Upvotes: 2

Related Questions