Skip to content

feat(ws): Implement pause workspace functionality as backend API #328

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

Conversation

andyatmiami
Copy link

@andyatmiami andyatmiami commented May 12, 2025

related: #298

  • Added PauseWorkspaceHandler to handle the pause operation for workspaces.
  • Introduced new route for pausing workspaces in the API.
    • POST api/v1/workspaces/{namespace}/{workspaceName}/actions/pause
  • Created a new EmptyResponse type for successful responses.
  • Added tests for the pause workspace functionality, including success and error cases.
  • Updated OpenAPI/README documentation to include the new pause workspace endpoint.

Functionality was tested via the Swagger client:

image

$ kubectl get workspaces -A
NAMESPACE   NAME                           STATE
default     andy-test-direct-with-secret   Running
default     andy-test-pr-verify            Running
default     andy-test-with-secret          Running
default     andy-test-with-secret-no-op    Running
default     jupyterlab-workspace           Paused

<executed /pause via Swagger client>

$ kubectl get workspaces -A
NAMESPACE   NAME                           STATE
default     andy-test-direct-with-secret   Running
default     andy-test-pr-verify            Paused
default     andy-test-with-secret          Running
default     andy-test-with-secret-no-op    Running
default     jupyterlab-workspace           Paused

$ kubectl get events --sort-by='.lastTimestamp'
LAST SEEN   TYPE      REASON                             OBJECT                                     MESSAGE
...
89s         Normal    Killing                            pod/ws-andy-test-pr-verify-z5qfg-0         Stopping container main
89s         Normal    SuccessfulDelete                   statefulset/ws-andy-test-pr-verify-z5qfg   delete Pod ws-andy-test-pr-verify-z5qfg-0 in StatefulSet ws-andy-test-pr-verify-z5qfg successful

Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign kimwnasptd for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

related: kubeflow#298

- Added PauseWorkspaceHandler to handle the pause operation for workspaces.
- Introduced new route for pausing workspaces in the API.
- Created a new EmptyResponse type for successful responses.
- Added tests for the pause workspace functionality, including success and error cases.
- Updated README/OpenAPI documentation to include the new pause workspace endpoint.

Signed-off-by: Andy Stoneberg <[email protected]>
@andyatmiami andyatmiami force-pushed the feat/workspace-pause-api branch from 0882a6b to 1d39e52 Compare May 15, 2025 19:41
Copy link

@harshad16 harshad16 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well designed
lgtm

small nitpick question, was wondering about the request resposne being empty.
as after the pause action , one has to do get on /workspaces/{namespace}/{workspace_name}

Tested:

Cli:
Screenshot from 2025-05-20 16-23-30

swagger:
Screenshot from 2025-05-20 16-24-04

Comment on lines +424 to +426
"description": "Successful action. Returns an empty JSON object.",
"schema": {
"$ref": "#/definitions/api.EmptyResponse"
Copy link

@harshad16 harshad16 May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"description": "Successful action. Returns an empty JSON object.",
"schema": {
"$ref": "#/definitions/api.EmptyResponse"
"description": "Successful action. Returns the paused workspace object.",
"schema": {
"$ref": "#/definitions/api.WorkspaceEnvelope"

The backend should return the object or the status of the workspace object or custom info that is agreed, so frontend can update the label or module based on this response.
WDYT ? is it for the first iteration, we wanna keep it empty till we discuss the format ?

| PATCH /api/v1/workspaces/{namespace}/{name} | TBD | Patch a Workspace entity |
| PUT /api/v1/workspaces/{namespace}/{name} | TBD | Update a Workspace entity |
| DELETE /api/v1/workspaces/{namespace}/{name} | workspaces_handler | Delete a Workspace entity |
| POST /api/v1/workspaces/{namespace}/{name}/actions/pause | workspace_actions_handler | Pause a running workspace |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Seems like the table format is missing here.
can be neglected for next time

return
}

// Return 200 OK with empty JSON object

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of returning a empty, shall we return the workspace object , so frontend can use this information ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very valid feedback and happy to implement as such if folks agree that is preferred.

my rationale for structuring this as such (with an "empty object") was:

  • this endpoint is really focused and designed to only set the spec.paused attribute - and as such - there is nothing to be returned that the client wouldn't already know if they cared to (or already has rendered in the case of our frontend)... returning the entirety of the workspace implies the client should update/merge that with this existing state - and I didn't feel it necessary/warranted (purely my $0.02!)
    • if client receives 200 response - they can infer the value of spec.paused to be updated in their state without having to parse a payload
  • as this endpoint lives under this /actions "umbrella" - I didn't necessarily want to enforce the Envelope structure when other endpoints that live under /actions (like say, logs or something?) would themselves have totally different structures - such that trying to be consistent within /actions is probably impossible moving forward

Given those 2 points above - I leaned towards {}

But again, it was something I myself wondered during implementation - and willing to change if we get another +1 that the Envelope response would be preferred!

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack, thanks for the explanation behind the return type,
if frontend has the state, and can set the paused based on information, we should be good.

i guess, i need to fimilarize myself with frontend a little bit, how the state of the paused/start are being displayed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andy, for consistency and forward compatibility, returning an envelope object is preferred even for action endpoints like pause.

It will make it much easier on FE if the backend always returns an envelope (plus the right status code) and never an empty response.

This will help, for instance, in case of an error, and avoid a bunch of if and else statements on the FE.
The structure should be like this:

{
"data": {
"status": "paused",
"message": "Workspace successfully paused."
}
}

type PauseResponse struct {
Status string json:"status" // e.g., "paused"
Message string json:"message" // optional
}

If we standardize on envelope makes us easy to evolve etc.

Copy link

@harshad16 harshad16 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

Copy link

@harshad16: changing LGTM is restricted to collaborators

In response to this:

/lgtm

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link
Member

@ederign ederign left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for consistency and forward compatibility, returning an envelope object is preferred even for all backend endpoints

return
}

// Return 200 OK with empty JSON object
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Andy, for consistency and forward compatibility, returning an envelope object is preferred even for action endpoints like pause.

It will make it much easier on FE if the backend always returns an envelope (plus the right status code) and never an empty response.

This will help, for instance, in case of an error, and avoid a bunch of if and else statements on the FE.
The structure should be like this:

{
"data": {
"status": "paused",
"message": "Workspace successfully paused."
}
}

type PauseResponse struct {
Status string json:"status" // e.g., "paused"
Message string json:"message" // optional
}

If we standardize on envelope makes us easy to evolve etc.

@andyatmiami
Copy link
Author

closing this PR in favor of #340 - but will apply all PR review comments as I update and squash those commits!

@github-project-automation github-project-automation bot moved this from Needs Triage to Done in Kubeflow Notebooks May 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Development

Successfully merging this pull request may close these issues.

3 participants