I'd previously reported this in #11039, but now I have a much simpler way to reproduce.
0.8.7
https://github.com/nwalke/terraform-nested-module-problem
Error configuring: Unexpected value for InstanceType field: "foo"
Terraform should allow me to target resources in a nested module properly.
I get a strange message about InstanceType.
terraform get
terraform plan -target module.glue.autoscaling.aws_launch_configuration.foo -target module.glue.autoscaling.aws_autoscaling_group.bar
@mitchellh This is a much simpler version of what I previously reported. I haven't gone through every iteration to find EXACTLY the configuration that causes the problem, but hopefully it becomes obvious with how little there is here :)
Got what looks like the same problem.
I have a module nested inside another module, as your example. And when I try to destroy it I receive one of two different messages, depending on how I try it:
$ terraform plan --destroy --target module.sandbox-environment.gateway.aws_elastic_beanstalk_environment.gateway
Error configuring: Unexpected value for InstanceType field: "gateway"
Which is the error you stated on "Panic Output".
$ terraform plan --destroy --target module.sandbox-environment.gateway.aws_elastic_beanstalk_environment
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.
No changes. Infrastructure is up-to-date. This means that Terraform
could not detect any differences between your configuration and
the real physical resources that exist. As a result, Terraform
doesn't need to do anything.
Which is very strange as there is a Beanstalk Environment built that I'd like to destroy.
Thank you :)
I also hit this recently, and noticed that, while the plan output would list module.outer.inner.resource
for resource names, terraform state list
instead lists module.outer.module.inner.resource
. If you target _that_ instead, everything seems to work. Example from @nwalke's repo:
$ terraform plan -target=module.glue.autoscaling
Error configuring: Unexpected value for InstanceType field: "autoscaling"
$ terraform plan -target=module.glue.module.autoscaling
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.
[snip]
Ah ha! Good find @pd. My guess is that's the intended behavior, so if this issue changed to be more about ensuring a decipherable error I'd be happy.
Same problem and solution as @pd. The InstanceType
error message is incredibly misleading and caused me to burn quite a bit of time troubleshooting.
I recently had the same issue when trying to do a terraform taint
:
$ terraform state list
...
module.environment-sandbox.module.autobahn.null_resource.vault-cassandra-auth
...
$ terraform taint module.environment-sandbox.module.autobahn.null_resource.vault-cassandra-auth
Failed to parse resource name: Malformed resource state key: module.environment-sandbox.module.autobahn.null_resource.vault-cassandra-auth
I solved this issue using -module
and the resource's root path:
$ terraform taint -module=environment-sandbox.autobahn null_resource.vault-cassandra-auth
Is this the intended behaviour? Or should the first case also work?
Thanks for the above. This was extremely helpful to resolve an issue with some tfs that someone else wrote that I could not figure out.
Srsly, this still exists in 0.11.1.
The input syntax for taint
is pretty awkward and should be consistent with state list
.
Has anyone had any success with terraform version higher than 0.11.1 and didnt ran into the same issue?
Same issue with v0.11.10 and using nested modules even using a string instead of variable, using as target module.module1.submodule
$ terraform apply --target=module.devops.nexus --auto-approve
Error: Error asking for user input: Unexpected value for **InstanceType field: "nexus"**
Here is the resource:
resource "aws_instance" "nexus" {
count = "${var.create_instance ? 1 : 0}"
ami = "${var.ami_id}"
instance_type = "t3.medium"
#instance_type = "${var.instance_type}"
key_name = "${var.key_name}"
monitoring = true
user_data = "${data.template_file.user_data.rendered}"
vpc_security_group_ids = ["${aws_security_group.nexus.id}"]
subnet_id = "${var.subnet_id}"
tags = "${var.tags}"
}
If I take a look to state list output, the submodules are called with other ".module" string before:
terraform state list
[...]
module.devops.module.jenkins.aws_efs_file_system.jenkins
module.devops.module.jenkins.aws_efs_mount_target.efs_target_jenkins[0]
module.devops.module.jenkins.aws_efs_mount_target.efs_target_jenkins[1]
module.devops.module.jenkins.aws_instance.jenkins_master
module.devops.module.jenkins.aws_security_group.jenkins_efs_endpoint
module.devops.module.jenkins.aws_security_group.jenkins_ssh
module.devops.module.jenkins.aws_subnet.this
module.devops.module.jenkins.template_file.user_data
module.devops.module.nexus.aws_instance.nexus
module.devops.module.nexus.aws_security_group.nexus
module.devops.module.nexus.aws_subnet.this
module.devops.module.nexus.template_file.user_data
[...]
Running apply using the same syntax that shows the list command works fine:
$ terraform apply --target=module.devops.module.nexus --auto-approve
data.template_file.user_data: Refreshing state...
[...]
Try to use the same module syntax that shows terraform list.
Hi everyone!
As others have correctly concluded, the syntax for absolute resource addresses is a sequence of module.name
sequences, followed by a resource type name, and then a resource name.
The reason module.sandbox-environment.gateway.aws_elastic_beanstalk_environment.gateway
failed, then, is because Terraform understood it as:
module.sandbox-environment
gateway
aws_elastic_beanstalk_environment
gateway
Indeed though, the error messages from this resource address parser are poor. This is partially because the resource address microsyntax is terse and doesn't provide many clues for Terraform to use to guess your intent and give a more actionable message, but in the 0.11 implementation the parser also isn't written very robustly.
In master we have a new parser for resource addresses that is built on the same foundation as expressions in the configuration language itself, and so the parsing is more robust but the problem of not enough context to guess intent remains, and so the new error messages are also not very actionable:
Invalid address: Resource instance key must be given in square brackets.
Invalid address: Resource specification must include a resource type and name.
Although the limitations of the syntax limit the assumptions we can make, I think we _could_ do better here by giving the address parser (or, more likely, a separate validation step afterward) access to information about which strings might be valid resource type names (based on provider schema), which strings might be child module names (based on configuration), and then augment these messages with suggestions.
For example, this hypothetical address validator could look at an address starting with module.sandbox-environment.gateway
and check whether gateway
is a valid resource type name for any available provider, see that it isn't, and then check to see if there is a module "gateway"
block inside the sandbox-environment
module. If it finds one, it can make a suggestion:
Invalid address: "gateway" is not a valid resource type name. Did you mean "module.gateway"?
Getting this done would require some refactoring and so we'll not be able to pursue it further in the very near future due to priorities elsewhere, but we'll consider this issue to represent improving these error messages and return to it in a later release.
Hi apparentlymart!
Just to provide more information. It seems that output parser differs from apply parser. With output --module
it doesn't work with module.name
sequences, it works with name
sequences.
Following my previous example:
$ terraform output --module=module.devops.module.nexus
The module root.module.devops.module.nexus could not be found. There is nothing to output.
$ terraform output --module=devops.nexus
private_ip = [
10.240.0.30
]
s3-bucket = arn:aws:s3:::nexus-blob-storage20181210111222233300000001
Most helpful comment
I recently had the same issue when trying to do a
terraform taint
:I solved this issue using
-module
and the resource's root path:Is this the intended behaviour? Or should the first case also work?