Обзор
При чтении конфигурации werf.yaml, werf использует встроенный движок шаблонов Go (text/template), а также расширяет набор функций с помощью Sprig и функций werf.
При организации конфигурации она может быть разбита на отдельные файлы в директории шаблонов.
Встроенные возможности шаблонизатора Go
Для эффективной работы мы рекомендуем изучить все возможности шаблонизатора или хотя бы ознакомиться со следующими разделами:
Функции Sprig
Библиотека Sprig предоставляет более 70 функций:
- Строковые функции.
- Математические функции.
- Функции кодирования.
- Работа с данными в формате ключ/значение (dict).
- Работа с файловыми путями.
- Остальное.
werf не поддерживает функцию expandenv и имеет свою собственную реализацию для функции env.
Функции werf
Различные окружения
.Env
Переменная .Env позволяет организовывать конфигурацию для нескольких сред (testing, staging, production и т.п.) и переключаться между ними с помощью опции --env=<environment_name>.
В helm шаблонах таким же образом может использоваться переменная
.Values.werf.env.
Информация о текущем коммите
.Commit.Hash
{{ .Commit.Hash }} возвращает SHA текущего коммита. Если есть возможность, лучше избегать использование .Commit.Hash, т. к. это может приводить к ненужным пересборкам слоев.
.Commit.Date
{{ .Commit.Date.Human }} возвращает дату текущего коммита в человекопонятной форме.
{{ .Commit.Date.Unix }} возвращает дату текущего коммита в формате Unix epoch.
Пример: пересобирать образ целиком каждый месяц
image: app
from: ubuntu:22.04
git:
- add: /
to: /app
stageDependencies:
install:
- "*"
fromCacheVersion: {{ div .Commit.Date.Unix (mul 60 60 24 30) }}
shell:
beforeInstall:
- apt-get update
- apt-get install -y nodejs npm
install:
- npm ci
Шаблонизация
include
Функция include позволяет переиспользовать общие части конфигурации, а также разбивать конфигурацию на несколько файлов.
Синтаксис:
{{ include "<TEMPLATE_NAME>" <VALUES> }}
Пример: использование общих кусков конфигурации
project: my-project
configVersion: 1
---
image: app1
from: alpine:3.21
shell:
beforeInstall:
{{- include "(component) ruby" . }}
---
image: app2
from: alpine:3.21
shell:
beforeInstall:
{{- include "(component) ruby" . }}
{{- define "(component) ruby" }}
- gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
- curl -sSL https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer -o /tmp/rvm-installer
- bash -e /tmp/rvm-installer
- bash -lec 'rvm install 2.3.4'
- bash -lec 'rvm use --default 2.3.4'
- bash -lec 'gem install bundler --no-ri --no-rdoc'
- bash -lec 'rvm cleanup all'
{{- end }}
tpl
Функция tpl позволяет обрабатывать строки как Go-шаблоны.
Синтаксис:
{{ tpl "<STRING>" <VALUES> }}
<STRING>— контент файла проекта, значение переменной окружения либо произвольная строка.<VALUES>— значения шаблона. При использовании текущего контекста,., в шаблоне можно использовать все шаблоны и значения (в том числе, описанные в файлах директории шаблонов).
Пример: использование файлов проекта в качестве шаблонов werf.yaml
{{ $_ := set . "BaseImage" "node:14.3" }}
project: app
configVersion: 1
---
{{ range $path, $content := .Files.Glob "**/werf-partial.yaml" }}
{{ tpl $content $ }}
{{ end }}
{{- define "common install commands" }}
- npm install
- npm run build
{{- end }}
image: backend
from: {{ .BaseImage }}
git:
- add: /backend
to: /app/backend
shell:
install:
- cd /app/backend
{{- include "common install commands" . | indent 2 }}
image: frontend
from: {{ .BaseImage }}
git:
- add: /frontend
to: /app/frontend
shell:
install:
- cd /app/frontend
{{- include "common install commands" . | indent 2 }}
Переменные окружения
env
Функция env читает переменную окружения.
Синтаксис:
{{ env "<ENV_NAME>" }}
{{ env "<ENV_NAME>" "default_value" }}
По умолчанию, использование функции
envзапрещено гитерминизмом (подробнее об этом в статье)
Файлы проекта
.Files.Exists
Функция .Files.Exists проверят наличие файла/директории в рамках проекта и возвращает результат true или false.
Синтаксис:
{{ .Files.Exists "<FILE_PATH>" }}
По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в статье)
.Files.Get
Функция .Files.Get получает содержимое определенного файла проекта.
Синтаксис:
{{ .Files.Get "<FILE_PATH>" }}
По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в статье)
Пример: использование определённого файла в stapel-образе без использования директивы git (shell)
project: my-project
configVersion: 1
---
image: app
from: alpine:3.21
shell:
setup:
- |
head -c -1 <<'EOF' > /etc/nginx/nginx.conf
{{ .Files.Get ".werf/nginx.conf" | indent 4 }}
EOF
.Files.Glob
Функция .Files.Glob позволяет работать с файлами проекта и их содержимым по глобу.
Функция поддерживает shell pattern matching и **. Результаты вызова функции можно объединить, используя sprig-функцию merge (к примеру, {{ $filesDict := merge (.Files.Glob "glob1") (.Files.Glob "glob2") }})
Синтаксис:
{{ .Files.Glob "<GLOB>" }}
По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в статье)
Пример: использование файлов по глобу в stapel-образе без использования директивы git (shell)
project: my-project
configVersion: 1
---
image: app
from: alpine:3.21
shell:
install: mkdir /app
setup:
{{ range $path, $content := .Files.Glob "modules/*/images/*/{Dockerfile,werf.inc.yaml}" }}
- |
head -c -1 <<EOF > /app/{{ base $path }}
{{ $content | indent 4 }}
EOF
{{ end }}
.Files.IsDir
Функция .Files.IsDir проверят, является ли путь директорией и возвращает результат true или false.
Синтаксис:
{{ .Files.IsDir "<PATH>" }}
По умолчанию, использование файлов, которые имеют незакоммиченные изменения, запрещено гитерминизмом (подробнее об этом в статье)
Другие
required
Функция required проверяет наличие значения у определённой переменной. Если значение пусто, то рендеринг шаблона завершится ошибкой с заданным пользователем сообщением.
Синтаксис:
value: {{ required "<ERROR_MSG>" <VALUE> }}
fromYaml
Функция fromYaml декодирует YAML-документ в структуру.
Синтаксис:
value: {{ fromYaml "<STRING>" }}
Пример: чтение YAML-файла и использование полученного значения
{{- $values := .Files.Get "werf_values.yaml" | fromYaml -}} # или fromYaml (.Files.Get "werf_values.yaml")
from: {{- $values.image.from }}
toYaml
Функция toYaml кодирует структуру в YAML-документ.
Синтаксис:
{{ toYaml <STRUCTURE> }}
Пример: вставка конфигурации в формате YAML
{{ $cmdList := list "cmd1" "cmd2" }}
shell:
install:
{{- $cmdList | toYaml | nindent 4 }} # возвращает "- cmd1\n - cmd2"
Директория шаблонов
Файлы шаблонов могут храниться в зарезервированной директории (по умолчанию .werf) с расширением .tmpl (поддерживается произвольная вложенность .werf/**/*.tmpl).
Все файлы шаблонов и основная конфигурация определяют общий контекст:
- Файл шаблонов является полноценным шаблоном и может использоваться функцией include по относительному пути (
{{ include "directory/partial.tmpl" . }}). - Шаблон определённый с помощью
defineв одном файле шаблонов доступен в любом другом, включая основную конфигурацию.
Пример: использование шаблонов, описанных в файле шаблонов
{{ $_ := set . "RubyVersion" "2.3.4" }}
{{ $_ := set . "BaseImage" "alpine:3.21" }}
project: my-project
configVersion: 1
---
image: rails
from: {{ .BaseImage }}
shell:
beforeInstall:
{{- include "(component) mysql client" . }}
{{- include "(component) ruby" . }}
install:
{{- include "(component) Gemfile dependencies" . }}
{{- define "(component) Gemfile dependencies" }}
- mkdir -p /root/.ssh
- |
bash -ec '
set -e
ssh-keyscan github.com >> /root/.ssh/known_hosts
ssh-keyscan mygitlab.myorg.com >> /root/.ssh/known_hosts
'
- |
bash -lec '
set -e
source /etc/profile.d/rvm.sh
cd /app
bundle install --without development test --path vendor/bundle
'
{{- end }}
{{- define "(component) mysql client" }}
- apt-get update && apt-get install -y libmysqlclient-dev mysql-client g++
{{- end }}
{{- define "(component) ruby" }}
- gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
- curl -sSL https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer -o /tmp/rvm-installer
- bash -e /tmp/rvm-installer
- bash -lec 'rvm install {{ .RubyVersion }}'
- bash -lec 'rvm use --default {{ .RubyVersion }}'
- bash -lec 'gem install bundler --no-ri --no-rdoc'
- bash -lec 'rvm cleanup all'
{{- end }}