I am trying to validate a module which has a provider configuration which contains a configuration alias. When I perform a terraform validate, I receive the following error:
Error: Provider configuration not present
│
│ To work with aws_acm_certificate.cloudfront its original provider configuration at provider["registry.terraform.io/hashicorp/aws"].us-east-1 is required, but it has been removed. This occurs when a provider configuration is removed while
│ objects created by that provider still exist in the state. Re-add the provider configuration to destroy aws_acm_certificate.cloudfront, after which you can remove the provider configuration again.
How am I supposed to validate modules which contain multiple configuration aliases?
I haven’t ever applied this module and there is no preexisting state; I am using terraform validate to verify that the module is reasonably valid before sharing it with others.
No state file was found!
Regardless, terraform validate should not take into account any state: “Validate runs checks that verify whether a configuration is syntactically valid and internally consistent, regardless of any provided variables or existing state.”
The error message you are receiving is misleading, and that feels like it’s worth filing a bug about.
But, terraform validate is correct to generate an error here, since you’re using a provider without configuring it.
terraform validate validates complete Terraform configurations - not individual modules that are incomplete on their own as they rely on providers being passed in by another module calling them.
What you’re saying appears to contradict the documentation, which says that validate may be run ‘as a test step for a re-usable module in a CI system.’
I’ll raise a bug for this and see where I get. Thanks!
I think what’s going on here is that you are using a module that’s designed to be used as a child module (using a module block) directly with the terraform validate command, which is designed for validating entire configurations and so expects to be working with a root module.
In today’s Terraform the best way to test and validate a shared module outside the context of any particular module is to create a simple root module wrapping your module and passing in all of the stuff it would normally expect to receive from its caller, including provider configurations:
You can then ask Terraform to validate the configuration starting at this placeholder root module, which will include validating your shared module’s own declarations.
I typically place my modules like this as subdirectories of a tests directory under my module, which is why the source in my example is ../../. You can place the placeholder root module wherever you like though; this is essentially the Terraform equivalent of writing a small main program to allow you to easily interactively test a library in a general purpose programming language. (And if you are interested in trying the experiment, the naming convention I described also happens to work with terraform test, although you will need a more complete setup in that case because full testing includes plan/apply/destroy actions, rather than just validate.)
We would like to eventually support a mode for validation where it validates only the content of one individual module in isolation, but there isn’t a clear path to supporting that since everything else in Terraform always considers the whole configuration together, and validation currently reuses a lot of internal infrastructure that is shared with all of the other operations.
Since this topic was bumped anyway, it’s a good prompt to add that the situation has changed a little since I wrote my previous comment.
Terraform v1.6 introduced a stabilized version of terraform test which has therefore formalized a slightly different convention for test layout than I described in my earlier comment. Now instead of a directory that contains a normal Terraform module that calls the module under test, Terraform expects .tftest.hcl files that each describe a test scenario.
There’s no reason why you can’t still use a separate root module as a vehicle for validating your shared module under one or more calls, but putting it under a test directory as I suggested would conflict with the new conventions of terraform test, and so I’d suggest using a different directory name instead. For example, if you have an examples directory containing some examples of using your module then you could potentially use validation of that to achieve indirect validation of the shared module.
I don’t think reading the source/spec is a good answer.
In my mind the source/spec is wrong, and unless that is fixed, a good work around is necessary.
The reason I think the source/spec is wrong is simple. You have to define configuration_aliases in order to accept providers provided explicitly to a module, terraform validate validates that you define configuration_aliases correctly so it absolutely understands that concept. If it understands the configuration_aliases concept, why is it complaining when we use that concept!? If a resource uses one of the providers listed in configuration_aliases there is no problem, the code is correct, and should pass validation.
terraform test isn’t a good replacement for terraform validate. It doesn’t complain when I reference resources that don’t exist. Unless I have to write a test for that? If so, urgh, no, get out.
I’m running into this issue again (and forget how I worked around it in the past).
While I do have an “examples/” directory that I use for generating docs, which would also serve to help validate things, I tend to like to validate all modules explicitly standalone, so it’s inconvenient to have to use some kind of workaround to ignore the directory.
It’s also somewhat confusing / misleading that the stuff about the state is still in the error message when, as shown above, it can be thrown when there is no state configured.