terraformyamlkubernetes-helmgo-templatesterraform-helm-provider

How to pass a string list to helm_release values.yaml file?


I am trying to pass a string list to a helm template like that:

ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
...
  annotations:
    alb.ingress.kubernetes.io/subnets: {{ .Values.alb.subnets }}
...

values.yaml

alb:
  subnets: 
    - subnet-A
    - subnet-B

main.tf

resource "helm_release" "site_ui" {
  name  = "site-ui"
  chart = "./charts/site-ui"
  values = [
    file("./charts/site-ui/values.yaml")
  ]
  reuse_values = true

  set_list {
    name  = "alb.subnets"
    value = var.data_subnet_ids
  }
}

variables.tf

variable "data_subnet_ids" {
  type    = list(string)
  default = ["subnet-A", "subnet-B"]
}

Terraform plan:

# helm_release.site_ui will be updated in-place
  ~ resource "helm_release" "site_ui" {
        id                         = "site-ui"
      ...
        name                       = "site-ui"
      ~ values                     = [
          ...
        # (25 unchanged attributes hidden)

     ...
      + set_list {
          + name  = "alb.subnets"
          + value = [
              + "subnet-A",
              + "subnet-B",
            ]
        }

        # (4 unchanged blocks hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

When I attempt to deploy the above code I get this error:

helm_release.site_ui: Modifying... [id=site-ui]
╷
│ Error: YAML parse error on foreseer-ui/templates/ingress.yaml: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal array into Go struct field .metadata.annotations of type string
│ 
│   with helm_release.site_ui,
│   on main.tf line 27, in resource "helm_release" "site_ui":
│   27: resource "helm_release" "site_ui" {
│ 

According to the docs alb.ingress.kubernetes.io/subnets should be of stringList type (see https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.1/guide/ingress/annotations/)

What am I missing?


Solution

  • The error is independent of TF or Helm. The schema for the metadata.annotations requires a string value as that is the type specified in the deserialized Go struct, and the Sprig renders to a list type from a YAML array/HCL2 list. You would need to specify multiple subnets as a string. The documentation describes that the string should be comma-delimited, and so the rendered value should be comma-delimited subnets:

    alb.ingress.kubernetes.io/subnets: {{ .Values.alb.subnets  | join ", " }}
    

    where the Sprig join function joins the list into subnets separated by , .