Создание отфильтрованного списка с помощью помощников по шаблону 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 }}