feat(iot): PATCH обновляет metadata (Terraform)
iotDeviceUpdateRequest получил поле metadata; UpdateIoTDevice обновляет переданные поля (enabled и/или metadata). Добавлен store.UpdateMetadata. Хотя бы одно поле обязательно. Раньше metadata нельзя было изменить (только enabled).
This commit is contained in:
@@ -29,9 +29,11 @@ type iotDeviceCreateRequest struct {
|
|||||||
Metadata map[string]string `json:"metadata,omitempty"`
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// iotDeviceUpdateRequest — тело PATCH.
|
// iotDeviceUpdateRequest — тело PATCH. Хотя бы одно поле обязательно:
|
||||||
|
// enabled и/или metadata (metadata раньше нельзя было обновить — ревью 2026-10-10).
|
||||||
type iotDeviceUpdateRequest struct {
|
type iotDeviceUpdateRequest struct {
|
||||||
Enabled *bool `json:"enabled"`
|
Enabled *bool `json:"enabled,omitempty"`
|
||||||
|
Metadata map[string]string `json:"metadata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// iotDeviceResponse — ответ API. MQTTPassword заполняется ТОЛЬКО при создании
|
// iotDeviceResponse — ответ API. MQTTPassword заполняется ТОЛЬКО при создании
|
||||||
@@ -314,21 +316,34 @@ func (h *Handler) UpdateIoTDevice(w http.ResponseWriter, r *http.Request) {
|
|||||||
writeJSON(w, http.StatusBadRequest, errResp("invalid JSON: "+err.Error()))
|
writeJSON(w, http.StatusBadRequest, errResp("invalid JSON: "+err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Enabled == nil {
|
if req.Enabled == nil && req.Metadata == nil {
|
||||||
writeJSON(w, http.StatusBadRequest, errResp("enabled field is required"))
|
writeJSON(w, http.StatusBadRequest, errResp("enabled или metadata обязательны"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err := h.Devices.UpdateEnabled(r.Context(), ns, name, *req.Enabled)
|
// Обновляем только переданные поля (enabled и/или metadata).
|
||||||
if err != nil {
|
if req.Enabled != nil {
|
||||||
|
if err := h.Devices.UpdateEnabled(r.Context(), ns, name, *req.Enabled); err != nil {
|
||||||
if errors.Is(err, store.ErrNotFound) {
|
if errors.Is(err, store.ErrNotFound) {
|
||||||
writeJSON(w, http.StatusNotFound, errResp("iot device not found"))
|
writeJSON(w, http.StatusNotFound, errResp("iot device not found"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Log.Error("update device", "namespace", ns, "name", name, "err", err)
|
h.Log.Error("update device enabled", "namespace", ns, "name", name, "err", err)
|
||||||
writeJSON(w, http.StatusInternalServerError, errResp("failed to update device"))
|
writeJSON(w, http.StatusInternalServerError, errResp("failed to update device"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if req.Metadata != nil {
|
||||||
|
if err := h.Devices.UpdateMetadata(r.Context(), ns, name, req.Metadata); err != nil {
|
||||||
|
if errors.Is(err, store.ErrNotFound) {
|
||||||
|
writeJSON(w, http.StatusNotFound, errResp("iot device not found"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
h.Log.Error("update device metadata", "namespace", ns, "name", name, "err", err)
|
||||||
|
writeJSON(w, http.StatusInternalServerError, errResp("failed to update device"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
device, err := h.Devices.GetByName(r.Context(), ns, name)
|
device, err := h.Devices.GetByName(r.Context(), ns, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -97,6 +97,24 @@ func (s *DeviceStore) UpdateEnabled(ctx context.Context, namespace, name string,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateMetadata обновляет metadata устройства.
|
||||||
|
func (s *DeviceStore) UpdateMetadata(ctx context.Context, namespace, name string, metadata map[string]string) error {
|
||||||
|
b, err := json.Marshal(metadata)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("store: marshal metadata: %w", err)
|
||||||
|
}
|
||||||
|
res, err := s.db.ExecContext(ctx,
|
||||||
|
`UPDATE iot_devices SET metadata = $3 WHERE namespace = $1 AND name = $2`,
|
||||||
|
namespace, name, b)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("store: update metadata: %w", err)
|
||||||
|
}
|
||||||
|
if n, _ := res.RowsAffected(); n == 0 {
|
||||||
|
return ErrNotFound
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Delete удаляет устройство.
|
// Delete удаляет устройство.
|
||||||
func (s *DeviceStore) Delete(ctx context.Context, namespace, name string) error {
|
func (s *DeviceStore) Delete(ctx context.Context, namespace, name string) error {
|
||||||
res, err := s.db.ExecContext(ctx,
|
res, err := s.db.ExecContext(ctx,
|
||||||
|
|||||||
Reference in New Issue
Block a user