terrafrom providers passed down to submodule doesn't work

12/18/2020

I have a module calling another module, I pass kubernetes provider from main to the 1st module which then passes it to the other module. provider passed to 1st module works ok, but the provider passed down from 1st module to other doesn't work

main.tf

data "google_container_cluster" "gke" {
  depends_on = [module.gke]

  name     = var.gke_cluster_name
  project  = var.project_id
  location = var.gke_zone
}

provider "kubernetes" {
  alias                  = "my-kuber"
  host                   = "https://${data.google_container_cluster.gke.endpoint}"
  token                  = data.google_client_config.provider.access_token
  cluster_ca_certificate = base64decode(data.google_container_cluster.gke.master_auth[0].cluster_ca_certificate)
  load_config_file       = false
}

module "first-module" {
  source = "./modules/first-module"

  providers {
    kubernetes.my-kuber = kubernetes.my-kuber
  }
  .
  .
  .
}

first-module.tf

provider "kubernetes" {
  alias = "my-kuber"
}

module "sub-module" {
  source = "./modules/second-module"

  providers {
    kubernetes.my-kuber = kubernetes.my-kuber
  }
  .
  .
  .
}

second-module.tf

provider "kubernetes" {
  alias = "my-kuber"
}

resource "kubernetes_namespace" "ns" {
  provider = kubernetes.my-kuber

  metadata {
    name = var.namespace
  }
}

Here the kubernetes.my-kuber passed down to second_module.tf doesn't have right cluster credentials and it fails

Am I missing something? is passing provider down to sub modules supported?

Thanks in advance

-- RandomQuests
google-kubernetes-engine
kubernetes
terraform

1 Answer

12/18/2020

You don't need to "pass" your provider to your module. The providers attribute in your module is only needed if you have multiple kubernetes provider which seems that is not your case. Only define the provider in the root module on which you are executing the terraform plan, you don't need the provider block in your sub modules. Terraform is able to defined which provider to use base on the resource type : kubernetes_namespace mean that the provider is kubernetes.

Something like this should work fine :

main.tf

data "google_container_cluster" "gke" {
  depends_on = [module.gke]

  name     = var.gke_cluster_name
  project  = var.project_id
  location = var.gke_zone
}

provider "kubernetes" {
  host                   = "https://${data.google_container_cluster.gke.endpoint}"
  token                  = data.google_client_config.provider.access_token
  cluster_ca_certificate = base64decode(data.google_container_cluster.gke.master_auth[0].cluster_ca_certificate)
  load_config_file       = false
}

module "first-module" {
  source = "./modules/first-module"

  .
  .
  .
}

first-module.tf

module "sub-module" {
  source = "./modules/second-module"

  .
  .
  .
}

second-module.tf

resource "kubernetes_namespace" "ns" {
  metadata {
    name = var.namespace
  }
}
-- Jean-Philippe Bond
Source: StackOverflow