How To Manage Infrastructure Data with Terraform Outputs
Introduction Terraform outputs are used to extract information about the infrastructure resources from the project state. Using other features of the Hashicorp Configuration Language (HCL), which Terr
Introduction
Terraform outputs are used to extract information about the infrastructure resources from the project state. Using other features of the Hashicorp Configuration Language (HCL), which Terraform uses, resource information can be queried and transformed into more complex data structures, such as lists and maps. Outputs are useful for providing information to external software, which can operate on the created infrastructure resources.
In this tutorial, you’ll learn about Terraform output syntax and its parameters by creating a simple infrastructure that deploys Droplets. You’ll also parse the outputs programmatically by converting them to JSON.
Prerequisites
- A DigitalOcean Personal Access Token, which you can create via the DigitalOcean control panel. You can find instructions in the DigitalOcean product documents, How to Create a Personal Access Token.
- Terraform installed on your local machine and a project set up with the DigitalOcean provider. Complete Step 1 and Step 2 of the How To Use Terraform with DigitalOcean tutorial, and be sure to name the project folder
terraform-outputs
, instead ofloadbalance
. During Step 2, do not include thepvt_key
variable and the SSH key resource. - Familiarity with HCL data types and loops. For more information, see the How To Improve Flexibility Using Terraform Variables, Dependencies, and Conditionals tutorial.
Note: This tutorial has specifically been tested with Terraform 1.0.2
.
Defining Outputs
In this section, you’ll declare a Droplet, deploy it to the cloud, and learn about outputs by defining one that will show the Droplet’s IP address.
From the terraform-outputs
directory you created as a prerequisite, create and open the droplets.tf
file for editing:
- nano droplets.tf
Add the following Droplet resource and output definition:
resource "digitalocean_droplet" "web" {
image = "ubuntu-20-04-x64"
name = "test-droplet"
region = "fra1"
size = "s-1vcpu-1gb"
}
output "droplet_ip_address" {
value = digitalocean_droplet.web.ipv4_address
}
You first declare a Droplet resource, called web
. Its actual name in the cloud will be test-droplet
, in the region fra1
, running Ubuntu 20.04.
Then, you declare an output called droplet_ip_address
. In Terraform, outputs are used to export and show internal and computed values and information about the resources. Here, you set the value
parameter, which accepts the data to output, to the IP address of the declared Droplet. At declare time, it’s unknown, but it will become available once the Droplet is deployed. Outputs are shown and accessible after each deployment.
Save and close the file, then deploy the project by running the following command:
- terraform apply -var "do_token=${DO_PAT}"
Enter yes
to apply when prompted. The end of the output will be similar to this:
Output...
digitalocean_droplet.web: Creating...
...
digitalocean_droplet.web: Creation complete after 32s [id=207631771]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
droplet_ip_address = ip_address
The highlighted IP address belongs to your newly deployed Droplet. Applying the project deploys the resources to the cloud and shows the outputs at the end, when all resource attributes are available. Without the droplet_ip_address
output, Terraform would show no further information about the Droplet, except that it’s deployed.
Outputs can also be shown using the output
command:
- terraform output
The output will list all outputs
in the project:
Outputdroplet_ip_address = ip_address
You can also query a specific output by name by specifying it as an argument:
- terraform output output_name
For droplet_ip_address
, the output will consist of the IP address only:
Outputip_address
Except for specifying the mandatory value
, outputs have a few optional parameters:
description
: embeds short documentation detailing what the output shows.depends_on
: a meta parameter available at each resource that allows you to explicitly specify resources the output depends on that Terraform is not able to automatically deduce during planning.sensitive
: accepts a boolean value, which prevents the content of the output from being shown after deploying if set totrue
.
The sensitive
parameter is useful when the logs of the Terraform deployment will be publicly available, but the output contents should be kept hidden. You’ll now add it to your Droplet resource definition.
Open droplets.tf
for editing and add the highlighted line:
resource "digitalocean_droplet" "web" {
image = "ubuntu-20-04-x64"
name = "test-droplet"
region = "fra1"
size = "s-1vcpu-1gb"
}
output "droplet_ip_address" {
value = digitalocean_droplet.web.ipv4_address
sensitive = true
}
Save and close the file when you’re done. Deploy the project again by running:
- terraform apply -var "do_token=${DO_PAT}"
Enter yes
when prompted. You’ll see that the output is redacted:
Output...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
droplet_ip_address = <sensitive>
Even if it’s marked as sensitive
, the output and its contents will still be available through other channels, such as viewing the Terraform state or querying the outputs directly.
In the next step, you’ll create a different Droplet and output structure, so destroy the currently deployed ones by running:
- terraform destroy -var "do_token=${DO_PAT}"
The output at the very end will be:
Output...
Destroy complete! Resources: 1 destroyed.
You’ve declared and deployed a Droplet and created an output that shows its IP address. You’ll now learn about using outputs to show more complex structures such as lists and maps.
Outputting Complex Structures
In this section, you’ll deploy multiple Droplets from the same definition using the count
keyword, and output their IP addresses in various formats.
Using the for
loop
You’ll need to modify the Droplet resource definition, so open it for editing:
- nano droplets.tf
Modify it to look like this:
resource "digitalocean_droplet" "web" {
count = 3
image = "ubuntu-20-04-x64"
name = "test-droplet-${count.index}"
region = "fra1"
size = "s-1vcpu-1gb"
}
You’ve specified that three Droplets should be created using the count
key and added the current index to the Droplet name, so that you’ll be able to later discern between them. Remove the existing output below. When you’re done, save and close the file.
Apply the code by running:
- terraform apply -var "do_token=${DO_PAT}"
Terraform will plan the creation of three numbered Droplets, called test-droplet-0
, test-droplet-1
, and test-droplet-2
. Enter yes
when prompted to finish the process. You’ll see the following output in the end:
Output...
Apply complete! Resources: 3 added, 0 changed, 0 destroyed.
This means that all three Droplets are successfully deployed and that all information about them is stored in the project state.
The easiest way to access their resource attributes is to use outputs, but creating one for each Droplet is not scalable. The solution is to use the for
loop to traverse through the list of Droplets and gather their attributes, or to alternatively use splat expressions (which you’ll learn about later in this step).
You’ll first define an output that will output the IP addresses of the three Droplets, paired with their names. Open droplets.tf
for editing:
- nano droplets.tf
Add the following lines:
resource "digitalocean_droplet" "web" {
count = 3
image = "ubuntu-20-04-x64"
name = "test-droplet-${count.index}"
region = "fra1"
size = "s-1vcpu-1gb"
}
output "droplet_ip_addresses" {
value = {
for droplet in digitalocean_droplet.web:
droplet.name => droplet.ipv4_address
}
}
The output value of droplet_ip_addresses
is constructed using a for
loop. Because it’s surrounded by braces, the resulting type will be a map. The loop traverses the list of Droplets, and for each instance, pairs its name with its IP address and appends it to the resulting map.
Save and close the file, then apply the project again:
- terraform apply -var "do_token=${DO_PAT}"
Enter yes
when prompted and you’ll receive the output contents at the end:
OutputApply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
droplet_ip_addresses = {
"test-droplet-0" = "ip_address"
"test-droplet-1" = "ip_address"
"test-droplet-2" = "ip_address"
}
The droplet_ip_addresses
output details the IP addresses of the three deployed droplets.
Using the Terraform output
command, you can get the contents of the output as JSON using its command argument:
- terraform output -json droplet_ip_addresses
The result will be similar to the following:
Output{"test-droplet-0":"ip_address","test-droplet-1":"ip_address","test-droplet-2":"ip_address"}
JSON parsing is widely used and supported in many programming languages. This way, you can programmatically parse the information about the deployed Droplet resources.
Using Splat Expressions
Splat expressions offer a compact way of iterating over all elements of a list, and collecting contents of an attribute from each of them, resulting in a list. A splat expression that would extract the IP addresses of the three deployed droplets would have the following syntax:
digitalocean_droplet.web[*].ipv4_address
The [*]
symbol traverses the list on its left and for each of the elements, takes the contents of its attribute specified on the right. If the reference on the left is not a list by itself, it will be converted to one where it will be the sole element.
You can open droplets.tf
for editing and modify the following lines to implement this:
resource "digitalocean_droplet" "web" {
count = 3
image = "ubuntu-20-04-x64"
name = "test-droplet-${count.index}"
region = "fra1"
size = "s-1vcpu-1gb"
}
output "droplet_ip_addresses" {
value = digitalocean_droplet.web[*].ipv4_address
}
After saving the file, apply the project by running the following command:
- terraform apply -var "do_token=${DO_PAT}"
You’ll receive output that is now a list, and which contains only the IP addresses of the Droplets:
Output...
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
droplet_ip_addresses = [
"ip_address",
"ip_address",
"ip_address",
]
To receive the output as JSON, run the following command:
- terraform output -json droplet_ip_addresses
The output will be a single array:
Output["ip_address","ip_address","ip_address"]
You’ve used outputs together with splat expressions and for
loops to export the IP addresses of the deployed Droplets. You’ve also received the output contents as JSON, and you’ll now use jq
—a tool for dynamically filtering JSON according to given expressions—to parse them.
Parsing Outputs Using jq
In this step, you’ll install and learn the basics of jq
, a tool for manipulating JSON documents. You’ll use it to parse the outputs of your Terraform project.
If you’re on Ubuntu, run the following command to install jq
:
- sudo snap install jq
On macOS, you can use Homebrew to install it:
- brew install jq
jq
applies the provided processing expression on given input, which can be piped in. The easiest task in jq
is to pretty print the input:
- terraform output -json droplet_ip_addresses | jq '.'
Passing in the identity operator (.
) means that the whole JSON document parsed from the input should be outputted without modifications:
Output[
"first_ip_address",
"second_ip_address",
"third_ip_address"
]
You can request just the second IP address using the array bracket notation, counting from zero:
- terraform output -json droplet_ip_addresses | jq '.[1]'
The output will be:
Output"second_ip_address"
To make the result of the processing an array, wrap the expression in brackets:
- terraform output -json droplet_ip_addresses | jq '[.[1]]'
You’ll get a pretty printed JSON array:
Output[
"second_ip_address"
]
You can retrieve parts of arrays instead of single elements by specifying a range of indexes inside the brackets:
- terraform output -json droplet_ip_addresses | jq '.[0:2]'
The output will be:
Output[
"first_ip_address",
"second_ip_address"
]
The range 0:2
returns the first two elements—the upper part of the range (2
) is not inclusive, so only elements at positions 0
and 1
are fetched.
You can now destroy the deployed resources by running:
- terraform destroy -var "do_token=${DO_PAT}"
In this step, you have installed jq
and used it to parse and manipulate the output of your Terraform project, which deploys three Droplets.
Conclusion
You have learned about Terraform outputs, using them to show details about the deployed resources and to export data structures for later external processing. You’ve also used outputs to show attributes of a single resource, as well as for showing constructed maps and lists containing resource attributes.
For more detailed information about the features of jq
, visit the official docs.
This tutorial is part of the How To Manage Infrastructure with Terraform series. The series covers a number of Terraform topics, from installing Terraform for the first time to managing complex projects.
更多推荐
所有评论(0)