liveBook · Manning

Check block

As explained in Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu

A Terraform configuration block that evaluates infrastructure assertions and reports failures without stopping Terraform execution.

A deployed API can exist in Terraform state yet fail to answer requests. A check block lets you test that kind of operational expectation with assertions in your configuration. Checks are intended for long-lived infrastructure, including production systems, as well as newly created resources. section 10.6 section 10.6.2

A check resembles a postcondition, but the failure behavior matters: a failed check reports a problem without stopping Terraform from continuing. One check block can contain multiple assertions. By contrast, the illustrated postconditions each need their own block and can stop execution when their requirements fail. Use a check to report health without blocking changes. section 10.6.2

Check an API health endpoint

Place an HTTP data source inside check "health_check", request the API’s /health URL, then assert that its status code is at least 200 and below 300. The data source is scoped to the check: its result can be used by that check’s assertion, but not elsewhere in the configuration. If the data source fails, Terraform issues a warning rather than stopping execution. section 10.6.2

Listing 10.32 check block with scoped data sources
check "health_check" {
  data "http" "api" {                                        #1
    url = "${module.api.url}/health"                         #2
    request_headers = {
      Accept = "application/json"
    }
  }
 
  assert {
    condition     = data.http.api.status_code >= 200 && 
data.http.api.status_code < 300                            #3
    error_message = "Healthcheck failed with status code 
${data.http.api.status_code} and content ${data.http.api.request_body}."
  }
}
#1 If this block fails it won’t stop execution as it’s part of the check block.
#2 You can use attributes and variables inside of these blocks.
#3 You refer to the data block just like you would outside of a check, but these are accessible only inside of the check.

The configuration shows the scoped HTTP request, the status-code assertion, and the failure message together. section 10.6.2

Check the dependency before relying on a health result. A URL built from a module output supplies an implicit dependency. If the URL comes only from an input variable, the check may run during the first plan, before the API exists. Put depends_on = [module.api] on the scoped data source in that case. Scoped data sources accept provider and depends_on, but no other lifecycle arguments. section 10.6.2

Listing 10.33 check block with data source dependencies
check "health_check" {
  data "http" "api" {
    url = var.healthcheck_endpoint                          #1
    request_headers = {
      Accept = "application/json"
    }
 
    depends_on = [module.api]                               #2
  }
 
  assert {
    condition     = data.http.api.status_code >= 200 && 
data.http.api.status_code < 300
    error_message = "Healthcheck failed with status code 
${data.http.api.status_code} and content ${data.http.api.request_body}."
  }
}
#1 Since we are using a variable there is no implicit dependency on this data source.
#2 To prevent the first run of this check from failing we need to make this block depend on the module that launches the API.

The variable-based endpoint example places depends_on on the scoped HTTP data source so the API module launches first. section 10.6.2

Terraform saves check results in state, including results from child modules and every assertion in a check block. This preserves the reported status alongside the infrastructure state; it does not make a failed check a deployment blocker. section 6.3.4 section 10.6.2

How Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu covers it

How deep it goes
Explains multiple assertions, scoped data sources, dependency timing, warnings, and stored results through configurations rather than implementation internals.
Examples
Illustrates an HTTP API health check, a variable-based endpoint needing depends_on, and check results saved in state.
What it assumes
Assumes familiarity with Terraform resources and modules while explaining scoped data sources and dependency timing.
What you can do after
Operate/configure it to report API health while preventing a first-run check from preceding deployment.
How it connects
Connects checks to postconditions, data sources, module dependencies, and Terraform state.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Terraform in Depth: Infrastructure as Code with Terraform and OpenTofu. The section links point to the parts of the book it draws on.