Terraform: error removing module containing legacy provider block, ‘Provider configuration not present’

If you have just removed a module declaration from your Terraform configuration and now get a ‘Provider configuration not present’ error when running apply:

Error: Provider configuration not present

To work with module.mymodule_legacysyntax.null_resource.test_rs (orphan) its original provider configuration at
module.mymodule_legacysyntax.provider["registry.terraform.io/hashicorp/null"] 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 module.mymodule_legacysyntax.null_resource.test_rs (orphan), after which
you can remove the provider configuration again.

Then the module is using a legacy method of including provider blocks directly in its module definition.  Either you have:

  • [Scenario #1] Removed the declaration of the module completely
  • [Scenario #2] Removed a single direct provider from inside the module itself

Download Example

In order to recreate the issue and provide a resolution, I’ve created a sample project on github.  It uses only local providers (time and null) and local file state to avoid any cloud infrastructure charges.

git clone https://github.com/fabianlee/tf-example-modules-legacy-and-newer-syntax
cd tf-example-modules-legacy-and-newer-syntax

terraform init
terraform apply

If you look at main.tf, you can see it includes a module.

module mymodule_legacysyntax {                                                            
  source = "./module-legacy-syntax"                                                       
}

And this module definition, module-legacy-syntax/main.tf, uses a legacy method of directly including its own provider blocks.

# legacy syntax (< v0.10) of provider blocks directly inside module
provider null { }
provider time { }

Scenario 1: Recreate issue with entire module removal

Comment out the module definition in main.tf to simulate our attempt to remove this module from management.

#module mymodule_legacysyntax {                                                            
#  source = "./module-legacy-syntax"                                                       
#}

Run “terraform apply”, and you will now see the “Error: Provider configuration not present” error.

Resolve issue with entire module removal

Reinclude the module back in main.tf

Remove the pound sign comments to re-include the module definition.

module mymodule_legacysyntax {                                                            
  source = "./module-legacy-syntax"                                                       
}

Rerun “terraform init”

terraform init

In a more complex configuration, you may have to use “terraform init −−upgrade”.

Remove the module from Terraform state

# terraform remove −−target module.<moduleName>
terraform destroy --auto-approve --target module.mymodule_legacysyntax

Remove the module definition from main.tf

Only now that the module is removed from state should you remove the module definition.  We will comment it out again.

#module mymodule_legacysyntax {                                                            
#  source = "./module-legacy-syntax"                                                       
#}

Rerun “terraform apply”

With the module removed from Terraform state and now also the main.tf definition, apply should run without errors.

terraform apply

 

Scenario 2: Recreate issue with removal of provider block inside legacy module

There is another scenario to consider where we own and control the legacy module code, and we do not remove the entire module (like first example).  Instead we remove a single legacy provider block in the module.

Consider the code in module-legacy-syntax/main.tf where we have a “null” and “time” provider.  If we comment out the null provider and its resources like below.

# commenting out null provider
#provider null { }                                                                        
provider time { }                                                                         
                                                                                          
# commenting out use of null provider                                                                    
#resource null_resource     test_rs  {}                                                   
#resource null_resource     test_rs2 {}                                                   
#data     null_data_source  test_ds  {}

Then ran “terraform apply”, we would get the “Error: Provider configuration not present” message for the same reason we got it when removing the entire module.

Resolve issue with removal of single legacy provider block

Reinclude the provider definition back in module-legacy-syntax/main.tf

# reinclude 'null' provider and its resources
provider null { }                                                                        
provider time { }                                                                         
                                                                                          
# commenting out use of null provider                                                                    
resource null_resource     test_rs  {}                                                   
resource null_resource     test_rs2 {}                                                   
data     null_data_source  test_ds  {}

Re-run “terraform init”

terraform init

In a more complex configuration, you may have to use “terraform init −−upgrade”.

Remove all the associated resources from Terraform state

This is the most complex step, because you will need to remove each of the resources associated with this single provider from the Terraform state.  The command will be in the syntax below:

terraform remove −−target module.<moduleName>.<resourceType>.<resourceName>

The best way to identify these is to parse the Terraform state file with a yaml/json parser.  If your Terraform state is remote, then temporarily pull it down for parsing.

[[ -f terraform.tfstate ]] || terraform state pull > terraform.tfstate

Then run the Terraform state file through a json parser to identify all the resources associated with the single provider.

# make sure jq json parser utility is installed
sudo apt install -y jq

# variables defining module and provider we want to remove
my_module="module.mymodule_legacysyntax"
my_module_source="hashicorp/null"

# jq expression that prints terraform destroy commands that need to be run
# you MUST run each of these manually
jq -r ".resources[] | select(.module == \"$my_module\" and .mode == \"managed\" and (.provider | contains(\"$my_module_source\")) ) | [.module,.type,.name] | @csv" terraform.tfstate | sed 's/\"//g; s/,/\./g' | xargs printf "terraform destroy --auto-approve --target %s\n"

With all the resources associated with this provider now removed from the Terraform state, we can remove the provider and its resources from the configuration.

Remove the provider definition and it resources from module-legacy-syntax/main.tf

# commenting out null provider
#provider null { }                                                                        
provider time { }                                                                         
                                                                                          
# commenting out use of null provider                                                                    
#resource null_resource     test_rs  {}                                                   
#resource null_resource     test_rs2 {}                                                   
#data     null_data_source  test_ds  {}

Rerun “terraform apply”

With the resources associated with this single provider removed from Terraform state, apply should run without errors.

terraform apply

 

 

REFERENCES

Terraform docs, legacy shared modules with provider configurations

github fabianlee, example project for this article, tf-example-modules-legacy-and-newer-syntax

github issue, showing steps how to resolve error

NOTES

yq equivalent command to identify resources

yq e ".resources[] | select(.module == \"$my_module\" and .mode == \"managed\" and (.provider | contains(\"$my_module_source\")) ) | [.module,.type,.name]" terraform.tfstate -o=csv | sed 's/,/\./g' | xargs printf "terraform destroy --auto-approve --target %s\n"