Variable Attribute Key Conditional

Is there a way of making a variable attribute key conditional?

For example, when declaring several EventBridge scheduled rules can the schedule_expression have a default value if not declared:

local.tfvars

eventbridge = {
rule_one = {
name = "rule_one"
schedule_expression = "cron(12 30 * * ? *)"
}
rule_two = {
name = "rule_two"
}
rule_three = {
name = "rule_three"
}
}

main.tf

resource "aws_cloudwatch_event_rule" "schedule" {
for_each = local.eventbridge

name = each.value["name"]
schedule_expression = ???
}

How would I get rule_one to use the declared schedule, i.e. cron(12 30 * * ? * ), while rule_two and rule_three would use a default value, like, cron(0 0 * * ? *).

TIA.

Hi @glenn.comiskey,

When assigning values to resource arguments, assigning null is exactly equivalent to omitting the argument altogether.

You can rely on that to make some of your elements of local.eventbridge leave schedule_expression unset, like this:

locals {
  eventbridge = tomap({
    rule_one = {
      name                = "rule_one"
      schedule_expression = "cron(12 30 * * ? *)"
    }
    rule_two = {
      name                = "rule_two"
      schedule_expression = null
    }
    rule_three = {
      name                = "rule_three"
      schedule_expression = null
    }
  })
}

resource "aws_cloudwatch_event_rule" "schedule" {
  for_each = local.eventbridge

  name                = each.value.name
  schedule_expression = each.value.schedule_expression
}

Thanks for the prompt reply, @apparentlymart, and I’ll bear the null tip in mind, especially as I believe I could use a check for null to use a default value.

resource "aws_cloudwatch_event_rule" "schedule" {
for_each = local.eventbridge

name = each.value.name
schedule_expression = each.value.schedule_expression == null ? "cron(0 0 * * ? *)" : each.value.schedule_expression
}

However, what I was really trying to achieve is the absence of the attribute when declaring, in the current example, EventBridge rules if a default value was to used. That is to say, for example:

eventbridge = {
rule_one = {
name = "rule_one"
schedule_expression = "cron(12 30 * * ? *)"
}
rule_two = {
name = "rule_two"
}
}

rather than

eventbridge = {
rule_one = {
name = "rule_one"
schedule_expression = "cron(12 30 * * ? *)"
}
rule_two = {
name = "rule_two"
schedule_expression = "cron(0 0 * * ? *)"

The aim was to make adding new rules as easy as possible so that, given a little bit of documentation, anyone would be able to add, in the current example, a new rule:

eventbridge = {
rule_one = {
name = "rule_one"
schedule_expression = "cron(12 30 * * ? *)"
}
rule_two = {
name = "rule_two"
}
rule_three = {
name = "rule_three"
}
rule_four = {
name = "rule_four"
}
}

Believe I’ve found a solution to the “problem” I was experiencing by using the lookup function.

local.tf

eventbridge = {
  rule_one = {
    name = "rule_one"
    schedule_expression = "cron(12 30 * * ? *)"
  }
  rule_two = {
    name = "rule_two"
  }
}

main.tf

resource "aws_cloudwatch_event_rule" "schedule" {
  for_each = local.eventbridge

  name = each.value.name
  schedule_expression = lookup(each.value, "schedule_expression", "cron(0 0 * * ? *)")
}

This means that additional rules can be added simply by making a new mapping in the “eventbridge” local variable by declaring only the name attribute, accepting the default schedule of “cron(0 0 * * ? *)”, or by declaring both the name and schedule_expression attributes.

eventbridge = {
  rule_one = {
    name = "rule_one"
    schedule_expression = "cron(12 30 * * ? *)"
  }
  rule_two = {
    name = "rule_two"
  }
  rule_three = {
    name = "rule_three"
  }
  rule_four = {
    name = "rule_four"
    schedule_expression = "cron(* 0 * * ? *)"
  }
}

Just in case anybody does read this topic, I’ve expanded the EventBridge declaration by making the use of pattern or schedule rules optional.

main.tf

resouce "aws_cloudwatch_event_rule" "pattern" {
  for_each = contains(keys(local.eventbridge), "rules_pattern") ? local.eventbridge.rules_pattern : {}

  name          = each.value.name
  event_pattern = each.value.event_pattern
}

resouce "aws_cloudwatch_event_rule" "schedule" {
  for_each = contains(keys(local.eventbridge), "rules_schedule") ? local.eventbridge.rules_schedule : {}

  name                 = each.value.name
  schedule_expressions = lookup(each.value, "schedule_expression", "cron(0 0 * * ? *)")
}

local.tf

eventbridge = {
  rules_pattern = {
    .....
  }
  rules_schedule = {
    .....
  }
}