Skip to content

Commit c1097ee

Browse files
committed
Validation in coderd
1 parent 6715d27 commit c1097ee

File tree

7 files changed

+77
-17
lines changed

7 files changed

+77
-17
lines changed

cli/cliui/parameter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,5 +114,5 @@ func validateRichPrompt(value string, p codersdk.TemplateVersionParameter) error
114114
return codersdk.ValidateWorkspaceBuildParameter(p, codersdk.WorkspaceBuildParameter{
115115
Name: p.Name,
116116
Value: value,
117-
})
117+
}, nil)
118118
}

coderd/workspacebuilds.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -467,24 +467,24 @@ func (api *API) postWorkspaceBuilds(rw http.ResponseWriter, r *http.Request) {
467467
return
468468
}
469469

470-
err = codersdk.ValidateWorkspaceBuildParameters(templateVersionParameters, createBuild.RichParameterValues)
470+
lastBuildParameters, err := api.Database.GetWorkspaceBuildParameters(ctx, priorHistory.ID)
471471
if err != nil {
472-
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
473-
Message: "Error validating workspace build parameters.",
472+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
473+
Message: "Internal error fetching prior workspace build parameters.",
474474
Detail: err.Error(),
475475
})
476476
return
477477
}
478+
apiLastBuildParameters := convertWorkspaceBuildParameters(lastBuildParameters)
478479

479-
lastBuildParameters, err := api.Database.GetWorkspaceBuildParameters(ctx, priorHistory.ID)
480+
err = codersdk.ValidateWorkspaceBuildParameters(templateVersionParameters, createBuild.RichParameterValues, apiLastBuildParameters)
480481
if err != nil {
481-
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
482-
Message: "Internal error fetching prior workspace build parameters.",
482+
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
483+
Message: "Error validating workspace build parameters.",
483484
Detail: err.Error(),
484485
})
485486
return
486487
}
487-
apiLastBuildParameters := convertWorkspaceBuildParameters(lastBuildParameters)
488488

