Using the terraform console to debug interpolation syntax


I am a long time Terraform user. The number of providers that are available for Terraform, and having a resource for pretty much every cloud service makes it super appealing. But even with several years of production usage, I still find myself scratching my head at times when I’m writing my interpolations. Terraform provides a really nice shell to assist with this, and it can be accessed with the terraform “console” option:

$ terraform console

Once you are in the shell, typing an expression will produce immediate feedback:

> list("a","b","c")[0]
> a

The expression above creates a list, and then displays the first element in it. A more realistic example would be grabbing a given subnet from a list:

> aws_subnet.vpc-foo-public-subnets-proxies.*.id[0]
subnet-0a211c324068d847e

In this example I use the splat operator to get all subnets in a list, and then display the subnet in index 0. The console is also super useful for playing with data sources. To see what a data source contains, you can type it into the console:

> data.aws_availability_zones.available
{
  "group_names" = [
    "us-east-1",
  ]
  "id" = "2020-04-26 14:08:51.531061491 +0000 UTC"
  "names" = [
    "us-east-1a",
    "us-east-1b",
    "us-east-1c",
    "us-east-1d",
    "us-east-1e",
    "us-east-1f",
  ]
  "state" = "available"
  "zone_ids" = [
    "use1-az2",
    "use1-az4",
    "use1-az6",
    "use1-az1",
    "use1-az3",
    "use1-az5",
  ]
}

Once you see the structure (maps, lists, strings etc.), you can use the built-in functions to massauge the data to your liking:

> slice(data.aws_availability_zones.available.names,2,4)
[
  "us-east-1c",
  "us-east-1d",
]

One other super useful feature is the ability to play with maps. You can retrieve map values:

> lookup(map("a","avalue","b","bvalue"), "a")
avalue

Or the keys that comprise a map:

> keys(map("a","avalue","b","bvalue"))
[
  "a",
  "b",
]

Or both the keys and their values:

> { for k, v in map("a", "one", "b", "two"): v => k }
> {
>   "one" = "a"
>   "two" = "b"
> }

As of Terraform 0.12, you now have the ability to use for, for_each and logic operators ( x ? y : z existed previously) in your HCL. Testing logic operations in the console is as easy as:

> keys(map("a","avalue","b","bvalue"))[0] == "a" ? "true" : "false"
true

> keys(map("a","avalue","b","bvalue"))[0] == "ab" ? "true" : "false"
false

The same goes for testing looping logic:

> [for string in ["one", "two", "three"] : upper(string)]
[
  "ONE",
  "TWO",
  "THREE",
]

> [ for key in keys(map("a", "one", "b", "two")) : key ]
[
  "a",
  "b",
]
> [ for value in map("a", "one", "b", "two") : value ]
[
  "one",
  "two",
]

The console has become my best friend when writing Terraform code. I can test my code in the shell, then commit it once I know it will produce the result I want. This also reduces the number of times I need to come back to my code after reviewing my terraform plans. Viva la Terraform!

This article was posted by on 2020-04-27 00:00:00 -0500 -0500