feat: add OpenIn option to coder_app (#15743)

This PR is the coder/coder part of [the open_in parameter
issue](https://github.com/coder/terraform-provider-coder/issues/297)
aiming to add a new optional parameter to choose how to open modules.

This PR is heavily linked [to this
PR](https://github.com/coder/terraform-provider-coder/pull/321).

ℹ️ For now, some integrations tests can not be pushed as it requires a
release on the terraform-provider repo.
This commit is contained in:
Vincent Vielle
2025-01-03 11:27:02 +01:00
committed by GitHub
parent 3f1795fd92
commit 08463c27d8
34 changed files with 1075 additions and 800 deletions
+4 -3
View File
@@ -2502,7 +2502,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
s.Run("GetWorkspaceAppsCreatedAfter", s.Subtest(func(db database.Store, check *expects) {
_ = dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{CreatedAt: time.Now().Add(-time.Hour)})
_ = dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{CreatedAt: time.Now().Add(-time.Hour), OpenIn: database.WorkspaceAppOpenInSlimWindow})
check.Args(time.Now()).Asserts(rbac.ResourceSystem, policy.ActionRead)
}))
s.Run("GetWorkspaceResourcesCreatedAfter", s.Subtest(func(db database.Store, check *expects) {
@@ -2551,13 +2551,13 @@ func (s *MethodTestSuite) TestSystemFunctions() {
aBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: aWs.ID, JobID: uuid.New()})
aRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: aBuild.JobID})
aAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: aRes.ID})
a := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: aAgt.ID})
a := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: aAgt.ID, OpenIn: database.WorkspaceAppOpenInSlimWindow})
bWs := dbgen.Workspace(s.T(), db, database.WorkspaceTable{})
bBuild := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{WorkspaceID: bWs.ID, JobID: uuid.New()})
bRes := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: bBuild.JobID})
bAgt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: bRes.ID})
b := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: bAgt.ID})
b := dbgen.WorkspaceApp(s.T(), db, database.WorkspaceApp{AgentID: bAgt.ID, OpenIn: database.WorkspaceAppOpenInSlimWindow})
check.Args([]uuid.UUID{a.AgentID, b.AgentID}).
Asserts(rbac.ResourceSystem, policy.ActionRead).
@@ -2611,6 +2611,7 @@ func (s *MethodTestSuite) TestSystemFunctions() {
ID: uuid.New(),
Health: database.WorkspaceAppHealthDisabled,
SharingLevel: database.AppSharingLevelOwner,
OpenIn: database.WorkspaceAppOpenInSlimWindow,
}).Asserts(rbac.ResourceSystem, policy.ActionCreate)
}))
s.Run("InsertWorkspaceResourceMetadata", s.Subtest(func(db database.Store, check *expects) {
+1
View File
@@ -659,6 +659,7 @@ func WorkspaceApp(t testing.TB, db database.Store, orig database.WorkspaceApp) d
Health: takeFirst(orig.Health, database.WorkspaceAppHealthHealthy),
DisplayOrder: takeFirst(orig.DisplayOrder, 1),
Hidden: orig.Hidden,
OpenIn: takeFirst(orig.OpenIn, database.WorkspaceAppOpenInSlimWindow),
})
require.NoError(t, err, "insert app")
return resource
+5
View File
@@ -8348,6 +8348,10 @@ func (q *FakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
arg.SharingLevel = database.AppSharingLevelOwner
}
if arg.OpenIn == "" {
arg.OpenIn = database.WorkspaceAppOpenInSlimWindow
}
// nolint:gosimple
workspaceApp := database.WorkspaceApp{
ID: arg.ID,
@@ -8367,6 +8371,7 @@ func (q *FakeQuerier) InsertWorkspaceApp(_ context.Context, arg database.InsertW
Health: arg.Health,
Hidden: arg.Hidden,
DisplayOrder: arg.DisplayOrder,
OpenIn: arg.OpenIn,
}
q.workspaceApps = append(q.workspaceApps, workspaceApp)
return workspaceApp, nil
+8 -1
View File
@@ -261,6 +261,12 @@ CREATE TYPE workspace_app_health AS ENUM (
'unhealthy'
);
CREATE TYPE workspace_app_open_in AS ENUM (
'tab',
'window',
'slim-window'
);
CREATE TYPE workspace_transition AS ENUM (
'start',
'stop',
@@ -1602,7 +1608,8 @@ CREATE TABLE workspace_apps (
slug text NOT NULL,
external boolean DEFAULT false NOT NULL,
display_order integer DEFAULT 0 NOT NULL,
hidden boolean DEFAULT false NOT NULL
hidden boolean DEFAULT false NOT NULL,
open_in workspace_app_open_in DEFAULT 'slim-window'::workspace_app_open_in NOT NULL
);
COMMENT ON COLUMN workspace_apps.display_order IS 'Specifies the order in which to display agent app in user interfaces.';
@@ -0,0 +1,3 @@
ALTER TABLE workspace_apps DROP COLUMN open_in;
DROP TYPE workspace_app_open_in;
@@ -0,0 +1,3 @@
CREATE TYPE workspace_app_open_in AS ENUM ('tab', 'window', 'slim-window');
ALTER TABLE workspace_apps ADD COLUMN open_in workspace_app_open_in NOT NULL DEFAULT 'slim-window'::workspace_app_open_in;
+63 -1
View File
@@ -2151,6 +2151,67 @@ func AllWorkspaceAppHealthValues() []WorkspaceAppHealth {
}
}
type WorkspaceAppOpenIn string
const (
WorkspaceAppOpenInTab WorkspaceAppOpenIn = "tab"
WorkspaceAppOpenInWindow WorkspaceAppOpenIn = "window"
WorkspaceAppOpenInSlimWindow WorkspaceAppOpenIn = "slim-window"
)
func (e *WorkspaceAppOpenIn) Scan(src interface{}) error {
switch s := src.(type) {
case []byte:
*e = WorkspaceAppOpenIn(s)
case string:
*e = WorkspaceAppOpenIn(s)
default:
return fmt.Errorf("unsupported scan type for WorkspaceAppOpenIn: %T", src)
}
return nil
}
type NullWorkspaceAppOpenIn struct {
WorkspaceAppOpenIn WorkspaceAppOpenIn `json:"workspace_app_open_in"`
Valid bool `json:"valid"` // Valid is true if WorkspaceAppOpenIn is not NULL
}
// Scan implements the Scanner interface.
func (ns *NullWorkspaceAppOpenIn) Scan(value interface{}) error {
if value == nil {
ns.WorkspaceAppOpenIn, ns.Valid = "", false
return nil
}
ns.Valid = true
return ns.WorkspaceAppOpenIn.Scan(value)
}
// Value implements the driver Valuer interface.
func (ns NullWorkspaceAppOpenIn) Value() (driver.Value, error) {
if !ns.Valid {
return nil, nil
}
return string(ns.WorkspaceAppOpenIn), nil
}
func (e WorkspaceAppOpenIn) Valid() bool {
switch e {
case WorkspaceAppOpenInTab,
WorkspaceAppOpenInWindow,
WorkspaceAppOpenInSlimWindow:
return true
}
return false
}
func AllWorkspaceAppOpenInValues() []WorkspaceAppOpenIn {
return []WorkspaceAppOpenIn{
WorkspaceAppOpenInTab,
WorkspaceAppOpenInWindow,
WorkspaceAppOpenInSlimWindow,
}
}
type WorkspaceTransition string
const (
@@ -3092,7 +3153,8 @@ type WorkspaceApp struct {
// Specifies the order in which to display agent app in user interfaces.
DisplayOrder int32 `db:"display_order" json:"display_order"`
// Determines if the app is not shown in user interfaces.
Hidden bool `db:"hidden" json:"hidden"`
Hidden bool `db:"hidden" json:"hidden"`
OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
}
// A record of workspace app usage statistics
+14 -6
View File
@@ -13157,7 +13157,7 @@ func (q *sqlQuerier) InsertWorkspaceAgentStats(ctx context.Context, arg InsertWo
}
const getWorkspaceAppByAgentIDAndSlug = `-- name: GetWorkspaceAppByAgentIDAndSlug :one
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden FROM workspace_apps WHERE agent_id = $1 AND slug = $2
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 AND slug = $2
`
type GetWorkspaceAppByAgentIDAndSlugParams struct {
@@ -13186,12 +13186,13 @@ func (q *sqlQuerier) GetWorkspaceAppByAgentIDAndSlug(ctx context.Context, arg Ge
&i.External,
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
)
return i, err
}
const getWorkspaceAppsByAgentID = `-- name: GetWorkspaceAppsByAgentID :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid.UUID) ([]WorkspaceApp, error) {
@@ -13221,6 +13222,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
&i.External,
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
); err != nil {
return nil, err
}
@@ -13236,7 +13238,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentID(ctx context.Context, agentID uuid
}
const getWorkspaceAppsByAgentIDs = `-- name: GetWorkspaceAppsByAgentIDs :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE agent_id = ANY($1 :: uuid [ ]) ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.UUID) ([]WorkspaceApp, error) {
@@ -13266,6 +13268,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
&i.External,
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
); err != nil {
return nil, err
}
@@ -13281,7 +13284,7 @@ func (q *sqlQuerier) GetWorkspaceAppsByAgentIDs(ctx context.Context, ids []uuid.
}
const getWorkspaceAppsCreatedAfter = `-- name: GetWorkspaceAppsCreatedAfter :many
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
SELECT id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in FROM workspace_apps WHERE created_at > $1 ORDER BY slug ASC
`
func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt time.Time) ([]WorkspaceApp, error) {
@@ -13311,6 +13314,7 @@ func (q *sqlQuerier) GetWorkspaceAppsCreatedAfter(ctx context.Context, createdAt
&i.External,
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
); err != nil {
return nil, err
}
@@ -13344,10 +13348,11 @@ INSERT INTO
healthcheck_threshold,
health,
display_order,
hidden
hidden,
open_in
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING id, created_at, agent_id, display_name, icon, command, url, healthcheck_url, healthcheck_interval, healthcheck_threshold, health, subdomain, sharing_level, slug, external, display_order, hidden, open_in
`
type InsertWorkspaceAppParams struct {
@@ -13368,6 +13373,7 @@ type InsertWorkspaceAppParams struct {
Health WorkspaceAppHealth `db:"health" json:"health"`
DisplayOrder int32 `db:"display_order" json:"display_order"`
Hidden bool `db:"hidden" json:"hidden"`
OpenIn WorkspaceAppOpenIn `db:"open_in" json:"open_in"`
}
func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspaceAppParams) (WorkspaceApp, error) {
@@ -13389,6 +13395,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
arg.Health,
arg.DisplayOrder,
arg.Hidden,
arg.OpenIn,
)
var i WorkspaceApp
err := row.Scan(
@@ -13409,6 +13416,7 @@ func (q *sqlQuerier) InsertWorkspaceApp(ctx context.Context, arg InsertWorkspace
&i.External,
&i.DisplayOrder,
&i.Hidden,
&i.OpenIn,
)
return i, err
}
+3 -2
View File
@@ -29,10 +29,11 @@ INSERT INTO
healthcheck_threshold,
health,
display_order,
hidden
hidden,
open_in
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17) RETURNING *;
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18) RETURNING *;
-- name: UpdateWorkspaceAppHealthByID :exec
UPDATE