8000 feat: add API/SDK support for autostop extension by johnstcn · Pull Request #1778 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat: add API/SDK support for autostop extension #1778

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

Merged
merged 11 commits into from
May 26, 2022
Next Next commit
add initial deadline field to workspace_build
  • Loading branch information
johnstcn committed May 26, 2022
commit c7dff0e4519084bd509c477f693fb99f5096daea
1 change: 1 addition & 0 deletions coderd/coderd.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ func New(options *Options) *API {
r.Put("/", api.putWorkspaceTTL)
})
r.Get("/watch", api.watchWorkspace)
r.Put("/deadline", api.putWorkspaceDeadline)
})
})
r.Route("/workspacebuilds/{workspacebuild}", func(r chi.Router) {
Expand Down
29 changes: 29 additions & 0 deletions coderd/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,35 @@ func (api *API) putWorkspaceTTL(rw http.ResponseWriter, r *http.Request) {
}
}

func (api *API) putWorkspaceDeadline(rw http.ResponseWriter, r *http.Request) {
workspace := httpmw.WorkspaceParam(r)

if !api.Authorize(rw, r, rbac.ActionUpdate, rbac.ResourceWorkspace.
InOrg(workspace.OrganizationID).WithOwner(workspace.OwnerID.String()).WithID(workspace.ID.String())) {
return
}

var req codersdk.PutExtendWorkspaceRequest
if !httpapi.Read(rw, r, &req) {
return
}

build, err := api.Database.GetLatestWorkspaceBuildByWorkspaceID(r.Context(), workspace.ID)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: fmt.Sprintf("get latest workspace build: %s", err),
})
return
}

if build.Transition != database.WorkspaceTransitionStart {
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
Message: fmt.Sprintf("workspace must be started, current status: %s", build.Transition),
})
return
}
}

func (api *API) watchWorkspace(rw http.ResponseWriter, r *http.Request) {
workspace := httpmw.WorkspaceParam(r)

Expand Down
25 changes: 25 additions & 0 deletions coderd/workspaces_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,31 @@ func TestWorkspaceUpdateAutostop(t *testing.T) {
})
}

func TestWorkspaceExtendAutostop(t *testing.T) {
t.Parallel()
var (
ctx = context.Background()
client = coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
user = coderdtest.CreateFirstUser(t, client)
version = coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
project = coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
workspace = coderdtest.CreateWorkspace(t, client, user.OrganizationID, project.ID)
extend = 90 * time.Minute
)

initTTL := time.Now()
req := codersdk.PutExtendWorkspaceRequest{
Deadline: initTTL.Add(extend),
}
err := client.PutExtendWorkspace(ctx, workspace.ID, req)
require.NoError(t, err, "failed to update workspace ttl")

updated, err := client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "failed to fetch updated workspace")
require.Equal(t, workspace.LatestBuild.Deadline.Add(extend), updated.LatestBuild.Deadline)
}

func TestWorkspaceWatcher(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true})
Expand Down
20 changes: 20 additions & 0 deletions codersdk/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,26 @@ func (c *Client) UpdateWorkspaceTTL(ctx context.Context, id uuid.UUID, req Updat
return nil
}

// PutExtendWorkspaceRequest is a request to extend the deadline of
// the active workspace build.
type PutExtendWorkspaceRequest struct {
Deadline time.Time `json:"deadline" validate:"required, datetime=RFC3339"`
}

// PutExtendWorkspace updates the deadline for resources of the latest workspace build.
func (c *Client) PutExtendWorkspace(ctx context.Context, id uuid.UUID, req PutExtendWorkspaceRequest) error {
path := fmt.Sprintf("/api/v2/workspaces/%s/extend", id.String())
res, err := c.Request(ctx, http.MethodPut, path, req)
if err != nil {
return xerrors.Errorf("extend workspace ttl: %w", err)
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return readBodyAsError(res)
}
return nil
}

type WorkspaceFilter struct {
OrganizationID uuid.UUID
// Owner can be a user_id (uuid), "me", or a username
Expand Down
7 changes: 6 additions & 1 deletion site/src/api/typesGenerated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ export interface ProvisionerJobLog {
readonly output: string
}

// From codersdk/workspaces.go:182:6
export interface PutWorkspaceDeadlineRequest {
readonly stop_at: string
}

// From codersdk/roles.go:12:6
export interface Role {
readonly name: string
Expand Down Expand Up @@ -430,7 +435,7 @@ export interface WorkspaceBuildsRequest extends Pagination {
readonly WorkspaceID: string
}

// From codersdk/workspaces.go:180:6
// From codersdk/workspaces.go:200:6
export interface WorkspaceFilter {
readonly OrganizationID: string
readonly Owner: string
Expand Down
0