@@ -13,7 +13,9 @@ import (
13
13
"github.com/hashicorp/hcl/v2"
14
14
"github.com/hashicorp/hcl/v2/hclsyntax"
15
15
16
+ "github.com/coder/coder/v2/apiversion"
16
17
"github.com/coder/coder/v2/coderd/rbac/policy"
18
+ "github.com/coder/coder/v2/coderd/util/ptr"
17
19
"github.com/coder/coder/v2/provisioner/terraform/tfparse"
18
20
"github.com/coder/coder/v2/provisionersdk"
19
21
sdkproto"github.com/coder/coder/v2/provisionersdk/proto"
@@ -51,9 +53,11 @@ type Builder struct {
51
53
state stateTarget
52
54
logLevel string
53
55
deploymentValues * codersdk.DeploymentValues
56
+ experiments codersdk.Experiments
54
57
55
- richParameterValues []codersdk.WorkspaceBuildParameter
56
- dynamicParametersEnabled bool
58
+ richParameterValues []codersdk.WorkspaceBuildParameter
59
+ // dynamicParametersEnabled is non-nil if set externally
60
+ dynamicParametersEnabled * bool
57
61
initiator uuid.UUID
58
62
reason database.BuildReason
59
63
templateVersionPresetID uuid.UUID
@@ -66,6 +70,7 @@ type Builder struct {
66
70
template * database.Template
67
71
templateVersion * database.TemplateVersion
68
72
templateVersionJob * database.ProvisionerJob
73
+ terraformValues * database.TemplateVersionTerraformValue
69
74
templateVersionParameters * []database.TemplateVersionParameter
70
75
templateVersionVariables * []database.TemplateVersionVariable
71
76
templateVersionWorkspaceTags * []database.TemplateVersionWorkspaceTag
@@ -155,6 +160,14 @@ func (b Builder) DeploymentValues(dv *codersdk.DeploymentValues) Builder {
155
160
return b
156
161
}
157
162
163
+ func (b Builder )Experiments (exp codersdk.Experiments )Builder {
164
+ // nolint: revive
165
+ cpy := make (codersdk.Experiments ,len (exp ))
166
+ copy (cpy ,exp )
167
+ b .experiments = cpy
168
+ return b
169
+ }
170
+
158
171
func (b Builder )Initiator (u uuid.UUID )Builder {
159
172
// nolint: revive
160
173
b .initiator = u
@@ -187,8 +200,9 @@ func (b Builder) MarkPrebuiltWorkspaceClaim() Builder {
187
200
return b
188
201
}
189
202
190
- func (b Builder )UsingDynamicParameters ()Builder {
191
- b .dynamicParametersEnabled = true
203
+ func (b Builder )DynamicParameters (using bool )Builder {
204
+ // nolint: revive
205
+ b .dynamicParametersEnabled = ptr .Ref (using )
192
206
return b
193
207
}
194
208
@@ -516,6 +530,22 @@ func (b *Builder) getTemplateVersionID() (uuid.UUID, error) {
516
530
return bld .TemplateVersionID ,nil
517
531
}
518
532
533
+ func (b * Builder )getTemplateTerraformValues () (* database.TemplateVersionTerraformValue ,error ) {
534
+ if b .terraformValues != nil {
535
+ return b .terraformValues ,nil
536
+ }
537
+ v ,err := b .getTemplateVersion ()
538
+ if err != nil {
539
+ return nil ,xerrors .Errorf ("get template version so we can get terraform values: %w" ,err )
540
+ }
541
+ vals ,err := b .store .GetTemplateVersionTerraformValues (b .ctx ,v .ID )
542
+ if err != nil {
543
+ return nil ,xerrors .Errorf ("get template version terraform values %s: %w" ,v .JobID ,err )
544
+ }
545
+ b .terraformValues = & vals
546
+ return b .terraformValues ,err
547
+ }
548
+
519
549
func (b * Builder )getLastBuild () (* database.WorkspaceBuild ,error ) {
520
550
if b .lastBuild != nil {
521
551
return b .lastBuild ,nil
@@ -593,9 +623,10 @@ func (b *Builder) getParameters() (names, values []string, err error) {
593
623
return nil ,nil ,BuildError {http .StatusBadRequest ,"Unable to build workspace with unsupported parameters" ,err }
594
624
}
595
625
596
- if b .dynamicParametersEnabled {
597
- // Dynamic parameters skip all parameter validation.
598
- // Pass the user's input as is.
626
+ // Dynamic parameters skip all parameter validation.
627
+ // Deleting a workspace also should skip parameter validation.
628
+ // Pass the user's input as is.
629
+ if b .usingDynamicParameters () {
599
630
// TODO: The previous behavior was only to pass param values
600
631
// for parameters that exist. Since dynamic params can have
601
632
// conditional parameter existence, the static frame of reference
@@ -989,3 +1020,36 @@ func (b *Builder) checkRunningBuild() error {
989
1020
}
990
1021
return nil
991
1022
}
1023
+
1024
+ func (b * Builder )usingDynamicParameters ()bool {
1025
+ if ! b .experiments .Enabled (codersdk .ExperimentDynamicParameters ) {
1026
+ // Experiment required
1027
+ return false
1028
+ }
1029
+
1030
+ vals ,err := b .getTemplateTerraformValues ()
1031
+ if err != nil {
1032
+ return false
1033
+ }
1034
+
1035
+ if ! ProvisionerVersionSupportsDynamicParameters (vals .ProvisionerdVersion ) {
1036
+ return false
1037
+ }
1038
+
1039
+ if b .dynamicParametersEnabled != nil {
1040
+ return * b .dynamicParametersEnabled
1041
+ }
1042
+
1043
+ tpl ,err := b .getTemplate ()
1044
+ if err != nil {
1045
+ return false // Let another part of the code get this error
1046
+ }
1047
+ return ! tpl .UseClassicParameterFlow
1048
+ }
1049
+
1050
+ func ProvisionerVersionSupportsDynamicParameters (version string )bool {
1051
+ major ,minor ,err := apiversion .Parse (version )
1052
+ // If the api version is not valid or less than 1.6, we need to use the static parameters
1053
+ useStaticParams := err != nil || major < 1 || (major == 1 && minor < 6 )
1054
+ return ! useStaticParams
1055
+ }