Files
pulse/internal/monitoring/monitor_profiles_test.go
T
rcourtman e8b3c7fcf7 Restore remote config signature compatibility
Keep desired config fingerprints as response metadata derived from the signed command and settings payload.

Use merged agent profile settings when building remote config fingerprints.
2026-05-13 19:00:02 +01:00

205 lines
6.1 KiB
Go

package monitoring
import (
"os"
"testing"
"github.com/rcourtman/pulse-go-rewrite/internal/config"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
"github.com/rcourtman/pulse-go-rewrite/internal/remoteconfig"
)
func TestGetHostAgentConfig_WithProfiles(t *testing.T) {
// Setup temp dir for persistence
tmpDir, err := os.MkdirTemp("", "monitor_profiles_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
// Initialize persistence
persistence := config.NewConfigPersistence(tmpDir)
// Create a profile
profile := models.AgentProfile{
ID: "profile-1",
Name: "Test Profile",
Config: map[string]interface{}{
"enable_docker": true,
"log_level": "debug",
},
}
if err := persistence.SaveAgentProfiles([]models.AgentProfile{profile}); err != nil {
t.Fatalf("Failed to save profiles: %v", err)
}
// Create an assignment
assignment := models.AgentProfileAssignment{
AgentID: "agent-123",
ProfileID: "profile-1",
}
if err := persistence.SaveAgentProfileAssignments([]models.AgentProfileAssignment{assignment}); err != nil {
t.Fatalf("Failed to save assignments: %v", err)
}
// Initialize Monitor with persistence
m := &Monitor{
persistence: persistence,
// minimal dependencies
config: &config.Config{},
}
// Test Case 1: Agent with assigned profile
t.Run("Agent with profile assignment", func(t *testing.T) {
cfg := m.GetHostAgentConfig("agent-123")
if cfg.Settings == nil {
t.Fatal("Expected Settings to be non-nil")
}
if val, ok := cfg.Settings["enable_docker"]; !ok || val != true {
t.Errorf("Expected enable_docker=true, got %v", val)
}
if val, ok := cfg.Settings["log_level"]; !ok || val != "debug" {
t.Errorf("Expected log_level='debug', got %v", val)
}
assertDesiredConfigMetadata(t, cfg)
})
// Test Case 2: Agent without assignment
t.Run("Agent without assignment", func(t *testing.T) {
cfg := m.GetHostAgentConfig("other-agent")
if len(cfg.Settings) != 0 {
t.Errorf("Expected empty Settings for unassigned agent, got %v", cfg.Settings)
}
assertDesiredConfigMetadata(t, cfg)
})
// Test Case 3: Agent assigned to non-existent profile
t.Run("Agent assigned to missing profile", func(t *testing.T) {
badAssignment := models.AgentProfileAssignment{
AgentID: "agent-bad",
ProfileID: "missing-profile",
}
if err := persistence.SaveAgentProfileAssignments([]models.AgentProfileAssignment{assignment, badAssignment}); err != nil {
t.Fatalf("Failed to save assignments: %v", err)
}
cfg := m.GetHostAgentConfig("agent-bad")
if len(cfg.Settings) != 0 {
t.Errorf("Expected empty Settings for missing profile, got %v", cfg.Settings)
}
assertDesiredConfigMetadata(t, cfg)
})
}
func TestGetHostAgentConfig_FingerprintIncludesCommandDecision(t *testing.T) {
m := &Monitor{
hostMetadataStore: config.NewHostMetadataStore(t.TempDir(), nil),
config: &config.Config{},
state: models.NewState(),
}
hostID := "agent-command-decision"
before := m.GetHostAgentConfig(hostID)
assertDesiredConfigMetadata(t, before)
enabled := true
if err := m.UpdateHostAgentConfig(hostID, &enabled); err != nil {
t.Fatalf("UpdateHostAgentConfig: %v", err)
}
after := m.GetHostAgentConfig(hostID)
assertDesiredConfigMetadata(t, after)
if after.CommandsEnabled == nil || !*after.CommandsEnabled {
t.Fatalf("expected commandsEnabled=true, got %#v", after.CommandsEnabled)
}
if before.DesiredConfig == nil || after.DesiredConfig == nil {
t.Fatalf("expected desired config metadata before and after command decision")
}
if before.DesiredConfig.Hash == after.DesiredConfig.Hash {
t.Fatalf("expected command decision to change desired config hash")
}
}
func TestGetHostAgentConfig_UsesMergedProfileConfigForFingerprint(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "monitor_profiles_merged_test")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tmpDir)
persistence := config.NewConfigPersistence(tmpDir)
parent := models.AgentProfile{
ID: "parent-profile",
Name: "Parent Profile",
Config: map[string]interface{}{
"enable_docker": true,
"log_level": "warn",
},
}
child := models.AgentProfile{
ID: "child-profile",
Name: "Child Profile",
ParentID: "parent-profile",
Config: map[string]interface{}{
"interval": "45s",
"log_level": "debug",
},
}
if err := persistence.SaveAgentProfiles([]models.AgentProfile{parent, child}); err != nil {
t.Fatalf("Failed to save profiles: %v", err)
}
if err := persistence.SaveAgentProfileAssignments([]models.AgentProfileAssignment{{
AgentID: "agent-child",
ProfileID: "child-profile",
}}); err != nil {
t.Fatalf("Failed to save assignments: %v", err)
}
m := &Monitor{
persistence: persistence,
config: &config.Config{},
}
cfg := m.GetHostAgentConfig("agent-child")
if cfg.Settings["enable_docker"] != true {
t.Fatalf("expected inherited enable_docker=true, got %v", cfg.Settings["enable_docker"])
}
if cfg.Settings["interval"] != "45s" {
t.Fatalf("expected child interval override, got %v", cfg.Settings["interval"])
}
if cfg.Settings["log_level"] != "debug" {
t.Fatalf("expected child log_level override, got %v", cfg.Settings["log_level"])
}
assertDesiredConfigMetadata(t, cfg)
childOnly := HostAgentConfig{CommandsEnabled: cfg.CommandsEnabled, Settings: child.Config}
childOnlyExpected, err := remoteconfig.BuildDesiredConfigMetadata(childOnly.CommandsEnabled, childOnly.Settings)
if err != nil {
t.Fatalf("BuildDesiredConfigMetadata child only: %v", err)
}
if cfg.DesiredConfig.Hash == childOnlyExpected.Hash {
t.Fatalf("expected inherited settings to affect desired config hash")
}
}
func assertDesiredConfigMetadata(t *testing.T, cfg HostAgentConfig) {
t.Helper()
if cfg.DesiredConfig == nil {
t.Fatalf("expected desired config metadata")
}
expected, err := remoteconfig.BuildDesiredConfigMetadata(cfg.CommandsEnabled, cfg.Settings)
if err != nil {
t.Fatalf("BuildDesiredConfigMetadata: %v", err)
}
if *cfg.DesiredConfig != expected {
t.Fatalf("desired config metadata = %#v, want %#v", *cfg.DesiredConfig, expected)
}
}