diff --git a/coderd/coderd.go b/coderd/coderd.go index 98ae7a8ede413..a12a5624b931c 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -1774,6 +1774,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 fa1f297b908ba..8a345fa0fd6e7 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/dbmem/dbmem.go b/coderd/database/dbmem/dbmem.go index dfa28097ab60c..63693604ae262 100644 --- a/coderd/database/dbmem/dbmem.go +++ b/coderd/database/dbmem/dbmem.go @@ -9343,10 +9343,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 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/000325_dynamic_parameters_metadata.down.sql b/coderd/database/migrations/000325_dynamic_parameters_metadata.down.sql new file mode 100644 index 0000000000000..991871b5700ab --- /dev/null +++ b/coderd/database/migrations/000325_dynamic_parameters_metadata.down.sql @@ -0,0 +1 @@ +ALTER TABLE template_version_terraform_values DROP COLUMN provisionerd_version; diff --git a/coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql b/coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql new file mode 100644 index 0000000000000..211693b7f3e79 --- /dev/null +++ b/coderd/database/migrations/000325_dynamic_parameters_metadata.up.sql @@ -0,0 +1,4 @@ +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/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 bd1d5cddd43ed..0fd886cf39f2b 100644 --- a/coderd/database/queries.sql.go +++ b/coderd/database/queries.sql.go @@ -11702,7 +11702,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 @@ -11717,6 +11717,7 @@ func (q *sqlQuerier) GetTemplateVersionTerraformValues(ctx context.Context, temp &i.UpdatedAt, &i.CachedPlan, &i.CachedModuleFiles, + &i.ProvisionerdVersion, ) return i, err } @@ -11727,22 +11728,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 { @@ -11751,6 +11755,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 6b6f4db531533..9d90bc5a0226f 100644 --- a/coderd/parameters.go +++ b/coderd/parameters.go @@ -8,9 +8,11 @@ import ( "time" "github.com/google/uuid" + "github.com/hashicorp/hcl/v2" "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" @@ -114,6 +116,9 @@ func (api *API) templateVersionDynamicParameters(rw http.ResponseWriter, r *http return } + // If the err is sql.ErrNoRows, an empty terraform values struct is correct. + staticDiagnostics := parameterProvisionerVersionDiagnostic(tf) + owner, err := api.getWorkspaceOwnerData(ctx, user, templateVersion.OrganizationID) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ @@ -148,7 +153,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 +181,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 @@ -269,3 +274,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.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} + } + + 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 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 nil +} diff --git a/coderd/parameters_internal_test.go b/coderd/parameters_internal_test.go new file mode 100644 index 0000000000000..a02baeae380b6 --- /dev/null +++ b/coderd/parameters_internal_test.go @@ -0,0 +1,77 @@ +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") + } + }) + } +} diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 075f927650284..cb7aefb717ab0 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -95,6 +95,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. @@ -153,7 +154,9 @@ func (t Tags) Valid() error { return nil } -func NewServer(lifecycleCtx context.Context, +func NewServer( + lifecycleCtx context.Context, + apiVersion string, accessURL *url.URL, id uuid.UUID, organizationID uuid.UUID, @@ -214,6 +217,7 @@ func NewServer(lifecycleCtx context.Context, s := &server{ lifecycleCtx: lifecycleCtx, + apiVersion: apiVersion, AccessURL: accessURL, ID: id, OrganizationID: organizationID, @@ -1536,10 +1540,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 b6c60781dac35..e125db348e701 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -2993,6 +2993,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 0315209e29543..9039d2e97dbc5 100644 --- a/enterprise/coderd/provisionerdaemons.go +++ b/enterprise/coderd/provisionerdaemons.go @@ -336,6 +336,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, 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