Terraform Certification (Part 9): Data sources
Tags: hashicorp, terraform
Published: 2023-04-09 10:00:00

A data source is used to access information (data) from outside of your current Terraform configuration. This could be a list of available EC2 AMI[^ami] IDs in AWS, or metadata for an existing resource group in Azure. There are a few more specific use-cases for data sources in Terraform, but since my lessons are focused on what I consider to be most important for the Terraform Associate Certification I will not go into these use-cases[^docs]. In fact, this will be a short lesson because in my experience you seldom use data sources.

In this lesson I continue to go through part 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 cover parts of 8 (d) and (e) in this lesson. I will also briefly touch on the subjects in 8 (f).

## Define a data source in HCL

The general format of the `data` block in HCL looks like this:

```hcl
data "data_source_type" "local_name" {
    argument1 = <expression>
    argument2 = <expression>
    argument3 = <expression>
    ...
}
```

This has the same format as the `resource` block, with two labels.

- The first label defines the _data source type_, and it depends on what data sources are exposed from the providers you use.
- The second label is the _local name_ of this data source, and you will use it to refer to this data source from other parts of your Terraform configuration.

The list of arguments is dependent on what data source type you are using, see the documentation for your provider.

## Using data sources

I think of data sources as existing in two different varieties:

1. Data sources for existing resources
1. Data sources for lists of alternatives

I will show examples of both and explain what I mean.

### Use a data source to access existing resources

When we start using Terraform chances are we already have a lot of cloud resources and other types of resources deployed all over the place. These could be imported into our Terraform state[^state], but that is an advanced operation and sometimes not practical. We could hard-code values for our existing resources, but what if something about them changes? Then we need to update our Terraform configurations to account for those changes. A data source can help us here.

Let us look at an example of a data source from the `azurrm` provider:

```hcl
data "azurerm_resource_group" "my_existing_rg" {
  name = "rg-existing-group"
}
```

This is a simple data source of the type `azurerm_resource_group`. It has a single required argument, `name`. Using this data source we can get a _handle_ for the resource group, and use references to it just like if it was created using a `resource` block. In a different part of my Terraform configuration I could have an expression like this:

```hcl
azurerm_resource_group.my_existing_rg.location
```

This would access the `location` property of the existing resource group.

### Use a data source to read lists of alternatives

I thought about what I should call this variety of data sources but could not come up with a better name than _... to read lists of alternatives_. So let's just go with it!

AWS has a number or regions. When you configure the AWS provider for Terraform you select one of these regions. Each region has a number of availability zones, which are data centers where you could create your resources. How many availability zones are there? You might have learned the number by heart, but is there a better way? This is where data sources can help you!

Let's look at an example:

```hcl
data "aws_availability_zones" "available" {
  state = "available"
}
```

This data source is of the `aws_availability_zones` type. In the arguments I specify that I want the availability zones that have the `state` of `available`. What I get back is a list containing the available availability zones! I can access them like this:

```hcl
data.aws_availability_zones.available.names[0]
data.aws_availability_zones.available.names[1]
data.aws_availability_zones.available.names[2]
...
```

To find out how many availability zones there are I could use the `length` function:

```hcl
length( data.aws_availability_zones.available.names )
```

## Summary

Data sources are useful sometimes, and in this lesson I showed two of the most common use-cases for them. As I mentioned before I have found that data sources are not used a lot, especially compared to resources. I don't think I had a single question concerning specifics of data sources on the certification exam, but it is of course a good idea to be ready for them anyway!

In summary we look at:

- How to define a data source in HCL using the `data` block.
- How we can use data sources to access information from existing resources.
- How we can use data sources to obtain lists of alternatives, e.g. lists of availability zones in an AWS region, or lists of available subscriptions in Azure.

[^ami]: EC2 stands for Elastic Compute Cloud and it is the virtual machines of the AWS cloud, and an AMI is an Amazon Machine Image, it is an image that you create virtual machines from.
[^docs]: Read the official documentation for data sources at https://developer.hashicorp.com/terraform/language/data-sources.
[^state]: More about Terraform state in a future lesson.