Skip to content

Commit 6889450

Browse files
committed
feat: add slug property to app, use in URLs
1 parent efdd5d5 commit 6889450

30 files changed

+406
-222
lines changed

coderd/coderdtest/authorize.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
330330
Id: "something",
331331
Auth: &proto.Agent_Token{},
332332
Apps: []*proto.App{{
333+
Slug: "testapp",
333334
Name: "testapp",
334335
Url: "http://localhost:3000",
335336
}},
@@ -371,7 +372,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
371372
"{template}": template.ID.String(),
372373
"{fileID}": file.ID.String(),
373374
"{workspaceresource}": workspace.LatestBuild.Resources[0].ID.String(),
374-
"{workspaceapp}": workspace.LatestBuild.Resources[0].Agents[0].Apps[0].Name,
375+
"{workspaceapp}": workspace.LatestBuild.Resources[0].Agents[0].Apps[0].Slug,
375376
"{templateversion}": version.ID.String(),
376377
"{jobID}": templateVersionDryRun.ID.String(),
377378
"{templatename}": template.Name,

coderd/database/databasefake/databasefake.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1705,15 +1705,15 @@ func (q *fakeQuerier) GetWorkspaceAgentsCreatedAfter(_ context.Context, after ti
17051705
return workspaceAgents, nil
17061706
}
17071707

