5.7 KiB
fission-console v0.6.9 — Отчёт о тестировании
Дата: 2026-04-19
Версия: naeel/fission-console:v0.6.9
Ветка: feat/namespace-isolation
Что реализовано
Managed serverless functions service поверх Fission + Kubernetes. Go-бэкенд (консоль), REST API, k8s dynamic client. Пользователи изолированы по namespace (fission-{SHA256(sub)[:16]}).
Поддерживаемые среды выполнения:
- Node.js 22 (ESM,
module.exports/export default/ анонимная функция) - Python 3.11 (Flask,
def main():без аргументов)
Auth: JWT или TEST_MODE (X-Test-Sub: user@domain → SHA256 → namespace)
Баги исправлены в этой сессии (v0.6.8 → v0.6.9)
| # | Баг | Симптом | Фикс |
|---|---|---|---|
| 1 | Route collision | Два разных пользователя создавали функцию с одинаковым маршрутом | Префикс последних 12 символов namespace: /{ns[-12:]}/{fn-name} |
| 2 | INVOKE несуществующей → 200 | Вызов несуществующей функции возвращал HTTP 200 без ошибки | GET из k8s перед invoke, IsNotFound → 404 |
| 3 | DELETE несуществующей → 200 | Удаление несуществующей функции возвращало deleted:true |
Инвертирован if err == nil → if err != nil, 404 |
| 4 | Orphan package при невалидном TTL | parseTTL вызывался после создания пакета — при ошибке оставался мусорный package в k8s |
parseTTL перемещён до создания k8s-ресурсов |
Результаты тестирования
PASS=41 FAIL=0
Покрытие (16 блоков):
| Блок | Что проверяется |
|---|---|
| A | Регресс v0.6.8: INVOKE/DELETE несуществующей → 404, route isolation |
| B | Валидация входных данных → 400 (missing name/code/language, пробелы) |
| C | Дублирующее создание → конфликт |
| D | UPDATE кода + повторный invoke возвращает новый код |
| E | GET функции (200/404) |
| F | LIST изоляция — пользователь видит только свои функции |
| G | Namespace изоляция DELETE — нельзя удалить чужую функцию |
| H | Python def main(): (без аргументов) → invoke 200 |
| I | Node.js: module.exports, export.handler, export default |
| J | TTL: expires_at создаётся / не создаётся / невалидный → 400 |
| K | ctx.request.url доступен внутри функции |
| L | Stress: 10 параллельных invoke → 10/10 OK |
| M | LIST пустого namespace → [] |
| N | DELETE полная цепочка: Function + Package + HTTPTrigger удаляются |
| O | Запрос без auth-заголовка → 401 |
| P | POST /auth: без токена → 400, невалидный токен → 401 |
Архитектурные решения — вопросы для ревью
1. Namespace on-demand
Namespace создаётся при первом обращении пользователя. Нет отдельного registration flow.
Вопрос: правильно ли это? Нет ли рисков при параллельном первом запросе от одного пользователя (race condition на создание namespace)?
2. Сборка функций
Код пользователя пакуется в zip в памяти и передаётся в Fission Package как literal (base64). При обновлении создаётся новый Package, старый удаляется.
Вопрос: нет версионирования. Стоит ли хранить историю версий?
3. Reaper
Горутина раз в 30 секунд проверяет expires-at аннотацию и удаляет протухшие функции вместе с Package и HTTPTrigger. Работает без персистентного стейта — при рестарте пода начинает заново со следующего цикла.
Вопрос: надёжно ли это? Что если под упал в момент удаления — останется ли мусор?
4. Python env и сигнатура main()
Официальный ghcr.io/fission/python-env вызывает main(*args) через Flask. Реально аргументы не передаются (только через route params). При def main(): работает. При def main(ctx): — TypeError: main() missing 1 required positional argument.
Вопрос: патчить env или задокументировать ограничение?
5. Валидация имени функции
Имя с пробелами возвращает 502 (k8s отклоняет по RFC 1123), а не 400 (явная валидация в API).
Вопрос: стоит ли добавить regex-валидацию имени на уровне API до обращения в k8s?
Что ещё не сделано
- Версионирование функций
- Явная валидация имени функции (RFC 1123) в API
- Метрики / биллинг
- Документация API (OpenAPI spec)
- Merge в master