# Interpolation and Conditionals

Terrform provides a way of interpolating values using `${...}`. We can use simple math functions, refer to other variables, or use conditional logic here. For example,

* Variables: ${var.VARIABLE\_NAME} refers to a variable.
* Resources: ${type.resource-name.attr} refers to a resource declared.
* Data source: ${data.type.resource-name.attr} refers to any rendered or dynamic data.

## Usage of different variable types with interpolation

| Name    | Syntax                 | Example                              |
| ------- | ---------------------- | ------------------------------------ |
| Strings | var.name               | ${var.SOMETHING}                     |
| Maps    | var.MAP\["key"]        | ${var.AMIS\["us-east-1"]}            |
|         |                        | ${lookup(var.AMIS, var.AWS\_REGION)} |
| Lists   | var.LIST, var.LIST\[i] | ${var.subnets\[i]}                   |
|         |                        | ${join(",", var.subnets)}            |

## Usage of some other types of items with interpolation

| Name               | Syntax             | Example                                                                            |
| ------------------ | ------------------ | ---------------------------------------------------------------------------------- |
| Output of a module | module.NAME.output | ${module.aws\_vpc.vpcid}                                                           |
| Count information  | count.FIELD        | When using the attribute `count =` number in a resource, we can use ${count.index} |
| Path information   | path.TYPE          | path.cwd(current directory)                                                        |
|                    |                    | path.module(module path)                                                           |
|                    |                    | path.root(root module path)                                                        |
| Meta information   | terraform.FIELD    | terraform.env shows active workspace                                               |

In addition to these, interpolation supports Add (+), Subtract (-), and Divide (/) for float types, and additionally Modulo (%) for integer types.

## Conditionals

Interpolations may contain conditionals. The syntax looks like below for conditional statements.

```
CONDITION ? TRUE-VALUE : FALSE-VALUE
```

For example,

```
resource "aws_instance" "myinstance" {
    ...
    count = "${var.env == "prod" ? 2 : 1}"
}
```

I will provision an EC2 instance in the example below.

First let's start creating a file with the name `vars.tf`,

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

variable "PATH_TO_PRIVATE_KEY" {
  default = "mykey"
}

variable "PATH_TO_PUBLIC_KEY" {
  default = "mykey.pub"
}

variable "ENV" {
  default = "prod"
}
```

Then the `provider.tf`,

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

Next let's create a file for out VPCs; `vpc.tf`,

```
module "vpc-prod" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.59.0"

  name = "vpc-prod"
  cidr = "10.0.0.0/16"

  azs             = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false

  tags = {
    Terraform   = "true"
    Environment = "prod"
  }
}

module "vpc-dev" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "2.59.0"

  name = "vpc-dev"
  cidr = "10.0.0.0/16"

  azs             = ["${var.AWS_REGION}a", "${var.AWS_REGION}b", "${var.AWS_REGION}c"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]

  enable_nat_gateway = false
  enable_vpn_gateway = false

  tags = {
    Terraform   = "true"
    Environment = "dev"
  }
}
```

Two important things to notice in here are that I use interpolation to name availability zones of the VPC, and that I introduce tag with the name Environment for future use.

Next let's create a file with the name `securitygroup.tf`,

```
resource "aws_security_group" "allow-ssh-prod" {
  vpc_id      = module.vpc-prod.vpc_id
  name        = "allow-ssh"
  description = "security group that allows ssh and all egress traffic"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "allow-ssh"
  }
}

resource "aws_security_group" "allow-ssh-dev" {
  vpc_id      = module.vpc-dev.vpc_id
  name        = "allow-ssh"
  description = "security group that allows ssh and all egress traffic"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "allow-ssh"
  }
}
```

To keep out keys a file with the name `key.tf`,

```
resource "aws_key_pair" "mykeypair" {
  key_name   = "mykeypair"
  public_key = file(var.PATH_TO_PUBLIC_KEY)
}
```

Finally, `instance.tf`,

```
data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"] # Canonical
}

resource "aws_instance" "example" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t2.micro"

  # the VPC subnet
  subnet_id = var.ENV == "prod" ? module.vpc-prod.public_subnets[0] : module.vpc-dev.public_subnets[0]

  # the security group
  vpc_security_group_ids = [var.ENV == "prod" ? aws_security_group.allow-ssh-prod.id : aws_security_group.allow-ssh-dev.id]

  # the public SSH key
  key_name = aws_key_pair.mykeypair.key_name
}
```

In here you can notice that I'm assigning subnet and security group ids based on the environment type.

Generate ssh keys,

```
$ ssh-keygen -f mykey
```

Initialize the providers,

```
$ terraform init
```

Apply the changes,

```
$ terraform apply
```

Don't forget to clean up once experiments are done,

```
$ terraform destroy
```


---

# 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-23/terraform-basics/05-interpolation-and-conditionals.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.
