Commit remaining workspace changes

This commit is contained in:
2026-02-15 19:53:38 +03:00
parent fd149c3d64
commit e6eca7cd50
7 changed files with 26 additions and 16 deletions

1
.gitignore vendored
View File

@@ -29,6 +29,7 @@ config.local.json
# editor settings
settings.json
example/
# ---> macOS
# General

View File

@@ -18,6 +18,10 @@
## Формат JSON для импорта
> Важно: endpoint использует строгий JSON-декодер (`DisallowUnknownFields`).
> Любое неизвестное поле (включая вложенные объекты) приведет к `400 Bad Request`.
> Используйте только `snake_case` ключи из этого руководства.
### Структура верхнего уровня
```json
@@ -42,7 +46,8 @@
### Обязательные поля верхнего уровня
- `collected_at` (string RFC3339, обязательно) - время сбора информации
- `target_host` (string, обязательно) - IP или hostname сервера
- `target_host` (string, опционально) - IP или hostname сервера
- `hardware.board.serial_number` (string, обязательно) - серийный номер сервера/платы
- `source_type` (string, опционально) - тип источника: `api`, `logfile`, `manual`
- `protocol` (string, опционально) - протокол сбора: `redfish`, `ipmi`, `snmp`, `ssh`
- `filename` (string, опционально) - идентификатор источника данных
@@ -532,7 +537,7 @@
### 1. Валидация входных данных
- Проверка наличия обязательных полей: `collected_at`, `target_host`, `hardware`
- Проверка наличия обязательных полей: `collected_at`, `hardware.board.serial_number`
- Проверка формата `collected_at` (RFC3339)
- Проверка наличия `hardware.board.serial_number`
@@ -545,7 +550,7 @@
vendor_serial = board.serial_number
vendor = board.manufacturer (если != "NULL")
model = board.product_name (если != "NULL")
name = target_host (если asset новый) или сохраняется существующее
name = target_host (если передан), иначе `hardware.board.serial_number`
```
**Примечание:** Asset должен быть связан с Project. Если project_id не задан, используется default project для данного импорта.
@@ -660,7 +665,7 @@ firmware_version = {new version}
## API Endpoint для импорта
```http
POST /api/v1/ingest/hardware
POST /ingest/hardware
Content-Type: application/json
{
@@ -675,17 +680,18 @@ Content-Type: application/json
```json
{
"status": "success",
"bundle_id": 12345,
"asset_id": 67,
"bundle_id": "lb_01J...",
"asset_id": "mach_01J...",
"collected_at": "2026-02-10T15:30:00Z",
"duplicate": false,
"summary": {
"components_observed": 15,
"components_created": 2,
"components_updated": 13,
"parts_observed": 15,
"parts_created": 2,
"parts_updated": 13,
"installations_created": 2,
"installations_closed": 1,
"timeline_events_created": 5
"timeline_events_created": 9,
"failure_events_created": 1
}
}
```
@@ -695,8 +701,8 @@ Content-Type: application/json
```json
{
"status": "success",
"bundle_id": 12345,
"asset_id": 67,
"bundle_id": "lb_01J...",
"asset_id": "mach_01J...",
"collected_at": "2026-02-10T15:30:00Z",
"duplicate": true,
"message": "LogBundle with this content hash already exists"
@@ -716,6 +722,13 @@ Content-Type: application/json
}
```
### Частые причины `400 Bad Request`
- Лишние поля в JSON (даже глубоко во вложенных объектах).
- Неверное имя ключа (например, `targetHost` вместо `target_host`).
- Неверный формат даты (`collected_at` должен быть RFC3339).
- Пустой `hardware.board.serial_number`.
---
## Правила автоопределения LOT

View File

@@ -155,10 +155,6 @@ func (h ingestHandlers) handleHardware(w http.ResponseWriter, r *http.Request) {
}
targetHost := strings.TrimSpace(req.TargetHost)
if targetHost == "" {
writeValidationError(w, "target_host", "target_host is required")
return
}
if strings.TrimSpace(req.CollectedAt) == "" {
writeValidationError(w, "collected_at", "collected_at is required")
return