Pulse/pkg/agents/docker/report_test.go
rcourtman 01f7d81d38 style: fix gofmt formatting inconsistencies
Run gofmt -w to fix tab/space inconsistencies across 33 files.
2025-11-26 23:44:36 +00:00

485 lines
11 KiB
Go

package dockeragent
import (
"encoding/json"
"testing"
"time"
)
func TestReport_AgentKey(t *testing.T) {
tests := []struct {
name string
report Report
expected string
}{
{
name: "uses agent ID first",
report: Report{
Agent: AgentInfo{ID: "agent-123"},
Host: HostInfo{MachineID: "machine-456", Hostname: "myhost"},
},
expected: "agent-123",
},
{
name: "falls back to machine ID",
report: Report{
Agent: AgentInfo{ID: ""},
Host: HostInfo{MachineID: "machine-456", Hostname: "myhost"},
},
expected: "machine-456",
},
{
name: "falls back to hostname",
report: Report{
Agent: AgentInfo{ID: ""},
Host: HostInfo{MachineID: "", Hostname: "myhost"},
},
expected: "myhost",
},
{
name: "empty report returns empty hostname",
report: Report{
Agent: AgentInfo{},
Host: HostInfo{},
},
expected: "",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
result := tc.report.AgentKey()
if result != tc.expected {
t.Errorf("AgentKey() = %q, want %q", result, tc.expected)
}
})
}
}
func TestReport_JSONMarshal(t *testing.T) {
now := time.Now()
report := Report{
Agent: AgentInfo{
ID: "docker-agent-1",
Version: "1.0.0",
Type: "docker",
IntervalSeconds: 30,
},
Host: HostInfo{
Hostname: "docker-host",
DockerVersion: "24.0.0",
TotalCPU: 8,
TotalMemoryBytes: 16000000000,
},
Containers: []Container{
{
ID: "abc123",
Name: "nginx",
Image: "nginx:latest",
State: "running",
},
},
Timestamp: now,
}
data, err := json.Marshal(report)
if err != nil {
t.Fatalf("Failed to marshal Report: %v", err)
}
var decoded Report
if err := json.Unmarshal(data, &decoded); err != nil {
t.Fatalf("Failed to unmarshal Report: %v", err)
}
if decoded.Agent.ID != report.Agent.ID {
t.Errorf("Agent.ID = %q, want %q", decoded.Agent.ID, report.Agent.ID)
}
if len(decoded.Containers) != 1 {
t.Errorf("Containers count = %d, want 1", len(decoded.Containers))
}
}
func TestAgentInfo_Fields(t *testing.T) {
agent := AgentInfo{
ID: "agent-456",
Version: "2.0.0",
Type: "unified",
IntervalSeconds: 60,
}
if agent.ID != "agent-456" {
t.Errorf("ID = %q, want agent-456", agent.ID)
}
if agent.Version != "2.0.0" {
t.Errorf("Version = %q, want 2.0.0", agent.Version)
}
if agent.Type != "unified" {
t.Errorf("Type = %q, want unified", agent.Type)
}
if agent.IntervalSeconds != 60 {
t.Errorf("IntervalSeconds = %d, want 60", agent.IntervalSeconds)
}
}
func TestHostInfo_Fields(t *testing.T) {
host := HostInfo{
Hostname: "docker-server",
Name: "Docker Server",
MachineID: "machine123",
OS: "linux",
Runtime: "docker",
RuntimeVersion: "24.0.0",
KernelVersion: "5.15.0",
Architecture: "x86_64",
DockerVersion: "24.0.0",
TotalCPU: 16,
TotalMemoryBytes: 32000000000,
UptimeSeconds: 86400,
CPUUsagePercent: 25.5,
LoadAverage: []float64{1.0, 0.8, 0.6},
}
if host.Hostname != "docker-server" {
t.Errorf("Hostname = %q, want docker-server", host.Hostname)
}
if host.Runtime != "docker" {
t.Errorf("Runtime = %q, want docker", host.Runtime)
}
if host.TotalCPU != 16 {
t.Errorf("TotalCPU = %d, want 16", host.TotalCPU)
}
if len(host.LoadAverage) != 3 {
t.Errorf("LoadAverage length = %d, want 3", len(host.LoadAverage))
}
}
func TestContainer_Fields(t *testing.T) {
now := time.Now()
container := Container{
ID: "container123",
Name: "web-app",
Image: "myapp:v1.2.3",
CreatedAt: now,
State: "running",
Status: "Up 2 hours",
Health: "healthy",
CPUPercent: 15.5,
MemoryUsageBytes: 512000000,
MemoryLimitBytes: 1024000000,
MemoryPercent: 50.0,
UptimeSeconds: 7200,
RestartCount: 0,
ExitCode: 0,
}
if container.ID != "container123" {
t.Errorf("ID = %q, want container123", container.ID)
}
if container.State != "running" {
t.Errorf("State = %q, want running", container.State)
}
if container.Health != "healthy" {
t.Errorf("Health = %q, want healthy", container.Health)
}
if container.CPUPercent != 15.5 {
t.Errorf("CPUPercent = %f, want 15.5", container.CPUPercent)
}
if container.MemoryPercent != 50.0 {
t.Errorf("MemoryPercent = %f, want 50.0", container.MemoryPercent)
}
}
func TestContainerPort_Fields(t *testing.T) {
port := ContainerPort{
PrivatePort: 80,
PublicPort: 8080,
Protocol: "tcp",
IP: "0.0.0.0",
}
if port.PrivatePort != 80 {
t.Errorf("PrivatePort = %d, want 80", port.PrivatePort)
}
if port.PublicPort != 8080 {
t.Errorf("PublicPort = %d, want 8080", port.PublicPort)
}
if port.Protocol != "tcp" {
t.Errorf("Protocol = %q, want tcp", port.Protocol)
}
}
func TestContainerNetwork_Fields(t *testing.T) {
network := ContainerNetwork{
Name: "bridge",
IPv4: "172.17.0.2",
IPv6: "fe80::1",
}
if network.Name != "bridge" {
t.Errorf("Name = %q, want bridge", network.Name)
}
if network.IPv4 != "172.17.0.2" {
t.Errorf("IPv4 = %q, want 172.17.0.2", network.IPv4)
}
}
func TestContainerBlockIO_Fields(t *testing.T) {
blockIO := ContainerBlockIO{
ReadBytes: 1000000,
WriteBytes: 500000,
}
if blockIO.ReadBytes != 1000000 {
t.Errorf("ReadBytes = %d, want 1000000", blockIO.ReadBytes)
}
if blockIO.WriteBytes != 500000 {
t.Errorf("WriteBytes = %d, want 500000", blockIO.WriteBytes)
}
}
func TestContainerMount_Fields(t *testing.T) {
mount := ContainerMount{
Type: "bind",
Source: "/host/data",
Destination: "/data",
Mode: "rw",
RW: true,
Propagation: "rprivate",
}
if mount.Type != "bind" {
t.Errorf("Type = %q, want bind", mount.Type)
}
if mount.Source != "/host/data" {
t.Errorf("Source = %q, want /host/data", mount.Source)
}
if !mount.RW {
t.Error("RW should be true")
}
}
func TestPodmanContainer_Fields(t *testing.T) {
podman := PodmanContainer{
PodName: "mypod",
PodID: "pod123",
Infra: false,
ComposeProject: "myproject",
ComposeService: "web",
AutoUpdatePolicy: "registry",
AutoUpdateRestart: "always",
}
if podman.PodName != "mypod" {
t.Errorf("PodName = %q, want mypod", podman.PodName)
}
if podman.ComposeProject != "myproject" {
t.Errorf("ComposeProject = %q, want myproject", podman.ComposeProject)
}
if podman.AutoUpdatePolicy != "registry" {
t.Errorf("AutoUpdatePolicy = %q, want registry", podman.AutoUpdatePolicy)
}
}
func TestSwarmInfo_Fields(t *testing.T) {
swarm := SwarmInfo{
NodeID: "node123",
NodeRole: "manager",
LocalState: "active",
ControlAvailable: true,
ClusterID: "cluster456",
ClusterName: "my-swarm",
Scope: "swarm",
}
if swarm.NodeID != "node123" {
t.Errorf("NodeID = %q, want node123", swarm.NodeID)
}
if swarm.NodeRole != "manager" {
t.Errorf("NodeRole = %q, want manager", swarm.NodeRole)
}
if !swarm.ControlAvailable {
t.Error("ControlAvailable should be true")
}
}
func TestService_Fields(t *testing.T) {
service := Service{
ID: "service123",
Name: "web",
Stack: "mystack",
Image: "nginx:latest",
Mode: "replicated",
DesiredTasks: 3,
RunningTasks: 3,
CompletedTasks: 0,
}
if service.ID != "service123" {
t.Errorf("ID = %q, want service123", service.ID)
}
if service.Mode != "replicated" {
t.Errorf("Mode = %q, want replicated", service.Mode)
}
if service.DesiredTasks != 3 {
t.Errorf("DesiredTasks = %d, want 3", service.DesiredTasks)
}
}
func TestServicePort_Fields(t *testing.T) {
port := ServicePort{
Name: "http",
Protocol: "tcp",
TargetPort: 80,
PublishedPort: 8080,
PublishMode: "ingress",
}
if port.Name != "http" {
t.Errorf("Name = %q, want http", port.Name)
}
if port.TargetPort != 80 {
t.Errorf("TargetPort = %d, want 80", port.TargetPort)
}
if port.PublishMode != "ingress" {
t.Errorf("PublishMode = %q, want ingress", port.PublishMode)
}
}
func TestServiceUpdate_Fields(t *testing.T) {
now := time.Now()
update := ServiceUpdate{
State: "completed",
Message: "update completed",
CompletedAt: &now,
}
if update.State != "completed" {
t.Errorf("State = %q, want completed", update.State)
}
if update.CompletedAt == nil {
t.Error("CompletedAt should not be nil")
}
}
func TestTask_Fields(t *testing.T) {
now := time.Now()
task := Task{
ID: "task123",
ServiceID: "service456",
ServiceName: "web",
Slot: 1,
NodeID: "node789",
NodeName: "docker-node-1",
DesiredState: "running",
CurrentState: "running",
ContainerID: "container000",
CreatedAt: now,
}
if task.ID != "task123" {
t.Errorf("ID = %q, want task123", task.ID)
}
if task.Slot != 1 {
t.Errorf("Slot = %d, want 1", task.Slot)
}
if task.DesiredState != "running" {
t.Errorf("DesiredState = %q, want running", task.DesiredState)
}
}
func TestCommand_Fields(t *testing.T) {
cmd := Command{
ID: "cmd-123",
Type: CommandTypeStop,
Payload: map[string]any{
"reason": "shutdown",
},
}
if cmd.ID != "cmd-123" {
t.Errorf("ID = %q, want cmd-123", cmd.ID)
}
if cmd.Type != CommandTypeStop {
t.Errorf("Type = %q, want %q", cmd.Type, CommandTypeStop)
}
if cmd.Payload["reason"] != "shutdown" {
t.Errorf("Payload[reason] = %v, want shutdown", cmd.Payload["reason"])
}
}
func TestReportResponse_Fields(t *testing.T) {
resp := ReportResponse{
Success: true,
Commands: []Command{
{ID: "cmd-1", Type: CommandTypeStop},
},
}
if !resp.Success {
t.Error("Success should be true")
}
if len(resp.Commands) != 1 {
t.Errorf("Commands count = %d, want 1", len(resp.Commands))
}
}
func TestCommandAck_Fields(t *testing.T) {
ack := CommandAck{
HostID: "host-123",
Status: CommandStatusCompleted,
Message: "Command executed successfully",
}
if ack.HostID != "host-123" {
t.Errorf("HostID = %q, want host-123", ack.HostID)
}
if ack.Status != CommandStatusCompleted {
t.Errorf("Status = %q, want %q", ack.Status, CommandStatusCompleted)
}
}
func TestCommandConstants(t *testing.T) {
// Verify constants are defined
if CommandTypeStop != "stop" {
t.Errorf("CommandTypeStop = %q, want stop", CommandTypeStop)
}
if CommandStatusAcknowledged != "acknowledged" {
t.Errorf("CommandStatusAcknowledged = %q, want acknowledged", CommandStatusAcknowledged)
}
if CommandStatusCompleted != "completed" {
t.Errorf("CommandStatusCompleted = %q, want completed", CommandStatusCompleted)
}
if CommandStatusFailed != "failed" {
t.Errorf("CommandStatusFailed = %q, want failed", CommandStatusFailed)
}
}
func TestReport_WithSwarm(t *testing.T) {
report := Report{
Host: HostInfo{
Hostname: "swarm-manager",
Swarm: &SwarmInfo{
NodeID: "node1",
NodeRole: "manager",
ControlAvailable: true,
},
},
Services: []Service{
{ID: "svc1", Name: "web", DesiredTasks: 3, RunningTasks: 3},
},
Tasks: []Task{
{ID: "task1", ServiceName: "web", CurrentState: "running"},
},
}
if report.Host.Swarm == nil {
t.Error("Swarm should not be nil")
}
if len(report.Services) != 1 {
t.Errorf("Services count = %d, want 1", len(report.Services))
}
if len(report.Tasks) != 1 {
t.Errorf("Tasks count = %d, want 1", len(report.Tasks))
}
}