288 lines
16 KiB
Markdown
288 lines
16 KiB
Markdown
# 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) через CRD `packages.fission.io`.
|
||
|
||
### Обновление этапа (fission_package)
|
||
- Реализован CRUD в `internal/client/client.go` для `packages.fission.io`:
|
||
- `CreatePackage`
|
||
- `GetPackage`
|
||
- `UpdatePackage`
|
||
- `DeletePackage`
|
||
- Реализован ресурс `fission_package` в `internal/resources/package_resource.go`:
|
||
- schema: `name`, `environment`, `source_dir`, `code_path`, `code_hash`, `build_command`, `namespace`, computed `id`, `uid`, `build_status`, `build_log`
|
||
- валидация источника кода: задан ровно один из `source_dir` или `code_path`
|
||
- упаковка `source_dir` в zip и кодирование base64 в `spec.source.literal`
|
||
- Create/Read/Update/Delete через Kubernetes CRD API
|
||
- Проверка сборки: `go build ./...` успешно.
|
||
|
||
### Следующий шаг
|
||
- Реализовать `fission_function` через CRD `functions.fission.io`.
|
||
|
||
### Обновление этапа (fission_function)
|
||
- Реализован CRUD в `internal/client/client.go` для `functions.fission.io`:
|
||
- `CreateFunction`
|
||
- `GetFunction`
|
||
- `UpdateFunction`
|
||
- `DeleteFunction`
|
||
- Реализован ресурс `fission_function` в `internal/resources/function_resource.go`:
|
||
- schema: `name`, `environment`, `package_name`, `entrypoint`, `namespace`, computed `id`, `uid`
|
||
- Configure/Create/Read/Update/Delete
|
||
- маппинг в CRD `Function` (`spec.environment`, `spec.package.packageref`, `spec.package.functionName`)
|
||
- Проверка сборки: `go build ./...` успешно.
|
||
|
||
### Следующий шаг
|
||
- Реализовать `fission_http_trigger` через CRD `httptriggers.fission.io`.
|
||
|
||
### Обновление этапа (fission_http_trigger)
|
||
- Реализован CRUD в `internal/client/client.go` для `httptriggers.fission.io`:
|
||
- `CreateHTTPTrigger`
|
||
- `GetHTTPTrigger`
|
||
- `UpdateHTTPTrigger`
|
||
- `DeleteHTTPTrigger`
|
||
- Реализован ресурс `fission_http_trigger` в `internal/resources/http_trigger_resource.go`:
|
||
- schema: `name`, `function`, `url`, `methods`, `create_ingress`, `host`, `namespace`, computed `id`, `uid`
|
||
- Configure/Create/Read/Update/Delete
|
||
- маппинг в CRD `HTTPTrigger` (`spec.relativeurl`, `spec.methods`, `spec.functionref`, `spec.createingress`)
|
||
- Проверка сборки: `go build ./...` успешно.
|
||
|
||
### Следующий шаг
|
||
- Добавить пример `examples/hello-python/main.tf` и выполнить smoke Terraform apply.
|
||
|
||
### Обновление этапа (пример Terraform)
|
||
- Создан пример `examples/hello-python/main.tf` с использованием ресурсов:
|
||
- `fission_environment`
|
||
- `fission_package`
|
||
- `fission_function`
|
||
- `fission_http_trigger`
|
||
- Добавлен код функции `examples/hello-python/code/main.py`.
|
||
|
||
### Следующий шаг
|
||
- Подготовить локальную установку бинарника провайдера для `terraform init` и выполнить smoke `terraform 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`.
|
||
- `fission_function`: CRD требовал обязательный `spec.InvokeStrategy`.
|
||
- Добавлен `InvokeStrategy` в payload функции.
|
||
- `fission_http_trigger`: несогласованность state (`create_ingress` null -> false).
|
||
- В schema добавлены `Computed` + `Default(false)` для `create_ingress`.
|
||
- Для `methods` добавлен `Computed`.
|
||
|
||
Дополнительно:
|
||
- Для текущего 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_environment`
|
||
- `fission_package`
|
||
- `fission_function`
|
||
- `fission_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` запросов на endpoint
|
||
- `90` параллелизм
|
||
- итог: `100%` success на всех трех endpoint-ах.
|
||
|
||
### Следующий шаг
|
||
- Добавить в acceptance-тест проверку HTTP latency/perf budget и порогов SLO.
|
||
|
||
### Обновление этапа (JS/Go source support)
|
||
- В `fission_package` расширена поддержка `source_dir`:
|
||
- `main.py`
|
||
- `main.js`
|
||
- `main.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` — обновление кода в package
|
||
- `TestInvokeFunctionWithJWTAuth` — 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.
|
||
|
||
**Исследование:**
|
||
1. Попробовал SA token из пода → `key is of invalid type` (K8s SA = RS256, router ожидает HS256)
|
||
2. Прочитал feature-config: `auth.enabled: true`, endpoint `/auth/login`, JWT expiry 120s
|
||
3. Нашёл credentials в секрете `router`: username=admin, password=..., jwtSigningKey=...
|
||
4. Протестировал: `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.username`
|
||
- `FISSION_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 tests
|
||
- `8920ba1` — fix: invoke auth via Fission router JWT login
|
||
|
||
**Docker Hub:** `naeel/fission-console:v0.2.2`
|
||
|
||
#### Правила репозитория
|
||
|
||
Создан `.github/copilot-instructions.md` с правилами:
|
||
- Маппинг путей (локально ~/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.py` `terraform plan` теперь показывает `fission_package.hello will be updated in-place` с изменением `code_hash`.
|
||
- Конфигурация с несуществующим `environment` теперь падает на этапе apply с ошибкой валидации.
|
||
- Конфигурация с неверным `entrypoint` теперь падает на этапе apply с ошибкой валидации.
|
||
|
||
### Ограничения
|
||
- Runtime-проблемы Fission (зависания на cold start/таймауты выполнения) в этом изменении не трогались: исправлен только provider-слой валидации и обнаружения изменений.
|