Thursday, January 16, 2020

Terraform loop - count vs for_each

Terraform Notes

Using Count Loop vs For_Each Loop

In my previous example, Terraform Cloudwatch Event Rules, I used Count to loop through a List of CloudWatch rules. One downside of doing it this way is that if you have to remove 1 resource in the array, it causes a cascade of delete and recreates to ensure the indices are reordered.
So if you have 5 resources and you delete [2], following will occur.

[1]   -->   [1]
[2]   -->    X
[3]   -->    X    -->   [2]
[4]   -->    X    -->   [3]
[5]   -->    X    -->   [4]

The better way to do this (supported as of Terraform version 0.12) is to use for_each. Here is my example.

This is the my variable
variable "event_rules" {
    description = "Create event rules with following name, description, and rule JSON"
    type = map(map(string))
    default = {
        "CIS3_1" = {
            "name"="CIS-UnauthorizedActivityAttempt",
            "description"="3.1 UnauthorizedActivityAttempt",
            "filename"="CIS-UnauthorizedActivityAttempt.json"
        },
        "CIS3_2" = {
            "name"="CIS-ConsoleLoginNoMFA",
            "description"="3.2 ConsoleLoginNoMFA",
            "filename"="CIS-ConsoleLoginNoMFA.json"
        }
    }
}

This is where resources are created

resource "aws_cloudwatch_event_rule" "all_events_map" {
    for_each = var.event_rules_map
      name = each.value["name"]
      description = each.value["description"]
      event_pattern = file("${path.module}/jsons/${each.value["filename"]}")
}

Here is another example, where we nest the for loop so that we evaluate the aws_cloudwatch_event_rule before we take action on it. The inner for loop will create a map that uses key as the key and value as its value (key => value) only if the following if statement resolves to true. Then the outer for loop will run against that resulting map. So it's possible that no resource gets created.


resource "aws_lambda_permission" "all_events_map" {
  for_each = {
    for key, value in aws_cloudwatch_event_rule.all_events_map:
    key => value
    if length(var.lambda_function_name) > 0
  }
    statement_id  = each.value["name"]
    action        = "lambda:InvokeFunction"
    function_name = var.lambda_function_name
    principal     = "events.amazonaws.com"
    source_arn    = each.value["arn"]
}








No comments:

Post a Comment

AWS WAF log4j query

How to query AWS WAF log for log4j attacks 1. Setup your Athena table using this instruction https://docs.aws.amazon.com/athena/latest/ug/wa...