Search code examples
kubernetes-helmhelm3

How to overwrite Table/Mapping in Helm Chart


I have a values.yaml that has

ingress:
  enabled: false 

volume:
  hostPath:
    path: /tmp
    type: DirectoryOrCreate 

I have an overlay.yaml that changes the value of values.yaml.

ingress:
  enabled: true 

volume:
  persistentVolumeClaim:
    claimName: test

For the ingress, it's working as I suspected because the value of enabled will change to true. However, for the volume, it appears that tables add on to each other rather than get overwritten. For instance, I would get something like:

volume: 
  persistentVolumeClaim:
    claimName: test
  hostPath:
    path: /tmp
    type: DirectoryOrCreate 

I would like to specify a default volume type and its configurations (e.g. path) in values.yaml, but have the freedom for others to change this through an overlay. However, what I have now "adds" a volume type rather than overwrite it. Is there a way to accomplish this?


Solution

  • null is a specific valid YAML value (the same as JSON null). If you set a Helm value to null, then the Go text/template logic will unmarshal it to Go nil and it will appear as "false" in if statements and similar conditionals.

    volume:
      persistentVolumeClaim:
        claimName: test
      hostPath: null
    

    I might avoid this problem in chart logic, though. One approach would be to use a separate type field to say which sub-field you're looking for:

    # the chart's defaults in values.yaml
    volume:
      type: HostPath
      hostPath: { ... }
    
    # your `helm install -f` overrides
    volume:
      type: PersistentVolumeClaim
      persistentVolumeClaim: { ... }
      # (the default hostPath: will be present but unused)
    

    A second option is to make the default "absent", and either disable the feature entirely or construct sensible defaults in the chart code if it's not present.

    # values.yaml
    
    # volume specifies where the application will keep persistent data.
    # If unset, each replica will have independent data and this data will
    # be lost on restart.
    #
    # volume:
    #
    #  persistentVolumeClaim stores data in an existing PVC.
    #
    #  persistentVolumeClaim:
    #    name: ???
    
    # deep in templates/deployment.yaml
    volumes:
    {{- if .Values.volume.persistentVolumeClaim }}
      - name: storage
        persistentVolumeClaim:
          claimName: {{ .Values.volume.persistentVolumeClaim.name }}
    {{- else if .Values.volume.hostPath }}
      - name: storage
        hostPath:
          path: {{ .Values.volume.hostPath.path }}
    {{- end }}
    {{-/* (just don't create a volume if not set) */}}
    

    Or, to always provide some kind of storage, even if it's not that useful:

    volumes:
      - name: storage
    {{- if .Values.volume.persistentVolumeClaim }}
        persistentVolumeClaim:
          claimName: {{ .Values.volume.persistentVolumeClaim.name }}
    {{- else if .Values.volume.hostPath }}
        hostPath:
          path: {{ .Values.volume.hostPath.path }}
    {{- else }}
        emptyDir: {}
    {{- end }}