Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

terraform: module variable as object

Tags:

terraform

This is my module snippet:

inputs.tf:

variable "namespace" {
    type = object({
        metadata = object({
            name = string
        })
    })
}

main.tf:

resource "helm_release" "spark" {
    name       = "spark"
    repository = "https://charts.bitnami.com/bitnami" 
    chart      = "spark"
    version    = "1.2.21"
    namespace  = var.namespace.metadata.name
}

As you can see, I'm trying to get access to previously created kubernetes_namespace.

Into my environment workspace:

resource "kubernetes_namespace" "this" {
    metadata {
        name = var.namespace
    }
}

module "spark" {
    source = "../modules/spark"

    namespace = kubernetes_namespace.this
    workers = 1
}

I'm getting this message when I'm trying to get plan:

➜  development terraform plan | xclip -selection clipboard

Error: Invalid value for module argument

  on main.tf line 14, in module "spark":
  14:     namespace = kubernetes_namespace.this

The given value is not suitable for child module variable "namespace" defined
at ../modules/spark/inputs.tf:1,1-21: attribute "metadata": object required.

Any ideas?

like image 519
Jordi Avatar asked Jan 22 '26 21:01

Jordi


1 Answers

The error is reporting that the value you've assigned to the namespace variable is not compatible with its type constraint.

The metadata attribute of kubernetes_namespace seems to be defined as a list of objects rather than as a single object, and so automatic type conversion here is impossible. One way you could proceed here is to change your variable's type to match the resource type schema, like this:

variable "namespace" {
    type = object({
        metadata = list(object({
            name = string
        }))
    })
}

We can see in the provider implementation that this block is defined as having MaxItems: 1 and so as long as that remains true (which seems likely) you can expect var.namespace.metadata to be either an empty list or a single-item list, which you could write in a local variable for easier use elsewhere in the module:

locals {
  namespace_name = var.namespace.metadata[0].name
}

The above will make local.namespace_name refer to the given namespace name, or the expression will fail if the given namespace doesn't have a metadata block, because there will be no element [0] in that case.


The above is a lot of complexity just to get access to the namespace name. A structure like the above could be useful if you expect to need to use other attributes of the kubernetes_namespace object in future, but if you can get by with just the name then it could be helpful to simplify this to be just a single string variable with the namespace name directly:

variable "namespace_name" {
  type = string
}

...and you can let the caller worry about how to obtain that name:

resource "kubernetes_namespace" "this" {
    metadata {
        name = var.namespace
    }
}

module "spark" {
    source = "../modules/spark"

    namespace_name = kubernetes_namespace.this.metadata.name
    workers        = 1
}
like image 105
Martin Atkins Avatar answered Jan 25 '26 18:01

Martin Atkins



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!