Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit946db5a

Browse files
authored
fix: coder_parameter: validation min and max are truly optional (#121)
1 parentdbc530b commit946db5a

File tree

3 files changed

+119
-32
lines changed

3 files changed

+119
-32
lines changed

‎provider/decode_test.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/coder/terraform-provider-coder/provider"
77
"github.com/mitchellh/mapstructure"
8+
"github.com/stretchr/testify/assert"
89
"github.com/stretchr/testify/require"
910
)
1011

@@ -18,15 +19,25 @@ func TestDecode(t *testing.T) {
1819

1920
aMap:=map[string]interface{}{
2021
"name":"Parameter Name",
22+
"type":"number",
2123
"display_name":displayName,
2224
"legacy_variable":legacyVariable,
2325
"legacy_variable_name":legacyVariableName,
26+
"min":nil,
27+
"validation": []map[string]interface{}{
28+
{
29+
"min":nil,
30+
"max":5,
31+
},
32+
},
2433
}
2534

2635
varparam provider.Parameter
2736
err:=mapstructure.Decode(aMap,&param)
2837
require.NoError(t,err)
29-
require.Equal(t,displayName,param.DisplayName)
30-
require.Equal(t,legacyVariable,param.LegacyVariable)
31-
require.Equal(t,legacyVariableName,param.LegacyVariableName)
38+
assert.Equal(t,displayName,param.DisplayName)
39+
assert.Equal(t,legacyVariable,param.LegacyVariable)
40+
assert.Equal(t,legacyVariableName,param.LegacyVariableName)
41+
assert.Equal(t, (*int)(nil),param.Validation[0].Min)
42+
assert.Equal(t,5,*param.Validation[0].Max)
3243
}

‎provider/parameter.go

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import (
1212
"strconv"
1313

1414
"github.com/google/uuid"
15+
"github.com/hashicorp/go-cty/cty"
1516
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1617
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
1718
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1819
"github.com/mitchellh/mapstructure"
20+
"golang.org/x/xerrors"
1921
)
2022

