# 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)