Terraform Certification (Part 10): Configuration "leftovers"
Tags: hashicorp, terraform
Published: 2023-04-12 10:00:00

In this lesson I will go through the few piece that are left in section 8 of the Certified Terraform Associate exam curriculum. This part of the curriculum is outlined below:

| Part  | Content                                                                       |
| :---: | ----------------------------------------------------------------------------- |
| **8** | **Read, generate, and modify configuration**                                  |
|  (a)  | Demonstrate use of variables and outputs                                      |
|  (b)  | Describe secure secret injection best practice                                |
|  (c)  | Understand the use of collection and structural types                         |
|  (d)  | Create and differentiate `resource` and `data` configuration                  |
|  (e)  | Use resource addressing and resource parameters to connect resources together |
|  (f)  | Use HCL and Terraform functions to write configuration                        |
|  (g)  | Describe built-in dependency management (order of execution based)            |

To be specific: I will discuss 8 (c), (f) and (g).

## Understand the use of collection and structural types

I went through basic types in an earlier lesson. Basic types include `string`, `number`, and `bool`. I have also briefly shown collection and structural types, but let us take another look at those here.

### list

A list is, like in most other programming languages, a sequence of values. Examples of lists in HCL:

```hcl
["a", "b", "c"]
[1,2,3,4,5]
[
    "one",
    2,
    true
]
```

Items are separated by commas, and you can write the list in a single line or split across multiple lines.

You can access elements of a list with `my_list[0]`, `my_list[1]`, etc. The index starts at 0.

### set

A set is similar to a list, but can only contain unique elements. A set can only contain elements of the same type[^set]. You can't write a literal set, but you can use the `toset` function to convert a literal list to a set:

```hcl
toset([1,2,3,4,5])
toset(["a", "b", "c"])
```

You access elements of the set using the same syntax as for lists.

### map

A map is a series of key/value pairs:

```hcl
{
    first  = 1
    second = 2
    third  = "three"
}
```

The keys in a map must be strings, but the values could be arbitrary expressions:

```hcl
{
    first  = toset([1,2,3])
    second = "my-string-${var.string_ending}"
    third  = {
        fourth = 4
    }
}
```

You can access values in the map with the syntax `my_map["first"]`, `my_map["second"]`, etc.

## Use HCL and Terraform functions to write configuration

Terraform includes a lot of functions that simplify writing Terraform configuration. The full list of available functions can be found in the [official documentation](https://developer.hashicorp.com/terraform/language/functions). It is a bit meaningless for me to go through all the available functions since there are 100s of them.

Instead, let me just mention that you can use functions in any expression. An example of what this might look like:

```hcl
"my-string-${lower(var.my_capslock_input)}"
```

Here I include the `lower()` function in a string, this function takes a string input and converts all uppercase characters to lowercase.

Out of all the available functions I have found the string functions to be most useful. This will of course depend on your specific use-case. Most often the name of the function will make it clear what it does, so do not worry too much about functions on the exam.

## Describe built-in dependency management (order of execution based)

In a previous lesson I described implicit and explicit dependencies. This is an important point when working with Terraform (or any other infrastructure-as-code tool). How does Terraform know in which order it should create resources? The plain truth is that it doesn't. You must write your Terraform configuration in a way that you tell Terraform in which order it should create your resources, either implicitly or explicitly.

In the following situation we have four resources with a relationship between `resource_1` and `resource_2`, and between `resource_2` and `resource_3`.

![execution order](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aijogso7uj2g3x3wckj0.png)

We see that `resource_4`, which has no relationship with any other resource is created at the same time as `resource_3` which also does not depend on any other resource. When `resource_3` is created Terraform will start creating `resource_2`, providing it the value of the `ip` from `resource_3`. Finally, once `resource_2` is created Terraform will create `resource_1`, passing it the value of the `name` property from `resource_2`.

There is a CLI command you can use to generate a graph that will show you an image similar to what I showed you, but with a bit more detail:

```console
$ terraform graph
```

This command will output a file in the DOT format, and you can use [Graphviz](http://www.graphviz.org/) to generate a chart from it. The chart will show you dependencies between resources, and from it you can understand the execution order.

## Summary

This was the last part of section 8 of the exam curriculum! What a journey it has been! After this we will move on to other parts of the curriculum.

In summary we looked at:

- Collection and structural types like `list`, `set`, and `map`.
- Terraform functions (we didn't see many functions in this lesson, but we learned that there ARE many functions).
- Execution order which is in what order Terraform creates the resources we define. We also learned that there is the CLI command `terraform graph` that can be used to generate a visual representation of the relationships between resources.

[^set]: If you convert a list of values of mixed types into a set Terraform will convert the values to the same type (most likely strings).