kubernetesterraformterraform-template-file

How to pass map in Terraform to a manifest yaml file using templatefile function to set NodeSelector?


I have a manifest yaml file in Terraform to deploy a deployment on a Kubernetes cluster and I want to pass a map having key-value pairs defining node selectors to that yaml file using templatefile function to set nodeSelector on it.

This is how my Terraform code looks like:

...
resource "kubernetes_manifest" "deployment" {
  manifest = yamldecode(
    templatefile("${path.module}/resources/deployment-tmpl.yaml",
      {
        app_name      = var.app_name,
        app_namespace = var.app_namespace
    })
  )
}
...

This is how my manifest yaml code looks like:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: ${app_name}
  name: ${app_name}
  namespace: ${app_namespace}
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: ${app_name}
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ${app_name}
    spec:
      containers:
        ...
...

My node selector variable may look like this:

variable "node_selector" {
  default = {
    "eks.amazonaws.com/nodegroup" = "app"
  }
}

My Terraform version is v0.14.11.

How can I do that in my case? I don't want to hardcode and I want to send a map which can have one or more key-value pairs.


Solution

  • It is possible to do so using yamlencode inside templatefile function in Terraform in this case.

    I have changed the manifest yaml file as follows:

    ...
        spec:
          nodeSelector:
            ${node_selector}
          containers:
    ...
    

    I have changed the Terraform file as follows:

    ...
    resource "kubernetes_manifest" "deployment" {
      manifest = yamldecode(
        templatefile("${path.module}/resources/deployment-tmpl.yaml",
          {
            app_name      = var.app_name,
            app_namespace = var.app_namespace,
            node_selector = yamlencode(var.node_selector)
        })
      )
    }
    ...
    

    Node selector variable will remain the same and can have more than one key-value pair:

    variable "node_selector" {
      default = {
        "eks.amazonaws.com/nodegroup" = "app"
      }
    }
    

    Reference: Terraform - templatefile Function