Files
fission-console/doc/AUDIT_PROVIDER_VS_FISSION_2026-06-03.md
T
Naeel fd236d87ea feat: provider audit — builder support, function tuning, source archive
Аудит провайдера vs каноничный Fission. Добавлено:

Environment:
- builder_image, builder_command для Go и языков с build step

Package:
- deploy_type (literal/source) для переключения deployment/source archive
- loadPackageSourceArchive() — zip-упаковка source_dir
- Убран пустой source:{} из literal mode

Function:
- executor_type (poolmgr/newdeploy/container)
- function_timeout, idle_timeout
- min_scale, max_scale для ExecutionStrategy

Все 21 тест пройден. Обратная совместимость проверена.
Документация: doc/AUDIT_PROVIDER_VS_FISSION_2026-06-03.md
2026-04-15 17:46:47 +03:00

18 KiB
Raw Blame History

Аудит: Terraform Provider vs Fission Canonical CRD

Дата: 2026-06-03
Ветка: feat/provider-audit
Предыдущая версия: v0.2.4 (ветка feat/console)

Методология

Сравнение производилось по трём источникам:

  1. Наш код/terraform/provider/internal/resources/*.go и /terraform/provider/internal/client/client.go
  2. Fission CRD types.gogithub.com/fission/fission/pkg/apis/core/v1/types.go (канонические Go-структуры)
  3. Реальные CRD объекты в кластереkubectl get для environments/packages/functions/httptriggers (наши vs CLI-созданные)

1. ENVIRONMENT (fission_environment)

1.1 Что у нас

// environmentResourceModel
ID, Name, Image, Version(default=3), PoolSize(default=3), Namespace, UID

environmentToUnstructured генерирует:

{
  "spec": {
    "version": 3,
    "runtime": { "image": "..." },
    "poolsize": 3
  }
}

1.2 Что делает Fission CLI (fission env create)

Fission CLI (из environment/create.go) создает полный EnvironmentSpec:

{
  "spec": {
    "version": 3,
    "runtime": {
      "image": "ghcr.io/fission/python-env",
      "container": { "name": "env-name", "resources": {} },
      "podspec": { "containers": [{"name": "env-name", "resources": {}}] }
    },
    "builder": {
      "image": "ghcr.io/fission/go-builder",
      "command": "build",
      "container": { "name": "builder", "resources": {} },
      "podspec": { "containers": [{"name": "builder", "resources": {}}] }
    },
    "poolsize": 3,
    "resources": {},
    "imagepullsecret": "",
    "keeparchive": false
  }
}

1.3 Реальное сравнение в кластере

Поле Наш (tf-python-env) CLI (python) Вердикт
spec.version 3 3 OK
spec.runtime.image OK
spec.runtime.container отсутствует {name, resources} ⚠️ Fission заполняет defaults — не критично
spec.runtime.podspec отсутствует {containers} ⚠️ Fission заполняет defaults — не критично
spec.builder ОТСУТСТВУЕТ {image, command, container, podspec} 🔴 КРИТИЧНО для Go
spec.poolsize 3 3 OK
spec.resources отсутствует {} ⚠️ Defaults — не критично
spec.imagepullsecret "" ⚠️ Можно добавить позже
spec.keeparchive false ⚠️ Нужно для JVM — не критично сейчас

1.4 Выводы по Environment

Критичный баг: Невозможно создать environment с builder (нет полей builder_image, builder_command). Это блокирует Go, любой язык с build step.

Что добавить (приоритетно):

  • builder_image (string, optional) → spec.builder.image
  • builder_command (string, optional) → spec.builder.command

Что можно добавить позже:

  • resources (object) → spec.resources
  • imagepullsecret (string) → spec.imagepullsecret
  • keeparchive (bool) → spec.keeparchive
  • runtime_container_name — Fission автозаполняет, мы не ставим, k8s принимает без него

Что НЕ нужно (Fission автозаполняет):

  • spec.runtime.container, spec.runtime.podspec — заливаются defaults на стороне сервера
  • spec.builder.container, spec.builder.podspec — аналогично

2. PACKAGE (fission_package)

2.1 Что у нас

// packageResourceModel
ID, Name, Environment, SourceDir, CodePath, CodeHash, BuildCmd, Namespace, UID, BuildStatus, BuildLog

packageToUnstructured генерирует:

{
  "spec": {
    "deployment": {
      "type": "literal",
      "literal": "base64..."
    },
    "environment": { "name": "...", "namespace": "..." },
    "source": {}
  }
}

2.2 Что делает Fission CLI

Для deploy-only (literal):

{
  "spec": {
    "deployment": {
      "type": "literal",
      "literal": "base64...",
      "checksum": {}
    },
    "environment": { "name": "...", "namespace": "..." },
    "source": { "checksum": {} }
  },
  "status": {
    "buildstatus": "none"
  }
}

Для source-with-builder (Go, Node с build):

{
  "spec": {
    "source": {
      "type": "literal",
      "literal": "base64-of-zip...",
      "checksum": {}
    },
    "environment": { "name": "...", "namespace": "..." },
    "buildcmd": "build"
  },
  "status": {
    "buildstatus": "pending"
  }
}

Для large archives (>256KB):

  • Загрузка через StorageSvc /v1/archive (multipart POST)
  • В CRD сохраняется type: "url", url: "http://storagesvc/v1/archive?id=..."

2.3 Реальное сравнение в кластере

Поле Наш (tf-hello-pkg) CLI (hello-*) Вердикт
spec.deployment.type "literal" "literal" OK
spec.deployment.literal base64 base64 OK
spec.deployment.checksum отсутствует {} ⚠️ K8s принимает без, но лучше добавить
spec.environment OK
spec.source {} (пустая map) {"checksum":{}} 🟡 БАГ: мы ставим пустой source — не мешает, но мусор
spec.buildcmd (если задан) OK
status.buildstatus "none" (от k8s default) "none" OK (k8s сам ставит)

2.4 Что ОТСУТСТВУЕТ для builder pipeline (Go)

Для Go-функций нужен source package (не deployment):

  1. Код упаковывается в zip
  2. zip кодируется в base64 → spec.source.literal (если <256KB)
  3. spec.source.type = "literal"
  4. spec.deployment = пусто
  5. spec.buildcmd = "build" (или пользовательская)
  6. status.buildstatus = "pending" → builder собирает → "succeeded"/"failed"
  7. После build: spec.deployment заполняется builder'ом (url на StorageSvc)

2.5 Выводы по Package

Баг (некритичный): Мы ВСЕГДА ставим "source": {} — пустой объект. Fission ставит "source": {"checksum": {}}. Оба варианта работают, но чистый вариант — не ставить source вообще если нет source archive.

Что добавить (приоритетно):

  • Режим source archive — для Go и языков с build step. Нужно:
    • Флаг/переключатель: deployment-only vs source-with-build
    • Упаковка source_dir в zip → base64 → spec.source.literal
    • Проверка размера <256KB (лимит ArchiveLiteralSizeLimit)
    • Очистка spec.deployment при source mode
    • status.buildstatus = "pending" на create

Что можно добавить позже:

  • StorageSvc загрузка для >256KB архивов
  • spec.source.checksum
  • Поддержка type: "url" (для уже загруженных архивов)

3. FUNCTION (fission_function)

3.1 Что у нас

// functionResourceModel
ID, Name, Environment, PackageName, Entrypoint, Namespace, UID

functionToUnstructured генерирует:

{
  "spec": {
    "environment": { "name": "...", "namespace": "..." },
    "InvokeStrategy": {
      "ExecutionStrategy": { "ExecutorType": "poolmgr" },
      "StrategyType": "execution"
    },
    "package": {
      "packageref": { "name": "...", "namespace": "..." },
      "functionName": "main.main"
    }
  }
}

3.2 Что делает Fission CLI (fission fn create)

{
  "spec": {
    "environment": { "name": "...", "namespace": "..." },
    "InvokeStrategy": {
      "ExecutionStrategy": {
        "ExecutorType": "poolmgr",
        "MaxScale": 0,
        "MinScale": 0,
        "SpecializationTimeout": 120,
        "TargetCPUPercent": 0
      },
      "StrategyType": "execution"
    },
    "package": {
      "packageref": {
        "name": "...",
        "namespace": "...",
        "resourceversion": "6000598"
      },
      "functionName": ""
    },
    "functionTimeout": 60,
    "idletimeout": 120,
    "concurrency": 500,
    "requestsPerPod": 1,
    "resources": {}
  }
}

3.3 Реальное сравнение в кластере

Поле Наш (tf-hello-fn) CLI (fn-js-acc) Вердикт
spec.environment OK
spec.InvokeStrategy.ExecutionStrategy.ExecutorType "poolmgr" "poolmgr" OK
spec.InvokeStrategy.ExecutionStrategy.MaxScale отсутствует 0 ⚠️ Defaults работают, но лучше ставить
spec.InvokeStrategy.ExecutionStrategy.MinScale 0 ⚠️
spec.InvokeStrategy.ExecutionStrategy.SpecializationTimeout 120 ⚠️
spec.InvokeStrategy.ExecutionStrategy.TargetCPUPercent 0 ⚠️ Не критично
spec.InvokeStrategy.StrategyType "execution" "execution" OK
spec.package.packageref.resourceversion отсутствует 🟡 CLI ставит для оптимизации, мы — нет
spec.package.functionName "main.main" "" (или функция) OK
spec.functionTimeout 60 🟡 Полезно для управления таймаутами
spec.idletimeout 120 🟡 Полезно для scale-to-zero
spec.concurrency 500 ⚠️
spec.requestsPerPod 1 ⚠️
spec.resources {} ⚠️

3.4 Выводы по Function

Критичных багов нет. Наши функции работают, потому что k8s/Fission подставляет defaults. НО:

Что добавить (приоритетно):

  • executor_type (string, optional, default="poolmgr") → для newdeploy/container strategies
  • function_timeout (int, optional) → spec.functionTimeout — важно для долгих функций
  • idle_timeout (int, optional) → spec.idletimeout — управление scale-to-zero
  • min_scale / max_scale (int, optional) → ExecutionStrategy — для newdeploy

Что можно добавить позже:

  • concurrency (int) → spec.concurrency
  • requests_per_pod (int) → spec.requestsPerPod
  • specialization_timeout (int) → spec.InvokeStrategy.ExecutionStrategy.SpecializationTimeout
  • resources (object) → CPU/MEM limits
  • secrets, configmaps (list) → volume mounts

4. HTTP TRIGGER (fission_http_trigger)

4.1 Что у нас

// httpTriggerResourceModel
ID, Name, Function, URL, Methods, CreateIngress, Host, Namespace, UID

httpTriggerToUnstructured генерирует:

{
  "spec": {
    "relativeurl": "/tf-hello",
    "methods": ["GET"],
    "functionref": { "type": "name", "name": "tf-hello-fn" },
    "createingress": false
  }
}

4.2 Что делает Fission CLI

{
  "spec": {
    "relativeurl": "/hello",
    "methods": ["GET"],
    "functionref": {
      "type": "name",
      "name": "hello",
      "functionweights": null
    },
    "createingress": false,
    "host": "",
    "ingressconfig": {
      "annotations": null,
      "host": "*",
      "path": "/hello",
      "tls": ""
    },
    "method": "",
    "prefix": ""
  }
}

4.3 Реальное сравнение в кластере

Поле Наш (tf-hello-route) CLI (hello-route) Вердикт
spec.relativeurl OK
spec.methods OK
spec.functionref.type "name" "name" OK
spec.functionref.name OK
spec.functionref.functionweights null Не нужно
spec.createingress OK
spec.host (если пусто) "" Не критично
spec.ingressconfig Частично (host) Полный ⚠️ IngressConfig неполный
spec.method "" Legacy, не нужно
spec.prefix "" ⚠️ Для prefix routing — добавить

4.4 Выводы по HTTPTrigger

Багов нет. Работает корректно. Мелкие расхождения не влияют.

Что можно добавить позже:

  • prefix (string) → spec.prefix — для prefix-based routing
  • keep_prefix (bool) → spec.keepPrefix
  • Полный ingressconfig (annotations, path, tls) — при create_ingress=true
  • function_weights (map) → для canary deployments

5. CLIENT (client.go)

5.1 Оценка

Код корректный. Чистый CRUD через dynamic.Interface:

  • 4 GVR определения (environments, packages, functions, httptriggers)
  • CRUD для каждого: Create/Get/Update/Delete
  • IsNotFound() для обработки 404
  • New() строит config из kubeconfig + context

Расхождений с Fission нет — это наш собственный low-level клиент для работы с CRD.


6. VALIDATION (validation_helpers.go, entrypoint validation)

6.1 Оценка

  • ensureEnvironmentExists корректно (проверяет наличие env перед созданием pkg/fn)
  • ensurePackageExists корректно
  • validateEntrypointAgainstPackageSource⚠️ Проверяет только Python def funcname(. Не проверяет:
    • Node: module.exports или export function
    • Go: plugin symbol
    • PHP: function handler(
    • Ruby: def handler

Это допустимо — избыточная валидация может мешать. Лучше валидировать только точно известные паттерны.


7. СВОДНАЯ ТАБЛИЦА ПРИОРИТЕТОВ

🔴 Критично (блокирует функционал)

# Ресурс Проблема Решение
1 Environment Нет builder support Добавить builder_image, builder_command
2 Package Нет source archive mode Добавить zip-упаковку source_dir → spec.source.literal

🟡 Важно (улучшает пользовательский опыт)

# Ресурс Проблема Решение
3 Function Захардкожен poolmgr Добавить executor_type с optional default
4 Function Нет пользовательских таймаутов Добавить function_timeout, idle_timeout
5 Function Нет min/max scale Добавить min_scale, max_scale
6 Package Пустой source: {} мусор Убрать пустой source из payload

Не критично (можно позже)

# Ресурс Проблема
7 Environment Нет resources, imagepullsecret, keeparchive
8 Function Нет concurrency, requestsPerPod, resources, secrets, configmaps
9 HTTPTrigger Нет prefix, keepPrefix, полного ingressconfig
10 Package Нет StorageSvc загрузки (>256KB)
11 Package Нет checksum

8. ПЛАН РЕАЛИЗАЦИИ (предлагаемый)

Этап 1: Builder support (Environment + Package)

environment_resource.go:

  • Добавить поля builder_image и builder_command в модель и schema
  • Добавить spec.builder в environmentToUnstructured (если builder_image задан)
  • Обновить unstructuredToEnvironmentModel для чтения builder полей

package_resource.go:

  • Добавить поле deploy_type (string: "literal" или "source", default "literal")
  • При deploy_type = "source": zip source_dir → base64 → spec.source.literal, spec.deployment пустой
  • Убрать пустой "source": {} при deploy_type = "literal"
  • Добавить base64 size check (<256KB) при literal mode

Этап 2: Function tuning

function_resource.go:

  • Добавить optional поля: executor_type, function_timeout, idle_timeout, min_scale, max_scale
  • Обновить functionToUnstructured для заполнения ExecutionStrategy полностью
  • Обновить unstructuredToFunctionModel для чтения новых полей

Этап 3: Мелкие улучшения

  • HTTPTrigger: prefix, keepPrefix
  • Package: checksum
  • Environment: resources, imagepullsecret

9. ВЫВОД

Наш провайдер работает корректно для основного сценария: Python/Node/PHP/Ruby/Perl literal deployment + poolmgr executor. Все критические поля (version, runtime.image, poolsize, deployment.literal, functionName, relativeurl, methods) генерируются правильно.

Главные пробелы:

  1. Нет builder support → Go и любые compiled languages не работают через builder pipeline
  2. Нет source archive → только deployment-only (literal из одного файла)
  3. Function executor hardcoded to poolmgr → нет newdeploy/container strategy
  4. Нет пользовательских таймаутов

Ни один из пробелов не является ошибкой в существующем коде — это недостающий функционал. То, что есть, соответствует канону Fission.