# API Design Последнее обновление: 2026-03-18 ## Базовый URL ``` http://:9090/v1 ``` Локально: `http://localhost:9090/v1` В кластере: `http://sless-operator.sless.svc.cluster.local:9090/v1` Публично: `https://sless.kube5s.ru/v1/...` (через Ingress) **Реализованные эндпоинты:** ``` GET /v1/namespaces/{ns}/functions POST /v1/namespaces/{ns}/functions GET /v1/namespaces/{ns}/functions/{name} PUT /v1/namespaces/{ns}/functions/{name} DELETE /v1/namespaces/{ns}/functions/{name} POST /v1/namespaces/{ns}/functions/{name}/upload GET /v1/namespaces/{ns}/functions/{name}/source ← файлы кода из S3 tar.gz (JSON) GET /v1/namespaces/{ns}/functions/{name}/invocations GET /v1/namespaces/{ns}/triggers POST /v1/namespaces/{ns}/triggers GET /v1/namespaces/{ns}/triggers/{name} PATCH /v1/namespaces/{ns}/triggers/{name} ← {"enabled": bool} DELETE /v1/namespaces/{ns}/triggers/{name} POST /v1/namespaces/{ns}/jobs GET /v1/namespaces/{ns}/jobs/{name} DELETE /v1/namespaces/{ns}/jobs/{name} ``` **Глобальный сервис funcs (не оператор):** ``` GET https://sless.kube5s.ru/funcs/ ← plain text (курл) / HTML (браузер) GET https://sless.kube5s.ru/funcs?token= ← редирект по namespace GET https://sless.kube5s.ru/funcs//source/ ← прокси к GET /source PATCH https://sless.kube5s.ru/funcs//triggers/ ← прокси к PATCH /triggers GET https://sless.kube5s.ru/health ← liveness probe ``` ## Аутентификация ``` Authorization: Bearer ``` Токен — JWT от `auth-api`. Middleware в операторе: 1. Извлекает `sub` из payload (без проверки подписи — доверяет Ingress) 2. Вычисляет namespace: `SHA256(sub)[:8]` hex → `sless-{16 hex символов}` 3. Проверяет что запрошенный `{namespace}` совпадает с вычисленным ## Ресурсы ### Functions | Метод | Путь | Описание | |-------|------|----------| | GET | /functions | Список функций | | POST | /functions | Создать функцию | | GET | /functions/{id} | Получить функцию | | PUT | /functions/{id} | Обновить функцию | | DELETE | /functions/{id} | Удалить функцию | ### Versions (код функции) | Метод | Путь | Описание | |-------|------|----------| | GET | /functions/{id}/versions | Список версий | | POST | /functions/{id}/versions | Загрузить новый код (multipart zip) | | GET | /functions/{id}/versions/{ver} | Получить версию | | POST | /functions/{id}/versions/{ver}/activate | Активировать версию | ### Triggers | Метод | Путь | Описание | |-------|------|----------| | GET | /functions/{id}/triggers | Список триггеров | | POST | /functions/{id}/triggers | Создать триггер (HTTP/Cron) | | DELETE | /functions/{id}/triggers/{tid} | Удалить триггер | ### Invocations (вызов и логи) | Метод | Путь | Описание | |-------|------|----------| | POST | /functions/{id}/invoke | Синхронный вызов | | GET | /functions/{id}/invocations | История вызовов | | GET | /functions/{id}/invocations/{iid} | Детали вызова + логи | ## Upload endpoint ``` POST /v1/namespaces/{namespace}/functions/{name}/upload Content-Type: multipart/form-data Authorization: Bearer field: code = ``` Процесс: 1. Принимает zip (max 32MB) 2. Распаковывает zip 3. Генерирует `Dockerfile` (`FROM naeel/sless-runtime-{runtime}:latest\nCOPY . /app/function/`) 4. Перепаковывает в `tar.gz` (kaniko требует tar format) 5. Загружает в S3: `contexts/{ns}/{name}/{timestamp}.tar.gz` 6. Обновляет `fn.Spec.S3Key` → контроллер видит изменение и запускает kaniko Job Ответ `200 OK`: ```json {"message": "build queued", "phase": "Pending", "s3_key": "contexts/..."} ``` ## Поддерживаемые runtime (v1) - `python3.11` — реализован и протестирован - `nodejs20` — реализован и протестирован - `go1.23` — реализован ## Модель Function ```json { "id": "fn-uuid", "name": "my-function", "description": "...", "runtime": "python3.11", "entrypoint": "handler.handle", "memory_mb": 128, "timeout_sec": 30, "env_vars": {"KEY": "value"}, "active_version": "1", "status": "active", "created_at": "...", "updated_at": "..." } ``` ## Модель Trigger ```json { "id": "tr-uuid", "type": "http", "url": "https://sless.api.ngcloud.ru/invoke/fn-uuid", "created_at": "..." } ``` ```json { "id": "tr-uuid", "type": "cron", "schedule": "0 * * * *", "created_at": "..." } ```