server/internal/handlers/agent_push_upsert_test.go
Rama main · réplica de lectura del repositorio original.
package handlers_test
import (
"net/http"
"testing"
"time"
"blackbox/server/internal/handlers"
"blackbox/server/internal/models"
"blackbox/shared/types"
"github.com/oklog/ulid/v2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAgentPush_CreatesNode(t *testing.T) {
database := newTestDB(t)
startedAt := time.Now().UTC()
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: startedAt.Add(-24 * time.Hour),
NodeName: "homelab-01",
Source: "agent",
Event: "start",
Content: "container nginx started",
Metadata: `{"agent_version":"v0.2.1","ip_address":"10.0.0.5","os_info":"Ubuntu 24.04 LTS"}`,
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.Equal(t, "homelab-01", node.Name)
assert.Equal(t, "v0.2.1", node.AgentVersion)
assert.Equal(t, "10.0.0.5", node.IPAddress)
assert.Equal(t, "Ubuntu 24.04 LTS", node.OsInfo)
assert.WithinDuration(t, startedAt, node.LastSeen, 2*time.Second)
}
func TestAgentPush_HeartbeatUpdatesNodeMetadata(t *testing.T) {
database := newTestDB(t)
meta := `{"agent_version":"v0.2.1","ip_address":"10.0.0.5","os_info":"Ubuntu 24.04 LTS"}`
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC(),
NodeName: "homelab-01",
Source: "agent",
Event: "heartbeat",
Content: "Blackbox Agent heartbeat",
Metadata: meta,
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.Equal(t, "v0.2.1", node.AgentVersion)
assert.Equal(t, "10.0.0.5", node.IPAddress)
assert.Equal(t, "Ubuntu 24.04 LTS", node.OsInfo)
}
func TestAgentPush_ThrottlesLastSeenUpdates(t *testing.T) {
database := newTestDB(t)
baseTime := time.Now().UTC().Add(-5 * time.Second).Round(0)
require.NoError(t, database.Create(&models.Node{
ID: ulid.Make().String(),
Name: "homelab-01",
LastSeen: baseTime,
}).Error)
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC(),
NodeName: "homelab-01",
Source: "docker",
Service: "nginx",
Event: "stop",
Content: "container nginx stopped",
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.True(t, node.LastSeen.Equal(baseTime), "expected LastSeen to be throttled; baseTime=%v got=%v", baseTime, node.LastSeen)
}
func TestAgentPush_StartUpdatesMetadataForExistingNode(t *testing.T) {
database := newTestDB(t)
existingSeen := time.Now().UTC().Add(-5 * time.Second).Round(0)
require.NoError(t, database.Create(&models.Node{
ID: ulid.Make().String(),
Name: "homelab-01",
LastSeen: existingSeen,
}).Error)
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC().Add(-24 * time.Hour),
NodeName: "homelab-01",
Source: "agent",
Event: "start",
Content: "Blackbox Agent started",
Metadata: `{"agent_version":"v0.3.0","ip_address":"10.0.0.8","os_info":"Debian 13"}`,
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.Equal(t, "v0.3.0", node.AgentVersion)
assert.Equal(t, "10.0.0.8", node.IPAddress)
assert.Equal(t, "Debian 13", node.OsInfo)
assert.WithinDuration(t, time.Now().UTC(), node.LastSeen, 2*time.Second)
}
func TestAgentPush_ShutdownMarksNodeOfflineImmediately(t *testing.T) {
database := newTestDB(t)
require.NoError(t, database.Create(&models.Node{
ID: ulid.Make().String(),
Name: "homelab-01",
LastSeen: time.Now().UTC(),
Status: "online",
}).Error)
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC(),
NodeName: "homelab-01",
Source: "agent",
Event: "shutdown",
Content: "Blackbox Agent shutting down",
Metadata: `{"agent_version":"v0.3.0","ip_address":"10.0.0.8","os_info":"Debian 13"}`,
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.Equal(t, "offline", node.Status)
assert.WithinDuration(t, time.Now().UTC(), node.LastSeen, 2*time.Second)
assert.Equal(t, "v0.3.0", node.AgentVersion)
}
func TestAgentPush_DockerStartRemainsThrottled(t *testing.T) {
database := newTestDB(t)
baseTime := time.Now().UTC().Add(-5 * time.Second).Round(0)
require.NoError(t, database.Create(&models.Node{
ID: ulid.Make().String(),
Name: "homelab-01",
LastSeen: baseTime,
}).Error)
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC(),
NodeName: "homelab-01",
Source: "docker",
Service: "nginx",
Event: "start",
Content: "container nginx started",
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "homelab-01")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
require.Equal(t, http.StatusCreated, rr.Code, rr.Body.String())
var node models.Node
require.NoError(t, database.Where("name = ?", "homelab-01").First(&node).Error)
assert.True(t, node.LastSeen.Equal(baseTime), "expected docker start to be throttled; baseTime=%v got=%v", baseTime, node.LastSeen)
}
func TestAgentPush_RejectsNodeMismatch(t *testing.T) {
database := newTestDB(t)
entry := types.Entry{
ID: ulid.Make().String(),
Timestamp: time.Now().UTC(),
NodeName: "forged-node",
Source: "agent",
Event: "heartbeat",
Content: "Blackbox Agent heartbeat",
}
req, rr, authMiddleware := authenticatedAgentRequest(t, entry, "real-node")
authMiddleware(handlers.AgentPush(database, nil, testIncidentChannel(t), nil)).ServeHTTP(rr, req)
assert.Equal(t, http.StatusForbidden, rr.Code)
var count int64
require.NoError(t, database.Model(&models.Node{}).Count(&count).Error)
assert.Zero(t, count)
}