I am setting up an infrastructure on Azure and my tool of choice for the code is Terraform.
To have a nice maintainable code, I decided to use modules. My current structure looks like this:
├── development/
│ ├── main.tf
│ ├── vars.tf
│ ├── outputs.tf
│
├── modules/
│ ├── provider
│ └── resource-group
│ └── eventhub
So, I even put out the provider code into a module. My code looks something like this:
terraform {
backend "azurerm" {}
}
module "provider" {
tenant_id = "${var.tenant_id}"
client_id = "${var.client_id}"
client_secret = "${var.client_secret}"
subscription_id = "${var.subscription_id}"
source = "../modules/provider"
}
module "resource-group" {
source = "../modules/resource-group"
}
module "iothub" {
name = "${module.resource-group.name}"
location = "${module.resource-group.location}"
source = "../modules/iothub"
}
But when I run terraform apply
I get the error message of * provider.azurerm: Error validating provider: No valid (unexpired) Azure CLI Auth Tokens found. Please run
az login.
I already fixed this by moving the code from the provider module into the main.tf
file for my development environment. But I am curious why this is happening in the first place. Is the provider resource required in the root module?
Thanks!
It's not possible to pass a provider configuration upwards so while it is possible to define providers in a module you can't then pass that provider configuration to a parent (including the root) or sibling module.
Terraform's own module documentation that you should define all providers at the root level.
I personally achieve this by defining a single provider file per configuration and then symlink this around to every appropriate location meaning I can change configuration in an easier way but there are other approaches as well.
Note that you may occasionally have a good reason for defining a provider directly in a resource. I personally define the postgresql
provider configuration in my Postgresql RDS module that creates an AWS RDS Postgresql instance and then configures users and databases using the PostgreSQL provider, connecting to the dynamic endpoint exposed by the RDS instance on creation.