489489
var parameters []codersdk.WorkspaceBuildParameter
490490
for _, templateVersionParameter := range templateVersionParameters {

coderd/workspacebuilds_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,18 @@ func TestWorkspaceBuildValidateRichParameters(t *testing.T) {
871871
{Name: boolParameterName, Type: "bool", Mutable: true},
872872
}
873873

874+
monotonicIncreasingNumberRichParameters := []*proto.RichParameter{
875+
{Name: stringParameterName, Type: "string", Mutable: true},
876+
{Name: numberParameterName, Type: "number", Mutable: true, ValidationMin: 3, ValidationMax: 10, ValidationMonotonic: "increasing"},
877+
{Name: boolParameterName, Type: "bool", Mutable: true},
878+
}
879+
880+
monotonicDecreasingNumberRichParameters := []*proto.RichParameter{
881+
{Name: stringParameterName, Type: "string", Mutable: true},
882+
{Name: numberParameterName, Type: "number", Mutable: true, ValidationMin: 3, ValidationMax: 10, ValidationMonotonic: "decreasing"},
883+
{Name: boolParameterName, Type: "bool", Mutable: true},
884+
}
885+
874886
stringRichParameters := []*proto.RichParameter{
875887
{Name: stringParameterName, Type: "string", Mutable: true},
876888
{Name: numberParameterName, Type: "number", Mutable: true},
@@ -900,6 +912,14 @@ func TestWorkspaceBuildValidateRichParameters(t *testing.T) {
900912
{numberParameterName, "10", true, numberRichParameters},
901913
{numberParameterName, "11", false, numberRichParameters},
902914

915+
{numberParameterName, "6", false, monotonicIncreasingNumberRichParameters},
916+
{numberParameterName, "7", true, monotonicIncreasingNumberRichParameters},
917+
{numberParameterName, "8", true, monotonicIncreasingNumberRichParameters},
918+
919+
{numberParameterName, "6", true, monotonicDecreasingNumberRichParameters},
920+
{numberParameterName, "7", true, monotonicDecreasingNumberRichParameters},
921+
{numberParameterName, "8", false, monotonicDecreasingNumberRichParameters},
922+
903923
{stringParameterName, "", true, stringRichParameters},
904924
{stringParameterName, "foobar", true, stringRichParameters},
905925

coderd/workspaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ func (api *API) postWorkspacesByOrganization(rw http.ResponseWriter, r *http.Req
419419
return
420420
}
421421

422-
err = codersdk.ValidateWorkspaceBuildParameters(templateVersionParameters, createWorkspace.RichParameterValues)
422+
err = codersdk.ValidateNewWorkspaceParameters(templateVersionParameters, createWorkspace.RichParameterValues)
423423
if err != nil {
424424
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
425425
Message: "Error validating workspace build parameters.",

codersdk/richparameters.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ import (
66
"github.com/coder/terraform-provider-coder/provider"
77
)
88

9-
func ValidateWorkspaceBuildParameters(richParameters []TemplateVersionParameter, buildParameters []WorkspaceBuildParameter) error {
9+
func ValidateNewWorkspaceParameters(richParameters []TemplateVersionParameter, buildParameters []WorkspaceBuildParameter) error {
10+
return ValidateWorkspaceBuildParameters(richParameters, buildParameters, nil)
11+
}
12+
13+
func ValidateWorkspaceBuildParameters(richParameters []TemplateVersionParameter, buildParameters, lastBuildParameters []WorkspaceBuildParameter) error {
1014
for _, buildParameter := range buildParameters {
1115
if buildParameter.Name == "" {
1216
return xerrors.Errorf(`workspace build parameter name is missing`)
@@ -16,20 +20,33 @@ func ValidateWorkspaceBuildParameters(richParameters []TemplateVersionParameter,
1620
return xerrors.Errorf(`workspace build parameter is not defined in the template ("coder_parameter"): %s`, buildParameter.Name)
1721
}
1822

19-
err := ValidateWorkspaceBuildParameter(*richParameter, buildParameter)
23+
err := ValidateWorkspaceBuildParameter(*richParameter, buildParameter, findLastBuildParameter(lastBuildParameters, buildParameter.Name))
2024
if err != nil {
2125
return xerrors.Errorf("can't validate build parameter %q: %w", buildParameter.Name, err)
2226
}
2327
}
2428
return nil
2529
}
2630

27-
func ValidateWorkspaceBuildParameter(richParameter TemplateVersionParameter, buildParameter WorkspaceBuildParameter) error {
31+
func ValidateWorkspaceBuildParameter(richParameter TemplateVersionParameter, buildParameter WorkspaceBuildParameter, lastBuildParameter *WorkspaceBuildParameter) error {
2832
value := buildParameter.Value
2933
if value == "" {
3034
value = richParameter.DefaultValue
3135
}
3236

37+
if lastBuildParameter != nil && richParameter.Type == "number" && len(richParameter.ValidationMonotonic) > 0 {
38+
switch richParameter.ValidationMonotonic {
39+
case MonotonicOrderIncreasing:
40+
if lastBuildParameter.Value > buildParameter.Value {
41+
return xerrors.Errorf("parameter value must be equal or lower than previous value: %s", lastBuildParameter.Value)
42+
}
43+
case MonotonicOrderDecreasing:
44+
if lastBuildParameter.Value < buildParameter.Value {
45+
return xerrors.Errorf("parameter value must be equal or greater than previous value: %s", lastBuildParameter.Value)
46+
}
47+
}
48+
}
49+
3350
if len(richParameter.Options) > 0 {
3451
var matched bool
3552
for _, opt := range richParameter.Options {
@@ -50,10 +67,11 @@ func ValidateWorkspaceBuildParameter(richParameter TemplateVersionParameter, bui
5067
}
5168

5269
validation := &provider.Validation{
53-
Min: int(richParameter.ValidationMin),
54-
Max: int(richParameter.ValidationMax),
55-
Regex: richParameter.ValidationRegex,
56-
Error: richParameter.ValidationError,
70+
Min: int(richParameter.ValidationMin),
71+
Max: int(richParameter.ValidationMax),
72+
Regex: richParameter.ValidationRegex,
73+
Error: richParameter.ValidationError,
74+
Monotonic: string(richParameter.ValidationMonotonic),
5775
}
5876
return validation.Valid(richParameter.Type, value)
5977
}
@@ -67,6 +85,15 @@ func findTemplateVersionParameter(params []TemplateVersionParameter, parameterNa
6785
return nil, false
6886
}
6987

88+
func findLastBuildParameter(params []WorkspaceBuildParameter, parameterName string) *WorkspaceBuildParameter {
89+
for _, p := range params {
90+
if p.Name == parameterName {
91+
return &p
92+
}
93+
}
94+
return nil
95+
}
96+
7097
func parameterValuesAsArray(options []TemplateVersionParameterOption) []string {
7198
var arr []string
7299
for _, opt := range options {
@@ -78,5 +105,6 @@ func parameterValuesAsArray(options []TemplateVersionParameterOption) []string {
78105
func validationEnabled(param TemplateVersionParameter) bool {
79106
return len(param.ValidationRegex) > 0 ||
80107
(param.ValidationMin != 0 && param.ValidationMax != 0) ||
108+
len(param.ValidationMonotonic) > 0 ||
81109
param.Type == "bool" // boolean type doesn't have any custom validation rules, but the value must be checked (true/false).
82110
}

go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ require (
6767
github.com/charmbracelet/lipgloss v0.6.0
6868
github.com/cli/safeexec v1.0.0
6969
github.com/coder/retry v1.3.0
70-
github.com/coder/terraform-provider-coder v0.6.9
70+
github.com/coder/terraform-provider-coder v0.6.11
7171
github.com/coreos/go-oidc/v3 v3.4.0
7272
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
7373
github.com/creack/pty v1.1.18
@@ -174,14 +174,18 @@ require (
174174
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
175175
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 // indirect
176176
github.com/hashicorp/go-hclog v1.2.1 // indirect
177+
github.com/hashicorp/go-plugin v1.4.4 // indirect
177178
github.com/hashicorp/go-uuid v1.0.3 // indirect
178179
github.com/hashicorp/logutils v1.0.0 // indirect
179180
github.com/hashicorp/terraform-plugin-go v0.12.0 // indirect
180181
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
181182
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 // indirect
183+
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect
184+
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
182185
github.com/mitchellh/copystructure v1.2.0 // indirect
183186
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
184187
github.com/mitchellh/reflectwalk v1.0.2 // indirect
188+
github.com/oklog/run v1.0.0 // indirect
185189
github.com/russross/blackfriday/v2 v2.1.0 // indirect
186190
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
187191
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3 h1:lq8GmpE5bn8A3
365365
github.com/coder/tailscale v1.1.1-0.20221117204504-2d6503f027c3/go.mod h1:lkCb74eSJwxeNq8YwyILoHD5vtHktiZnTOxBxo3tbNc=
366366
github.com/coder/terraform-provider-coder v0.6.9 h1:8WKYCwc3kq6Be/cjzrCKydbGB464xfGpnHHCzJULVA0=
367367
github.com/coder/terraform-provider-coder v0.6.9/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
368+
github.com/coder/terraform-provider-coder v0.6.11 h1:xdzopnSgy6bMBQlIkAgyyF0m6C3HzEQiF9DnHYpbIFU=
369+
github.com/coder/terraform-provider-coder v0.6.11/go.mod h1:UIfU3bYNeSzJJvHyJ30tEKjD6Z9utloI+HUM/7n94CY=
368370
github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE=
369371
github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU=
370372
github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU=
@@ -1003,6 +1005,7 @@ github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+
10031005
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
10041006
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
10051007
github.com/hashicorp/go-plugin v1.4.4 h1:NVdrSdFRt3SkZtNckJ6tog7gbpRrcbOjQi/rgF7JYWQ=
1008+
github.com/hashicorp/go-plugin v1.4.4/go.mod h1:viDMjcLJuDui6pXb8U4HVfb8AamCWhHGUjr2IrTF67s=
10061009
github.com/hashicorp/go-reap v0.0.0-20170704170343-bf58d8a43e7b h1:3GrpnZQBxcMj1gCXQLelfjCT1D5MPGTuGMKHVzSIH6A=
10071010
github.com/hashicorp/go-reap v0.0.0-20170704170343-bf58d8a43e7b/go.mod h1:qIFzeFcJU3OIFk/7JreWXcUjFmcCaeHTH9KoNyHYVCs=
10081011
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
@@ -1013,6 +1016,7 @@ github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
10131016
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
10141017
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
10151018
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
1019+
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
10161020
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
10171021
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
10181022
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
@@ -1049,7 +1053,9 @@ github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfD
10491053
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0 h1:+KxZULPsbjpAVoP0WNj/8aVW6EqpcX5JcUcQ5wl7Da4=
10501054
github.com/hashicorp/terraform-plugin-sdk/v2 v2.20.0/go.mod h1:DwGJG3KNxIPluVk6hexvDfYR/MS/eKGpiztJoT3Bbbw=
10511055
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg=
1056+
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI=
10521057
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0=
1058+
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734/go.mod h1:kNDNcF7sN4DocDLBkQYz73HGKwN1ANB1blq4lIYLYvg=
10531059
github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce h1:7FO+LmZwiG/eDsBWo50ZeqV5PoH0gwiM1mxFajXAkas=
10541060
github.com/hashicorp/yamux v0.0.0-20220718163420-dd80a7ee44ce/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
10551061
github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU=
@@ -1458,6 +1464,7 @@ github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH
14581464
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
14591465
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
14601466
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
1467+
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
14611468
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
14621469
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
14631470
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
@@ -2123,6 +2130,7 @@ golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLL
21232130
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
21242131
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
21252132
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
2133+
golang.org/x/net v0.0.0-20191009170851-d66e71096ffb/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
21262134
golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
21272135
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
21282136
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=

0 commit comments

Comments
 (0)