Создание отфильтрованного списка с помощью помощников по шаблону Helm

Я пытаюсь использовать помощник по шаблону Helm для фильтрации значений из списка в моем values.yaml файл на основе значения одного из ключей в каждом элементе списка.

Моя диаграмма в настоящее время состоит из этих файлов -
values.yaml -

namespaces:
- name: filter
  profiles:
  - nonProduction
- name: dont-filter
  profiles:
  - production  
clusterProfile: production

шаблоны /namespaces.yaml

apiVersion: v1
kind: List
items:
{{ $filteredList := include "filteredNamespaces" . }}
{{ range $filteredList }}
  {{ .name }}
{{- end -}}

шаблоны /_profile-match.tpl

{{/* vim: set filetype=mustache: */}}
{{- define "filteredNamespaces" -}}
  {{ $newList := list }}
  {{- range .Values.namespaces }}
    {{- if has $.Values.clusterProfile .profiles -}}
      {{ $newList := append $newList . }}
    {{- end -}}
  {{ end -}}
  {{ $newList }}
{{- end -}}

Проблема в том, что в моем вспомогательном файле $newList переменная заполняется только в рамках range цикл, и я получаю пустой список, возвращающийся в namespaces.yamlшаблон.
Есть ли способ обойти эту проблему? Я принимаю неправильный подход к решению этой проблемы?

3 ответа

Решение

При всем том, что шаблоны Go - это почти универсальные функции, у них есть несколько ограничений. Одно из этих ограничений заключается в том, что они всегда возвращают только строку; вы не можете написать базовых функциональных помощников, напримерmap или filter потому что вы не можете вернуть получившийся список.

Более простой подход к выполнению фильтрации, как вы показали, - переместить его до точки вызывающего (и, возможно, повторить условие, если оно необходимо в нескольких местах):

items:
{{- range .Values.namespaces }}
{{- if has $.Values.clusterProfile .profiles }}
  - {{ .name }}
{{- end }}
{{- end }}

Хакерский способ сделать эту работу такой, какой она есть у вас, - это упорядочить список в какой-либо другой строковый формат, например JSON:

{{- define "filteredNamespaces" -}}
...
{{ toJson $newList }}
{{- end -}}

{{- range include "filteredNamespaces" . | fromJson -}}...{{- end -}}

Также помните, что вы можете внедрить файлы значений Helm, используя helm install -fвариант. Поэтому вместо того, чтобы перечислять каждую перестановку опций и затем отфильтровывать те, которые вам не нужны, вы могли бы реструктурировать это так, чтобыnamespaces: содержит только список пространств имен, которые вы действительно хотите использовать, но затем вы используете разные файлы значений для каждого профиля.

Мне пришлось столкнуться с очень похожей проблемой. Я даю минимальный пример того, как фильтровать и использовать сгенерированный шаблон в виде списка (Helm 3).

_helpers.tpl:

      {{- define "FilteredList" -}}

  {{ $newList := list }}
  {{- range .Values.my_list }}
    {{ $newList = append $newList .pvc }}
  {{- end }}

  {{ toJson $newList }}
{{- end }}

pvc.yaml:

      {{- range include "FilteredList" . | fromJsonArray }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: {{ . }}
spec:
  resources:
    requests:
      storage: 1G
---
{{- end }}

values.yaml:

      my_list:
  - name: foo
    pvc: pvc-one
  - name: foo2
    pvc: pvc-two
  - name: foo3
    pvc: pvc-three

Создает 3 ресурса PVC, как и следовало ожидать.
Обратите внимание на две вещи, которые отличаются от вопроса и принятого ответа:

  • При добавлении и замене списка мы используем вместо :=. Обратите внимание на пример документации Helm 3 для "добавления" : $new = append $myList 6.
    Я вообще не знаю почему = требуется, быстрое исследование с моей стороны не дало никаких результатов.

  • Восстановите список из строки JSON, используя fromJsonArray. Эта функция еще не задокументирована, что очень прискорбно и является основной причиной, по которой я даю этот дополнительный ответ. Однако вы можете найти его в исходниках Helm .

Мы столкнулись с аналогичной проблемой, и благодаря ответу, предоставленному nichoio , мы смогли ее решить. Просто ради Google, я также приведу это здесь :)

Мы включили все наши секретные ссылки, и мы хотели отфильтровать эти секреты в зависимости от того, какая служба в настоящее время развернута.

Мы добавили новый массив в values.yaml(с именем ), который представлял собой список секретов, необходимых для текущего развертывания. Затем с помощью функции в деплоймент передаются только те секретные ссылки, которые включены в . Обратите внимание, что следующая функция возвращает исходный полный список secretRefsесли нет selectedSecretsприсутствуют.

      {{- define "FilteredSecrets" -}}

    {{ $result := .Values.secretRefs }}
    {{ $selectedSecrets := .Values.selectedSecrets }}
    {{- if gt (len $selectedSecrets) 0 -}}
        {{ $result = list }}
        {{ range $secret := .Values.secretRefs }}
            {{ if has $secret.name $selectedSecrets }}
                {{ $result = append $result $secret }}
            {{- end -}}
        {{- end }}
    {{- end -}}
    {{ toJson $result }}
{{- end }}

Соответствующая часть из развертывания:

      containers:
  - env:
    {{- range include "FilteredSecrets" . | fromJsonArray }}
    {{- range $env := .envs }}
    - name: {{ $env.name }}
      valueFrom:
      secretKeyRef:
        key: {{ $env.name }}
        name: {{ .name }}
        optional: {{ $env.optional }}
    {{- end }}
    {{- end }}
Другие вопросы по тегам