Help create terraform module use Kubernetes provider

Hi, everyone!

I’m writing a terraform module using kubernetes provider, I coded namespace resource using the variable named namespace with a type map(any) .

The resoure namespace I use for_each, becouse I will have many namespace in the same project, and increment wthi new map.

variables.tf:

variable "namespace" {
  type = map(any)
  default = {}
  description = "Map key/value to configure `Namespace`."
}

main.tf

resource "kubernetes_namespace_v1" "default" {
  for_each = var.namespace
  metadata = each.value.metadata
}

I configured the namespace.tf with following

module "ns" {
  source = "../../tf-modules/kubernetes"

  namespace = {
    ns_01 = {
      metadata = {
        name = "awx"
  
        labels = {
          "istio-injection" = "enabled"
          "kubernetes.io/metadata.name" = "awx"
        }
      }
    }
  }
}

But when I going test I’m receiving the following error message:

I understand is not recognizing my namespace variable, but I don’t have idea where is my erro.

If anyone can point me to a way that I can research what I’m doing wrong, I’d be grateful,

Hi @leandro,

This error message is trying to tell you that you are using the wrong syntax to declare your metadata block inside this resource block. Specifically, you are trying to use it as if it were an argument, whereas the provider schema expects a nested block containing its own arguments.

You’ve also used an incorrect type constraint for variable "namespace"; you are claiming that namespace elements can be of any type, but that isn’t true because the provider has specific expectations for which arguments are allowed in a metadata block.

Here’s a version of your code which I think fixes both of the problems:

variable "namespace" {
  type = map(object({
    annotations   = optional(map(string))
    generate_name = optional(string)
    labels        = optional(map(string))
    name          = optional(string)
  }))
}

resource "kubernetes_namespace_v1" "default" {
  for_each = var.namespace

  metadata {
    annotations   = each.value.annotations
    generate_name = each.value.generate_name
    labels        = each.value.labels
    name          = each.value.name
  }
}

I assumed that it was your intention to allow all of the arguments the provider accepts in the metadata block, but if you wish your module to only allow name and labels in particular then you can remove the other two attributes from the type constraint and from the metadata block.

Hi, @apparentlymart

Thank very much, I implemented you sugestion and my code work.

Thanks your help.