Files
fission-console/doc/CODEX_PLAN.md
T

729 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Terraform Provider для Fission — Подробный план разработки
# Дата: 2026-04-14
# Агент: GPT 5.3 Codex
# Домен: fission.kube5s.ru
## ОБНОВЛЕНИЕ ПО ФАКТУ ПРОВЕРКИ В КЛАСТЕРЕ (2026-04-14)
Проверено на кластере `iot-naeel`:
- Fission `v1.22.1` поднят и работает (env/function/route через `fission` CLI успешны)
- путь `GET /v2/environments` через ingress (`185.247.187.151`) возвращает `404 page not found`
- отдельного `controller` service/deployment в текущем `fission-all` релизе нет
**Критичное решение:**
MVP провайдера делать через Kubernetes API (CRD Fission) с использованием `client-go`/dynamic client,
а не через REST `/v2/*`.
Provider продолжает управлять теми же сущностями (`Environment`, `Package`, `Function`, `HTTPTrigger`),
но операции Create/Read/Update/Delete выполняются через Kubernetes CRD ресурсы.
---
## КОНТЕКСТ ПРОЕКТА
### Что делаем
Terraform provider для Fission (https://fission.io) — open-source serverless фреймворка на Kubernetes.
Provider позволяет управлять Fission-ресурсами (environments, packages, functions, triggers) через Terraform.
### Зачем
Fission используется как managed FaaS-сервис в нашем облаке. Terraform — основной инструмент IaC.
Готового провайдера не существует (единственная попытка — https://github.com/sambuysse/terraform-provider-fission — заброшена 5 лет назад, реализован только 1 ресурс).
### Архитектура
```
Terraform Provider (Go) → Kubernetes API (client-go/dynamic) → Fission CRD
Fission делает всё сам:
- StorageSvc (PV, позже S3)
- Builder Manager → Builder Pods
- Executor → Function Pods
- Router → HTTP routing
```
**Provider НЕ управляет S3/PV напрямую.** Он управляет только Fission CRD через Kubernetes API.
Fission сам хранит код (StorageSvc), собирает (Builder), запускает (Executor), маршрутизирует (Router).
### Ключевые решения
- Без proxy/operator — provider напрямую к Kubernetes API (Fission CRD)
- StorageSvc на PV (local storage) — позже мигрируем на S3
- terraform-plugin-framework (НЕ старый SDKv2)
- Паттерны из существующего sless-провайдера (структура, client, build script)
- Domain: fission.kube5s.ru
---
## РЕФЕРЕНСНЫЙ КОД — sless provider
Провайдер sless (наш существующий, рабочий) находится в:
```
/home/naeel/terra/sless/terraform/provider/
├── main.go # Точка входа
├── go.mod / go.sum
├── hack/build-and-publish.sh # Сборка и публикация
└── internal/
├── client/client.go # HTTP-клиент (~34KB) — к sless API
├── provider/provider.go # Конфигурация провайдера
└── resources/
├── function_resource.go # sless_function
├── service_resource.go # sless_service
├── trigger_resource.go # sless_trigger
├── job_resource.go # sless_job
└── iot_device_resource.go # sless_iot_device
```
**Что копировать из sless:**
- Структуру каталогов и файлов
- main.go (адаптировать имя провайдера)
- provider.go (endpoint, token — аналогично; убрать nubes_endpoint, namespace вычисление)
- build-and-publish.sh (адаптировать имена)
- Паттерн resources: Metadata, Schema, Create, Read, Update, Delete, Configure
**Что НЕ копировать:**
- client.go целиком — переписать под Fission API (другие endpoints, другой формат)
- Kaniko-логику — Fission строит сам
- S3 upload — Fission принимает через HTTP, хранит сам
- JWT→namespace mapping — для MVP не нужно
- source_dir zip + hash логику — упростить, Fission Package принимает zip напрямую
---
## FISSION API REFERENCE
> ⚠️ Для текущей установки Fission v1.22.1 в этом кластере REST `/v2/*` недоступен (`404`).
> Раздел ниже оставлен как историческая справка; для реализации MVP использовать Kubernetes CRD API.
### Fission Controller REST API
Fission Controller слушает на порте 8888 (внутри кластера) или через Ingress.
API работает с Kubernetes CRD-объектами через REST.
**Base URL:** `https://fission.kube5s.ru/` (через Ingress) или `http://controller.fission.svc:8888`
### Эндпоинты (v2 API)
#### Environments
```
POST /v2/environments — создать environment
GET /v2/environments — список environments
GET /v2/environments/{name} — получить environment
PUT /v2/environments/{name} — обновить environment
DELETE /v2/environments/{name} — удалить environment
```
#### Packages
```
POST /v2/packages — создать package (multipart: zip с кодом)
GET /v2/packages — список packages
GET /v2/packages/{name} — получить package
PUT /v2/packages/{name} — обновить package
DELETE /v2/packages/{name} — удалить package
```
#### Functions
```
POST /v2/functions — создать function
GET /v2/functions — список functions
GET /v2/functions/{name} — получить function
PUT /v2/functions/{name} — обновить function
DELETE /v2/functions/{name} — удалить function
```
#### HTTP Triggers
```
POST /v2/triggers/http — создать HTTP trigger
GET /v2/triggers/http — список HTTP triggers
GET /v2/triggers/http/{name} — получить HTTP trigger
PUT /v2/triggers/http/{name} — обновить HTTP trigger
DELETE /v2/triggers/http/{name} — удалить HTTP trigger
```
#### Time Triggers
```
POST /v2/triggers/time — создать time trigger
GET /v2/triggers/time — список time triggers
GET /v2/triggers/time/{name} — получить time trigger
PUT /v2/triggers/time/{name} — обновить time trigger
DELETE /v2/triggers/time/{name} — удалить time trigger
```
#### Message Queue Triggers
```
POST /v2/triggers/messagequeue — создать MQ trigger
GET /v2/triggers/messagequeue — список MQ triggers
GET /v2/triggers/messagequeue/{name} — получить MQ trigger
PUT /v2/triggers/messagequeue/{name} — обновить MQ trigger
DELETE /v2/triggers/messagequeue/{name} — удалить MQ trigger
```
### Аутентификация
Fission 1.22 поддерживает auth. При установке через helm:
```yaml
authentication:
enabled: true
```
Provider передаёт токен в заголовке:
```
Authorization: Bearer <token>
```
### Namespace
Все ресурсы Fission создаются в namespace указанном при helm install (по дефолту `fission`).
Функции работают в `defaultNamespace` (по дефолту тот же `fission` или кастомный).
---
## FISSION CRD МОДЕЛИ (для Schema ресурсов)
### Environment
```json
{
"metadata": { "name": "python", "namespace": "fission-function" },
"spec": {
"version": 3,
"runtime": {
"image": "ghcr.io/fission/python-env"
},
"builder": {
"image": "ghcr.io/fission/python-builder",
"command": "build"
},
"poolsize": 3,
"resources": {
"requests": { "cpu": "100m", "memory": "128Mi" },
"limits": { "cpu": "200m", "memory": "256Mi" }
},
"imagepullsecret": "",
"allowedFunctionsPerContainer": "single"
}
}
```
### Package
```json
{
"metadata": { "name": "hello-pkg", "namespace": "fission-function" },
"spec": {
"environment": { "name": "python", "namespace": "fission-function" },
"source": {
"type": "literal",
"literal": "<base64 zip>"
},
"buildcmd": ""
},
"status": {
"buildstatus": "succeeded",
"buildlog": "..."
}
}
```
Для больших файлов source.type = "url", и архив загружается через StorageSvc.
### Function
```json
{
"metadata": { "name": "hello", "namespace": "fission-function" },
"spec": {
"environment": { "name": "python", "namespace": "fission-function" },
"package": {
"packageref": { "name": "hello-pkg", "namespace": "fission-function", "resourceversion": "12345" },
"functionName": "main.handler"
},
"resources": {
"requests": { "cpu": "100m", "memory": "128Mi" },
"limits": { "cpu": "200m", "memory": "256Mi" }
},
"InvokeStrategy": {
"ExecutionStrategy": {
"ExecutorType": "poolmgr",
"MinScale": 0,
"MaxScale": 5,
"TargetCPUPercent": 80,
"SpecializationTimeout": 120
},
"StrategyType": "execution"
},
"functionTimeout": 60,
"idletimeout": 120,
"concurrency": 500,
"requestsPerPod": 1
}
}
```
### HTTPTrigger
```json
{
"metadata": { "name": "hello-route", "namespace": "fission-function" },
"spec": {
"relativeurl": "/hello",
"methods": ["GET", "POST"],
"functionref": { "type": "name", "name": "hello" },
"createingress": false,
"ingressconfig": {
"host": "fission.kube5s.ru",
"path": "/hello",
"annotations": {}
}
}
}
```
### TimeTrigger
```json
{
"metadata": { "name": "cron-job", "namespace": "fission-function" },
"spec": {
"cron": "*/5 * * * *",
"functionref": { "type": "name", "name": "hello" }
}
}
```
---
## СТРУКТУРА ПРОЕКТА (создать)
```
fission/
├── .github/
│ └── copilot-instructions.md # Правила для агентов
├── doc/
│ ├── CODEX_PLAN.md # Этот файл
│ └── progress.md # Трекер задач
├── terraform/
│ └── provider/
│ ├── main.go # Точка входа terraform-plugin-framework
│ ├── go.mod # Module: terraform-provider-fission
│ ├── go.sum
│ ├── internal/
│ │ ├── client/
│ │ │ └── client.go # HTTP-клиент к Fission Controller API
│ │ ├── provider/
│ │ │ └── provider.go # Конфигурация провайдера
│ │ └── resources/
│ │ ├── environment_resource.go # fission_environment
│ │ ├── package_resource.go # fission_package
│ │ ├── function_resource.go # fission_function
│ │ ├── http_trigger_resource.go # fission_http_trigger
│ │ ├── time_trigger_resource.go # fission_time_trigger (фаза 2)
│ │ └── mqt_resource.go # fission_mqt (фаза 2)
│ └── hack/
│ └── build-and-publish.sh
├── examples/
│ ├── hello-python/
│ │ ├── main.tf
│ │ └── code/
│ │ └── main.py
│ └── README.md
├── .gitignore
└── README.md
```
---
## ФАЗЫ РАЗРАБОТКИ
### ФАЗА 0 — Подготовка (инфраструктура, ДО codex — руками)
**0.1** Установить Fission 1.22 на кластер:
```bash
kubectl create namespace fission
kubectl create -k "github.com/fission/fission/crds/v1?ref=v1.22.0"
helm repo add fission-charts https://fission.github.io/fission-charts/
helm repo update
helm install fission fission-charts/fission-all \
--version 1.22.1 \
--namespace fission \
--set serviceType=ClusterIP \
--set routerServiceType=ClusterIP \
--set authentication.enabled=true
```
**0.2** Настроить Ingress на fission.kube5s.ru → Fission Router
**0.3** Установить fission CLI и проверить:
```bash
fission env create --name python --image ghcr.io/fission/python-env
fission fn create --name hello --env python --code hello.py
fission fn test --name hello
```
**0.4** Проверить CRD API через Kubernetes:
```bash
kubectl get crd environments.fission.io functions.fission.io packages.fission.io httptriggers.fission.io
kubectl get environments -n default
```
---
### ФАЗА 1 — Provider MVP (codex)
**Задача: provider с 4 ресурсами, рабочий terraform apply → функция отвечает по HTTP.**
#### 1.1 Scaffolding
- Создать структуру каталогов (см. выше)
- `go.mod` с зависимостями: `github.com/hashicorp/terraform-plugin-framework`, `terraform-plugin-go`
- `main.go` — точка входа (по образцу sless/terraform/provider/main.go)
- `.gitignore` — бинарники, .terraform, *.tfstate
#### 1.2 Client (internal/client/client.go)
Клиент к Kubernetes API для работы с Fission CRD.
**Структура:**
```go
package client
type Client struct {
dynClient dynamic.Interface
k8sClient kubernetes.Interface
namespace string // namespace для функций (дефолт "default")
}
func New(kubeconfigPath, kubeContext, namespace string) (*Client, error)
// Environments
func (c *Client) CreateEnvironment(ctx, env) error
func (c *Client) GetEnvironment(ctx, name) (*Environment, error)
func (c *Client) UpdateEnvironment(ctx, env) error
func (c *Client) DeleteEnvironment(ctx, name) error
// Packages
func (c *Client) CreatePackage(ctx, pkg) (*Package, error)
func (c *Client) GetPackage(ctx, name) (*Package, error)
func (c *Client) UpdatePackage(ctx, pkg) (*Package, error)
func (c *Client) DeletePackage(ctx, name) error
// Functions
func (c *Client) CreateFunction(ctx, fn) error
func (c *Client) GetFunction(ctx, name) (*Function, error)
func (c *Client) UpdateFunction(ctx, fn) error
func (c *Client) DeleteFunction(ctx, name) error
// HTTP Triggers
func (c *Client) CreateHTTPTrigger(ctx, trigger) error
func (c *Client) GetHTTPTrigger(ctx, name) (*HTTPTrigger, error)
func (c *Client) UpdateHTTPTrigger(ctx, trigger) error
func (c *Client) DeleteHTTPTrigger(ctx, name) error
```
**Формат работы:**
- dynamic client для CRD `*.fission.io`
- операции CRUD через Kubernetes API
- Namespace через metadata и provider config
- код package загружается в `spec.source.literal` (base64 zip) для MVP
**ВАЖНО:** Размер client.go — целевой ~500-900 строк. Никакого S3, kaniko, polling.
#### 1.3 Provider (internal/provider/provider.go)
**Атрибуты провайдера:**
```hcl
provider "fission" {
kubeconfig_path = "~/.kube/config" # env: KUBECONFIG
kube_context = "" # env: KUBE_CONTEXT (optional)
namespace = "default" # env: FISSION_NAMESPACE
}
```
**Configure():**
1. Прочитать kubeconfig_path (config → env KUBECONFIG)
2. Прочитать kube_context (config → env KUBE_CONTEXT)
3. Прочитать namespace (config → env FISSION_NAMESPACE → default "default")
4. Создать Kubernetes dynamic client
5. Положить в resp.ResourceData и resp.DataSourceData
**Resources():**
```go
return []func() resource.Resource{
resources.NewEnvironmentResource,
resources.NewPackageResource,
resources.NewFunctionResource,
resources.NewHTTPTriggerResource,
}
```
#### 1.4 Resource: fission_environment
**Terraform Schema:**
```hcl
resource "fission_environment" "python" {
name = "python" # Required, ForceNew
image = "ghcr.io/fission/python-env" # Required (runtime image)
version = 3 # Optional, default 3
builder_image = "ghcr.io/fission/python-builder" # Optional
builder_command = "build" # Optional
poolsize = 3 # Optional, default 3
min_cpu = "100m" # Optional
max_cpu = "200m" # Optional
min_memory = "128Mi" # Optional
max_memory = "256Mi" # Optional
image_pull_secret = "" # Optional
keepalive = "single" # Optional: "single" / "infinite"
# Computed
uid = "..." # k8s UID
}
```
**CRUD:**
- Create: Kubernetes `create` CRD `environments.fission.io`
- Read: Kubernetes `get` CRD `environments.fission.io`
- Update: Kubernetes `update` CRD `environments.fission.io`
- Delete: Kubernetes `delete` CRD `environments.fission.io`
#### 1.5 Resource: fission_package
**Terraform Schema:**
```hcl
resource "fission_package" "hello_pkg" {
name = "hello-pkg" # Required, ForceNew
environment = "python" # Required — имя environment
source_dir = "${path.module}/code" # Optional — директория (provider пакует в zip)
code_path = "${path.module}/hello.zip" # Optional — путь к готовому zip
code_hash = filesha256("...") # Optional — для детекции изменений
build_command = "" # Optional
# Computed
build_status = "succeeded"
build_log = "..."
uid = "..."
}
```
source_dir и code_path — взаимоисключающие.
**CRUD:**
- Create: zip source_dir или читаем code_path → base64 → Kubernetes `create` CRD `packages.fission.io`
- Read: Kubernetes `get` CRD `packages.fission.io`
- Update: Kubernetes `update` CRD `packages.fission.io`
- Delete: Kubernetes `delete` CRD `packages.fission.io`
#### 1.6 Resource: fission_function
**Terraform Schema:**
```hcl
resource "fission_function" "hello" {
name = "hello" # Required, ForceNew
environment = "python" # Required
package_name = fission_package.hello_pkg.name # Required
entrypoint = "main.handler" # Required
# Optional — execution strategy
executor_type = "poolmgr" # "poolmgr" / "newdeploy" / "container"
min_scale = 0
max_scale = 5
target_cpu_percent = 80
specialization_timeout = 120 # сек
# Optional — timeouts и concurrency
function_timeout = 60 # сек
idle_timeout = 120 # сек
concurrency = 500
requests_per_pod = 1
# Optional — resources
min_cpu = "100m"
max_cpu = "200m"
min_memory = "128Mi"
max_memory = "256Mi"
# Optional — secrets и configmaps
secrets = ["my-secret"]
configmaps = ["my-config"]
# Computed
uid = "..."
}
```
**CRUD:**
- Create: Kubernetes `create` CRD `functions.fission.io`
- Read: Kubernetes `get` CRD `functions.fission.io`
- Update: Kubernetes `update` CRD `functions.fission.io`
- Delete: Kubernetes `delete` CRD `functions.fission.io`
#### 1.7 Resource: fission_http_trigger
**Terraform Schema:**
```hcl
resource "fission_http_trigger" "hello_route" {
name = "hello-route" # Required, ForceNew
function = "hello" # Required — имя функции
url = "/hello" # Required — relative URL path
methods = ["GET", "POST"] # Optional, default ["GET"]
create_ingress = false # Optional
host = "fission.kube5s.ru" # Optional — для ingress
prefix = "" # Optional — prefix routing
keep_prefix = false # Optional
# Computed
uid = "..."
}
```
**CRUD:**
- Create: Kubernetes `create` CRD `httptriggers.fission.io`
- Read: Kubernetes `get` CRD `httptriggers.fission.io`
- Update: Kubernetes `update` CRD `httptriggers.fission.io`
- Delete: Kubernetes `delete` CRD `httptriggers.fission.io`
#### 1.8 Build & Publish (hack/build-and-publish.sh)
Адаптировать из sless:
- Имя: terraform-provider-fission
- Build для linux_amd64 и darwin_amd64
- Публикация в Gitea
- Версия из git tag
#### 1.9 Example
```hcl
# examples/hello-python/main.tf
terraform {
required_providers {
fission = {
source = "gitea.services.ngcloud.ru/Nail/fission"
version = "~> 0.1.0"
}
}
}
provider "fission" {
endpoint = "https://fission.kube5s.ru"
token = var.token
namespace = "fission-function"
}
resource "fission_environment" "python" {
name = "python"
image = "ghcr.io/fission/python-env"
version = 3
poolsize = 3
}
resource "fission_package" "hello_pkg" {
name = "hello-pkg"
environment = fission_environment.python.name
source_dir = "${path.module}/code"
}
resource "fission_function" "hello" {
name = "hello"
environment = fission_environment.python.name
package_name = fission_package.hello_pkg.name
entrypoint = "main.handler"
}
resource "fission_http_trigger" "hello_route" {
name = "hello-route"
function = fission_function.hello.name
url = "/hello"
methods = ["GET"]
}
output "function_url" {
value = "https://fission.kube5s.ru/hello"
}
```
```python
# examples/hello-python/code/main.py
def handler(context):
return "Hello from Fission via Terraform!\n"
```
---
### ФАЗА 2 — Дополнительные ресурсы (после MVP)
- **fission_time_trigger** — cron triggers
- **fission_mqt** — message queue triggers (Kafka/NATS)
- **fission_canary** — canary deployments
- **fission_watch_trigger** — kubernetes watch triggers
- **data sources** — для чтения существующих ресурсов
### ФАЗА 3 — Multi-tenancy (после демо)
- JWT→namespace mapping (как в sless)
- Каждый пользователь — свой namespace для функций
- Валидация токена через nubes API
---
## ПРАВИЛА ДЛЯ CODEX
1. **Язык — Go.** Все комментарии — на русском.
2. **terraform-plugin-framework** — НЕ terraform-plugin-sdk/v2.
3. **Комментарии обязательны:** в начале файла (дата, назначение), на каждой функции, на нетривиальной логике.
4. **Именование:** уникальные, осмысленные имена. Запрещены `handler`, `data`, `temp` без контекста.
5. **Не выдумывать** значения, API эндпоинты, поведение. Если не уверен — оставить TODO.
6. **Не совершенствовать** то что уже работает. Делать только то что описано в плане.
7. **Размер client.go:** 500-800 строк. Не раздувать.
8. **Тестирование:** `go build ./...` должен проходить после каждого шага.
9. **Git:** коммит после каждого логического этапа.
---
## ПОРЯДОК ВЫПОЛНЕНИЯ ДЛЯ CODEX
```
Шаг 1: Создать структуру каталогов + go.mod + main.go + .gitignore
Шаг 2: Написать client/client.go (модели данных + HTTP методы)
Шаг 3: Написать provider/provider.go
Шаг 4: Написать resources/environment_resource.go
Шаг 5: go build — должен компилироваться
Шаг 6: Написать resources/package_resource.go (включая zip-логику)
Шаг 7: Написать resources/function_resource.go
Шаг 8: Написать resources/http_trigger_resource.go
Шаг 9: go build — финальная проверка
Шаг 10: Написать hack/build-and-publish.sh
Шаг 11: Создать examples/
Шаг 12: Создать README.md
Шаг 13: Создать .github/copilot-instructions.md
Шаг 14: git add -A && git commit && git push
```
---
## ПРОВЕРКА РЕЗУЛЬТАТА
После завершения codex, мы руками:
1. Соберём: `cd terraform/provider && go build -o terraform-provider-fission`
2. Установим в ~/.terraform.d/plugins/
3. `cd examples/hello-python && terraform init && terraform plan && terraform apply`
4. `curl https://fission.kube5s.ru/hello` → "Hello from Fission via Terraform!"
# Terraform Provider для Fission — Подробный план разработки
# Дата: 2026-04-14
# Агент: GPT 5.3 Codex
# Домен: fission.kube5s.ru
---
## КОНТЕКСТ ПРОЕКТА
### Что делаем
Terraform provider для Fission (https://fission.io) — open-source serverless фреймворка на Kubernetes.
Provider позволяет управлять Fission-ресурсами (environments, packages, functions, triggers) через Terraform.
### Зачем
Fission используется как managed FaaS-сервис в нашем облаке. Terraform — основной инструмент IaC.
Готового провайдера не существует.
### Архитектура
Terraform Provider (Go) -> HTTP -> Fission Controller API (порт 443 через Ingress)
|
Fission делает все сам:
- StorageSvc (PV, позже S3)
- Builder Manager -> Builder Pods
- Executor -> Function Pods
- Router -> HTTP routing
Provider НЕ управляет S3, PV, Kubernetes напрямую. Только HTTP-вызовы к Fission Controller REST API.
### Ключевые решения
- Без proxy/operator — provider напрямую к Fission Controller API
- StorageSvc на PV (local storage) — позже мигрируем на S3
- terraform-plugin-framework (НЕ старый SDKv2)
- Паттерны из существующего sless-провайдера (структура, client, build script)
- Domain: fission.kube5s.ru