feat(coderd): store workspace proxy version in the database (#10790)

Stores workspace proxy version in database upon registration.
This commit is contained in:
Cian Johnston 2023-11-21 11:21:25 +00:00 committed by GitHub
parent 7060069034
commit abafc0863c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 56 additions and 12 deletions

View File

@ -254,7 +254,7 @@ func TestIsDERPPath(t *testing.T) {
//{
// path: "/derp",
// expected: true,
//},
// },
{
path: "/derp/",
expected: true,

3
coderd/apidoc/docs.go generated
View File

@ -11898,6 +11898,9 @@ const docTemplate = `{
"type": "string",
"format": "date-time"
},
"version": {
"type": "string"
},
"wildcard_hostname": {
"description": "WildcardHostname is the wildcard hostname for subdomain apps.\nE.g. *.us.example.com\nE.g. *--suffix.au.example.com\nOptional. Does not need to be on the same domain as PathAppURL.",
"type": "string"

View File

@ -10827,6 +10827,9 @@
"type": "string",
"format": "date-time"
},
"version": {
"type": "string"
},
"wildcard_hostname": {
"description": "WildcardHostname is the wildcard hostname for subdomain apps.\nE.g. *.us.example.com\nE.g. *--suffix.au.example.com\nOptional. Does not need to be on the same domain as PathAppURL.",
"type": "string"

View File

@ -5563,6 +5563,7 @@ func (q *FakeQuerier) RegisterWorkspaceProxy(_ context.Context, arg database.Reg
p.WildcardHostname = arg.WildcardHostname
p.DerpEnabled = arg.DerpEnabled
p.DerpOnly = arg.DerpOnly
p.Version = arg.Version
p.UpdatedAt = dbtime.Now()
q.workspaceProxies[i] = p
return p, nil

View File

@ -1127,7 +1127,8 @@ CREATE TABLE workspace_proxies (
token_hashed_secret bytea NOT NULL,
region_id integer NOT NULL,
derp_enabled boolean DEFAULT true NOT NULL,
derp_only boolean DEFAULT false NOT NULL
derp_only boolean DEFAULT false NOT NULL,
version text DEFAULT ''::text NOT NULL
);
COMMENT ON COLUMN workspace_proxies.icon IS 'Expects an emoji character. (/emojis/1f1fa-1f1f8.png)';

View File

@ -0,0 +1,3 @@
BEGIN;
ALTER TABLE workspace_proxies DROP COLUMN version;
COMMIT;

View File

@ -0,0 +1,3 @@
BEGIN;
ALTER TABLE workspace_proxies ADD COLUMN version TEXT DEFAULT ''::TEXT NOT NULL;
COMMIT;

View File

@ -2364,7 +2364,8 @@ type WorkspaceProxy struct {
RegionID int32 `db:"region_id" json:"region_id"`
DerpEnabled bool `db:"derp_enabled" json:"derp_enabled"`
// Disables app/terminal proxying for this proxy and only acts as a DERP relay.
DerpOnly bool `db:"derp_only" json:"derp_only"`
DerpOnly bool `db:"derp_only" json:"derp_only"`
Version string `db:"version" json:"version"`
}
type WorkspaceResource struct {

View File

@ -3667,7 +3667,7 @@ func (q *sqlQuerier) UpdateProvisionerJobWithCompleteByID(ctx context.Context, a
const getWorkspaceProxies = `-- name: GetWorkspaceProxies :many
SELECT
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
FROM
workspace_proxies
WHERE
@ -3697,6 +3697,7 @@ func (q *sqlQuerier) GetWorkspaceProxies(ctx context.Context) ([]WorkspaceProxy,
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
); err != nil {
return nil, err
}
@ -3713,7 +3714,7 @@ func (q *sqlQuerier) GetWorkspaceProxies(ctx context.Context) ([]WorkspaceProxy,
const getWorkspaceProxyByHostname = `-- name: GetWorkspaceProxyByHostname :one
SELECT
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
FROM
workspace_proxies
WHERE
@ -3772,13 +3773,14 @@ func (q *sqlQuerier) GetWorkspaceProxyByHostname(ctx context.Context, arg GetWor
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}
const getWorkspaceProxyByID = `-- name: GetWorkspaceProxyByID :one
SELECT
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
FROM
workspace_proxies
WHERE
@ -3804,13 +3806,14 @@ func (q *sqlQuerier) GetWorkspaceProxyByID(ctx context.Context, id uuid.UUID) (W
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}
const getWorkspaceProxyByName = `-- name: GetWorkspaceProxyByName :one
SELECT
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
FROM
workspace_proxies
WHERE
@ -3837,6 +3840,7 @@ func (q *sqlQuerier) GetWorkspaceProxyByName(ctx context.Context, name string) (
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}
@ -3858,7 +3862,7 @@ INSERT INTO
deleted
)
VALUES
($1, '', '', $2, $3, $4, $5, $6, $7, $8, $9, false) RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
($1, '', '', $2, $3, $4, $5, $6, $7, $8, $9, false) RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
`
type InsertWorkspaceProxyParams struct {
@ -3900,6 +3904,7 @@ func (q *sqlQuerier) InsertWorkspaceProxy(ctx context.Context, arg InsertWorkspa
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}
@ -3912,10 +3917,11 @@ SET
wildcard_hostname = $2 :: text,
derp_enabled = $3 :: boolean,
derp_only = $4 :: boolean,
version = $5 :: text,
updated_at = Now()
WHERE
id = $5
RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
id = $6
RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
`
type RegisterWorkspaceProxyParams struct {
@ -3923,6 +3929,7 @@ type RegisterWorkspaceProxyParams struct {
WildcardHostname string `db:"wildcard_hostname" json:"wildcard_hostname"`
DerpEnabled bool `db:"derp_enabled" json:"derp_enabled"`
DerpOnly bool `db:"derp_only" json:"derp_only"`
Version string `db:"version" json:"version"`
ID uuid.UUID `db:"id" json:"id"`
}
@ -3932,6 +3939,7 @@ func (q *sqlQuerier) RegisterWorkspaceProxy(ctx context.Context, arg RegisterWor
arg.WildcardHostname,
arg.DerpEnabled,
arg.DerpOnly,
arg.Version,
arg.ID,
)
var i WorkspaceProxy
@ -3949,6 +3957,7 @@ func (q *sqlQuerier) RegisterWorkspaceProxy(ctx context.Context, arg RegisterWor
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}
@ -3971,7 +3980,7 @@ SET
updated_at = Now()
WHERE
id = $5
RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only
RETURNING id, name, display_name, icon, url, wildcard_hostname, created_at, updated_at, deleted, token_hashed_secret, region_id, derp_enabled, derp_only, version
`
type UpdateWorkspaceProxyParams struct {
@ -4006,6 +4015,7 @@ func (q *sqlQuerier) UpdateWorkspaceProxy(ctx context.Context, arg UpdateWorkspa
&i.RegionID,
&i.DerpEnabled,
&i.DerpOnly,
&i.Version,
)
return i, err
}

View File

@ -25,6 +25,7 @@ SET
wildcard_hostname = @wildcard_hostname :: text,
derp_enabled = @derp_enabled :: boolean,
derp_only = @derp_only :: boolean,
version = @version :: text,
updated_at = Now()
WHERE
id = @id

View File

@ -59,6 +59,7 @@ type WorkspaceProxy struct {
CreatedAt time.Time `json:"created_at" format:"date-time" table:"created_at,default_sort"`
UpdatedAt time.Time `json:"updated_at" format:"date-time" table:"updated_at"`
Deleted bool `json:"deleted" table:"deleted"`
Version string `json:"version" table:"version"`
}
type CreateWorkspaceProxyRequest struct {

View File

@ -20,7 +20,7 @@ We track the following resources:
| User<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>avatar_url</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table> |
| Workspace<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>automatic_updates</td><td>true</td></tr><tr><td>autostart_schedule</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deleting_at</td><td>true</td></tr><tr><td>dormant_at</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>owner_id</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>ttl</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
| WorkspaceBuild<br><i>start, stop</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>build_number</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>daily_cost</td><td>false</td></tr><tr><td>deadline</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>initiator_by_avatar_url</td><td>false</td></tr><tr><td>initiator_by_username</td><td>false</td></tr><tr><td>initiator_id</td><td>false</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>max_deadline</td><td>false</td></tr><tr><td>provisioner_state</td><td>false</td></tr><tr><td>reason</td><td>false</td></tr><tr><td>template_version_id</td><td>true</td></tr><tr><td>transition</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>workspace_id</td><td>false</td></tr></tbody></table> |
| WorkspaceProxy<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table> |
| WorkspaceProxy<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>derp_enabled</td><td>true</td></tr><tr><td>derp_only</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>region_id</td><td>true</td></tr><tr><td>token_hashed_secret</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>url</td><td>true</td></tr><tr><td>version</td><td>true</td></tr><tr><td>wildcard_hostname</td><td>true</td></tr></tbody></table> |
<!-- End generated by 'make docs/admin/audit-logs.md'. -->

View File

@ -1513,6 +1513,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaceproxies \
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
]
@ -1551,6 +1552,7 @@ Status Code **200**
| `»»»» warnings` | array | false | | Warnings do not prevent the workspace proxy from being healthy, but should be addressed. |
| `»»» status` | [codersdk.ProxyHealthStatus](schemas.md#codersdkproxyhealthstatus) | false | | |
| `»» updated_at` | string(date-time) | false | | |
| `»» version` | string | false | | |
| `»» wildcard_hostname` | string | false | | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. _.us.example.com E.g. _--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. |
#### Enumerated Values
@ -1619,6 +1621,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaceproxies \
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
```
@ -1675,6 +1678,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy} \
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
```
@ -1789,6 +1793,7 @@ curl -X PATCH http://coder-server:8080/api/v2/workspaceproxies/{workspaceproxy}
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
```

3
docs/api/schemas.md generated
View File

@ -4086,6 +4086,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
]
@ -6649,6 +6650,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
"status": "ok"
},
"updated_at": "2019-08-24T14:15:22Z",
"version": "string",
"wildcard_hostname": "string"
}
```
@ -6669,6 +6671,7 @@ If the schedule is empty, the user will be updated to use the default schedule.|
| `path_app_url` | string | false | | Path app URL is the URL to the base path for path apps. Optional unless wildcard_hostname is set. E.g. https://us.example.com |
| `status` | [codersdk.WorkspaceProxyStatus](#codersdkworkspaceproxystatus) | false | | Status is the latest status check of the proxy. This will be empty for deleted proxies. This value can be used to determine if a workspace proxy is healthy and ready to use. |
| `updated_at` | string | false | | |
| `version` | string | false | | |
| `wildcard_hostname` | string | false | | Wildcard hostname is the wildcard hostname for subdomain apps. E.g. _.us.example.com E.g. _--suffix.au.example.com Optional. Does not need to be on the same domain as PathAppURL. |
## codersdk.WorkspaceProxyStatus

View File

@ -207,6 +207,7 @@ var auditableResourcesTypes = map[any]map[string]Action{
"derp_enabled": ActionTrack,
"derp_only": ActionTrack,
"region_id": ActionTrack,
"version": ActionTrack,
},
}

View File

@ -31,6 +31,7 @@ func insertProxy(t *testing.T, db database.Store, url string) database.Workspace
Url: url,
WildcardHostname: "",
ID: proxy.ID,
Version: `v2.34.5-test+beefcake`,
})
require.NoError(t, err, "failed to update proxy")
return proxy

View File

@ -625,6 +625,7 @@ func (api *API) workspaceProxyRegister(rw http.ResponseWriter, r *http.Request)
DerpEnabled: req.DerpEnabled,
DerpOnly: req.DerpOnly,
WildcardHostname: req.WildcardHostname,
Version: req.Version,
})
if err != nil {
return xerrors.Errorf("register workspace proxy: %w", err)
@ -951,6 +952,7 @@ func convertProxy(p database.WorkspaceProxy, status proxyhealth.ProxyStatus) cod
CreatedAt: p.CreatedAt,
UpdatedAt: p.UpdatedAt,
Deleted: p.Deleted,
Version: p.Version,
Status: codersdk.WorkspaceProxyStatus{
Status: codersdk.ProxyHealthStatus(status.Status),
Report: status.Report,

View File

@ -1581,6 +1581,7 @@ export interface WorkspaceProxy extends Region {
readonly created_at: string;
readonly updated_at: string;
readonly deleted: boolean;
readonly version: string;
}
// From codersdk/deployment.go

View File

@ -85,6 +85,7 @@ export const MockPrimaryWorkspaceProxy: TypesGen.WorkspaceProxy = {
derp_only: false,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
version: "v2.34.5-test+primary",
deleted: false,
status: {
status: "ok",
@ -105,6 +106,7 @@ export const MockHealthyWildWorkspaceProxy: TypesGen.WorkspaceProxy = {
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
version: "v2.34.5-test+haswildcard",
status: {
status: "ok",
checked_at: new Date().toISOString(),
@ -123,6 +125,7 @@ export const MockUnhealthyWildWorkspaceProxy: TypesGen.WorkspaceProxy = {
derp_only: true,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
version: "v2.34.5-test+unhealthy",
deleted: false,
status: {
status: "unhealthy",
@ -151,6 +154,7 @@ export const MockWorkspaceProxies: TypesGen.WorkspaceProxy[] = [
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
deleted: false,
version: "v2.34.5-test+nowildcard",
status: {
status: "ok",
checked_at: new Date().toISOString(),