Assertions for a resource
The generated skeleton marks which condition can use self and which cannot
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
}Generate the three kinds of assertion Terraform has. Choosing between them comes down to one question, and most people get the answer backwards.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Generate. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
The generated skeleton marks which condition can use self and which cannot
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = var.instance_type
}Data sources take conditions too, and one inside a check block fails softly
data "aws_ami" "ubuntu" {
most_recent = true
}These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
A failed check is a warning. The apply proceeds, so the guard exists, reports the problem, and changes nothing about the outcome.
Instead:Use a precondition or a postcondition when the run must stop. Keep check blocks for what you want reported.
It runs before the object exists, so there is nothing for self to refer to, and using the resource's own address instead is a dependency cycle.
Instead:Check inputs and other resources in a precondition; check the result in a postcondition through self.
Terraform prints the message and the address and nothing else, so a message without the offending value leaves the reader to work out what happened from the configuration.
Instead:Interpolate the value: "Expected at least two subnets, got ${length(var.subnets)}."
Almost everybody adding their first check block expects it to be a gate. It is a monitor: the assertion fails, a warning appears, and the apply succeeds.
Its assert produces a warning in the output and stops nothing. That is useful for something you want reported and are willing to proceed past, such as an endpoint that should be healthy. Used as a guard, the guard is there and does nothing, which is worse than no guard because everybody believes it.
These live inside a resource's lifecycle block and they do stop the run. A precondition is evaluated before Terraform creates or changes the object, so it can prevent the work. A postcondition runs after and checks the result.
The precondition runs before the object exists, so there is nothing to look at, and referring to the resource by its own address is a dependency cycle. In a postcondition, self.attribute is how you check what was actually created.
And its failure produces a warning rather than failing the plan. That is the reason to put a probe there rather than at the top level: an ordinary data source that cannot be read fails the plan, which is exactly what you do not want from something reaching out to the network.
Terraform prints the message and the address and nothing about the values, unless you interpolate them yourself. "Invalid configuration" tells somebody at three in the morning nothing at all; "Expected at least two subnets, got 1" tells them everything.
On an older version each is reported as an unsupported block, naming the block rather than the version. Setting required_version turns that into a message about the version instead.