-
Notifications
You must be signed in to change notification settings - Fork 956
fix: don't create autostart workspace builds with no available provisioners #19067
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ import ( | |
"strings" | ||
"sync" | ||
"sync/atomic" | ||
"testing" | ||
"time" | ||
|
||
"github.com/dustin/go-humanize" | ||
|
@@ -28,11 +29,14 @@ import ( | |
"github.com/coder/coder/v2/coderd/database/provisionerjobs" | ||
"github.com/coder/coder/v2/coderd/database/pubsub" | ||
"github.com/coder/coder/v2/coderd/notifications" | ||
"github.com/coder/coder/v2/coderd/provisionerdserver" | ||
"github.com/coder/coder/v2/coderd/schedule" | ||
"github.com/coder/coder/v2/coderd/wsbuilder" | ||
"github.com/coder/coder/v2/codersdk" | ||
) | ||
|
||
const TestingStaleInterval = time.Second * 5 | ||
|
||
// Executor automatically starts or stops workspaces. | ||
type Executor struct { | ||
ctx context.Context | ||
|
@@ -52,6 +56,9 @@ type Executor struct { | |
experiments codersdk.Experiments | ||
|
||
metrics executorMetrics | ||
|
||
// Skip provisioner availability check (should only be true for *some* tests) | ||
SkipProvisionerCheck bool | ||
} | ||
|
||
type executorMetrics struct { | ||
|
@@ -131,6 +138,39 @@ func (e *Executor) Run() { | |
}() | ||
} | ||
|
||
func (e *Executor) hasAvailableProvisioners(ctx context.Context, tx database.Store, ws database.Workspace, templateVersionJob database.ProvisionerJob) (bool, error) { | ||
if e.SkipProvisionerCheck { | ||
return true, nil | ||
} | ||
|
||
// Use a shorter stale interval for tests | ||
staleInterval := provisionerdserver.StaleInterval | ||
if testing.Testing() { | ||
staleInterval = TestingStaleInterval | ||
} | ||
Comment on lines
+148
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use the passed in time from |
||
|
||
// Get eligible provisioner daemons for this workspace's template | ||
provisionerDaemons, err := tx.GetProvisionerDaemonsByOrganization(ctx, database.GetProvisionerDaemonsByOrganizationParams{ | ||
OrganizationID: ws.OrganizationID, | ||
WantTags: templateVersionJob.Tags, | ||
}) | ||
if err != nil { | ||
return false, xerrors.Errorf("get provisioner daemons: %w", err) | ||
} | ||
|
||
// Check if any provisioners are active (not stale) | ||
now := dbtime.Now() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be using the passed in time from |
||
for _, pd := range provisionerDaemons { | ||
if pd.LastSeenAt.Valid { | ||
age := now.Sub(pd.LastSeenAt.Time) | ||
if age <= staleInterval { | ||
return true, nil | ||
} | ||
} | ||
} | ||
return false, nil | ||
} | ||
|
||
func (e *Executor) runOnce(t time.Time) Stats { | ||
stats := Stats{ | ||
Transitions: make(map[uuid.UUID]database.WorkspaceTransition), | ||
|
@@ -280,6 +320,22 @@ func (e *Executor) runOnce(t time.Time) Stats { | |
return nil | ||
} | ||
|
||
// Get the template version job to access tags | ||
templateVersionJob, err := tx.GetProvisionerJobByID(e.ctx, activeTemplateVersion.JobID) | ||
if err != nil { | ||
return xerrors.Errorf("get template version job: %w", err) | ||
} | ||
|
||
// Before creating the workspace build, check for available provisioners | ||
hasProvisioners, err := e.hasAvailableProvisioners(e.ctx, tx, ws, templateVersionJob) | ||
if err != nil { | ||
return xerrors.Errorf("check provisioner availability: %w", err) | ||
} | ||
if !hasProvisioners { | ||
log.Warn(e.ctx, "skipping autostart - no available provisioners") | ||
return nil // Skip this workspace | ||
} | ||
|
||
if nextTransition != "" { | ||
builder := wsbuilder.New(ws, nextTransition, *e.buildUsageChecker.Load()). | ||
SetLastWorkspaceBuildInTx(&latestBuild). | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It says it should only be true for some tests, but it seems it's true for almost every test using
coderdtest
. How many tests are actually broken by this change? If it's only a few, I'd rather we just fix those tests (e.g. by adding provisioners) rather than add a skip flag.