Skip to content

Commit 4f064d4

Browse files
committed
added new route
1 parent a3cfc85 commit 4f064d4

File tree

10 files changed

+329
-10
lines changed

10 files changed

+329
-10
lines changed

cli/restart.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (r *RootCmd) restart() *clibase.Cmd {
3434
return err
3535
}
3636

37-
// get the workspace - this can probably stay in here
37+
// get the workspace
3838
workspace, err := namedWorkspace(inv.Context(), client, inv.Args[0])
3939
if err != nil {
4040
return err

coderd/apidoc/docs.go

Lines changed: 38 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/coderd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,7 @@ func New(options *Options) *API {
646646
r.Route("/builds", func(r chi.Router) {
647647
r.Get("/", api.workspaceBuilds)
648648
r.Post("/", api.postWorkspaceBuilds)
649+
r.Post("/restart", api.restartWorkspace)
649650
})
650651
r.Route("/autostart", func(r chi.Router) {
651652
r.Put("/", api.putWorkspaceAutostart)

coderd/workspacebuilds.go

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -288,16 +288,11 @@ func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Requ
288288
httpapi.Write(ctx, rw, http.StatusOK, apiBuild)
289289
}
290290

291-
func (api *API) postBuild(rw http.ResponseWriter, r *http.Request) (codersdk.WorkspaceBuild, error) {
291+
func (api *API) postBuild(rw http.ResponseWriter, r *http.Request, createBuild codersdk.CreateWorkspaceBuildRequest) (codersdk.WorkspaceBuild, error) {
292292
ctx := r.Context()
293293
apiKey := httpmw.APIKey(r)
294294
workspace := httpmw.WorkspaceParam(r)
295295

296-
var createBuild codersdk.CreateWorkspaceBuildRequest
297-
if !httpapi.Read(ctx, rw, r, &createBuild) {
298-
return codersdk.WorkspaceBuild{}, xerrors.Errorf("Decode CreateWorkspaceBuildRequest")
299-
}
300-
301296
// Doing this up front saves a lot of work if the user doesn't have permission.
302297
// This is checked again in the dbauthz layer, but the check is cached
303298
// and will be a noop later.
@@ -673,6 +668,58 @@ func (api *API) postBuild(rw http.ResponseWriter, r *http.Request) (codersdk.Wor
673668
return apiBuild, nil
674669
}
675670

671+
// Restarts a workspace.
672+
//
673+
// @Summary Restart workspace
674+
// @ID restart-workspace
675+
// @Security CoderSessionToken
676+
// @Accept json
677+
// @Produce json
678+
// @Tags Builds
679+
// @Param workspace path string true "Workspace ID" format(uuid)
680+
// @Success 200 {object} codersdk.WorkspaceBuild
681+
// @Router /workspaces/{workspace}/builds/restart [post]
682+
func (api *API) restartWorkspace(rw http.ResponseWriter, r *http.Request) {
683+
// what about audit
684+
ctx := r.Context()
685+
fmt.Println("in restartWorkspace!!!!!")
686+
687+
// create a build - stop the workspace
688+
build, err := api.postBuild(rw, r, codersdk.CreateWorkspaceBuildRequest{
689+
Transition: codersdk.WorkspaceTransitionStop,
690+
})
691+
if err != nil {
692+
fmt.Println("in postBuildStop err!!!!!")
693+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
694+
Message: "Internal error stopping workspace.",
695+
Detail: err.Error(),
696+
})
697+
return
698+
}
699+
700+
// this seems to return the provisioner job - perhaps we are watching for an error - do i need this
701+
702+
// create a build - start the workspace
703+
build, err = api.postBuild(rw, r, codersdk.CreateWorkspaceBuildRequest{
704+
Transition: codersdk.WorkspaceTransitionStart,
705+
})
706+
if err != nil {
707+
fmt.Println("in postBuildStart err!!!!!")
708+
709+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
710+
Message: "Internal error starting workspace.",
711+
Detail: err.Error(),
712+
})
713+
return
714+
}
715+
716+
// this seems to return the provisioner job - perhaps we are watching for an error - do i need this
717+
718+
// not sure what to return
719+
httpapi.Write(ctx, rw, http.StatusOK, build)
720+
721+
}
722+
676723
// Azure supports instance identity verification:
677724
// https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux#tabgroup_14
678725
//
@@ -690,8 +737,13 @@ func (api *API) postBuild(rw http.ResponseWriter, r *http.Request) (codersdk.Wor
690737
func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
691738
ctx := r.Context()
692739

693-
build, buildErr := api.postBuild(rw, r)
694-
if buildErr != nil {
740+
var createBuild codersdk.CreateWorkspaceBuildRequest
741+
if !httpapi.Read(ctx, rw, r, &createBuild) {
742+
return
743+
}
744+
745+
build, err := api.postBuild(rw, r, createBuild)
746+
if err != nil {
695747
// all errors handled in api.postBuild
696748
return
697749
}

docs/api/builds.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1327,3 +1327,155 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \
13271327
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |
13281328

13291329
To perform this operation, you must be authenticated. [Learn more](authentication.md).
1330+
1331+
## Restart workspace
1332+
1333+
### Code samples
1334+
1335+
```shell
1336+
# Example request using curl
1337+
curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds/restart \
1338+
-H 'Accept: application/json' \
1339+
-H 'Coder-Session-Token: API_KEY'
1340+
```
1341+
1342+
`POST /workspaces/{workspace}/builds/restart`
1343+
1344+
### Parameters
1345+
1346+
| Name | In | Type | Required | Description |
1347+
| ----------- | ---- | ------------ | -------- | ------------ |
1348+
| `workspace` | path | string(uuid) | true | Workspace ID |
1349+
1350+
### Example responses
1351+
1352+
> 200 Response
1353+
1354+
```json
1355+
{
1356+
"build_number": 0,
1357+
"created_at": "2019-08-24T14:15:22Z",
1358+
"daily_cost": 0,
1359+
"deadline": "2019-08-24T14:15:22Z",
1360+
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1361+
"initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3",
1362+
"initiator_name": "string",
1363+
"job": {
1364+
"canceled_at": "2019-08-24T14:15:22Z",
1365+
"completed_at": "2019-08-24T14:15:22Z",
1366+
"created_at": "2019-08-24T14:15:22Z",
1367+
"error": "string",
1368+
"error_code": "MISSING_TEMPLATE_PARAMETER",
1369+
"file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
1370+
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1371+
"started_at": "2019-08-24T14:15:22Z",
1372+
"status": "pending",
1373+
"tags": {
1374+
"property1": "string",
1375+
"property2": "string"
1376+
},
1377+
"worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b"
1378+
},
1379+
"max_deadline": "2019-08-24T14:15:22Z",
1380+
"reason": "initiator",
1381+
"resources": [
1382+
{
1383+
"agents": [
1384+
{
1385+
"apps": [
1386+
{
1387+
"command": "string",
1388+
"display_name": "string",
1389+
"external": true,
1390+
"health": "disabled",
1391+
"healthcheck": {
1392+
"interval": 0,
1393+
"threshold": 0,
1394+
"url": "string"
1395+
},
1396+
"icon": "string",
1397+
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1398+
"sharing_level": "owner",
1399+
"slug": "string",
1400+
"subdomain": true,
1401+
"url": "string"
1402+
}
1403+
],
1404+
"architecture": "string",
1405+
"connection_timeout_seconds": 0,
1406+
"created_at": "2019-08-24T14:15:22Z",
1407+
"directory": "string",
1408+
"disconnected_at": "2019-08-24T14:15:22Z",
1409+
"environment_variables": {
1410+
"property1": "string",
1411+
"property2": "string"
1412+
},
1413+
"expanded_directory": "string",
1414+
"first_connected_at": "2019-08-24T14:15:22Z",
1415+
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1416+
"instance_id": "string",
1417+
"last_connected_at": "2019-08-24T14:15:22Z",
1418+
"latency": {
1419+
"property1": {
1420+
"latency_ms": 0,
1421+
"preferred": true
1422+
},
1423+
"property2": {
1424+
"latency_ms": 0,
1425+
"preferred": true
1426+
}
1427+
},
1428+
"lifecycle_state": "created",
1429+
"login_before_ready": true,
1430+
"name": "string",
1431+
"operating_system": "string",
1432+
"resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f",
1433+
"shutdown_script": "string",
1434+
"shutdown_script_timeout_seconds": 0,
1435+
"startup_logs_length": 0,
1436+
"startup_logs_overflowed": true,
1437+
"startup_script": "string",
1438+
"startup_script_timeout_seconds": 0,
1439+
"status": "connecting",
1440+
"troubleshooting_url": "string",
1441+
"updated_at": "2019-08-24T14:15:22Z",
1442+
"version": "string"
1443+
}
1444+
],
1445+
"created_at": "2019-08-24T14:15:22Z",
1446+
"daily_cost": 0,
1447+
"hide": true,
1448+
"icon": "string",
1449+
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
1450+
"job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f",
1451+
"metadata": [
1452+
{
1453+
"key": "string",
1454+
"sensitive": true,
1455+
"value": "string"
1456+
}
1457+
],
1458+
"name": "string",
1459+
"type": "string",
1460+
"workspace_transition": "start"
1461+
}
1462+
],
1463+
"status": "pending",
1464+
"template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1",
1465+
"template_version_name": "string",
1466+
"transition": "start",
1467+
"updated_at": "2019-08-24T14:15:22Z",
1468+
"workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9",
1469+
"workspace_name": "string",
1470+
"workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7",
1471+
"workspace_owner_name": "string"
1472+
}
1473+
```
1474+
1475+
### Responses
1476+
1477+
| Status | Meaning | Description | Schema |
1478+
| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------ |
1479+
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) |
1480+
1481+
To perform this operation, you must be authenticated. [Learn more](authentication.md).

site/src/api/api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,15 @@ export const stopWorkspace = (workspaceId: string) =>
499499
export const deleteWorkspace = (workspaceId: string) =>
500500
postWorkspaceBuild(workspaceId, { transition: "delete" })
501501

502+
export const restartWorkspace = async (
503+
workspaceId: string,
504+
): Promise<TypesGen.WorkspaceBuild> => {
505+
const response = await axios.post(
506+
`/api/v2/workspaces/${workspaceId}/builds/restart`,
507+
)
508+
return response.data
509+
}
510+
502511
export const cancelWorkspaceBuild = async (
503512
workspaceBuildId: TypesGen.WorkspaceBuild["id"],
504513
): Promise<Types.Message> => {

site/src/components/Workspace/Workspace.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export interface WorkspaceProps {
3939
}
4040
handleStart: () => void
4141
handleStop: () => void
42+
handleRestart: () => void
4243
handleDelete: () => void
4344
handleUpdate: () => void
4445
handleCancel: () => void
@@ -64,6 +65,7 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
6465
scheduleProps,
6566
handleStart,
6667
handleStop,
68+
handleRestart,
6769
handleDelete,
6870
handleUpdate,
6971
handleCancel,
@@ -125,7 +127,7 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
125127
isOutdated={workspace.outdated}
126128
handleStart={handleStart}
127129
handleStop={handleStop}
128-
handleRestart={() => console.log("restarting!")}
130+
handleRestart={handleRestart}
129131
handleDelete={handleDelete}
130132
handleUpdate={handleUpdate}
131133
handleCancel={handleCancel}

site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ export const WorkspaceReadyPage = ({
108108
workspace={workspace}
109109
handleStart={() => workspaceSend({ type: "START" })}
110110
handleStop={() => workspaceSend({ type: "STOP" })}
111+
handleRestart={() => workspaceSend({ type: "RESTART" })}
111112
handleDelete={() => workspaceSend({ type: "ASK_DELETE" })}
112113
handleUpdate={() => workspaceSend({ type: "UPDATE" })}
113114
handleCancel={() => workspaceSend({ type: "CANCEL" })}

0 commit comments

Comments
 (0)