Search code examples
terraform

Fix indentation with Terraform yamlencode


I'm deploying a helm chart with Terraform v0.14.11, using the yamlencode function to encode my values.

resource "helm_release" "foo" {
  name = local.chart_name

  chart     = "${path.module}/charts/${local.chart_name}"
  namespace = var.name-sp
  values    = [yamlencode(local.helm_values.foo)]
}

And this is what my local_helm_values.foo looks like

alertmanagerFiles = {
"alertmanager.yml" = var.slack_key != "" ? {
    global = {
    slack_api_url = var.alertmanager_slack_key

    receivers = [for k, v in var.receivers : {
      name = k
      slack_configs = [{
        send_resolved = true
        channel       = v.channel
        title         = ""
        text          = ""
    }]
    }]

    route = {
      group_wait = "10s"
      group_interval = "3m"
      receiver = "slack-notify"
      repeat_interval = "5m"
        }
    }
    } : {}
}

However, the chart deploys with errors and when I run the helm get manifest command, the indentation looks off.

  alertmanager.yml: |
    global:
      receivers:
      - name: slack_notify
        slack_configs:
        - channel: '#prometheus-alerts'

      route:
        routes:
          receiver: slack_notify
          repeat_interval: 5m
      slack_api_url: https://hooks.slackurl

Instead of

  alertmanager.yml: |
    global:
    receivers:
    - name: slack_notify
      slack_configs:
      - channel: '#prometheus-alerts'

    route:
      routes:
        receiver: slack_notify
        repeat_interval: 5m
      slack_api_url: https://hooks.slackurl

Is there a way to get the correct indentation levels?


Solution

  • I see what you're trying to do.

    If you look at the values.yaml file of the AlertManager helm chart, you'll see that receivers and routes stand alone and are not children of global

    What you want is this.

    alertmanagerFiles = {
    "alertmanager.yml" = var.slack_key != "" ? {
        global = {
        slack_api_url = var.alertmanager_slack_key
        }
    
        receivers = [for k, v in var.receivers : {
          name = k
          slack_configs = [{
            send_resolved = true
            channel       = v.channel
            title         = ""
            text          = ""
        }]
        }]
    
        route = {
          group_wait = "10s"
          group_interval = "3m"
          receiver = "slack-notify"
          repeat_interval = "5m"
            }
        } : tostring()
    }
    
    

    I've added tostring() at the end to maintain consistent types on both sides of the True and False evaluation.