cairnr01probe
5faec45a04
feat: provider v0.1.9 — namespace hardcoded in client, removed from provider schema and all examples
2026-03-09 15:27:55 +04:00
cairnr01probe
17d32fcb39
feat: provider v0.1.9 — namespace removed from resources, moved to provider block
2026-03-09 15:12:07 +04:00
cairnr01probe
0aaeb47b3b
feat: operator v0.1.16 — job stdout -> status.Message (feature B)
...
- FunctionJobReconciler: added KubeClient field (kubernetes.Interface)
- getJobPodOutput(): reads pod logs via typed client after job succeeds
- main.go: inject kubernetes.NewForConfigOrDie into FunctionJobReconciler
- rbac.yaml: add pods/pods/log get/list/watch permissions
- examples/simple-python/: job->function chain demo (Python)
- examples/simple-node/: job->function chain demo (Node.js)
sless_job.X.message now contains the return value of the function
2026-03-09 14:50:06 +04:00
cairnr01probe
53d9fa6e74
feat: outputs — статус init-джобов для пользователя без kubectl
2026-03-09 14:09:55 +04:00
cairnr01probe
381ec44852
fix: operator v0.1.15 — обновлять Env при изменении функции
...
function_controller.go: при update deployment обновлять не только Image,
но и Env целиком. Без этого изменение entrypoint или env_vars не применялось
в уже существующем Deployment — поды продолжали стартовать со старым
SLESS_ENTRYPOINT и падали с FileNotFoundError.
2026-03-09 10:26:54 +04:00
cairnr01probe
cefef54936
refactor: уникальные имена функций-обработчиков
...
handle() → run_sql() (sql_runner.py, entrypoint: sql_runner.run_sql)
handle() → crud() (notes_crud.py, entrypoint: notes_crud.crud)
handle() → list_notes() (notes_list.py, entrypoint: notes_list.list_notes)
2026-03-09 10:14:36 +04:00
cairnr01probe
7dffc61c84
refactor: notes-python — описательные имена файлов/ресурсов + комментарии
...
Python файлы:
- handler.py → sql_runner.py (entrypoint: sql_runner.handle)
- handler.py → notes_crud.py (entrypoint: notes_crud.handle)
- handler.py → notes_list.py (entrypoint: notes_list.handle)
TF ресурсы переименованы:
- sless_function.notes → sless_function.notes_crud
- sless_trigger.notes_http → sless_trigger.notes_crud_http
- sless_job.create_table → sless_job.notes_table_init
- sless_job.create_index → sless_job.notes_index_init
- archive_file.notes → archive_file.notes_crud_zip
- archive_file.sql_runner → archive_file.sql_runner_zip
- archive_file.notes_list → archive_file.notes_list_zip
Добавлены подробные комментарии во все .tf файлы
2026-03-09 10:10:43 +04:00
cairnr01probe
8602b023fc
fix: provider v0.1.8 — wait for trigger URL after create
...
trigger_resource.go: after CreateTrigger, if URL is empty (HTTP trigger),
retry GetTrigger every 2s up to 30s until controller sets status.URL.
Without this, URL in terraform state was always empty after apply.
2026-03-09 09:58:37 +04:00
cairnr01probe
88a0fb9db6
feat: notes-python CRUD example + runtime path/query forwarding
...
- invoke.go: forward sub-path and query string to function pods
- server.js v0.1.2: add _path, _query, _method to event
- server.py v0.1.1: add _path, _query, _method to event
- upload.go: bump runtime versions (nodejs20:v0.1.2, python3.11:v0.1.1)
- examples/notes-python: CRUD notes via sub-path routing
- sql-runner: generic SQL executor for DDL jobs
- notes: CRUD router (/add, /update, /delete)
- notes-list: SELECT all notes
- init.tf: create TABLE + INDEX on apply
2026-03-09 09:51:56 +04:00
cairnr01probe
0066d9c0f9
refactor: pg-query — ресурсы вынесены в pg-query.tf, main.tf только провайдеры
2026-03-09 09:11:31 +04:00
cairnr01probe
237a636097
refactor: pg-query — code/ исходники, dist/ zip, archive_file datasource
2026-03-09 09:07:57 +04:00
cairnr01probe
e8497644e6
refactor: hello-node — zip-файлы в dist/, исходники остаются в code/
2026-03-09 09:03:00 +04:00
cairnr01probe
53e82ea47b
fix: pg-query — filesha256(handler.py) вместо filemd5(handler.zip), версия провайдера 0.1.7
2026-03-09 08:56:19 +04:00
cairnr01probe
976fcadc36
fix: API validation + Terraform plan-time validators
...
API (operator v0.1.13):
- functions.go: добавлена валидация entrypoint (не пустой) и
memory_mb (1-4096). Фиксирует БАГ-1/2/4 из негативных тестов.
- triggers.go: добавлена валидация type (только 'http'/'cron').
Фиксирует БАГ-3 (неверное сообщение об ошибке).
Провайдер (v0.1.7):
- Добавлен пакет terraform-plugin-framework-validators v0.19.0
- function_resource: runtime OneOf, memory_mb 1-4096, timeout_sec 1-900
- trigger_resource: type OneOf(http, cron)
- job_resource: run_id AtLeast(0)
- examples/main.tf: обновлена версия до ~> 0.1.7
doc/errors/log.md: задокументированы исправления и результаты повторных тестов
2026-03-09 08:52:13 +04:00
cairnr01probe
c0fe63b3d3
fix: откат 409-fallback из клиента провайдера (provider v0.1.6 не опубликован с изменениями)
...
- terraform/provider/internal/client/client.go: откат 409 fallback для
CreateFunction, CreateTrigger, CreateJob — import не нужен в данном провайдере,
409 должен быть ошибкой
- examples/hello-node/main.tf: версия провайдера ~> 0.1.6 (опубликована
без изменений клиента — только исходная версия кода)
- examples/hello-node/job.tf: run_id=9, numbers=[100,200,300]
Тесты пройдены: plan(no-changes), state-rm+apply, code update, run_id++, destroy+apply
2026-03-09 08:17:17 +04:00
cairnr01probe
f8fe3835a4
fix: уникальный image tag per build вместо :latest (operator v0.1.12)
...
- internal/builder/builder.go: ImageRef() теперь использует sha256(s3Key)[:12]
как тег образа вместо :latest
Пример: naeel/sless-default-hello-http:d431de61e2c9
- controllers/function_controller.go: убран хак с restartedAt аннотацией —
больше не нужен, новый тег = kubelet всегда пул-ит новый образ
- deployments/k8s/operator.yaml: обновлён до v0.1.12
- doc/progress.md: версия обновлена
Преимущества уникального тега:
- imagePullPolicy: IfNotPresent работает корректно
- Rollback к предыдущей версии возможен (теги не перезаписываются)
- Нет race condition при параллельных сборках
2026-03-08 21:05:35 +04:00
cairnr01probe
79719e078d
fix: rollout restart после kaniko rebuild (operator v0.1.11)
...
- controllers/function_controller.go: в ensureDeployment добавить аннотацию
kubectl.kubernetes.io/restartedAt = fn.Status.LastBuiltAt при обновлении
существующего Deployment — принудительный rolling restart после каждой сборки
- deployments/k8s/operator.yaml: образ обновлён до v0.1.11
- doc/errors/log.md: задокументирована причина и решение
- doc/decisions/log.md: добавлено правило restartedAt + :latest
- doc/progress.md: версия обновлена до v0.1.11
Причина бага: imagePullPolicy=IfNotPresent + :latest — kubelet кешировал
старый образ, pod не рестартовал после успешного kaniko build.
2026-03-08 20:55:47 +04:00
cairnr01probe
df540e6b81
docs: обновление doc/ по итогам сессии 2026-03-08
2026-03-08 20:36:16 +04:00
cairnr01probe
99ef17d62f
fix: убрать UseStateForUnknown с image_ref, provider v0.1.5
2026-03-08 20:34:00 +04:00
cairnr01probe
b69f795eb1
config: REGISTRY_HOST переключён с Harbor на DockerHub (naeel)
2026-03-08 20:18:59 +04:00
cairnr01probe
461ac096f9
fix: FunctionJob зависал в Running — добавлен RequeueAfter polling
2026-03-08 12:13:15 +04:00
cairnr01probe
e6abc490cd
fix: imagePullSecrets, SLESS_ENTRYPOINT, registry secret propagation
...
- function_controller: добавить RegistrySecret + OperatorNamespace, копировать
sless-registry-auth в sless-fn-<ns>, выставлять imagePullSecrets в Deployment,
также обновлять imagePullSecrets при reconcile
- functionjob_controller: fnEnvVars включает SLESS_ENTRYPOINT, runner читает его
- server.js + server.py: читать SLESS_ENTRYPOINT вместо hardcoded handler.js/py
- rbac.yaml: добавить права на secrets
- operator.yaml: v0.1.8
- main.go: передать RegistrySecret + OperatorNamespace в FunctionReconciler
2026-03-08 11:15:48 +04:00
cairnr01probe
d67b9745a8
feat: trigger.enabled + job.run_id lifecycle control (operator v0.1.6, provider v0.1.4)
...
- TriggerSpec.Enabled bool (default=true): enabled=false масштабирует Deployment до 0
- FunctionJobSpec.RunID int64 (default=0): run_id=0 = skip, >0 = run
- API: PATCH /v1/namespaces/{ns}/triggers/{name} (UpdateTrigger)
- Provider: enabled attribute (Optional, Computed, in-place update)
- Provider: run_id attribute (Optional, Computed, default=0, RequiresReplace)
- operator image: naeel/sless-operator:v0.1.6
- provider: terra.k8c.ru/naeel/sless v0.1.4
2026-03-08 10:10:32 +04:00
cairnr01probe
8fb0ef5ea1
ops: switch registry from DockerHub to Harbor (pearlharbor.registryk8s.services.ngcloud.ru/sless)
2026-03-08 09:28:18 +04:00
cairnr01probe
4f0b8fb486
examples/hello-node: two different functions (http greeting, job sum)
2026-03-08 09:22:38 +04:00
cairnr01probe
00cd3d181b
examples/hello-node: move handler to code/, split http.tf and job.tf
2026-03-08 09:14:34 +04:00
cairnr01probe
7f5a881c8a
examples: switch hello-node to sless_job (one-shot run)
2026-03-07 23:05:09 +04:00
cairnr01probe
2ebff6c05a
examples: auto-zip via hashicorp/archive, remove manual zip step
2026-03-07 18:46:23 +04:00
cairnr01probe
d6212d1cee
doc: обновлена документация — FunctionJob, proxy /fn/, operator v0.1.5, provider v0.1.3
2026-03-07 18:40:36 +04:00
cairnr01probe
2ee9cae6d2
feat: proxy /fn/{namespace}/{name} — обход wildcard DNS
...
Проблема: wildcard DNS *.fn.kube5s.ru недоступен.
Решение: прокси через sless-api.kube5s.ru/fn/{ns}/{name}.
- handler/invoke.go: прокси к Service функции внутри кластера
- router.go: /fn/ без auth токена, /v1/ с auth (gorilla Use())
- config.go: поле ExternalURL (EXTERNAL_URL env)
- trigger_controller.go: если ExternalURL задан — URL = ExternalURL/fn/{ns}/{fn}
иначе fallback: Ingress + поддомен (прежнее поведение)
- operator.yaml: EXTERNAL_URL=https://sless-api.kube5s.ru , image v0.1.5
Оператор v0.1.5 задеплоен.
E2E: curl https://sless-api.kube5s.ru/fn/default/hello-node → {"message":"Hello, Naeel! (nodejs20)"}
2026-03-07 18:36:03 +04:00
cairnr01probe
a6bc67de05
feat: configurable timeouts for sless_function and sless_job
...
- sless_function: build_timeout_sec (optional, default 300s = 5 min)
- sless_job: wait_timeout_sec (optional, default 600s = 10 min)
- provider v0.1.3 published to terra.k8c.ru
2026-03-07 17:49:07 +04:00
cairnr01probe
f405596d42
feat: sless_job terraform resource + jobs REST API
...
Operator (v0.1.4):
- internal/api/handler/jobs.go: CreateJob/GetJob/DeleteJob handlers
- internal/api/router.go: POST/GET/DELETE /v1/namespaces/{ns}/jobs/{name}
Terraform provider (v0.1.2):
- client.go: JobRequest/JobResponse + CreateJob/GetJob/DeleteJob/WaitJobDone
- resources/job_resource.go: sless_job resource (Create blocks until Succeeded/Failed)
- provider.go: register NewJobResource
Deploy:
- operator:v0.1.4 deployed and running in cluster
- provider v0.1.2 published to terra.k8c.ru
2026-03-07 17:43:26 +04:00
cairnr01probe
22685a72a9
feat: add FunctionJob CRD for one-shot function runs
...
- api/v1alpha1/job_types.go: new CRD FunctionJob (Pending/Running/Succeeded/Failed)
- controllers/functionjob_controller.go: reconciler creates k8s Job from FunctionRef + EventJSON
- zz_generated.deepcopy.go: DeepCopy methods for FunctionJob types
- config/crd/bases: generated CRD YAML, applied to cluster
- main.go: register FunctionJobReconciler
- rbac.yaml: add functionjobs permissions
- operator.yaml: v0.1.2 -> v0.1.3
- operator:v0.1.3 deployed and running in cluster
2026-03-07 17:20:21 +04:00
cairnr01probe
d6dc676dfd
doc: document operator deploy, nodejs20 runtime, Dockerfile fixes, go.mod fix
2026-03-07 17:02:28 +04:00
cairnr01probe
22c7e92590
feat: add nodejs20 runtime
...
- runtimes/nodejs20/server.js: HTTP wrapper, exports.handle(event)
- runtimes/nodejs20/Dockerfile: node:20-alpine base image
- naeel/sless-runtime-nodejs20:v0.1.0 pushed to DockerHub
- upload.go: nodejs20 in runtimeBaseImage(), package.json → npm install
- upload.go: python3.11 now uses v0.1.0 tag (no more latest)
- operator v0.1.2 deployed in cluster
- E2E: hello-node-default.fn.kube5s.ru → {"message":"Hello, Naeel! (nodejs20)"}
2026-03-07 17:00:29 +04:00
cairnr01probe
97f38c1f72
chore: switch pg-query example to remote endpoint sless-api.kube5s.ru
2026-03-07 16:50:05 +04:00
cairnr01probe
b338192cbf
chore: go mod tidy — fix direct/indirect annotations
2026-03-07 16:31:54 +04:00
cairnr01probe
3fdf342115
feat: deploy operator in-cluster v0.1.1
...
- Dockerfile: fix golang 1.23→1.25, add internal/ + migrations/ to image
- deployments/k8s/operator.yaml: ConfigMap + Secret + Deployment + Service + Ingress
- Ingress: sless-api.kube5s.ru, TLS via cert-manager letsencrypt-prod
- naeel/sless-operator:v0.1.1 — running in namespace sless
- E2E: https://sless-api.kube5s.ru → HTTP/2 200
2026-03-07 16:30:14 +04:00
cairnr01probe
0856fbc454
doc: decisions — scale-to-zero v2, replicas todo, postgres optional
2026-03-07 11:10:37 +04:00
cairnr01probe
0268ef0523
fix: multiple fixes + pg-query e2e passed
...
upload.go:
- Update → Patch (MergeFrom) to avoid resourceVersion conflict when operator
modifies Function between Get() and Update()
terraform provider v0.1.1:
- trigger_resource.go: trToModel returns StringNull() for empty schedule
(fixes 'provider produced inconsistent result' for http triggers)
- main.go: bump version to 0.1.1
examples/pg-query:
- handler.py: fix column name started_at → created_at (matches migrations/001)
- main.tf: pin provider to ~> 0.1.1
.gitignore: add terraform state, lock, .terraform/, handler.zip
doc/errors/log.md: documented all 5 errors from this session:
- resourceVersion conflict → use Patch
- terraform inconsistent result for schedule → StringNull
- terraform import not implemented → delete+recreate workaround
- wrong column name → check migrations before writing handlers
- Deployment not restarting after image rebuild → rollout restart / TODO: restartedAt annotation
doc/progress.md: terraform apply e2e ✅
2026-03-07 10:52:29 +04:00
cairnr01probe
4e59d79884
feat: add pg-query example + upload.go supports requirements.txt
...
- examples/pg-query/handler.py: Python function querying PostgreSQL invocations table
- examples/pg-query/requirements.txt: psycopg2-binary==2.9.9
- examples/pg-query/main.tf: terraform config for sless_function + sless_trigger
- internal/api/handler/upload.go: generateDockerfile() now accepts hasRequirements bool
- scans zip for requirements.txt at upload time
- adds RUN pip install --no-cache-dir to Dockerfile when requirements.txt present
- doc/progress.md: updated status for pg-query e2e task
2026-03-07 10:30:50 +04:00
cairnr01probe
dc7542148e
docs: обновить всю документацию по результатам сессии 2026-03-07
...
- infrastructure/overview.md: исправить S3 URL, Container Registry (DockerHub),
namespace sless, Terraform Registry terra.k8c.ru
- errors/log.md: добавить 3 ошибки — kaniko S3 scheme, бесконечный цикл сборки,
docker credStore desktop.exe
- decisions/log.md: добавить решения — DockerHub, terraform провайдер в той же
репе, WaitReady паттерн, code_hash для версионирования кода
- api/design.md: обновить базовый URL, добавить upload endpoint с описанием
процесса, исправить runtime список
2026-03-07 10:26:13 +04:00
cairnr01probe
19c9e016a8
feat: Terraform провайдер sless v0.1.0 + обновление doc/progress.md
...
Независимый Go-модуль terraform/provider/ для управления функциями через REST API.
Ресурсы:
- sless_function: CRUD + upload zip + WaitReady (kaniko build 5 мин)
- sless_trigger: CRUD (http/cron)
Компоненты:
- internal/client/client.go — HTTP-клиент, готов к переносу в nubes
- internal/provider/provider.go — паттерн идентичен nubes NubesProvider
- internal/resources/ — function_resource.go, trigger_resource.go
- hack/build-and-publish.sh — GPG-подпись + mc upload в S3
Опубликовано: terra.k8c.ru/naeel/sless v0.1.0
Проверено: terraform init успешен
2026-03-07 10:23:52 +04:00
cairnr01probe
4115e0f172
fix: бесконечный цикл сборки — idempotency guard через last-built-s3key аннотацию
...
Проблема: upload handler сбрасывал phase в Pending ПОСЛЕ того как
контроллер уже выставил Building → бесконечный цикл (94 job'а).
Решение:
- controllers/function_controller.go: startBuild сначала ставит аннотацию
last-built-s3key = spec.S3Key (idempotency guard), потом status.
Reconcile стартует сборку только если spec.S3Key != last-built-s3key.
- handler/upload.go: убран Status().Update() — контроллер сам управляет фазой.
- builder.go: IsAlreadyExists при создании job не ошибка (parallel reconcile).
2026-03-07 09:50:24 +04:00
cairnr01probe
8bae4ca69c
fix: kaniko S3 endpoint — добавить https:// схему и S3_FORCE_PATH_STYLE=true
...
Kaniko AWS SDK требует полный URL с протоколом.
Ceph не поддерживает virtual-hosted style — нужен path style.
2026-03-07 09:39:53 +04:00
cairnr01probe
74458f848d
feat: upload endpoint POST /v1/namespaces/{ns}/functions/{name}/upload
...
- s3/client.go: Bucket() accessor + UploadContext() для tar.gz build context
- handler/upload.go: принимает zip, генерирует Dockerfile (FROM naeel/sless-runtime-{runtime}),
перепаковывает в tar.gz, загружает в S3, обновляет Function CRD → kaniko запускается
- router.go: маршрут POST .../upload зарегистрирован
2026-03-07 09:36:32 +04:00
cairnr01probe
c61e822308
feat: python3.11 base runtime image + DockerHub registry support
...
- runtimes/python3.11/: Dockerfile + server.py (HTTP wrapper на :8080)
- builder.go: RegistrySecret field, volume mount docker-creds для kaniko, убран --skip-tls-verify
- config.go: добавлен RegistrySecret (env REGISTRY_SECRET, default sless-registry-auth)
- main.go: передаём RegistrySecret в builder.Config
- hack/create-registry-secret.sh: создаёт k8s Secret из DockerHub токена
Образ наружу: naeel/sless-runtime-python3.11:latest (DockerHub)
K8s secret: sless-registry-auth в namespace sless
2026-03-07 09:32:59 +04:00
cairnr01probe
33ee17729f
docs: обновить progress.md по фактическому состоянию
...
- отражён реальный статус всех компонентов кода
- отражено состояние кластера (CRD, RBAC, postgres)
- добавлен список что ещё не сделано
- добавлены deployments/k8s/rbac.yaml, postgres.yaml
2026-03-07 08:57:54 +04:00
cairnr01probe
43e7d0ea48
feat: REST API (gorilla/mux + slog) + trigger controller + main.go wiring
...
- controllers/trigger_controller.go: полная реализация, HTTP->Ingress+Service, Cron->CronJob
- internal/config: добавлены IngressHost, APIToken
- internal/api/router.go: gorilla/mux роутер /v1/namespaces/{ns}/...
- internal/api/handler/: functions, triggers, invocations, base handler с slog
- internal/api/middleware/: auth (Bearer token) + logging (slog)
- main.go: запуск operator + HTTP сервера параллельно
- go.sum: добавлен gorilla/mux v1.8.1
2026-03-07 08:46:10 +04:00
cairnr01probe
5f25f61948
chore: ignore .s3cfg* files
2026-03-07 08:28:33 +04:00