What is Terraform null Resource?
Terraform null_resource is one of the features which is underused by the DevOps professional. When I looked at Terraform's documentation for null_resource I felt they have not put much effort into explaining null_resource in more detail.
But when I tried the null_resource by myself I really felt to use it more often inside my Terraform project. In this blog, I will talk about null_resource and what are the different use cases for it.
What is null_resource? - As in the name you see a prefix null which means this resource will not exist on your Cloud Infrastructure(AWS, Google Cloud, Azure). The reason is there is no terraform state associated with it, due to you can update the null_resource inside your Terraform file as many times as you can.
Terraform null_resource can be used in the following scenario -
- Run shell command
- You can use it along with local provisioner and remote provisioner
- It can also be used with Terraform Module, Terraform count, Terraform Data source, Local variables
- It can even be used for output block
We will try to address all the possible use cases for null_resource in this blog post with the help of examples.
Read More on -
Table of Content
- How does Terraform null_resource work?
- What is trigger inside null_resource?
- Use Case 1 - null_resource with local provisioner
- Use Case 2 - null_resource with remote provisioner
- Use Case 3 - Using trigger to execute null_resource everytime
- Advantages of null_resource
- Conclusion
1. How does Terraform null_resource work?
Terraform null_resource does not have a state which means it will be executed as soon as you run $ terraform apply
command but no state will be saved.
Example - Please refer to the following code of null_resource -
- Keep in mind when you execute
$terraform apply
command the null_resource will always execute it once.
1#main.tf
2
3provider "aws" {
4 region = "eu-central-1"
5 shared_credentials_files = ["/Users/rahulwagh/.aws/credentials"]
6}
7
8resource "aws_instance" "ec2_example" {
9 ami = "ami-0767046d1677be5a0"
10 instance_type = "t2.micro"
11 tags = {
12 Name = "Terraform EC2 "
13 }
14}
15
16# The following null resource will print message "Hello World"
17resource "null_resource" "null_resource_simple" {
18 provisioner "local-exec" {
19 command = "echo Hello World"
20 }
21}
Output -
2. What is the trigger inside null_resource?
The trigger is a block inside the null_resource which holds key-value pair. But to understand the trigger please have look at the following points -
- As the name suggest trigger, it will execute local-exec, remote-exec or data block.
- trigger will only work when it detects the change in the key-value pair
- trigger can only work once if key-value is changed once but on the other hand if the key-value pair changes its value every time it will execute the every time you run
$terraform apply
command.
Example-
1#main.tf
2
3provider "aws" {
4 region = "eu-central-1"
5 shared_credentials_files = ["/Users/rahulwagh/.aws/credentials"]
6}
7
8resource "aws_instance" "ec2_example" {
9 ami = "ami-0767046d1677be5a0"
10 instance_type = "t2.micro"
11 tags = {
12 Name = "Terraform EC2 "
13 }
14}
15
16# The following null resource has the trigger
17resource "null_resource" "null_resource_simple" {
18
19 # This trigger will only execute once when it detects the instance id of EC2 instance
20 triggers = {
21 id = aws_instance.ec2_example.id # to execute it every time replace - id = time()
22 }
23 provisioner "local-exec" {
24 command = "echo Hello World"
25 }
26}
**Note - Further down the post we will take a look at how to execute trigger every time.
Use Case 1 - null_resource with local provisioner
In the previous section, we have seen a very basic example of local-exec provisioner where we have executed hello world program. But with null resource and local-exec provisioner you can do more.
Here are a few examples -
1. Run multiple commands- The local-exec provisioner is not limited to running single command but instead, you can run multiple commands within local-exec provisioner using the null_resource.
1resource "null_resource" "null_resource_simple" {
2
3 triggers = {
4 id = aws_instance.ec2_example.id
5 }
6 provisioner "local-exec" {
7 command = <<-EOT
8 chmod +x install-istio.sh
9 ./install-istio.sh
10 EOT
11 }
12}
2. Create a file- As you know local-exec provisioner gives you the liberty to execute shell commands, so you can pretty much do everything possible with your terminal. For example, you can create the file -
1 resource "null_resource" "null_resource_simple" {
2
3 triggers = {
4 id = aws_instance.ec2_example.id
5 }
6 provisioner "local-exec" {
7 command = <<-EOT
8 touch hello-world.txt
9 EOT
10 }
11}
I hope the above two examples are sufficient enough for you to explore various possibilities of null_resource along with local-exec provisioner.
Use Case 2 - null_resource with remote provisioner
The second use case for null_resource is to use it with remote_provisioner. With the help of remote_provisioner you can execute commands on the remote machine. To explain a bit further we are going to take an example in which -
- First we will setup the ec2 instance
- Write null_resource and remote-exec provisioner
- Use the remote-exec provisioner to connect remote EC2 instance
- After a successful connection create a txt file.
Here is how the terraform code would look like -
1resource "aws_instance" "ec2_example" {
2 ami = "ami-0767046d1677be5a0"
3 instance_type = "t2.micro"
4 tags = {
5 Name = "Terraform EC2 "
6 }
7}
8
9resource "null_resource" "null_resource_with_remote_exec" {
10
11 triggers = {
12 id = aws_instance.ec2_example.id
13 }
14
15 provisioner "remote-exec" {
16 inline = [
17 "touch hello.txt",
18 "echo helloworld remote provisioner >> hello.txt",
19 ]
20 }
21
22 connection {
23 type = "ssh"
24 host = ec2_example.id
25 user = "ubuntu"
26 private_key = file("/home/rahul/Jhooq/keys/aws/aws_key")
27 timeout = "4m"
28 }
29
30}
Use Case 3 - Using trigger to execute null_resource everytime
In the final use case, we are going to see how to execute trigger every time inside the null_resource. Always remember trigger inside the null_resource always retains and key-value pair. If there is an update in the value of key-value pair then null_resource will execute every time.
Here is a Terraform code example -
1# main.tf
2
3provider "aws" {
4 region = "eu-central-1"
5 shared_credentials_files = ["/Users/rahulwagh/.aws/credentials"]
6}
7
8resource "aws_instance" "ec2_example" {
9 ami = "ami-0767046d1677be5a0"
10 instance_type = "t2-micro"
11 tags = {
12 Name = "Terraform EC2 "
13 }
14}
15
16# This null_resource will be executed everytime because of id = time().
17resource "null_resource" "null_resource_simple" {
18
19 # Look carefully in the trigger we have assigned time() which we change value every time you run $terraform apply command.
20 triggers = {
21 id = time()
22 }
23
24 provisioner "local-exec" {
25 command = "echo Hello World"
26 }
27}
time() - Time function is just an example in which we always get a different value and due to which the local-exec provisioner gets executed all the time.
Advantages of null_resource
Here are some the advantages of the null_resource -
-
Don't create any infrastructure resources - It allows you to perform actions that don't create any infrastructure resources, such as running a local script or making an API call. This can be useful for tasks that need to be performed as part of your infrastructure deployment, but don't involve creating or modifying resources.
-
Automate tasks and integrate with external systems - It provides a convenient way to automate tasks and integrate with external systems as part of your infrastructure deployment. This can save you time and effort by allowing you to automate repetitive tasks, and integrate your infrastructure with other systems and services.
-
Modular and reusable infrastructure code - It allows you to create modular and reusable infrastructure code, by separating the actions that create resources from the actions that perform other tasks. This can make your infrastructure more maintainable and easier to understand, as it follows the principle of separating concerns.
-
Variety of provisioners - It allows you to use a variety of provisioners, depending on your needs and preferences. For example, you can use the local-exec provisioner to run a local script, the http provisioner to make an HTTP request, or the remote-exec provisioner to run a script on a remote host. This flexibility allows you to choose the most appropriate provisioner for each task.
-
Powerful and Flexible - Overall, the null_resource in Terraform provides a powerful and flexible way to perform actions that don't create infrastructure resources, allowing you to automate tasks and integrate with external systems as part of your infrastructure deployment.
Conclusion
I hope this blog will help you to understand the null_resource and trigger in a simple way. There are various applications and use cases for null_resources and they might differ based on your project needs. But the idea of this blog is to cover the basics use cases so that it is easy to understand.
To read further you can refer to Terraform's official documentation on null_resource.
Posts in this Series
- Securing Sensitive Data in Terraform
- Boost Your AWS Security with Terraform : A Step-by-Step Guide
- How to Load Input Data from a File in Terraform?
- Can Terraform be used to provision on-premises infrastructure?
- Fixing the Terraform Error creating IAM Role. MalformedPolicyDocument Has prohibited field Resource
- In terraform how to handle null value with default value?
- Terraform use module output variables as inputs for another module?
- How to Reference a Resource Created by a Terraform Module?
- Understanding Terraform Escape Sequences
- How to fix private-dns-enabled cannot be set because there is already a conflicting DNS domain?
- Use Terraform to manage AWS IAM Policies, Roles and Users
- How to split Your Terraform main.tf File into Multiple Files
- How to use Terraform variable within variable
- Mastering the Terraform Lookup Function for Dynamic Keys
- Copy files to EC2 and S3 bucket using Terraform
- Troubleshooting Error creating EC2 Subnet InvalidSubnet Range The CIDR is Invalid
- Troubleshooting InvalidParameter Security group and subnet belong to different networks
- Managing strings in Terraform: A comprehensive guide
- How to use terraform depends_on meta argument?
- What is user_data in Terraform?
- Why you should not store terraform state file(.tfstate) inside Git Repository?
- How to import existing resource using terraform import comand?
- Terraform - A detailed guide on setting up ALB(Application Load Balancer) and SSL?
- Testing Infrastructure as Code with Terraform?
- How to remove a resource from Terraform state?
- What is Terraform null Resource?
- In terraform how to skip creation of resource if the resource already exist?
- How to setup Virtual machine on Google Cloud Platform
- How to use Terraform locals?
- Terraform Guide - Docker Containers & AWS ECR(elastic container registry)?
- How to generate SSH key in Terraform using tls_private_key?
- How to fix-Terraform Error acquiring the state lock ConditionalCheckFiledException?
- Terraform Template - A complete guide?
- How to use Terragrunt?
- Terraform and AWS Multi account Setup?
- Terraform and AWS credentials handling?
- How to fix-error configuring S3 Backend no valid credential sources for S3 Backend found?
- Terraform state locking using DynamoDB (aws_dynamodb_table)?
- Managing Terraform states?
- Securing AWS secrets using HashiCorp Vault with Terraform?
- How to use Workspaces in Terraform?
- How to run specific terraform resource, module, target?
- How Terraform modules works?
- Secure AWS EC2s & GCP VMs with Terraform SSH Keys!
- What is terraform provisioner?
- Is terraform destroy needed before terraform apply?
- How to fix terraform error Your query returned no results. Please change your search criteria and try again?
- How to use Terraform Data sources?
- How to use Terraform resource meta arguments?
- How to use Terraform Dynamic blocks?
- Terraform - How to nuke AWS resources and save additional AWS infrastructure cost?
- Understanding terraform count, for_each and for loop?
- How to use Terraform output values?
- How to fix error configuring Terraform AWS Provider error validating provider credentials error calling sts GetCallerIdentity SignatureDoesNotMatch?
- How to fix Invalid function argument on line in provider credentials file google Invalid value for path parameter no file exists
- How to fix error value for undeclared variable a variable named was assigned on the command line?
- What is variable.tf and terraform.tfvars?
- How to use Terraform Variables - Locals,Input,Output
- Terraform create EC2 Instance on AWS
- How to fix Error creating service account googleapi Error 403 Identity and Access Management (IAM) API has not been used in project before or it is disabled
- Install terraform on Ubuntu 20.04, CentOS 8, MacOS, Windows 10, Fedora 33, Red hat 8 and Solaris 11