Commit remaining workspace changes
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,6 +29,7 @@ config.local.json
|
||||
|
||||
# editor settings
|
||||
settings.json
|
||||
example/
|
||||
|
||||
# ---> macOS
|
||||
# General
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user