diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 16a51d187a486..07a0407c0014d 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-for-template-version", + "parameters": [ { "type": "string", "format": "uuid", @@ -5908,11 +5935,23 @@ const docTemplate = `{ "name": "templateversion", "in": "path", "required": true + }, + { + "description": "Initial parameter values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersRequest" + } } ], "responses": { - "101": { - "description": "Switching Protocols" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersResponse" + } } } } @@ -12573,6 +12612,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": [ @@ -12590,6 +12648,46 @@ 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": { + "diagnostics": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.FriendlyDiagnostic" + } + }, + "id": { + "type": "integer" + }, + "parameters": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.PreviewParameter" + } + } + } + }, "codersdk.Entitlement": { "type": "string", "enum": [ @@ -12870,6 +12968,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": { @@ -13661,6 +13776,17 @@ const docTemplate = `{ } } }, + "codersdk.NullHCLString": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "codersdk.OAuth2AppEndpoints": { "type": "object", "properties": { @@ -13918,6 +14044,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": [ @@ -14065,6 +14206,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": { @@ -14381,6 +14551,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 986862df59a09..076f170d27e72 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-for-template-version", + "parameters": [ { "type": "string", "format": "uuid", @@ -5223,11 +5244,23 @@ "name": "templateversion", "in": "path", "required": true + }, + { + "description": "Initial parameter values", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersRequest" + } } ], "responses": { - "101": { - "description": "Switching Protocols" + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.DynamicParametersResponse" + } } } } @@ -11279,6 +11312,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": [ @@ -11296,6 +11345,46 @@ "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": { + "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"], @@ -11572,6 +11661,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": { @@ -12314,6 +12420,17 @@ } } }, + "codersdk.NullHCLString": { + "type": "object", + "properties": { + "valid": { + "type": "boolean" + }, + "value": { + "type": "string" + } + } + }, "codersdk.OAuth2AppEndpoints": { "type": "object", "properties": { @@ -12571,6 +12688,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"], @@ -12713,6 +12840,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": { @@ -13021,6 +13177,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/coderd/coderd.go b/coderd/coderd.go index 69d942304acea..0b8a13befde56 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.Post("/evaluate", api.templateVersionDynamicParametersEvaluate) + r.Get("/", api.templateVersionDynamicParametersWebsocket) + }) }) }) r.Route("/users", func(r chi.Router) { diff --git a/coderd/parameters.go b/coderd/parameters.go index d1e989c8ad032..d8551b2031f7a 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -29,57 +29,89 @@ import ( "github.com/coder/websocket" ) +// @Summary Evaluate dynamic parameters for template version +// @ID evaluate-dynamic-parameters-for-template-version +// @Security CoderSessionToken +// @Tags Templates +// @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) { + 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) { +// 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() apikey = httpmw.APIKey(r) @@ -159,7 +191,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 +218,16 @@ 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) { +// 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) if err != nil { @@ -275,7 +313,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 +335,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) 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: 0, + 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 +379,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), diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index f8e2152f629be..6b0f8254a720c 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,111 @@ 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 +{ + "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 +3718,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 +4704,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 +4990,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 +5174,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 +5532,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 6075af775c9bc..b1957873a1be6 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,125 @@ 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 '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 | +| `body` | body | [codersdk.DynamicParametersRequest](schemas.md#codersdkdynamicparametersrequest) | true | Initial parameter values | + +### 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 | +|--------|---------------------------------------------------------|-------------|------------------------------------------------------------------------------------| +| 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). + ## Get external auth by template version ### Code samples 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