Skip to content

Commit 77c0a76

Browse files
committed
Adding Set validation for SizeAtLeast, SizeAtMost and SizeBetween (#5)
1 parent 5896064 commit 77c0a76

File tree

6 files changed

+472
-0
lines changed

6 files changed

+472
-0
lines changed

setvalidator/size_at_least.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package setvalidator
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
8+
9+
"github.com/hashicorp/terraform-plugin-framework-validators/validatordiag"
10+
)
11+
12+
var _ tfsdk.AttributeValidator = sizeAtLeastValidator{}
13+
14+
// sizeAtLeastValidator validates that set contains at least min elements.
15+
type sizeAtLeastValidator struct {
16+
min int
17+
}
18+
19+
// Description describes the validation in plain text formatting.
20+
func (v sizeAtLeastValidator) Description(ctx context.Context) string {
21+
return fmt.Sprintf("set must contain at least %d elements", v.min)
22+
}
23+
24+
// MarkdownDescription describes the validation in Markdown formatting.
25+
func (v sizeAtLeastValidator) MarkdownDescription(ctx context.Context) string {
26+
return v.Description(ctx)
27+
}
28+
29+
// Validate performs the validation.
30+
func (v sizeAtLeastValidator) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
31+
elems, ok := validateSet(ctx, req, resp)
32+
if !ok {
33+
return
34+
}
35+
36+
if len(elems) < v.min {
37+
resp.Diagnostics.Append(validatordiag.AttributeValueDiagnostic(
38+
req.AttributePath,
39+
v.Description(ctx),
40+
fmt.Sprintf("%d", len(elems)),
41+
))
42+
43+
return
44+
}
45+
}
46+
47+
func SizeAtLeast(min int) tfsdk.AttributeValidator {
48+
return sizeAtLeastValidator{
49+
min: min,
50+
}
51+
}

setvalidator/size_at_least_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package setvalidator
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/attr"
8+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
"github.com/hashicorp/terraform-plugin-go/tftypes"
11+
)
12+
13+
func TestSizeAtLeastValidator(t *testing.T) {
14+
t.Parallel()
15+
16+
type testCase struct {
17+
val attr.Value
18+
min int
19+
expectError bool
20+
}
21+
tests := map[string]testCase{
22+
"not a Set": {
23+
val: types.Bool{Value: true},
24+
expectError: true,
25+
},
26+
"Set unknown": {
27+
val: types.Set{
28+
Unknown: true,
29+
ElemType: types.StringType,
30+
},
31+
expectError: false,
32+
},
33+
"Set null": {
34+
val: types.Set{
35+
Null: true,
36+
ElemType: types.StringType,
37+
},
38+
expectError: false,
39+
},
40+
"Set size greater than min": {
41+
val: types.Set{
42+
ElemType: types.StringType,
43+
Elems: []attr.Value{
44+
types.String{Value: "first"},
45+
types.String{Value: "second"},
46+
},
47+
},
48+
min: 1,
49+
expectError: false,
50+
},
51+
"Set size equal to min": {
52+
val: types.Set{
53+
ElemType: types.StringType,
54+
Elems: []attr.Value{
55+
types.String{Value: "first"},
56+
},
57+
},
58+
min: 1,
59+
expectError: false,
60+
},
61+
"Set size less than min": {
62+
val: types.Set{
63+
ElemType: types.StringType,
64+
Elems: []attr.Value{},
65+
},
66+
min: 1,
67+
expectError: true,
68+
},
69+
}
70+
71+
for name, test := range tests {
72+
name, test := name, test
73+
t.Run(name, func(t *testing.T) {
74+
request := tfsdk.ValidateAttributeRequest{
75+
AttributePath: tftypes.NewAttributePath().WithAttributeName("test"),
76+
AttributeConfig: test.val,
77+
}
78+
response := tfsdk.ValidateAttributeResponse{}
79+
SizeAtLeast(test.min).Validate(context.TODO(), request, &response)
80+
81+
if !response.Diagnostics.HasError() && test.expectError {
82+
t.Fatal("expected error, got no error")
83+
}
84+
85+
if response.Diagnostics.HasError() && !test.expectError {
86+
t.Fatalf("got unexpected error: %s", response.Diagnostics)
87+
}
88+
})
89+
}
90+
}

setvalidator/size_at_most.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package setvalidator
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
8+
9+
"github.com/hashicorp/terraform-plugin-framework-validators/validatordiag"
10+
)
11+
12+
var _ tfsdk.AttributeValidator = sizeAtMostValidator{}
13+
14+
// sizeAtMostValidator validates that set contains at most max elements.
15+
type sizeAtMostValidator struct {
16+
max int
17+
}
18+
19+
// Description describes the validation in plain text formatting.
20+
func (v sizeAtMostValidator) Description(ctx context.Context) string {
21+
return fmt.Sprintf("set must contain at most %d elements", v.max)
22+
}
23+
24+
// MarkdownDescription describes the validation in Markdown formatting.
25+
func (v sizeAtMostValidator) MarkdownDescription(ctx context.Context) string {
26+
return v.Description(ctx)
27+
}
28+
29+
// Validate performs the validation.
30+
func (v sizeAtMostValidator) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
31+
elems, ok := validateSet(ctx, req, resp)
32+
if !ok {
33+
return
34+
}
35+
36+
if len(elems) > v.max {
37+
resp.Diagnostics.Append(validatordiag.AttributeValueDiagnostic(
38+
req.AttributePath,
39+
v.Description(ctx),
40+
fmt.Sprintf("%d", len(elems)),
41+
))
42+
43+
return
44+
}
45+
}
46+
47+
func SizeAtMost(max int) tfsdk.AttributeValidator {
48+
return sizeAtMostValidator{
49+
max: max,
50+
}
51+
}

