server/internal/handlers/admin_systemd_test.go
Rama main · réplica de lectura del repositorio original.
package handlers_test
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"blackbox/server/internal/handlers"
"blackbox/server/internal/models"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
type systemdConfigPayload struct {
Units []string `json:"units"`
}
func seedNode(t *testing.T, db *gorm.DB, name string) {
t.Helper()
require.NoError(t, db.Create(&models.Node{ID: name, Name: name, Capabilities: "[]"}).Error)
}
func TestGetSystemdSettings_ReturnsEmptyMapWhenNoneConfigured(t *testing.T) {
database := newTestDB(t)
req := httptest.NewRequest(http.MethodGet, "/api/admin/settings/systemd", nil)
w := httptest.NewRecorder()
handlers.GetSystemdSettings(database)(w, req)
require.Equal(t, http.StatusOK, w.Code)
var resp map[string][]string
require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
require.Empty(t, resp)
}
func TestUpdateSystemdSettings_UpsertsUnitList(t *testing.T) {
database := newTestDB(t)
seedNode(t, database, "node-01")
body := `{"units":["nginx.service","postgres.service"]}`
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Equal(t, []string{"nginx.service", "postgres.service"}, cfg.Units)
}
func TestUpdateSystemdSettings_OverwritesExistingList(t *testing.T) {
database := newTestDB(t)
nodeName := "node-01"
existingCfg, _ := json.Marshal(map[string]any{"units": []string{"old.service"}})
require.NoError(t, database.Create(&models.DataSourceInstance{
ID: "sys-test-1", Type: "systemd", Scope: "agent", NodeID: &nodeName,
Name: "Systemd", Config: string(existingCfg), Enabled: true,
}).Error)
body := `{"units":["nginx.service"]}`
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Equal(t, []string{"nginx.service"}, cfg.Units)
}
func TestUpdateSystemdSettings_RequiresNodeName(t *testing.T) {
database := newTestDB(t)
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd",
bytes.NewBufferString(`{"units":["nginx.service"]}`))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusBadRequest, w.Code)
}
func TestUpdateSystemdSettings_RejectsInvalidJSON(t *testing.T) {
database := newTestDB(t)
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(`{"units":[}`))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusBadRequest, w.Code)
}
func TestUpdateSystemdSettings_PersistsEmptyUnitList(t *testing.T) {
database := newTestDB(t)
seedNode(t, database, "node-01")
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(`{"units":[]}`))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Empty(t, cfg.Units)
}
func TestUpdateSystemdSettings_DeduplicatesMixedForms(t *testing.T) {
database := newTestDB(t)
seedNode(t, database, "node-01")
body := `{"units":["nginx","nginx.service","redis.service","redis"]}`
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Equal(t, []string{"nginx.service", "redis.service"}, cfg.Units)
}
func TestUpdateSystemdSettings_NormalizesBareName(t *testing.T) {
database := newTestDB(t)
seedNode(t, database, "node-01")
body := `{"units":["nginx","redis.service"]}`
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Equal(t, []string{"nginx.service", "redis.service"}, cfg.Units)
}
func TestUpdateSystemdSettings_DottedBareNameGetsSuffix(t *testing.T) {
database := newTestDB(t)
seedNode(t, database, "node-01")
body := `{"units":["dbus-org.freedesktop.resolve1"]}`
req := httptest.NewRequest(http.MethodPut, "/api/admin/settings/systemd/node-01",
bytes.NewBufferString(body))
req.Header.Set("Content-Type", "application/json")
req = withChiParam(req, "node_name", "node-01")
w := httptest.NewRecorder()
handlers.UpdateSystemdSettings(database)(w, req)
require.Equal(t, http.StatusNoContent, w.Code)
var inst models.DataSourceInstance
require.NoError(t, database.Where("type = ? AND node_id = ?", "systemd", "node-01").First(&inst).Error)
var cfg systemdConfigPayload
require.NoError(t, json.Unmarshal([]byte(inst.Config), &cfg))
require.Equal(t, []string{"dbus-org.freedesktop.resolve1.service"}, cfg.Units)
}
func TestGetSystemdSettings_ReturnsAllNodes(t *testing.T) {
database := newTestDB(t)
node01 := "node-01"
node02 := "node-02"
cfg1, _ := json.Marshal(map[string]any{"units": []string{"nginx.service"}})
cfg2, _ := json.Marshal(map[string]any{"units": []string{"redis.service"}})
require.NoError(t, database.Create(&models.DataSourceInstance{
ID: "sys-n1", Type: "systemd", Scope: "agent", NodeID: &node01,
Name: "Systemd", Config: string(cfg1), Enabled: true,
}).Error)
require.NoError(t, database.Create(&models.DataSourceInstance{
ID: "sys-n2", Type: "systemd", Scope: "agent", NodeID: &node02,
Name: "Systemd", Config: string(cfg2), Enabled: true,
}).Error)
req := httptest.NewRequest(http.MethodGet, "/api/admin/settings/systemd", nil)
w := httptest.NewRecorder()
handlers.GetSystemdSettings(database)(w, req)
require.Equal(t, http.StatusOK, w.Code)
var resp map[string][]string
require.NoError(t, json.NewDecoder(w.Body).Decode(&resp))
require.Equal(t, []string{"nginx.service"}, resp["node-01"])
require.Equal(t, []string{"redis.service"}, resp["node-02"])
}