diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 00000000..d1b65c05 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,61 @@ +# Правила + +## ⛔ ОТВЕЧАТЬ КРАТКО — АБСОЛЮТНОЕ ПРАВИЛО +- Вопрос → короткий ответ → СТОП. +- Ничего лишнего. +- Код — только по запросу. + +## ⛔⛔⛔ ВОПРОС = СТОП + +**Если в сообщении есть вопрос в ЛЮБОЙ форме** ("так ?", "верно ?", "почему ?", "как ?", "так же ?" и т.д.): +1. ТОЛЬКО ответить на вопрос +2. ОСТАНОВИТЬСЯ +3. ЖДАТЬ следующей команды +**ЗАПРЕЩЕНО** начинать работу, писать код, запускать команды — без явного "делай". + +1. Не трогать рабочий код без явного указания. + +2. Файлы редактируются локально: + ~/fission-src (текущая рабочая папка) + + После ЛЮБЫХ изменений ОБЯЗАТЕЛЬНО синхронизировать на ВМ командой: + rsync -az \ + -e "ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10" \ + ~/fission-src/ \ + naeel@5.172.178.213:~/terra/fission-src/ + + +3. Git (add/commit/push) выполнять ЛОКАЛЬНО в ~/fission-src +4. Docker, kubectl и другие инфраструктурные команды — только через SSH на ВМ: + ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10 naeel@5.172.178.213 'КОМАНДА' + + - не выполнять инфраструктурные команды локально + - не открывать интерактивные сессии + - не делать цепочки без необходимости + +4. Перед запуском команд ОБЯЗАТЕЛЬНО убедиться, что синхронизация выполнена. + +5. ЗАПРЕЩЕНО: + - откатывать код + - менять версии + - ломать рабочее состояние + +6. После каждого исправления: + - git add/commit ЛОКАЛЬНО (в ~/fission-src) + - затем синхронизация (rsync) на ВМ + +## ⛔⛔⛔ ДЕЛАТЬ ТОЛЬКО ЧТО ПРЯМО ПРИКАЗАНО + +**АБСОЛЮТНЫЙ ЗАПРЕТ на додумывание:** +- Не расширять масштаб работы +- Не выполнять "логичные следующие шаги" +- Не инициировать дополнительные операции +- Не делать ничего кроме того что сказано + +**Пример (2026-05-01):** +- Приказано: "собери" +- Сделано: ✓ собрал образы v1.3.17 и v0.1.2 +- СТОП — жду команды дальше +- **ЗАПРЕЩЕНО:** обновлять манифесты, заливать образы, применять на кластер, запускать тесты + +**Исключение:** только если приказ явно включает цепочку ("собери И залей И тесты") diff --git a/.github/pravila.md b/.github/pravila.md new file mode 100644 index 00000000..1b3c9f2c --- /dev/null +++ b/.github/pravila.md @@ -0,0 +1,99 @@ +# Правила работы агента + +## ⛔⛔⛔ DOCKER — ОБЯЗАТЕЛЬНЫЙ ПОРЯДОК ПЕРЕД КАЖДЫМ BUILD + +1. УВЕЛИЧИТЬ ТЕГ в `console/deploy/console.yaml` (vX.Y.Z → vX.Y.Z+1) +2. rsync на ВМ +3. ПРОВЕРИТЬ что файлы на ВМ новые (grep ключевой строки) +4. docker build с НОВЫМ тегом +5. docker push с НОВЫМ тегом +6. kubectl apply (не rollout restart — apply подтягивает новый тег) + +**НИКОГДА не делать `docker build` со старым тегом — под не перетянет образ (imagePullPolicy: IfNotPresent)** + +## Файловая система (актуально) + +1. Все файлы редактируются локально: `~/fission-src` (текущая рабочая папка) +2. После любых изменений — обязательно rsync на ВМ: + rsync -az \ + -e "ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10" \ + ~/fission-src/ \ + naeel@5.172.178.213:~/terra/fission-src/ + +3. Git (add/commit/push) выполнять ЛОКАЛЬНО в ~/fission-src +4. Docker, kubectl и другие инфраструктурные команды — только через SSH на ВМ +5. Перед запуском любой команды на ВМ обязательно убедиться, что синхронизация (rsync) выполнена +6. SCP, sshfs, remote_dev и маунты больше НЕ используются +7. Только rsync для синхронизации + +Пример: +1. Редактируешь локально (~/fission-src) +2. rsync на ВМ +3. Выполняешь команды через SSH на ВМ + +## SSH + +Все команды — только через SSH на ВМ. Локально — только читать и редактировать файлы. + +```bash +ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no -o ConnectTimeout=10 naeel@5.172.178.213 'КОМАНДА' +``` + +Запрещено локально: `go`, `docker`, `kubectl`, `helm`, `terraform`, `curl/wget`, `git push/pull`, любые скрипты проекта. + +## Документация + +- `doc/thinking/` — лог рассуждений агента (обязательно) +- `doc/progress.md` — трекер задач +- Старые файлы `doc/` не перезаписывать — новое в новых файлах с датой + +## Git + +- Git — ТОЛЬКО ЛОКАЛЬНО в `~/fission-src`. НИКОГДА через SSH на VM. +- Разрешены ТОЛЬКО две операции: `git commit` и `git push`. +- ЗАПРЕЩЕНО: git pull, git fetch, git rebase, git merge, git reset, git stash, git checkout — что угодно кроме commit и push. +- Если push отклонён — СТОП, доложить пользователю. Не лезть в pull/merge/rebase самостоятельно. + +Версионирование тегами: `vMAJOR.MINOR.PATCH` +- Patch — любое изменение кода +- Minor — новая фича / компонент +- Major — breaking change + +```bash +git tag vX.Y.Z && git push origin vX.Y.Z +``` + +## ⛔ ТЕРМИНАЛЬНЫЙ БУФЕР — НИКОГДА НЕ ЧИТАТЬ СТАРЫЙ + +**АБСОЛЮТНОЕ ПРАВИЛО:** +- get_terminal_output из старых сессий — МУСОР. Там старые прогоны. +- Всегда запускать новую команду через SSH и читать её вывод напрямую. +- НИКОГДА не читать буфер терминала из предыдущей сессии как актуальные данные. +- Актуальный результат — только из команды, которая была запущена СЕЙЧАС. + +## ⛔ ДОКУМЕНТАЦИЯ ТЕСТ-ПРОГОНОВ — В РЕАЛЬНОМ ВРЕМЕНИ + +**Правила:** +1. Перед запуском `run_all.sh` — создать файл `test-results/YYYY-MM-DD_HH-MM.log` и записать в него метку времени и что запускается. +2. Запускать `run_all.sh 2>&1 | tee ~/terra/fission-src/test-results/YYYY-MM-DD_HH-MM.log` — вывод пишется сразу в файл и отображается в терминале. +3. После завершения — rsync лога локально. Лог остаётся как документация. +4. Папка `test-results/` в репозитории — `.gitignore` не добавлять, логи коммитить. + +**Формат запуска:** +```bash +LOG="test-results/$(date +%Y-%m-%d_%H-%M).log" +ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no naeel@5.172.178.213 \ + "bash ~/terra/fission-src/scripts/run_all.sh 2>&1 | tee ~/terra/fission-src/${LOG}" +rsync -az -e "ssh -i ~/.ssh/naeel_vm_id_ed25519 -o StrictHostKeyChecking=no" \ + naeel@5.172.178.213:~/terra/fission-src/test-results/ ~/fission-src/test-results/ +``` + +**Никогда не разбираться с результатами по памяти / буферу / чату. Только лог.** + +## Поведение агента + +- Не трогать рабочий код без явного указания +- Не делать НИЧЕГО сверх того, о чём явно приказали — ни git-команд, ни rebase, ни дополнительных шагов +- Если для продолжения нужен выбор — СПРОСИТЬ разрешения, не делать самостоятельно +- Деструктивные операции (`kubectl delete`, `rm -rf`, `terraform destroy` и др.) — только после явного подтверждения с указанием конкретных объектов +- Отвечать кратко, без вступлений, извинений, благодарностей и прочей воды diff --git a/.gitignore b/.gitignore index 8f81cd1d..8447049b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ environments/php7/vendor/ *.tfstate *.backup +*.token + # Common backup files *.swp *.bak diff --git a/doc/api-guide.md b/doc/api-guide.md new file mode 100644 index 00000000..a2a91241 --- /dev/null +++ b/doc/api-guide.md @@ -0,0 +1,644 @@ +# Fission Console API — Руководство пользователя + +> Версия: актуальна для модернизированного Fission с мультитенантностью (ngcloud). + +--- + +## Базовый URL + +``` +https://fission.kube5s.ru/console/api +``` + +--- + +## Аутентификация + +### Где взять токен + +Сервер поддерживает два типа токенов — определяет автоматически по форме: + +| Форма токена | Тип | Описание | +|---|---|---| +| JWT (три части через `.`) | **Production** | JWT из личного кабинета NUBES (Профиль → Токены). Валидируется через Deck API облака | +| Любая строка ≥ 6 символов | **Demo** | Любой произвольный логин — без внешней проверки. Удобно для разработки и тестирования | +| Строка < 6 символов | — | 401 | + +**Production (NUBES):** JWT-токен берётся в личном кабинете NUBES → Профиль → Токены. +**Demo:** любая строка ≥ 6 символов — например `myuser@example.com` или `dev-user-1`. + +### Передача токена + +Два способа — оба равнозначны: + +```http +X-Auth-Token: <токен> +``` +```http +Authorization: Bearer <токен> +``` + +### POST /auth + +Проверка токена и получение информации о своём namespace. + +```bash +curl -X POST https://fission.kube5s.ru/console/api/auth \ + -H "Content-Type: application/json" \ + -d '{"token": "myuser@example.com", "env": "test"}' +``` + +**Параметры:** +| Поле | Описание | +|---|---| +| `token` | Токен (JWT или demo-строка) | +| `env` | Стенд: `prod`, `dev`, `test` (только для JWT; по умолчанию `test`) | + +**Ответ 200:** +```json +{ + "ok": true, + "env": "test", + "namespace": "fission-a3f9c1b2d4e6f8a1", + "email": "user@example.com" +} +``` + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 400 | Тело не JSON или `token` пустой | +| 401 | Токен < 6 символов или JWT не прошёл валидацию в Deck API | +| 405 | GET вместо POST | + +> **Namespace детерминирован**: `fission-` + hex(SHA256(sub)[:8]) — одинаковый токен → всегда один namespace. +> Namespace и RBAC создаются автоматически при первом обращении. + +--- + +## Мультитенантность ★ КЛЮЧЕВОЕ ОТЛИЧИЕ + +- Каждый пользователь работает в **изолированном K8s namespace**: `fission-` +- Все операции (создание, список, вызов, удаление) **автоматически ограничены своим namespace** +- Указать namespace вручную **невозможно** +- Функции другого пользователя **не видны и не доступны** — любая операция над чужим объектом возвращает **404** (не 403, чтобы не раскрывать факт существования) +- **Routes изолированы**: функции разных пользователей с одинаковым именем получают разные HTTP-маршруты + +### Квоты (применяются автоматически, значения по умолчанию) + +| Ресурс | Лимит | +|--------|-------| +| Функции (`count/functions.fission.io`) | 20 | +| Пакеты (`count/packages.fission.io`) | 40 | +| HTTP Triggers (`count/httptriggers.fission.io`) | 20 | +| Pods | 30 | +| CPU requests (суммарно) | 1 | +| CPU limits (суммарно) | 12 | +| RAM requests (суммарно) | 2 Gi | +| RAM limits (суммарно) | 6 Gi | + +> Значения настраиваются env vars (`QUOTA_REQ_CPU`, `QUOTA_PODS`, и т.д.) без пересборки. + +--- + +## Функции + +### POST /functions — Создать функцию из кода (JSON) + +```bash +curl -X POST https://fission.kube5s.ru/console/api/functions \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-fn", + "language": "nodejs", + "code": "module.exports = async function(ctx) { return { status: 200, body: \"hello\" }; }" + }' +``` + +**Параметры запроса:** +| Поле | Тип | Обязательно | Описание | +|------|-----|:-----------:|---------| +| `name` | string | ✓ | Имя функции (см. правила ниже) | +| `language` | string | ✓ | Среда выполнения: `nodejs`, `python`, `go`, `php`, `ruby` | +| `code` | string | ✓ | Исходный код (строка). Максимум 1 MB | +| `entrypoint` | string | — | Точка входа (по умолчанию — зависит от языка) | +| `route` | string | — | HTTP-маршрут (по умолчанию `//`) | +| `methods` | []string | — | HTTP-методы (по умолчанию `["GET"]`) | +| `timeout` | int64 | — | Таймаут функции в секундах | +| `ttl` | string | — | Время жизни функции: `15m`, `1h`, `2d` и т.д. ★ | + +**Правила именования (`name`):** +- Только строчные буквы, цифры, дефис +- Не начинается и не заканчивается дефисом +- Максимум **57 символов** + +**Ответ 201:** +```json +{ + "name": "my-fn", + "package": "my-fn-pkg", + "httptrigger": "my-fn-route", + "route": "/a3f9c1b2d4e6/my-fn", + "expires_at": null +} +``` +> `expires_at` — время удаления функции (RFC3339), `null` если TTL не задан. + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 400 | Нет `name`/`language`/`code`, невалидное имя, неизвестный язык, код > 1 MB, невалидный TTL | +| 409 | Функция с таким именем уже существует у этого пользователя | + +--- + +### POST /functions — Создать функцию из zip-архива (multipart) + +Альтернативный способ: передать архив напрямую при создании функции. + +```bash +curl -X POST https://fission.kube5s.ru/console/api/functions \ + -H "X-Auth-Token: user@domain.com" \ + -F "name=my-fn" \ + -F "language=python" \ + -F "entrypoint=main.handler" \ + -F "archive=@my-function.zip" +``` + +**Параметры формы (multipart/form-data):** +| Поле | Тип | Обязательно | Описание | +|------|-----|:-----------:|---------| +| `name` | string | ✓ | Имя функции | +| `language` | string | ✓* | Язык (`python`, `nodejs`, `go`, `php`, `ruby`) — или `environment` | +| `environment` | string | ✓* | Явное имя environment (вместо `language`) | +| `archive` | file | ✓ | zip-архив с кодом. Максимум 100 KB | +| `entrypoint` | string | — | Точка входа | +| `route` | string | — | HTTP-маршрут | +| `methods` | string | — | HTTP-методы через запятую (`GET,POST`) | +| `timeout` | string | — | Таймаут в секундах | +| `ttl` | string | — | Время жизни: `15m`, `1h`, `2d` и т.д. | + +> Архив должен быть валидным zip (magic bytes `PK`). Максимальный суммарный распакованный размер — 100 KB (защита от zip bomb). + +**Ответ 201:** +```json +{ + "name": "my-fn", + "namespace": "fission-a3f9c1b2d4e6f8a1", + "environment": "python-env", + "route": "/a3f9c1b2d4e6/my-fn", + "source_type": "archive" +} +``` + +--- + +### GET /functions — Список функций + +```bash +curl https://fission.kube5s.ru/console/api/functions \ + -H "X-Auth-Token: user@domain.com" +``` + +**Ответ 200** — массив сырых K8s объектов типа `Function`. Новый пользователь → `[]`. +Возвращает **только функции текущего пользователя**. + +--- + +### GET /functions/{name} — Описание функции + +```bash +curl https://fission.kube5s.ru/console/api/functions/my-fn \ + -H "X-Auth-Token: user@domain.com" +``` + +**Ответ 200:** +```json +{ + "name": "my-fn", + "namespace": "fission-a3f9c1b2d4e6f8a1", + "environment": "nodejs-env", + "package": "my-fn-pkg", + "entrypoint": "main", + "timeout": 60, + "created_at": "2026-05-01T10:00:00Z", + "updated_at": "2026-05-01T12:00:00Z", + "code": "module.exports = async function(ctx) { ... }", + "source_type": "code", + "archive_filename": "", + "route": "/a3f9c1b2d4e6/my-fn", + "methods": ["GET", "POST"], + "raw": {} +} +``` + +> `code` — исходный код (если хранится как literal). Для функций из архива может быть пустым. +> `source_type` — `"code"` или `"archive"`. +> `raw` — полный K8s объект Function. + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 404 | Функция не существует или принадлежит другому пользователю | + +--- + +### POST /functions/{name}/invoke — Вызов функции + +```bash +curl -X POST https://fission.kube5s.ru/console/api/functions/my-fn/invoke \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{}' +``` + +**Ответ 200:** +```json +{ + "status": 200, + "latency_ms": 42, + "response_raw": "hello" +} +``` + +> `response_raw` — тело ответа функции как строка. +> `status` — HTTP-статус ответа функции. +> `latency_ms` — время выполнения в миллисекундах. +> Cold start (первый вызов после создания) может занять **10-60 секунд** — Pod создаётся и прогревается. Последующие вызовы быстрые. + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 404 | Функция не существует или принадлежит другому пользователю | +| 502 | Fission router недоступен или функция завершилась с timeout | + +--- + +### PUT /functions/{name}/code — Обновить код функции ★ + +Обновляет код существующей функции. Создаётся новый Package, executor подхватывает его при следующем вызове. + +```bash +curl -X PUT https://fission.kube5s.ru/console/api/functions/my-fn/code \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{ + "code": "module.exports = async function(ctx) { return { status: 200, body: \"v2\" }; }" + }' +``` + +**Параметры:** +| Поле | Тип | Обязательно | Описание | +|------|-----|:-----------:|---------| +| `code` | string | ✓ | Новый исходный код | +| `timeout` | int64 | — | Новый таймаут в секундах | + +**Ответ 200:** +```json +{ + "updated": true, + "package": "my-fn-pkg-xxxxxx" +} +``` + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 400 | `code` пустой или только пробелы | +| 404 | Функция не существует или принадлежит другому пользователю | + +--- + +### PUT /functions/{name}/archive — Обновить архив функции ★ + +Обновляет функцию новым zip-архивом (multipart/form-data, поле `archive`). + +```bash +curl -X PUT https://fission.kube5s.ru/console/api/functions/my-fn/archive \ + -H "X-Auth-Token: user@domain.com" \ + -F "archive=@my-function-v2.zip" +``` + +**Ответ 200:** +```json +{ + "updated": true, + "package": "my-fn-pkg-xxxxxx" +} +``` + +--- + +### PUT /functions/{name}/timeout — Обновить таймаут функции ★ + +Обновляет только таймаут (и опционально entrypoint) без замены кода или архива. + +```bash +curl -X PUT https://fission.kube5s.ru/console/api/functions/my-fn/timeout \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{"timeout": 120}' +``` + +**Параметры:** +| Поле | Тип | Описание | +|------|-----|---------| +| `timeout` | int64 | Новый таймаут в секундах | +| `entrypoint` | string | Новая точка входа (опционально) | + +**Ответ 200:** +```json +{ + "updated": true, + "timeout": 120 +} +``` + +--- + +### DELETE /functions/{name} — Удалить функцию + +```bash +curl -X DELETE https://fission.kube5s.ru/console/api/functions/my-fn \ + -H "X-Auth-Token: user@domain.com" +``` + +**Ответ 200:** +```json +{ + "deleted": true, + "name": "my-fn", + "package": "my-fn-pkg" +} +``` + +> Удаляются также связанные HTTPTrigger, TimeTrigger и Package. +> Архив в S3 удаляется асинхронно. +> Если язык больше не используется ни одной функцией — environment Pod'ы убираются автоматически. + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 404 | Функция не существует или принадлежит другому пользователю | + +> Повторное удаление той же функции → **404**. + +--- + +## Прямой вызов по route — GET|POST /fn/{route} + +Вызов функции напрямую по HTTP-маршруту без обёртки invoke. Ответ проксируется как есть — без JSON-обёртки. + +```bash +curl https://fission.kube5s.ru/fn/a3f9c1b2d4e6/my-fn \ + -H "X-Auth-Token: user@domain.com" +``` + +> Используйте этот endpoint когда нужно получить чистый HTTP-ответ функции, а не JSON-обёртку с `response_raw`. +> Метод запроса (GET/POST/…) проксируется без изменений. + +--- + +## Time Triggers (расписание) + +### GET /timetriggers — Список + +```bash +curl https://fission.kube5s.ru/console/api/timetriggers \ + -H "X-Auth-Token: user@domain.com" +``` + +Возвращает массив сырых K8s объектов TimeTrigger. + +### POST /timetriggers — Создать + +```bash +curl -X POST https://fission.kube5s.ru/console/api/timetriggers \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-cron", + "functionName": "my-fn", + "cron": "*/5 * * * *" + }' +``` + +**Параметры:** +| Поле | Тип | Обязательно | Описание | +|------|-----|:-----------:|---------| +| `name` | string | ✓ | Имя trigger'а | +| `functionName` | string | ✓ | Имя функции | +| `cron` | string | ✓ | Cron-выражение (стандартный формат) | +| `method` | string | — | HTTP-метод для вызова (по умолчанию `POST`) | +| `subpath` | string | — | Дополнительный путь | + +**Ответ 201:** +```json +{ + "name": "my-cron", + "namespace": "fission-a3f9c1b2d4e6f8a1", + "cron": "*/5 * * * *", + "method": "POST", + "subpath": "", + "function": "my-fn", + "raw": {} +} +``` + +### GET /timetriggers/{name} — Описание + +**Ответ 200** — та же структура что и при создании. + +### PUT /timetriggers/{name} — Обновить + +**Ответ 200:** +```json +{ + "updated": true, + "trigger": { ...та же структура... } +} +``` + +### DELETE /timetriggers/{name} — Удалить + +**Ответ 200:** +```json +{ + "deleted": true, + "name": "my-cron" +} +``` + +--- + +## AI-линтер архивов ★ + +Проверяет zip-архив на синтаксические ошибки до деплоя. Не создаёт функцию. +Поддерживаемые файлы: `.py`, `.js`, `.rb`, `.php`. + +### POST /ai/lint-archive + +```bash +curl -X POST https://fission.kube5s.ru/console/api/ai/lint-archive \ + -H "X-Auth-Token: user@domain.com" \ + -F "archive=@my-function.zip" \ + -F "entrypoint=main.handler" \ + -F "language=python" +``` + +**Параметры формы:** +| Поле | Описание | +|------|---------| +| `archive` | zip-архив (обязательно) | +| `entrypoint` | Точка входа `module.function` — проверяется что файл и функция существуют в архиве | +| `language` | Язык — проверяется что архив содержит файлы нужного расширения | + +**Ответ 200:** +```json +{ + "ok": true, + "results": [ + {"file": "main.py", "ok": true}, + {"file": "helper.py", "ok": false, "output": "SyntaxError: invalid syntax (helper.py, line 5)"}, + {"file": "main.handler", "ok": true, "output": "entrypoint 'main.handler' найден"} + ] +} +``` + +> `ok: false` в корне объекта означает что хотя бы один файл не прошёл проверку. +> `output` содержит вывод линтера — присутствует только при ошибке (для entrypoint — всегда). + +**Ошибки:** +| Код | Причина | +|-----|---------| +| 400 | Нет поля `archive`, нет поддерживаемых файлов (.py/.js/.rb/.php) в архиве | +| 413 | Архив > 100 KB или суммарный распакованный размер > 100 KB (zip bomb protection) | + +--- + +## TTL — Время жизни функции ★ + +Функция может быть создана с ограниченным временем жизни. После истечения TTL функция удаляется автоматически. + +**Формат:** число + суффикс: `m` (минуты), `h` (часы), `d` (дни). +**Примеры:** `15m`, `1h`, `2d`, `12h` + +```bash +curl -X POST .../functions \ + -H "X-Auth-Token: user@domain.com" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "temp-fn", + "language": "python", + "code": "def main(event, context): return \"hi\"", + "ttl": "1h" + }' +``` + +В ответе будет поле `expires_at` (формат RFC3339): +```json +{ + "name": "temp-fn", + "package": "temp-fn-pkg", + "httptrigger": "temp-fn-route", + "route": "/...", + "expires_at": "2026-05-06T14:00:00Z" +} +``` + +Невалидные значения TTL (`0d`, `-1h`, `99z`, `abc`) → **400**. + +--- + +## HTTP-коды — сводная таблица + +| Код | Значение | +|-----|---------| +| 200 | Успех (GET, DELETE, PUT) | +| 201 | Объект создан (POST /functions, POST /timetriggers) | +| 400 | Ошибка валидации параметров | +| 401 | Не авторизован (нет токена или < 6 символов) | +| 404 | Объект не найден (или чужой) | +| 405 | Неверный HTTP-метод | +| 409 | Конфликт (дубликат имени) | +| 413 | Тело слишком большое (код > 1 MB, архив > 100 KB) | +| 502 | Ошибка взаимодействия с Fission (router/executor недоступен) | + +**Формат ошибки:** +```json +{ "error": "описание ошибки" } +``` + +--- + +## Поддерживаемые языки + +| `language` | Расширение файла | Entrypoint по умолчанию | +|------------|-----------------|------------------------| +| `python` | `.py` | `main.main` | +| `nodejs` | `.js` | зависит от runtime | +| `go` | `.go` | зависит от runtime | +| `php` | `.php` | зависит от runtime | +| `ruby` | `.rb` | зависит от runtime | + +--- + +## Примеры сценариев + +### Быстрый старт (inline-код) +```bash +BASE="https://fission.kube5s.ru/console/api" +TOKEN="myuser@example.com" + +# Создать функцию +curl -X POST "$BASE/functions" \ + -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \ + -d '{"name":"hello","language":"python","code":"def main(event, context): return \"hello world\""}' + +# Вызвать +curl -X POST "$BASE/functions/hello/invoke" \ + -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" -d '{}' + +# Обновить код +curl -X PUT "$BASE/functions/hello/code" \ + -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \ + -d '{"code":"def main(event, context): return \"v2\""}' + +# Удалить +curl -X DELETE "$BASE/functions/hello" -H "X-Auth-Token: $TOKEN" +``` + +### Создать из архива напрямую +```bash +curl -X POST "$BASE/functions" \ + -H "X-Auth-Token: $TOKEN" \ + -F "name=my-fn" \ + -F "language=python" \ + -F "entrypoint=main.handler" \ + -F "archive=@my-fn.zip" +``` + +### Проверить архив перед деплоем +```bash +curl -X POST "$BASE/ai/lint-archive" \ + -H "X-Auth-Token: $TOKEN" \ + -F "archive=@my-fn.zip" \ + -F "entrypoint=main.handler" \ + -F "language=python" +``` + +### Создать временную функцию (исчезнет через 30 минут) +```bash +curl -X POST "$BASE/functions" \ + -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \ + -d '{"name":"temp-fn","language":"nodejs","code":"module.exports = async () => ({status:200,body:\"tmp\"})","ttl":"30m"}' +``` + +### Настроить расписание +```bash +# Вызывать my-fn каждые 5 минут +curl -X POST "$BASE/timetriggers" \ + -H "X-Auth-Token: $TOKEN" -H "Content-Type: application/json" \ + -d '{"name":"my-cron","functionName":"my-fn","cron":"*/5 * * * *"}' +``` diff --git a/doc/quick-ref.md b/doc/quick-ref.md new file mode 100644 index 00000000..13e373d8 --- /dev/null +++ b/doc/quick-ref.md @@ -0,0 +1,191 @@ +# Fission — Краткий справочник команд + +> Базовый URL: `https://fission.kube5s.ru/console/api` +> Токен передаётся через `X-Auth-Token: ` или `Authorization: Bearer ` + +```bash +BASE="https://fission.kube5s.ru/console/api" +T="X-Auth-Token: mylogin@example.com" # demo: любая строка ≥6 символов +``` + +--- + +## Стандартные операции + +### Функции + +```bash +# Создать функцию +curl -X POST "$BASE/functions" -H "$T" -H "Content-Type: application/json" \ + -d '{"name":"hello","language":"python","code":"def main(event, context): return \"hi\""}' + +# Список функций +curl "$BASE/functions" -H "$T" + +# Описание функции +curl "$BASE/functions/hello" -H "$T" + +# Вызвать функцию +curl -X POST "$BASE/functions/hello/invoke" -H "$T" \ + -H "Content-Type: application/json" -d '{}' + +# Обновить код +curl -X PUT "$BASE/functions/hello/code" -H "$T" -H "Content-Type: application/json" \ + -d '{"code":"def main(event, context): return \"v2\""}' + +# Удалить функцию +curl -X DELETE "$BASE/functions/hello" -H "$T" +``` + +**Языки:** `python`, `nodejs`, `go`, `php`, `ruby` + +**Правила имени:** строчные буквы, цифры, дефис; не начинается/не заканчивается дефисом; максимум 57 символов. + +--- + +### Environments + +```bash +# Список environments +curl "$BASE/environments" -H "$T" +``` + +--- + +### Packages + +```bash +# Список пакетов +curl "$BASE/packages" -H "$T" +``` + +--- + +### HTTP Triggers + +```bash +# Список HTTP triggers +curl "$BASE/httptriggers" -H "$T" +``` + +--- + +### Time Triggers (cron) + +```bash +# Создать cron +curl -X POST "$BASE/timetriggers" -H "$T" -H "Content-Type: application/json" \ + -d '{"name":"my-cron","functionName":"hello","cron":"*/5 * * * *"}' + +# Список +curl "$BASE/timetriggers" -H "$T" + +# Обновить +curl -X PUT "$BASE/timetriggers/my-cron" -H "$T" -H "Content-Type: application/json" \ + -d '{"cron":"0 * * * *"}' + +# Удалить +curl -X DELETE "$BASE/timetriggers/my-cron" -H "$T" +``` + +--- + +### Прямой вызов по route + +```bash +# Вызов без JSON-обёртки (чистый HTTP) +curl "https://fission.kube5s.ru/fn/" -H "$T" +``` + +--- + +## Наши расширения + +### Создание из zip-архива + +```bash +# Создать функцию из архива напрямую +curl -X POST "$BASE/functions" -H "$T" \ + -F "name=my-fn" -F "language=python" -F "entrypoint=main.handler" \ + -F "archive=@my-function.zip" + +# Обновить функцию новым архивом +curl -X PUT "$BASE/functions/my-fn/archive" -H "$T" \ + -F "archive=@my-function-v2.zip" +``` + +--- + +### TTL — самоуничтожающиеся функции + +```bash +# Функция исчезнет через 1 час +curl -X POST "$BASE/functions" -H "$T" -H "Content-Type: application/json" \ + -d '{"name":"temp","language":"nodejs","code":"module.exports=async()=>({status:200,body:\"ok\"})","ttl":"1h"}' +``` + +Форматы TTL: `15m`, `2h`, `1d`, `7d` + +--- + +### AI: проверить архив перед деплоем + +```bash +curl -X POST "$BASE/ai/lint-archive" -H "$T" \ + -F "archive=@my-fn.zip" \ + -F "language=python" \ + -F "entrypoint=main.handler" +``` + +Ответ: +```json +{ + "ok": true, + "results": [{"file": "main.py", "ok": true}] +} +``` + +Поддерживает: `.py`, `.js`, `.rb`, `.php` + +--- + +### Обновить только таймаут + +```bash +curl -X PUT "$BASE/functions/hello/timeout" -H "$T" -H "Content-Type: application/json" \ + -d '{"timeout": 120}' +``` + +--- + +### Статус namespace + +```bash +# Готовность namespace (stages: создан → RBAC → control-plane) +curl "$BASE/ns/status" -H "$T" +``` + +--- + +### Аутентификация / получить namespace + +```bash +curl -X POST "$BASE/auth" -H "Content-Type: application/json" \ + -d '{"token":"mylogin@example.com"}' +# → {"ok":true,"namespace":"fission-a3f9c1b2...","email":"..."} +``` + +--- + +## HTTP-коды + +| Код | Значение | +|-----|---------| +| 200 | OK | +| 201 | Создано | +| 400 | Ошибка валидации | +| 401 | Нет/невалидный токен | +| 404 | Не найдено (или чужое) | +| 409 | Уже существует | +| 413 | Слишком большой код/архив | +| 502 | Fission внутренняя ошибка |