-
Notifications
You must be signed in to change notification settings - Fork 881
feat: update workspace deadline when workspace ttl updated #2165
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
Changes from all commits
5c443de
c2127c1
07320a4
7846dd8
6d7187d
daa9a5f
fe79c0c
85da57b
8c38a74
a4c07df
582873a
9a7c623
0278a93
a372dce
ac1d29a
23b474c
de28477
a52d815
fd86474
2b9f93c
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 |
---|---|---|
@@ -1,12 +1,14 @@ | ||
package cli | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"time" | ||
|
||
"github.com/spf13/cobra" | ||
"golang.org/x/xerrors" | ||
|
||
"github.com/coder/coder/cli/cliui" | ||
"github.com/coder/coder/codersdk" | ||
) | ||
|
||
|
@@ -89,6 +91,30 @@ func ttlset() *cobra.Command { | |
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "warning: ttl rounded down to %s\n", truncated) | ||
} | ||
|
||
if changed, newDeadline := changedNewDeadline(workspace, truncated); changed { | ||
// For the purposes of the user, "less than a minute" is essentially the same as "immediately". | ||
timeRemaining := time.Until(newDeadline).Truncate(time.Minute) | ||
humanRemaining := "in " + timeRemaining.String() | ||
if timeRemaining <= 0 { | ||
humanRemaining = "immediately" | ||
} | ||
_, err = cliui.Prompt(cmd, cliui.PromptOptions{ | ||
Text: fmt.Sprintf( | ||
"Workspace %q will be stopped %s. Are you sure?", | ||
workspace.Name, | ||
humanRemaining, | ||
), | ||
Default: "yes", | ||
IsConfirm: true, | ||
Comment on lines
+101
to
+108
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. review: we can skip the prompt if |
||
}) | ||
if err != nil { | ||
if errors.Is(err, cliui.Canceled) { | ||
return nil | ||
} | ||
return err | ||
} | ||
} | ||
|
||
millis := truncated.Milliseconds() | ||
if err = client.UpdateWorkspaceTTL(cmd.Context(), workspace.ID, codersdk.UpdateWorkspaceTTLRequest{ | ||
TTLMillis: &millis, | ||
|
@@ -131,3 +157,18 @@ func ttlunset() *cobra.Command { | |
}, | ||
} | ||
} | ||
|
||
func changedNewDeadline(ws codersdk.Workspace, newTTL time.Duration) (changed bool, newDeadline time.Time) { | ||
if ws.LatestBuild.Transition != codersdk.WorkspaceTransitionStart { | ||
// not running | ||
return false, newDeadline | ||
} | ||
|
||
if ws.LatestBuild.Job.CompletedAt == nil { | ||
// still building | ||
return false, newDeadline | ||
} | ||
|
||
newDeadline = ws.LatestBuild.Job.CompletedAt.Add(newTTL) | ||
return true, newDeadline | ||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -566,17 +566,57 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) { | |||
return | ||||
} | ||||
|
||||
err = api.Database.UpdateWorkspaceTTL(r.Context(), database.UpdateWorkspaceTTLParams{ | ||||
ID: workspace.ID, | ||||
Ttl: dbTTL, | ||||
err = api.Database.InTx(func(s database.Store) error { | ||||
if err := s.UpdateWorkspaceTTL(r.Context(), database.UpdateWorkspaceTTLParams{ | ||||
ID: workspace.ID, | ||||
Ttl: dbTTL, | ||||
}); err != nil { | ||||
return xerrors.Errorf("update workspace TTL: %w", err) | ||||
} | ||||
|
||||
// Also extend the workspace deadline if the workspace is running | ||||
latestBuild, err := s.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID) | ||||
if err != nil { | ||||
return xerrors.Errorf("get latest workspace build: %w", err) | ||||
} | ||||
|
||||
if latestBuild.Transition != database.WorkspaceTransitionStart { | ||||
return nil // nothing to do | ||||
} | ||||
|
||||
if latestBuild.UpdatedAt.IsZero() { | ||||
// Build in progress; provisionerd should update with the new TTL. | ||||
return nil | ||||
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. Question: What happens if a user starts a workspace with one TTL, but tries to update the TTL before the build is complete? As a user, I'd expect the new TTL to be in-effect once the build has completed or receive an error that TTL cannot be updated (yet). 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. See coder/coderd/provisionerdaemons.go Line 598 in 567e4af
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. Ooh yeah that makes sense, thanks for clarifying! |
||||
} | ||||
|
||||
var newDeadline time.Time | ||||
if dbTTL.Valid { | ||||
newDeadline = latestBuild.UpdatedAt.Add(time.Duration(dbTTL.Int64)) | ||||
} | ||||
|
||||
if err := s.UpdateWorkspaceBuildByID( | ||||
r.Context(), | ||||
database.UpdateWorkspaceBuildByIDParams{ | ||||
ID: latestBuild.ID, | ||||
UpdatedAt: latestBuild.UpdatedAt, | ||||
ProvisionerState: latestBuild.ProvisionerState, | ||||
Deadline: newDeadline, | ||||
}, | ||||
); err != nil { | ||||
return xerrors.Errorf("update workspace deadline: %w", err) | ||||
} | ||||
return nil | ||||
}) | ||||
|
||||
johnstcn marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
if err != nil { | ||||
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{ | ||||
Message: "Internal error updating workspace TTL.", | ||||
Message: "Error updating workspace time until shutdown!", | ||||
Detail: err.Error(), | ||||
}) | ||||
return | ||||
} | ||||
|
||||
httpapi.Write(rw, http.StatusOK, nil) | ||||
} | ||||
|
||||
func (api *API) putExtendWorkspace(rw http.ResponseWriter, r *http.Request) { | ||||
|
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.
praise: wonderful strings!