related: #298 - Added PauseActionWorkspaceHandler to handle pausing or unpausing a given workspace - Introduced single new route for starting and pausing workspaces in the API. - `api/v1/workspaces/{namespace}/{name}/actions/pause` - pausing or unpausing operation is specified in the request payload - Created a new WorkspaceActionPauseEnvelope type for successful responses. - Leveraging JSONPatch / client.RawPatch to ensure Workspace in "valid state" before attempting action - for `start`: `spec.paused` must be `true`, and `status.state` must be `Paused` - for `pause`: `spec.paused` must be `false` - note: I would love to have a `status.state` check here of `status.state != Paused`, but that type of comparison is not supported in [JSONPatch](https://datatracker.ietf.org/doc/html/rfc6902#section-4.6) - Added tests for the new API, including success and error cases. - Updated README/OpenAPI documentation to include the new endpoints. --- As an interesting "edge case" worth calling out, the following payload is currently honored by the API: ``` { "data": {} } ``` Given the `WorkspaceActionPause` struct is simply `{"paused": true|false}`, the "empty" Envelope presented above deserializes the JSON using the zero value of `bool` (which is `false`). Our validation today is always performed against the **deserialized** object, and as such impossible to distinguish the following cases: ``` { "data": {} } ``` vs ``` { "data": { "paused": false } } ``` The effort and (relative) complexity to prevent this and return a `422` in this scenario was not deemed "worth it" for the time being. As a result, a test case has been added for this specific scenario to at minimum document this "strange" behavior. - Clients, however, should **NOT** rely on this behavior and always provide a fully defined `WorkspaceActionPause` JSON object to ensure future compatibility. Signed-off-by: Andy Stoneberg <astonebe@redhat.com> |
||
|---|---|---|
| .. | ||
| api | ||
| cmd | ||
| internal | ||
| openapi | ||
| .dockerignore | ||
| .gitignore | ||
| .golangci.yml | ||
| Dockerfile | ||
| Makefile | ||
| OWNERS | ||
| README.md | ||
| go.mod | ||
| go.sum | ||
README.md
Kubeflow Workspaces Backend
The Kubeflow Workspaces Backend is the backend for frontend (BFF) used by the Kubeflow Workspaces Frontend as part of Kubeflow Notebooks 2.0.
⚠️ Warning ⚠️
The Kubeflow Workspaces Backend is a work in progress and is NOT currently ready for use. We greatly appreciate any contributions.
Building and Deploying
TBD
Development
Run the following command to build the BFF:
make build
After building it, you can run our app with:
make run
If you want to use a different port:
make run PORT=8000
Endpoints
| URL Pattern | Handler | Action |
|---|---|---|
| GET /api/v1/healthcheck | healthcheck_handler | Show application information |
| GET /api/v1/namespaces | namespaces_handler | Get all Namespaces |
| GET /api/v1/swagger/ | swagger_handler | Swagger API documentation |
| GET /api/v1/workspaces | workspaces_handler | Get all Workspaces |
| GET /api/v1/workspaces/{namespace} | workspaces_handler | Get all Workspaces from a namespace |
| POST /api/v1/workspaces/{namespace} | workspaces_handler | Create a Workspace in a given namespace |
| GET /api/v1/workspaces/{namespace}/{name} | workspaces_handler | Get a Workspace entity |
| 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 | Set paused state of a workspace |
| GET /api/v1/workspacekinds | workspacekinds_handler | Get all WorkspaceKind |
| POST /api/v1/workspacekinds | TBD | Create a WorkspaceKind |
| GET /api/v1/workspacekinds/{name} | workspacekinds_handler | Get a WorkspaceKind entity |
| PATCH /api/v1/workspacekinds/{name} | TBD | Patch a WorkspaceKind entity |
| PUT /api/v1/workspacekinds/{name} | TBD | Update a WorkspaceKind entity |
| DELETE /api/v1/workspacekinds/{name} | TBD | Delete a WorkspaceKind entity |
Sample local calls
Healthcheck:
# GET /api/v1/healthcheck
curl -i localhost:4000/api/v1/healthcheck
List all Namespaces:
# GET /api/v1/namespaces
curl -i localhost:4000/api/v1/namespaces
List all Workspaces:
# GET /api/v1/workspaces/
curl -i localhost:4000/api/v1/workspaces
List all Workspaces in a Namespace:
# GET /api/v1/workspaces/{namespace}
curl -i localhost:4000/api/v1/workspaces/default
Create a Workspace:
# POST /api/v1/workspaces/{namespace}
curl -X POST http://localhost:4000/api/v1/workspaces/default \
-H "Content-Type: application/json" \
-d '{
"data": {
"name": "dora",
"kind": "jupyterlab",
"paused": false,
"deferUpdates": false,
"podTemplate": {
"podMetadata": {
"labels": {
"app": "dora"
},
"annotations": {
"app": "dora"
}
},
"volumes": {
"home": "workspace-home-bella",
"data": [
{
"pvcName": "workspace-data-bella",
"mountPath": "/data/my-data",
"readOnly": false
}
]
},
"options": {
"imageConfig": "jupyterlab_scipy_190",
"podConfig": "tiny_cpu"
}
}
}
}'
Get a Workspace:
# GET /api/v1/workspaces/{namespace}/{name}
curl -i localhost:4000/api/v1/workspaces/default/dora
Pause a Workspace:
# POST /api/v1/workspaces/{namespace}/{name}/actions/pause
curl -X POST localhost:4000/api/v1/workspaces/default/dora/actions/pause \
-H "Content-Type: application/json" \
-d '{
"data": {
"paused": true
}
}'
Start a Workspace:
# POST /api/v1/workspaces/{namespace}/{name}/actions/pause
curl -X POST localhost:4000/api/v1/workspaces/default/dora/actions/pause \
-H "Content-Type: application/json" \
-d '{
"data": {
"paused": false
}
}'
Delete a Workspace:
# DELETE /api/v1/workspaces/{namespace}/{name}
curl -X DELETE localhost:4000/api/v1/workspaces/default/dora
List all WorkspaceKinds:
# GET /api/v1/workspacekinds
curl -i localhost:4000/api/v1/workspacekinds
Get a WorkspaceKind:
# GET /api/v1/workspacekinds/{name}
curl -i localhost:4000/api/v1/workspacekinds/jupyterlab