mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-07 00:37:36 +00:00
178 lines
5.9 KiB
Go
178 lines
5.9 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/models"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestExecuteCheckDockerUpdates(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
exec := NewPulseToolExecutor(ExecutorConfig{})
|
|
result, err := exec.executeCheckDockerUpdates(ctx, map[string]interface{}{})
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "Docker update checking not available. Ensure updates provider is configured.", result.Content[0].Text)
|
|
|
|
updatesProvider := &mockUpdatesProvider{}
|
|
exec = NewPulseToolExecutor(ExecutorConfig{UpdatesProvider: updatesProvider})
|
|
result, err = exec.executeCheckDockerUpdates(ctx, map[string]interface{}{})
|
|
require.NoError(t, err)
|
|
assert.True(t, result.IsError)
|
|
assert.Contains(t, result.Content[0].Text, "host is required")
|
|
|
|
state := models.StateSnapshot{
|
|
DockerHosts: []models.DockerHost{
|
|
{ID: "host1", Hostname: "dock1", DisplayName: "Dock One"},
|
|
},
|
|
}
|
|
|
|
updatesProvider.On("TriggerUpdateCheck", "host1").Return(DockerCommandStatus{
|
|
ID: "cmd1",
|
|
Type: "check",
|
|
Status: "queued",
|
|
}, nil).Once()
|
|
|
|
exec = NewPulseToolExecutor(ExecutorConfig{
|
|
UpdatesProvider: updatesProvider,
|
|
StateProvider: &mockStateProvider{state: state},
|
|
})
|
|
result, err = exec.executeCheckDockerUpdates(ctx, map[string]interface{}{
|
|
"host": "dock1",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
var resp DockerCheckUpdatesResponse
|
|
require.NoError(t, json.Unmarshal([]byte(result.Content[0].Text), &resp))
|
|
assert.Equal(t, "host1", resp.TargetID)
|
|
assert.Equal(t, "Dock One", resp.HostName)
|
|
assert.Equal(t, "cmd1", resp.CommandID)
|
|
|
|
updatesProvider.On("TriggerUpdateCheck", "host1").Return(DockerCommandStatus{}, errors.New("boom")).Once()
|
|
exec = NewPulseToolExecutor(ExecutorConfig{
|
|
UpdatesProvider: updatesProvider,
|
|
StateProvider: &mockStateProvider{state: state},
|
|
})
|
|
result, err = exec.executeCheckDockerUpdates(ctx, map[string]interface{}{
|
|
"host": "dock1",
|
|
})
|
|
require.NoError(t, err)
|
|
assert.Contains(t, result.Content[0].Text, "Failed to trigger update check")
|
|
}
|
|
|
|
func TestExecuteCheckDockerUpdates_RetriesTransientError(t *testing.T) {
|
|
origSleep := dockerUpdateQueueSleepFn
|
|
dockerUpdateQueueSleepFn = func(context.Context, time.Duration) error { return nil }
|
|
t.Cleanup(func() { dockerUpdateQueueSleepFn = origSleep })
|
|
|
|
state := models.StateSnapshot{
|
|
DockerHosts: []models.DockerHost{
|
|
{ID: "host1", Hostname: "dock1", DisplayName: "Dock One"},
|
|
},
|
|
}
|
|
|
|
updatesProvider := &mockUpdatesProvider{}
|
|
updatesProvider.On("TriggerUpdateCheck", "host1").Return(DockerCommandStatus{}, errors.New("queue temporarily unavailable")).Once()
|
|
updatesProvider.On("TriggerUpdateCheck", "host1").Return(DockerCommandStatus{
|
|
ID: "cmd-retry",
|
|
Type: "check",
|
|
Status: "queued",
|
|
}, nil).Once()
|
|
|
|
exec := NewPulseToolExecutor(ExecutorConfig{
|
|
UpdatesProvider: updatesProvider,
|
|
StateProvider: &mockStateProvider{state: state},
|
|
})
|
|
|
|
result, err := exec.executeCheckDockerUpdates(context.Background(), map[string]interface{}{
|
|
"host": "dock1",
|
|
})
|
|
require.NoError(t, err)
|
|
require.False(t, result.IsError)
|
|
|
|
var resp DockerCheckUpdatesResponse
|
|
require.NoError(t, json.Unmarshal([]byte(result.Content[0].Text), &resp))
|
|
assert.Equal(t, "cmd-retry", resp.CommandID)
|
|
updatesProvider.AssertExpectations(t)
|
|
}
|
|
|
|
func TestExecuteCheckDockerUpdates_DoesNotRetryNonTransientError(t *testing.T) {
|
|
origSleep := dockerUpdateQueueSleepFn
|
|
dockerUpdateQueueSleepFn = func(context.Context, time.Duration) error { return nil }
|
|
t.Cleanup(func() { dockerUpdateQueueSleepFn = origSleep })
|
|
|
|
state := models.StateSnapshot{
|
|
DockerHosts: []models.DockerHost{
|
|
{ID: "host1", Hostname: "dock1", DisplayName: "Dock One"},
|
|
},
|
|
}
|
|
|
|
updatesProvider := &mockUpdatesProvider{}
|
|
updatesProvider.On("TriggerUpdateCheck", "host1").Return(DockerCommandStatus{}, errors.New("invalid host id")).Once()
|
|
|
|
exec := NewPulseToolExecutor(ExecutorConfig{
|
|
UpdatesProvider: updatesProvider,
|
|
StateProvider: &mockStateProvider{state: state},
|
|
})
|
|
|
|
result, err := exec.executeCheckDockerUpdates(context.Background(), map[string]interface{}{
|
|
"host": "dock1",
|
|
})
|
|
require.NoError(t, err)
|
|
require.False(t, result.IsError)
|
|
assert.Contains(t, result.Content[0].Text, "Failed to trigger update check")
|
|
assert.NotContains(t, result.Content[0].Text, "after 3 attempts")
|
|
updatesProvider.AssertNumberOfCalls(t, "TriggerUpdateCheck", 1)
|
|
}
|
|
|
|
func TestExecuteUpdateDockerContainer_RetriesTransientError(t *testing.T) {
|
|
origSleep := dockerUpdateQueueSleepFn
|
|
dockerUpdateQueueSleepFn = func(context.Context, time.Duration) error { return nil }
|
|
t.Cleanup(func() { dockerUpdateQueueSleepFn = origSleep })
|
|
|
|
state := models.StateSnapshot{
|
|
DockerHosts: []models.DockerHost{
|
|
{
|
|
ID: "host1",
|
|
Hostname: "dock1",
|
|
DisplayName: "Dock One",
|
|
Containers: []models.DockerContainer{
|
|
{ID: "c1", Name: "/nginx"},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
updatesProvider := &mockUpdatesProvider{}
|
|
updatesProvider.On("IsUpdateActionsEnabled").Return(true).Once()
|
|
updatesProvider.On("UpdateContainer", "host1", "c1", "nginx").Return(DockerCommandStatus{}, errors.New("i/o timeout")).Once()
|
|
updatesProvider.On("UpdateContainer", "host1", "c1", "nginx").Return(DockerCommandStatus{
|
|
ID: "cmd-update",
|
|
Type: "update",
|
|
Status: "queued",
|
|
}, nil).Once()
|
|
|
|
exec := NewPulseToolExecutor(ExecutorConfig{
|
|
UpdatesProvider: updatesProvider,
|
|
StateProvider: &mockStateProvider{state: state},
|
|
ControlLevel: ControlLevelAutonomous,
|
|
})
|
|
|
|
result, err := exec.executeUpdateDockerContainer(context.Background(), map[string]interface{}{
|
|
"host": "dock1",
|
|
"container": "c1",
|
|
})
|
|
require.NoError(t, err)
|
|
require.False(t, result.IsError)
|
|
|
|
var resp DockerUpdateContainerResponse
|
|
require.NoError(t, json.Unmarshal([]byte(result.Content[0].Text), &resp))
|
|
assert.Equal(t, "cmd-update", resp.CommandID)
|
|
updatesProvider.AssertExpectations(t)
|
|
}
|