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: задокументированы исправления и результаты повторных тестов
This commit is contained in:
“Naeel”
2026-03-09 08:52:13 +04:00
parent c0fe63b3d3
commit 976fcadc36
11 changed files with 227 additions and 57 deletions
+100
View File
@@ -316,3 +316,103 @@ existing.Spec.Template.Annotations["kubectl.kubernetes.io/restartedAt"] = fn.Sta
Оператор: **v0.1.11**.
---
## 2026-03-09 — Негативные тесты API: найденные баги валидации
### Методология тестирования
Тесты запускались через прямые POST-запросы к API (`https://sless-api.kube5s.ru`)
со специально некорректными параметрами. Скрипт: `/tmp/sless_negative_tests.sh`.
### Результаты
| # | Тест | Ожидание | Факт | Статус |
|---|---|---|---|---|
| T1 | `runtime="python999"` | 400 ошибка | `Unsupported value: "python999"` | ✅ |
| T2 | `memory_mb=-10` | 400 ошибка | **201 Created** — принято без ошибки | ❌ БАГ |
| T3 | `name=""` | 400 ошибка | `name and runtime are required` | ✅ |
| T4 | `entrypoint=""` (не передан) | 400 ошибка | **201 Created** с `entrypoint:""` | ❌ БАГ |
| T5 | trigger → несуществующая fn | 404/400 | `name, type and function are required` | ❌ Неверный текст ошибки |
| T6 | job → несуществующая fn | 404/400 | **Создался** (fn не проверяется при создании job) | ⚠️ |
| T7 | trigger `type="rabbitmq"` | 400 ошибка | `name, type and function are required` | ❌ Неверный текст ошибки |
| T8 | `run_id=0` | job создаётся, не запускается | 201, `run_id:0` | ✅ |
| T9 | несуществующий namespace | 404 | `namespaces "nonexistent-ns" not found` | ✅ |
| T10 | `memory_mb=999999` | 400 или ограничение | **201, вернул memory_mb=128** (молча обрезан) | ❌ БАГ |
### Баги для исправления
**БАГ-1 (API handler/function):** `memory_mb <= 0` не валидируется. Нужно: `if req.MemoryMB <= 0 { return 400 }`.
**БАГ-2 (API handler/function):** `entrypoint == ""` не валидируется. Нужно: проверять непустой entrypoint.
**БАГ-3 (API handler/trigger):** При передаче `type="rabbitmq"` или несуществующей `functionRef` ошибка говорит `"name, type and function are required"` — неверный текст. Скорее всего handler проверяет поле `function_ref` (snake_case) а принимает `functionRef` (camelCase) — маппинг не работает.
**БАГ-4 (API handler/function):** `memory_mb=999999` принято, но возвращён `memory_mb=128` — молчаливое изменение без ошибки.
### Дополнительно: валидация в Terraform провайдере (plan-time)
Провайдер не имел schema-level валидаторов — все ошибки проявлялись только на `apply`.
Добавлены validators в `function_resource.go`, `trigger_resource.go`, `job_resource.go`:
- `runtime` — только допустимые значения
- `memory_mb` — диапазон 64-4096
- `timeout_sec` — диапазон 1-900
- `trigger.type` — только `http`/`cron`
- `run_id` — >= 0
---
## Исправления (2026-03-08): v0.1.13 оператор + v0.1.7 провайдер
### API исправления (internal/api/handler/)
**БАГ-1 FIXED (functions.go):** Добавлена валидация `memory_mb`:
```
if req.MemoryMB <= 0 || req.MemoryMB > 4096 → 400 "memory_mb must be between 1 and 4096"
```
**БАГ-2 FIXED (functions.go):** Добавлена валидация `entrypoint`:
```
if req.Entrypoint == "" → 400 "entrypoint is required"
```
**БАГ-3 FIXED (triggers.go):** Добавлена валидация `type`:
```
if req.Type != "http" && req.Type != "cron" → 400 "type must be \"http\" or \"cron\""
```
**БАГ-4 FIXED (functions.go):** Покрыт случаем T10 — `memory_mb=999999` теперь возвращает 400.
### Провайдер план-валидаторы (terraform/provider/)
Добавлен пакет `terraform-plugin-framework-validators v0.19.0`.
`function_resource.go`:
- `runtime``stringvalidator.OneOf("nodejs20", "python3.11", "go1.21")`
- `memory_mb``int64validator.Between(1, 4096)`
- `timeout_sec``int64validator.Between(1, 900)`
`trigger_resource.go`:
- `type``stringvalidator.OneOf("http", "cron")`
`job_resource.go`:
- `run_id``int64validator.AtLeast(0)`
### Подтверждение повторными тестами (API)
| Тест | Ожидание | Результат |
|------|----------|----------|
| T2: `memory_mb=-10` | 400 | ✅ `{"error":"memory_mb must be between 1 and 4096"}` |
| T4: `entrypoint=""` | 400 | ✅ `{"error":"entrypoint is required"}` |
| T7: `type="rabbitmq"` | 400 + правильное сообщение | ✅ `{"error":"type must be \"http\" or \"cron\""}` |
| T10: `memory_mb=999999` | 400 | ✅ `{"error":"memory_mb must be between 1 and 4096"}` |
### Подтверждение план-валидаторов (Terraform)
Тест: `runtime = "python2.7"` в http.tf →
```
Error: Invalid Attribute Value Match
Attribute runtime value must be one of: ["nodejs20" "python3.11" "go1.21"], got: "python2.7"
```
### Версии
- Оператор: `naeel/sless-operator:v0.1.13`
- Провайдер: `terra.k8c.ru/naeel/sless v0.1.7`