test: cover docker command lifecycle and server info
This commit is contained in:
parent
3efa9ff71b
commit
958d6218c2
2 changed files with 242 additions and 0 deletions
|
|
@ -186,6 +186,41 @@ func TestStateEndpointReturnsMockData(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestServerInfoEndpointReportsDevelopment(t *testing.T) {
|
||||
srv := newIntegrationServer(t)
|
||||
|
||||
res, err := http.Get(srv.server.URL + "/api/server/info")
|
||||
if err != nil {
|
||||
t.Fatalf("server info request failed: %v", err)
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != http.StatusOK {
|
||||
t.Fatalf("unexpected status: got %d want %d", res.StatusCode, http.StatusOK)
|
||||
}
|
||||
|
||||
var payload map[string]any
|
||||
if err := json.NewDecoder(res.Body).Decode(&payload); err != nil {
|
||||
t.Fatalf("decode server info response: %v", err)
|
||||
}
|
||||
|
||||
isDev, ok := payload["isDevelopment"].(bool)
|
||||
if !ok {
|
||||
t.Fatalf("isDevelopment missing or not bool: %v", payload["isDevelopment"])
|
||||
}
|
||||
if !isDev {
|
||||
t.Fatalf("expected development mode to be true")
|
||||
}
|
||||
|
||||
version, ok := payload["version"].(string)
|
||||
if !ok {
|
||||
t.Fatalf("version missing or not string: %v", payload["version"])
|
||||
}
|
||||
if version == "" {
|
||||
t.Fatalf("expected non-empty version string")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigNodesUsesMockTopology(t *testing.T) {
|
||||
srv := newIntegrationServer(t)
|
||||
|
||||
|
|
|
|||
207
internal/monitoring/docker_commands_test.go
Normal file
207
internal/monitoring/docker_commands_test.go
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
package monitoring
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
||||
)
|
||||
|
||||
func newTestMonitorForCommands(t *testing.T) *Monitor {
|
||||
t.Helper()
|
||||
state := models.NewState()
|
||||
return &Monitor{
|
||||
state: state,
|
||||
removedDockerHosts: make(map[string]time.Time),
|
||||
dockerCommands: make(map[string]*dockerHostCommand),
|
||||
dockerCommandIndex: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
func findDockerHost(t *testing.T, m *Monitor, id string) models.DockerHost {
|
||||
t.Helper()
|
||||
hosts := m.state.GetDockerHosts()
|
||||
for _, host := range hosts {
|
||||
if host.ID == id {
|
||||
return host
|
||||
}
|
||||
}
|
||||
t.Fatalf("docker host %s not found", id)
|
||||
return models.DockerHost{}
|
||||
}
|
||||
|
||||
func TestDockerStopCommandLifecycle(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
monitor := newTestMonitorForCommands(t)
|
||||
|
||||
host := models.DockerHost{
|
||||
ID: "host-1",
|
||||
Hostname: "node-1",
|
||||
DisplayName: "node-1",
|
||||
Status: "online",
|
||||
}
|
||||
monitor.state.UpsertDockerHost(host)
|
||||
|
||||
cmdStatus, err := monitor.QueueDockerHostStop(host.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("queue stop command: %v", err)
|
||||
}
|
||||
if cmdStatus.Status != DockerCommandStatusQueued {
|
||||
t.Fatalf("expected queued status, got %s", cmdStatus.Status)
|
||||
}
|
||||
|
||||
hostState := findDockerHost(t, monitor, host.ID)
|
||||
if !hostState.PendingUninstall {
|
||||
t.Fatalf("expected host to be marked pending uninstall")
|
||||
}
|
||||
if hostState.Command == nil || hostState.Command.Status != DockerCommandStatusQueued {
|
||||
t.Fatalf("expected host command to be stored with queued status")
|
||||
}
|
||||
|
||||
payload, fetchedStatus := monitor.FetchDockerCommandForHost(host.ID)
|
||||
if payload != nil {
|
||||
t.Fatalf("expected no payload, got %v", payload)
|
||||
}
|
||||
if fetchedStatus == nil {
|
||||
t.Fatalf("expected command status from fetch")
|
||||
}
|
||||
if fetchedStatus.Status != DockerCommandStatusDispatched {
|
||||
t.Fatalf("expected dispatched status, got %s", fetchedStatus.Status)
|
||||
}
|
||||
|
||||
completedStatus, returnedHostID, shouldRemove, err := monitor.AcknowledgeDockerHostCommand(fetchedStatus.ID, host.ID, DockerCommandStatusCompleted, "done")
|
||||
if err != nil {
|
||||
t.Fatalf("acknowledge command: %v", err)
|
||||
}
|
||||
if returnedHostID != host.ID {
|
||||
t.Fatalf("expected host id %s, got %s", host.ID, returnedHostID)
|
||||
}
|
||||
if completedStatus.Status != DockerCommandStatusCompleted {
|
||||
t.Fatalf("expected completed status, got %s", completedStatus.Status)
|
||||
}
|
||||
if !shouldRemove {
|
||||
t.Fatalf("expected shouldRemove true for stop command")
|
||||
}
|
||||
|
||||
if len(monitor.dockerCommands) != 0 {
|
||||
t.Fatalf("expected command map to be cleared")
|
||||
}
|
||||
if len(monitor.dockerCommandIndex) != 0 {
|
||||
t.Fatalf("expected command index to be cleared")
|
||||
}
|
||||
|
||||
hostState = findDockerHost(t, monitor, host.ID)
|
||||
if hostState.Command == nil || hostState.Command.Status != DockerCommandStatusCompleted {
|
||||
t.Fatalf("expected host command status to be completed in state")
|
||||
}
|
||||
if hostState.Command.Message != "done" {
|
||||
t.Fatalf("expected completion message to be propagated")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerCommandExpiryCleanup(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
monitor := newTestMonitorForCommands(t)
|
||||
|
||||
host := models.DockerHost{
|
||||
ID: "host-expire",
|
||||
Hostname: "expire",
|
||||
DisplayName: "expire",
|
||||
Status: "online",
|
||||
}
|
||||
monitor.state.UpsertDockerHost(host)
|
||||
|
||||
status, err := monitor.QueueDockerHostStop(host.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("queue stop command: %v", err)
|
||||
}
|
||||
if status.Status != DockerCommandStatusQueued {
|
||||
t.Fatalf("expected queued status, got %s", status.Status)
|
||||
}
|
||||
|
||||
monitor.mu.Lock()
|
||||
cmd := monitor.dockerCommands[host.ID]
|
||||
past := time.Now().Add(-2 * dockerCommandDefaultTTL)
|
||||
cmd.status.ExpiresAt = &past
|
||||
monitor.mu.Unlock()
|
||||
|
||||
payload, fetched := monitor.FetchDockerCommandForHost(host.ID)
|
||||
if payload != nil || fetched != nil {
|
||||
t.Fatalf("expected expired command to be removed")
|
||||
}
|
||||
|
||||
if len(monitor.dockerCommands) != 0 {
|
||||
t.Fatalf("expected command to be removed after expiry")
|
||||
}
|
||||
if len(monitor.dockerCommandIndex) != 0 {
|
||||
t.Fatalf("expected index to be cleared after expiry")
|
||||
}
|
||||
|
||||
hostState := findDockerHost(t, monitor, host.ID)
|
||||
if hostState.Command == nil || hostState.Command.Status != DockerCommandStatusExpired {
|
||||
t.Fatalf("expected state to record expiry status, got %#v", hostState.Command)
|
||||
}
|
||||
if hostState.Command.FailureReason == "" {
|
||||
t.Fatalf("expected failure reason to be set on expiry")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAllowDockerHostReenrollClearsState(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
monitor := newTestMonitorForCommands(t)
|
||||
|
||||
host := models.DockerHost{
|
||||
ID: "host-reenroll",
|
||||
Hostname: "reenroll",
|
||||
DisplayName: "reenroll",
|
||||
Status: "online",
|
||||
PendingUninstall: true,
|
||||
}
|
||||
monitor.state.UpsertDockerHost(host)
|
||||
monitor.removedDockerHosts[host.ID] = time.Now().Add(-time.Hour)
|
||||
|
||||
status, err := monitor.QueueDockerHostStop(host.ID)
|
||||
if err != nil {
|
||||
t.Fatalf("queue stop command: %v", err)
|
||||
}
|
||||
if status.Status != DockerCommandStatusQueued {
|
||||
t.Fatalf("expected queued status, got %s", status.Status)
|
||||
}
|
||||
|
||||
if err := monitor.AllowDockerHostReenroll(host.ID); err != nil {
|
||||
t.Fatalf("allow reenroll: %v", err)
|
||||
}
|
||||
|
||||
if _, exists := monitor.removedDockerHosts[host.ID]; exists {
|
||||
t.Fatalf("expected host removal block to be cleared")
|
||||
}
|
||||
if _, exists := monitor.dockerCommands[host.ID]; exists {
|
||||
t.Fatalf("expected any queued commands to be cleared")
|
||||
}
|
||||
|
||||
hostState := findDockerHost(t, monitor, host.ID)
|
||||
if hostState.Command != nil {
|
||||
t.Fatalf("expected host command pointer to be cleared")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanupRemovedDockerHosts(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
monitor := newTestMonitorForCommands(t)
|
||||
monitor.removedDockerHosts["old-host"] = time.Now().Add(-2 * removedDockerHostsTTL)
|
||||
monitor.removedDockerHosts["fresh-host"] = time.Now()
|
||||
|
||||
now := time.Now()
|
||||
monitor.cleanupRemovedDockerHosts(now)
|
||||
|
||||
if _, exists := monitor.removedDockerHosts["old-host"]; exists {
|
||||
t.Fatalf("expected old host removal entry to be purged")
|
||||
}
|
||||
if _, exists := monitor.removedDockerHosts["fresh-host"]; !exists {
|
||||
t.Fatalf("expected fresh host removal entry to remain")
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue