Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки
Для Deckhouse Commander доступно технологическое превью активно развивающегося Terraform-провайдера, который работает через API интеграции, описанный в этом разделе. Провайдер в настоящее время поддерживает создание, удаление, изменение кластеров и шаблонов кластеров в одном рабочем пространстве, в котором создан токен доступа к API.
Обзор
Deckhouse Commander предоставляет внешний API для сценариев автоматизации и интеграции — CI/CD, self-service-порталов, IDP-платформ. Интерактивная документация OpenAPI (Swagger) встроена в веб-интерфейс и всегда соответствует версии запущенного бэкенда; чтобы её открыть, нажмите на иконку в виде шестерёнки в верхней панели:
- на стартовой странице (список рабочих пространств) пункт «Документация API» открывает справочник глобального API по адресу
/documentation; - на странице рабочего пространства пункт «Документация API» открывает справочник API рабочего пространства по адресу
/workspaces/<slug-рабочего-пространства>/auth-tokens/documentation.
Каждый запрос должен содержать токен в HTTP-заголовке X-Auth-Token. Все пути указываются относительно https://$COMMANDER_HOST; в примерах используется переменная окружения $COMMANDER_HOST для адреса сервера и $COMMANDER_GLOBAL_TOKEN / $COMMANDER_TOKEN — для токенов.
GET /api/v1/workspaces HTTP/1.1
Host: $COMMANDER_HOST
X-Auth-Token: $COMMANDER_GLOBAL_TOKEN
Accept: application/jsonСуществует два типа токенов, каждый выпускается в веб-интерфейсе Commander (полная процедура — в разделе API интеграции руководства пользователя):
- Глобальный токен — выпускается на начальном экране со списком рабочих пространств, в разделе «Параметры → Токены доступа». Позволяет управлять рабочими пространствами, глобальными ролями и назначениями в рабочих пространствах; не позволяет управлять сущностями внутри рабочих пространств;
- Токен рабочего пространства — выпускается внутри рабочего пространства, в разделе «Параметры → Токены доступа». Позволяет управлять ресурсами того рабочего пространства, в котором токен был выпущен: кластерами, шаблонами кластеров, каталогами инвентаря, записями каталогов, хранилищами образов контейнеров и проектами. Токен всегда привязан к одному рабочему пространству; попытка обратиться к ресурсам другого рабочего пространства возвращает
403 Forbidden.
Запросы без токена или с недействительным/просроченным токеном возвращают 401 Unauthorized. За исчерпывающими схемами запросов и ответов, перечислениями и HTTP-кодами для каждого эндпоинта всегда обращайтесь к Swagger UI.
Доступно по глобальному токену
- Получение списка глобальных ролей:
GET /api/v1/global_roles.
- Управление рабочими пространствами:
GET /api/v1/workspaces;POST /api/v1/workspaces;PUT /api/v1/workspaces/:id;DELETE /api/v1/workspaces/:id.
- Управление назначениями в рабочих пространствах:
GET /api/v1/workspace_role_bindings;POST /api/v1/workspace_role_bindings;GET /api/v1/workspace_role_bindings/:id;PUT /api/v1/workspace_role_bindings/:id;DELETE /api/v1/workspace_role_bindings/:id.
Доступно по токену рабочего пространства
Все эндпоинты неявно ограничены рабочим пространством, к которому привязан токен. Пути, помеченные (архивируемые), принимают query-параметр archived=true, чтобы включить архивные сущности в ответ; по умолчанию они из ответа исключаются.
- Управление шаблонами кластеров:
GET /api/v1/cluster_templates(архивируемые);POST /api/v1/cluster_templates;GET /api/v1/cluster_templates/:id;PUT /api/v1/cluster_templates/:id;DELETE /api/v1/cluster_templates/:id.
- Управление каталогами инвентаря:
GET /api/v1/catalogs(архивируемые);POST /api/v1/catalogs;GET /api/v1/catalogs/:id;PUT /api/v1/catalogs/:id;DELETE /api/v1/catalogs/:id.
- Управление записями каталогов:
POST /api/v1/records;GET /api/v1/records(архивируемые);GET /api/v1/records/:id;PUT /api/v1/records/:id;DELETE /api/v1/records/:id.
- Управление кластерами:
POST /api/v1/clusters;GET /api/v1/clusters(архивируемые);GET /api/v1/clusters/:id;GET /api/v1/clusters/:id/status;PUT /api/v1/clusters/:id;DELETE /api/v1/clusters/:id;DELETE /api/v1/clusters/:id/force.
- Управление хранилищами образов контейнеров:
POST /api/v1/registries;GET /api/v1/registries;GET /api/v1/registries/:id;DELETE /api/v1/registries/:id.
- Управление проектами:
GET /api/v1/projects;POST /api/v1/projects;GET /api/v1/projects/:id;PUT /api/v1/projects/:id;DELETE /api/v1/projects/:id.
- Одобрение запросов на изменение кластера:
GET /api/v1/cluster_change_requests;GET /api/v1/cluster_change_requests/:id;POST /api/v1/cluster_change_requests/:id/approve.
- Чтение задач кластера и их логов:
GET /api/v1/cluster_tasks(архивируемые);GET /api/v1/cluster_task_logs(архивируемые).
Ошибки
Все ошибки возвращаются в едином JSON-конверте:
{
"error": "Человекочитаемое сообщение",
"error_code": "invalid",
"errors": { "name": ["can't be blank"] }
}Опирайтесь в автоматизации на error_code — это стабильный контракт; сообщение error локализовано и может меняться. Используются стандартные HTTP-коды; полный список для каждого эндпоинта — в Swagger UI. Наиболее частые случаи:
401 no_token/invalid_token— заголовокX-Auth-Tokenотсутствует, просрочен или не распознан;403 forbidden— у токена нет прав либо запрос обращается к ресурсу вне его рабочего пространства;409 stale_objectприPUT— ресурс изменён параллельным запросом; перечитайте его, слейте изменения и повторите запрос с новымcurrent_revision;409 conflictна/cluster_change_requests/:id/approve(already_approved,already_completed,cluster_cannot_be_convergedи аналогичные) — не повторяйте одобрение: перечитайте запрос на изменение и выберите дальнейшее действие;422 invalid— ошибка валидации; детали по полям — в полеdata;500 internal_server_error— неожиданная ошибка бэкенда; безопасно повторять идемпотентные запросы с экспоненциальным backoff.
При опросе кластера учитывайте одновременно status и render_errors: ошибка рендеринга шаблона оставляет кластер в нетерминальном статусе, но заполняет render_errors.
Примеры
Во всех примерах предполагается, что заданы переменные окружения:
export COMMANDER_HOST="commander.example.com"
export COMMANDER_GLOBAL_TOKEN="..." # глобальный токен
export COMMANDER_TOKEN="..." # токен рабочего пространстваСоздание рабочего пространства
curl -X "POST" \
"https://$COMMANDER_HOST/api/v1/workspaces" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Рабочее пространство из API"}'В ответ приходят данные рабочего пространства; id понадобится для последующих запросов.
{
"id": "088b8e03-e7c0-4655-aae7-d11b7609c579",
"slug": "sftpp",
"name": "Рабочее пространство из API",
"comment": null,
"main": false,
"current_revision": 0,
"created_at": "2026-01-15T12:19:57.002+03:00",
"updated_at": "2026-01-15T12:19:57.002+03:00"
}Получение глобальной роли
Чтобы назначить глобальную роль пользователю или группе, получите id роли:
curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/global_roles" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN"В ответе будут объекты ролей; нужное поле — id:
[
{
"id": "818c3814-4973-452e-9985-d75fbe35eb4c",
"name": "commander-admin",
"comment": null,
"labels": {
"commander.deckhouse.io/owned-by": "commander"
},
"current_revision": 0,
"commander_rules": [
{
"id": "455ccf46-f34c-4c75-970d-4dbc361adc68",
"verbs": ["*"],
"resources": ["*"],
"resource_names": null,
"created_at": "2025-04-30T23:46:18.616+03:00",
"updated_at": "2025-04-30T23:46:18.616+03:00"
}
],
"kubernetes_rules": [
{
"id": "9713527d-69df-4ecb-9db2-35df194e18b5",
"verbs": ["*"],
"resources": ["*"],
"resource_names": null,
"api_groups": ["*"],
"created_at": "2025-06-06T16:56:32.208+03:00",
"updated_at": "2025-06-06T16:56:32.208+03:00"
}
],
"created_at": "2025-04-30T23:46:18.567+03:00",
"updated_at": "2025-04-30T23:46:18.567+03:00"
}
]Создание назначения
PAYLOAD="$(jq -nc '{
"workspace_id": "088b8e03-e7c0-4655-aae7-d11b7609c579",
"name": "workspace-admins",
"comment": "Назначение из API",
"role": {
"type": "GlobalRole",
"id": "818c3814-4973-452e-9985-d75fbe35eb4c"
},
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io"
}
]
}')"
curl -X "POST" \
"https://$COMMANDER_HOST/api/v1/workspace_role_bindings" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"Успешный ответ:
{
"id": "05b3abdf-20a5-447b-823b-8e1a57b46158",
"name": "workspace-admins",
"comment": "Назначение из API",
"current_revision": 0,
"role_type": "GlobalRole",
"role": {
"id": "818c3814-4973-452e-9985-d75fbe35eb4c",
"name": "commander-admin",
"comment": null,
"labels": {
"commander.deckhouse.io/owned-by": "commander"
},
"current_revision": 0,
"created_at": "2025-04-30T23:46:18.567+03:00",
"updated_at": "2025-04-30T23:46:18.567+03:00"
},
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io",
"created_at": "2026-01-15T14:01:01.858+03:00",
"updated_at": "2026-01-15T14:01:01.858+03:00"
}
],
"created_at": "2026-01-15T14:01:01.821+03:00",
"updated_at": "2026-01-15T14:01:01.821+03:00"
}Добавление группы пользователей в назначение
PUT /api/v1/workspace_role_bindings/:id целиком заменяет список subjects и требует current_revision для оптимистичной блокировки.
PAYLOAD="$(jq -nc '{
"current_revision": 0,
"subjects": [
{
"kind": "User",
"name": "commander-admin@deckhouse.io"
},
{
"kind": "Group",
"name": "Administrators"
}
]
}')"
curl -X "PUT" \
"https://$COMMANDER_HOST/api/v1/workspace_role_bindings/05b3abdf-20a5-447b-823b-8e1a57b46158" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_GLOBAL_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"Получение актуальной версии шаблона
TEMPLATE_ID="fb999a72-efe7-4db7-af53-11b17bc0a687"
curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq "del(.cluster_template_versions)"Нужное поле — current_cluster_template_version_id:
{
"id": "fb999a72-efe7-4db7-af53-11b17bc0a687",
"name": "YC Dev",
"current_cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"comment": "Канал обновлений и версия k8s задаются параметрами",
"current_revision": 12,
"immutable": false,
"created_at": "2024-02-05T17:35:44.318+03:00",
"updated_at": "2024-04-10T18:00:57.835+03:00",
"archived_at": null,
"archive_number": null
}Сохраним его для последующих шагов:
TEMPLATE_VERSION_ID="$(curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r ".current_cluster_template_version_id")"Поиск неиспользованной записи в каталоге
Посмотрим схему входных параметров выбранной версии шаблона:
curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/cluster_templates/$TEMPLATE_ID?without_archived=true" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r --arg ver "$TEMPLATE_VERSION_ID" '
.cluster_template_versions[]
| select(.id == $ver)
| .params'Схема предусматривает три обязательных параметра; один из них — запись из каталога yandex-cloud-slot (поле catalog):
[
{ "header": "Параметры кластера" },
{
"key": "slot",
"span": 4,
"title": "Слот для кластера в Yandex Cloud",
"catalog": "yandex-cloud-slot",
"immutable": true
},
{
"key": "releaseChannel",
"enum": ["Alpha", "Beta", "EarlyAccess", "Stable", "RockSolid"],
"span": 1,
"title": "Канал обновлений",
"default": "EarlyAccess"
},
{
"key": "kubeVersion",
"enum": ["Automatic", "1.25", "1.26", "1.27", "1.28", "1.29"],
"span": 1,
"title": "Версия Kubernetes",
"default": "Automatic"
}
]Найдём каталог по его slug:
CATALOG_ID="$(curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/catalogs?without_archived=true" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -r '.[] | select(.slug == "yandex-cloud-slot") | .id')"Возьмём первую запись из этого каталога, не занятую другим кластером (cluster_id == null), и подготовим её к использованию: в значения записи добавим специальное поле x-commander-record-id со ссылкой на ID записи:
SLOT_VALUES="$(curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/records?without_archived=true" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" |
jq -c --arg cid "$CATALOG_ID" '
[ .[]
| select(.catalog_id == $cid and .cluster_id == null) ][0]
| .values + { "x-commander-record-id": .id }')"
echo "$SLOT_VALUES"Результат:
{
"ip": "158.166.177.188",
"name": "x",
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee"
}Имя ключа x-commander-record-id выбрано так, чтобы не конфликтовать с пользовательскими полями id, которые могут присутствовать в самих записях.
Создание кластера
PAYLOAD="$(jq -nc --argjson slot "$SLOT_VALUES" --arg ver "$TEMPLATE_VERSION_ID" '{
"name": "Кластер из API",
"cluster_template_version_id": $ver,
"values": {
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess",
"slot": $slot
}
}')"
curl -X "POST" \
"https://$COMMANDER_HOST/api/v1/clusters" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" \
-H "Content-Type: application/json" \
-d "$PAYLOAD"В ответ придут данные кластера. Часть полей (отрендеренная конфигурация, timestamps) в примере ниже опущена для краткости:
{
"id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"name": "Кластер из API",
"values": {
"slot": {
"ip": "158.166.177.188",
"name": "x",
"x-commander-record-id": "5f6727e7-630c-4b18-bcf0-868ea96a27ee"
},
"kubeVersion": "1.29",
"releaseChannel": "EarlyAccess"
},
"cluster_template_version_id": "8e75210a-f05c-421d-84b3-fc0697814d6d",
"was_created": false,
"status": "new"
}Опрос статуса готовности кластера
После создания или обновления кластера нужно опрашивать GET /api/v1/clusters/:id до достижения статуса status: "in_sync". Учитывайте поле render_errors: непустой список означает, что шаблон не отрендерился и операция не продвинется, пока входные значения не будут исправлены через PUT /api/v1/clusters/:id.
CLUSTER_ID="5436e6ef-d811-472f-9c9c-46cb9c6321d9"
DEADLINE=$(( $(date +%s) + 60 * 60 )) # таймаут 1 час
while : ; do
RESP="$(curl -sS -X "GET" \
"https://$COMMANDER_HOST/api/v1/clusters/$CLUSTER_ID" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN")"
STATUS="$(jq -r ".status" <<<"$RESP")"
RENDER_ERRORS="$(jq -r ".render_errors // [] | length" <<<"$RESP")"
echo "status=$STATUS render_errors=$RENDER_ERRORS"
if [ "$STATUS" = "in_sync" ]; then
echo "кластер готов"
break
fi
if [ "$RENDER_ERRORS" != "0" ]; then
echo "ошибка рендеринга шаблона, см. render_errors:"
jq ".render_errors" <<<"$RESP"
exit 1
fi
if [ "$(date +%s)" -gt "$DEADLINE" ]; then
echo "таймаут ожидания in_sync"
exit 1
fi
sleep 10
doneТипичная последовательность значений status: new → creating → in_sync. Застревание в creating вместе с непустым render_errors указывает на проблему с шаблоном или входными значениями; после обновления кластера через PUT опрос возобновится.
Получение облегчённого статуса кластера
Для частого опроса и дашбордов используйте GET /api/v1/clusters/:id/status. Эндпоинт возвращает компактный snapshot — текущий статус, активные алерты, сводку Upmeter и данные для подключения к master-узлу — и не содержит чувствительных полей, таких как отрендеренная конфигурация и API-ключ агента.
curl -s -X "GET" \
"https://$COMMANDER_HOST/api/v1/clusters/$CLUSTER_ID/status" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" | jq .{
"id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"status": "in_sync",
"active_alerts": [
{ "name": "KubeletDown", "severity_level": 4 }
],
"upmeter": {
"status": "up",
"components": [
{ "name": "control-plane", "status": "up" },
{ "name": "synthetic", "status": "up" }
]
},
"master_node": {
"host": "203.0.113.10",
"user": "ubuntu"
}
}active_alerts может быть пустым; upmeter и master_node могут быть null, пока агент кластера ещё не собрал данные.
Удаление кластера и ожидание его полного уничтожения
DELETE /api/v1/clusters/:id только инициирует удаление — в ответе возвращается кластер со статусом status: "delete" и флагом is_locked: true. Полное удаление подтверждается тем, что последующий GET возвращает 404 not_found.
CLUSTER_ID="5436e6ef-d811-472f-9c9c-46cb9c6321d9"
curl -sS -X "DELETE" \
"https://$COMMANDER_HOST/api/v1/clusters/$CLUSTER_ID" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" | jq "{id, status, is_locked}"{
"id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"status": "delete",
"is_locked": true
}Опрос до полного удаления:
DEADLINE=$(( $(date +%s) + 60 * 60 ))
while : ; do
HTTP_CODE="$(curl -sS -o /dev/null -w "%{http_code}" -X "GET" \
"https://$COMMANDER_HOST/api/v1/clusters/$CLUSTER_ID" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN")"
echo "http_code=$HTTP_CODE"
if [ "$HTTP_CODE" = "404" ]; then
echo "кластер полностью удалён"
break
fi
if [ "$(date +%s)" -gt "$DEADLINE" ]; then
echo "таймаут ожидания удаления"
exit 1
fi
sleep 10
doneЕсли кластер заблокирован другой операцией (например, идёт converge), DELETE вернёт 409 Conflict:
{
"error": "Cluster is locked",
"error_code": "conflict",
"errors": null
}Повторите DELETE после завершения блокирующей операции или проверьте ожидающие запросы на изменение кластера через GET /api/v1/cluster_change_requests?cluster_id=$CLUSTER_ID и одобрите/отмените их.
Принудительное удаление кластера
Используйте DELETE /api/v1/clusters/:id/force, если инфраструктура уже уничтожена вне Commander либо кластер находится в состоянии, из которого обычный DELETE /api/v1/clusters/:id не может восстановиться. Принудительное удаление убирает запись кластера из Commander без запуска dhctl destroy и не затрагивает внешние ресурсы — очистите инфраструктуру самостоятельно.
curl -sS -X "DELETE" \
"https://$COMMANDER_HOST/api/v1/clusters/$CLUSTER_ID/force" \
-H "accept: application/json" \
-H "X-Auth-Token: $COMMANDER_TOKEN" | jq "{id, status, is_locked}"Для штатного удаления используйте DELETE /api/v1/clusters/:id; принудительное удаление оставьте как инструмент ручного восстановления
Управление проектами
API позволяет получать список проектов, создавать, изменять и удалять проекты типа commander. Проекты типа deckhouse — это проекты DKP (ресурсы Project модуля multitenancy-manager), созданные непосредственно в прикладном кластере и не управляемые Deckhouse Commander; Commander их обнаруживает и отображает, но изменение и удаление таких проектов через API запрещено — попытка возвращает 403. Подробнее о типах проектов, статусах и коллизиях имён см. раздел Проекты руководства пользователя.
Все примеры используют токен рабочего пространства (заголовок X-Auth-Token: $COMMANDER_TOKEN).
Получение списка проектов
curl -s -X 'GET' \
"https://$COMMANDER_HOST/api/v1/projects" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN"В ответе возвращается массив проектов рабочего пространства. Ниже приведён сокращённый пример (часть полей опущена для краткости):
[
{
"id": "1a0c4f1b-8f24-4d0a-9a21-0c2d7e1a2b3c",
"name": "web-frontend",
"kind": "commander",
"description": "Публичный сайт команды",
"resource_quota": {
"requests": {
"cpu": "2",
"memory": "4Gi",
"storage": "50Gi"
}
},
"cumulative_status": "deployed",
"status_data": {},
"kubernetes_project_id": "b7c1d1d8-9d0e-4cbb-8d9e-2b77b6b9f9c1",
"cluster_id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"cluster_name": "prod-eu-1",
"administrators": [
{ "kind": "User", "name": "alice@example.com" },
{ "kind": "Group", "name": "platform-admins" }
],
"error_messages": [],
"created_at": "2026-04-10T12:00:00Z",
"synced_at": "2026-04-23T18:15:32Z"
}
]Ключевые поля ответа:
id— идентификатор проекта в Deckhouse Commander;name— имя проекта (совпадает с именем namespace в прикладном кластере);kind— тип проекта:commanderилиdeckhouse;cluster_id,cluster_name— прикладной кластер, в котором создан проект;cumulative_status— итоговый статус проекта (см. Статусы проекта);kubernetes_project_id— идентификатор объектаProjectв прикладном кластере; заполняется после успешного применения агентом;resource_quota— установленные ресурсные квоты проекта;administrators— пользователи и группы, назначенные администраторами проекта;error_messages— сообщения об ошибках применения проекта, если они есть.
Создание проекта
curl -s -X 'POST' \
"https://$COMMANDER_HOST/api/v1/projects" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "web-frontend",
"cluster_id": "5436e6ef-d811-472f-9c9c-46cb9c6321d9",
"description": "Публичный сайт команды",
"resource_quota": {
"requests": {
"cpu": "2",
"memory": "4Gi",
"storage": "50Gi"
}
},
"administrators": [
{ "kind": "User", "name": "alice@example.com" },
{ "kind": "Group", "name": "platform-admins" }
]
}'Параметры запроса:
name(обязательный) — имя проекта. Должно соответствовать правилам именованияnamespaceв Kubernetes, зарезервированные системные имена (в частности,defaultиdeckhouse) использовать нельзя, уникальность проверяется в пределах кластера.cluster_id(обязательный) — идентификатор прикладного кластера. После создания проекта менять нельзя.administrators(обязательный, минимум один элемент) — массив объектов{"kind": "User"|"Group", "name": "..."}. Значениеkindпринимает толькоUserилиGroup.description— произвольное описание проекта.resource_quota— ресурсные квоты; поддерживаются ключиrequests.cpu,requests.memory,requests.storage. Ограничения (limits) в текущей итерации не задаются.
В успешном ответе 201 Created возвращается тело объекта проекта, идентичное формату в получении списка. Сразу после создания cumulative_status обычно равен initialized и со временем переходит в synchronization, а затем в deployed.
При нарушении правил валидации возвращается 422 Unprocessable Entity, например при попытке сохранить проект без администраторов:
{
"errors": {
"administrators": ["В проекте должен быть назначен хотя бы один администратор"]
}
}Изменение проекта
curl -s -X 'PUT' \
"https://$COMMANDER_HOST/api/v1/projects/1a0c4f1b-8f24-4d0a-9a21-0c2d7e1a2b3c" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN" \
-H 'Content-Type: application/json' \
-d '{
"name": "web-frontend",
"description": "Публичный сайт команды (прод)",
"resource_quota": {
"requests": {
"cpu": "4",
"memory": "8Gi",
"storage": "100Gi"
}
},
"administrators": [
{ "kind": "User", "name": "alice@example.com" },
{ "kind": "User", "name": "bob@example.com" },
{ "kind": "Group", "name": "platform-admins" }
]
}'Тело запроса такое же, как при создании, за исключением поля cluster_id — изменить прикладной кластер у существующего проекта нельзя. В ответе возвращается обновлённый объект проекта.
Попытка изменить проект типа deckhouse возвращает 403 Forbidden.
Удаление проекта
Удаление проекта через API — необратимая операция. Вместе с проектом в прикладном кластере удаляются все созданные в нём ресурсы (namespace, рабочие нагрузки, конфигурации и секреты). Отменить удаление нельзя, и ни сам проект, ни его ресурсы восстановлению не подлежат. Перед выполнением DELETE-запроса убедитесь, что проект и все его данные больше не нужны — в интеграционном сценарии рекомендуется явно подтверждать намерение удалить проект на стороне вызывающей системы.
curl -s -X 'DELETE' \
"https://$COMMANDER_HOST/api/v1/projects/1a0c4f1b-8f24-4d0a-9a21-0c2d7e1a2b3c" \
-H 'accept: application/json' \
-H "X-Auth-Token: $COMMANDER_TOKEN"Commander снимает с проекта служебные лейблы и запрашивает у агента удаление ресурса Project в прикладном кластере. В ответе возвращается тело удаляемого проекта с обновлённым статусом.
Удаление проектов типа deckhouse через API недоступно и возвращает 403 Forbidden; такие проекты удаляются непосредственно в Deckhouse с помощью модуля multitenancy-manager.
Управление участниками проекта (ресурсы ProjectRoleBinding) и пользовательскими шаблонами проектов через API интеграции в текущем релизе не поддерживаются и появятся в следующих релизах.