Search code examples
terraformterraform-modules

Terraform Module throw provider configuration not present when modifying


I have a standalone module that previously used implicit provider inheritence. I now need to pass the providers explicitly. As I need to reference resources in multiple regions. After making the change to the module, before publishing it, if I run terraform validate then I get several Error: Provider configuration not present errors.

│ Error: Provider configuration not present
│ 
│ To work with aws_api_gateway_method.function_proxy_root its original provider configuration at
│ provider["registry.terraform.io/hashicorp/aws"].env 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_api_gateway_method.function_proxy_root, after which you can remove the provider configuration again.

I have read Terraform - refactoring modules: Error: Provider configuration not present. However, I don't believe this is my problem. As this is a standalone module, so there is no state for it to reference. I must not understand something; as I cannot see how Terraform can know that I have made the change.

Any advice would be greatly appreciated.


Solution

  • From what you've shared it seems like you are trying to use terraform validate directly with a module that is designed to be called from another module. You've asked Terraform to validate it as a root module, and so Terraform is reporting that this module is not valid to use as a root module because it expects a calling module to pass it a provider configuration, but there is no calling module in this case.

    (The error message is admittedly confusing for this situation. Terraform thinks that on a previous run you had a provider "aws" block in this module because for a root module that would be the only way for this module to have been valid. Terraform doesn't know that this module has never been used as a root module before, so it's making an incorrect assumption when deciding how to describe this problem.)

    If you want to validate a module that is intended to be called from another module, a typical solution is to create a development-time-only root module that exists only for you to validate and test your module in isolation.

    For example, you could make a subdirectory test and place in it a test.tf file containing the following source code:

    terraform {
      required_providers {
        aws = {
          source = "hashicorp/aws"
        }
      }
    }
    
    provider "aws" {
    }
    
    module "main" {
      source = "../"
    
      # ...
    
      providers = {
        aws.env = aws
      }
    }
    

    You can then validate your shared module in the context of this stub root module like this:

    • cd test
    • terraform init (to initialize the test directory as a root module working directory)
    • terraform validate (to validate the entire configuration all together, including both this stub root module and the main module you want to validate)

    Terraform should then see that your root module is passing a hashicorp/aws provider configuration into the aws.env configuration slot declared by the shared module, and therefore consider this overall configuration to be valid.

    A bonus benefit of this approach is that you can also perform other operations using that test subdirectory, such as running terraform plan assuming that you have suitable environment variables set to allow configuring the hashicorp/aws provider, so that you can try out your module in isolation before you update other configurations to use it.