Skip to content

Commit 10036ab

Browse files
authored
fix: use minDisabled, maxDisabled for parameter validation (#7755)
1 parent a7366a8 commit 10036ab

16 files changed

+1595
-62
lines changed

codersdk/richparameters.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -78,22 +78,24 @@ func ValidateWorkspaceBuildParameter(richParameter TemplateVersionParameter, bui
7878
return nil
7979
}
8080

81-
validation := &provider.Validation{
82-
Min: ptrInt(richParameter.ValidationMin),
83-
Max: ptrInt(richParameter.ValidationMax),
84-
Regex: richParameter.ValidationRegex,
85-
Error: richParameter.ValidationError,
86-
Monotonic: string(richParameter.ValidationMonotonic),
81+
var min, max int
82+
if richParameter.ValidationMin != nil {
83+
min = int(*richParameter.ValidationMin)
84+
}
85+
if richParameter.ValidationMax != nil {
86+
max = int(*richParameter.ValidationMax)
8787
}
88-
return validation.Valid(richParameter.Type, value)
89-
}
9088

91-
func ptrInt(number *int32) *int {
92-
if number == nil {
93-
return nil
89+
validation := &provider.Validation{
90+
Min: min,
91+
Max: max,
92+
MinDisabled: richParameter.ValidationMin == nil,
93+
MaxDisabled: richParameter.ValidationMax == nil,
94+
Regex: richParameter.ValidationRegex,
95+
Error: richParameter.ValidationError,
96+
Monotonic: string(richParameter.ValidationMonotonic),
9497
}
95-
n := int(*number)
96-
return &n
98+
return validation.Valid(richParameter.Type, value)
9799
}
98100

99101
func findBuildParameter(params []WorkspaceBuildParameter, parameterName string) (*WorkspaceBuildParameter, bool) {

codersdk/richparameters_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,18 @@ func TestRichParameterValidation(t *testing.T) {
187187
{Name: boolParameterName, Type: "bool", Mutable: true},
188188
}
189189

190+
numberRichParametersMinOnly := []codersdk.TemplateVersionParameter{
191+
{Name: stringParameterName, Type: "string", Mutable: true},
192+
{Name: numberParameterName, Type: "number", Mutable: true, ValidationMin: ptr.Ref(int32(5))},
193+
{Name: boolParameterName, Type: "bool", Mutable: true},
194+
}
195+
196+
numberRichParametersMaxOnly := []codersdk.TemplateVersionParameter{
197+
{Name: stringParameterName, Type: "string", Mutable: true},
198+
{Name: numberParameterName, Type: "number", Mutable: true, ValidationMax: ptr.Ref(int32(5))},
199+
{Name: boolParameterName, Type: "bool", Mutable: true},
200+
}
201+
190202
monotonicIncreasingNumberRichParameters := []codersdk.TemplateVersionParameter{
191203
{Name: stringParameterName, Type: "string", Mutable: true},
192204
{Name: numberParameterName, Type: "number", Mutable: true, ValidationMin: ptr.Ref(int32(3)), ValidationMax: ptr.Ref(int32(10)), ValidationMonotonic: "increasing"},
@@ -232,6 +244,14 @@ func TestRichParameterValidation(t *testing.T) {
232244
{numberParameterName, "10", true, numberRichParameters},
233245
{numberParameterName, "11", false, numberRichParameters},
234246

247+
{numberParameterName, "4", false, numberRichParametersMinOnly},
248+
{numberParameterName, "5", true, numberRichParametersMinOnly},
249+
{numberParameterName, "6", true, numberRichParametersMinOnly},
250+
251+
{numberParameterName, "4", true, numberRichParametersMaxOnly},
252+
{numberParameterName, "5", true, numberRichParametersMaxOnly},
253+
{numberParameterName, "6", false, numberRichParametersMaxOnly},
254+
235255
{numberParameterName, "6", false, monotonicIncreasingNumberRichParameters},
236256
{numberParameterName, "7", true, monotonicIncreasingNumberRichParameters},
237257
{numberParameterName, "8", true, monotonicIncreasingNumberRichParameters},

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ require (
7575
github.com/codeclysm/extract v2.2.0+incompatible
7676
github.com/coder/flog v1.1.0
7777
github.com/coder/retry v1.4.0
78-
github.com/coder/terraform-provider-coder v0.8.1
78+
github.com/coder/terraform-provider-coder v0.8.2
7979
github.com/coder/wgtunnel v0.1.5
8080
github.com/coreos/go-oidc/v3 v3.6.0
8181
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf

go.sum

+2-2
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,8 @@ github.com/coder/ssh v0.0.0-20230421140225-04bb837133e1 h1:LBw76rEDuhNJyohve11mb
336336
github.com/coder/ssh v0.0.0-20230421140225-04bb837133e1/go.mod h1:ZSS+CUoKHDrqVakTfTWUlKSr9MtMFkC4UvtQKD7O914=
337337
github.com/coder/tailscale v0.0.0-20230522123520-74712221d00f h1:F0Xr1d8h8dAHn7tab1HXuzYFkcjmCydnEfdMbkOhlVk=
338338
github.com/coder/tailscale v0.0.0-20230522123520-74712221d00f/go.mod h1:jpg+77g19FpXL43U1VoIqoSg1K/Vh5CVxycGldQ8KhA=
339-
github.com/coder/terraform-provider-coder v0.8.1 h1:i/LhvFi+Ei0gL+h4GItJfwtxjcITTlQhS+R8J+0vRo8=
340-
github.com/coder/terraform-provider-coder v0.8.1/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
339+
github.com/coder/terraform-provider-coder v0.8.2 h1:EPhkdpsNd8fcg6eqpAQr+W1eRrEAMtugoqujoTK4O6o=
340+
github.com/coder/terraform-provider-coder v0.8.2/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
341341
github.com/coder/wgtunnel v0.1.5 h1:WP3sCj/3iJ34eKvpMQEp1oJHvm24RYh0NHbj1kfUKfs=
342342
github.com/coder/wgtunnel v0.1.5/go.mod h1:bokoUrHnUFY4lu9KOeSYiIcHTI2MO1KwqumU4DPDyJI=
343343
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=

provisioner/terraform/resources.go

+31-8
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,35 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa
483483
if len(param.Validation) == 1 {
484484
protoParam.ValidationRegex = param.Validation[0].Regex
485485
protoParam.ValidationError = param.Validation[0].Error
486-
protoParam.ValidationMax = ptrInt32(param.Validation[0].Max)
487-
protoParam.ValidationMin = ptrInt32(param.Validation[0].Min)
486+
487+
validationAttributeValues, ok := resource.AttributeValues["validation"]
488+
if ok {
489+
validationAttributeValuesArr, ok := validationAttributeValues.([]interface{})
490+
if ok {
491+
validationAttributeValuesMapStr, ok := validationAttributeValuesArr[0].(map[string]interface{})
492+
if ok {
493+
// Backward compatibility with terraform-coder-plugin < v0.8.2:
494+
// * "min_disabled" and "max_disabled" are not available yet
495+
// * "min" and "max" are required to be specified together
496+
if _, ok = validationAttributeValuesMapStr["min_disabled"]; !ok {
497+
if param.Validation[0].Min != 0 || param.Validation[0].Max != 0 {
498+
param.Validation[0].MinDisabled = false
499+
param.Validation[0].MaxDisabled = false
500+
} else {
501+
param.Validation[0].MinDisabled = true
502+
param.Validation[0].MaxDisabled = true
503+
}
504+
}
505+
}
506+
}
507+
}
508+
509+
if !param.Validation[0].MaxDisabled {
510+
protoParam.ValidationMax = PtrInt32(param.Validation[0].Max)
511+
}
512+
if !param.Validation[0].MinDisabled {
513+
protoParam.ValidationMin = PtrInt32(param.Validation[0].Min)
514+
}
488515
protoParam.ValidationMonotonic = param.Validation[0].Monotonic
489516
}
490517
if len(param.Option) > 0 {
@@ -527,12 +554,8 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string, rawParameterNa
527554
}, nil
528555
}
529556

530-
func ptrInt32(number *int) *int32 {
531-
var n int32
532-
if number == nil {
533-
return &n
534-
}
535-
n = int32(*number)
557+
func PtrInt32(number int) *int32 {
558+
n := int32(number)
536559
return &n
537560
}
538561

provisioner/terraform/resources_test.go

+77
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,83 @@ func TestConvertResources(t *testing.T) {
323323
Type: "string",
324324
Description: "blah blah",
325325
DefaultValue: "ok",
326+
}, {
327+
Name: "number_example_min_max",
328+
Type: "number",
329+
DefaultValue: "4",
330+
ValidationMin: terraform.PtrInt32(3),
331+
ValidationMax: terraform.PtrInt32(6),
332+
}, {
333+
Name: "number_example_min_zero",
334+
Type: "number",
335+
DefaultValue: "4",
336+
ValidationMin: terraform.PtrInt32(0),
337+
ValidationMax: terraform.PtrInt32(6),
338+
}, {
339+
Name: "number_example_max_zero",
340+
Type: "number",
341+
DefaultValue: "-2",
342+
ValidationMin: terraform.PtrInt32(-3),
343+
ValidationMax: terraform.PtrInt32(0),
344+
}, {
345+
Name: "number_example",
346+
Type: "number",
347+
DefaultValue: "4",
348+
ValidationMin: nil,
349+
ValidationMax: nil,
350+
}},
351+
},
352+
"rich-parameters-validation": {
353+
resources: []*proto.Resource{{
354+
Name: "dev",
355+
Type: "null_resource",
356+
Agents: []*proto.Agent{{
357+
Name: "dev",
358+
OperatingSystem: "windows",
359+
ShutdownScriptTimeoutSeconds: 300,
360+
StartupScriptTimeoutSeconds: 300,
361+
Architecture: "arm64",
362+
Auth: &proto.Agent_Token{},
363+
LoginBeforeReady: true,
364+
ConnectionTimeoutSeconds: 120,
365+
}},
366+
}},
367+
parameters: []*proto.RichParameter{{
368+
Name: "number_example_min_max",
369+
Type: "number",
370+
DefaultValue: "4",
371+
ValidationMin: terraform.PtrInt32(3),
372+
ValidationMax: terraform.PtrInt32(6),
373+
}, {
374+
Name: "number_example_min",
375+
Type: "number",
376+
DefaultValue: "4",
377+
ValidationMin: terraform.PtrInt32(3),
378+
ValidationMax: nil,
379+
}, {
380+
Name: "number_example_min_zero",
381+
Type: "number",
382+
DefaultValue: "4",
383+
ValidationMin: terraform.PtrInt32(0),
384+
ValidationMax: nil,
385+
}, {
386+
Name: "number_example_max",
387+
Type: "number",
388+
DefaultValue: "4",
389+
ValidationMin: nil,
390+
ValidationMax: terraform.PtrInt32(6),
391+
}, {
392+
Name: "number_example_max_zero",
393+
Type: "number",
394+
DefaultValue: "-3",
395+
ValidationMin: nil,
396+
ValidationMax: terraform.PtrInt32(0),
397+
}, {
398+
Name: "number_example",
399+
Type: "number",
400+
DefaultValue: "4",
401+
ValidationMin: nil,
402+
ValidationMax: nil,
326403
}},
327404
},
328405
"git-auth-providers": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
version = "0.8.2"
6+
}
7+
}
8+
}
9+
10+
data "coder_parameter" "number_example_min_max" {
11+
name = "number_example_min_max"
12+
type = "number"
13+
default = 4
14+
validation {
15+
min = 3
16+
max = 6
17+
}
18+
}
19+
20+
data "coder_parameter" "number_example_min" {
21+
name = "number_example_min"
22+
type = "number"
23+
default = 4
24+
validation {
25+
min = 3
26+
}
27+
}
28+
29+
data "coder_parameter" "number_example_min_zero" {
30+
name = "number_example_min_zero"
31+
type = "number"
32+
default = 4
33+
validation {
34+
min = 0
35+
}
36+
}
37+
38+
data "coder_parameter" "number_example_max" {
39+
name = "number_example_max"
40+
type = "number"
41+
default = 4
42+
validation {
43+
max = 6
44+
}
45+
}
46+
47+
data "coder_parameter" "number_example_max_zero" {
48+
name = "number_example_max_zero"
49+
type = "number"
50+
default = -3
51+
validation {
52+
max = 0
53+
}
54+
}
55+
56+
data "coder_parameter" "number_example" {
57+
name = "number_example"
58+
type = "number"
59+
default = 4
60+
}
61+
62+
resource "coder_agent" "dev" {
63+
os = "windows"
64+
arch = "arm64"
65+
}
66+
67+
resource "null_resource" "dev" {
68+
depends_on = [coder_agent.dev]
69+
}

provisioner/terraform/testdata/rich-parameters-validation/rich-parameters-validation.tfplan.dot

+36
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)