Update website/docs/language/checks (#222)

Signed-off-by: Marcin Białoń <mbialon@spacelift.io>
This commit is contained in:
Marcin Białoń 2023-08-29 16:35:43 +02:00 committed by GitHub
parent 9ca1a27be2
commit 26dcb63d0f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -6,19 +6,15 @@ description: >-
# Checks
-> **Note:** Check blocks are only available in Terraform v1.5.0 and later.
The `check` block can validate your infrastructure outside the usual resource lifecycle. Check blocks address a gap between post-apply and functional validation of infrastructure.
> **Hands-on:** Try the [Validate Infrastructure Using Checks](/terraform/tutorials/configuration-language/checks) tutorial.
Check blocks allow you to define [custom conditions](/terraform/language/expressions/custom-conditions) that execute on every Terraform plan or apply operation without affecting the overall status of an operation. Check blocks execute as the last step of a plan or apply after Terraform has planned or provisioned your infrastructure.
Check blocks allow you to define [custom conditions](/opentf/language/expressions/custom-conditions) that execute on every OpenTF plan or apply operation without affecting the overall status of an operation. Check blocks execute as the last step of a plan or apply after OpenTF has planned or provisioned your infrastructure.
## Syntax
You can declare a `check` block with a local name, zero-to-one scoped [data sources](#scoped-data-sources), and one-to-many [assertions](#assertions).
The following example loads the Terraform website and validates that it returns the expected status code `200`.
The following example loads the website and validates that it returns the expected status code `200`.
```hcl
check "health_check" {
@ -37,67 +33,67 @@ check "health_check" {
You can use any data source from any provider as a scoped data source within a `check` block.
A `check` block can optionally contain a nested (a.k.a. scoped) data source. This `data` block behaves like an external [data source](/terraform/language/data-sources), except you can not reference it outside its enclosing `check` block. Additionally, if a scoped data source's provider raises any errors, they are masked as warnings and do not prevent Terraform from continuing operation execution.
A `check` block can optionally contain a nested (a.k.a. scoped) data source. This `data` block behaves like an external [data source](/opentf/language/data-sources), except you can not reference it outside its enclosing `check` block. Additionally, if a scoped data source's provider raises any errors, they are masked as warnings and do not prevent OpenTF from continuing operation execution.
You can use a scoped data source to validate the status of a piece of infrastructure outside of the usual Terraform resource lifecycle. [In the above example](#checks-syntax), if the `placeholderplaceholderplaceholder_io` data source fails to load, you receive a warning instead of a blocking error, which would occur if you declared this data source outside of a `check` block.
You can use a scoped data source to validate the status of a piece of infrastructure outside of the usual OpenTF resource lifecycle. [In the above example](#checks-syntax), if the `placeholderplaceholderplaceholder_io` data source fails to load, you receive a warning instead of a blocking error, which would occur if you declared this data source outside of a `check` block.
#### Meta-Arguments
Scoped data sources support the `depends_on` and `provider` [meta-arguments](/terraform/language/resources/syntax#meta-arguments). Scoped data sources do not support the `count` or`for_each` meta-arguments.
Scoped data sources support the `depends_on` and `provider` [meta-arguments](/opentf/language/resources/syntax#meta-arguments). Scoped data sources do not support the `count` or`for_each` meta-arguments.
##### `depends_on`
The `depends_on` meta-argument can be particularly powerful when used within scoped data sources.
The first time Terraform creates the _initial_ plan for our [previous example](#checks-syntax), the plan fails because Terraform has not applied its configuration yet. Meaning this test fails because Terraform must still create the resources to make this website exist. Therefore, the first time Terraform runs this check, it always throws a potentially distracting error message.
The first time OpenTF creates the _initial_ plan for our [previous example](#checks-syntax), the plan fails because OpenTF has not applied its configuration yet. Meaning this test fails because OpenTF must still create the resources to make this website exist. Therefore, the first time OpenTF runs this check, it always throws a potentially distracting error message.
You can fix this by adding [`depends_on`](/terraform/language/meta-arguments/depends_on) to your scoped data source, ensuring it depends on an essential piece of your site's infrastructure, such as the load balancer. The check returns `known after apply` until that crucial piece of your website is ready. This strategy avoids producing unnecessary warnings during setup, and the check executes during subsequent plans and applies.
You can fix this by adding [`depends_on`](/opentf/language/meta-arguments/depends_on) to your scoped data source, ensuring it depends on an essential piece of your site's infrastructure, such as the load balancer. The check returns `known after apply` until that crucial piece of your website is ready. This strategy avoids producing unnecessary warnings during setup, and the check executes during subsequent plans and applies.
One problem with this strategy is that if the resource your scoped data source `depends_on` changes, the check block returns `known after apply` until Terraform has updated that resource. Depending on your use case, this behavior could be acceptable or problematic.
One problem with this strategy is that if the resource your scoped data source `depends_on` changes, the check block returns `known after apply` until OpenTF has updated that resource. Depending on your use case, this behavior could be acceptable or problematic.
We recommend implementing the `depends_on` meta-argument if your scoped data source depends on the existence of another resource without referencing it directly.
### Assertions
Check blocks validate your custom assertions using `assert` blocks. Each `check` block must have at least one, but potentially many, `assert` blocks. Each `assert` block has a [`condition` attribute](/terraform/language/expressions/custom-conditions#condition-expressions) and an [`error_message` attribute](/terraform/language/expressions/custom-conditions#error-messages).
Check blocks validate your custom assertions using `assert` blocks. Each `check` block must have at least one, but potentially many, `assert` blocks. Each `assert` block has a [`condition` attribute](/opentf/language/expressions/custom-conditions#condition-expressions) and an [`error_message` attribute](/opentf/language/expressions/custom-conditions#error-messages).
Unlike other [custom conditions](/terraform/language/expressions/custom-conditions), assertions do not affect Terraform's execution of an operation. A failed assertion reports a warning without halting the ongoing operation. This contrasts with other custom conditions, such as a postcondition, where Terraform produces an error immediately, halting the operation and blocking the application or planning of future resources.
Unlike other [custom conditions](/opentf/language/expressions/custom-conditions), assertions do not affect OpenTF's execution of an operation. A failed assertion reports a warning without halting the ongoing operation. This contrasts with other custom conditions, such as a postcondition, where OpenTF produces an error immediately, halting the operation and blocking the application or planning of future resources.
Condition arguments within `assert` blocks can refer to scoped data sources within the enclosing `check` block and any variables, resources, data sources, or module outputs within the current module.
[Learn more about assertions](/terraform/language/expressions/custom-conditions#checks-with-assertions).
[Learn more about assertions](/opentf/language/expressions/custom-conditions#checks-with-assertions).
### Meta-Arguments
Check blocks do not currently support [meta-arguments](/terraform/language/resources/syntax#meta-arguments). We are still collecting feedback on this feature, so if your use case would benefit from check blocks supporting meta-arguments, please [let us know](https://github.com/placeholderplaceholderplaceholder/opentf/issues/new/choose).
Check blocks do not currently support [meta-arguments](/opentf/language/resources/syntax#meta-arguments). We are still collecting feedback on this feature, so if your use case would benefit from check blocks supporting meta-arguments, please [let us know](https://github.com/placeholderplaceholderplaceholder/opentf/issues/new/choose).
## Continuous validation in Terraform Cloud
## Continuous validation in TACOS (TF Automation and Collaboration Software)
Terraform Cloud can automatically validate whether checks in a workspaces configuration continue to pass after Terraform provisions new infrastructure. See [Continuous Validation](/terraform/cloud-docs/workspaces/health#continuous-validation) for details.
TACOS (TF Automation and Collaboration Software) can automatically validate whether checks in a workspaces configuration continue to pass after OpenTF provisions new infrastructure.
## Choosing Checks or other Custom Conditions
Check blocks offer the most _flexible_ validation solution within Terraform. You can reference outputs, variables, resources, and data sources within check assertions. You can also use checks to model every alternate [Custom Condition](/terraform/language/expressions/custom-conditions). However, that does not mean you should replace all your custom conditions with check blocks.
Check blocks offer the most _flexible_ validation solution within OpenTF. You can reference outputs, variables, resources, and data sources within check assertions. You can also use checks to model every alternate [Custom Condition](/opentf/language/expressions/custom-conditions). However, that does not mean you should replace all your custom conditions with check blocks.
There are major behavioral differences between check block assertions and other custom conditions, the main one being that check blocks do _not_ affect Terraform's execution of an operation. You can use this non-blocking behavior to decide the best type of validation for your use case.
There are major behavioral differences between check block assertions and other custom conditions, the main one being that check blocks do _not_ affect OpenTF's execution of an operation. You can use this non-blocking behavior to decide the best type of validation for your use case.
### Outputs and variables
[Output postconditions](/terraform/language/expressions/custom-conditions#outputs) and [variable validations](/terraform/language/expressions/custom-conditions#input-variable-validation) both make assertions around inputs and outputs.
[Output postconditions](/opentf/language/expressions/custom-conditions#outputs) and [variable validations](/opentf/language/expressions/custom-conditions#input-variable-validation) both make assertions around inputs and outputs.
This is one of the cases where you might want Terraform to block further execution.
This is one of the cases where you might want OpenTF to block further execution.
For example, it is not helpful for Terraform to warn that an input variable is invalid after it applies an entire configuration with that input variable. In this case, a check block would warn of the invalid input variable _without_ interrupting the operation. A validation block for the same input variable would alert you of the invalid variable and halt the plan or apply operation.
For example, it is not helpful for OpenTF to warn that an input variable is invalid after it applies an entire configuration with that input variable. In this case, a check block would warn of the invalid input variable _without_ interrupting the operation. A validation block for the same input variable would alert you of the invalid variable and halt the plan or apply operation.
### Resource Preconditions and Postconditions
The difference between [preconditions and postconditions](/terraform/language/expressions/custom-conditions#preconditions-and-postconditions) and check blocks is more nuanced.
The difference between [preconditions and postconditions](/opentf/language/expressions/custom-conditions#preconditions-and-postconditions) and check blocks is more nuanced.
Preconditions are unique amongst the custom conditions in that they execute _before_ a resource change is applied or planned. [Choosing Between Preconditions and Postconditions](/terraform/language/expressions/custom-conditions#choosing-between-preconditions-and-postconditions) offers guidance on choosing between a precondition and a postcondition, and the same topics also apply to choosing between a precondition and a check block.
Preconditions are unique amongst the custom conditions in that they execute _before_ a resource change is applied or planned. [Choosing Between Preconditions and Postconditions](/opentf/language/expressions/custom-conditions#choosing-between-preconditions-and-postconditions) offers guidance on choosing between a precondition and a postcondition, and the same topics also apply to choosing between a precondition and a check block.
You can often use postconditions interchangeably with check blocks to validate resources and data sources.
For example, you can [rewrite the above `check` block example](#checks-syntax) to use a postcondition instead. The below code uses a `postcondition` block to validate that the Terraform website returns the expected status code of `200`.
For example, you can [rewrite the above `check` block example](#checks-syntax) to use a postcondition instead. The below code uses a `postcondition` block to validate that the website returns the expected status code of `200`.
```hcl
data "http" "placeholderplaceholderplaceholder_io" {
@ -112,10 +108,10 @@ data "http" "placeholderplaceholderplaceholder_io" {
}
```
Both the `check` and `postcondition` block examples validate that the Terraform website returns a `200` status code during a plan or an apply operation. The difference between the two blocks is how each handles failure.
Both the `check` and `postcondition` block examples validate that the website returns a `200` status code during a plan or an apply operation. The difference between the two blocks is how each handles failure.
If a `postcondition` block fails, it _blocks_ Terraform from executing the current operation. If a `check` block fails, it _does not_ block Terraform from executing an operation.
If a `postcondition` block fails, it _blocks_ OpenTF from executing the current operation. If a `check` block fails, it _does not_ block OpenTF from executing an operation.
If the above example's postcondition fails, it is impossible to recover from. Terraform blocks any future plan or apply operations if your postcondition is unsatisfied during the planning stage. This problem occurs because the postcondition does not directly depend on Terraform configuration, but instead on the complex interactions between multiple resources.
If the above example's postcondition fails, it is impossible to recover from. OpenTF blocks any future plan or apply operations if your postcondition is unsatisfied during the planning stage. This problem occurs because the postcondition does not directly depend on OpenTF configuration, but instead on the complex interactions between multiple resources.
We recommend using check blocks to validate the status of infrastructure as a whole. We only recommend using postconditions when you want a guarantee on a single resource based on that resource's configuration.