From 6f67a9aca51a69bbf1df770060f77c54a626eca2 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Tue, 13 May 2025 16:16:21 -0500 Subject: [PATCH 1/8] chore: previous template versions missing dynamic param metadata --- coderd/parameters.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 6b6f4db531533..5f3656a12d73e 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -8,6 +8,7 @@ import ( "time" "github.com/google/uuid" + "github.com/hashicorp/hcl/v2" "golang.org/x/sync/errgroup" "golang.org/x/xerrors" @@ -79,11 +80,21 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http } defer api.FileCache.Release(fileID) + staticDiagnostics := hcl.Diagnostics{} + // Having the Terraform plan available for the evaluation engine is helpful // for populating values from data blocks, but isn't strictly required. If // we don't have a cached plan available, we just use an empty one instead. plan := json.RawMessage("{}") tf, err := api.Database.GetTemplateVersionTerraformValues(ctx, templateVersion.ID) + if xerrors.Is(err, sql.ErrNoRows) { + staticDiagnostics.Append(&hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "This template version is missing required metadata to support dynamic parameters.", + Detail: "To restore full functionality, please re-import the terraform as a new template version.", + }) + } + if err == nil { plan = tf.CachedPlan @@ -148,7 +159,7 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http result, diagnostics := preview.Preview(ctx, input, templateFS) response := codersdk.DynamicParametersResponse{ ID: -1, - Diagnostics: previewtypes.Diagnostics(diagnostics), + Diagnostics: previewtypes.Diagnostics(diagnostics.Extend(staticDiagnostics)), } if result != nil { response.Parameters = result.Parameters @@ -176,7 +187,7 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http result, diagnostics := preview.Preview(ctx, input, templateFS) response := codersdk.DynamicParametersResponse{ ID: update.ID, - Diagnostics: previewtypes.Diagnostics(diagnostics), + Diagnostics: previewtypes.Diagnostics(diagnostics.Extend(staticDiagnostics)), } if result != nil { response.Parameters = result.Parameters From 2d1701d06d4c0bb27a4d8b39cb67f699e7d49556 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Tue, 13 May 2025 16:58:21 -0500 Subject: [PATCH 2/8] chore: add parameter warning if metadata is missing Dynamic parameters require the latest provisioner to function --- coderd/coderd.go | 1 + coderd/database/dbgen/dbgen.go | 10 ++++---- coderd/database/dump.sql | 5 +++- ...00324_dynamic_parameters_metadata.down.sql | 1 + .../000324_dynamic_parameters_metadata.up.sql | 4 ++++ coderd/database/models.go | 2 ++ coderd/database/queries.sql.go | 19 +++++++++------ .../templateversionterraformvalues.sql | 6 +++-- coderd/parameters.go | 23 ++++++++++++++----- .../provisionerdserver/provisionerdserver.go | 12 ++++++---- .../provisionerdserver_test.go | 1 + enterprise/coderd/provisionerdaemons.go | 1 + 12 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql create mode 100644 coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql diff --git a/coderd/coderd.go b/coderd/coderd.go index 86db50d9559a4..5f423688cd9b8 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1771,6 +1771,7 @@ func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, n logger := api.Logger.Named(fmt.Sprintf("inmem-provisionerd-%s", name)) srv, err := provisionerdserver.NewServer( api.ctx, // use the same ctx as the API + daemon.APIVersion, api.AccessURL, daemon.ID, defaultOrg.ID, diff --git a/coderd/database/dbgen/dbgen.go b/coderd/database/dbgen/dbgen.go index b16faba6a8891..161a984d1bf0e 100644 --- a/coderd/database/dbgen/dbgen.go +++ b/coderd/database/dbgen/dbgen.go @@ -29,6 +29,7 @@ import ( "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/cryptorand" + "github.com/coder/coder/v2/provisionerd/proto" "github.com/coder/coder/v2/testutil" ) @@ -1000,10 +1001,11 @@ func TemplateVersionTerraformValues(t testing.TB, db database.Store, orig databa t.Helper() params := database.InsertTemplateVersionTerraformValuesByJobIDParams{ - JobID: takeFirst(orig.JobID, uuid.New()), - CachedPlan: takeFirstSlice(orig.CachedPlan, []byte("{}")), - CachedModuleFiles: orig.CachedModuleFiles, - UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()), + JobID: takeFirst(orig.JobID, uuid.New()), + CachedPlan: takeFirstSlice(orig.CachedPlan, []byte("{}")), + CachedModuleFiles: orig.CachedModuleFiles, + UpdatedAt: takeFirst(orig.UpdatedAt, dbtime.Now()), + ProvisionerdVersion: takeFirst(orig.ProvisionerdVersion, proto.CurrentVersion.String()), } err := db.InsertTemplateVersionTerraformValuesByJobID(genCtx, params) diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql index a03ea910f937c..f56b417dbe4d4 100644 --- a/coderd/database/dump.sql +++ b/coderd/database/dump.sql @@ -1441,9 +1441,12 @@ CREATE TABLE template_version_terraform_values ( template_version_id uuid NOT NULL, updated_at timestamp with time zone DEFAULT now() NOT NULL, cached_plan jsonb NOT NULL, - cached_module_files uuid + cached_module_files uuid, + provisionerd_version text DEFAULT ''::text NOT NULL ); +COMMENT ON COLUMN template_version_terraform_values.provisionerd_version IS 'What version of the provisioning engine was used to generate the cached plan and module files.'; + CREATE TABLE template_version_variables ( template_version_id uuid NOT NULL, name text NOT NULL, diff --git a/coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql b/coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql new file mode 100644 index 0000000000000..991871b5700ab --- /dev/null +++ b/coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql @@ -0,0 +1 @@ +ALTER TABLE template_version_terraform_values DROP COLUMN provisionerd_version; diff --git a/coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql b/coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql new file mode 100644 index 0000000000000..05403341e2218 --- /dev/null +++ b/coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql @@ -0,0 +1,4 @@ +ALTER TABLE template_version_terraform_values ADD COLUMN provisionerd_version TEXT NOT NULL DEFAULT ''; + +COMMENT ON COLUMN template_version_terraform_values.provisionerd_version IS + 'What version of the provisioning engine was used to generate the cached plan and module files.'; diff --git a/coderd/database/models.go b/coderd/database/models.go index 3944d56268eaf..1b6ea7591d652 100644 --- a/coderd/database/models.go +++ b/coderd/database/models.go @@ -3225,6 +3225,8 @@ type TemplateVersionTerraformValue struct { UpdatedAt time.Time `db:"updated_at" json:"updated_at"` CachedPlan json.RawMessage `db:"cached_plan" json:"cached_plan"` CachedModuleFiles uuid.NullUUID `db:"cached_module_files" json:"cached_module_files"` + // What version of the provisioning engine was used to generate the cached plan and module files. + ProvisionerdVersion string `db:"provisionerd_version" json:"provisionerd_version"` } type TemplateVersionVariable struct { diff --git a/coderd/database/queries.sql.go b/coderd/database/queries.sql.go index e2e38c36fe10a..dbae305c9b7fd 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -11698,7 +11698,7 @@ func (q *sqlQuerier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx conte const getTemplateVersionTerraformValues = `-- name: GetTemplateVersionTerraformValues :one SELECT - template_version_terraform_values.template_version_id, template_version_terraform_values.updated_at, template_version_terraform_values.cached_plan, template_version_terraform_values.cached_module_files + template_version_terraform_values.template_version_id, template_version_terraform_values.updated_at, template_version_terraform_values.cached_plan, template_version_terraform_values.cached_module_files, template_version_terraform_values.provisionerd_version FROM template_version_terraform_values WHERE @@ -11713,6 +11713,7 @@ func (q *sqlQuerier) GetTemplateVersionTerraformValues(ctx context.Context, temp &i.UpdatedAt, &i.CachedPlan, &i.CachedModuleFiles, + &i.ProvisionerdVersion, ) return i, err } @@ -11723,22 +11724,25 @@ INSERT INTO template_version_id, cached_plan, cached_module_files, - updated_at + updated_at, + provisionerd_version ) VALUES ( (select id from template_versions where job_id = $1), $2, $3, - $4 + $4, + $5 ) ` type InsertTemplateVersionTerraformValuesByJobIDParams struct { - JobID uuid.UUID `db:"job_id" json:"job_id"` - CachedPlan json.RawMessage `db:"cached_plan" json:"cached_plan"` - CachedModuleFiles uuid.NullUUID `db:"cached_module_files" json:"cached_module_files"` - UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + JobID uuid.UUID `db:"job_id" json:"job_id"` + CachedPlan json.RawMessage `db:"cached_plan" json:"cached_plan"` + CachedModuleFiles uuid.NullUUID `db:"cached_module_files" json:"cached_module_files"` + UpdatedAt time.Time `db:"updated_at" json:"updated_at"` + ProvisionerdVersion string `db:"provisionerd_version" json:"provisionerd_version"` } func (q *sqlQuerier) InsertTemplateVersionTerraformValuesByJobID(ctx context.Context, arg InsertTemplateVersionTerraformValuesByJobIDParams) error { @@ -11747,6 +11751,7 @@ func (q *sqlQuerier) InsertTemplateVersionTerraformValuesByJobID(ctx context.Con arg.CachedPlan, arg.CachedModuleFiles, arg.UpdatedAt, + arg.ProvisionerdVersion, ) return err } diff --git a/coderd/database/queries/templateversionterraformvalues.sql b/coderd/database/queries/templateversionterraformvalues.sql index b4c93081177f1..2ded4a2675375 100644 --- a/coderd/database/queries/templateversionterraformvalues.sql +++ b/coderd/database/queries/templateversionterraformvalues.sql @@ -12,12 +12,14 @@ INSERT INTO template_version_id, cached_plan, cached_module_files, - updated_at + updated_at, + provisionerd_version ) VALUES ( (select id from template_versions where job_id = @job_id), @cached_plan, @cached_module_files, - @updated_at + @updated_at, + @provisionerd_version ); diff --git a/coderd/parameters.go b/coderd/parameters.go index 5f3656a12d73e..43efbc22659db 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -12,6 +12,7 @@ import ( "golang.org/x/sync/errgroup" "golang.org/x/xerrors" + "github.com/coder/coder/v2/apiversion" "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/files" @@ -81,6 +82,11 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http defer api.FileCache.Release(fileID) staticDiagnostics := hcl.Diagnostics{} + missingMetaData := hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "This template version is missing required metadata to support dynamic parameters. Go back to the classic creation flow.", + Detail: "To restore full functionality, please re-import the terraform as a new template version.", + } // Having the Terraform plan available for the evaluation engine is helpful // for populating values from data blocks, but isn't strictly required. If @@ -88,16 +94,21 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http plan := json.RawMessage("{}") tf, err := api.Database.GetTemplateVersionTerraformValues(ctx, templateVersion.ID) if xerrors.Is(err, sql.ErrNoRows) { - staticDiagnostics.Append(&hcl.Diagnostic{ - Severity: hcl.DiagWarning, - Summary: "This template version is missing required metadata to support dynamic parameters.", - Detail: "To restore full functionality, please re-import the terraform as a new template version.", - }) + staticDiagnostics = staticDiagnostics.Append(&missingMetaData) } - if err == nil { plan = tf.CachedPlan + major, minor, err := apiversion.Parse(tf.ProvisionerdVersion) + if err != nil || tf.ProvisionerdVersion == "" { + staticDiagnostics = staticDiagnostics.Append(&missingMetaData) + } else if major < 1 || (major == 1 && minor < 5) { + missingMetaData.Detail = "This template version requires provisioner v1.5 or newer to support dynamic parameters. " + + "Some options may be missing or incorrect. " + + "Please contact an administrator to update the provisioner and re-import the template version." + staticDiagnostics = staticDiagnostics.Append(&missingMetaData) + } + if tf.CachedModuleFiles.Valid { moduleFilesFS, err := api.FileCache.Acquire(fileCtx, tf.CachedModuleFiles.UUID) if err != nil { diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 1206d81025d7a..d3f1e2b8ee4dd 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -92,6 +92,7 @@ type Options struct { } type server struct { + apiVersion string // lifecycleCtx must be tied to the API server's lifecycle // as when the API server shuts down, we want to cancel any // long-running operations. @@ -151,6 +152,7 @@ func (t Tags) Valid() error { func NewServer( lifecycleCtx context.Context, + apiVersion string, accessURL *url.URL, id uuid.UUID, organizationID uuid.UUID, @@ -210,6 +212,7 @@ func NewServer( s := &server{ lifecycleCtx: lifecycleCtx, + apiVersion: apiVersion, AccessURL: accessURL, ID: id, OrganizationID: organizationID, @@ -1506,10 +1509,11 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob) } err = s.Database.InsertTemplateVersionTerraformValuesByJobID(ctx, database.InsertTemplateVersionTerraformValuesByJobIDParams{ - JobID: jobID, - UpdatedAt: now, - CachedPlan: plan, - CachedModuleFiles: fileID, + JobID: jobID, + UpdatedAt: now, + CachedPlan: plan, + CachedModuleFiles: fileID, + ProvisionerdVersion: s.apiVersion, }) if err != nil { return nil, xerrors.Errorf("insert template version terraform data: %w", err) diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 9cfb3449ea522..bb3112eb3f033 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -2719,6 +2719,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi srv, err := provisionerdserver.NewServer( ov.ctx, + proto.CurrentVersion.String(), &url.URL{}, daemon.ID, defOrg.ID, diff --git a/enterprise/coderd/provisionerdaemons.go b/enterprise/coderd/provisionerdaemons.go index b9a93144f4931..3c529fa8bcfdd 100644 --- a/enterprise/coderd/provisionerdaemons.go +++ b/enterprise/coderd/provisionerdaemons.go @@ -335,6 +335,7 @@ func (api *API) provisionerDaemonServe(rw http.ResponseWriter, r *http.Request) logger.Info(ctx, "starting external provisioner daemon") srv, err := provisionerdserver.NewServer( srvCtx, + daemon.APIVersion, api.AccessURL, daemon.ID, authRes.orgID, From 0351ce54fc47bb3b5b73d63f19b9b985f4e45990 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Tue, 13 May 2025 17:13:01 -0500 Subject: [PATCH 3/8] update dbmem --- coderd/database/dbmem/dbmem.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/coderd/database/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index 2760c0c929c58..4c6a58d2cb840 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -9319,10 +9319,11 @@ func (q *FakeQuerier) InsertTemplateVersionTerraformValuesByJobID(_ context.Cont // Insert the new row row := database.TemplateVersionTerraformValue{ - TemplateVersionID: templateVersion.ID, - CachedPlan: arg.CachedPlan, - CachedModuleFiles: arg.CachedModuleFiles, - UpdatedAt: arg.UpdatedAt, + TemplateVersionID: templateVersion.ID, + UpdatedAt: arg.UpdatedAt, + CachedPlan: arg.CachedPlan, + CachedModuleFiles: arg.CachedModuleFiles, + ProvisionerdVersion: arg.ProvisionerdVersion, } q.templateVersionTerraformValues = append(q.templateVersionTerraformValues, row) return nil From 9f947c3caebf944231b96d1aa73d238bb95dd57a Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 14 May 2025 09:50:21 -0500 Subject: [PATCH 4/8] refactor warnings into its own function --- ...0325_dynamic_parameters_metadata.down.sql} | 0 ...000325_dynamic_parameters_metadata.up.sql} | 2 +- coderd/parameters.go | 52 ++++++++----- coderd/parameters_internal_test.go | 78 +++++++++++++++++++ 4 files changed, 111 insertions(+), 21 deletions(-) rename coderd/database/migrations/{000324_dynamic_parameters_metadata.down.sql => 000325_dynamic_parameters_metadata.down.sql} (100%) rename coderd/database/migrations/{000324_dynamic_parameters_metadata.up.sql => 000325_dynamic_parameters_metadata.up.sql} (59%) create mode 100644 coderd/parameters_internal_test.go diff --git a/coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql b/coderd/database/migrations/000325_dynamic_parameters_metadata.down.sql similarity index 100% rename from coderd/database/migrations/000324_dynamic_parameters_metadata.down.sql rename to coderd/database/migrations/000325_dynamic_parameters_metadata.down.sql diff --git a/coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql b/coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql similarity index 59% rename from coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql rename to coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql index 05403341e2218..211693b7f3e79 100644 --- a/coderd/database/migrations/000324_dynamic_parameters_metadata.up.sql +++ b/coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql @@ -1,4 +1,4 @@ -ALTER TABLE template_version_terraform_values ADD COLUMN provisionerd_version TEXT NOT NULL DEFAULT ''; +ALTER TABLE template_version_terraform_values ADD COLUMN IF NOT EXISTS provisionerd_version TEXT NOT NULL DEFAULT ''; COMMENT ON COLUMN template_version_terraform_values.provisionerd_version IS 'What version of the provisioning engine was used to generate the cached plan and module files.'; diff --git a/coderd/parameters.go b/coderd/parameters.go index 43efbc22659db..3019322dc4ddf 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -81,34 +81,14 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http } defer api.FileCache.Release(fileID) - staticDiagnostics := hcl.Diagnostics{} - missingMetaData := hcl.Diagnostic{ - Severity: hcl.DiagWarning, - Summary: "This template version is missing required metadata to support dynamic parameters. Go back to the classic creation flow.", - Detail: "To restore full functionality, please re-import the terraform as a new template version.", - } - // Having the Terraform plan available for the evaluation engine is helpful // for populating values from data blocks, but isn't strictly required. If // we don't have a cached plan available, we just use an empty one instead. plan := json.RawMessage("{}") tf, err := api.Database.GetTemplateVersionTerraformValues(ctx, templateVersion.ID) - if xerrors.Is(err, sql.ErrNoRows) { - staticDiagnostics = staticDiagnostics.Append(&missingMetaData) - } if err == nil { plan = tf.CachedPlan - major, minor, err := apiversion.Parse(tf.ProvisionerdVersion) - if err != nil || tf.ProvisionerdVersion == "" { - staticDiagnostics = staticDiagnostics.Append(&missingMetaData) - } else if major < 1 || (major == 1 && minor < 5) { - missingMetaData.Detail = "This template version requires provisioner v1.5 or newer to support dynamic parameters. " + - "Some options may be missing or incorrect. " + - "Please contact an administrator to update the provisioner and re-import the template version." - staticDiagnostics = staticDiagnostics.Append(&missingMetaData) - } - if tf.CachedModuleFiles.Valid { moduleFilesFS, err := api.FileCache.Acquire(fileCtx, tf.CachedModuleFiles.UUID) if err != nil { @@ -136,6 +116,10 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http return } + var staticDiagnostics hcl.Diagnostics + // If the err is sql.ErrNoRows, an empty terraform values struct is correct. + staticDiagnostics = staticDiagnostics.Extend(parameterProvisionerVersionDiagnostic(tf)) + owner, err := api.getWorkspaceOwnerData(ctx, user, templateVersion.OrganizationID) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ @@ -291,3 +275,31 @@ func (api *API) getWorkspaceOwnerData( Groups: groupNames, }, nil } + +// parameterProvisionerVersionDiagnostic checks the version of the provisioner +// used to create the template version. If the version is less than 1.5, it +// returns a warning diagnostic. Only versions 1.5+ return the module & plan data +// required. +func parameterProvisionerVersionDiagnostic(tf database.TemplateVersionTerraformValue) hcl.Diagnostics { + missingMetaData := hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: "This template version is missing required metadata to support dynamic parameters. Go back to the classic creation flow.", + Detail: "To restore full functionality, please re-import the terraform as a new template version.", + } + + if tf.ProvisionerdVersion == "" { + return hcl.Diagnostics{&missingMetaData} + } + + major, minor, err := apiversion.Parse(tf.ProvisionerdVersion) + if err != nil || tf.ProvisionerdVersion == "" { + return hcl.Diagnostics{&missingMetaData} + } else if major < 1 || (major == 1 && minor < 5) { + missingMetaData.Detail = "This template version requires provisioner v1.5 or newer to support dynamic parameters. " + + "Some options may be missing or incorrect. " + + "Please contact an administrator to update the provisioner and re-import the template version." + return hcl.Diagnostics{&missingMetaData} + } + + return nil +} diff --git a/coderd/parameters_internal_test.go b/coderd/parameters_internal_test.go new file mode 100644 index 0000000000000..59730c42879ea --- /dev/null +++ b/coderd/parameters_internal_test.go @@ -0,0 +1,78 @@ +package coderd + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/v2/coderd/database" +) + +func Test_parameterProvisionerVersionDiagnostic(t *testing.T) { + t.Parallel() + + testCases := []struct { + version string + warning bool + }{ + { + version: "", + warning: true, + }, + { + version: "invalid", + warning: true, + }, + { + version: "0.4", + warning: true, + }, + { + version: "0.5", + warning: true, + }, + { + version: "0.6", + warning: true, + }, + { + version: "1.4", + warning: true, + }, + { + version: "1.5", + warning: false, + }, + { + version: "1.6", + warning: false, + }, + { + version: "2.0", + warning: false, + }, + { + version: "2.5", + warning: false, + }, + { + version: "2.6", + warning: false, + }, + } + + for _, tc := range testCases { + t.Run("Version_"+tc.version, func(t *testing.T) { + t.Parallel() + diags := parameterProvisionerVersionDiagnostic(database.TemplateVersionTerraformValue{ + ProvisionerdVersion: tc.version, + }) + if tc.warning { + require.Len(t, diags, 1, "expected warning") + } else { + require.Len(t, diags, 0, "expected no warning") + } + }) + } + +} From a0f4d5804e3f119418af38b36d72b7310b717198 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 14 May 2025 09:53:40 -0500 Subject: [PATCH 5/8] make the warning an error --- coderd/parameters.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 3019322dc4ddf..2e67f38e3e0e2 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -282,7 +282,7 @@ func (api *API) getWorkspaceOwnerData( // required. func parameterProvisionerVersionDiagnostic(tf database.TemplateVersionTerraformValue) hcl.Diagnostics { missingMetaData := hcl.Diagnostic{ - Severity: hcl.DiagWarning, + Severity: hcl.DiagError, Summary: "This template version is missing required metadata to support dynamic parameters. Go back to the classic creation flow.", Detail: "To restore full functionality, please re-import the terraform as a new template version.", } From eb656efb4f57fae2123e19dca3af4c228a036dd9 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 14 May 2025 09:57:15 -0500 Subject: [PATCH 6/8] fmy --- coderd/parameters_internal_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/coderd/parameters_internal_test.go b/coderd/parameters_internal_test.go index 59730c42879ea..a02baeae380b6 100644 --- a/coderd/parameters_internal_test.go +++ b/coderd/parameters_internal_test.go @@ -74,5 +74,4 @@ func Test_parameterProvisionerVersionDiagnostic(t *testing.T) { } }) } - } From 478280b6fe0c45ea4c0780a32fc7af5c1a4dd226 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 14 May 2025 11:41:55 -0500 Subject: [PATCH 7/8] Update coderd/parameters.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ケイラ --- coderd/parameters.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index 2e67f38e3e0e2..b03ea2576cc57 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -116,9 +116,8 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http return } - var staticDiagnostics hcl.Diagnostics // If the err is sql.ErrNoRows, an empty terraform values struct is correct. - staticDiagnostics = staticDiagnostics.Extend(parameterProvisionerVersionDiagnostic(tf)) + staticDiagnostics := parameterProvisionerVersionDiagnostic(tf) owner, err := api.getWorkspaceOwnerData(ctx, user, templateVersion.OrganizationID) if err != nil { From 155f2cffad8eb1f4b28a2e2658c44f7d71d4957e Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 14 May 2025 12:02:55 -0500 Subject: [PATCH 8/8] Pr suggestions --- coderd/parameters.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/coderd/parameters.go b/coderd/parameters.go index b03ea2576cc57..9d90bc5a0226f 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -280,24 +280,24 @@ func (api *API) getWorkspaceOwnerData( // returns a warning diagnostic. Only versions 1.5+ return the module & plan data // required. func parameterProvisionerVersionDiagnostic(tf database.TemplateVersionTerraformValue) hcl.Diagnostics { - missingMetaData := hcl.Diagnostic{ + missingMetadata := hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "This template version is missing required metadata to support dynamic parameters. Go back to the classic creation flow.", Detail: "To restore full functionality, please re-import the terraform as a new template version.", } if tf.ProvisionerdVersion == "" { - return hcl.Diagnostics{&missingMetaData} + return hcl.Diagnostics{&missingMetadata} } major, minor, err := apiversion.Parse(tf.ProvisionerdVersion) if err != nil || tf.ProvisionerdVersion == "" { - return hcl.Diagnostics{&missingMetaData} + return hcl.Diagnostics{&missingMetadata} } else if major < 1 || (major == 1 && minor < 5) { - missingMetaData.Detail = "This template version requires provisioner v1.5 or newer to support dynamic parameters. " + + missingMetadata.Detail = "This template version does not support dynamic parameters. " + "Some options may be missing or incorrect. " + "Please contact an administrator to update the provisioner and re-import the template version." - return hcl.Diagnostics{&missingMetaData} + return hcl.Diagnostics{&missingMetadata} } return nil