04. Loops, iterations and conditions

Contents

    Count and count index

    In resource blocks where the count is set, an additional count object (count.index) is available in expressions, so that you can modify the configuration of each instance.

    resource "aws_instance" "myec2" {
      count         = 3
      ami           = "ami-0dab0800aa38826f2"
      instance_type = "t2.micro"
    
      tags = {
        Name = "myinstance-${count.index}"
      }
    }
    
    output "arns" {
      value = aws_instance.myec2[*].arn
    }
    

    List iteration

    variable "users" {
      type        = list(string)
      description = "user names"
      default     = ["alice", "bob"]
    }
    
    resource "aws_iam_user" "myuser" {
      count = length(var.users)
      name  = element(var.users, count.index)
      path  = "/system/"
      tags = {
        tag-key = "tag-value"
      }
    }
    

    Count vs for_each

    Set

    SET items are unordered and no duplicates allowed.
    Convert a list to a set : toset function (which removes ordering and duplicates)

    for_each

    With a set → each.key (which equals each.value)

    resource "aws_iam_user" "iam" {
      for_each = toset(["user-0", "user-01", "user-02", "user-03"])
      name     = each.key
    }
    

    each.key value is used to reference a given instance: aws_iam_user.iam["user-0"].

    With a map → each.key / each.value

    resource "aws_instance" "myec2" {
      ami = "ami-0cea098ed2ac54925"
      for_each = {
        little_instance = "t2.micro"
        big_instance    = "t2.medium"
      }
      instance_type = each.value
      tags = {
        Name = each.key
      }
    }
    

    each.key value is used to reference a given instance: aws_instance.myec2["little_instance"].

    Conditional Expression

    variable "istest" {}
    
    resource "aws_instance" "dev" {
      ami           = "ami-082b5a644766e0e6f"
      instance_type = "t2.micro"
      count         = var.istest == true ? 3 : 0
    }
    
    resource "aws_instance" "prod" {
      ami           = "ami-082b5a644766e0e6f"
      instance_type = "t2.large"
      count         = var.istest == false ? 1 : 0
    }
    

    Dynamic block

    Dynamic Block allows to dynamically construct repeatable nested blocks inside resource, data, provider, and provisioner blocks.
    Note: this feature is a bit difficult to read and therefore, alternatives should be used when it is possible.

    variable "sg_ports" {
      type        = list(number)
      description = "list of ingress ports"
      default     = [8200, 8201, 8300, 9200, 9500]
    }
    
    resource "aws_security_group" "dynamicsg" {
      name        = "dynamic-sg"
      description = "Ingress for Vault"
    
      # with an iterator
      dynamic "ingress" {
        for_each = var.sg_ports
        iterator = port
        content {
          from_port   = port.value
          to_port     = port.value
          protocol    = "tcp"
          cidr_blocks = ["0.0.0.0/0"]
        }
      }
    
      # without iterator, the variable is the label
      dynamic "egress" {
        for_each = var.sg_ports
        content {
          from_port   = egress.value
          to_port     = egress.value
          protocol    = "tcp"
          cidr_blocks = ["0.0.0.0/0"]
        }
      }
    }
    

    Remember!

    countcount.index
    for_each

    dynamic_bloc

    Proudly Powered by Zim 0.75.2.

    Template by Etienne Gandrille, based on ZeroFiveEight and using JQuery Toc Plugin.