1708-
func (q *fakeQuerier) GetWorkspaceAppByAgentIDAndName(_ context.Context, arg database.GetWorkspaceAppByAgentIDAndNameParams) (database.WorkspaceApp, error) {
1708+
func (q *fakeQuerier) GetWorkspaceAppByAgentIDAndSlug(_ context.Context, arg database.GetWorkspaceAppByAgentIDAndSlugParams) (database.WorkspaceApp, error) {
17091709
q.mutex.RLock()
17101710
defer q.mutex.RUnlock()
17111711

17121712
for _, app := range q.workspaceApps {
17131713
if app.AgentID != arg.AgentID {
17141714
continue
17151715
}
1716-
if app.Name != arg.Name {
1716+
if app.Slug != arg.Slug {
17171717
continue
17181718
}
17191719
return app, nil
@@ -2362,6 +2362,7 @@ func (q *fakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
23622362
ID: arg.ID,
23632363
AgentID: arg.AgentID,
23642364
CreatedAt: arg.CreatedAt,
2365+
Slug: arg.Slug,
23652366
Name: arg.Name,
23662367
Icon: arg.Icon,
23672368
Command: arg.Command,

coderd/database/dump.sql

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
-- drop "slug" column from "workspace_apps" table
2+
ALTER TABLE "workspace_apps" DROP COLUMN "slug";
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-- add "slug" column to "workspace_apps" table
2+
ALTER TABLE "workspace_apps" ADD COLUMN "slug" text DEFAULT '';
3+
4+
-- copy the "name" column for each workspace app to the "slug" column
5+
UPDATE "workspace_apps" SET "slug" = "name";
6+
7+
-- make "slug" column not nullable and remove default
8+
ALTER TABLE "workspace_apps" ALTER COLUMN "slug" SET NOT NULL;
9+
ALTER TABLE "workspace_apps" ALTER COLUMN "slug" DROP DEFAULT;

coderd/database/models.go

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

coderd/database/querier.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

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

coderd/database/queries/workspaceapps.sql

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
-- name: GetWorkspaceAppsByAgentID :many
2-
SELECT * FROM workspace_apps WHERE agent_id = $1 ORDER BY name ASC;
2+
SELECT * FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC;
33

44
-- name: GetWorkspaceAppsByAgentIDs :many
5-
SELECT * FROM workspace_apps WHERE agent_id = ANY(@ids :: uuid [ ]) ORDER BY name ASC;
5+
SELECT * FROM workspace_apps WHERE agent_id = ANY(@ids :: uuid [ ]) ORDER BY slug ASC;
66

7-
-- name: GetWorkspaceAppByAgentIDAndName :one
8-
SELECT * FROM workspace_apps WHERE agent_id = $1 AND name = $2;
7+
-- name: GetWorkspaceAppByAgentIDAndSlug :one
8+
SELECT * FROM workspace_apps WHERE agent_id = $1 AND slug = $2;
99

1010
-- name: GetWorkspaceAppsCreatedAfter :many
11-
SELECT * FROM workspace_apps WHERE created_at > $1 ORDER BY name ASC;
11+
SELECT * FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC;
1212

1313
-- name: InsertWorkspaceApp :one
1414
INSERT INTO
1515
workspace_apps (
1616
id,
1717
created_at,
1818
agent_id,
19+
slug,
1920
name,
2021
icon,
2122
command,
@@ -28,7 +29,7 @@ INSERT INTO
2829
health
2930
)
3031
VALUES
31-
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) RETURNING *;
32+
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING *;
3233

3334
-- name: UpdateWorkspaceAppHealthByID :exec
3435
UPDATE

coderd/httpapi/url.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ var (
1414
// Remove the "starts with" and "ends with" regex components.
1515
nameRegex = strings.Trim(UsernameValidRegex.String(), "^$")
1616
appURL = regexp.MustCompile(fmt.Sprintf(
17-
// {PORT/APP_NAME}--{AGENT_NAME}--{WORKSPACE_NAME}--{USERNAME}
18-
`^(?P<AppName>%[1]s)--(?P<AgentName>%[1]s)--(?P<WorkspaceName>%[1]s)--(?P<Username>%[1]s)$`,
17+
// {PORT/APP_SLUG}--{AGENT_NAME}--{WORKSPACE_NAME}--{USERNAME}
18+
`^(?P<AppSlug>%[1]s)--(?P<AgentName>%[1]s)--(?P<WorkspaceName>%[1]s)--(?P<Username>%[1]s)$`,
1919
nameRegex))
2020

2121
validHostnameLabelRegex = regexp.MustCompile(`^[a-z0-9]([-a-z0-9]*[a-z0-9])?$`)
2222
)
2323

2424
// ApplicationURL is a parsed application URL hostname.
2525
type ApplicationURL struct {
26-
// Only one of AppName or Port will be set.
27-
AppName string
26+
// Only one of AppSlug or Port will be set.
27+
AppSlug string
2828
Port uint16
2929
AgentName string
3030
WorkspaceName string
@@ -34,12 +34,12 @@ type ApplicationURL struct {
3434
// String returns the application URL hostname without scheme. You will likely
3535
// want to append a period and the base hostname.
3636
func (a ApplicationURL) String() string {
37-
appNameOrPort := a.AppName
37+
appSlugOrPort := a.AppSlug
3838
if a.Port != 0 {
39-
appNameOrPort = strconv.Itoa(int(a.Port))
39+
appSlugOrPort = strconv.Itoa(int(a.Port))
4040
}
4141

42-
return fmt.Sprintf("%s--%s--%s--%s", appNameOrPort, a.AgentName, a.WorkspaceName, a.Username)
42+
return fmt.Sprintf("%s--%s--%s--%s", appSlugOrPort, a.AgentName, a.WorkspaceName, a.Username)
4343
}
4444

4545
// ParseSubdomainAppURL parses an ApplicationURL from the given subdomain. If
@@ -60,19 +60,19 @@ func ParseSubdomainAppURL(subdomain string) (ApplicationURL, error) {
6060
}
6161
matchGroup := matches[0]
6262

63-
appName, port := AppNameOrPort(matchGroup[appURL.SubexpIndex("AppName")])
63+
appSlug, port := AppSlugOrPort(matchGroup[appURL.SubexpIndex("AppSlug")])
6464
return ApplicationURL{
65-
AppName: appName,
65+
AppSlug: appSlug,
6666
Port: port,
6767
AgentName: matchGroup[appURL.SubexpIndex("AgentName")],
6868
WorkspaceName: matchGroup[appURL.SubexpIndex("WorkspaceName")],
6969
Username: matchGroup[appURL.SubexpIndex("Username")],
7070
}, nil
7171
}
7272

73-
// AppNameOrPort takes a string and returns either the input string or a port
73+
// AppSlugOrPort takes a string and returns either the input string or a port
7474
// number.
75-
func AppNameOrPort(val string) (string, uint16) {
75+
func AppSlugOrPort(val string) (string, uint16) {
7676
port, err := strconv.ParseUint(val, 10, 16)
7777
if err != nil || port == 0 {
7878
port = 0

coderd/httpapi/url_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestApplicationURLString(t *testing.T) {
2525
{
2626
Name: "AppName",
2727
URL: httpapi.ApplicationURL{
28-
AppName: "app",
28+
AppSlug: "app",
2929
Port: 0,
3030
AgentName: "agent",
3131
WorkspaceName: "workspace",
@@ -36,7 +36,7 @@ func TestApplicationURLString(t *testing.T) {
3636
{
3737
Name: "Port",
3838
URL: httpapi.ApplicationURL{
39-
AppName: "",
39+
AppSlug: "",
4040
Port: 8080,
4141
AgentName: "agent",
4242
WorkspaceName: "workspace",
@@ -47,7 +47,7 @@ func TestApplicationURLString(t *testing.T) {
4747
{
4848
Name: "Both",
4949
URL: httpapi.ApplicationURL{
50-
AppName: "app",
50+
AppSlug: "app",
5151
Port: 8080,
5252
AgentName: "agent",
5353
WorkspaceName: "workspace",
@@ -111,7 +111,7 @@ func TestParseSubdomainAppURL(t *testing.T) {
111111
Name: "AppName--Agent--Workspace--User",
112112
Subdomain: "app--agent--workspace--user",
113113
Expected: httpapi.ApplicationURL{
114-
AppName: "app",
114+
AppSlug: "app",
115115
Port: 0,
116116
AgentName: "agent",
117117
WorkspaceName: "workspace",
@@ -122,7 +122,7 @@ func TestParseSubdomainAppURL(t *testing.T) {
122122
Name: "Port--Agent--Workspace--User",
123123
Subdomain: "8080--agent--workspace--user",
124124
Expected: httpapi.ApplicationURL{
125-
AppName: "",
125+
AppSlug: "",
126126
Port: 8080,
127127
AgentName: "agent",
128128
WorkspaceName: "workspace",
@@ -133,7 +133,7 @@ func TestParseSubdomainAppURL(t *testing.T) {
133133
Name: "HyphenatedNames",
134134
Subdomain: "app-name--agent-name--workspace-name--user-name",
135135
Expected: httpapi.ApplicationURL{
136-
AppName: "app-name",
136+
AppSlug: "app-name",
137137
Port: 0,
138138
AgentName: "agent-name",
139139
WorkspaceName: "workspace-name",

coderd/provisionerdaemons.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/coder/coder/coderd/rbac"
2929
"github.com/coder/coder/coderd/telemetry"
3030
"github.com/coder/coder/codersdk"
31+
"github.com/coder/coder/provisioner"
3132
"github.com/coder/coder/provisionerd/proto"
3233
"github.com/coder/coder/provisionersdk"
3334
sdkproto "github.com/coder/coder/provisionersdk/proto"
@@ -806,6 +807,17 @@ func insertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
806807
snapshot.WorkspaceAgents = append(snapshot.WorkspaceAgents, telemetry.ConvertWorkspaceAgent(dbAgent))
807808

808809
for _, app := range prAgent.Apps {
810+
slug := app.Slug
811+
if slug == "" {
812+
slug = app.Name
813+
}
814+
if slug == "" {
815+
return xerrors.Errorf("app must have a slug or name set")
816+
}
817+
if !provisioner.ValidAppNameRegex.MatchString(slug) {
818+
return xerrors.Errorf("app slug %q does not match regex %q", slug, provisioner.ValidAppNameRegex.String())
819+
}
820+
809821
health := database.WorkspaceAppHealthDisabled
810822
if app.Healthcheck == nil {
811823
app.Healthcheck = &sdkproto.Healthcheck{}
@@ -826,6 +838,7 @@ func insertWorkspaceResource(ctx context.Context, db database.Store, jobID uuid.
826838
ID: uuid.New(),
827839
CreatedAt: database.Now(),
828840
AgentID: dbAgent.ID,
841+
Slug: slug,
829842
Name: app.Name,
830843
Icon: app.Icon,
831844
Command: sql.NullString{

coderd/workspaceagents.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,7 @@ func convertApps(dbApps []database.WorkspaceApp) []codersdk.WorkspaceApp {
595595
for _, dbApp := range dbApps {
596596
apps = append(apps, codersdk.WorkspaceApp{
597597
ID: dbApp.ID,
598+
Slug: dbApp.Slug,
598599
Name: dbApp.Name,
599600
Command: dbApp.Command.String,
600601
Icon: dbApp.Icon,

0 commit comments

Comments
 (0)