Вычисляемые выражения в конфигурации продукта Cloud Apps
При настройке конфигурации продукта Cloud Apps в строковых значениях атрибутов ресурсов пользователи могут использовать вычисляемые выражения. Такие выражения позволяют динамически формировать значение атрибута на основе вычислений, входных параметров и значений других атрибутов.
Базовый синтаксис
Выражения основаны на синтаксисе интерполяции
Интерполяция
Выражения заключаются в двойные фигурные скобки:
Привет {{ выражение }} мир!
Экранирование
Для вывода сочетаний символов {{ и }} используется экранирование — символ \:
\{{выводит{{;\}}выводит}}.
Примеры базового использования
# Простая интерполяция
name: "{{ input.environment }}-server"
# Смешанный текст с выражениями
description: "Сервер для окружения {{ input.environment }} в регионе {{ input.region }}"
# Экранирование
template: "Используйте \{{ variable \}} для подстановки значений"
Типы данных
Строки
Строковые литералы заключаются в одинарные или двойные кавычки:
"строка в двойных кавычках"
'строка в одинарных кавычках'
Числа
# Целые числа
42
-17
# Десятичные дроби
3.14
-2.5
Булевы значения
true
false
Операторы
Арифметические операторы
+— сложение;-— вычитание;*— умножение;/— деление;%— остаток от деления.
# Примеры
cpu_count: "{{ input.base_cpu + 2 }}"
memory_gb: "{{ input.memory_mb / 1024 }}"
Операторы сравнения
==— равно;!=— не равно;<— меньше;>— больше;<=— меньше или равно;>=— больше или равно.
# Пример
high_availability: "{{ input.node_count >= 3 }}"
Логические операторы
&&— логическоеИ;||— логическоеИЛИ;!— логическоеНЕ.
# Примеры
enable_backup: "{{ input.environment == 'prod' && input.backup_enabled }}"
use_spot: "{{ input.cost_optimization || input.environment != 'prod' }}"
is_dev: "{{ !input.production }}"
Тернарный оператор
Условный оператор условие ? значение_если_истина : значение_если_ложь:
# Примеры
instance_type: "{{ input.environment == 'prod' ? 'large' : 'small' }}"
replica_count: "{{ input.high_availability ? 3 : 1 }}"
Переменные
Ресурсы
Доступ к атрибутам созданных ресурсов:
resource.<тип_ресурса>.<имя_ресурса>.<атрибут>
# Примеры
vpc_id: "{{ resource.yandex_vpc_network.main.id }}"
subnet_cidr: "{{ resource.yandex_vpc_subnet.private.v4_cidr_blocks[0] }}"
instance_ip: "{{ resource.yandex_compute_instance.web_server.network_interface.0.nat_ip_address }}"
Источники данных (Data Sources)
Доступ к атрибутам источников данных:
data.<тип_источника>.<имя_источника>.<атрибут>
# Примеры
image_id: "{{ data.yandex_compute_image.ubuntu.id }}"
zone_id: "{{ data.yandex_dns_zone.main.zone_id }}"
folder_id: "{{ data.yandex_resourcemanager_folder.current.folder_id }}"
Входные параметры
Доступ к параметрам, переданным пользователем:
input.<имя_параметра>
# Примеры
environment: "{{ input.environment }}"
region: "{{ input.deployment_region }}"
instance_count: "{{ input.replica_count }}"
Артефакты
Доступ к артефактам (например, Docker-образам):
artifact.<имя_артефакта>
# Примеры
container_image: "{{ artifact.web_app_image }}"
deployment_package: "{{ artifact.application_archive }}"
Атрибуты приложения
Доступ к системным атрибутам текущего приложения (экземпляра продукта Cloud Apps):
application.id— уникальный идентификатор приложения;application.folderId— идентификатор каталога Yandex Cloud;application.serviceAccountId— идентификатор сервисного аккаунта.
# Примеры
app_id: "{{ application.id }}"
folder_id: "{{ application.folderId }}"
service_account: "{{ application.serviceAccountId }}"
Цепочки доступа
Для сложных структур данных используются цепочки доступа. Имена переменных пишутся в snake_caseFolder Id → folder_id.
Для доступа к атрибутам ресурса или вложенного объекта используется запись через точку:
<ресурс>.<атрибут_уровня_1>.<атрибут_уровня_2>.<...>.<атрибут_уровня_n>
Для доступа к элементам массива или карты (ассоциативного массива) используется запись с квадратными скобками:
<массив>[0].<атрибут>["<элемент>"]
# Доступ к вложенным полям через точку
network_id: "{{ resource.yandex_compute_instance.resources.cores }}"
# Доступ к элементам массива через квадратные скобки
first_ip: "{{ resource.yandex_vpc_subnet.public.v4_cidr_blocks[0] }}"
second_ip: "{{ resource.yandex_vpc_subnet.public.v4_cidr_blocks[1] }}"
# Комбинированный доступ
instance_zone: "{{ resource.yandex_compute_instance_group.web.instances[0].zone_id }}"
Функции
min()
Возвращает минимальное значение из списка аргументов:
# Примеры
min_cpu: "{{ min(input.cpu_request, 4, input.cpu_limit) }}"
min_memory: "{{ min(1, input.memory_gb) }}"
max()
Возвращает максимальное значение из списка аргументов:
# Примеры
max_cpu: "{{ max(input.cpu_request, 2) }}"
max_replicas: "{{ max(input.min_replicas, 1, input.desired_replicas) }}"
Фильтры
Фильтры применяются к выражениям через символ | и позволяют преобразовывать данные:
abs
Абсолютное значение числа:
positive_value: "{{ input.offset | abs }}"
# input: -5 -> output: 5
base64decode
Декодирование из Base64
decoded_data: "{{ input.encoded_config | base64decode }}"
base64encode
Кодирование строки в Base64
encoded_data: "{{ input.user_data | base64encode }}"
capitalize
Все слова в строке с заглавной буквы без преобразования строки в нижний регистр:
label: "{{ input.type | capitalize }}"
# input: "dataBase" -> output: "DataBase"
default
Значение по умолчанию:
region: "{{ input.region | default('kz1-a') }}"
# Если input.region не заполнен или null, будет использовано 'kz1-a'
ident
Добавление пробелов в начало строки:
value: "{{ input.data | ident(2) }}"
# input: "some: 3" -> output: " some: 3"
length
Длина строки или массива:
name_length: "{{ input.service_name | length }}"
# input: "webapp" -> output: 6
lower
Преобразование строки в нижний регистр:
resource_name: "{{ input.service_name | lower }}"
# input: "WebApp" -> output: "webapp"
replace
Замена подстроки:
# Заменить пробелы на дефисы
safe_name: "{{ input.display_name | replace(' ', '-') | lower }}"
# input: "My Service" -> output: "my-service"
sha256
Вычисление хеша SHA256
config_hash: "{{ input.configuration | sha256 }}"
title
Преобразование строки в нижний регистр, затем все слова с заглавной буквы:
display_name: "{{ input.service_name | title }}"
# input: "weB serVice" -> output: "Web Service"
trim
Удаление пробелов в начале и конце строки:
clean_name: "{{ input.name | trim }}"
# input: " app " -> output: "app"
upper
Преобразование строки в верхний регистр:
env_name: "{{ input.environment | upper }}"
# input: "prod" -> output: "PROD"
Цепочки фильтров
Фильтры можно объединять в цепочки:
# Комбинирование нескольких фильтров
resource_name: "{{ input.service_name | trim | lower | replace(' ', '-') }}"
# input: " Web Service " -> output: "web-service"
# С использованием default
final_name: "{{ input.custom_name | default('default-app') | upper }}"
# Если input.custom_name пустой -> output: "DEFAULT-APP"
Особенности использования
При использовании выражений в именах ресурсов необходимо явно добавлять уникальный идентификатор продукта Cloud Apps. Это позволит установить в один каталог пользователя одновременно несколько приложений, не рискуя спровоцировать конфликт в именах ресурсов.
- type: resource.yandex_compute_instance
name: web_server
config:
name: "my-best-application-{{ application.id }}"
...
Примеры практического использования
Конфигурация виртуальной машины
- type: resource.yandex_compute_instance
name: web_server
config:
name: "{{ input.environment }}-web-{{ input.instance_number | default(1) }}-{{ application.id }}"
hostname: "{{ input.service_name | lower | replace(' ', '-') }}.{{ input.domain }}"
cores: "{{ min(input.cpu_cores, 2) }}"
memory: "{{ input.memory_gb * 1024 }}"
boot_disk:
image_id: "{{ data.yandex_compute_image.ubuntu.id }}"
size: "{{ input.disk_size | default(20) }}"
network_interface:
subnet_id: "{{ resource.yandex_vpc_subnet.main.id }}"
nat: "{{ input.environment != 'prod' }}"
metadata:
user-data: |
users:
- name: {{ input.username }}
sudo: 'ALL=(ALL) NOPASSWD:ALL'
shell: /bin/bash
ssh_authorized_keys:
- {{ input.public_key }}
labels:
environment: "{{ input.environment }}"
project: "{{ application.id }}"
cost-center: "{{ input.cost_center | default('default') | upper }}"
Условная конфигурация базы данных
- type: resource.yandex_mdb_postgresql_cluster
name: main_db
config:
name: "{{ input.project_name | lower }}-{{ input.environment }}-db-{{ application.id }}"
# Размер инстанса зависит от окружения
resources:
resource_preset_id: "{{ input.environment == 'prod' ? 's3-c8-m32' : 's3-c2-m8' }}"
disk_size: "{{ input.environment == 'prod' ? 100 : 20 }}"
disk_type_id: "{{ input.environment == 'prod' ? 'network-ssd' : 'network-hdd' }}"
# Сеть
network_id: "{{ resource.yandex_vpc_network.main.id }}"
# Конфигурация доступа
config:
access:
web_sql: "{{ input.environment == 'dev' }}"
serverless: "{{ input.enable_functions | default(false) }}"
Настройка групп безопасности
- type: resource.yandex_vpc_security_group
name: web_sg
config:
name: "{{ input.project_name }}-web-sg-{{ application.id }}"
network_id: "{{ resource.yandex_vpc_network.main.id }}"
ingress:
# HTTP доступ
- protocol: TCP
port: 80
v4_cidr_blocks: "{{ input.allow_public_access ? ['0.0.0.0/0'] : input.allowed_cidrs }}"
# HTTPS доступ только для prod
- protocol: TCP
port: 443
v4_cidr_blocks: "{{ input.environment == 'prod' ? ['0.0.0.0/0'] : [] }}"
# SSH доступ только с определенных IP
- protocol: TCP
port: 22
v4_cidr_blocks: "{{ input.admin_cidrs | default(['10.0.0.0/8']) }}"
Лучшие практики
Использование значений по умолчанию
# Всегда задавайте разумные значения по умолчанию для полей с необязательными значениями
instance_type: "{{ input.instance_type | default('s3-c4-m8') }}"
region: "{{ input.region | default('kz1-a') }}"
Валидация значений
# Используйте условные выражения для валидации
cpu_cores: "{{ max(min(input.cpu_cores, 32), 1) }}"
memory_gb: "{{ input.memory_gb >= 1 ? input.memory_gb : 1 }}"
Человекочитаемые имена ресурсов
# Создавайте понятные имена ресурсов
name: "{{ input.project_name | lower | replace(' ', '-') }}-{{ input.environment }}-{{ input.component }}"
Условная логика для окружений
# Различайте конфигурацию по окружениям
backup_enabled: "{{ input.environment == 'prod' || input.environment == 'staging' }}"
monitoring_level: "{{ input.environment == 'prod' ? 'detailed' : 'basic' }}"
Безопасность
# Ограничивайте доступ в зависимости от окружения
public_access: "{{ input.environment == 'dev' && input.debug_mode }}"