fix(iot): telemetry_topic в ответе + нормализация metadata
- iotDeviceResponse: добавлено telemetry_topic = «ns/telemetry/device» (явный
топик для Terraform; topic_prefix = «ns/» был неполным).
- metadata теперь без omitempty и всегда «{}» при пустом — убран drift
«{}» против null (ревью 2026-10-10, «Что стабилизировать для Terraform»).
This commit is contained in:
@@ -46,25 +46,40 @@ type iotDeviceResponse struct {
|
|||||||
MQTTUsername string `json:"mqtt_username,omitempty"`
|
MQTTUsername string `json:"mqtt_username,omitempty"`
|
||||||
MQTTPassword string `json:"mqtt_password,omitempty"`
|
MQTTPassword string `json:"mqtt_password,omitempty"`
|
||||||
TopicPrefix string `json:"topic_prefix,omitempty"`
|
TopicPrefix string `json:"topic_prefix,omitempty"`
|
||||||
LastConnected string `json:"last_connected,omitempty"`
|
// TelemetryTopic — полный MQTT-топик телеметрии устройства «ns/telemetry/device».
|
||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
// Явное поле (в отличие от topic_prefix = «ns/»): Terraform должен знать
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
// точный топик для публикации/подписки (ревью 2026-10-10).
|
||||||
|
TelemetryTopic string `json:"telemetry_topic"`
|
||||||
|
LastConnected string `json:"last_connected,omitempty"`
|
||||||
|
// Metadata — без omitempty: всегда присутствует в ответе. Пустой → «{}»,
|
||||||
|
// иначе Terraform видел бы drift «{}» против null (ревью 2026-10-10).
|
||||||
|
Metadata map[string]string `json:"metadata"`
|
||||||
|
CreatedAt string `json:"created_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// deviceToResponse конвертирует устройство из БД в ответ API.
|
// deviceToResponse конвертирует устройство из БД в ответ API.
|
||||||
// password отдаётся только если непустая — только на создании, при чтении
|
// password отдаётся только если непустая — только на создании, при чтении
|
||||||
// передаётся пустая строка (пароль повторно не показывается).
|
// передаётся пустая строка (пароль повторно не показывается).
|
||||||
func deviceToResponse(d *store.Device, password string) iotDeviceResponse {
|
func deviceToResponse(d *store.Device, password string) iotDeviceResponse {
|
||||||
|
// Пустой metadata нормализуем в «{}» (а не null/omit): иначе Terraform видел
|
||||||
|
// бы drift между «{}» и отсутствующим полем. nil-карту не мутируем — подменяем
|
||||||
|
// только для сериализации ответа.
|
||||||
|
metadata := d.Metadata
|
||||||
|
if metadata == nil {
|
||||||
|
metadata = map[string]string{}
|
||||||
|
}
|
||||||
|
|
||||||
resp := iotDeviceResponse{
|
resp := iotDeviceResponse{
|
||||||
Name: d.Name,
|
Name: d.Name,
|
||||||
Namespace: d.Namespace,
|
Namespace: d.Namespace,
|
||||||
DeviceID: d.DeviceID,
|
DeviceID: d.DeviceID,
|
||||||
Enabled: d.Enabled,
|
Enabled: d.Enabled,
|
||||||
Phase: d.Phase,
|
Phase: d.Phase,
|
||||||
MQTTUsername: d.Namespace + "_" + d.DeviceID,
|
MQTTUsername: d.Namespace + "_" + d.DeviceID,
|
||||||
MQTTPassword: password,
|
MQTTPassword: password,
|
||||||
TopicPrefix: d.Namespace + "/",
|
TopicPrefix: d.Namespace + "/",
|
||||||
Metadata: d.Metadata,
|
TelemetryTopic: d.Namespace + "/telemetry/" + d.DeviceID,
|
||||||
|
Metadata: metadata,
|
||||||
}
|
}
|
||||||
if d.LastConnected != nil && !d.LastConnected.IsZero() {
|
if d.LastConnected != nil && !d.LastConnected.IsZero() {
|
||||||
resp.LastConnected = d.LastConnected.UTC().Format(time.RFC3339)
|
resp.LastConnected = d.LastConnected.UTC().Format(time.RFC3339)
|
||||||
|
|||||||
Reference in New Issue
Block a user