3

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?

2 Answers 2

2

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
}
Sign up to request clarification or add additional context in comments.

Comments

1

You should be able to pass kubernetes_namespace.this.metadata.0.name to the module instead and just have the module variable take a string. That should give you the required dependency chain and also simplify things a little.

So your module's inputs.tf should have:

variable "namespace" {
  type = string
}

and then you call it like this:

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

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

    namespace = kubernetes_namespace.this.metadata.0.name
    workers   = 1
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.