server/internal/handlers/datasource_migration_test.go
Rama main · réplica de lectura del repositorio original.
package handlers_test
import (
"encoding/json"
"testing"
"blackbox/server/internal/handlers"
"blackbox/server/internal/models"
"github.com/glebarez/sqlite"
"github.com/stretchr/testify/require"
"gorm.io/gorm"
)
func newMigrationTestDB(t *testing.T) *gorm.DB {
t.Helper()
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
require.NoError(t, err)
require.NoError(t, db.AutoMigrate(
&models.AppSetting{},
&models.SystemdUnitConfig{},
&models.Node{},
&models.DataSourceInstance{},
))
return db
}
func TestMigrateDataSources_SystemdRows(t *testing.T) {
db := newMigrationTestDB(t)
units, err := json.Marshal([]string{"nginx.service", "caddy.service"})
require.NoError(t, err)
require.NoError(t, db.Create(&models.SystemdUnitConfig{
NodeName: "homelab-01",
Units: string(units),
}).Error)
require.NoError(t, handlers.MigrateDataSources(db, ""))
var instances []models.DataSourceInstance
require.NoError(t, db.Where("type = ?", "systemd").Find(&instances).Error)
require.Len(t, instances, 1)
require.NotNil(t, instances[0].NodeID)
require.Equal(t, "homelab-01", *instances[0].NodeID)
require.Equal(t, "agent", instances[0].Scope)
var cfg struct {
Units []string `json:"units"`
}
require.NoError(t, json.Unmarshal([]byte(instances[0].Config), &cfg))
require.Equal(t, []string{"nginx.service", "caddy.service"}, cfg.Units)
var legacyCount int64
require.NoError(t, db.Model(&models.SystemdUnitConfig{}).Where("node_name = ?", "homelab-01").Count(&legacyCount).Error)
require.Equal(t, int64(0), legacyCount)
}
func TestMigrateDataSources_FileWatcherPerNode(t *testing.T) {
db := newMigrationTestDB(t)
require.NoError(t, db.Create(&models.Node{ID: "n1", Name: "homelab-01", Capabilities: `["filewatcher"]`}).Error)
require.NoError(t, db.Create(&models.AppSetting{Key: "file_watcher_redact_secrets", Value: "true"}).Error)
require.NoError(t, handlers.MigrateDataSources(db, ""))
var instances []models.DataSourceInstance
require.NoError(t, db.Where("type = ?", "filewatcher").Find(&instances).Error)
require.Len(t, instances, 1)
require.NotNil(t, instances[0].NodeID)
require.Equal(t, "homelab-01", *instances[0].NodeID)
require.True(t, instances[0].Enabled)
var cfg struct {
RedactSecrets bool `json:"redact_secrets"`
}
require.NoError(t, json.Unmarshal([]byte(instances[0].Config), &cfg))
require.True(t, cfg.RedactSecrets)
}
func TestMigrateDataSources_FileWatcherSeedsLegacyNodeWithEmptyCapabilities(t *testing.T) {
db := newMigrationTestDB(t)
require.NoError(t, db.Create(&models.Node{ID: "n1", Name: "homelab-01", Capabilities: "[]"}).Error)
require.NoError(t, handlers.MigrateDataSources(db, ""))
var instances []models.DataSourceInstance
require.NoError(t, db.Where("type = ?", "filewatcher").Find(&instances).Error)
require.Len(t, instances, 1)
require.NotNil(t, instances[0].NodeID)
require.Equal(t, "homelab-01", *instances[0].NodeID)
var node models.Node
require.NoError(t, db.Where("name = ?", "homelab-01").First(&node).Error)
require.Equal(t, `["filewatcher"]`, node.Capabilities)
}
func TestMigrateDataSources_WebhookInstances(t *testing.T) {
db := newMigrationTestDB(t)
require.NoError(t, handlers.MigrateDataSources(db, "mysecret"))
var uptime, watchtower models.DataSourceInstance
require.NoError(t, db.Where("type = ?", "webhook_uptime_kuma").First(&uptime).Error)
require.NoError(t, db.Where("type = ?", "webhook_watchtower").First(&watchtower).Error)
var cfgUptime struct {
Secret string `json:"secret"`
}
var cfgWatchtower struct {
Secret string `json:"secret"`
}
require.NoError(t, json.Unmarshal([]byte(uptime.Config), &cfgUptime))
require.Equal(t, "mysecret", cfgUptime.Secret)
require.NoError(t, json.Unmarshal([]byte(watchtower.Config), &cfgWatchtower))
require.Equal(t, "mysecret", cfgWatchtower.Secret)
}
func TestMigrateDataSources_Idempotent(t *testing.T) {
db := newMigrationTestDB(t)
require.NoError(t, db.Create(&models.Node{ID: "n1", Name: "homelab-01", Capabilities: `["filewatcher"]`}).Error)
units, err := json.Marshal([]string{"nginx.service"})
require.NoError(t, err)
require.NoError(t, db.Create(&models.SystemdUnitConfig{
NodeName: "homelab-01",
Units: string(units),
}).Error)
require.NoError(t, handlers.MigrateDataSources(db, "s"))
require.NoError(t, handlers.MigrateDataSources(db, "s"))
for _, sourceType := range []string{"webhook_uptime_kuma", "webhook_watchtower", "systemd", "filewatcher"} {
var count int64
require.NoError(t, db.Model(&models.DataSourceInstance{}).Where("type = ?", sourceType).Count(&count).Error)
require.Equal(t, int64(1), count, "unexpected count for %s", sourceType)
}
}
func TestMigrateDataSources_DoesNotRecreateDeletedFileWatcherAfterMarker(t *testing.T) {
db := newMigrationTestDB(t)
require.NoError(t, db.Create(&models.Node{ID: "n1", Name: "homelab-01", Capabilities: `["filewatcher"]`}).Error)
require.NoError(t, handlers.MigrateDataSources(db, ""))
var inst models.DataSourceInstance
require.NoError(t, db.Where("type = ? AND node_id = ?", "filewatcher", "homelab-01").First(&inst).Error)
require.NoError(t, db.Delete(&inst).Error)
require.NoError(t, handlers.MigrateDataSources(db, ""))
var count int64
require.NoError(t, db.Model(&models.DataSourceInstance{}).Where("type = ? AND node_id = ?", "filewatcher", "homelab-01").Count(&count).Error)
require.Equal(t, int64(0), count)
}