Seemingly, when a validation error occurs in a resource (due to a failing ValidateFunc), terraform plan returns missing resource errors over returning the original validation error that caused the issue even though the underlying EvalValidateResource notices the error.
terraform -v
Terraform v0.11.7
+ provider.aws v1.20.0
+ provider.null v1.0.0
terraform {
required_version = "0.11.7"
}
provider "aws" {
region = "us-east-1"
version = "1.20.0"
}
resource "null_resource" "upstream" {
triggers = {
name = "invalid name"
}
}
# aws_iam_role is an example resource that has a ValidateFunc
resource "aws_iam_role" "test" {
assume_role_policy = "{}"
# Hardcoding this correctly returns the validation error
# name = "invalid name"
name = "${null_resource.upstream.triggers.name}"
}
resource "null_resource" "downstream" {
triggers = {
name = "${aws_iam_role.test.name}"
}
}
https://gist.github.com/bflad/62edb26125e13dbac68d0a556523f1fd
Error: aws_iam_role.test: "name" must match [\w+=,.@-]
2018/05/25 14:48:50 [ERROR] root: eval: *terraform.EvalValidateResource, err: Warnings: []. Errors: ["name" must match [\w+=,.@-]]
2018/05/25 14:48:50 [ERROR] root: eval: *terraform.EvalSequence, err: Warnings: []. Errors: ["name" must match [\w+=,.@-]]
...
2018/05/25 14:48:50 [ERROR] root: eval: *terraform.EvalInterpolate, err: Resource 'aws_iam_role.test' not found for variable 'aws_iam_role.test.name'
2018/05/25 14:48:50 [ERROR] root: eval: *terraform.EvalSequence, err: Resource 'aws_iam_role.test' not found for variable 'aws_iam_role.test.name'
Which is output as:
* null_resource.downstream: 1 error(s) occurred:
* null_resource.downstream: Resource 'aws_iam_role.test' not found for variable 'aws_iam_role.test.name'
terraform initterraform planThis issue relates to:
It seems this issue also goes beyond just ValidateFunc errors not being reported. Here's a fresh example.
Given this example configuration:
# Invalid configuration - do not use this in a real environment
terraform {
required_version = "0.11.8"
}
provider "aws" {
version = "1.36.0"
}
resource "null_resource" "test" {}
resource "aws_launch_template" "test" {
iam_instance_profile = ["${null_resource.test.id}"]
}
output "test" {
value = "${aws_launch_template.test.id}"
}
And this resource schema:
"iam_instance_profile": {
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
// ...
},
},
},
On Terraform 0.11.8, it seems to output a configuration validation error correctly along with the Resource X not found error, but only when both the aws_launch_template resource and its reference are being created at the same time. On first terraform apply:
2 error(s) occurred:
* output.test: Resource 'aws_launch_template.test' not found for variable 'aws_launch_template.test.id'
* aws_launch_template.test: iam_instance_profile.0: expected object, got string
On the second terraform apply it just reports the unhelpful error (from the debug logs we are able to see that the validation error should have been reported):
2018/09/19 11:05:55 [ERROR] root: eval: *terraform.EvalValidateResource, err: Warnings: []. Errors: [iam_instance_profile.0: expected object, got string]
2018/09/19 11:05:55 [ERROR] root: eval: *terraform.EvalSequence, err: Warnings: []. Errors: [iam_instance_profile.0: expected object, got string]
2018/09/19 11:05:55 [TRACE] [walkPlan] Exiting eval tree: aws_launch_template.test
2018/09/19 11:05:55 [DEBUG] plugin: waiting for all plugin processes to complete...
Error: Error running plan: 1 error(s) occurred:
* output.test: Resource 'aws_launch_template.test' not found for variable 'aws_launch_template.test.id'
I tried the following modified version of the first example in v0.12.0-alpha2:
provider "aws" {
region = "us-east-1"
}
resource "null_resource" "upstream" {
triggers = {
name = "invalid name"
}
}
# aws_iam_role is an example resource that has a ValidateFunc
resource "aws_iam_role" "test" {
assume_role_policy = "{}"
# Hardcoding this correctly returns the validation error
# name = "invalid name"
name = "${null_resource.upstream.triggers.name}"
}
resource "null_resource" "downstream" {
triggers = {
name = "${aws_iam_role.test.name}"
}
}
The incorrect message about aws_iam_role.test not being set is gone (:tada:) but it looks like the validation error is still not showing up:
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_iam_role.test will be created
+ resource "aws_iam_role" "test" {
+ arn = (known after apply)
+ assume_role_policy = jsonencode(
{
}
)
+ create_date = (known after apply)
+ force_detach_policies = false
+ id = (known after apply)
+ max_session_duration = 3600
+ name = "invalid name"
+ path = "/"
+ unique_id = (known after apply)
}
# null_resource.downstream will be created
+ resource "null_resource" "downstream" {
+ id = (known after apply)
+ triggers = {
+ "name" = "invalid name"
}
}
# null_resource.upstream will be created
+ resource "null_resource" "upstream" {
+ id = (known after apply)
+ triggers = {
+ "name" = "invalid name"
}
}
Plan: 3 to add, 0 to change, 0 to destroy.
The local validation didn't run during terraform apply either, so the error ended up reported from the remote API instead:
Error: Error creating IAM Role invalid name: ValidationError: The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.@_-
status code: 400, request id: 30854322-dcae-11e8-b38b-47a25fcbf39e
on resource-validation-masked.tf line 17:
17: }
Amusingly though, when I ran terraform destroy it _did_ catch the validation error in the provider:
Error: "name" must match [\w+=,.@-]
on resource-validation-masked.tf line 17:
17: }
This over-zealous validation during destroy is likely just another instance of #19216, not directly related to _this_ issue.
It looks like there's still a validation-related bug here for us to take care of before v0.12.0 final, so I'm going to mark this with the v0.12.0 milestone.
For the second example in the later comment, I did at least get a reasonable error message out of it:
Error: Unsupported attribute
on resource-validation-masked.tf line 28, in resource "aws_launch_template" "test":
28: iam_instance_profile = ["${null_resource.test.id}"]
An attribute named "iam_instance_profile" is not expected here. Did you mean
to define a block of type "iam_instance_profile"?
However, this particular problem is now caught be Terraform Core (by referring to the schema) rather than by the provider itself, so it makes sense that this one would work even if Terraform does not properly pass through the results of the provider's own validation: this error is detected and returned before ValidateResourceConfig is even called on the provider.
I just re-tested this on v0.12.0-alpha4 and verified that it is now fixed:
$ terraform apply
Error: "name" must match [\w+=,.@-]
on resource-validation-masked.tf line 12, in resource "aws_iam_role" "test":
12: resource "aws_iam_role" "test" {
The error message form is still a little strange because the providers and provider SDK could do with some more work to improve these, but that work will happen asynchronously from v0.12.0 development since these error messages are not coming from the main core executable and can thus be updated at any time.
Thanks for reporting this, @bflad!
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.
Most helpful comment
I tried the following modified version of the first example in v0.12.0-alpha2:
The incorrect message about
aws_iam_role.testnot being set is gone (:tada:) but it looks like the validation error is still not showing up:The local validation didn't run during
terraform applyeither, so the error ended up reported from the remote API instead:Amusingly though, when I ran
terraform destroyit _did_ catch the validation error in the provider:This over-zealous validation during destroy is likely just another instance of #19216, not directly related to _this_ issue.
It looks like there's still a validation-related bug here for us to take care of before v0.12.0 final, so I'm going to mark this with the v0.12.0 milestone.
For the second example in the later comment, I did at least get a reasonable error message out of it:
However, this particular problem is now caught be Terraform Core (by referring to the schema) rather than by the provider itself, so it makes sense that this one would work even if Terraform does not properly pass through the results of the provider's own validation: this error is detected and returned before
ValidateResourceConfigis even called on the provider.