diff --git a/doc/CODEX_UI_PLAN.md b/doc/CODEX_UI_PLAN.md new file mode 100644 index 0000000..2b14dc9 --- /dev/null +++ b/doc/CODEX_UI_PLAN.md @@ -0,0 +1,805 @@ +# Fission Console — план разработки UI + +Дата: 2026-04-15 +Автор: Claude Opus → план для GPT 5.3 Codex +Статус: ПЛАН (к реализации) + +--- + +## Цель + +Создать веб-консоль для Fission — аналог `sless-funcs-service` из проекта sless. +Консоль позволяет: смотреть функции, создавать, редактировать код, вызывать, управлять триггерами. + +## Референсные файлы (ОБЯЗАТЕЛЬНО ИЗУЧИТЬ) + +Перед написанием кода — прочитай эти файлы из sless (монтирован рядом на VM): + +| Файл | Зачем | +|------|-------| +| `~/terra/sless/services/funcs/main.go` (942 строки) | **Главный референс** — Go backend funcs-service. Роутинг, proxy к оператору, рендеринг HTML с JSON data injection | +| `~/terra/sless/services/funcs/index.html` (1146 строк) | **Главный референс** — UI. Vanilla JS SPA, карточки функций, создание, редактирование, highlight.js, build polling | +| `~/terra/sless/services/funcs/Dockerfile` | Multi-stage Go+embed сборка | +| `~/terra/sless/services/funcs/funcs-service.yaml` | K8s Deployment+Service+Ingress | +| `~/terra/sless/internal/api/ui/iot-console.html` (1330 строк) | Референс для IoT-стиля UI (Nubes branding, login, табы, модалки) | +| `~/terra/sless/shared-sqs/app/ui/embed.go` | Паттерн go:embed | +| `~/terra/sless/shared-sqs/app/ui/index.html` (932 строки) | Ещё один референс SPA (queue CRUD) | +| `~/terra/sless/doc/decisions/funcs_console_editor.md` | Архитектурные решения по редактору кода | + +## Архитектура + +### Компоненты + +``` +User Browser + └─► https://fission.kube5s.ru/console + └─► nginx Ingress (уже есть для fission router) + └─► fission-console:8090 (новый pod в namespace fission) + ├─► GET /console → HTML SPA (go:embed) + ├─► GET /api/environments → kubectl proxy → CRD list + ├─► GET /api/functions → kubectl proxy → CRD list + ├─► GET /api/packages → kubectl proxy → CRD list + ├─► GET /api/triggers → kubectl proxy → CRD list + ├─► POST /api/functions → create CRD + ├─► POST /api/functions/{name}/code → update package literal + ├─► POST /api/functions/{name}/invoke → proxy → router + ├─► DELETE /api/functions/{name} → delete CRD + └─► GET /api/functions/{name}/status → pod status +``` + +### Технологии + +- **Backend:** Go, net/http, k8s client-go (dynamic client) +- **Frontend:** Vanilla HTML/CSS/JS (один файл, go:embed) +- **Подсветка кода:** highlight.js (CDN) +- **Стиль:** Nubes dark theme (идентичный sless/IoT) +- **Деплой:** Docker multi-stage → K8s Deployment + Service + Ingress + +### Почему dynamic client (не REST API): + +Fission в нашем кластере НЕ имеет REST `/v2` API. +Все данные — через Kubernetes CRD (environments.fission.io, functions.fission.io итд). +Текущий Terraform provider уже работает через dynamic client — переиспользуем тот же подход. + +--- + +## Структура файлов (создать) + +``` +console/ +├── main.go # HTTP server + API handlers + k8s client +├── ui/ +│ ├── embed.go # go:embed index.html +│ └── index.html # SPA: весь CSS + JS +├── go.mod +├── Dockerfile # multi-stage: Go → alpine +└── deploy/ + └── console.yaml # K8s Deployment + Service + Ingress rule +``` + +--- + +## Этап 1: Backend (main.go) — ~400-500 строк Go + +### 1.1 Инициализация + +```go +// Переменные окружения: +// KUBECONFIG — путь к kubeconfig (dev) или in-cluster +// FISSION_NAMESPACE — namespace с функциями (default: "default") +// FISSION_ROUTER_URL — внутренний URL роутера (default: "http://router.fission.svc.cluster.local") +// PORT — порт (default: "8090") +``` + +- Создать dynamic client (как в terraform provider — client.go) +- Маршруты: `/console` (UI), `/api/*` (JSON API), `/health` + +### 1.2 API endpoints + +| Метод | Путь | Что делает | +|-------|------|-----------| +| GET | /api/environments | List environments.fission.io → JSON array | +| GET | /api/packages | List packages.fission.io → JSON array | +| GET | /api/functions | List functions.fission.io → JSON array | +| GET | /api/httptriggers | List httptriggers.fission.io → JSON array | +| GET | /api/timetriggers | List timetriggers.fission.io → JSON array | +| GET | /api/functions/{name} | Get function + связанный package + trigger info | +| POST | /api/functions | Create: environment → package → function → httptrigger (всё за один вызов) | +| PUT | /api/functions/{name}/code | Update package spec.deployment.literal (новый код) | +| POST | /api/functions/{name}/invoke | Proxy → fission router: POST http://router/fission-function/v2/functions/{name} | +| DELETE | /api/functions/{name} | Delete function + httptrigger + package (каскадно) | +| GET | /api/pods | List pods по label svc=... в namespace "default" (показать runtime pods) | + +### 1.3 Формат ответа (JSON) + +Для листинга функций — объединённая структура: + +```json +{ + "functions": [ + { + "name": "hello", + "environment": "python", + "package": "hello-pkg", + "entrypoint": "main.main", + "code": "def main():\n return hello\n", + "trigger_url": "/hello", + "trigger_methods": ["GET"], + "invoke_url": "https://fission.kube5s.ru/hello", + "created": "2026-04-14T18:30:00Z" + } + ], + "environments": [ + {"name": "python", "image": "ghcr.io/fission/python-env", "version": 3} + ] +} +``` + +### 1.4 Create function — полный flow + +POST /api/functions с телом: +```json +{ + "name": "my-func", + "environment": "python", + "code": "def main():\n return {hello: world}\n", + "entrypoint": "main.main", + "route": "/my-func", + "methods": ["GET", "POST"] +} +``` + +Backend создаёт 3 CRD объекта: +1. Package (`{name}-pkg`) — spec.environment + spec.deployment.literal (base64 код) +2. Function (`{name}`) — spec.environment + spec.package + spec.invokeStrategy +3. HTTPTrigger (`{name}-route`) — spec.functionref + spec.relativeurl + spec.methods + +Если environment не существует — вернуть ошибку (не создавать). + +### 1.5 Update code + +PUT /api/functions/{name}/code с телом: `{"code": "..."}` + +1. Найти function CRD → получить package name +2. Обновить package spec.deployment.literal (base64 encode) +3. Вернуть 200 + +### 1.6 Invoke + +POST /api/functions/{name}/invoke с телом: произвольный JSON + +Proxy → `http://router.fission.svc.cluster.local/fission-function/v2/functions/{name}` +Вернуть: status code + body + latency + +### 1.7 Каскадное удаление + +DELETE /api/functions/{name}: +1. Получить function → имя package и trigger +2. Удалить httptrigger(s) связанные с функцией +3. Удалить function +4. Удалить package + +--- + +## Этап 2: Frontend (index.html) — ~800-1000 строк + +### 2.1 Дизайн — Nubes dark theme + +CSS переменные (скопировать из sless): +```css +:root { + --bg-page: #001120; + --bg-surface: #001929; + --bg-navbar: #001C34; + --border: #0b2d50; + --accent: #1a7fd4; + --text-primary: #e2ecf6; + --text-secondary: #6b8eaa; + --danger: #e74c3c; + --success: #27ae60; +} +``` + +### 2.2 Страницы/секции + +#### Navbar +``` +[Nubes logo] [/] [Fission Console] [namespace: default] [↻ Refresh] [+ Создать функцию] +``` + +#### Секция: Dashboard (summary) +``` +Environments: 3 | Functions: 8 | Triggers: 7 | Router: fission.kube5s.ru +``` + +#### Секция: Карточки функций (как в sless funcs-service) + +Каждая функция — карточка: +``` +┌────────────────────────────────────────────────────────────┐ +│ hello-fn [python] [Ready] https://fission.kube5s.ru/hello │ +│ ✎ Edit ▶ Invoke ✕ Delete │ +├────────────────────────────────────────────────────────────┤ +│ (expand) → показать код с подсветкой (highlight.js) │ +│ (edit mode) → textarea + Save │ +│ (invoke mode) → JSON input + Send + Response display │ +└────────────────────────────────────────────────────────────┘ +``` + +#### Модалка: Создать функцию +``` +┌─── Создать функцию ──────────────────────────┐ +│ Environment: [python ▾] [nodejs ▾] [go ▾] │ +│ Имя: [my-func_________] │ +│ Entrypoint: [main.main_______] │ +│ Route: [/my-func________] │ +│ Файл: main.py │ +│ ┌──────────────────────────────────────┐ │ +│ │ def main(): │ │ +│ │ return {"hello": "world"} │ │ +│ └──────────────────────────────────────┘ │ +│ [Отмена] [Создать] │ +└───────────────────────────────────────────────┘ +``` + +При смене environment → обновить шаблон кода/файла: +- python → main.py, `def main(): ...` +- nodejs → main.js, `module.exports = async function(req) { ... }` +- go → main.go, `func Handler(w http.ResponseWriter, r *http.Request) { ... }` + +#### Inline: Invoke функции + +``` +┌─── Invoke: hello-fn ─────────────────────────┐ +│ Input JSON: │ +│ ┌──────────────────────────────────┐ │ +│ │ {"name": "world"} │ │ +│ └──────────────────────────────────┘ │ +│ [▶ Send] │ +│ │ +│ Response (200, 34ms): │ +│ ┌──────────────────────────────────┐ │ +│ │ {"hello": "world"} │ │ +│ └──────────────────────────────────┘ │ +└────────────────────────────────────────────────┘ +``` + +### 2.3 JavaScript — SPA логика + +Принципы (из sless referenceов): +- Весь state в объекте `S = { functions: [], environments: [], ... }` +- `render()` — главный диспетчер +- Partial DOM updates по ID (не полный re-render) +- `fetch(/api/...)` для всех операций +- `h()` — HTML escape utility +- Карточки: expand/collapse для кода, inline edit, inline invoke + +--- + +## Этап 3: Сборка и деплой + +### 3.1 go.mod + +``` +module fission-console + +go 1.24.0 + +require ( + k8s.io/apimachinery v0.32.3 + k8s.io/client-go v0.32.3 +) +``` + +Важно: использовать те же версии k8s что в terraform/provider/go.mod. + +### 3.2 Dockerfile + +```dockerfile +FROM golang:1.24-alpine AS builder +WORKDIR /build +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o fission-console . + +FROM alpine:3.20 +RUN apk add --no-cache ca-certificates +COPY --from=builder /build/fission-console /fission-console +EXPOSE 8090 +ENTRYPOINT ["/fission-console"] +``` + +### 3.3 K8s manifest (deploy/console.yaml) + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: fission-console + namespace: fission +spec: + replicas: 1 + selector: + matchLabels: + app: fission-console + template: + metadata: + labels: + app: fission-console + spec: + serviceAccountName: fission-console + containers: + - name: console + image: naeel/fission-console:v0.1.0 + ports: + - containerPort: 8090 + env: + - name: FISSION_NAMESPACE + value: "default" + - name: FISSION_ROUTER_URL + value: "http://router.fission.svc.cluster.local" + - name: PORT + value: "8090" + livenessProbe: + httpGet: {path: /health, port: 8090} + initialDelaySeconds: 5 + resources: + requests: {cpu: 10m, memory: 16Mi} + limits: {cpu: 100m, memory: 64Mi} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: fission-console + namespace: fission +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: fission-console +rules: + - apiGroups: ["fission.io"] + resources: ["environments", "packages", "functions", "httptriggers", "timetriggers"] + verbs: ["get", "list", "create", "update", "patch", "delete"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: fission-console +subjects: + - kind: ServiceAccount + name: fission-console + namespace: fission +roleRef: + kind: ClusterRole + name: fission-console + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: v1 +kind: Service +metadata: + name: fission-console + namespace: fission +spec: + selector: + app: fission-console + ports: + - port: 8090 + targetPort: 8090 +--- +# Ingress: добавить path /console к существующему fission ingress +# ИЛИ создать отдельный Ingress для fission-console +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: fission-console + namespace: fission + annotations: + nginx.ingress.kubernetes.io/force-ssl-redirect: "true" +spec: + ingressClassName: nginx + rules: + - host: fission.kube5s.ru + http: + paths: + - path: /console + pathType: Prefix + backend: + service: + name: fission-console + port: + number: 8090 + tls: + - hosts: [fission.kube5s.ru] + secretName: fission-tls # проверить имя секрета +``` + +--- + +## Этап 4: Тестирование + +### 4.1 Smoke test (вручную в браузере) +1. Открыть https://fission.kube5s.ru/console +2. Увидеть список существующих функций +3. Создать новую функцию (Python) → увидеть в списке +4. Отредактировать код → сохранить +5. Invoke → получить ответ +6. Удалить → исчезла из списка + +### 4.2 curl smoke +```bash +# API листинг +curl -s https://fission.kube5s.ru/console/api/functions | jq . + +# Создать функцию +curl -s -X POST https://fission.kube5s.ru/console/api/functions \ + -H Content-Type: application/json \ + -d name:test-ui + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform) +ENDOFPLAN application/json \ + -d environment:python + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform) +ENDOFPLAN application/json \ + -d code:def main():\n return {"ok":true} + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform) +ENDOFPLAN application/json \ + -d entrypoint:main.main + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform) +ENDOFPLAN application/json \ + -d route:/test-ui + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform) +ENDOFPLAN application/json \ + -d methods:[GET] + +# Invoke +curl -s -X POST https://fission.kube5s.ru/console/api/functions/test-ui/invoke + +# Удалить +curl -s -X DELETE https://fission.kube5s.ru/console/api/functions/test-ui +``` + +--- + +## Порядок выполнения (для Codex) + +| # | Шаг | Файл(ы) | Критерий готовности | +|---|-----|---------|-------------------| +| 1 | Создать структуру console/ + go.mod | console/ | `go mod tidy` проходит | +| 2 | Написать main.go — HTTP server + k8s client init + health endpoint | main.go | Компилируется, /health отвечает | +| 3 | Написать API handlers: list environments/functions/packages/triggers | main.go | `curl /api/functions` возвращает JSON | +| 4 | Написать API handler: create function (env→pkg→fn→trigger) | main.go | POST создаёт 3 CRD | +| 5 | Написать API handler: update code (package literal) | main.go | PUT обновляет пакет | +| 6 | Написать API handler: invoke (proxy → router) | main.go | POST вызывает функцию | +| 7 | Написать API handler: delete (каскадно) | main.go | DELETE удаляет fn+pkg+trigger | +| 8 | Создать ui/embed.go | ui/embed.go | — | +| 9 | Создать index.html — CSS (Nubes dark theme) + navbar + layout | ui/index.html | Открывается с правильным стилем | +| 10 | JS: загрузка данных + рендер карточек функций | ui/index.html | Карточки отображаются | +| 11 | JS: expand карточки → показать код с подсветкой | ui/index.html | Код виден | +| 12 | JS: модалка создания функции + шаблоны Python/JS/Go | ui/index.html | Функция создаётся через UI | +| 13 | JS: inline edit mode + save | ui/index.html | Код обновляется | +| 14 | JS: inline invoke панель | ui/index.html | Вызов и ответ показываются | +| 15 | JS: delete с подтверждением | ui/index.html | Удаление работает | +| 16 | Dockerfile + добавить в .gitignore | Dockerfile, .gitignore | `docker build` проходит | +| 17 | K8s manifest + RBAC | deploy/console.yaml | Pod запускается, /health OK | +| 18 | Ingress → smoke test в браузере | deploy/console.yaml | UI доступен по HTTPS | +| 19 | Commit + push | — | Всё в git | + +--- + +## КРИТИЧЕСКИЕ ПРАВИЛА ВЫПОЛНЕНИЯ + +1. **ВСЁ через SSH на VM** — `ssh naeel@5.172.178.213`. Файлы писать локально (sshfs mount), команды — по SSH. +2. **Образы на Docker Hub** (`naeel/fission-console`). НЕ использовать pearlharbor. +3. **Nubes branding** — идентичный sless. CSS variables из референса. +4. **Vanilla JS** — без React/Vue/Angular. Один HTML файл. +5. **go:embed** — index.html встраивается в бинарник. +6. **Рабочая директория:** `~/terra/fission/console/` +7. **Проверять go.mod версии** — взять k8s-* из `~/terra/fission/terraform/provider/go.mod` +8. **Не ломать существующий provider** — console/ отдельный Go module +9. **Перед docker build** — убедиться что бинарник в .gitignore +10. **Commit + push** после каждого рабочего этапа + +--- + +## Что НЕ делать + +- Auth/login — пока не нужен (демо-режим, без токенов) +- Multi-namespace — работаем с одним namespace (default) +- Управление environments через UI — только листинг (создание через terraform) +- Логи функций (stdout/stderr) — отложить +- Version history — отложить +- TimeTriggers CRUD — только отображение (создание — terraform)