Skip to content

Instantly share code, notes, and snippets.

@max-rocket-internet
Last active January 26, 2022 16:03
Show Gist options
  • Save max-rocket-internet/0b6955a80b0fab1b3d3fe81f8953c0a2 to your computer and use it in GitHub Desktop.
Save max-rocket-internet/0b6955a80b0fab1b3d3fe81f8953c0a2 to your computer and use it in GitHub Desktop.
Some examples for iteration in Terraform 0.12

Iteration in Terraform 0.12+

All of these examples allow for an item to be removed without recreation of any other resources.

Basic iteration 1

variable "data" {
  type = map
  default = {
    test1 = {
      display_name = "some_string1"
    }
    test2 = {
      display_name = "some_string2"
    }
    test3 = {
      display_name = "some_string3"
    }
  }
}

resource "aws_sns_topic" "topic" {
  for_each     = var.data
  name         = each.key
  display_name = each.value["display_name"]
}

Basic iteration 2

variable "my_lifecycle_policy" {
  type    = string
  default = <<EOF
{
    "rules": [
        {
            "rulePriority": 1,
            "description": "Keep last 1000 images",
            "selection": {
                "tagStatus": "any",
                "countType": "imageCountMoreThan",
                "countNumber": 1000
            },
            "action": {
                "type": "expire"
            }
        }
    ]
}
EOF
}

variable "ecr_repos" {
  type = list(string)

  default = [
    "my-app-1",
    "my-app-2",
    "my-app-3",
  ]
}

resource "aws_ecr_lifecycle_policy" "ecr" {
  for_each   = toset(var.ecr_repos)
  repository = aws_ecr_repository.ecr[each.key].name
  policy     = var.my_lifecycle_policy
}

resource "aws_ecr_repository" "ecr" {
  for_each = toset(var.ecr_repos)
  name     = each.key
}

resource "aws_ecr_repository_policy" "ecr" {
  for_each   = toset(var.ecr_repos)
  repository = aws_ecr_repository.ecr[each.key].name
  policy     = data.aws_iam_policy_document.my_ecr_pull_policy.json
}

Double iteration

variable "data" {
  type = map
  default = {
    dispatch_service = {
      enabled = true
      countries = [
        "at",
        "fi",
        "no"
      ]
    }
    porygon = {
      enabled   = true
      countries = [
        "za",
        "sa",
      ]
    }
    rider_transmission = {
      enabled   = true
      countries = [
        "ca",
      ]
    }
  }
}

locals {
  app_country_pairs = flatten(
    [
      for key, value in var.data : [
        for country in value["countries"] : {
          name = format("%s_%s", key, country)
          enabled = value["enabled"]
        }
      ]
    ]
  )

  resources = {
    for obj in local.app_country_pairs : "${obj.name}" => obj.enabled
  }
}

resource "aws_sns_topic" "topic" {
  for_each = local.resources
  name     = each.key
}

Iteration over map with condition

variable "data" {
  type = map(any)
  default = {
    service1 = {
      id         = "abcd"
      create_sns = true
    }
    service2 = {
      id = "efghi"
    }
    service3 = {
      id = "jklmno"
    }

  }
}

resource "aws_sns_topic" "topic" {
  for_each = {
    for k, v in var.data : k => v
    if lookup(v, "create_sns", false)
  }
  name = each.key
}

Complex iteration

variable "data" {
  type = any
  default = {
    dispatch_service = {
      enabled   = false
      countries = [
        "at",
        "fi",
        "no"
      ]
    }

    porygon = {
      enabled = true
      cloudwatch_settings = {
        threshold_1 = 999
      }
      countries = [
        "za",
        "sa",
      ]
    }

    rider_transmission = {
      enabled             = true
      sqs_delay_seconds   = 90
      cloudwatch_settings = {
        threshold_2 = 777
      }
      countries = [
        "ca",
        "us",
        "mx"
      ]
      extra_tags = {
        extra_tag = "my_value"
      }
    }
  }
}

locals {
  cloudwatch_defaults = {
    threshold_1 = 5
    threshold_2 = 10
    threshold_3 = 20
  }

  app_country_pairs = flatten(
    [
      for key, value in var.data : [
        for country in value["countries"] : {
          resource_name       = format("%s_%s", key, country)
          app                 = key
          country             = country
          enabled             = value["enabled"]
          cloudwatch_settings = merge(local.cloudwatch_defaults, lookup(value, "cloudwatch_settings", {}))
        }
      ]
    ]
  )

  resources = {
    for obj in local.app_country_pairs : "${obj.resource_name}" => {
      cloudwatch_settings = obj.cloudwatch_settings
      app                 = obj.app
      country             = obj.country
    } if obj.enabled
  }
}

resource "aws_sns_topic" "topic" {
  for_each = local.resources
  name     = each.key
}

resource "aws_sqs_queue" "terraform_queue" {
  for_each      = local.resources
  name          = each.key
  delay_seconds = lookup(var.data[each.value["app"]], "sqs_delay_seconds", 120)

  tags = merge(
    lookup(var.data[each.value["app"]], "extra_tags", {}),
    {
      "app"     = each.value["app"]
      "country" = each.value["country"]
    }
  )
}

resource "aws_cloudwatch_metric_alarm" "one" {
  for_each                  = local.resources
  alarm_name                = "${each.key}_one"
  comparison_operator       = "GreaterThanOrEqualToThreshold"
  evaluation_periods        = "2"
  metric_name               = "CPUUtilization"
  namespace                 = "AWS/EC2"
  period                    = "120"
  statistic                 = "Average"
  threshold                 = each.value["cloudwatch_settings"]["threshold_1"]
  alarm_description         = "This metric monitors ec2 cpu utilization"
  insufficient_data_actions = []
}

resource "aws_cloudwatch_metric_alarm" "two" {
  for_each                  = local.resources
  alarm_name                = "${each.key}_two"
  comparison_operator       = "GreaterThanOrEqualToThreshold"
  evaluation_periods        = "2"
  metric_name               = "CPUUtilization"
  namespace                 = "AWS/EC2"
  period                    = "120"
  statistic                 = "Average"
  threshold                 = each.value["cloudwatch_settings"]["threshold_2"]
  alarm_description         = "This metric monitors ec2 cpu utilization"
  insufficient_data_actions = []
}

resource "aws_cloudwatch_metric_alarm" "three" {
  for_each                  = local.resources
  alarm_name                = "${each.key}_three"
  comparison_operator       = "GreaterThanOrEqualToThreshold"
  evaluation_periods        = "2"
  metric_name               = "CPUUtilization"
  namespace                 = "AWS/EC2"
  period                    = "120"
  statistic                 = "Average"
  threshold                 = each.value["cloudwatch_settings"]["threshold_3"]
  alarm_description         = "This metric monitors ec2 cpu utilization"
  insufficient_data_actions = []
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment