From c7a5d22e173ccf5af47cc88bd02426c276230aa1 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 10:40:50 -0500 Subject: [PATCH 01/13] feat: add dynamic parameters evaluate api Used when a websocket is too heavy --- coderd/coderd.go | 5 +- coderd/parameters.go | 141 ++++++++++++++++++++++++++++++------------- 2 files changed, 102 insertions(+), 44 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 69d942304acea..9392838713dbb 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1156,7 +1156,10 @@ func New(options *Options) *API { r.Use( httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentDynamicParameters), ) - r.Get("/dynamic-parameters", api.templateVersionDynamicParameters) + r.Route("/dynamic-parameters/", func(r chi.Router) { + r.Get("/evaluate", api.templateVersionDynamicParameters) + r.Get("/", api.templateVersionDynamicParameters) + }) }) }) r.Route("/users", func(r chi.Router) { diff --git a/coderd/parameters.go b/coderd/parameters.go index d1e989c8ad032..7a01033f8b48e 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -29,57 +29,86 @@ import ( "github.com/coder/websocket" ) +// @Summary Evaluate dynamic parameters for template version +// @ID evaluate-dynamic-parameters-by-template-version +// @Security CoderSessionToken +// @Tags Templates +// @Param templateversion path string true "Template version ID" format(uuid) +// @Accept json +// @Produce json +// @Router /templateversions/{templateversion}/dynamic-parameters/evaluate [post] +func (api *API) templateVersionDynamicParametersEvaluate(rw http.ResponseWriter, r *http.Request) { + ctx := r.Context() + var req codersdk.DynamicParametersRequest + if !httpapi.Read(ctx, rw, r, &req) { + return + } + + api.templateVersionDynamicParameters(false, req)(rw, r) +} + // @Summary Open dynamic parameters WebSocket by template version // @ID open-dynamic-parameters-websocket-by-template-version // @Security CoderSessionToken // @Tags Templates -// @Param user path string true "Template version ID" format(uuid) // @Param templateversion path string true "Template version ID" format(uuid) // @Success 101 // @Router /templateversions/{templateversion}/dynamic-parameters [get] -func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http.Request) { - ctx := r.Context() - templateVersion := httpmw.TemplateVersionParam(r) +func (api *API) templateVersionDynamicParametersWebsocket(rw http.ResponseWriter, r *http.Request) { + apikey := httpmw.APIKey(r) + + api.templateVersionDynamicParameters(true, codersdk.DynamicParametersRequest{ + ID: -1, + Inputs: map[string]string{}, + OwnerID: apikey.UserID, + })(rw, r) +} - // Check that the job has completed successfully - job, err := api.Database.GetProvisionerJobByID(ctx, templateVersion.JobID) - if httpapi.Is404Error(err) { - httpapi.ResourceNotFound(rw) - return - } - if err != nil { - httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching provisioner job.", - Detail: err.Error(), - }) - return - } - if !job.CompletedAt.Valid { - httpapi.Write(ctx, rw, http.StatusTooEarly, codersdk.Response{ - Message: "Template version job has not finished", - }) - return - } +func (api *API) templateVersionDynamicParameters(listen bool, initial codersdk.DynamicParametersRequest) func(rw http.ResponseWriter, r *http.Request) { + return func(rw http.ResponseWriter, r *http.Request) { + ctx := r.Context() + templateVersion := httpmw.TemplateVersionParam(r) - tf, err := api.Database.GetTemplateVersionTerraformValues(ctx, templateVersion.ID) - if err != nil && !xerrors.Is(err, sql.ErrNoRows) { - httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to retrieve Terraform values for template version", - Detail: err.Error(), - }) - return - } + // Check that the job has completed successfully + job, err := api.Database.GetProvisionerJobByID(ctx, templateVersion.JobID) + if httpapi.Is404Error(err) { + httpapi.ResourceNotFound(rw) + return + } + if err != nil { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Internal error fetching provisioner job.", + Detail: err.Error(), + }) + return + } + if !job.CompletedAt.Valid { + httpapi.Write(ctx, rw, http.StatusTooEarly, codersdk.Response{ + Message: "Template version job has not finished", + }) + return + } - if wsbuilder.ProvisionerVersionSupportsDynamicParameters(tf.ProvisionerdVersion) { - api.handleDynamicParameters(rw, r, tf, templateVersion) - } else { - api.handleStaticParameters(rw, r, templateVersion.ID) + tf, err := api.Database.GetTemplateVersionTerraformValues(ctx, templateVersion.ID) + if err != nil && !xerrors.Is(err, sql.ErrNoRows) { + httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ + Message: "Failed to retrieve Terraform values for template version", + Detail: err.Error(), + }) + return + } + + if wsbuilder.ProvisionerVersionSupportsDynamicParameters(tf.ProvisionerdVersion) { + api.handleDynamicParameters(listen, rw, r, tf, templateVersion, initial) + } else { + api.handleStaticParameters(listen, rw, r, templateVersion.ID, initial) + } } } type previewFunction func(ctx context.Context, ownerID uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) -func (api *API) handleDynamicParameters(rw http.ResponseWriter, r *http.Request, tf database.TemplateVersionTerraformValue, templateVersion database.TemplateVersion) { +func (api *API) handleDynamicParameters(listen bool, rw http.ResponseWriter, r *http.Request, tf database.TemplateVersionTerraformValue, templateVersion database.TemplateVersion, initial codersdk.DynamicParametersRequest) { var ( ctx = r.Context() apikey = httpmw.APIKey(r) @@ -159,7 +188,7 @@ func (api *API) handleDynamicParameters(rw http.ResponseWriter, r *http.Request, }, } - api.handleParameterWebsocket(rw, r, apikey.UserID, func(ctx context.Context, ownerID uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) { + dynamicRender := func(ctx context.Context, ownerID uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) { if ownerID == uuid.Nil { // Default to the authenticated user // Nice for testing @@ -186,10 +215,15 @@ func (api *API) handleDynamicParameters(rw http.ResponseWriter, r *http.Request, } return preview.Preview(ctx, input, templateFS) - }) + } + if listen { + api.handleParameterWebsocket(rw, r, initial, dynamicRender) + } else { + api.handleParameterEvaluate(rw, r, initial, dynamicRender) + } } -func (api *API) handleStaticParameters(rw http.ResponseWriter, r *http.Request, version uuid.UUID) { +func (api *API) handleStaticParameters(listen bool, rw http.ResponseWriter, r *http.Request, version uuid.UUID, initial codersdk.DynamicParametersRequest) { ctx := r.Context() dbTemplateVersionParameters, err := api.Database.GetTemplateVersionParameters(ctx, version) if err != nil { @@ -275,7 +309,7 @@ func (api *API) handleStaticParameters(rw http.ResponseWriter, r *http.Request, params = append(params, param) } - api.handleParameterWebsocket(rw, r, uuid.Nil, func(_ context.Context, _ uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) { + staticRender := func(_ context.Context, _ uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) { for i := range params { param := ¶ms[i] paramValue, ok := values[param.Name] @@ -297,10 +331,31 @@ func (api *API) handleStaticParameters(rw http.ResponseWriter, r *http.Request, Detail: "To restore full functionality, please re-import the terraform as a new template version.", }, } - }) + } + if listen { + api.handleParameterWebsocket(rw, r, initial, staticRender) + } else { + api.handleParameterEvaluate(rw, r, initial, staticRender) + } +} + +func (api *API) handleParameterEvaluate(rw http.ResponseWriter, r *http.Request, initial codersdk.DynamicParametersRequest, render previewFunction) { + ctx := r.Context() + + // Send an initial form state, computed without any user input. + result, diagnostics := render(ctx, initial.OwnerID, initial.Inputs) + response := codersdk.DynamicParametersResponse{ + ID: -1, // Always start with -1. + Diagnostics: db2sdk.HCLDiagnostics(diagnostics), + } + if result != nil { + response.Parameters = db2sdk.List(result.Parameters, db2sdk.PreviewParameter) + } + + httpapi.Write(ctx, rw, http.StatusOK, response) } -func (api *API) handleParameterWebsocket(rw http.ResponseWriter, r *http.Request, ownerID uuid.UUID, render previewFunction) { +func (api *API) handleParameterWebsocket(rw http.ResponseWriter, r *http.Request, initial codersdk.DynamicParametersRequest, render previewFunction) { ctx, cancel := context.WithTimeout(r.Context(), 30*time.Minute) defer cancel() @@ -320,7 +375,7 @@ func (api *API) handleParameterWebsocket(rw http.ResponseWriter, r *http.Request ) // Send an initial form state, computed without any user input. - result, diagnostics := render(ctx, ownerID, map[string]string{}) + result, diagnostics := render(ctx, initial.OwnerID, initial.Inputs) response := codersdk.DynamicParametersResponse{ ID: -1, // Always start with -1. Diagnostics: db2sdk.HCLDiagnostics(diagnostics), From a134e9af198be8016ca8035e3f152aea2e2ba5f3 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 10:47:59 -0500 Subject: [PATCH 02/13] fix router --- coderd/coderd.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 9392838713dbb..2eb64a11e9ca3 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1157,8 +1157,8 @@ func New(options *Options) *API { httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentDynamicParameters), ) r.Route("/dynamic-parameters/", func(r chi.Router) { - r.Get("/evaluate", api.templateVersionDynamicParameters) - r.Get("/", api.templateVersionDynamicParameters) + r.Post("/evaluate", api.templateVersionDynamicParametersEvaluate) + r.Get("/", api.templateVersionDynamicParametersWebsocket) }) }) }) From d5e5ee89e434820a2f2e35e09cad4e81079b7416 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:11:40 -0500 Subject: [PATCH 03/13] make gen --- coderd/apidoc/docs.go | 37 ++++++++++++++++++++++++++------- coderd/apidoc/swagger.json | 31 ++++++++++++++++++++------- docs/reference/api/templates.md | 26 ++++++++++++++++++++++- 3 files changed, 79 insertions(+), 15 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 16a51d187a486..6b83a663ac139 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5897,10 +5897,37 @@ const docTemplate = `{ "type": "string", "format": "uuid", "description": "Template version ID", - "name": "user", + "name": "templateversion", "in": "path", "required": true - }, + } + ], + "responses": { + "101": { + "description": "Switching Protocols" + } + } + } + }, + "/templateversions/{templateversion}/dynamic-parameters/evaluate": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Templates" + ], + "summary": "Evaluate dynamic parameters for template version", + "operationId": "evaluate-dynamic-parameters-by-template-version", + "parameters": [ { "type": "string", "format": "uuid", @@ -5910,11 +5937,7 @@ const docTemplate = `{ "required": true } ], - "responses": { - "101": { - "description": "Switching Protocols" - } - } + "responses": {} } }, "/templateversions/{templateversion}/external-auth": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 986862df59a09..e1f8d92a9afb3 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5212,10 +5212,31 @@ "type": "string", "format": "uuid", "description": "Template version ID", - "name": "user", + "name": "templateversion", "in": "path", "required": true - }, + } + ], + "responses": { + "101": { + "description": "Switching Protocols" + } + } + } + }, + "/templateversions/{templateversion}/dynamic-parameters/evaluate": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Templates"], + "summary": "Evaluate dynamic parameters for template version", + "operationId": "evaluate-dynamic-parameters-by-template-version", + "parameters": [ { "type": "string", "format": "uuid", @@ -5225,11 +5246,7 @@ "required": true } ], - "responses": { - "101": { - "description": "Switching Protocols" - } - } + "responses": {} } }, "/templateversions/{templateversion}/external-auth": { diff --git a/docs/reference/api/templates.md b/docs/reference/api/templates.md index 6075af775c9bc..7efd65d83870a 100644 --- a/docs/reference/api/templates.md +++ b/docs/reference/api/templates.md @@ -2593,7 +2593,6 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d | Name | In | Type | Required | Description | |-------------------|------|--------------|----------|---------------------| -| `user` | path | string(uuid) | true | Template version ID | | `templateversion` | path | string(uuid) | true | Template version ID | ### Responses @@ -2604,6 +2603,31 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d To perform this operation, you must be authenticated. [Learn more](authentication.md). +## Evaluate dynamic parameters for template version + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/dynamic-parameters/evaluate \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /templateversions/{templateversion}/dynamic-parameters/evaluate` + +### Parameters + +| Name | In | Type | Required | Description | +|-------------------|------|--------------|----------|---------------------| +| `templateversion` | path | string(uuid) | true | Template version ID | + +### Responses + +|Status|Meaning|Description|Schema| +|---|---|---|---| + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + ## Get external auth by template version ### Code samples From b1617fb38f1dcd60801b89af4338545e84f1174f Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:34:06 -0500 Subject: [PATCH 04/13] linting --- coderd/parameters.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/coderd/parameters.go b/coderd/parameters.go index 7a01033f8b48e..8c400875f0f45 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -108,6 +108,8 @@ func (api *API) templateVersionDynamicParameters(listen bool, initial codersdk.D type previewFunction func(ctx context.Context, ownerID uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) +// handleDynamicParameters +// nolint:revive func (api *API) handleDynamicParameters(listen bool, rw http.ResponseWriter, r *http.Request, tf database.TemplateVersionTerraformValue, templateVersion database.TemplateVersion, initial codersdk.DynamicParametersRequest) { var ( ctx = r.Context() @@ -223,6 +225,8 @@ func (api *API) handleDynamicParameters(listen bool, rw http.ResponseWriter, r * } } +// handleStaticParameters +// nolint:revive func (api *API) handleStaticParameters(listen bool, rw http.ResponseWriter, r *http.Request, version uuid.UUID, initial codersdk.DynamicParametersRequest) { ctx := r.Context() dbTemplateVersionParameters, err := api.Database.GetTemplateVersionParameters(ctx, version) From 761f2907d5ef06dcc7eb56916c37fa38a149ba80 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:42:15 -0500 Subject: [PATCH 05/13] evaluate endpoint to return 0 for id --- coderd/parameters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 8c400875f0f45..a91fd92589d90 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -349,7 +349,7 @@ func (api *API) handleParameterEvaluate(rw http.ResponseWriter, r *http.Request, // Send an initial form state, computed without any user input. result, diagnostics := render(ctx, initial.OwnerID, initial.Inputs) response := codersdk.DynamicParametersResponse{ - ID: -1, // Always start with -1. + ID: 0, Diagnostics: db2sdk.HCLDiagnostics(diagnostics), } if result != nil { From 0d71165af0352ae86cae97c05ec2ee39b2808804 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:44:57 -0500 Subject: [PATCH 06/13] swagger --- coderd/apidoc/docs.go | 2 +- coderd/apidoc/swagger.json | 2 +- coderd/parameters.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 6b83a663ac139..c941b9f7d521e 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5926,7 +5926,7 @@ const docTemplate = `{ "Templates" ], "summary": "Evaluate dynamic parameters for template version", - "operationId": "evaluate-dynamic-parameters-by-template-version", + "operationId": "evaluate-dynamic-parameters-for-template-version", "parameters": [ { "type": "string", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index e1f8d92a9afb3..b3f4dcce8f51a 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5235,7 +5235,7 @@ "produces": ["application/json"], "tags": ["Templates"], "summary": "Evaluate dynamic parameters for template version", - "operationId": "evaluate-dynamic-parameters-by-template-version", + "operationId": "evaluate-dynamic-parameters-for-template-version", "parameters": [ { "type": "string", diff --git a/coderd/parameters.go b/coderd/parameters.go index a91fd92589d90..44783fd3fdb1c 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -30,7 +30,7 @@ import ( ) // @Summary Evaluate dynamic parameters for template version -// @ID evaluate-dynamic-parameters-by-template-version +// @ID evaluate-dynamic-parameters-for-template-version // @Security CoderSessionToken // @Tags Templates // @Param templateversion path string true "Template version ID" format(uuid) From f31197a359453d45ab07802f8b353db2f4ab3635 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:47:59 -0500 Subject: [PATCH 07/13] comments remove --- coderd/parameters.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 44783fd3fdb1c..694cf94a0ffbf 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -108,7 +108,6 @@ func (api *API) templateVersionDynamicParameters(listen bool, initial codersdk.D type previewFunction func(ctx context.Context, ownerID uuid.UUID, values map[string]string) (*preview.Output, hcl.Diagnostics) -// handleDynamicParameters // nolint:revive func (api *API) handleDynamicParameters(listen bool, rw http.ResponseWriter, r *http.Request, tf database.TemplateVersionTerraformValue, templateVersion database.TemplateVersion, initial codersdk.DynamicParametersRequest) { var ( @@ -225,7 +224,6 @@ func (api *API) handleDynamicParameters(listen bool, rw http.ResponseWriter, r * } } -// handleStaticParameters // nolint:revive func (api *API) handleStaticParameters(listen bool, rw http.ResponseWriter, r *http.Request, version uuid.UUID, initial codersdk.DynamicParametersRequest) { ctx := r.Context() From dba576c5856477016ad64f4132e621caf5beb81e Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 11:53:01 -0500 Subject: [PATCH 08/13] linting --- coderd/parameters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 694cf94a0ffbf..696938f9aa544 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -341,7 +341,7 @@ func (api *API) handleStaticParameters(listen bool, rw http.ResponseWriter, r *h } } -func (api *API) handleParameterEvaluate(rw http.ResponseWriter, r *http.Request, initial codersdk.DynamicParametersRequest, render previewFunction) { +func (*API) handleParameterEvaluate(rw http.ResponseWriter, r *http.Request, initial codersdk.DynamicParametersRequest, render previewFunction) { ctx := r.Context() // Send an initial form state, computed without any user input. From 62ef7122394b8792d9c396c41e2ca3b4862bd8eb Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 12:04:16 -0500 Subject: [PATCH 09/13] add success return --- coderd/parameters.go | 1 + 1 file changed, 1 insertion(+) diff --git a/coderd/parameters.go b/coderd/parameters.go index 696938f9aa544..b7793bcd49261 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -36,6 +36,7 @@ import ( // @Param templateversion path string true "Template version ID" format(uuid) // @Accept json // @Produce json +// @Success 200 {object} codersdk.DynamicParametersResponse // @Router /templateversions/{templateversion}/dynamic-parameters/evaluate [post] func (api *API) templateVersionDynamicParametersEvaluate(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() From e4007a6dc1882c8683b53cae9857eed5c61b0dad Mon Sep 17 00:00:00 2001 From: Emyrk Date: Mon, 2 Jun 2025 17:07:05 +0000 Subject: [PATCH 10/13] make gne --- coderd/apidoc/docs.go | 235 +++++++++++++++++++++- coderd/apidoc/swagger.json | 227 +++++++++++++++++++++- docs/reference/api/schemas.md | 335 ++++++++++++++++++++++++++++++++ docs/reference/api/templates.md | 83 +++++++- 4 files changed, 876 insertions(+), 4 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index c941b9f7d521e..4af0993101c91 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5937,7 +5937,14 @@ const docTemplate = `{ "required": true } ], - "responses": {} + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersResponse" + } + } + } } }, "/templateversions/{templateversion}/external-auth": { @@ -12596,6 +12603,25 @@ const docTemplate = `{ } } }, + "codersdk.DiagnosticExtra": { + "type": "object", + "properties": { + "code": { + "type": "string" + } + } + }, + "codersdk.DiagnosticSeverityString": { + "type": "string", + "enum": [ + "error", + "warning" + ], + "x-enum-varnames": [ + "DiagnosticSeverityError", + "DiagnosticSeverityWarning" + ] + }, "codersdk.DisplayApp": { "type": "string", "enum": [ @@ -12613,6 +12639,26 @@ const docTemplate = `{ "DisplayAppSSH" ] }, + "codersdk.DynamicParametersResponse": { + "type": "object", + "properties": { + "diagnostics": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.FriendlyDiagnostic" + } + }, + "id": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameter" + } + } + } + }, "codersdk.Entitlement": { "type": "string", "enum": [ @@ -12893,6 +12939,23 @@ const docTemplate = `{ } } }, + "codersdk.FriendlyDiagnostic": { + "type": "object", + "properties": { + "detail": { + "type": "string" + }, + "extra": { + "$ref": "#/definitions/codersdk.DiagnosticExtra" + }, + "severity": { + "$ref": "#/definitions/codersdk.DiagnosticSeverityString" + }, + "summary": { + "type": "string" + } + } + }, "codersdk.GenerateAPIKeyResponse": { "type": "object", "properties": { @@ -13684,6 +13747,17 @@ const docTemplate = `{ } } }, + "codersdk.NullHCLString": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "codersdk.OAuth2AppEndpoints": { "type": "object", "properties": { @@ -13941,6 +14015,21 @@ const docTemplate = `{ } } }, + "codersdk.OptionType": { + "type": "string", + "enum": [ + "string", + "number", + "bool", + "list(string)" + ], + "x-enum-varnames": [ + "OptionTypeString", + "OptionTypeNumber", + "OptionTypeBoolean", + "OptionTypeListString" + ] + }, "codersdk.Organization": { "type": "object", "required": [ @@ -14088,6 +14177,35 @@ const docTemplate = `{ } } }, + "codersdk.ParameterFormType": { + "type": "string", + "enum": [ + "", + "radio", + "slider", + "input", + "dropdown", + "checkbox", + "switch", + "multi-select", + "tag-select", + "textarea", + "error" + ], + "x-enum-varnames": [ + "ParameterFormTypeDefault", + "ParameterFormTypeRadio", + "ParameterFormTypeSlider", + "ParameterFormTypeInput", + "ParameterFormTypeDropdown", + "ParameterFormTypeCheckbox", + "ParameterFormTypeSwitch", + "ParameterFormTypeMultiSelect", + "ParameterFormTypeTagSelect", + "ParameterFormTypeTextArea", + "ParameterFormTypeError" + ] + }, "codersdk.PatchGroupIDPSyncConfigRequest": { "type": "object", "properties": { @@ -14404,6 +14522,121 @@ const docTemplate = `{ } } }, + "codersdk.PreviewParameter": { + "type": "object", + "properties": { + "default_value": { + "$ref": "#/definitions/codersdk.NullHCLString" + }, + "description": { + "type": "string" + }, + "diagnostics": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.FriendlyDiagnostic" + } + }, + "display_name": { + "type": "string" + }, + "ephemeral": { + "type": "boolean" + }, + "form_type": { + "$ref": "#/definitions/codersdk.ParameterFormType" + }, + "icon": { + "type": "string" + }, + "mutable": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameterOption" + } + }, + "order": { + "description": "legacy_variable_name was removed (= 14)", + "type": "integer" + }, + "required": { + "type": "boolean" + }, + "styling": { + "$ref": "#/definitions/codersdk.PreviewParameterStyling" + }, + "type": { + "$ref": "#/definitions/codersdk.OptionType" + }, + "validations": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameterValidation" + } + }, + "value": { + "$ref": "#/definitions/codersdk.NullHCLString" + } + } + }, + "codersdk.PreviewParameterOption": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "name": { + "type": "string" + }, + "value": { + "$ref": "#/definitions/codersdk.NullHCLString" + } + } + }, + "codersdk.PreviewParameterStyling": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "placeholder": { + "type": "string" + } + } + }, + "codersdk.PreviewParameterValidation": { + "type": "object", + "properties": { + "validation_error": { + "type": "string" + }, + "validation_max": { + "type": "integer" + }, + "validation_min": { + "type": "integer" + }, + "validation_monotonic": { + "type": "string" + }, + "validation_regex": { + "description": "All validation attributes are optional.", + "type": "string" + } + } + }, "codersdk.PrometheusConfig": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index b3f4dcce8f51a..2af3a8087eecd 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5246,7 +5246,14 @@ "required": true } ], - "responses": {} + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersResponse" + } + } + } } }, "/templateversions/{templateversion}/external-auth": { @@ -11296,6 +11303,22 @@ } } }, + "codersdk.DiagnosticExtra": { + "type": "object", + "properties": { + "code": { + "type": "string" + } + } + }, + "codersdk.DiagnosticSeverityString": { + "type": "string", + "enum": ["error", "warning"], + "x-enum-varnames": [ + "DiagnosticSeverityError", + "DiagnosticSeverityWarning" + ] + }, "codersdk.DisplayApp": { "type": "string", "enum": [ @@ -11313,6 +11336,26 @@ "DisplayAppSSH" ] }, + "codersdk.DynamicParametersResponse": { + "type": "object", + "properties": { + "diagnostics": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.FriendlyDiagnostic" + } + }, + "id": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameter" + } + } + } + }, "codersdk.Entitlement": { "type": "string", "enum": ["entitled", "grace_period", "not_entitled"], @@ -11589,6 +11632,23 @@ } } }, + "codersdk.FriendlyDiagnostic": { + "type": "object", + "properties": { + "detail": { + "type": "string" + }, + "extra": { + "$ref": "#/definitions/codersdk.DiagnosticExtra" + }, + "severity": { + "$ref": "#/definitions/codersdk.DiagnosticSeverityString" + }, + "summary": { + "type": "string" + } + } + }, "codersdk.GenerateAPIKeyResponse": { "type": "object", "properties": { @@ -12331,6 +12391,17 @@ } } }, + "codersdk.NullHCLString": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "codersdk.OAuth2AppEndpoints": { "type": "object", "properties": { @@ -12588,6 +12659,16 @@ } } }, + "codersdk.OptionType": { + "type": "string", + "enum": ["string", "number", "bool", "list(string)"], + "x-enum-varnames": [ + "OptionTypeString", + "OptionTypeNumber", + "OptionTypeBoolean", + "OptionTypeListString" + ] + }, "codersdk.Organization": { "type": "object", "required": ["created_at", "id", "is_default", "updated_at"], @@ -12730,6 +12811,35 @@ } } }, + "codersdk.ParameterFormType": { + "type": "string", + "enum": [ + "", + "radio", + "slider", + "input", + "dropdown", + "checkbox", + "switch", + "multi-select", + "tag-select", + "textarea", + "error" + ], + "x-enum-varnames": [ + "ParameterFormTypeDefault", + "ParameterFormTypeRadio", + "ParameterFormTypeSlider", + "ParameterFormTypeInput", + "ParameterFormTypeDropdown", + "ParameterFormTypeCheckbox", + "ParameterFormTypeSwitch", + "ParameterFormTypeMultiSelect", + "ParameterFormTypeTagSelect", + "ParameterFormTypeTextArea", + "ParameterFormTypeError" + ] + }, "codersdk.PatchGroupIDPSyncConfigRequest": { "type": "object", "properties": { @@ -13038,6 +13148,121 @@ } } }, + "codersdk.PreviewParameter": { + "type": "object", + "properties": { + "default_value": { + "$ref": "#/definitions/codersdk.NullHCLString" + }, + "description": { + "type": "string" + }, + "diagnostics": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.FriendlyDiagnostic" + } + }, + "display_name": { + "type": "string" + }, + "ephemeral": { + "type": "boolean" + }, + "form_type": { + "$ref": "#/definitions/codersdk.ParameterFormType" + }, + "icon": { + "type": "string" + }, + "mutable": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "options": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameterOption" + } + }, + "order": { + "description": "legacy_variable_name was removed (= 14)", + "type": "integer" + }, + "required": { + "type": "boolean" + }, + "styling": { + "$ref": "#/definitions/codersdk.PreviewParameterStyling" + }, + "type": { + "$ref": "#/definitions/codersdk.OptionType" + }, + "validations": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameterValidation" + } + }, + "value": { + "$ref": "#/definitions/codersdk.NullHCLString" + } + } + }, + "codersdk.PreviewParameterOption": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "icon": { + "type": "string" + }, + "name": { + "type": "string" + }, + "value": { + "$ref": "#/definitions/codersdk.NullHCLString" + } + } + }, + "codersdk.PreviewParameterStyling": { + "type": "object", + "properties": { + "disabled": { + "type": "boolean" + }, + "label": { + "type": "string" + }, + "placeholder": { + "type": "string" + } + } + }, + "codersdk.PreviewParameterValidation": { + "type": "object", + "properties": { + "validation_error": { + "type": "string" + }, + "validation_max": { + "type": "integer" + }, + "validation_min": { + "type": "integer" + }, + "validation_monotonic": { + "type": "string" + }, + "validation_regex": { + "description": "All validation attributes are optional.", + "type": "string" + } + } + }, "codersdk.PrometheusConfig": { "type": "object", "properties": { diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index f8e2152f629be..a2995240230cb 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -3281,6 +3281,35 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | `workspace_prebuilds` | [codersdk.PrebuildsConfig](#codersdkprebuildsconfig) | false | | | | `write_config` | boolean | false | | | +## codersdk.DiagnosticExtra + +```json +{ + "code": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|--------|--------|----------|--------------|-------------| +| `code` | string | false | | | + +## codersdk.DiagnosticSeverityString + +```json +"error" +``` + +### Properties + +#### Enumerated Values + +| Value | +|-----------| +| `error` | +| `warning` | + ## codersdk.DisplayApp ```json @@ -3299,6 +3328,89 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | `port_forwarding_helper` | | `ssh_helper` | +## codersdk.DynamicParametersResponse + +```json +{ + "diagnostics": [ + { + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" + } + ], + "id": 0, + "parameters": [ + { + "default_value": { + "valid": true, + "value": "string" + }, + "description": "string", + "diagnostics": [ + { + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" + } + ], + "display_name": "string", + "ephemeral": true, + "form_type": "", + "icon": "string", + "mutable": true, + "name": "string", + "options": [ + { + "description": "string", + "icon": "string", + "name": "string", + "value": { + "valid": true, + "value": "string" + } + } + ], + "order": 0, + "required": true, + "styling": { + "disabled": true, + "label": "string", + "placeholder": "string" + }, + "type": "string", + "validations": [ + { + "validation_error": "string", + "validation_max": 0, + "validation_min": 0, + "validation_monotonic": "string", + "validation_regex": "string" + } + ], + "value": { + "valid": true, + "value": "string" + } + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|---------------|---------------------------------------------------------------------|----------|--------------|-------------| +| `diagnostics` | array of [codersdk.FriendlyDiagnostic](#codersdkfriendlydiagnostic) | false | | | +| `id` | integer | false | | | +| `parameters` | array of [codersdk.PreviewParameter](#codersdkpreviewparameter) | false | | | + ## codersdk.Entitlement ```json @@ -3584,6 +3696,28 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith | `entitlement` | [codersdk.Entitlement](#codersdkentitlement) | false | | | | `limit` | integer | false | | | +## codersdk.FriendlyDiagnostic + +```json +{ + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|------------|------------------------------------------------------------------------|----------|--------------|-------------| +| `detail` | string | false | | | +| `extra` | [codersdk.DiagnosticExtra](#codersdkdiagnosticextra) | false | | | +| `severity` | [codersdk.DiagnosticSeverityString](#codersdkdiagnosticseveritystring) | false | | | +| `summary` | string | false | | | + ## codersdk.GenerateAPIKeyResponse ```json @@ -4548,6 +4682,22 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith |------------|----------------------------|----------|--------------|----------------------------------------------------------------------| | `endpoint` | [serpent.URL](#serpenturl) | false | | The URL to which the payload will be sent with an HTTP POST request. | +## codersdk.NullHCLString + +```json +{ + "valid": true, + "value": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|---------|---------|----------|--------------|-------------| +| `valid` | boolean | false | | | +| `value` | string | false | | | + ## codersdk.OAuth2AppEndpoints ```json @@ -4818,6 +4968,23 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith | `user_roles_default` | array of string | false | | | | `username_field` | string | false | | | +## codersdk.OptionType + +```json +"string" +``` + +### Properties + +#### Enumerated Values + +| Value | +|----------------| +| `string` | +| `number` | +| `bool` | +| `list(string)` | + ## codersdk.Organization ```json @@ -4985,6 +5152,30 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith | `count` | integer | false | | | | `members` | array of [codersdk.OrganizationMemberWithUserData](#codersdkorganizationmemberwithuserdata) | false | | | +## codersdk.ParameterFormType + +```json +"" +``` + +### Properties + +#### Enumerated Values + +| Value | +|----------------| +| `` | +| `radio` | +| `slider` | +| `input` | +| `dropdown` | +| `checkbox` | +| `switch` | +| `multi-select` | +| `tag-select` | +| `textarea` | +| `error` | + ## codersdk.PatchGroupIDPSyncConfigRequest ```json @@ -5319,6 +5510,150 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith | `name` | string | false | | | | `value` | string | false | | | +## codersdk.PreviewParameter + +```json +{ + "default_value": { + "valid": true, + "value": "string" + }, + "description": "string", + "diagnostics": [ + { + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" + } + ], + "display_name": "string", + "ephemeral": true, + "form_type": "", + "icon": "string", + "mutable": true, + "name": "string", + "options": [ + { + "description": "string", + "icon": "string", + "name": "string", + "value": { + "valid": true, + "value": "string" + } + } + ], + "order": 0, + "required": true, + "styling": { + "disabled": true, + "label": "string", + "placeholder": "string" + }, + "type": "string", + "validations": [ + { + "validation_error": "string", + "validation_max": 0, + "validation_min": 0, + "validation_monotonic": "string", + "validation_regex": "string" + } + ], + "value": { + "valid": true, + "value": "string" + } +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|-----------------|-------------------------------------------------------------------------------------|----------|--------------|-----------------------------------------| +| `default_value` | [codersdk.NullHCLString](#codersdknullhclstring) | false | | | +| `description` | string | false | | | +| `diagnostics` | array of [codersdk.FriendlyDiagnostic](#codersdkfriendlydiagnostic) | false | | | +| `display_name` | string | false | | | +| `ephemeral` | boolean | false | | | +| `form_type` | [codersdk.ParameterFormType](#codersdkparameterformtype) | false | | | +| `icon` | string | false | | | +| `mutable` | boolean | false | | | +| `name` | string | false | | | +| `options` | array of [codersdk.PreviewParameterOption](#codersdkpreviewparameteroption) | false | | | +| `order` | integer | false | | legacy_variable_name was removed (= 14) | +| `required` | boolean | false | | | +| `styling` | [codersdk.PreviewParameterStyling](#codersdkpreviewparameterstyling) | false | | | +| `type` | [codersdk.OptionType](#codersdkoptiontype) | false | | | +| `validations` | array of [codersdk.PreviewParameterValidation](#codersdkpreviewparametervalidation) | false | | | +| `value` | [codersdk.NullHCLString](#codersdknullhclstring) | false | | | + +## codersdk.PreviewParameterOption + +```json +{ + "description": "string", + "icon": "string", + "name": "string", + "value": { + "valid": true, + "value": "string" + } +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|---------------|--------------------------------------------------|----------|--------------|-------------| +| `description` | string | false | | | +| `icon` | string | false | | | +| `name` | string | false | | | +| `value` | [codersdk.NullHCLString](#codersdknullhclstring) | false | | | + +## codersdk.PreviewParameterStyling + +```json +{ + "disabled": true, + "label": "string", + "placeholder": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|---------------|---------|----------|--------------|-------------| +| `disabled` | boolean | false | | | +| `label` | string | false | | | +| `placeholder` | string | false | | | + +## codersdk.PreviewParameterValidation + +```json +{ + "validation_error": "string", + "validation_max": 0, + "validation_min": 0, + "validation_monotonic": "string", + "validation_regex": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|------------------------|---------|----------|--------------|-----------------------------------------| +| `validation_error` | string | false | | | +| `validation_max` | integer | false | | | +| `validation_min` | integer | false | | | +| `validation_monotonic` | string | false | | | +| `validation_regex` | string | false | | All validation attributes are optional. | + ## codersdk.PrometheusConfig ```json diff --git a/docs/reference/api/templates.md b/docs/reference/api/templates.md index 7efd65d83870a..c2d064231595d 100644 --- a/docs/reference/api/templates.md +++ b/docs/reference/api/templates.md @@ -2610,6 +2610,7 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio ```shell # Example request using curl curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/dynamic-parameters/evaluate \ + -H 'Accept: application/json' \ -H 'Coder-Session-Token: API_KEY' ``` @@ -2621,10 +2622,88 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/ |-------------------|------|--------------|----------|---------------------| | `templateversion` | path | string(uuid) | true | Template version ID | +### Example responses + +> 200 Response + +```json +{ + "diagnostics": [ + { + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" + } + ], + "id": 0, + "parameters": [ + { + "default_value": { + "valid": true, + "value": "string" + }, + "description": "string", + "diagnostics": [ + { + "detail": "string", + "extra": { + "code": "string" + }, + "severity": "error", + "summary": "string" + } + ], + "display_name": "string", + "ephemeral": true, + "form_type": "", + "icon": "string", + "mutable": true, + "name": "string", + "options": [ + { + "description": "string", + "icon": "string", + "name": "string", + "value": { + "valid": true, + "value": "string" + } + } + ], + "order": 0, + "required": true, + "styling": { + "disabled": true, + "label": "string", + "placeholder": "string" + }, + "type": "string", + "validations": [ + { + "validation_error": "string", + "validation_max": 0, + "validation_min": 0, + "validation_monotonic": "string", + "validation_regex": "string" + } + ], + "value": { + "valid": true, + "value": "string" + } + } + ] +} +``` + ### Responses -|Status|Meaning|Description|Schema| -|---|---|---|---| +| Status | Meaning | Description | Schema | +|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------| +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.DynamicParametersResponse](schemas.md#codersdkdynamicparametersresponse) | To perform this operation, you must be authenticated. [Learn more](authentication.md). From 19cba4cb395b200933961161e3fa7f6a281de1e1 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 13:04:09 -0500 Subject: [PATCH 11/13] swagger --- coderd/parameters.go | 1 + 1 file changed, 1 insertion(+) diff --git a/coderd/parameters.go b/coderd/parameters.go index b7793bcd49261..d8551b2031f7a 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -36,6 +36,7 @@ import ( // @Param templateversion path string true "Template version ID" format(uuid) // @Accept json // @Produce json +// @Param request body codersdk.DynamicParametersRequest true "Initial parameter values" // @Success 200 {object} codersdk.DynamicParametersResponse // @Router /templateversions/{templateversion}/dynamic-parameters/evaluate [post] func (api *API) templateVersionDynamicParametersEvaluate(rw http.ResponseWriter, r *http.Request) { From 6751fbab98c2666f9096feef94c86c7141260437 Mon Sep 17 00:00:00 2001 From: Emyrk Date: Mon, 2 Jun 2025 18:06:47 +0000 Subject: [PATCH 12/13] make gen --- coderd/apidoc/docs.go | 29 +++++++++++++++++++++++++++++ coderd/apidoc/swagger.json | 29 +++++++++++++++++++++++++++++ docs/reference/api/schemas.md | 22 ++++++++++++++++++++++ docs/reference/api/templates.md | 21 ++++++++++++++++++--- 4 files changed, 98 insertions(+), 3 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 4af0993101c91..07a0407c0014d 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5935,6 +5935,15 @@ const docTemplate = `{ "name": "templateversion", "in": "path", "required": true + }, + { + "description": "Initial parameter values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersRequest" + } } ], "responses": { @@ -12639,6 +12648,26 @@ const docTemplate = `{ "DisplayAppSSH" ] }, + "codersdk.DynamicParametersRequest": { + "type": "object", + "properties": { + "id": { + "description": "ID identifies the request. The response contains the same\nID so that the client can match it to the request.", + "type": "integer" + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "owner_id": { + "description": "OwnerID if uuid.Nil, it defaults to ` + "`" + `codersdk.Me` + "`" + `", + "type": "string", + "format": "uuid" + } + } + }, "codersdk.DynamicParametersResponse": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 2af3a8087eecd..076f170d27e72 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5244,6 +5244,15 @@ "name": "templateversion", "in": "path", "required": true + }, + { + "description": "Initial parameter values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersRequest" + } } ], "responses": { @@ -11336,6 +11345,26 @@ "DisplayAppSSH" ] }, + "codersdk.DynamicParametersRequest": { + "type": "object", + "properties": { + "id": { + "description": "ID identifies the request. The response contains the same\nID so that the client can match it to the request.", + "type": "integer" + }, + "inputs": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "owner_id": { + "description": "OwnerID if uuid.Nil, it defaults to `codersdk.Me`", + "type": "string", + "format": "uuid" + } + } + }, "codersdk.DynamicParametersResponse": { "type": "object", "properties": { diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index a2995240230cb..6b0f8254a720c 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -3328,6 +3328,28 @@ CreateWorkspaceRequest provides options for creating a new workspace. Only one o | `port_forwarding_helper` | | `ssh_helper` | +## codersdk.DynamicParametersRequest + +```json +{ + "id": 0, + "inputs": { + "property1": "string", + "property2": "string" + }, + "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|--------------------|---------|----------|--------------|--------------------------------------------------------------------------------------------------------------| +| `id` | integer | false | | ID identifies the request. The response contains the same ID so that the client can match it to the request. | +| `inputs` | object | false | | | +| ยป `[any property]` | string | false | | | +| `owner_id` | string | false | | Owner ID if uuid.Nil, it defaults to `codersdk.Me` | + ## codersdk.DynamicParametersResponse ```json diff --git a/docs/reference/api/templates.md b/docs/reference/api/templates.md index c2d064231595d..b1957873a1be6 100644 --- a/docs/reference/api/templates.md +++ b/docs/reference/api/templates.md @@ -2610,17 +2610,32 @@ To perform this operation, you must be authenticated. [Learn more](authenticatio ```shell # Example request using curl curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/dynamic-parameters/evaluate \ + -H 'Content-Type: application/json' \ -H 'Accept: application/json' \ -H 'Coder-Session-Token: API_KEY' ``` `POST /templateversions/{templateversion}/dynamic-parameters/evaluate` +> Body parameter + +```json +{ + "id": 0, + "inputs": { + "property1": "string", + "property2": "string" + }, + "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05" +} +``` + ### Parameters -| Name | In | Type | Required | Description | -|-------------------|------|--------------|----------|---------------------| -| `templateversion` | path | string(uuid) | true | Template version ID | +| Name | In | Type | Required | Description | +|-------------------|------|----------------------------------------------------------------------------------|----------|--------------------------| +| `templateversion` | path | string(uuid) | true | Template version ID | +| `body` | body | [codersdk.DynamicParametersRequest](schemas.md#codersdkdynamicparametersrequest) | true | Initial parameter values | ### Example responses From ca292ae74f139760416bd8a9a40d1cabfbf918e7 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Mon, 2 Jun 2025 13:31:30 -0500 Subject: [PATCH 13/13] fix router --- coderd/coderd.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/coderd.go b/coderd/coderd.go index 2eb64a11e9ca3..0b8a13befde56 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1156,7 +1156,7 @@ func New(options *Options) *API { r.Use( httpmw.RequireExperiment(api.Experiments, codersdk.ExperimentDynamicParameters), ) - r.Route("/dynamic-parameters/", func(r chi.Router) { + r.Route("/dynamic-parameters", func(r chi.Router) { r.Post("/evaluate", api.templateVersionDynamicParametersEvaluate) r.Get("/", api.templateVersionDynamicParametersWebsocket) })