Unable to use alternate Google providers

Hi everybody,

I wrote a Terraform code in which the root module calls a child module that creates projects in google folders.

I want Terraform to use the proper google provider for creating projects, therefore in the root module, I defined a default google provider with an empty configuration and multiple alternate google providers, each one having in their configuration the credentials of a service account which has the necessary rights for creating projects in a specific folder. Thus each provider should be able to create projects in the folder in which its service account has the necessary rights as long as the proper folder ID is also passed to the module.
Then in the root module, I set the providers argument within the module block to explicitly define which google provider should be passed to the child module.

However when I run terraform plan I get the following error message:

Error: Attempted to load application default credentials since neither credentials nor access_token was set in the provider block. No credentials loaded. To use your gcloud credentials, run ‘gcloud auth application-default login’. Original error: google: could not find default credentials. See Authenticating as a service account  |  Authentication  |  Google Cloud for more information.

Thus, it seems that since I do not specify a service account credentials in the default google provider, Terraform does not select the alternate providers when running command terraform plan and the command fails since no credentials are selected. What should I do so that Terraform selects the alternate google providers I specified in my code when running commands terraform plan terraform apply or terraform destroy ?

Note that in case I specify only alternate providers and no default provider, I get the following error message in addition :

Provider “registry.terraform.io/hashicorp/google” requires explicit configuration. Add a provider block to the root module and configure the provider’s required arguments as described in the provider documentation.

Thank you in advance for your help

Hi @tne,

In order to provide a convenient experience for the simple case of using just one provider configuration, Terraform will associate all resources with a “default” (unaliased) provider configuration unless you specify otherwise.

In your case it sounds like you have only defined additional (i.e. aliased) provider configurations, and so the default provider configuration isn’t defined and is thus taking on default values, which the hashicorp/google provider in particular doesn’t support.

If you’re intentionally not using a default provider configuration then you’ll need to explicitly specify for each resource which provider configuration it will be associated with, using the provider meta-argument. For example:

resource "google_folder" {
  provider = google.your_chosen_alias
}

If you are calling child modules in your configuration then you’ll also need to specify which provider configurations they should use. In the simplest case, the child module only expects to use a default provider configuration and so it’d be sufficient to map the module’s default google provider configuration to any one of the additional configurations defined in your root module:

module "example" {
  source = "./modules/example"
  providers = {
    google = google.your_chosen_alias
  }
}

The more complicated scenario is when the child module itself works with more than one provider configuration. In that case, the module itself will declare that it’s expecting additional (aliased) provider configurations as part of declaring its dependency on the provider:

terraform {
  required_providers {
    google = {
      source = "hashicorp/google"
      configuration_aliases = [
        child_alias_1,
        child_alias_2,
      ]
    }
  }
}

For a module designed in this way, you’ll be required to specify a providers meta-argument inside the calling module block, in which you’ll define how the child module’s provider configuration aliases will relate to the ones in your root module:

module "example" {
  source = "./modules/example"
  providers = {
    google.child_alias_1 = google.your_chosen_alias_1
    google.child_alias_2 = google.your_chosen_alias_2
  }
}

There’s more detail on all of this in the Provider Configuration section of the Terraform documentation.

1 Like

Hello,

Thank you, the problem from my side came from the fact that I specified configuration_aliases in the child module required_providers configuration like below:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      configuration_aliases = [ google.alternate ]
    }
  }
}

In case I do not specify a required_providers block in the child module, if I call the child module from the root module and I explicitly pass a provider to the child module, I get the following warning

Warning: Provider google is undefined
Module XXX does not declare a provider named google.
If you wish to specify a provider configuration for the module, add an
entry for google in the required_providers block within the module.

To avoid the warning, I removed the configuration_aliases parameter from the required_providers block in the child module as follows:

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
    }
  }
}

Then all is working fine now.

Thank you for your help