mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 10:35:51 +00:00
e8b3c7fcf7
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.
205 lines
6.1 KiB
Go
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)
|
|
}
|
|
}
|