docs: record strict cleanup to 6 verified functions

This commit is contained in:
Naeel
2026-04-15 14:43:58 +03:00
parent ba50d18f8f
commit 8ac8428a76
2 changed files with 361 additions and 0 deletions
+140
View File
@@ -258,6 +258,30 @@
#### Правила репозитория #### Правила репозитория
Создан `.github/copilot-instructions.md` с правилами: Создан `.github/copilot-instructions.md` с правилами:
### Обновление этапа (UI invoke stability: JS)
- Проведена диагностика JS invoke через реальный UI-путь (`/console/api/functions/{name}/invoke`) и роутер/экзекьютор логи.
- Найдена корневая причина JS-таймаутов:
- для `node-env` используется `v2/specialize`
- при `functionName=main` runtime пытался загрузить `/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-ok`
- `fn-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/) - Маппинг путей (локально ~/remote_dev/ = ВМ ~/terra/)
- Редактирование файлов — разрешено локально - Редактирование файлов — разрешено локально
- Команды — ИСКЛЮЧИТЕЛЬНО через SSH (VPN-конфликты) - Команды — ИСКЛЮЧИТЕЛЬНО через SSH (VPN-конфликты)
@@ -326,3 +350,119 @@
### Статус `fn-go-acc` ### Статус `fn-go-acc`
- `fn-go-acc` продолжает падать не из-за UI, а из-за runtime specialization на стороне Fission. - `fn-go-acc` продолжает падать не из-за UI, а из-за runtime specialization на стороне Fission.
- Подтверждено логами `router/executor`: `GetServiceForFunction ... context canceled` и постоянными readiness-fail у poolmgr pod-ов `go-acc`. - Подтверждено логами `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.literal`
- `spec.deployment.literal`
- `spec.source.url`
- `spec.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-tls`
- `cert-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` с TLS
- `fission-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` -> `308` redirect на 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-test2`
- `fn-js-direct`
- `fn-js-acc`
- `hello`
- `tf-auto-ok-fn`
- `tf-stress-fast-fn`
### Финальное состояние кластера
- `functions=6`
- `httptriggers=6`
- `packages=6`
### Финальная валидация
- Для каждой из 6 функций: `code=OK`, `invoke=OK`.
+221
View File
@@ -147,3 +147,224 @@ User → POST /console/api/functions/NAME/invoke
Причина: VPN может быть активен локально, вызывая сбои при прямом выполнении команд. Причина: VPN может быть активен локально, вызывая сбои при прямом выполнении команд.
Монтирование sshfs делает локальное редактирование файлов эквивалентным редактированию на ВМ. Монтирование sshfs делает локальное редактирование файлов эквивалентным редактированию на ВМ.
---
## Сессия: JS invoke timeouts в UI (root cause + fix)
### Симптом
- Все JS invoke через UI (`/console/api/functions/{name}/invoke`) падали по timeout.
- В router логах: `roundtripper timeout (60s)`/`error sending request to function`.
- В executor логах specialization для node окружения могла проходить, но ответ функции не возвращался.
### Ключевые находки
1. Node runtime работал через `POST /v2/specialize`.
2. При `functionName=main` runtime строил путь загрузки как:
- `/userfunc/deployarchive/main`
3. В реальном поде `/userfunc/deployarchive` был **файлом** (literal payload), а не директорией.
4. После перевода на пустой entrypoint (`functionName=""`) specialization стала успешной (`202`, `user code loaded`),
но запросы всё равно зависали.
5. Прямая проверка контейнера показала второй контрактный нюанс node runtime:
- пользовательская функция должна возвращать объект формата
`{ status, body, headers? }`
- возврат простой строки приводил к зависанию ответа (callback не отправлял HTTP response).
### Принятые изменения
- `nodejs-acc` закреплен на `ghcr.io/fission/node-env:1.32.5`.
- Для JS функций (`fn-js-acc`, `fn-js-direct`, тестовые `jsm1..jsm4`):
- выставлен пустой entrypoint (`functionName=""`)
- код приведен к контракту Node runtime:
- `module.exports = async function(context) { return { status: 200, body: "..." }; }`
- Для основных JS trigger включены методы `GET` и `POST`.
### Проверка
- UI invoke:
- `fn-js-acc` -> `status=200`, `response_raw=hello-js-ok`
- `fn-js-direct` -> `status=200`, `response_raw=hello-js-ok`
- Прямые GET через роутер:
- `/js-acc` -> 200
- `/js-direct` -> 200
- Тестовые `jsm1..jsm4` после унификации кода -> 200 через UI invoke.
### Вывод
Проблема была не в UI-рендеринге и не в одном конкретном trigger, а в несовпадении контракта Node runtime:
- entrypoint/path specialization
- shape возвращаемого значения функции.
---
## Сессия: Финальный fix `fn-go-acc` (Go runtime specialization)
### Симптом
- `fn-go-acc` выдавал timeout на invoke через console/router.
### Диагностика
1. На исходной конфигурации в executor логах:
- `plugin.Open("/userfunc/deployarchive/main.go"): invalid ELF header`.
2. Это означало, что runtime ожидал plugin-артефакт, но в package deployment лежал исходник `main.go`.
3. После первой попытки собрать plugin локальным `go1.26.1` ошибка `invalid ELF` ушла, но появился новый фейл specialization:
- `Post "http://127.0.0.1:8888/v2/specialize": EOF`.
4. Вывод: plugin собран несовместимой версией Go относительно runtime.
### Решение
- Сборка plugin выполнена в `ghcr.io/fission/go-builder` (Go 1.25.6), то есть тем же toolchain, что у Fission environment builder:
- `GO111MODULE=off /usr/local/go/bin/go build -buildmode=plugin -o main.so ./main.go`
- упаковка `main.so` в `deploy.zip`.
- Обновление функции через 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` и без `EOF`.
### Контрольная матрица маршрутов
- `/auto/ok` -> 200
- `/js-acc` -> 200
- `/js-direct` -> 200
- `/go-acc` -> 200
### Практический вывод
Для go-env в этом кластере критично соблюдать контракт runtime:
1. deploy-пакет должен содержать именно plugin (`.so`), а не исходник.
2. plugin должен быть собран совместимой версией Go (через `ghcr.io/fission/go-builder`).
---
## Сессия: `Edit Code` для `fn-go-acc` пустой
### Симптом
- В UI (`GET /console/api/functions/fn-go-acc`) поле `code` было пустым.
### Почему так произошло
- После фикса runtime функция была переведена на deploy-архив plugin (`main.so`).
- Package имел вид:
- `spec.deployment.type=url`
- `spec.deployment.url=...`
- без `spec.deployment.literal`
- Backend в `handleGetFunction` извлекал код только из `spec.deployment.literal`, поэтому для URL-пакета отдавал пустую строку.
### Что изменено
- В backend добавлен `extractPackageSourceCode(...)` с fallback-приоритетом:
1. `spec.source.literal`
2. `spec.deployment.literal`
3. `spec.source.url`
4. `spec.deployment.url`
- Добавлена загрузка URL-архива через `fetchPackageArchive(...)` и декодирование через `decodeArchiveBytesToSource(...)`.
- Обновлен unit-тестами сценарий, где `deployment.literal` отсутствует, но есть `source.literal`.
### Операционные шаги
- Собран и задеплоен `naeel/fission-console:v0.2.6`.
- Для текущей `fn-go-acc` дополнительно обновлен `sourcearchive` (`main.go`), чтобы исходник гарантированно отображался в Edit Code.
### Результат
- `GET /console/api/functions/fn-go-acc` теперь возвращает непустой Go source в `code`.
- Вызов `/go-acc` остается рабочим (`hello-go-ok`, HTTP 200).
---
## Сессия: Проверка TLS + branding NUBES + верификация `tf-neg-syntax-fn`
### TLS
- Проверен доступ к console:
- `http://.../console/` -> `308` redirect на HTTPS
- `https://.../console/` -> `200`
- Ingress конфиг содержит корректный TLS блок и принудительный SSL redirect.
- Вывод: endpoint защищен TLS, «незащищенного HTTP-доступа» нет.
### Брендинг NUBES
- В `console/ui/index.html` добавлены:
- `<title>NUBES Fission Console</title>`
- favicon (inline SVG)
- navbar brand block с `NUBES` / `FISSION CONSOLE`.
- Обновлен образ до `naeel/fission-console:v0.2.9`.
### `tf-neg-syntax-fn` — почему timeout вместо прямого SyntaxError
- Функция содержит заведомо битый Python (`def main(:`), confirmed через `GET /console/api/functions/tf-neg-syntax-fn`.
- На runtime это роняет specialization (`500`), после чего executor ретраит.
- Поэтому router/console не получает «чистый traceback» сразу из runtime API и видит timeout/ошибку specialization.
- Для UX введен fail-fast и явная ошибка в console invoke:
- `timeout after 20s: function specialization likely failed (for example, syntax error)`.
---
## Сессия: "Не защищено красным" — экстренное лечение
### Наблюдение
- Сертификат endpoint сам по себе валидный (Let's Encrypt, CN/SAN = `fission.kube5s.ru`).
- Но на том же host были два ingress с разной TLS-конфигурацией:
- `fission-console` с TLS
- `fission-router` без TLS
### Действие
- Патч `fission-router`:
- добавлен `spec.tls` с `secretName: fission-tls`
- добавлен `force-ssl-redirect=true`
### Результат
- HTTP на роутер-пути дает 308 -> HTTPS
- HTTPS на console стабильно 200
- Конфигурация host выровнена: теперь и console, и router на одном сертификате.
---
## Сессия: Строгая чистка до "только точно рабочие и видимые"
### Запрос
- Оставить только функции, которые в UI/Console:
- показывают исходник (`code` не пустой)
- реально вызываются (`invoke.status == 200`)
### Что произошло
- Выполнен массовый cleanup с keep-list.
- По логу cleanup выявилась ошибка jsonpath в пост-обработке orphan-пакетов:
- использовалось `{n}` вместо `{"\\n"}`
- это ломало шаг удаления orphan-объектов после основного удаления.
- Основное удаление функций при этом сработало корректно.
### Проверка после cleanup
- Текущее состояние:
- functions: 6
- httptriggers: 6
- packages: 6
- Остались только:
- `auth-test2`
- `fn-js-direct`
- `fn-js-acc`
- `hello`
- `tf-auto-ok-fn`
- `tf-stress-fast-fn`
- Для каждой функции через Console API подтверждено:
- `code=OK`
- `invoke=OK`
### Вывод
- Финальный набор теперь соответствует строгому критерию "однозначно работает и показывается".