setvalidator/size_at_most_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package setvalidator
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/attr"
8+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
9+
"github.com/hashicorp/terraform-plugin-framework/types"
10+
"github.com/hashicorp/terraform-plugin-go/tftypes"
11+
)
12+
13+
func TestSizeAtMostValidator(t *testing.T) {
14+
t.Parallel()
15+
16+
type testCase struct {
17+
val attr.Value
18+
max int
19+
expectError bool
20+
}
21+
tests := map[string]testCase{
22+
"not a Set": {
23+
val: types.Bool{Value: true},
24+
expectError: true,
25+
},
26+
"Set unknown": {
27+
val: types.Set{
28+
Unknown: true,
29+
ElemType: types.StringType,
30+
},
31+
expectError: false,
32+
},
33+
"Set null": {
34+
val: types.Set{
35+
Null: true,
36+
ElemType: types.StringType,
37+
},
38+
expectError: false,
39+
},
40+
"Set size less than max": {
41+
val: types.Set{
42+
ElemType: types.StringType,
43+
Elems: []attr.Value{
44+
types.String{Value: "first"},
45+
},
46+
},
47+
max: 2,
48+
expectError: false,
49+
},
50+
"Set size equal to max": {
51+
val: types.Set{
52+
ElemType: types.StringType,
53+
Elems: []attr.Value{
54+
types.String{Value: "first"},
55+
types.String{Value: "second"},
56+
},
57+
},
58+
max: 2,
59+
expectError: false,
60+
},
61+
"Set size greater than max": {
62+
val: types.Set{
63+
ElemType: types.StringType,
64+
Elems: []attr.Value{
65+
types.String{Value: "first"},
66+
types.String{Value: "second"},
67+
types.String{Value: "third"},
68+
}},
69+
max: 2,
70+
expectError: true,
71+
},
72+
}
73+
74+
for name, test := range tests {
75+
name, test := name, test
76+
t.Run(name, func(t *testing.T) {
77+
request := tfsdk.ValidateAttributeRequest{
78+
AttributePath: tftypes.NewAttributePath().WithAttributeName("test"),
79+
AttributeConfig: test.val,
80+
}
81+
response := tfsdk.ValidateAttributeResponse{}
82+
SizeAtMost(test.max).Validate(context.TODO(), request, &response)
83+
84+
if !response.Diagnostics.HasError() && test.expectError {
85+
t.Fatal("expected error, got no error")
86+
}
87+
88+
if response.Diagnostics.HasError() && !test.expectError {
89+
t.Fatalf("got unexpected error: %s", response.Diagnostics)
90+
}
91+
})
92+
}
93+
}

setvalidator/size_between.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package setvalidator
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
8+
9+
"github.com/hashicorp/terraform-plugin-framework-validators/validatordiag"
10+
)
11+
12+
var _ tfsdk.AttributeValidator = sizeBetweenValidator{}
13+
14+
// sizeBetweenValidator validates that set contains at least min elements
15+
// and at most max elements.
16+
type sizeBetweenValidator struct {
17+
min int
18+
max int
19+
}
20+
21+
// Description describes the validation in plain text formatting.
22+
func (v sizeBetweenValidator) Description(ctx context.Context) string {
23+
return fmt.Sprintf("set must contain at least %d elements and at most %d elements", v.min, v.max)
24+
}
25+
26+
// MarkdownDescription describes the validation in Markdown formatting.
27+
func (v sizeBetweenValidator) MarkdownDescription(ctx context.Context) string {
28+
return v.Description(ctx)
29+
}
30+
31+
// Validate performs the validation.
32+
func (v sizeBetweenValidator) Validate(ctx context.Context, req tfsdk.ValidateAttributeRequest, resp *tfsdk.ValidateAttributeResponse) {
33+
elems, ok := validateSet(ctx, req, resp)
34+
if !ok {
35+
return
36+
}
37+
38+
if len(elems) < v.min || len(elems) > v.max {
39+
resp.Diagnostics.Append(validatordiag.AttributeValueDiagnostic(
40+
req.AttributePath,
41+
v.Description(ctx),
42+
fmt.Sprintf("%d", len(elems)),
43+
))
44+
45+
return
46+
}
47+
}
48+
49+
func SizeBetween(min, max int) tfsdk.AttributeValidator {
50+
return sizeBetweenValidator{
51+
min: min,
52+
max: max,
53+
}
54+
}

0 commit comments

Comments
 (0)