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"`
|
||||
MQTTPassword string `json:"mqtt_password,omitempty"`
|
||||
TopicPrefix string `json:"topic_prefix,omitempty"`
|
||||
LastConnected string `json:"last_connected,omitempty"`
|
||||
Metadata map[string]string `json:"metadata,omitempty"`
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
// TelemetryTopic — полный MQTT-топик телеметрии устройства «ns/telemetry/device».
|
||||
// Явное поле (в отличие от topic_prefix = «ns/»): Terraform должен знать
|
||||
// точный топик для публикации/подписки (ревью 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.
|
||||
// password отдаётся только если непустая — только на создании, при чтении
|
||||
// передаётся пустая строка (пароль повторно не показывается).
|
||||
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{
|
||||
Name: d.Name,
|
||||
Namespace: d.Namespace,
|
||||
DeviceID: d.DeviceID,
|
||||
Enabled: d.Enabled,
|
||||
Phase: d.Phase,
|
||||
MQTTUsername: d.Namespace + "_" + d.DeviceID,
|
||||
MQTTPassword: password,
|
||||
TopicPrefix: d.Namespace + "/",
|
||||
Metadata: d.Metadata,
|
||||
Name: d.Name,
|
||||
Namespace: d.Namespace,
|
||||
DeviceID: d.DeviceID,
|
||||
Enabled: d.Enabled,
|
||||
Phase: d.Phase,
|
||||
MQTTUsername: d.Namespace + "_" + d.DeviceID,
|
||||
MQTTPassword: password,
|
||||
TopicPrefix: d.Namespace + "/",
|
||||
TelemetryTopic: d.Namespace + "/telemetry/" + d.DeviceID,
|
||||
Metadata: metadata,
|
||||
}
|
||||
if d.LastConnected != nil && !d.LastConnected.IsZero() {
|
||||
resp.LastConnected = d.LastConnected.UTC().Format(time.RFC3339)
|
||||
|
||||
Reference in New Issue
Block a user