fix: migration runner and scan logging fixes

- Fix migration conflicts and duplicate key errors
- Remove duplicate scan logging from agents
- Fix AgentHealth UI and Storage page triggers
- Prevent scans from appearing on wrong pages

Fixes duplicate key violations on fresh installs and
storage scans appearing on Updates page.
This commit is contained in:
Fimeg
2025-12-19 20:59:12 -05:00
parent 6b3ab6d6fc
commit 2da93e442e
8 changed files with 424 additions and 109 deletions

View File

@@ -91,28 +91,33 @@ func (db *DB) Migrate(migrationsPath string) error {
// Execute the migration SQL
if _, err := tx.Exec(string(content)); err != nil {
// Check if it's a "already exists" error - if so, handle gracefully
// Check if it's an "already exists" error
if strings.Contains(err.Error(), "already exists") ||
strings.Contains(err.Error(), "duplicate key") ||
strings.Contains(err.Error(), "relation") && strings.Contains(err.Error(), "already exists") {
fmt.Printf("⚠ Migration %s failed (objects already exist), marking as applied: %v\n", filename, err)
// Rollback current transaction and start a new one for tracking
// Rollback the failed transaction
tx.Rollback()
// Start new transaction just for migration tracking
if newTx, newTxErr := db.Beginx(); newTxErr == nil {
if _, insertErr := newTx.Exec("INSERT INTO schema_migrations (version) VALUES ($1)", filename); insertErr == nil {
newTx.Commit()
} else {
newTx.Rollback()
}
// Check if this migration was already recorded as applied
var count int
checkErr := db.Get(&count, "SELECT COUNT(*) FROM schema_migrations WHERE version = $1", filename)
if checkErr == nil && count > 0 {
// Migration was already applied, just skip it
fmt.Printf("⚠ Migration %s already applied, skipping\n", filename)
} else {
// Migration failed and wasn't applied - this is a real error
return fmt.Errorf("migration %s failed with 'already exists' but migration not recorded: %w", filename, err)
}
continue
}
// For any other error, rollback and fail
tx.Rollback()
return fmt.Errorf("failed to execute migration %s: %w", filename, err)
}
// Record the migration as applied
// Record the migration as applied (normal success path)
if _, err := tx.Exec("INSERT INTO schema_migrations (version) VALUES ($1)", filename); err != nil {
tx.Rollback()
return fmt.Errorf("failed to record migration %s: %w", filename, err)
@@ -123,7 +128,7 @@ func (db *DB) Migrate(migrationsPath string) error {
return fmt.Errorf("failed to commit migration %s: %w", filename, err)
}
fmt.Printf("✓ Executed migration: %s\n", filename)
fmt.Printf("✓ Successfully executed migration: %s\n", filename)
}
return nil

View File

@@ -1,11 +1,12 @@
-- Add machine_id column to agents table for hardware fingerprint binding
-- Ensure proper UNIQUE constraint on machine_id for hardware fingerprint binding
-- This prevents config file copying attacks by validating hardware identity
-- NOTE: Migration 016 already added the machine_id column, this ensures proper unique constraint
ALTER TABLE agents
ADD COLUMN machine_id VARCHAR(64);
-- Drop the old non-unique index if it exists
DROP INDEX IF EXISTS idx_agents_machine_id;
-- Create unique index to prevent duplicate machine IDs
CREATE UNIQUE INDEX idx_agents_machine_id ON agents(machine_id) WHERE machine_id IS NOT NULL;
-- Create unique index to prevent duplicate machine IDs (allows multiple NULLs)
CREATE UNIQUE INDEX CONCURRENTLY idx_agents_machine_id_unique ON agents(machine_id) WHERE machine_id IS NOT NULL;
-- Add comment for documentation
COMMENT ON COLUMN agents.machine_id IS 'SHA-256 hash of hardware fingerprint (prevents agent impersonation via config copying)';

View File

@@ -22,6 +22,3 @@ CREATE INDEX idx_storage_metrics_agent_id ON storage_metrics(agent_id);
CREATE INDEX idx_storage_metrics_created_at ON storage_metrics(created_at DESC);
CREATE INDEX idx_storage_metrics_mountpoint ON storage_metrics(mountpoint);
CREATE INDEX idx_storage_metrics_agent_mount ON storage_metrics(agent_id, mountpoint, created_at DESC);
-- Track migration
INSERT INTO schema_migrations (version, description) VALUES ('021', 'Create storage_metrics table');