mirror of
https://github.com/coder/coder.git
synced 2025-07-08 11:39:50 +00:00
131 lines
4.5 KiB
Go
131 lines
4.5 KiB
Go
package prebuilds
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
)
|
|
|
|
var (
|
|
templateID = uuid.New()
|
|
templateVersionID = uuid.New()
|
|
presetID = uuid.New()
|
|
preset2ID = uuid.New()
|
|
prebuildID = uuid.New()
|
|
)
|
|
|
|
func TestReconciliationActions(t *testing.T) {
|
|
cases := map[string]struct {
|
|
preset database.GetTemplatePresetsWithPrebuildsRow // TODO: make own structs; reusing these types is lame
|
|
running []database.GetRunningPrebuildsRow
|
|
inProgress []database.GetPrebuildsInProgressRow
|
|
expected reconciliationActions
|
|
}{
|
|
// New template version created which adds a new preset with prebuilds configured.
|
|
"CreateNetNew": {
|
|
preset: preset(true, 1),
|
|
expected: reconciliationActions{
|
|
desired: 1,
|
|
create: 1,
|
|
},
|
|
},
|
|
// New template version created, making an existing preset and its prebuilds outdated.
|
|
"DeleteOutdated": {
|
|
preset: preset(false, 1),
|
|
running: []database.GetRunningPrebuildsRow{
|
|
{
|
|
WorkspaceID: prebuildID,
|
|
TemplateID: templateID,
|
|
TemplateVersionID: templateVersionID,
|
|
CurrentPresetID: uuid.NullUUID{UUID: presetID, Valid: true},
|
|
DesiredPresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true},
|
|
Ready: true,
|
|
},
|
|
},
|
|
expected: reconciliationActions{
|
|
outdated: 1,
|
|
deleteIDs: []uuid.UUID{prebuildID},
|
|
},
|
|
},
|
|
// Somehow an additional prebuild is running, delete it.
|
|
// This can happen if an operator messes with a prebuild's state (stop, start).
|
|
"DeleteOldestExtraneous": {
|
|
preset: preset(true, 1),
|
|
running: []database.GetRunningPrebuildsRow{
|
|
{
|
|
WorkspaceID: prebuildID,
|
|
TemplateID: templateID,
|
|
TemplateVersionID: templateVersionID,
|
|
CurrentPresetID: uuid.NullUUID{UUID: presetID, Valid: true},
|
|
DesiredPresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true},
|
|
CreatedAt: time.Now().Add(-time.Hour),
|
|
},
|
|
{
|
|
WorkspaceID: uuid.New(),
|
|
TemplateID: templateID,
|
|
TemplateVersionID: templateVersionID,
|
|
CurrentPresetID: uuid.NullUUID{UUID: presetID, Valid: true},
|
|
DesiredPresetID: uuid.NullUUID{UUID: uuid.New(), Valid: true},
|
|
CreatedAt: time.Now(),
|
|
},
|
|
},
|
|
expected: reconciliationActions{
|
|
desired: 1,
|
|
extraneous: 1,
|
|
actual: 2,
|
|
deleteIDs: []uuid.UUID{prebuildID},
|
|
},
|
|
},
|
|
}
|
|
|
|
for name, tc := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
ps := presetState{
|
|
preset: tc.preset,
|
|
running: tc.running,
|
|
inProgress: tc.inProgress,
|
|
}
|
|
|
|
actions, err := ps.calculateActions()
|
|
require.NoError(t, err, "could not calculate reconciliation actions")
|
|
|
|
validateActions(t, tc.expected, *actions)
|
|
})
|
|
}
|
|
}
|
|
|
|
func preset(active bool, instances int32) database.GetTemplatePresetsWithPrebuildsRow {
|
|
return database.GetTemplatePresetsWithPrebuildsRow{
|
|
TemplateID: templateID,
|
|
TemplateVersionID: templateVersionID,
|
|
UsingActiveVersion: active,
|
|
PresetID: presetID,
|
|
Name: "bob",
|
|
DesiredInstances: instances,
|
|
Deleted: false,
|
|
Deprecated: false,
|
|
}
|
|
}
|
|
|
|
// validateActions is a convenience func to make tests more readable; it exploits the fact that the default states for
|
|
// prebuilds align with zero values.
|
|
func validateActions(t *testing.T, expected, actual reconciliationActions) bool {
|
|
return assert.EqualValuesf(t, expected.deleteIDs, actual.deleteIDs, "'deleteIDs' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.create, actual.create, "'create' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.desired, actual.desired, "'desired' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.actual, actual.actual, "'actual' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.eligible, actual.eligible, "'eligible' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.extraneous, actual.extraneous, "'extraneous' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.outdated, actual.outdated, "'outdated' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.starting, actual.starting, "'starting' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.stopping, actual.stopping, "'stopping' did not match expectation") &&
|
|
assert.EqualValuesf(t, expected.deleting, actual.deleting, "'deleting' did not match expectation")
|
|
}
|