# For Loops

Terraform provides for-loops and for-each loops. These can be used to loop over variables, transform those, and output in different formats.

For example,

* \[for s in \["this is a ", "list"] : upper(s)] : this loop over the list and make all strings uppercase.
* We can loop over a list or maps
* We can even perform calculations or manipulations on values
* And it's possible to output them as a list or map

## For loops

In order to further explore this, let's first create a file with the name `vars.tf`,

```
variable "list1" {
  type = list(string)
  default = [1, 10, 9, 101, 3]
}

variable "list2" {
  type = list(string)
  default = ["apple", "pear", "banana", "mango"]
}

variable "map1" {
  type = map(number)
  default = {
   "apple" = 5
   "pear" = 3
   "banana" = 10
   "mango" = 0
  }
}
```

Let's start the Terraform console and experiment with this file,

```
$ terraform console
> [for s in ["a", "b", "c"]: s]
[
  "a",
  "b",
  "c",
]
> [for s in ["a", "b", "c"]: upper(s)]
[
  "A",
  "B",
  "C",
]
> [for s in var.list1: s ]
[
  "1",
  "10",
  "9",
  "101",
  "3",
]
> [for s in var.list1: s + 1]
[
  2,
  11,
  10,
  102,
  4,
]
> [for s in var.list2: upper(s)]
[
  "APPLE",
  "PEAR",
  "BANANA",
  "MANGO",
]
> [for k, v in var.map1: k]
[
  "apple",
  "banana",
  "mango",
  "pear",
]
> [for k, v in var.map1: v]
[
  5,
  10,
  0,
  3,
]
> {for k, v in var.map1: k => v}
{
  "apple" = 5
  "banana" = 10
  "mango" = 0
  "pear" = 3
}
> {for k, v in var.map1: v => k}
{
  "0" = "mango"
  "10" = "banana"
  "3" = "pear"
  "5" = "apple"
}
>
```

To make things more interesting let's create a file with the name `provider.tf`,

```
provider "aws" {
  region = var.AWS_REGION
}
```

Then replace the content of the `vars.tf` file,

```
variable "AWS_REGION" {
  type    = string
  default = "eu-west-1"
}
variable "project_tags" {
  type          = map(string)
  default       = {
    Component   = "Frontend"
    Environment = "Production"
  }
}
```

Finally a file with the name `ebs.tf`,

```
resource "aws_ebs_volume" "example" {
  availability_zone = "eu-west-1a"
  size              = 8

  tags = {for k, v in merge({ Name = "Myvolume" }, var.project_tags): k => lower(v)}
}
```

Init the modules,

```
$ terraform init
```

Let's examine the output,

```
$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # aws_ebs_volume.example will be created
  + resource "aws_ebs_volume" "example" {
      + arn               = (known after apply)
      + availability_zone = "eu-west-1a"
      + encrypted         = (known after apply)
      + id                = (known after apply)
      + iops              = (known after apply)
      + kms_key_id        = (known after apply)
      + size              = 8
      + snapshot_id       = (known after apply)
      + tags              = {
          + "Component"   = "frontend"
          + "Environment" = "production"
          + "Name"        = "myvolume"
        }
      + tags_all          = {
          + "Component"   = "frontend"
          + "Environment" = "production"
          + "Name"        = "myvolume"
        }
      + throughput        = (known after apply)
      + type              = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.
```

## For-Each loops

Let's start this by creating a file with the name `provider.tf`,

```
provider "aws" {
  region = var.AWS_REGION
}
```

Then let's create a file with the name `vars.tf`,

```
variable "AWS_REGION" {
  type    = string
  default = "eu-west-1"
}

variable "ports" {
  type = map(list(string))
  default = {
    "22" = [ "127.0.0.1/32", "192.168.0.0/24" ]
    "443" = [ "0.0.0.0/0" ]
  }
}
```

Finally a file with the name `securitygroup.tf`,

```
resource "aws_security_group" "example" {
  name = "example" # can use expressions here

  dynamic "ingress" {
    for_each = var.ports
    content {
      from_port   = ingress.key
      to_port     = ingress.key
      cidr_blocks = ingress.value
      protocol    = "tcp"
    }
  }
}
```

Init the modules,

```
$ terraform init
```

Let's examine the output,

```
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following
symbols:
  + create

Terraform will perform the following actions:

  # aws_security_group.example will be created
  + resource "aws_security_group" "example" {
      + arn                    = (known after apply)
      + description            = "Managed by Terraform"
      + egress                 = (known after apply)
      + id                     = (known after apply)
      + ingress                = [
          + {
              + cidr_blocks      = [
                  + "0.0.0.0/0",
                ]
              + description      = ""
              + from_port        = 443
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 443
            },
          + {
              + cidr_blocks      = [
                  + "127.0.0.1/32",
                  + "192.168.0.0/24",
                ]
              + description      = ""
              + from_port        = 22
              + ipv6_cidr_blocks = []
              + prefix_list_ids  = []
              + protocol         = "tcp"
              + security_groups  = []
              + self             = false
              + to_port          = 22
            },
        ]
      + name                   = "example"
      + name_prefix            = (known after apply)
      + owner_id               = (known after apply)
      + revoke_rules_on_delete = false
      + tags_all               = (known after apply)
      + vpc_id                 = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run
"terraform apply" now.
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://isurus.gitbook.io/infrastructure-and-platform-notes/terraform-25/terraform-basics/07-for-loops.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
