azure-devopsgo-templateshelmfile

How to pass Environment Variables to Helmfile Values file


I am new to helmfile and I want to use an exported environment variable that I use in the helmfile values file when running the helmfile diff.

I have the following helmfile.yaml as below:

repositories:
  - name: backstage
    url: https://backstage.github.io/charts
  # - name: backstage-additional-configs
  #   url: ./backstage-additional-configs

helmDefaults:
  cleanupOnFail: true
  verify: false
  wait: true
  timeout: 180
  historyMax: 0
  recreatePods: true
  atomic: true
  createNamespace: false

helmfiles:
  - path: releases/releases.yaml
    values:
      - {{ .Environment.Name }}.yaml

environments:
  dev:
    values:
      - dev.yaml.gotmpl

And here's how my dev.yaml.gotmpl looks like

backstage:
  image:
    registry: somregistry
    image: someimage
    tag: {{ .Values.IMAGE_TAG | quote }}

And I am using the Azure DevOps pipelines to execute helmfile commands because I need to dynamically set the IMAGE_TAG value based on the $(Build.BuildId), so here's my pipeline.yaml look like:

. . .

    - task: AzureCLI@1
        displayName: 'Run helmfile - diff'
        inputs:
          azureSubscription: ${{ parameters.keyvault_service_connection }}
          scriptLocation: 'inlineScript' # Options: inlineScript, scriptPath
          inlineScript: |
            set -euo pipefail
            export IMAGE_TAG=$(Build.BuildId)  #<-------- exporting here
            helmfile -b /usr/local/bin/helm3 -e ${{ parameters.env }} repos
            helmfile -b /usr/local/bin/helm3 -e ${{ parameters.env }} diff

So I am exporting the IMAGE_TAG with export IMAGE_TAG=$(Build.BuildId) command.

I get the following error:

in ./helmfile.yaml: failed to read helmfile.yaml: failed to load environment values file "dev.yaml.gotmpl": failed to render [dev.yaml.gotmpl], because of template: stringTemplate:18:19: executing "stringTemplate" at <.Values.IMAGE_TAG>: map has no entry for key "IMAGE_TAG"

I also tried tag: "{{ .Values.IMAGE_TAG }}"

Could someone please help me what am I missing here?


Solution

  • Values from the environment aren't normally visible in Helmfile templating (or in plain Helm).

    Helmfile includes env and requiredEnv template functions and the documentation includes an example of using them. In your *.yaml.gotmpl file you need to explicitly request the environment value; it won't be automatically reflected in the Helmfile values.

    # dev.yaml.gotmpl
    tag: {{ requiredEnv "IMAGE_TAG" | quote }}
    

    env defaults to an empty string if the environment variable isn't set, the same way as saying "$IMAGE_TAG" in a shell; you can combine it with default. requiredEnv produces a fatal error if the variable isn't set.

    In principle you can use the helmfile --state-values-set option to inject this value to the Helmfile-level values, so that the template syntax you show in the question works. This isn't heavily documented, though. Its syntax is presumably similar to helm --set, which comes with some unusual syntax and some things it can and can't directly set; for a simple string value it would be a reasonable alternative here.

    The Helmfile terminology is a little bit confusing here because Helmfile also has a notion of environments, often things like "dev" vs. "prod", which is different from the Unix (shell) environment.