HashiCorp Configuration Language

The syntax used for declaring Terraform configurations is called HashiCorp Configuration Language (HCL). Terraform uses configuration files written in HCL that are named with .tf extension.

HashiCorp Configuration Language Syntax

resource "aws_instance" "syntx_example" {
    ami = "abc123"

    network_interface {
        # ...
    }
}
  • Single line comments start with #.

  • Multiline comments are wrappend with /* and */.

  • Values are assigned with the syntac of key = value.

  • Strings are in double quotes.

  • Strings can interpolate other values using syntax wrapped in ${}, for example ${var.foo}.

  • Numbers are assumed to be base 10.

  • true and false respresents boolean value.

  • List of primitives can be create by using [ ], for example ["foo", "bar", "baz"].

  • Maps can be made with { }, for exampe { "foo": "bar", "bar": "baz" }.

Also, when it comes to common coding styles with HCL, it prefers indenting with two spaces for each nesting level and aligning multiple arguments with their equal sign.

Example

In this example I'm trying to deploy a Docker container.

Setup the environment:

> mkdir terraform-basics
> cd terraform-basics

Next let's create the Terraform program with main.tf file,

main.tf

# Download the latest Ghost image
resource "docker_image" "image_id" {
  name = "ghost:latest"
}

# Start the Container
resource "docker_container" "container_id" {
  name  = "ghost_blog"
  image = "${docker_image.image_id.latest}"
  ports {
    internal = "2368"
    external = "80"
  }
}

Validate main.tf,

> terraform validate

Terraform plan,

> terraform plan

Apply the changes,

> terraform apply

List the Docker containers,

docker container ls

Reset the environment,

> terraform destroy

Example

This example provides a couple of simple examples of different use cases with variables.

Create a faile called main.tf.

variable "myvar" {
  type    = string
  default = "hello terraform"
}

variable "mymap" {
  type = map(string)
  default = {
    mykey = "my value"
  }
}

variable "mylist" {
  type    = list(any)
  default = [1, 2, 3]
}

In here, we first define a variable named myvar of type string and it's default value is hello terraform. Next it we declare a variable of type map with the name mymap. In maps we can specify the type of value it is going to keep like this map(TYPE). In a similar approach, we can specify lists. Next, we have declared a variable of type list with name myname and it's default value is 1, 2, 3, an array of integers.

These can be verified by invoking the Terraform console,

> terraform console

Check the value of myvar,

$ var.myvar
"hello terraform"

$ "${var.myvar}"
"hello terraform"

Check the value of mymap,

$ var.mymap
tomap({
  "mykey" = "my value"
})

$ var.mymap["mykey"]
"my value"

Check the value of mylist,

$ var.mylist
tolist([
  1,
  2,
  3,
])

$ var.mylist[0]
1

$ element(var.mylist, 1)
1

$ slice(var.mylist, 0, 2)
[
  1,
  2,
]

Create a file called resources.tf,

provider "aws" {
  ...
}

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

variable "AMIS" {
  type = map(string)
  default = {
    eu-west-1 = "my ami"
  }
}

resource "aws_instance" "example" {
  ami           = var.AMIS[var.AWS.REGION]
  instance_type = "t2.micro"
}

This file uses the AWS Terraform module. First it declares a variable to specify the AWS region with the default value eu-west-1. Then it spefies an AMIS resource, and finally an EC2 instance. It is important to notice here that machine image (ami) is specifed by refering to the AMIS and AWS REGION variables that we declared.

Last updated