Files

40 KiB
Raw Permalink Blame History

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 Инициализация

// Переменные окружения:
//   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)

Для листинга функций — объединённая структура:

{
  "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 с телом:

{
  "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):

: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

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)

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

# 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 на VMssh 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 на VMssh 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 на VMssh 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)