Validating modules which have configuration aliases

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?

You’re supposed to not remove provider configurations whilst you still have resources in your Terraform state, that were created using that provider.

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.

The error message you provided specifically refers to existing state.

Try running

terraform state list

to see what Terraform believes is in existing state.

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.”

Hmm… then it may be that you have found a bug.

Can you post the source code of the module, or a cut down version which still reproduces the error?

I’ve managed to reproduce this with the following steps:

  1. mkdir test && cd test
  2. Create tf file with the following content:
resource "aws_acm_certificate" "cloudfront" {
  provider                   = aws.us-east-1
  domain_name                = "mydomain.com"
  validation_method          = "DNS"
}

terraform {
  required_version = ">= 0.13"
  required_providers {
    aws = {
      source = "hashicorp/aws"

      configuration_aliases = [
        aws.us-east-1,
      ]
    }
  }
}
  1. terraform init -backend=false
  2. terraform validate

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 do use validate in a CI environment, but I found I had to assemble an example configuration calling the re-usable module, to do so.

Hi @jack,

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:

module "test" {
  source = "../../"

  providers = {
    aws.us-east-1 = aws
  }
}

provider "aws" {
  region = "us-east-1"
}

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.