diff --git a/cli/parameterresolver.go b/cli/parameterresolver.go index 8cae66527d503..486188d52a27a 100644 --- a/cli/parameterresolver.go +++ b/cli/parameterresolver.go @@ -141,6 +141,10 @@ next: continue // immutables should not be passed to consecutive builds } + if len(tvp.Options) > 0 && !isValidTemplateParameterOption(buildParameter, tvp.Options) { + continue // do not propagate invalid options + } + for i, r := range resolved { if r.Name == buildParameter.Name { resolved[i].Value = buildParameter.Value @@ -180,10 +184,12 @@ func (pr *ParameterResolver) resolveWithInput(resolved []codersdk.WorkspaceBuild // Parameter has not been resolved yet, so CLI needs to determine if user should input it. firstTimeUse := pr.isFirstTimeUse(tvp.Name) + promptParameterOption := pr.isLastBuildParameterInvalidOption(tvp) if (tvp.Ephemeral && pr.promptBuildOptions) || (action == WorkspaceCreate && tvp.Required) || (action == WorkspaceCreate && !tvp.Ephemeral) || + (action == WorkspaceUpdate && promptParameterOption) || (action == WorkspaceUpdate && tvp.Mutable && tvp.Required) || (action == WorkspaceUpdate && !tvp.Mutable && firstTimeUse) || (action == WorkspaceUpdate && tvp.Mutable && !tvp.Ephemeral && pr.promptRichParameters) { @@ -207,6 +213,19 @@ func (pr *ParameterResolver) isFirstTimeUse(parameterName string) bool { return findWorkspaceBuildParameter(parameterName, pr.lastBuildParameters) == nil } +func (pr *ParameterResolver) isLastBuildParameterInvalidOption(templateVersionParameter codersdk.TemplateVersionParameter) bool { + if len(templateVersionParameter.Options) == 0 { + return false + } + + for _, buildParameter := range pr.lastBuildParameters { + if buildParameter.Name == templateVersionParameter.Name { + return !isValidTemplateParameterOption(buildParameter, templateVersionParameter.Options) + } + } + return false +} + func findTemplateVersionParameter(workspaceBuildParameter codersdk.WorkspaceBuildParameter, templateVersionParameters []codersdk.TemplateVersionParameter) *codersdk.TemplateVersionParameter { for _, tvp := range templateVersionParameters { if tvp.Name == workspaceBuildParameter.Name { @@ -224,3 +243,12 @@ func findWorkspaceBuildParameter(parameterName string, params []codersdk.Workspa } return nil } + +func isValidTemplateParameterOption(buildParameter codersdk.WorkspaceBuildParameter, options []codersdk.TemplateVersionParameterOption) bool { + for _, opt := range options { + if opt.Value == buildParameter.Value { + return true + } + } + return false +} diff --git a/cli/root.go b/cli/root.go index 2b4db5eb8b221..fad5625d909c0 100644 --- a/cli/root.go +++ b/cli/root.go @@ -981,6 +981,8 @@ func (p *prettyErrorFormatter) format(err error) { msg = sdkError.Message if sdkError.Helper != "" { msg = msg + "\n" + sdkError.Helper + } else if sdkError.Detail != "" { + msg = msg + "\n" + sdkError.Detail } // The SDK error is usually good enough, and we don't want to overwhelm // the user with output. diff --git a/cli/update_test.go b/cli/update_test.go index a066eaef7278c..57e49d0db3766 100644 --- a/cli/update_test.go +++ b/cli/update_test.go @@ -593,12 +593,138 @@ func TestUpdateValidateRichParameters(t *testing.T) { assert.NoError(t, err) }() + pty.ExpectMatch("Planning workspace...") + <-doneChan + }) + + t.Run("ParameterOptionChanged", func(t *testing.T) { + t.Parallel() + + // Create template and workspace + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) + + templateParameters := []*proto.RichParameter{ + {Name: stringParameterName, Type: "string", Mutable: true, Required: true, Options: []*proto.RichParameterOption{ + {Name: "First option", Description: "This is first option", Value: "1st"}, + {Name: "Second option", Description: "This is second option", Value: "2nd"}, + {Name: "Third option", Description: "This is third option", Value: "3rd"}, + }}, + } + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, prepareEchoResponses(templateParameters)) + coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + + inv, root := clitest.New(t, "create", "my-workspace", "--yes", "--template", template.Name, "--parameter", fmt.Sprintf("%s=%s", stringParameterName, "2nd")) + clitest.SetupConfig(t, client, root) + err := inv.Run() + require.NoError(t, err) + + // Update template + updatedTemplateParameters := []*proto.RichParameter{ + {Name: stringParameterName, Type: "string", Mutable: true, Required: true, Options: []*proto.RichParameterOption{ + {Name: "first_option", Description: "This is first option", Value: "1"}, + {Name: "second_option", Description: "This is second option", Value: "2"}, + {Name: "third_option", Description: "This is third option", Value: "3"}, + }}, + } + + updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, prepareEchoResponses(updatedTemplateParameters), template.ID) + coderdtest.AwaitTemplateVersionJob(t, client, updatedVersion.ID) + err = client.UpdateActiveTemplateVersion(context.Background(), template.ID, codersdk.UpdateActiveTemplateVersion{ + ID: updatedVersion.ID, + }) + require.NoError(t, err) + + // Update the workspace + inv, root = clitest.New(t, "update", "my-workspace") + clitest.SetupConfig(t, client, root) + doneChan := make(chan struct{}) + pty := ptytest.New(t).Attach(inv) + go func() { + defer close(doneChan) + err := inv.Run() + assert.NoError(t, err) + }() + matches := []string{ + stringParameterName, "second_option", "Planning workspace...", "", } for i := 0; i < len(matches); i += 2 { match := matches[i] + value := matches[i+1] pty.ExpectMatch(match) + + if value != "" { + pty.WriteLine(value) + } + } + <-doneChan + }) + + t.Run("ParameterOptionDisappeared", func(t *testing.T) { + t.Parallel() + + // Create template and workspace + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) + + templateParameters := []*proto.RichParameter{ + {Name: stringParameterName, Type: "string", Mutable: true, Required: true, Options: []*proto.RichParameterOption{ + {Name: "First option", Description: "This is first option", Value: "1st"}, + {Name: "Second option", Description: "This is second option", Value: "2nd"}, + {Name: "Third option", Description: "This is third option", Value: "3rd"}, + }}, + } + version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, prepareEchoResponses(templateParameters)) + coderdtest.AwaitTemplateVersionJob(t, client, version.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID) + + inv, root := clitest.New(t, "create", "my-workspace", "--yes", "--template", template.Name, "--parameter", fmt.Sprintf("%s=%s", stringParameterName, "2nd")) + clitest.SetupConfig(t, client, root) + err := inv.Run() + require.NoError(t, err) + + // Update template - 2nd option disappeared, 4th option added + updatedTemplateParameters := []*proto.RichParameter{ + {Name: stringParameterName, Type: "string", Mutable: true, Required: true, Options: []*proto.RichParameterOption{ + {Name: "First option", Description: "This is first option", Value: "1st"}, + {Name: "Third option", Description: "This is third option", Value: "3rd"}, + {Name: "Fourth option", Description: "This is fourth option", Value: "4th"}, + }}, + } + + updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, prepareEchoResponses(updatedTemplateParameters), template.ID) + coderdtest.AwaitTemplateVersionJob(t, client, updatedVersion.ID) + err = client.UpdateActiveTemplateVersion(context.Background(), template.ID, codersdk.UpdateActiveTemplateVersion{ + ID: updatedVersion.ID, + }) + require.NoError(t, err) + + // Update the workspace + inv, root = clitest.New(t, "update", "my-workspace") + clitest.SetupConfig(t, client, root) + doneChan := make(chan struct{}) + pty := ptytest.New(t).Attach(inv) + go func() { + defer close(doneChan) + err := inv.Run() + assert.NoError(t, err) + }() + + matches := []string{ + stringParameterName, "Third option", + "Planning workspace...", "", + } + for i := 0; i < len(matches); i += 2 { + match := matches[i] + value := matches[i+1] + pty.ExpectMatch(match) + + if value != "" { + pty.WriteLine(value) + } } <-doneChan }) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 561848ba4a1bb..58f6d3267376e 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -8440,11 +8440,9 @@ const docTemplate = `{ "codersdk.JobErrorCode": { "type": "string", "enum": [ - "MISSING_TEMPLATE_PARAMETER", "REQUIRED_TEMPLATE_VARIABLES" ], "x-enum-varnames": [ - "MissingTemplateParameter", "RequiredTemplateVariables" ] }, @@ -8978,7 +8976,6 @@ const docTemplate = `{ }, "error_code": { "enum": [ - "MISSING_TEMPLATE_PARAMETER", "REQUIRED_TEMPLATE_VARIABLES" ], "allOf": [ diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index ee7c78c369698..5d88d599e3039 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -7572,11 +7572,8 @@ }, "codersdk.JobErrorCode": { "type": "string", - "enum": ["MISSING_TEMPLATE_PARAMETER", "REQUIRED_TEMPLATE_VARIABLES"], - "x-enum-varnames": [ - "MissingTemplateParameter", - "RequiredTemplateVariables" - ] + "enum": ["REQUIRED_TEMPLATE_VARIABLES"], + "x-enum-varnames": ["RequiredTemplateVariables"] }, "codersdk.License": { "type": "object", @@ -8070,7 +8067,7 @@ "type": "string" }, "error_code": { - "enum": ["MISSING_TEMPLATE_PARAMETER", "REQUIRED_TEMPLATE_VARIABLES"], + "enum": ["REQUIRED_TEMPLATE_VARIABLES"], "allOf": [ { "$ref": "#/definitions/codersdk.JobErrorCode" diff --git a/coderd/wsbuilder/wsbuilder.go b/coderd/wsbuilder/wsbuilder.go index 3b6bcf1ae832b..26090a4f1be99 100644 --- a/coderd/wsbuilder/wsbuilder.go +++ b/coderd/wsbuilder/wsbuilder.go @@ -525,7 +525,7 @@ func (b *Builder) getParameters() (names, values []string, err error) { // At this point, we've queried all the data we need from the database, // so the only errors are problems with the request (missing data, failed // validation, immutable parameters, etc.) - return nil, nil, BuildError{http.StatusBadRequest, err.Error(), err} + return nil, nil, BuildError{http.StatusBadRequest, fmt.Sprintf("Unable to validate parameter %q", templateVersionParameter.Name), err} } names = append(names, templateVersionParameter.Name) values = append(values, value) diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go index 30e0896707d56..4a3e280697f74 100644 --- a/codersdk/provisionerdaemons.go +++ b/codersdk/provisionerdaemons.go @@ -69,7 +69,6 @@ const ( type JobErrorCode string const ( - MissingTemplateParameter JobErrorCode = "MISSING_TEMPLATE_PARAMETER" RequiredTemplateVariables JobErrorCode = "REQUIRED_TEMPLATE_VARIABLES" ) @@ -81,7 +80,7 @@ type ProvisionerJob struct { CompletedAt *time.Time `json:"completed_at,omitempty" format:"date-time"` CanceledAt *time.Time `json:"canceled_at,omitempty" format:"date-time"` Error string `json:"error,omitempty"` - ErrorCode JobErrorCode `json:"error_code,omitempty" enums:"MISSING_TEMPLATE_PARAMETER,REQUIRED_TEMPLATE_VARIABLES"` + ErrorCode JobErrorCode `json:"error_code,omitempty" enums:"REQUIRED_TEMPLATE_VARIABLES"` Status ProvisionerJobStatus `json:"status" enums:"pending,running,succeeded,canceling,canceled,failed"` WorkerID *uuid.UUID `json:"worker_id,omitempty" format:"uuid"` FileID uuid.UUID `json:"file_id" format:"uuid"` diff --git a/docs/api/builds.md b/docs/api/builds.md index 782e41a6f61aa..f6aa71be7a555 100644 --- a/docs/api/builds.md +++ b/docs/api/builds.md @@ -39,7 +39,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -201,7 +201,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild} \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -759,7 +759,7 @@ curl -X GET http://coder-server:8080/api/v2/workspacebuilds/{workspacebuild}/sta "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -926,7 +926,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace}/builds \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -1163,7 +1163,6 @@ Status Code **200** | Property | Value | | ------------------------- | ----------------------------- | -| `error_code` | `MISSING_TEMPLATE_PARAMETER` | | `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | | `status` | `pending` | | `status` | `running` | @@ -1273,7 +1272,7 @@ curl -X POST http://coder-server:8080/api/v2/workspaces/{workspace}/builds \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 019043cfda687..b9b55dc7fbe26 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -3090,7 +3090,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in ## codersdk.JobErrorCode ```json -"MISSING_TEMPLATE_PARAMETER" +"REQUIRED_TEMPLATE_VARIABLES" ``` ### Properties @@ -3099,7 +3099,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | Value | | ----------------------------- | -| `MISSING_TEMPLATE_PARAMETER` | | `REQUIRED_TEMPLATE_VARIABLES` | ## codersdk.License @@ -3628,7 +3627,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -3666,7 +3665,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | Property | Value | | ------------ | ----------------------------- | -| `error_code` | `MISSING_TEMPLATE_PARAMETER` | | `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | | `status` | `pending` | | `status` | `running` | @@ -4658,7 +4656,7 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -5371,7 +5369,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -5978,7 +5976,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -6505,7 +6503,7 @@ If the schedule is empty, the user will be updated to use the default schedule.| "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, diff --git a/docs/api/templates.md b/docs/api/templates.md index 14ce5dec7d29f..407ab84eba439 100644 --- a/docs/api/templates.md +++ b/docs/api/templates.md @@ -385,7 +385,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -455,7 +455,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -549,7 +549,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -850,7 +850,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -920,7 +920,6 @@ Status Code **200** | Property | Value | | ------------ | ----------------------------- | -| `error_code` | `MISSING_TEMPLATE_PARAMETER` | | `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | | `status` | `pending` | | `status` | `running` | @@ -1024,7 +1023,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/versions/{templ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -1094,7 +1093,6 @@ Status Code **200** | Property | Value | | ------------ | ----------------------------- | -| `error_code` | `MISSING_TEMPLATE_PARAMETER` | | `error_code` | `REQUIRED_TEMPLATE_VARIABLES` | | `status` | `pending` | | `status` | `running` | @@ -1142,7 +1140,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -1221,7 +1219,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templateversions/{templateversion} "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -1347,7 +1345,7 @@ curl -X POST http://coder-server:8080/api/v2/templateversions/{templateversion}/ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -1400,7 +1398,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/d "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, diff --git a/docs/api/workspaces.md b/docs/api/workspaces.md index f5c4aadd729c5..01b85e21b3527 100644 --- a/docs/api/workspaces.md +++ b/docs/api/workspaces.md @@ -67,7 +67,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/member "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -255,7 +255,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -446,7 +446,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -631,7 +631,7 @@ curl -X GET http://coder-server:8080/api/v2/workspaces/{workspace} \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, @@ -953,7 +953,7 @@ curl -X PUT http://coder-server:8080/api/v2/workspaces/{workspace}/lock \ "completed_at": "2019-08-24T14:15:22Z", "created_at": "2019-08-24T14:15:22Z", "error": "string", - "error_code": "MISSING_TEMPLATE_PARAMETER", + "error_code": "REQUIRED_TEMPLATE_VARIABLES", "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "queue_position": 0, diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 7625368589e31..eefbcfba275e7 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -1225,7 +1225,6 @@ const getMissingParameters = ( if (isMutableAndRequired || isImmutable) { requiredParameters.push(p) - return } }) @@ -1248,6 +1247,35 @@ const getMissingParameters = ( missingParameters.push(parameter) } + // Check if parameter "options" changed and we can't use old build parameters. + templateParameters.forEach((templateParameter) => { + if (templateParameter.options.length === 0) { + return + } + + // Check if there is a new value + let buildParameter = newBuildParameters.find( + (p) => p.name === templateParameter.name, + ) + + // If not, get the old one + if (!buildParameter) { + buildParameter = oldBuildParameters.find( + (p) => p.name === templateParameter.name, + ) + } + + if (!buildParameter) { + return + } + + const matchingOption = templateParameter.options.find( + (option) => option.value === buildParameter?.value, + ) + if (!matchingOption) { + missingParameters.push(templateParameter) + } + }) return missingParameters } diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 7d93591344fb8..ebe8fb61218e2 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1663,13 +1663,8 @@ export type InsightsReportInterval = "day" export const InsightsReportIntervals: InsightsReportInterval[] = ["day"] // From codersdk/provisionerdaemons.go -export type JobErrorCode = - | "MISSING_TEMPLATE_PARAMETER" - | "REQUIRED_TEMPLATE_VARIABLES" -export const JobErrorCodes: JobErrorCode[] = [ - "MISSING_TEMPLATE_PARAMETER", - "REQUIRED_TEMPLATE_VARIABLES", -] +export type JobErrorCode = "REQUIRED_TEMPLATE_VARIABLES" +export const JobErrorCodes: JobErrorCode[] = ["REQUIRED_TEMPLATE_VARIABLES"] // From codersdk/provisionerdaemons.go export type LogLevel = "debug" | "error" | "info" | "trace" | "warn" diff --git a/site/src/pages/WorkspacePage/UpdateBuildParametersDialog.tsx b/site/src/pages/WorkspacePage/UpdateBuildParametersDialog.tsx index 33d42b6bc5ae2..860969267fb7e 100644 --- a/site/src/pages/WorkspacePage/UpdateBuildParametersDialog.tsx +++ b/site/src/pages/WorkspacePage/UpdateBuildParametersDialog.tsx @@ -48,6 +48,7 @@ export const UpdateBuildParametersDialog: FC< onSubmit: (values) => { onUpdate(values.rich_parameter_values) }, + enableReinitialize: true, }) const getFieldHelpers = getFormHelpers(form) const { t } = useTranslation("workspacePage") diff --git a/site/src/xServices/createTemplate/createTemplateXService.ts b/site/src/xServices/createTemplate/createTemplateXService.ts index 3d4205fc23f05..bfff04549fe17 100644 --- a/site/src/xServices/createTemplate/createTemplateXService.ts +++ b/site/src/xServices/createTemplate/createTemplateXService.ts @@ -517,11 +517,7 @@ export const createTemplateMachine = isNotUsingExample: ({ exampleId }) => !exampleId, hasFile: ({ file }) => Boolean(file), hasFailed: (_, { data }) => - Boolean( - data.job.status === "failed" && - !isMissingParameter(data) && - !isMissingVariables(data), - ), + Boolean(data.job.status === "failed" && !isMissingVariables(data)), hasNoParametersOrVariables: (_, { data }) => data.variables === undefined, hasParametersOrVariables: (_, { data }) => { @@ -531,13 +527,6 @@ export const createTemplateMachine = }, ) -const isMissingParameter = (version: TemplateVersion) => { - return Boolean( - version.job.error_code && - version.job.error_code === "MISSING_TEMPLATE_PARAMETER", - ) -} - const isMissingVariables = (version: TemplateVersion) => { return Boolean( version.job.error_code && 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