doc: CODEX_PLAN.md — подробный план для GPT 5.3 Codex
This commit is contained in:
@@ -0,0 +1,711 @@
|
|||||||
|
# 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.
|
||||||
|
Готового провайдера не существует (единственная попытка — https://github.com/sambuysse/terraform-provider-fission — заброшена 5 лет назад, реализован только 1 ресурс).
|
||||||
|
|
||||||
|
### Архитектура
|
||||||
|
```
|
||||||
|
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.
|
||||||
|
Fission сам хранит код (StorageSvc), собирает (Builder), запускает (Executor), маршрутизирует (Router).
|
||||||
|
|
||||||
|
### Ключевые решения
|
||||||
|
- Без proxy/operator — provider напрямую к Fission Controller API
|
||||||
|
- 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 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 + Controller
|
||||||
|
|
||||||
|
**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** Проверить REST API:
|
||||||
|
```bash
|
||||||
|
curl -H "Authorization: Bearer $TOKEN" https://fission.kube5s.ru/v2/environments
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ФАЗА 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)
|
||||||
|
HTTP-клиент к Fission Controller API.
|
||||||
|
|
||||||
|
**Структура:**
|
||||||
|
```go
|
||||||
|
package client
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
httpClient *http.Client
|
||||||
|
endpoint string // https://fission.kube5s.ru
|
||||||
|
token string // Bearer JWT
|
||||||
|
namespace string // namespace для функций (дефолт "fission-function")
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(endpoint, token, namespace string) *Client
|
||||||
|
|
||||||
|
// 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
|
||||||
|
```
|
||||||
|
|
||||||
|
**Формат запросов:**
|
||||||
|
- Content-Type: application/json (для CRUD)
|
||||||
|
- Content-Type: multipart/form-data (для upload в Package)
|
||||||
|
- Authorization: Bearer <token>
|
||||||
|
- Namespace в metadata объекта
|
||||||
|
|
||||||
|
**ВАЖНО:** Размер client.go — целевой ~500-800 строк. Никакого S3, kaniko, polling.
|
||||||
|
|
||||||
|
#### 1.3 Provider (internal/provider/provider.go)
|
||||||
|
|
||||||
|
**Атрибуты провайдера:**
|
||||||
|
```hcl
|
||||||
|
provider "fission" {
|
||||||
|
endpoint = "https://fission.kube5s.ru" # URL Fission Controller (env: FISSION_ENDPOINT)
|
||||||
|
token = "xxx" # Bearer JWT (env: FISSION_TOKEN)
|
||||||
|
namespace = "fission-function" # Namespace (env: FISSION_NAMESPACE, default: "fission-function")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Configure():**
|
||||||
|
1. Прочитать endpoint (config → env FISSION_ENDPOINT → default "http://localhost:8888")
|
||||||
|
2. Прочитать token (config → env FISSION_TOKEN → пусто = без auth)
|
||||||
|
3. Прочитать namespace (config → env FISSION_NAMESPACE → default "fission-function")
|
||||||
|
4. Создать 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: POST /v2/environments → JSON body
|
||||||
|
- Read: GET /v2/environments/{name}?namespace={ns}
|
||||||
|
- Update: PUT /v2/environments/{name} → JSON body
|
||||||
|
- Delete: DELETE /v2/environments/{name}?namespace={ns}
|
||||||
|
|
||||||
|
#### 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 → POST /v2/packages (multipart) → poll build_status
|
||||||
|
- Read: GET /v2/packages/{name}
|
||||||
|
- Update: PUT /v2/packages/{name} (перезаливаем zip)
|
||||||
|
- Delete: DELETE /v2/packages/{name}
|
||||||
|
|
||||||
|
#### 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: POST /v2/functions → JSON body
|
||||||
|
- Read: GET /v2/functions/{name}
|
||||||
|
- Update: PUT /v2/functions/{name}
|
||||||
|
- Delete: DELETE /v2/functions/{name}
|
||||||
|
|
||||||
|
#### 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: POST /v2/triggers/http → JSON body
|
||||||
|
- Read: GET /v2/triggers/http/{name}
|
||||||
|
- Update: PUT /v2/triggers/http/{name}
|
||||||
|
- Delete: DELETE /v2/triggers/http/{name}
|
||||||
|
|
||||||
|
#### 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
|
||||||
Reference in New Issue
Block a user