mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: claim prebuilds based on workspace parameters instead of preset id (#19279)
Closes https://github.com/coder/coder/issues/18356. This change finds and selects a matching preset if one was not chosen during workspace creation. This solidifies the relationship between presets and parameters. When a workspace is created without in explicitly chosen preset, it will now still be eligible to claim a prebuilt workspace if one is available.
This commit is contained in:
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/coder/coder/v2/coderd/dynamicparameters"
|
||||
"github.com/coder/coder/v2/coderd/files"
|
||||
"github.com/coder/coder/v2/coderd/prebuilds"
|
||||
"github.com/coder/coder/v2/coderd/rbac/policy"
|
||||
"github.com/coder/coder/v2/coderd/util/ptr"
|
||||
"github.com/coder/coder/v2/provisioner/terraform/tfparse"
|
||||
@@ -442,6 +443,20 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
|
||||
|
||||
var workspaceBuild database.WorkspaceBuild
|
||||
err = b.store.InTx(func(store database.Store) error {
|
||||
names, values, err := b.getParameters()
|
||||
if err != nil {
|
||||
// getParameters already wraps errors in BuildError
|
||||
return err
|
||||
}
|
||||
|
||||
if b.templateVersionPresetID == uuid.Nil {
|
||||
presetID, err := prebuilds.FindMatchingPresetID(b.ctx, b.store, templateVersionID, names, values)
|
||||
if err != nil {
|
||||
return BuildError{http.StatusInternalServerError, "find matching preset", err}
|
||||
}
|
||||
b.templateVersionPresetID = presetID
|
||||
}
|
||||
|
||||
err = store.InsertWorkspaceBuild(b.ctx, database.InsertWorkspaceBuildParams{
|
||||
ID: workspaceBuildID,
|
||||
CreatedAt: now,
|
||||
@@ -473,12 +488,6 @@ func (b *Builder) buildTx(authFunc func(action policy.Action, object rbac.Object
|
||||
return BuildError{code, "insert workspace build", err}
|
||||
}
|
||||
|
||||
names, values, err := b.getParameters()
|
||||
if err != nil {
|
||||
// getParameters already wraps errors in BuildError
|
||||
return err
|
||||
}
|
||||
|
||||
err = store.InsertWorkspaceBuildParameters(b.ctx, database.InsertWorkspaceBuildParametersParams{
|
||||
WorkspaceBuildID: workspaceBuildID,
|
||||
Name: names,
|
||||
|
||||
@@ -82,6 +82,7 @@ func TestBuilder_NoOptions(t *testing.T) {
|
||||
}),
|
||||
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(inactiveVersionID, bld.TemplateVersionID)
|
||||
asrt.Equal(workspaceID, bld.WorkspaceID)
|
||||
@@ -132,6 +133,7 @@ func TestBuilder_Initiator(t *testing.T) {
|
||||
asrt.Equal(otherUserID, job.InitiatorID)
|
||||
}),
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(otherUserID, bld.InitiatorID)
|
||||
}),
|
||||
@@ -180,6 +182,7 @@ func TestBuilder_Baggage(t *testing.T) {
|
||||
asrt.Contains(string(job.TraceMetadata.RawMessage), "ip=127.0.0.1")
|
||||
}),
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
}),
|
||||
expectBuildParameters(func(params database.InsertWorkspaceBuildParametersParams) {
|
||||
@@ -219,6 +222,7 @@ func TestBuilder_Reason(t *testing.T) {
|
||||
expectProvisionerJob(func(_ database.InsertProvisionerJobParams) {
|
||||
}),
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(database.BuildReasonAutostart, bld.Reason)
|
||||
}),
|
||||
@@ -261,6 +265,7 @@ func TestBuilder_ActiveVersion(t *testing.T) {
|
||||
}),
|
||||
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(activeVersionID, bld.TemplateVersionID)
|
||||
// no previous build...
|
||||
@@ -386,6 +391,7 @@ func TestWorkspaceBuildWithTags(t *testing.T) {
|
||||
expectBuildParameters(func(_ database.InsertWorkspaceBuildParametersParams) {
|
||||
}),
|
||||
withBuild,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
)
|
||||
fc := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{})
|
||||
|
||||
@@ -470,6 +476,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||
}
|
||||
}),
|
||||
withBuild,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
)
|
||||
fc := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{})
|
||||
|
||||
@@ -519,6 +526,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||
}
|
||||
}),
|
||||
withBuild,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
)
|
||||
fc := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{})
|
||||
|
||||
@@ -661,6 +669,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||
}
|
||||
}),
|
||||
withBuild,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
)
|
||||
fc := files.New(prometheus.NewRegistry(), &coderdtest.FakeAuthorizer{})
|
||||
|
||||
@@ -713,6 +722,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||
withProvisionerDaemons([]database.GetEligibleProvisionerDaemonsByProvisionerJobIDsRow{}),
|
||||
|
||||
// Outputs
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||
withInTx,
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {}),
|
||||
@@ -775,6 +785,7 @@ func TestWorkspaceBuildWithRichParameters(t *testing.T) {
|
||||
withProvisionerDaemons([]database.GetEligibleProvisionerDaemonsByProvisionerJobIDsRow{}),
|
||||
|
||||
// Outputs
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||
withInTx,
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {}),
|
||||
@@ -906,6 +917,7 @@ func TestWorkspaceBuildDeleteOrphan(t *testing.T) {
|
||||
}),
|
||||
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(inactiveVersionID, bld.TemplateVersionID)
|
||||
asrt.Equal(workspaceID, bld.WorkspaceID)
|
||||
@@ -968,6 +980,7 @@ func TestWorkspaceBuildDeleteOrphan(t *testing.T) {
|
||||
}),
|
||||
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {
|
||||
asrt.Equal(inactiveVersionID, bld.TemplateVersionID)
|
||||
asrt.Equal(workspaceID, bld.WorkspaceID)
|
||||
@@ -1041,6 +1054,7 @@ func TestWorkspaceBuildUsageChecker(t *testing.T) {
|
||||
// Outputs
|
||||
expectProvisionerJob(func(job database.InsertProvisionerJobParams) {}),
|
||||
withInTx,
|
||||
expectFindMatchingPresetID(uuid.Nil, sql.ErrNoRows),
|
||||
expectBuild(func(bld database.InsertWorkspaceBuildParams) {}),
|
||||
withBuild,
|
||||
expectBuildParameters(func(params database.InsertWorkspaceBuildParametersParams) {}),
|
||||
@@ -1485,6 +1499,14 @@ func withProvisionerDaemons(provisionerDaemons []database.GetEligibleProvisioner
|
||||
}
|
||||
}
|
||||
|
||||
func expectFindMatchingPresetID(id uuid.UUID, err error) func(mTx *dbmock.MockStore) {
|
||||
return func(mTx *dbmock.MockStore) {
|
||||
mTx.EXPECT().FindMatchingPresetID(gomock.Any(), gomock.Any()).
|
||||
Times(1).
|
||||
Return(id, err)
|
||||
}
|
||||
}
|
||||
|
||||
type fakeUsageChecker struct {
|
||||
checkBuildUsageFunc func(ctx context.Context, store database.Store, templateVersion *database.TemplateVersion) (wsbuilder.UsageCheckResponse, error)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user