Skip to content

Commit 5355be4

Browse files
authored
Merge pull request #131 from coder/coder/param_required
chore: add error diagnostic to missing required parameters
2 parents ac39143 + f5939eb commit 5355be4

File tree

6 files changed

+110
-2
lines changed

6 files changed

+110
-2
lines changed

parameter.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ func parameters(modules terraform.Modules) ([]types.Parameter, hcl.Diagnostics)
2525
}
2626

2727
if param != nil {
28+
if param.Required && param.Value.Value.IsNull() {
29+
param.Diagnostics = append(param.Diagnostics, types.DiagnosticCode(&hcl.Diagnostic{
30+
Severity: hcl.DiagError,
31+
Summary: "Required parameter not provided",
32+
Detail: "parameter value is null",
33+
}, types.DiagnosticCodeRequired))
34+
}
35+
2836
params = append(params, *param)
2937

3038
if _, ok := exists[param.Name]; !ok {

preview_test.go

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"path/filepath"
88
"regexp"
99
"slices"
10+
"strings"
1011
"testing"
1112

1213
"github.com/hashicorp/hcl/v2"
@@ -144,7 +145,8 @@ func Test_Extract(t *testing.T) {
144145
unknownTags: []string{},
145146
input: preview.Input{},
146147
params: map[string]assertParam{
147-
"os": ap().
148+
"os": apWithDiags().
149+
errorDiagnostics("unique").
148150
value("0000000000000000000000000000000000000000000000000000000000000000"),
149151
},
150152
},
@@ -222,7 +224,18 @@ func Test_Extract(t *testing.T) {
222224
input: preview.Input{},
223225
unknownTags: []string{},
224226
params: map[string]assertParam{
225-
"word": ap(),
227+
"word": apWithDiags().
228+
errorDiagnostics("Required"),
229+
},
230+
},
231+
{
232+
name: "required",
233+
dir: "required",
234+
expTags: map[string]string{},
235+
input: preview.Input{},
236+
unknownTags: []string{},
237+
params: map[string]assertParam{
238+
"region": apWithDiags().errorDiagnostics("Required"),
226239
},
227240
},
228241
{
@@ -487,9 +500,53 @@ func Test_Extract(t *testing.T) {
487500
type assertParam func(t *testing.T, parameter types.Parameter)
488501

489502
func ap() assertParam {
503+
return func(t *testing.T, parameter types.Parameter) {
504+
t.Helper()
505+
assert.Empty(t, parameter.Diagnostics, "parameter should have no diagnostics")
506+
}
507+
}
508+
509+
func apWithDiags() assertParam {
490510
return func(t *testing.T, parameter types.Parameter) {}
491511
}
492512

513+
func (a assertParam) errorDiagnostics(patterns ...string) assertParam {
514+
return a.diagnostics(hcl.DiagError, patterns...)
515+
}
516+
517+
func (a assertParam) warnDiagnostics(patterns ...string) assertParam {
518+
return a.diagnostics(hcl.DiagWarning, patterns...)
519+
}
520+
521+
func (a assertParam) diagnostics(sev hcl.DiagnosticSeverity, patterns ...string) assertParam {
522+
shadow := patterns
523+
return a.extend(func(t *testing.T, parameter types.Parameter) {
524+
checks := make([]string, len(shadow))
525+
copy(checks, shadow)
526+
527+
DiagLoop:
528+
for _, diag := range parameter.Diagnostics {
529+
if diag.Severity != sev {
530+
continue
531+
}
532+
for i, pat := range checks {
533+
if strings.Contains(diag.Summary, pat) || strings.Contains(diag.Detail, pat) {
534+
checks = append(checks[:i], checks[i+1:]...)
535+
break DiagLoop
536+
}
537+
}
538+
}
539+
540+
assert.Equal(t, []string{}, checks, "missing expected diagnostic errors")
541+
})
542+
}
543+
544+
func (a assertParam) noDiagnostics() assertParam {
545+
return a.extend(func(t *testing.T, parameter types.Parameter) {
546+
assert.Empty(t, parameter.Diagnostics, "parameter should have no diagnostics")
547+
})
548+
}
549+
493550
func (a assertParam) formType(exp provider.ParameterFormType) assertParam {
494551
return a.extend(func(t *testing.T, parameter types.Parameter) {
495552
assert.Equal(t, exp, parameter.FormType, "parameter form type equality check")
@@ -555,6 +612,7 @@ func (a assertParam) extend(f assertParam) assertParam {
555612
}
556613

557614
return func(t *testing.T, parameter types.Parameter) {
615+
t.Helper()
558616
(a)(t, parameter)
559617
f(t, parameter)
560618
}

site/src/types/preview.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// Code generated by 'guts'. DO NOT EDIT.
22

3+
// From types/diagnostics.go
4+
export const DiagnosticCodeRequired = "required";
5+
36
// From types/diagnostics.go
47
export interface DiagnosticExtra {
58
readonly code: string;

testdata/required/main.tf

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Base case for workspace tags + parameters.
2+
terraform {
3+
required_providers {
4+
coder = {
5+
source = "coder/coder"
6+
version = "2.4.0-pre0"
7+
}
8+
}
9+
}
10+
11+
data "coder_parameter" "region" {
12+
name = "region"
13+
description = "Which region would you like to deploy to?"
14+
type = "string"
15+
order = 1
16+
17+
option {
18+
name = "Europe"
19+
value = "eu"
20+
}
21+
option {
22+
name = "United States"
23+
value = "us"
24+
}
25+
}

testdata/required/skipe2e

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
missing param value

types/diagnostics.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import (
66
"github.com/hashicorp/hcl/v2"
77
)
88

9+
const (
10+
// DiagnosticCodeRequired is used when a parameter value is `null`, but
11+
// the parameter is required.
12+
DiagnosticCodeRequired = "required"
13+
)
14+
915
type DiagnosticExtra struct {
1016
Code string `json:"code"`
1117

@@ -19,6 +25,13 @@ func (e DiagnosticExtra) UnwrapDiagnosticExtra() interface{} {
1925
return e.Wrapped
2026
}
2127

28+
func DiagnosticCode(diag *hcl.Diagnostic, code string) *hcl.Diagnostic {
29+
SetDiagnosticExtra(diag, DiagnosticExtra{
30+
Code: code,
31+
})
32+
return diag
33+
}
34+
2235
func ExtractDiagnosticExtra(diag *hcl.Diagnostic) DiagnosticExtra {
2336
// Zero values for a missing extra field is fine.
2437
extra, _ := hcl.DiagnosticExtra[DiagnosticExtra](diag)

0 commit comments

Comments
 (0)