2123
typeOptionstruct {
@@ -26,8 +28,8 @@ type Option struct {
2628
}
2729

2830
typeValidationstruct {
29-
Minint
30-
Maxint
31+
Min*int
32+
Max*int
3133
Monotonicstring
3234

3335
Regexstring
@@ -62,8 +64,18 @@ func parameterDataSource() *schema.Resource {
6264
ReadContext:func(ctx context.Context,rd*schema.ResourceData,iinterface{}) diag.Diagnostics {
6365
rd.SetId(uuid.NewString())
6466

67+
fixedValidation,err:=fixValidationResourceData(rd.GetRawConfig(),rd.Get("validation"))
68+
iferr!=nil {
69+
returndiag.FromErr(err)
70+
}
71+
72+
err=rd.Set("validation",fixedValidation)
73+
iferr!=nil {
74+
returndiag.FromErr(err)
75+
}
76+
6577
varparameterParameter
66-
err:=mapstructure.Decode(struct {
78+
err=mapstructure.Decode(struct {
6779
Valueinterface{}
6880
Nameinterface{}
6981
DisplayNameinterface{}
@@ -98,7 +110,7 @@ func parameterDataSource() *schema.Resource {
98110
}(),
99111
Icon:rd.Get("icon"),
100112
Option:rd.Get("option"),
101-
Validation:rd.Get("validation"),
113+
Validation:fixedValidation,
102114
Optional:func()bool {
103115
// This hack allows for checking if the "default" field is present in the .tf file.
104116
// If "default" is missing or is "null", then it means that this field is required,
@@ -272,17 +284,14 @@ func parameterDataSource() *schema.Resource {
272284
Elem:&schema.Resource{
273285
Schema:map[string]*schema.Schema{
274286
"min": {
275-
Type:schema.TypeInt,
276-
Optional:true,
277-
Default:0,
278-
Description:"The minimum of a number parameter.",
279-
RequiredWith: []string{"validation.0.max"},
287+
Type:schema.TypeInt,
288+
Optional:true,
289+
Description:"The minimum of a number parameter.",
280290
},
281291
"max": {
282-
Type:schema.TypeInt,
283-
Optional:true,
284-
Description:"The maximum of a number parameter.",
285-
RequiredWith: []string{"validation.0.min"},
292+
Type:schema.TypeInt,
293+
Optional:true,
294+
Description:"The maximum of a number parameter.",
286295
},
287296
"monotonic": {
288297
Type:schema.TypeString,
@@ -325,6 +334,45 @@ func parameterDataSource() *schema.Resource {
325334
}
326335
}
327336

337+
funcfixValidationResourceData(rawConfig cty.Value,validationinterface{}) (interface{},error) {
338+
// Read validation from raw config
339+
rawValidation,ok:=rawConfig.AsValueMap()["validation"]
340+
if!ok {
341+
returnvalidation,nil// no validation rules, nothing to fix
342+
}
343+
344+
rawValidationArr:=rawValidation.AsValueSlice()
345+
iflen(rawValidationArr)==0 {
346+
returnvalidation,nil// no validation rules, nothing to fix
347+
}
348+
349+
rawValidationRule:=rawValidationArr[0].AsValueMap()
350+
351+
// Load validation from resource data
352+
vArr,ok:=validation.([]interface{})
353+
if!ok {
354+
returnnil,xerrors.New("validation should be an array")
355+
}
356+
357+
iflen(vArr)==0 {
358+
returnvalidation,nil// no validation rules, nothing to fix
359+
}
360+
361+
validationRule,ok:=vArr[0].(map[string]interface{})
362+
if!ok {
363+
returnnil,xerrors.New("validation rule should be a map")
364+
}
365+
366+
// Fix the resource data
367+
ifrawValidationRule["min"].IsNull() {
368+
validationRule["min"]=nil
369+
}
370+
ifrawValidationRule["max"].IsNull() {
371+
validationRule["max"]=nil
372+
}
373+
returnvArr,nil
374+
}
375+
328376
funcvalueIsType(typ,valuestring) diag.Diagnostics {
329377
switchtyp {
330378
case"number":
@@ -353,10 +401,10 @@ func valueIsType(typ, value string) diag.Diagnostics {
353401

354402
func (v*Validation)Valid(typ,valuestring)error {
355403
iftyp!="number" {
356-
ifv.Min!=0 {
404+
ifv.Min!=nil {
357405
returnfmt.Errorf("a min cannot be specified for a %s type",typ)
358406
}
359-
ifv.Max!=0 {
407+
ifv.Max!=nil {
360408
returnfmt.Errorf("a max cannot be specified for a %s type",typ)
361409
}
362410
}
@@ -389,10 +437,10 @@ func (v *Validation) Valid(typ, value string) error {
389437
iferr!=nil {
390438
returnfmt.Errorf("value %q is not a number",value)
391439
}
392-
ifnum<v.Min {
440+
ifv.Min!=nil&&num<*v.Min {
393441
returnfmt.Errorf("value %d is less than the minimum %d",num,v.Min)
394442
}
395-
ifnum>v.Max {
443+
ifv.Max!=nil&&num>*v.Max {
396444
returnfmt.Errorf("value %d is more than the maximum %d",num,v.Max)
397445
}
398446
ifv.Monotonic!=""&&v.Monotonic!=ValidationMonotonicIncreasing&&v.Monotonic!=ValidationMonotonicDecreasing {

‎provider/parameter_test.go

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,30 @@ func TestParameter(t *testing.T) {
109109
}
110110
}
111111
`,
112+
}, {
113+
Name:"NumberValidation_Min",
114+
Config:`
115+
data "coder_parameter" "region" {
116+
name = "Region"
117+
type = "number"
118+
default = 2
119+
validation {
120+
min = 1
121+
}
122+
}
123+
`,
124+
}, {
125+
Name:"NumberValidation_Max",
126+
Config:`
127+
data "coder_parameter" "region" {
128+
name = "Region"
129+
type = "number"
130+
default = 2
131+
validation {
132+
max = 9
133+
}
134+
}
135+
`,
112136
}, {
113137
Name:"DefaultNotNumber",
114138
Config:`
@@ -443,18 +467,18 @@ func TestValueValidatesType(t *testing.T) {
443467
Regex,
444468
RegexErrorstring
445469
Min,
446-
Maxint
470+
Max*int
447471
Monotonicstring
448472
Error*regexp.Regexp
449473
}{{
450474
Name:"StringWithMin",
451475
Type:"string",
452-
Min:1,
476+
Min:ptrNumber(1),
453477
Error:regexp.MustCompile("cannot be specified"),
454478
}, {
455479
Name:"StringWithMax",
456480
Type:"string",
457-
Max:1,
481+
Max:ptrNumber(1),
458482
Error:regexp.MustCompile("cannot be specified"),
459483
}, {
460484
Name:"NonStringWithRegex",
@@ -474,13 +498,13 @@ func TestValueValidatesType(t *testing.T) {
474498
Name:"NumberBelowMin",
475499
Type:"number",
476500
Value:"0",
477-
Min:1,
501+
Min:ptrNumber(1),
478502
Error:regexp.MustCompile("is less than the minimum"),
479503
}, {
480504
Name:"NumberAboveMax",
481505
Type:"number",
482-
Value:"1",
483-
Max:0,
506+
Value:"2",
507+
Max:ptrNumber(1),
484508
Error:regexp.MustCompile("is more than the maximum"),
485509
}, {
486510
Name:"InvalidBool",
@@ -498,23 +522,23 @@ func TestValueValidatesType(t *testing.T) {
498522
Name:"InvalidMonotonicity",
499523
Type:"number",
500524
Value:"1",
501-
Min:0,
502-
Max:2,
525+
Min:ptrNumber(0),
526+
Max:ptrNumber(2),
503527
Monotonic:"foobar",
504528
Error:regexp.MustCompile(`number monotonicity can be either "increasing" or "decreasing"`),
505529
}, {
506530
Name:"IncreasingMonotonicity",
507531
Type:"number",
508532
Value:"1",
509-
Min:0,
510-
Max:2,
533+
Min:ptrNumber(0),
534+
Max:ptrNumber(2),
511535
Monotonic:"increasing",
512536
}, {
513537
Name:"DecreasingMonotonicity",
514538
Type:"number",
515539
Value:"1",
516-
Min:0,
517-
Max:2,
540+
Min:ptrNumber(0),
541+
Max:ptrNumber(2),
518542
Monotonic:"decreasing",
519543
}, {
520544
Name:"ValidListOfStrings",
@@ -550,3 +574,7 @@ func TestValueValidatesType(t *testing.T) {
550574
})
551575
}
552576
}
577+
578+
funcptrNumber(iint)*int {
579+
return&i
580+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp