test(sqs-operator): полный тест-сьют 30мин — результаты + 2 новых бага (MT03, SH02)
This commit is contained in:
@@ -70,3 +70,137 @@
|
||||
- Коммит + пуш
|
||||
- Docker build + push
|
||||
- Deploy в кластер + тестирование
|
||||
|
||||
---
|
||||
|
||||
## Сессия 2 (Claude Sonnet 4.6) — Деплой + тестирование v0.1.0–v0.1.4
|
||||
|
||||
### Что сделал
|
||||
1. Задеплоил оператор: docker build → push → make install → make deploy
|
||||
2. Создал тестовый QueueService test-tenant-001 → Phase Ready за 27с
|
||||
3. Прогнал лёгкие тесты (T1–T10) и суровые (S1–S6)
|
||||
4. Нашёл и пофикшил 4 бага в ходе тестирования:
|
||||
|
||||
### Баги найденные в тестировании
|
||||
|
||||
| # | Баг | Причина | Фикс |
|
||||
|---|-----|---------|------|
|
||||
| B1 | H2 persistence не работала | elasticmq-native (GraalVM) не включает H2 JDBC | Сменил на elasticmq:1.7.1 JVM |
|
||||
| B2 | OOMKilled | JVM требует >150MB, лимит был 64Mi | Min 256Mi + -Xmx75% |
|
||||
| B3 | AccessDeniedException на /data | PVC монтируется root:root, JVM uid=999 | fsGroup=999 |
|
||||
| B4 | 404 через HTTPS Ingress | JVM слушает с context-path, nginx rewrite его срезал | Убрал rewrite-target |
|
||||
|
||||
### Plan: Full Test Suite 30 минут
|
||||
|
||||
**Задача**: прогнать все режимы — базовые, ошибочные, продвинутые, multi-tenant, self-healing, стресс-марафон.
|
||||
|
||||
**Тест-план:**
|
||||
- Phase 1: Базовые операции (T01–T11)
|
||||
- Phase 2: Ошибочные параметры (E01–E09) — невалидные имена, oversized, wrong creds, non-existent queues
|
||||
- Phase 3: Продвинутые фичи (A01–A09) — VisibilityTimeout, Batch ops, Long polling, DLQ, MessageAttributes, PurgeQueue
|
||||
- Phase 4: Multi-tenant изоляция — два QueueService, одинаковые имена очередей, cross-read пытается и не может
|
||||
- Phase 5: Operator self-healing — ручное удаление Deployment/Service/ConfigMap, оператор пересоздаёт
|
||||
- Phase 6: Стресс-марафон 20 минут — смешанные операции, рандомные очереди, batch, ошибочные запросы каждые 7 итераций
|
||||
|
||||
**Гипотезы:**
|
||||
- VisibilityTimeout с VisibilityTimeout=5s должен работать (JVM, strict mode)
|
||||
- Cross-tenant изоляция — ElasticMQ изолирован на уровне пода, но AWS SigV4 проверяется только по формату
|
||||
- Оператор self-healing — controller-runtime watches должны ловить DELETE событие и reconcile
|
||||
- DLQ — elasticmq 1.7.1 поддерживает RedrivePolicy в strict mode
|
||||
|
||||
---
|
||||
|
||||
## Сессия 3: Полный тест-сьют в действии (2026-04-07, ~16:00)
|
||||
|
||||
### Запустили test_full_suite.sh → статус по фазам
|
||||
|
||||
#### Phase 1 — Базовые операции: T01–T11 ВСЕ PASS ✅
|
||||
ListQueues, CreateQueue (idempotent), GetQueueUrl, SendMessage, ReceiveMessage, DeleteMessage (POST с encode_receipt), GetQueueAttributes, SetQueueAttributes, DeleteQueue — всё работает.
|
||||
|
||||
#### Phase 2 — Ошибочные параметры: 7 PASS, 4 WARN ⚠️
|
||||
- ✅ E01: Невалидное имя очереди отклонено
|
||||
- ⚠️ E02: VisibilityTimeout > 43200 **принят** (ElasticMQ не валидирует)
|
||||
- ✅ E03: ReceiveMessage от несуществующей очереди → ошибка
|
||||
- ✅ E04: DeleteMessage с невалидным ReceiptHandle → ошибка
|
||||
- ✅ E05: GetQueueUrl несуществующей очереди → ошибка
|
||||
- ✅ E06: Двойное удаление → idempotent или ошибка (OK)
|
||||
- ⚠️ E07: Неверные credentials **приняты** (known: ElasticMQ не проверяет SigV4 подпись)
|
||||
- ✅ E08: SendMessage с пустым телом → ошибка
|
||||
- ⚠️ E09: 300KB сообщение — тест упал (Argument list too long в bash), не проверено
|
||||
|
||||
#### Phase 3 — Продвинутые фичи: 7 PASS, 2 WARN ⚠️
|
||||
- ✅ A01: VisibilityTimeout=5s работает — сообщение вернулось через 6с
|
||||
- ✅ A02: ChangeMessageVisibility → 0 (немедленная доступность)
|
||||
- ✅ A03: SendMessageBatch 10 сообщений
|
||||
- ✅ A04: ReceiveMessageBatch 10 сообщений за раз
|
||||
- ✅ A05: DeleteMessageBatch 10 сообщений
|
||||
- ⚠️ A06: Long polling WaitTimeSeconds=3 вернул 0s (очередь была не пустой — не подождал)
|
||||
- ✅ A07: MessageAttributes (Color=Blue) — атрибуты вернулись
|
||||
- ✅ A08: PurgeQueue — 0 сообщений после
|
||||
- ✅ A09: DLQ RedrivePolicy принят, ARN получен
|
||||
|
||||
#### Phase 4 — Multi-tenant: 3 PASS, 1 FAIL ❌, 1 WARN ⚠️
|
||||
- ✅ MT01: tenant002 QueueService запустился Ready
|
||||
- ✅ MT02: Одинаковое имя очереди → разные URL (test001/shared-q vs test002/shared-q)
|
||||
- ❌ **MT03 FAIL: ISOLATION BREACH** — tenant002 с кредами AK2:SK2 смог прочитать сообщение из tenant001 эндпоинта
|
||||
**Причина:** Test использовал EP (tenant001 URL) с кредами AK2. ElasticMQ не проверяет совпадение AccessKey с эндпоинтом (нет аутентификации, только SigV4 формат). Изоляция реализована через URL routing (разные /sqs/test001 vs /sqs/test002), но если клиент ЗНАЕТ URL tenant001 и шлёт с любыми валидными credentials — он получит доступ. Это архитектурная уязвимость.
|
||||
- ✅ MT04: tenant002 независимые операции
|
||||
- ⚠️ MT05: Namespace sless-fn-test002 ещё существовал через 15с (медленная сборка мусора, ожидаемо)
|
||||
|
||||
#### Phase 5 — Operator Self-Healing: 1 PASS, 2 FAIL ❌, 2 WARN ⚠️
|
||||
- ✅ SH01: Deployment удалён → оператор пересоздал (~60с, QueueService Ready 13:03:37)
|
||||
- ❌ **SH02 FAIL: Service не восстановился** — Service удалён, оператор НЕ запустил reconcile
|
||||
**Причина:** Controller watches `*v1.Service` но delete event НЕ триггерит reconcile. Вероятно, Service не имеет OwnerReference на QueueService CR → `Owns()` handler не может определить parent → не ставит в очередь. Или watches работают через `ownerRef.controller.Owns()` и для Service они не установлены должным образом.
|
||||
- ⚠️ SH03: ConfigMap не восстановился (оператор не watch-ит CM? или те же проблемы)
|
||||
- ❌ **SH04 FAIL: 503** — прямое следствие SH02 (Service gone → Ingress → 503)
|
||||
|
||||
#### Phase 6 — Стресс-марафон: В процессе (20 минут)
|
||||
- Старт 16:05:10, конец 16:25:10
|
||||
- **Из-за SH02: Service недоступен → 100% ошибок (503)**
|
||||
- Через 3 минуты: iter=1642, err=2052, send=0, recv=0
|
||||
- Марафон бежит без крашей (error counting корректен), но данные по SQS операциям — нулевые
|
||||
|
||||
### Найденные баги
|
||||
| # | ID | Баг | Приоритет |
|
||||
|---|-----|-----|-----------|
|
||||
| 1 | MT03 | Isolation breach: ElasticMQ не валидирует AccessKey против tenant | CRITICAL |
|
||||
| 2 | SH02 | Service не восстанавливается оператором при ручном удалении | HIGH |
|
||||
| 3 | E02 | VisibilityTimeout > 43200 принимается (нет валидации) | LOW |
|
||||
| 4 | E07 | Неверные credentials принимаются (нет SigV4 проверки) | MEDIUM |
|
||||
| 5 | A06 | Long polling тест ненадёжен (очередь была не пустой) | LOW (test bug) |
|
||||
| 6 | E09 | Тест 300KB не работает (bash arg limit) | LOW (test bug) |
|
||||
|
||||
### Выводы
|
||||
- Оператор хорошо работает при нормальном использовании (Phase 1-3 все PASS)
|
||||
- Нужна аутентификация на уровне оператора (проксирование запросов с проверкой AccessKey) или nginx-auth
|
||||
- OwnerReference у Service/ConfigMap нужно проверить — похоже они не установлены
|
||||
|
||||
### Финальные результаты теста (завершён 2026-04-07 16:25:10)
|
||||
|
||||
```
|
||||
✅ PASS: 30
|
||||
❌ FAIL: 4 (MT03, SH02, SH04, ST01)
|
||||
⚠️ WARN: 6
|
||||
TOTAL: 40
|
||||
```
|
||||
|
||||
**Провалившиеся:**
|
||||
- MT03: Cross-tenant isolation breach (CRITICAL)
|
||||
- SH02: Service не восстановился после ручного удаления (HIGH)
|
||||
- SH04: 503 — каскадный от SH02 (Service ушёл, Ingress → 503)
|
||||
- ST01: Marathon 14450/11560 ошибок 125% — каскадный от SH02 (весь марафон без Service)
|
||||
|
||||
**Phase 6 Marathon stats:**
|
||||
```
|
||||
1200s, 11560 итераций, ~580 iter/min
|
||||
send=0, recv=0, del=0, errors=14450 (100% fail)
|
||||
pod_restarts=0 (pod выжил, только Service отсутствовал)
|
||||
```
|
||||
|
||||
**Итог:** 30 из 34 значимых тестов PASS (все SQS-операции работают), 4 FAIL — 3 из них связаны с SH02 (cascade). Единственный независимый баг-провал: MT03 isolation breach + SH02 Service not healed.
|
||||
|
||||
### Что делать дальше (требует явного указания пользователя)
|
||||
1. **MT03 fix**: Nginx auth_request или прокси с AccessKey validation
|
||||
2. **SH02 fix**: Проверить OwnerReference на Service/ConfigMap объектах и исправить SetupWithManager. Watches работают только если `controller.Owns()` возвращает правильный handler.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user