Check Block
The "check" block is a new feature available since version 1.5.0 and later that allows you to define custom conditions that are always checked during a Terraform plan or apply run but which don't affect the outcome of the operation.
The "check" block serves to enable verification of your infrastructure outside of normal resource lifecycle. This will bridge the gap between post-apply and functional validation of your infrastructure. As a result, when you use "check" blocks, it runs as the final part of a plan or apply operation after Terraform planned or provisioned your infrastructure so additional validation checks on the deployed infrastructure can be performed without affecting the overall success or failure of the plan or apply.
<condition> {
condition = <expression>
error_message = <expression>
}
Check block Syntax
The syntax of a check block is as follows:
resource resource_type local_name {
# arguments
}
Here is the breakdown of syntax:
check
is the keyword that declares a check block.
local_name
is the local name given to the check block.
- The block body (between
{}
) contains either zero or one datasource and at least one assert block.
Here is a sample check block that checks the contents of a file.
check "verify_file_content" { data "local_file" "local-testing" { filename = "file.txt" } assert { condition = data.local_file.local-testing.content == "same" error_message = "Content in this file is different" } }
Terraform will perform the following actions: data.local_file.local-testing: Reading... data.local_file.local-testing: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7] Plan: 0 to add, 0 to change, 0 to destroy. Warning: Check block assertion failed Content in this file is different Enter a value: yes data.local_file.local-testing: Reading... data.local_file.local-testing: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7] Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Warning: Check block assertion failed Content in this file is different
During the Terraform plan or apply operation, the check block is executed as the last. If this condition in the assert block is not met, Terraform will report an error message, but will not terminate the execution of Terraform.
Blocks Used in Check Block
The Check consists of two major blocks:
- Scoped Datasourceblock
- Assert Block
Scoped Datasource Block
Data sources in Terraform are a way of accessing data that is defined outside of Terraform. For example, information defined in another, separate Terraform configuration. Each provider in Terraform (e.g., AWS, Azure, Google Cloud) may provide a set of data sources in addition to the resource types that it supports. Data sources are considered read-only resources; Terraform will only read information from the external source and will not create, update, or delete any infrastructure objects.
Data sources used within a check block are referred to as
Scoped data sources
. These data sources cannot be referenced outside the block where they are defined. If a scoped data source's provider encounters an error, Terraform will only warn instead of aborting the operation. Let's take an example. Suppose we have a local_file data source inside of a block. If the file test.txt does not exist, then the local_file data source will fail. Since it's a scoped data source, Terraform will not abort the process. It will just show a warning message indicating that an error has occurred, and the Terraform run will continue.
check "verify_file_content" { data "local_file" "check_file" { filename = "./test.txt" } assert { condition = data.local_file.check_file.content == "content" error_message = "The file content is different" } }
Terraform will perform the following actions: data.local_file.local-testing: Reading... Plan: 0 to add, 0 to change, 0 to destroy. Warning: Read local file data source error The file at given path cannot be read +Original Error: open ./test.txt: no such file or directory Enter a value: yes data.local_file.local-testing: Reading... data.local_file.local-testing: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7] Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Warning: Read local file data source error The file at given path cannot be read +Original Error: open ./test.txt: no such file or directory
Meta-arguments of Scoped Datasource
1. depends_on
depends_on is a metaargument in Terraform that explicitly specifies dependencies of resources. It is used where Terraform cannot, by itself, automatically infer the dependency between resources.
When running Terraform for the very first time, an the initial plan (not while apply phase) may check block fail due to resources not yet created, resulting in these warning messages. To fix this, make use of depends_on so the scoped data source would run only after a particular resource (for example, a load balancer) has been created. This way, the check will only run when the essential infrastructure is present.
Suppose you have a check block using a local_file data source for checking contents of a file. In this case, using depends_on you ensure that the local_file data source runs only after the file has been created, thus avoiding unnecessary error messages.
resource "null_resource" "command" { provisioner "local-exec" { command = "echo 'content'>./test.txt" } } check "verify_file_content" { data "local_file" "check_file" { filename = "./test.txt" } assert { condition = data.local_file.check_file.content == "content" error_message = "The file content is different" } }
data.local_file.check_file: Reading...
data.local_file.check_file: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7]
Terraform will perform the following actions:
# null_resource.command will be created
+ resource "null_resource" "command" {
+ id = (known after apply)
+ }
Plan: 1 to add, 0 to change, 0 to destroy.
Warning: Check block assertion failed
The file content is different
Enter a value: yes
data.local_file.ping-website: Reading...
data.local_file.ping-website: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7]
null_resource.exposing_sensitive: Creating...
null_resource.exposing_sensitive: Provisioning with 'local-exec'...
null_resource.exposing_sensitive (local-exec): Executing: ["/bin/sh" "-c" "echo 'content'>./test.txt"]
null_resource.exposing_sensitive: Creation complete after 0s [id=7139618234716910930]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
In this case, the local_file datasource tried to read before the null_resource append the content to test.txt file which is in the current location hence got into warning message. To avoid the warning message you use depends_on to explicitly specify the dependency to terraform then datasource from check block will start to run after dependency completed successfully. For Example
resource "null_resource" "command" { provisioner "local-exec" { command = "echo 'content'>./test.txt" } } check "verify_file_content" { data "local_file" "check_file" { filename = "./test.txt" depends_on = [null_resource.command] } assert { condition = data.local_file.check_file.content == "content" error_message = "The file content is different" } }
Terraform will perform the following actions: data.local_file.ping-website: Reading... data.local_file.ping-website: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7] Plan: 0 to add, 0 to change, 0 to destroy. Warning: Check block assertion known after apply Warning: The condition could not be evaluated at this time, a result will be known when this plan is applied. Enter a value: yes data.local_file.ping-website: Reading... data.local_file.ping-website: Read complete after 0s [id=1c58a446a63e719d7b90156a8998ccc461609ed7] null_resource.exposing_sensitive: Creating... null_resource.exposing_sensitive: Provisioning with 'local-exec'... null_resource.exposing_sensitive (local-exec): Executing: ["/bin/sh" "-c" "echo 'content'>./test.txt"] null_resource.exposing_sensitive: Creation complete after 0s [id=7139618234716910930] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
In this case, you wouldn't see the warning message due to check block failure. This is because Terraform executed local_file datasource after null_resource could provision entirely or, in other words, once
known after apply
id value was known to Terraform.
NOTE: The above same output you will get when you followed implicit dependency when using resource attributes in scoped data source.
2. provider
The provider meta-argument in Terraform is a special argument that allows to specify which provider configuration should be used with a particular resource. This overrides the default behavior of Terraform where it selects a provider configuration based on resource type name. For more details refer providers in datasource.
assert block
An assert block provides a way in Terraform to validate custom conditions inside a check block. Essentially, it is used to verify whether the infrastructure deployment is correct after the Terraform plan or apply is executed. A check block must have at least one assert block, though it can have more.
An assert block consists of two attributes:
condition
A custom condition to validate. This may reference scoped data sources in the same enclosing check block as well as variables, resources, data sources or module outputs in the current module.
error_message
The message that is to be displayed in case of failure of the condition.
If an assert block fails, Terraform will report a warning including the error message but doesn't stop the operation, meaning the Terraform run will complete even if the assertion fails.
Let's take an example to show how assert blocks make use of custom conditions within a check block in Terraform. The check block validates whether the deployment of the infrastructure is correct after the Terraform plan or apply is finished. This example consists of two files, which are server/main.tf (Child Module) and main.tf (Root Module), which define an AWS instance, a null resource, and a variable.
// File: server/main.tf (Child Module) resource "aws_instance" "instance" { ami = var.ami instance_type = "t2.micro" tags = { Name = "Dev Instance" } } output "instance_type" { value = aws_instance.instance.instance_type } // File: main.tf (Root Module) resource "null_resource" "command" { provisioner "local-exec" { command = "echo 'content'>./test.txt" } } module "server" { source = "./server/main.tf" } variable "region" { default = "us-east-1" } data "aws_instance" "server" { instance_id = "i-74w84s368h7t42d4" } check "verify_infrastructure" { assert { condition = data.local_file.check_file.content == "content" error_message = "The file content is different" } assert { condition = module.server.instance_type == "t2.micro" error_message = "The Dev server instance type is different" } assert { condition = var.region == "us-east-1" error_message = "Instance created region is different" } assert { condition = data.aws_instance.verify_image _type.ami == "ami-0123456789" error_message = "The Dev server image type is different" } }
Here, the check block verify_infrastructure owns four assert blocks, each responsible for a certain condition: the contents of a local file, the instance type of the Dev server, the region instance creation, and the AMI type of the Dev server image. In case any of these conditions turn out to be false, Terraform will report a warning with an appropriate error message but will not stop the operation.
Related Pages
Feedback
Was this page helpful?