27 KiB
27 KiB
Progress Log
2026-04-14
План перед работой
- Зафиксировать, что REST
/v2/*недоступен в текущем кластере Fission v1.22.1 и MVP идет через Kubernetes CRD API. - Реализовать первый рабочий Terraform ресурс
fission_environment. - Добавить минимальный CRUD в клиент для CRD
environments.fission.io. - Проверить сборку
go build ./....
Факт выполнения
- Обновлен план в
doc/CODEX_PLAN.md: путь реализации переведен на CRD API. - Создан каркас провайдера и заготовки ресурсов.
- Реализован рабочий
fission_environment:- schema (name, image, version, poolsize, namespace, id, uid)
- Configure() с получением клиента из provider
- Create/Read/Update/Delete через Kubernetes CRD
environments.fission.io
- В
internal/client/client.goдобавлены методы:- CreateEnvironment / GetEnvironment / UpdateEnvironment / DeleteEnvironment
- IsNotFound для обработки удаления/дрейфа state
- Проверка
go build ./...проходит успешно.
Следующий шаг
- Реализовать
fission_package(zip/base64 -> spec.source.literal) через CRDpackages.fission.io.
Обновление этапа (fission_package)
- Реализован CRUD в
internal/client/client.goдляpackages.fission.io:CreatePackageGetPackageUpdatePackageDeletePackage
- Реализован ресурс
fission_packageвinternal/resources/package_resource.go:- schema:
name,environment,source_dir,code_path,code_hash,build_command,namespace, computedid,uid,build_status,build_log - валидация источника кода: задан ровно один из
source_dirилиcode_path - упаковка
source_dirв zip и кодирование base64 вspec.source.literal - Create/Read/Update/Delete через Kubernetes CRD API
- schema:
- Проверка сборки:
go build ./...успешно.
Следующий шаг
- Реализовать
fission_functionчерез CRDfunctions.fission.io.
Обновление этапа (fission_function)
- Реализован CRUD в
internal/client/client.goдляfunctions.fission.io:CreateFunctionGetFunctionUpdateFunctionDeleteFunction
- Реализован ресурс
fission_functionвinternal/resources/function_resource.go:- schema:
name,environment,package_name,entrypoint,namespace, computedid,uid - Configure/Create/Read/Update/Delete
- маппинг в CRD
Function(spec.environment,spec.package.packageref,spec.package.functionName)
- schema:
- Проверка сборки:
go build ./...успешно.
Следующий шаг
- Реализовать
fission_http_triggerчерез CRDhttptriggers.fission.io.
Обновление этапа (fission_http_trigger)
- Реализован CRUD в
internal/client/client.goдляhttptriggers.fission.io:CreateHTTPTriggerGetHTTPTriggerUpdateHTTPTriggerDeleteHTTPTrigger
- Реализован ресурс
fission_http_triggerвinternal/resources/http_trigger_resource.go:- schema:
name,function,url,methods,create_ingress,host,namespace, computedid,uid - Configure/Create/Read/Update/Delete
- маппинг в CRD
HTTPTrigger(spec.relativeurl,spec.methods,spec.functionref,spec.createingress)
- schema:
- Проверка сборки:
go build ./...успешно.
Следующий шаг
- Добавить пример
examples/hello-python/main.tfи выполнить smoke Terraform apply.
Обновление этапа (пример Terraform)
- Создан пример
examples/hello-python/main.tfс использованием ресурсов:fission_environmentfission_packagefission_functionfission_http_trigger
- Добавлен код функции
examples/hello-python/code/main.py.
Следующий шаг
- Подготовить локальную установку бинарника провайдера для
terraform initи выполнить smoketerraform apply.
Обновление этапа (smoke Terraform apply)
- Собран бинарник провайдера и подключен через Terraform
dev_overrides. - Прогнан
terraform planдляexamples/hello-python: план успешен, 4 ресурса к созданию. - Прогнан
terraform applyи выполнена функциональная проверка.
Исправленные баги по факту smoke:
fission_package: после Create computed-поля (build_status,build_log) могли оставатьсяunknown.- Исправлено формирование state в
unstructuredToPackageModel.
- Исправлено формирование state в
fission_function: CRD требовал обязательныйspec.InvokeStrategy.- Добавлен
InvokeStrategyв payload функции.
- Добавлен
fission_http_trigger: несогласованность state (create_ingressnull -> false).- В schema добавлены
Computed+Default(false)дляcreate_ingress. - Для
methodsдобавленComputed.
- В schema добавлены
Дополнительно:
- Для текущего python MVP
fission_packageпереведен наspec.deployment.literal(как у рабочего CLI-пакета). - Проверка endpoint после apply:
GET /tf-hello->hello from fission via terraform.
Следующий шаг
- Добавить README по запуску dev override и оговорить ограничения текущего MVP (
source_dirожидаетmain.py).
Обновление этапа (README)
- Добавлен
README.mdв корень репозитория. - Описаны:
- список реализованных ресурсов MVP
- запуск через Terraform dev override
- текущие ограничения MVP
Обновление этапа (import + тесты)
- Добавлена поддержка
terraform importдля всех 4 ресурсов:fission_environmentfission_packagefission_functionfission_http_trigger
- Формат import ID:
namespace/name. - Добавлены unit-тесты в
terraform/provider/internal/resources/*_test.go:- парсинг import ID
- конвертация model <-> unstructured
- валидация package source
- базовая проверка HTTP trigger round-trip
- Прогон валидации:
go test ./...— успешно- smoke
terraform plan/apply— успешно - endpoint
GET /tf-hello—hello from fission via terraform
Следующий шаг
- Добавить acceptance-тесты с опциональным запуском по env-флагу.
Обновление этапа (acceptance тест)
- Добавлен acceptance-тест
terraform/provider/internal/client/client_acceptance_test.go. - Тест выполняет живой CRUD в кластере для цепочки:
- Environment -> Package -> Function -> HTTPTrigger
- Запуск теста:
ACCEPTANCE_TEST=1 KUBECONFIG=/home/naeel/.kube/config go test ./internal/client -run TestAcceptanceFissionCRUD -v
- Результат: PASS.
Следующий шаг
- Расширить acceptance-тест проверкой реального HTTP-вызова функции через ingress.
Обновление этапа (много функций + суровая нагрузка)
- Добавлен
examples/stress-suite:- функции:
fast,cpu,json - маршруты:
/stress/fast,/stress/cpu,/stress/json - Terraform-конфиг на 10 ресурсов (env + 3 package + 3 function + 3 trigger)
- функции:
- Добавлен скрипт
examples/stress-suite/scripts/load_test.shдля параллельной нагрузки. - Реальный прогон после донастройки:
900запросов на endpoint90параллелизм- итог:
100%success на всех трех endpoint-ах.
Следующий шаг
- Добавить в acceptance-тест проверку HTTP latency/perf budget и порогов SLO.
Обновление этапа (JS/Go source support)
- В
fission_packageрасширена поддержкаsource_dir:main.pymain.jsmain.go
- Добавлены unit-тесты на выбор JS/Go исходников в
package_resource_test.go. - Прогон
go test ./...— успешно.
Следующий шаг
- Добавить отдельные Terraform примеры для Node.js и Go функций.
2026-04-15
Fission Console — Web UI для управления функциями
Ветка: feat/console
Реализовано (14 апреля, вечер → 15 апреля, утро)
Backend (console/main.go):
- Go HTTP-сервер с embedded UI
- CRUD API для Fission CRD через dynamic k8s client:
POST /api/functions— создание (Package + Function + HTTPTrigger атомарно с rollback)GET /api/functions— список всехGET /api/functions/{name}— детали (с декодированным кодом, route, methods)PUT /api/functions/{name}/code— обновление кодаPOST /api/functions/{name}/invoke— вызов функции через роутерDELETE /api/functions/{name}— удаление (trigger + function + package)
- Двойная маршрутизация:
/api/*и/console/api/*(для работы через ingress/console/) - CORS middleware, request logging
UI (console/ui/index.html):
- SPA-дашборд с карточками (environments, packages, functions, httptriggers, timetriggers)
- Таблица функций с кнопками Edit/Invoke/Delete
- Модал Create: выбор environment, ввод кода, route, methods
- Модал Edit Code: редактирование и сохранение
- Модал Invoke: отправка запроса, отображение статуса/latency/response
- Модал Delete: подтверждение
- Динамический
API_BASEдля работы как с/так и с/console/prefix
Тесты (console/main_test.go):
- 5 unit-тестов:
TestNormalizeMethods— нормализация HTTP-методовTestCreateFunctionValidation— валидация обязательных полейTestCreateFunctionSuccessAndGetDetails— полный CRUD flow + Get с декодированным кодомTestUpdateFunctionCode— обновление кода в packageTestInvokeFunctionWithJWTAuth— invoke с mock-роутером, проверка JWT auth flow
- Используется
dynamicfake.NewSimpleDynamicClientWithCustomListKinds
Docker (console/Dockerfile):
- Multi-stage:
golang:1.26-alpine→alpine:3.20 - Бинарник ~15MB
K8s deployment (console/deploy/console.yaml):
- ServiceAccount
fission-console - ClusterRole с доступом к fission.io CRD (get/list/create/update/patch/delete)
- ClusterRoleBinding
- Deployment (1 replica, port 8090, health probes, resource limits)
- Service (ClusterIP:8090)
- Ingress (fission.kube5s.ru/console, nginx, TLS)
Invoke auth — проблема и решение
Проблема: invoke через console возвращал 401 от Fission router.
Исследование:
- Попробовал SA token из пода →
key is of invalid type(K8s SA = RS256, router ожидает HS256) - Прочитал feature-config:
auth.enabled: true, endpoint/auth/login, JWT expiry 120s - Нашёл credentials в секрете
router: username=admin, password=..., jwtSigningKey=... - Протестировал:
POST /auth/login→ получил JWT → invoke с Bearer JWT → 200 OK
Решение: console при invoke делает POST /auth/login к роутеру, получает JWT, кеширует на 100s.
Баги по пути:
- Router возвращает 201 Created (не 200) на login — код проверял строго 200 → добавил
|| 201 - Кешированный Docker-образ: пересобрал тот же тег v0.2.0, нод использовал старый → перешёл на v0.2.2
Env переменные для auth:
FISSION_AUTH_USERNAME→ secretKeyRef изrouter.usernameFISSION_AUTH_PASSWORD→ secretKeyRef изrouter.password
E2E результат (все через ingress https://fission.kube5s.ru/console/)
| Операция | Результат |
|---|---|
| health | 200 ok |
| create | 201 Created (function + package + httptrigger) |
| get | 200 (code, route, methods, environment) |
| update code | 200 |
| invoke | 200, response_raw = ответ функции, latency_ms = 138 |
| delete | 200 (trigger + function + package очищены) |
Коммиты
6731e89— feat: deliver fission console UI, k8s deploy, and tests8920ba1— fix: invoke auth via Fission router JWT login
Docker Hub: naeel/fission-console:v0.2.2
Правила репозитория
Создан .github/copilot-instructions.md с правилами:
Обновление этапа (UI invoke stability: JS)
- Проведена диагностика JS invoke через реальный UI-путь (
/console/api/functions/{name}/invoke) и роутер/экзекьютор логи. - Найдена корневая причина JS-таймаутов:
- для
node-envиспользуетсяv2/specialize - при
functionName=mainruntime пытался загрузить/userfunc/deployarchive/main - при plain literal
deployarchiveявляется файлом, не директорией - после specialize без корректного контракта запросы зависали и упирались в router roundtripper timeout.
- для
- Для
nodejs-accзафиксирован runtime image:ghcr.io/fission/node-env:1.32.5. - Для JS-функций выровнен контракт runtime:
spec.package.functionNameвыставлен в пустой entrypoint ("") для default export- код приведен к формату ответа Node runtime:
return { status: 200, body: "..." } - для основных JS-маршрутов включены методы
GET+POST.
- Подтверждена работоспособность через console invoke:
fn-js-acc->status=200,response_raw=hello-js-okfn-js-direct->status=200,response_raw=hello-js-ok- тестовая матрица
jsm1..jsm4->status=200.
Статус после фикса
- Python invoke: работает.
- JS invoke: работает по UI-пути и по прямому GET роутов.
- Go invoke (
fn-go-acc): остается отдельной runtime-проблемой (вне JS-фикса). - Маппинг путей (локально ~/remote_dev/ = ВМ ~/terra/)
- Редактирование файлов — разрешено локально
- Команды — ИСКЛЮЧИТЕЛЬНО через SSH (VPN-конфликты)
Следующий шаг
- UI: автоматическое обновление дашборда после create/delete
- Рассмотреть добавление логов функций (kubectl logs)
- Рассмотреть добавление time triggers в UI
2026-04-15 (дополнение) — Fix по результатам баг-репорта
Что исправлено в Terraform provider
fission_package: добавленModifyPlan, который автоматически пересчитываетcode_hashпо локальному коду (source_dir/code_path).fission_package: добавлена валидация существованияenvironmentдо создания/обновления package.fission_function: добавлена валидация существованияenvironmentиpackageдо create/update.fission_function: добавлена pre-flight валидацияentrypointдля Python-исходника (main.funcдолжен существовать какdef func().- Добавлены unit-тесты на новый функционал (
code_hash, entrypoint validation).
Проверка на живом кластере
- После изменения
examples/hello-python/code/main.pyterraform planтеперь показываетfission_package.hello will be updated in-placeс изменениемcode_hash. - Конфигурация с несуществующим
environmentтеперь падает на этапе apply с ошибкой валидации. - Конфигурация с неверным
entrypointтеперь падает на этапе apply с ошибкой валидации.
Ограничения
- Runtime-проблемы Fission (зависания на cold start/таймауты выполнения) в этом изменении не трогались: исправлен только provider-слой валидации и обнаружения изменений.
2026-04-15 (дополнение) — Fix отображения кода в Console UI
Проблема
- В модальном окне редактирования функции (
Edit Code) для некоторых пакетов отображались байты ZIP (PK...) вместо исходного кода.
Причина
GET /console/api/functions/{name}декодировалspec.deployment.literalтолько из base64, но не обрабатывал архивированный payload.
Исправление
- В
console/main.goдобавлено декодированиеliteralс поддержкой ZIP:- если payload plain text/utf-8 -> отдаётся как есть
- если payload ZIP -> извлекается
main.py/main.js/main.go(или первый utf-8 файл)
- Обновлён deployment image:
naeel/fission-console:v0.2.4.
Проверка
GET /console/api/functions/fn-go-accтеперь возвращает читаемый Go-код, безPK...сигнатур.
2026-04-15 (дополнение) — Полный пользовательский прогон UI и invoke-fix
Что проверено как пользовательский сценарий
- Прогнан массовый invoke через UI API (
POST /console/api/functions/{name}/invoke) для всех функций в списке. - Итого:
31функций, из них25успешно отработали,6вернули 502/timeout (ожидаемо проблемные/сломанные кейсы). - Проверен полный edit flow через UI API на рабочей функции:
GET function->PUT /code->POST /invoke->PUT /code(restore) ->POST /invoke.
Найденный UI-баг и исправление
- Баг: после обновления кода через UI следующий invoke мог отдавать старую специализацию/кэш.
- Причина: обновлялся только
Package, но не обновлялсяFunction.spec.package.packageref.resourceversion. - Фикс в
console/main.go:- после
package updateчитается новыйpackage.resourceVersion - выполняется update
Functionс новымpackageref.resourceversion - invoke сразу использует новую (или восстановленную) версию кода.
- после
Проверка фикса
- После update через UI invoke возвращает новый ответ.
- После restore через UI invoke возвращает исходный ответ (без зависания старого кэша).
Статус fn-go-acc
fn-go-accпродолжает падать не из-за UI, а из-за runtime specialization на стороне Fission.- Подтверждено логами
router/executor:GetServiceForFunction ... context canceledи постоянными readiness-fail у poolmgr pod-овgo-acc.
2026-04-15 (дополнение) — Финальный фикс fn-go-acc
Симптом и root cause
fn-go-accстабильно timeout'ился на invoke.- Изначальный пакет содержал
main.goкакdeployment.literal, из-за чего go-runtime пытался грузить текст как plugin:plugin.Open("/userfunc/deployarchive/main.go"): invalid ELF header.
Что сделано
- Пересобран deploy-артефакт как Go plugin (
main.so) и упакован вdeploy.zip. - Важно: сборка выполнена в том же образе, что у Fission environment builder:
ghcr.io/fission/go-builder(Go 1.25.6), чтобы избежать несовместимости plugin ABI.
- Функция обновлена через Fission CLI:
fission function update -n default --name fn-go-acc --env go-acc --entrypoint Handler --deployarchive /tmp/fn-go-acc-fix2/deploy.zip -f.
Результат проверки
/go-accчерез router с JWT:hello-go-ok,HTTP 200.- Executor логи: specialization проходит успешно (
specialized pod,added function service), безinvalid ELF.
Контрольный smoke после фикса
/auto/ok->HTTP 200/js-acc->HTTP 200/js-direct->HTTP 200/go-acc->HTTP 200
2026-04-15 (дополнение) — Edit Code для fn-go-acc снова показывает исходник
Проблема
- В
Edit Codeдляfn-go-accполеcodeбыло пустым. - Причина: после
--deployarchiveпакетpkg-go-accперешел наspec.deployment.type=url, а в console backend чтение кода шло только изspec.deployment.literal.
Исправление
- В
console/main.goдобавлен fallback-поиск исходника:spec.source.literalspec.deployment.literalspec.source.urlspec.deployment.url
- Добавлена загрузка архива по URL и извлечение исходника из zip (если есть текстовые файлы).
- Добавлен unit-тест
TestGetFunctionUsesSourceLiteralWhenDeploymentLiteralMissing. - Собран и выкачен образ
naeel/fission-console:v0.2.6, деплой обновлен.
Дополнительно по данным в кластере
- Для
fn-go-accобновленsourcearchive(main.go), чтобыpkg-go-acc.spec.source.literalсодержал исходник и был доступен в Edit Code.
Проверка
GET /console/api/functions/fn-go-accвозвращает непустойcode(Go source)./go-accпродолжает отвечатьhello-go-ok,HTTP 200.
2026-04-15 (дополнение) — TLS в console, бренд NUBES, проверка tf-neg-syntax-fn
TLS: фактический статус
http://fission.kube5s.ru/console/->308 Permanent Redirectнаhttps://...https://fission.kube5s.ru/console/->200- Ingress
fission-consoleнастроен с:nginx.ingress.kubernetes.io/force-ssl-redirect: "true"tls.secretName: fission-tlscert-manager.io/cluster-issuer: letsencrypt-prod
UI оформление (NUBES)
- В
console/ui/index.htmlдобавлены:- favicon (inline SVG)
- брендинг в navbar: mark + wordmark
NUBES/FISSION CONSOLE - обновлен
<title>наNUBES Fission Console
- Выкат:
naeel/fission-console:v0.2.9.
Invoke tf-neg-syntax-fn — проверка
- Подтверждено, что у функции синтаксически невалидный код (
def main(: ...). - Console invoke теперь возвращает fail-fast ошибку (не «молчание»):
{"error":"invoke \"tf-neg-syntax-fn\" timeout after 20s: function specialization likely failed (for example, syntax error)"}
- Причина на кластере: specialization падает в runtime с
500, executor делает ретраи.
2026-04-15 (дополнение) — Лечение "красного" HTTPS
Root cause
- На одном host
fission.kube5s.ruбыло два ingress:fission-consoleс TLSfission-routerбез TLS
- Из-за смешанной host-конфигурации TLS мог работать нестабильно/давать красный индикатор в браузере.
Fix
- Пропатчен
fission/fission-router:- добавлен
spec.tlsсsecretName: fission-tls - добавлена аннотация
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
- добавлен
Проверка
http://fission.kube5s.ru/neg/syntax->308redirect на HTTPS- Сертификат endpoint: Let's Encrypt R13, CN/SAN
fission.kube5s.ru, валиден https://fission.kube5s.ru/console/->HTTP 200
2026-04-15 (дополнение) — Строгая очистка: оставлены только рабочие и с видимым кодом
Требование
- Убрать всё лишнее и оставить только функции, которые одновременно:
- имеют непустой
codeвGET /console/api/functions/{name} - успешно проходят
POST /console/api/functions/{name}/invokeсоstatus=200
- имеют непустой
Что сделано
- Выполнена финальная очистка функций по whitelist.
- После очистки дополнительно проверены все оставшиеся функции через Console API (code + invoke).
- Исправлена ошибка в служебном cleanup-скрипте (битый jsonpath с
{n}), из-за которой падала пост-обработка orphan-ресурсов.
Итоговый набор
auth-test2fn-js-directfn-js-acchellotf-auto-ok-fntf-stress-fast-fn
Финальное состояние кластера
functions=6httptriggers=6packages=6
Финальная валидация
- Для каждой из 6 функций:
code=OK,invoke=OK.