kubernetes-helmgo-templates

Helm: the range function is not keeping the input values in order as expected?


I know, the dictionary is processed based on order. However, for some process purpose I need to run the certain process in some order. (Since native k8s wont support cronjobs in order, I am doing it in entry point of single pod). Below is my values.yaml

batches:
  evaluate_events:
    ev-cron-3:
      populate_data:
        event-name: "Populate  Data process"
        business-process: "Generic"
        rule-type: "Identification"
      auth_export:
        event-name: "Auth Export Ruleset"
        business-process: "Generic"
        rule-type: "Constraint Satisfaction"
      new_document_attached:
        event-name: "New Document Attached"
        business-process: "Generic"
        rule-type: "Constraint Satisfaction"

My code inv k8s yaml:

{{- range $event, $data := $.Values.batches }}
{{- range $key, $cron := $data }
{{- range $jobname, $inputs := $cron }}
            - '{{ $event }} {{- range $args, $val := $inputs }} --{{ $args }} "{{ $val }}" {{- end }}'
{{- end }}
{{- end }}
{{- end }}

Expected output: Same order as in values.yaml

- 'evaluate_events --business-process "Generic" --event-name "Populate  Data process" --rule-type "Identification"'
- 'evaluate_events --business-process "Generic" --event-name "Auth Export Ruleset" --rule-type "Constraint Satisfaction"'
- 'evaluate_events --business-process "Generic" --event-name "New Document Attached" --rule-type "Constraint Satisfaction"'

Actual Output: Not in the order as per values.yaml

- 'evaluate_events --business-process "Generic" --event-name "Auth Export Ruleset" --rule-type "Constraint Satisfaction"'
- 'evaluate_events --business-process "Generic" --event-name "New Document Attached" --rule-type "Constraint Satisfaction"'
- 'evaluate_events --business-process "Generic" --event-name "Populate  Data process" --rule-type "Identification"'

Needed, if there is anyone handled such situation? and How this can be achieved?


Solution

  • You're using a YAML map object in your values.yaml. This consists of pairs of keys and values, but not necessarily in any order. You probably want a YAML list instead:

    - arg: event-name
      value: Populate  Data process
    - arg: business-process
      value: Generic
    - arg: rule-type
      value: Identification
    

    Then you can iterate through the list (not the map) using range:

    - '{{ $event }}
    {{- range $inputs }} --{{ .arg }} "{{ .value }}"{{- end -}}
    '
    

    Several places in Kubernetes have lists with name fields for pretty much exactly this reason, and you might also consider using this approach higher in your values structure. If you control the application itself, you also may find it easier to pass these settings as environment variables rather than command-line arguments, since constructing a command string as you show can be syntactically a little tricky.