From 8084cae2bfc3324950b2648c8a534f7cc7520892 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 27 Jun 2025 08:36:25 -0500 Subject: [PATCH 1/3] feat: support dynamic parameters on create template request --- coderd/coderdtest/dynamicparameters.go | 21 ++++++++++++--------- coderd/database/dbgen/dbgen.go | 1 + coderd/database/queries.sql.go | 7 +++++-- coderd/database/queries/templates.sql | 5 +++-- coderd/templates.go | 17 +++++++++++------ coderd/templates_test.go | 1 + codersdk/organizations.go | 6 ++++++ 7 files changed, 39 insertions(+), 19 deletions(-) diff --git a/coderd/coderdtest/dynamicparameters.go b/coderd/coderdtest/dynamicparameters.go index cb295eeaae965..fbc61b745d2a3 100644 --- a/coderd/coderdtest/dynamicparameters.go +++ b/coderd/coderdtest/dynamicparameters.go @@ -50,22 +50,25 @@ func DynamicParameterTemplate(t *testing.T, client *codersdk.Client, org uuid.UU }) AwaitTemplateVersionJobCompleted(t, client, version.ID) - tplID := args.TemplateID + var tpl codersdk.Template + var err error + if args.TemplateID == uuid.Nil { - tpl := CreateTemplate(t, client, org, version.ID) - tplID = tpl.ID + tpl = CreateTemplate(t, client, org, version.ID, func(request *codersdk.CreateTemplateRequest) { + request.UseClassicParameterFlow = ptr.Ref(false) + }) + } else { + tpl, err = client.UpdateTemplateMeta(t.Context(), args.TemplateID, codersdk.UpdateTemplateMeta{ + UseClassicParameterFlow: ptr.Ref(false), + }) + require.NoError(t, err) } - var err error - tpl, err := client.UpdateTemplateMeta(t.Context(), tplID, codersdk.UpdateTemplateMeta{ - UseClassicParameterFlow: ptr.Ref(false), - }) - require.NoError(t, err) - err = client.UpdateActiveTemplateVersion(t.Context(), tpl.ID, codersdk.UpdateActiveTemplateVersion{ ID: version.ID, }) require.NoError(t, err) + require.Equal(t, tpl.UseClassicParameterFlow, false, "template should use dynamic parameters") return tpl, version } diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index fb3adc9e6f057..e1c9d40436936 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -100,6 +100,7 @@ func Template(t testing.TB, db database.Store, seed database.Template) database. DisplayName: takeFirst(seed.DisplayName, testutil.GetRandomName(t)), AllowUserCancelWorkspaceJobs: seed.AllowUserCancelWorkspaceJobs, MaxPortSharingLevel: takeFirst(seed.MaxPortSharingLevel, database.AppSharingLevelOwner), + UseClassicParameterFlow: takeFirst(seed.UseClassicParameterFlow, true), }) require.NoError(t, err, "insert template") diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index 733b42db7a461..96e89ec662761 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -10854,10 +10854,11 @@ INSERT INTO group_acl, display_name, allow_user_cancel_workspace_jobs, - max_port_sharing_level + max_port_sharing_level, + use_classic_parameter_flow ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) ` type InsertTemplateParams struct { @@ -10876,6 +10877,7 @@ type InsertTemplateParams struct { DisplayName string `db:"display_name" json:"display_name"` AllowUserCancelWorkspaceJobs bool `db:"allow_user_cancel_workspace_jobs" json:"allow_user_cancel_workspace_jobs"` MaxPortSharingLevel AppSharingLevel `db:"max_port_sharing_level" json:"max_port_sharing_level"` + UseClassicParameterFlow bool `db:"use_classic_parameter_flow" json:"use_classic_parameter_flow"` } func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParams) error { @@ -10895,6 +10897,7 @@ func (q *sqlQuerier) InsertTemplate(ctx context.Context, arg InsertTemplateParam arg.DisplayName, arg.AllowUserCancelWorkspaceJobs, arg.MaxPortSharingLevel, + arg.UseClassicParameterFlow, ) return err } diff --git a/coderd/database/queries/templates.sql b/coderd/database/queries/templates.sql index 8b399fae87f3f..d10d09daaf6ea 100644 --- a/coderd/database/queries/templates.sql +++ b/coderd/database/queries/templates.sql @@ -98,10 +98,11 @@ INSERT INTO group_acl, display_name, allow_user_cancel_workspace_jobs, - max_port_sharing_level + max_port_sharing_level, + use_classic_parameter_flow ) VALUES - ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15); + ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16); -- name: UpdateTemplateActiveVersionByID :exec UPDATE diff --git a/coderd/templates.go b/coderd/templates.go index 2a3e0326b1970..bba38bb033614 100644 --- a/coderd/templates.go +++ b/coderd/templates.go @@ -197,16 +197,20 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque return } + // Default is true until dynamic parameters are promoted to stable. + useClassicParameterFlow := ptr.NilToDefault(createTemplate.UseClassicParameterFlow, true) + // Make a temporary struct to represent the template. This is used for // auditing if any of the following checks fail. It will be overwritten when // the template is inserted into the db. templateAudit.New = database.Template{ - OrganizationID: organization.ID, - Name: createTemplate.Name, - Description: createTemplate.Description, - CreatedBy: apiKey.UserID, - Icon: createTemplate.Icon, - DisplayName: createTemplate.DisplayName, + OrganizationID: organization.ID, + Name: createTemplate.Name, + Description: createTemplate.Description, + CreatedBy: apiKey.UserID, + Icon: createTemplate.Icon, + DisplayName: createTemplate.DisplayName, + UseClassicParameterFlow: useClassicParameterFlow, } _, err := api.Database.GetTemplateByOrganizationAndName(ctx, database.GetTemplateByOrganizationAndNameParams{ @@ -404,6 +408,7 @@ func (api *API) postTemplateByOrganization(rw http.ResponseWriter, r *http.Reque Icon: createTemplate.Icon, AllowUserCancelWorkspaceJobs: allowUserCancelWorkspaceJobs, MaxPortSharingLevel: maxPortShareLevel, + UseClassicParameterFlow: useClassicParameterFlow, }) if err != nil { return xerrors.Errorf("insert template: %s", err) diff --git a/coderd/templates_test.go b/coderd/templates_test.go index f8861da246260..5e7fcea75609d 100644 --- a/coderd/templates_test.go +++ b/coderd/templates_test.go @@ -77,6 +77,7 @@ func TestPostTemplateByOrganization(t *testing.T) { assert.Equal(t, expected.Name, got.Name) assert.Equal(t, expected.Description, got.Description) assert.Equal(t, expected.ActivityBumpMillis, got.ActivityBumpMillis) + assert.Equal(t, expected.UseClassicParameterFlow, true) // Current default is true require.Len(t, auditor.AuditLogs(), 3) assert.Equal(t, database.AuditActionCreate, auditor.AuditLogs()[0].Action) diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 08c1fb0034b46..59fd201d7f47b 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -200,6 +200,12 @@ type CreateTemplateRequest struct { // MaxPortShareLevel allows optionally specifying the maximum port share level // for workspaces created from the template. MaxPortShareLevel *WorkspaceAgentPortShareLevel `json:"max_port_share_level"` + + // UseClassicParameterFlow allows optionally specifying whether + // the template should use the classic parameter flow. The default if unset is + // true, and is why `*bool` is used here. When dynamic parameters becomes + // the default, this will default to false. + UseClassicParameterFlow *bool `json:"template_use_classic_parameter_flow"` } // CreateWorkspaceRequest provides options for creating a new workspace. From 7fb96d95359705d2fd223f81dfd64601356f69a6 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Fri, 27 Jun 2025 14:42:17 +0000 Subject: [PATCH 2/3] make gen --- coderd/apidoc/docs.go | 4 ++++ coderd/apidoc/swagger.json | 4 ++++ codersdk/organizations.go | 2 +- docs/reference/api/schemas.md | 40 +++++++++++++++++---------------- docs/reference/api/templates.md | 1 + site/src/api/typesGenerated.ts | 1 + 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 745ea3e3ff4b1..1ed2d2d164955 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -11337,6 +11337,10 @@ const docTemplate = `{ "description": "RequireActiveVersion mandates that workspaces are built with the active\ntemplate version.", "type": "boolean" }, + "template_use_classic_parameter_flow": { + "description": "UseClassicParameterFlow allows optionally specifying whether\nthe template should use the classic parameter flow. The default if unset is\ntrue, and is why ` + "`" + `*bool` + "`" + ` is used here. When dynamic parameters becomes\nthe default, this will default to false.", + "type": "boolean" + }, "template_version_id": { "description": "VersionID is an in-progress or completed job to use as an initial version\nof the template.\n\nThis is required on creation to enable a user-flow of validating a\ntemplate works. There is no reason the data-model cannot support empty\ntemplates, but it doesn't make sense for users.", "type": "string", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index d782946aa467a..e473736ac36f4 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -10103,6 +10103,10 @@ "description": "RequireActiveVersion mandates that workspaces are built with the active\ntemplate version.", "type": "boolean" }, + "template_use_classic_parameter_flow": { + "description": "UseClassicParameterFlow allows optionally specifying whether\nthe template should use the classic parameter flow. The default if unset is\ntrue, and is why `*bool` is used here. When dynamic parameters becomes\nthe default, this will default to false.", + "type": "boolean" + }, "template_version_id": { "description": "VersionID is an in-progress or completed job to use as an initial version\nof the template.\n\nThis is required on creation to enable a user-flow of validating a\ntemplate works. There is no reason the data-model cannot support empty\ntemplates, but it doesn't make sense for users.", "type": "string", diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 59fd201d7f47b..35a1e0be0a426 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -205,7 +205,7 @@ type CreateTemplateRequest struct { // the template should use the classic parameter flow. The default if unset is // true, and is why `*bool` is used here. When dynamic parameters becomes // the default, this will default to false. - UseClassicParameterFlow *bool `json:"template_use_classic_parameter_flow"` + UseClassicParameterFlow *bool `json:"template_use_classic_parameter_flow,omitempty"` } // CreateWorkspaceRequest provides options for creating a new workspace. diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 389c7ec9c39c8..56c5b5af77f3f 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -1258,31 +1258,33 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "max_port_share_level": "owner", "name": "string", "require_active_version": true, + "template_use_classic_parameter_flow": true, "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1" } ``` ### Properties -| Name | Type | Required | Restrictions | Description | -|------------------------------------|--------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `activity_bump_ms` | integer | false | | Activity bump ms allows optionally specifying the activity bump duration for all workspaces created from this template. Defaults to 1h but can be set to 0 to disable activity bumping. | -| `allow_user_autostart` | boolean | false | | Allow user autostart allows users to set a schedule for autostarting their workspace. By default this is true. This can only be disabled when using an enterprise license. | -| `allow_user_autostop` | boolean | false | | Allow user autostop allows users to set a custom workspace TTL to use in place of the template's DefaultTTL field. By default this is true. If false, the DefaultTTL will always be used. This can only be disabled when using an enterprise license. | -| `allow_user_cancel_workspace_jobs` | boolean | false | | Allow users to cancel in-progress workspace jobs. *bool as the default value is "true". | -| `autostart_requirement` | [codersdk.TemplateAutostartRequirement](#codersdktemplateautostartrequirement) | false | | Autostart requirement allows optionally specifying the autostart allowed days for workspaces created from this template. This is an enterprise feature. | -| `autostop_requirement` | [codersdk.TemplateAutostopRequirement](#codersdktemplateautostoprequirement) | false | | Autostop requirement allows optionally specifying the autostop requirement for workspaces created from this template. This is an enterprise feature. | -| `default_ttl_ms` | integer | false | | Default ttl ms allows optionally specifying the default TTL for all workspaces created from this template. | -| `delete_ttl_ms` | integer | false | | Delete ttl ms allows optionally specifying the max lifetime before Coder permanently deletes dormant workspaces created from this template. | -| `description` | string | false | | Description is a description of what the template contains. It must be less than 128 bytes. | -| `disable_everyone_group_access` | boolean | false | | Disable everyone group access allows optionally disabling the default behavior of granting the 'everyone' group access to use the template. If this is set to true, the template will not be available to all users, and must be explicitly granted to users or groups in the permissions settings of the template. | -| `display_name` | string | false | | Display name is the displayed name of the template. | -| `dormant_ttl_ms` | integer | false | | Dormant ttl ms allows optionally specifying the max lifetime before Coder locks inactive workspaces created from this template. | -| `failure_ttl_ms` | integer | false | | Failure ttl ms allows optionally specifying the max lifetime before Coder stops all resources for failed workspaces created from this template. | -| `icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | -| `max_port_share_level` | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel) | false | | Max port share level allows optionally specifying the maximum port share level for workspaces created from the template. | -| `name` | string | true | | Name is the name of the template. | -| `require_active_version` | boolean | false | | Require active version mandates that workspaces are built with the active template version. | +| Name | Type | Required | Restrictions | Description | +|---------------------------------------|--------------------------------------------------------------------------------|----------|--------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `activity_bump_ms` | integer | false | | Activity bump ms allows optionally specifying the activity bump duration for all workspaces created from this template. Defaults to 1h but can be set to 0 to disable activity bumping. | +| `allow_user_autostart` | boolean | false | | Allow user autostart allows users to set a schedule for autostarting their workspace. By default this is true. This can only be disabled when using an enterprise license. | +| `allow_user_autostop` | boolean | false | | Allow user autostop allows users to set a custom workspace TTL to use in place of the template's DefaultTTL field. By default this is true. If false, the DefaultTTL will always be used. This can only be disabled when using an enterprise license. | +| `allow_user_cancel_workspace_jobs` | boolean | false | | Allow users to cancel in-progress workspace jobs. *bool as the default value is "true". | +| `autostart_requirement` | [codersdk.TemplateAutostartRequirement](#codersdktemplateautostartrequirement) | false | | Autostart requirement allows optionally specifying the autostart allowed days for workspaces created from this template. This is an enterprise feature. | +| `autostop_requirement` | [codersdk.TemplateAutostopRequirement](#codersdktemplateautostoprequirement) | false | | Autostop requirement allows optionally specifying the autostop requirement for workspaces created from this template. This is an enterprise feature. | +| `default_ttl_ms` | integer | false | | Default ttl ms allows optionally specifying the default TTL for all workspaces created from this template. | +| `delete_ttl_ms` | integer | false | | Delete ttl ms allows optionally specifying the max lifetime before Coder permanently deletes dormant workspaces created from this template. | +| `description` | string | false | | Description is a description of what the template contains. It must be less than 128 bytes. | +| `disable_everyone_group_access` | boolean | false | | Disable everyone group access allows optionally disabling the default behavior of granting the 'everyone' group access to use the template. If this is set to true, the template will not be available to all users, and must be explicitly granted to users or groups in the permissions settings of the template. | +| `display_name` | string | false | | Display name is the displayed name of the template. | +| `dormant_ttl_ms` | integer | false | | Dormant ttl ms allows optionally specifying the max lifetime before Coder locks inactive workspaces created from this template. | +| `failure_ttl_ms` | integer | false | | Failure ttl ms allows optionally specifying the max lifetime before Coder stops all resources for failed workspaces created from this template. | +| `icon` | string | false | | Icon is a relative path or external URL that specifies an icon to be displayed in the dashboard. | +| `max_port_share_level` | [codersdk.WorkspaceAgentPortShareLevel](#codersdkworkspaceagentportsharelevel) | false | | Max port share level allows optionally specifying the maximum port share level for workspaces created from the template. | +| `name` | string | true | | Name is the name of the template. | +| `require_active_version` | boolean | false | | Require active version mandates that workspaces are built with the active template version. | +| `template_use_classic_parameter_flow` | boolean | false | | Template use classic parameter flow allows optionally specifying whether the template should use the classic parameter flow. The default if unset is true, and is why `*bool` is used here. When dynamic parameters becomes the default, this will default to false. | |`template_version_id`|string|true||Template version ID is an in-progress or completed job to use as an initial version of the template. This is required on creation to enable a user-flow of validating a template works. There is no reason the data-model cannot support empty templates, but it doesn't make sense for users.| diff --git a/docs/reference/api/templates.md b/docs/reference/api/templates.md index dc4605532ff41..a7c81220469cc 100644 --- a/docs/reference/api/templates.md +++ b/docs/reference/api/templates.md @@ -193,6 +193,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa "max_port_share_level": "owner", "name": "string", "require_active_version": true, + "template_use_classic_parameter_flow": true, "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1" } ``` diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 6552c0f0d56d3..f3638a1d913c2 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -394,6 +394,7 @@ export interface CreateTemplateRequest { readonly disable_everyone_group_access: boolean; readonly require_active_version: boolean; readonly max_port_share_level: WorkspaceAgentPortShareLevel | null; + readonly template_use_classic_parameter_flow?: boolean; } // From codersdk/templateversions.go From 62de89755f2242cd69f5258b5af7a5b60fcd12b0 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 30 Jun 2025 17:23:08 -0500 Subject: [PATCH 3/3] update dbmem --- coderd/database/dbmem/dbmem.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index cd1067e61dbb5..6a9b97b6a6f29 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -9323,7 +9323,7 @@ func (q *FakeQuerier) InsertTemplate(_ context.Context, arg database.InsertTempl AllowUserAutostart: true, AllowUserAutostop: true, MaxPortSharingLevel: arg.MaxPortSharingLevel, - UseClassicParameterFlow: true, + UseClassicParameterFlow: arg.UseClassicParameterFlow, } q.templates = append(q.templates, template) return nil pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy