Search code examples
yamlkubernetes-helm

helm chart values.dev.yaml - extract parts to a dedicated file


I have this helm chart for my frontend application and parts of it is values.dev.yaml

ingress:
  enabled: true
  ingressClassName: nginx
  hostname:
    - test.example.com
    - test2.example.com
  tls:
    - secretName: wildcard-subdomain-cert
      hosts:
        - test.example.com
        - test2.example.com
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 40m
    nginx.ingress.kubernetes.io/server-tokens: "false"

I would love to have the list of domains elsewhere to simplify the management (on top of that, I have to do it twice here)..

Is there a way how I can use it like that?

I tried to create values.subdomains.dev.yaml (which I tried to provide to Argo while creating the app)

subdomains:
 - test.example.com
 - test2.example.com

and then updating the values.dev.yaml as follows:

ingress:
  enabled: true
  ingressClassName: nginx
  hostname: {{ .Values.subdomains }}
  tls:
    - secretName: wildcard-subdomain-cert
      hosts:  {{ .Values.subdomains }}
  annotations:
    nginx.ingress.kubernetes.io/proxy-body-size: 40m
    nginx.ingress.kubernetes.io/server-tokens: "false"

However, it keeps complaining

Unable to create application: application spec for app is invalid: InvalidSpecError:
Unable to generate manifests in helm-charts/frontend/app: rpc error: 
code = Unknown 
desc = `helm template . --name-template app --namespace frontend --kube-version 1.28 --values <path to cached source>/helm-charts/frontend/app/values.dev.yaml --values <path to cached source>/helm-charts/frontend/app/values.subdomains.dev.yaml <api versions removed> --include-crds` 
failed exit status 1: Error: failed to parse <path to cached source>/helm-charts/frontend/app/values.dev.yaml: error converting YAML to JSON: yaml: line 6: could not find expected ':'

here is the manifest:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: app
spec:
  destination:
    name: ''
    namespace: frontend
    server: <**REMOVED**>
  source:
    path: helm-charts/frontend/app
    repoURL: <**REMOVED**>
    targetRevision: <**REMOVED**>
    helm:
      valueFiles:
        - values.dev.yaml
        - values.subdomains.dev.yaml
  sources: []
  project: default
  syncPolicy:
    automated:
      prune: false
      selfHeal: true

Solution

  • You can't normally use Helm templating in values files. That means you can only kind of do what you're describing.

    You can split this into two values files. But, the file that contains the host names needs to contain all of the configuration above that in the YAML map tree hierarchy, and all of the surrounding options in the YAML list item.

    # values.subdomains.dev.yaml
    ingress:
      hostname:
        - test.example.com
        - test2.example.com
      tls:
        - secretName: wildcard-subdomain-cert
          hosts:
            - test.example.com
            - test2.example.com
    
    # values.dev.yaml
    ingress:
      enabled: true
      ingressClassName: nginx
      annotations:
        nginx.ingress.kubernetes.io/proxy-body-size: 40m
        nginx.ingress.kubernetes.io/server-tokens: "false"
    

    If you did that, the helm install -f option or the ArgoCD valueFiles: option would use both sets of options. They don't try to refer to each other or use Helm templating, and the two sets of ingress: options get merged.

    If you know that you'll always want to use the same set of host names in both places, I'd change your template code itself to accommodate this. For example, if you changed your configuration to look a little more like

    ingress:
      hostname:
        - test.example.com
        - test2.example.com
      tlsSecretName: wildcard-subdomain-cert
    

    then your template code could say

    spec:
    {{- if .Values.ingress.tlsSecretName }}
      tls:
        - hosts:
    {{ .Values.ingress.hostname | toYaml | indent 4 }}
          secretName: {{ .Values.ingress.tlsSecretName }}
    {{- end }}
      rules:
    {{- range .Values.ingress.hostname }}
        - host: {{ . }}
          ...
    {{- end }}
    

    reusing the single list of hostnames in both places.