Утилита управления Control Plane (cpctl)
Клиент cpctl для публичного API Control Plane
Назначение
cpctl — клиент на языке Go для публичного management API компонента Control Plane Платформы ИИ. Он самостоятельный дистрибутив: не входит в образ Python-сервиса и не обращается к его базе данных, Kubernetes или внутренней реализации. cpctl работает только через публичный API, от имени выбранного контекста (человека или сервиса).
Утилита покрывает 56 публичных операций OpenAPI: каждая операция сопоставлена с командой ровно один раз. Закрытый JSON-запрос отправляется на API без изменений — это карта «метод/путь/команда», а не отдельная реализация домена.
Подготовка: контекст и вход
Контекст хранит только непубличные настройки (адрес, идентификацию) — секреты токенов в него не пишутся. Сначала создают контекст, затем выбирают его и входят.
Контекст человека (авторизация устройства, значения задаёт владелец окружения):
cpctl config set-context dev-local \
--server http://api-gw.localhost:18085/control-plane \
--identity human \
--issuer http://api-gw.localhost:18085/keycloak/realms/ap-dev \
--audience control-plane \
--client-id cpctl-dev \
--device-authorization-endpoint http://api-gw.localhost:18085/keycloak/realms/ap-dev/protocol/openid-connect/auth/device \
--token-endpoint http://api-gw.localhost:18085/keycloak/realms/ap-dev/protocol/openid-connect/token
cpctl config use-context dev-local
cpctl loginAccess- и refresh-токены лежат только в хранилище секретов ОС (security на macOS, Secret Service через secret-tool на Linux) и никогда не попадают в файл контекста.
Контекст сервиса (обмен client-credentials на каждый процесс; секрет клиента читается из переменной окружения):
cpctl config set-context ci \
--server https://api.example/control-plane \
--identity service \
--issuer https://identity.example/realms/platform \
--audience control-plane \
--client-id cpctl-service \
--token-endpoint https://identity.example/realms/platform/protocol/openid-connect/token \
--client-secret-env CPCTL_SERVICE_CLIENT_SECRET
CPCTL_CONTEXT=ci CPCTL_SERVICE_CLIENT_SECRET='<внедрено>' cpctl system statusПрофили человека и сервиса не переключают друг на друга и не подхватывают внедрённый access-токен. Связка CPCTL_SERVER + CPCTL_ACCESS_TOKEN — явный процессный профиль разработки, работоспособный только на localhost.
Команды чтения и контроля состояния
Чтение не изменяет состояние и безопасно повторять. Для администратора доступны следующие команды:
| Команда | Назначение |
|---|---|
cpctl system status | Общая доступность Control Plane |
cpctl tiers list / tiers get <id> | Просмотр уровней и лимитов |
cpctl providers list / providers get <id> | Просмотр поставщиков |
cpctl models list / models get <id> | Просмотр моделей |
cpctl keys list | Список всех ключей с фильтрами по владельцу |
cpctl keys get <id> | Метаданные ключа без секрета |
cpctl policies key-issuance get | Текущая политика выдачи ключей |
cpctl policies agent-publication get | Текущая политика публикации |
cpctl operations list / get / wait / cancel | Управление длительными операциями |
cpctl drift | Отклонения желаемого и фактического состояния |
cpctl audit | Неизменяемый журнал операций |
cpctl contract check --openapi <путь> | Сверка с каноническим OpenAPI |
Списки принимают --limit 1..100 (по умолчанию 20) и --cursor для пагинации; keys list дополнительно поддерживает фильтры --owner-type, --owner-issuer, --owner-subject. operations wait <id> ждёт терминального состояния операции с таймаутом --wait-timeout.
Изменяющие операции
Все изменяющие команды принимают --file (закрытый JSON-объект; - читает из stdin), обязательный --idempotency-key, а для операций с контролем версий — --revision <n>, из которого строится заголовок If-Match: "r<n>".
| Команда | Назначение |
|---|---|
cpctl tiers create|update|delete | Управление уровнями и лимитами |
cpctl providers create|update|delete | Управление поставщиками |
cpctl providers credential put <id> | Привязка зашифрованных учётных данных провайдера |
cpctl models create|update|delete | Управление моделями |
cpctl keys issue | Выдача ключа администратором |
cpctl keys update <id> | Изменение политики ключа |
cpctl keys rotate <id> | Ротация ключа |
cpctl keys revoke <id> | Отзыв ключа |
cpctl policies key-issuance update | Изменение политики выдачи |
cpctl policies agent-publication update | Изменение политики публикации |
cpctl agents create|update|status | Управление агентами |
cpctl agents rollback|unpublish|revalidate <id> | Жизненный цикл публикации |
cpctl agents versions create <id> | Создание версии агента |
cpctl low-code artifacts upload | Загрузка артефакта Low-code Конструктора |
cpctl bulk preview|execute | Массовое изменение состояния |
cpctl recovery preview|execute | Согласованное ручное продолжение |
Примеры:
cpctl providers credential put '<provider-id>' --revision 2 \
--file credential.json --idempotency-key provider-credential-0001
cpctl models update '<model-id>' --revision 4 \
--file model-patch.json --idempotency-key model-update-0001Поведение асинхронных операций
Изменяющие команды, возвращающие 202 Accepted, по умолчанию ждут завершения Operation и печатают терминальный результат. Флаг --no-wait возвращает сразу после принятия, печатает точный ID и ссылку операции и завершается кодом 10 (принято, но не выполнено). Это корректно только для асинхронных операций; для синхронных (например, keys rotate) флаг отклоняется.
Обработка одноразовых секретов
Команды keys issue и keys rotate не печатают oneTimeSecret в stdout. Они создают новый файл с правом 0600 по пути из --secret-output, резервируют его до изменения и отказываются перезаписывать существующий. При идемпотентном повторе (тот же Idempotency-Key) сервер возвращает только метаданные — файл секретов в этом случае не создаётся, о чём утилита предупреждает в stderr.
cpctl keys issue --file issue.json --idempotency-key issue-key-00000001 \
--secret-output ./issued.keyМассовые операции и восстановление
bulk и recovery используют схему «предпросмотр → подтверждённое выполнение». Выполнение требует подтверждение в интерактивном терминале или флаг --yes. Если передан --preview-file, cpctl сверяет previewId и previewDigest с путём и запросом выполнения до обращения к API.
cpctl bulk preview --file revoke.json --idempotency-key bulk-preview-0001 \
--output json > preview.json
cpctl bulk execute '<preview-id>' --request-digest '<sha256:...>' \
--preview-file preview.json --idempotency-key bulk-execute-0001 --yes
cpctl recovery preview --reason-code recovery_drill \
--idempotency-key recovery-preview-0001 --output json > recovery-preview.json
cpctl recovery execute '<preview-id>' --file recovery-decisions.json \
--preview-file recovery-preview.json --idempotency-key recovery-execute-0001 --yesЗакрытый запрос recovery execute отправляется побайто из --file; для чтения из stdin используют --file - --yes.
Коды завершения
| Код | Значение |
|---|---|
0 | Успех; Operation завершилась в succeeded |
2 | Ошибка локального ввода (аргументы, файлы, формат) |
3 | Ошибка API |
4 | Operation завершилась в failed или cancelled |
5 | Сбой транспорта или тайм-аут ожидания |
10 | Operation принята (--no-wait), но ещё не выполнена |
Ограничения
cpctlне управляет ключами, принадлежащими агенту: их жизненный цикл принадлежит публикации (см. руководство по Control Plane).keys update— только административная команда; для самообслуживания (keys self) изменение политики ключа недоступно.- Жёсткое удаление агентов не предусмотрено — используйте
agents unpublish.