Skip to content

Commit f37d1cb

Browse files
committed
Switching to using path expressions for AtLeastSumOf, AtMostSumOf and EqualToSumOf validators (#20)
1 parent 533f2df commit f37d1cb

File tree

6 files changed

+213
-179
lines changed

6 files changed

+213
-179
lines changed

int64validator/at_least_sum_of.go

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ import (
1515
var _ tfsdk.AttributeValidator = atLeastSumOfValidator{}
1616

1717
// atLeastSumOfValidator validates that an integer Attribute's value is at least the sum of one
18-
// or more integer Attributes.
18+
// or more integer Attributes retrieved via the given path expressions.
1919
type atLeastSumOfValidator struct {
20-
attributesToSumPaths []path.Path
20+
attributesToSumPathExpressions path.Expressions
2121
}
2222

2323
// Description describes the validation in plain text formatting.
2424
func (validator atLeastSumOfValidator) Description(_ context.Context) string {
2525
var attributePaths []string
26-
for _, p := range validator.attributesToSumPaths {
26+
for _, p := range validator.attributesToSumPathExpressions {
2727
attributePaths = append(attributePaths, p.String())
2828
}
2929

@@ -46,32 +46,44 @@ func (validator atLeastSumOfValidator) Validate(ctx context.Context, request tfs
4646
var sumOfAttribs int64
4747
var numUnknownAttribsToSum int
4848

49-
for _, p := range validator.attributesToSumPaths {
50-
var attribToSum types.Int64
49+
for _, expression := range validator.attributesToSumPathExpressions {
50+
matchedPaths, diags := request.Config.PathMatches(ctx, expression)
51+
response.Diagnostics.Append(diags...)
5152

52-
response.Diagnostics.Append(request.Config.GetAttribute(ctx, p, &attribToSum)...)
53-
if response.Diagnostics.HasError() {
54-
return
55-
}
56-
57-
if attribToSum.Null {
53+
// Collect all errors
54+
if diags.HasError() {
5855
continue
5956
}
6057

61-
if attribToSum.Unknown {
62-
numUnknownAttribsToSum++
63-
continue
64-
}
58+
for _, mp := range matchedPaths {
59+
var attribToSum types.Int64
60+
61+
diags := request.Config.GetAttribute(ctx, mp, &attribToSum)
62+
response.Diagnostics.Append(diags...)
63+
64+
// Collect all errors
65+
if diags.HasError() {
66+
continue
67+
}
6568

66-
sumOfAttribs += attribToSum.Value
69+
if attribToSum.IsNull() {
70+
continue
71+
}
72+
73+
if attribToSum.IsUnknown() {
74+
numUnknownAttribsToSum++
75+
continue
76+
}
77+
78+
sumOfAttribs += attribToSum.Value
79+
}
6780
}
6881

69-
if numUnknownAttribsToSum == len(validator.attributesToSumPaths) {
82+
if numUnknownAttribsToSum == len(validator.attributesToSumPathExpressions) {
7083
return
7184
}
7285

7386
if i < sumOfAttribs {
74-
7587
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
7688
request.AttributePath,
7789
validator.Description(ctx),
@@ -86,11 +98,9 @@ func (validator atLeastSumOfValidator) Validate(ctx context.Context, request tfs
8698
// attribute value:
8799
//
88100
// - Is a number, which can be represented by a 64-bit integer.
89-
// - Is exclusively at least the sum of the given attributes.
101+
// - Is at least the sum of the attributes retrieved via the given path expression(s).
90102
//
91103
// Null (unconfigured) and unknown (known after apply) values are skipped.
92-
func AtLeastSumOf(attributesToSum ...path.Path) tfsdk.AttributeValidator {
93-
return atLeastSumOfValidator{
94-
attributesToSumPaths: attributesToSum,
95-
}
104+
func AtLeastSumOf(attributesToSumPathExpressions ...path.Expression) tfsdk.AttributeValidator {
105+
return atLeastSumOfValidator{attributesToSumPathExpressions}
96106
}

int64validator/at_least_sum_of_test.go

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ func TestAtLeastSumOfValidator(t *testing.T) {
1515
t.Parallel()
1616

1717
type testCase struct {
18-
val attr.Value
19-
attributesToSumPaths []path.Path
20-
requestConfigRaw map[string]tftypes.Value
21-
expectError bool
18+
val attr.Value
19+
attributesToSumExpressions path.Expressions
20+
requestConfigRaw map[string]tftypes.Value
21+
expectError bool
2222
}
2323
tests := map[string]testCase{
2424
"not an Int64": {
@@ -33,9 +33,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
3333
},
3434
"valid integer as Int64 less than sum of attributes": {
3535
val: types.Int64{Value: 10},
36-
attributesToSumPaths: []path.Path{
37-
path.Root("one"),
38-
path.Root("two"),
36+
attributesToSumExpressions: path.Expressions{
37+
path.MatchRoot("one"),
38+
path.MatchRoot("two"),
3939
},
4040
requestConfigRaw: map[string]tftypes.Value{
4141
"one": tftypes.NewValue(tftypes.Number, 15),
@@ -45,9 +45,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
4545
},
4646
"valid integer as Int64 equal to sum of attributes": {
4747
val: types.Int64{Value: 10},
48-
attributesToSumPaths: []path.Path{
49-
path.Root("one"),
50-
path.Root("two"),
48+
attributesToSumExpressions: path.Expressions{
49+
path.MatchRoot("one"),
50+
path.MatchRoot("two"),
5151
},
5252
requestConfigRaw: map[string]tftypes.Value{
5353
"one": tftypes.NewValue(tftypes.Number, 5),
@@ -56,9 +56,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
5656
},
5757
"valid integer as Int64 greater than sum of attributes": {
5858
val: types.Int64{Value: 10},
59-
attributesToSumPaths: []path.Path{
60-
path.Root("one"),
61-
path.Root("two"),
59+
attributesToSumExpressions: path.Expressions{
60+
path.MatchRoot("one"),
61+
path.MatchRoot("two"),
6262
},
6363
requestConfigRaw: map[string]tftypes.Value{
6464
"one": tftypes.NewValue(tftypes.Number, 4),
@@ -67,9 +67,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
6767
},
6868
"valid integer as Int64 greater than sum of attributes, when one summed attribute is null": {
6969
val: types.Int64{Value: 10},
70-
attributesToSumPaths: []path.Path{
71-
path.Root("one"),
72-
path.Root("two"),
70+
attributesToSumExpressions: path.Expressions{
71+
path.MatchRoot("one"),
72+
path.MatchRoot("two"),
7373
},
7474
requestConfigRaw: map[string]tftypes.Value{
7575
"one": tftypes.NewValue(tftypes.Number, nil),
@@ -78,9 +78,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
7878
},
7979
"valid integer as Int64 does not return error when all attributes are null": {
8080
val: types.Int64{Null: true},
81-
attributesToSumPaths: []path.Path{
82-
path.Root("one"),
83-
path.Root("two"),
81+
attributesToSumExpressions: path.Expressions{
82+
path.MatchRoot("one"),
83+
path.MatchRoot("two"),
8484
},
8585
requestConfigRaw: map[string]tftypes.Value{
8686
"one": tftypes.NewValue(tftypes.Number, nil),
@@ -89,9 +89,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
8989
},
9090
"valid integer as Int64 returns error when all attributes to sum are null": {
9191
val: types.Int64{Value: -1},
92-
attributesToSumPaths: []path.Path{
93-
path.Root("one"),
94-
path.Root("two"),
92+
attributesToSumExpressions: path.Expressions{
93+
path.MatchRoot("one"),
94+
path.MatchRoot("two"),
9595
},
9696
requestConfigRaw: map[string]tftypes.Value{
9797
"one": tftypes.NewValue(tftypes.Number, nil),
@@ -101,9 +101,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
101101
},
102102
"valid integer as Int64 greater than sum of attributes, when one summed attribute is unknown": {
103103
val: types.Int64{Value: 10},
104-
attributesToSumPaths: []path.Path{
105-
path.Root("one"),
106-
path.Root("two"),
104+
attributesToSumExpressions: path.Expressions{
105+
path.MatchRoot("one"),
106+
path.MatchRoot("two"),
107107
},
108108
requestConfigRaw: map[string]tftypes.Value{
109109
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
@@ -112,9 +112,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
112112
},
113113
"valid integer as Int64 does not return error when all attributes are unknown": {
114114
val: types.Int64{Unknown: true},
115-
attributesToSumPaths: []path.Path{
116-
path.Root("one"),
117-
path.Root("two"),
115+
attributesToSumExpressions: path.Expressions{
116+
path.MatchRoot("one"),
117+
path.MatchRoot("two"),
118118
},
119119
requestConfigRaw: map[string]tftypes.Value{
120120
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
@@ -123,9 +123,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
123123
},
124124
"valid integer as Int64 does not return error when all attributes to sum are unknown": {
125125
val: types.Int64{Value: -1},
126-
attributesToSumPaths: []path.Path{
127-
path.Root("one"),
128-
path.Root("two"),
126+
attributesToSumExpressions: path.Expressions{
127+
path.MatchRoot("one"),
128+
path.MatchRoot("two"),
129129
},
130130
requestConfigRaw: map[string]tftypes.Value{
131131
"one": tftypes.NewValue(tftypes.Number, tftypes.UnknownValue),
@@ -134,9 +134,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
134134
},
135135
"error when attribute to sum is not Number": {
136136
val: types.Int64{Value: 9},
137-
attributesToSumPaths: []path.Path{
138-
path.Root("one"),
139-
path.Root("two"),
137+
attributesToSumExpressions: path.Expressions{
138+
path.MatchRoot("one"),
139+
path.MatchRoot("two"),
140140
},
141141
requestConfigRaw: map[string]tftypes.Value{
142142
"one": tftypes.NewValue(tftypes.Bool, true),
@@ -150,8 +150,9 @@ func TestAtLeastSumOfValidator(t *testing.T) {
150150
name, test := name, test
151151
t.Run(name, func(t *testing.T) {
152152
request := tfsdk.ValidateAttributeRequest{
153-
AttributePath: path.Root("test"),
154-
AttributeConfig: test.val,
153+
AttributePath: path.Root("test"),
154+
AttributePathExpression: path.MatchRoot("test"),
155+
AttributeConfig: test.val,
155156
Config: tfsdk.Config{
156157
Raw: tftypes.NewValue(tftypes.Object{}, test.requestConfigRaw),
157158
Schema: tfsdk.Schema{
@@ -166,7 +167,7 @@ func TestAtLeastSumOfValidator(t *testing.T) {
166167

167168
response := tfsdk.ValidateAttributeResponse{}
168169

169-
AtLeastSumOf(test.attributesToSumPaths...).Validate(context.Background(), request, &response)
170+
AtLeastSumOf(test.attributesToSumExpressions...).Validate(context.Background(), request, &response)
170171

171172
if !response.Diagnostics.HasError() && test.expectError {
172173
t.Fatal("expected error, got no error")

int64validator/at_most_sum_of.go

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ import (
1515
var _ tfsdk.AttributeValidator = atMostSumOfValidator{}
1616

1717
// atMostSumOfValidator validates that an integer Attribute's value is at most the sum of one
18-
// or more integer Attributes.
18+
// or more integer Attributes retrieved via the given path expressions.
1919
type atMostSumOfValidator struct {
20-
attributesToSumPaths []path.Path
20+
attributesToSumPathExpressions path.Expressions
2121
}
2222

2323
// Description describes the validation in plain text formatting.
2424
func (validator atMostSumOfValidator) Description(_ context.Context) string {
2525
var attributePaths []string
26-
for _, p := range validator.attributesToSumPaths {
26+
for _, p := range validator.attributesToSumPathExpressions {
2727
attributePaths = append(attributePaths, p.String())
2828
}
2929

@@ -46,32 +46,44 @@ func (validator atMostSumOfValidator) Validate(ctx context.Context, request tfsd
4646
var sumOfAttribs int64
4747
var numUnknownAttribsToSum int
4848

49-
for _, p := range validator.attributesToSumPaths {
50-
var attribToSum types.Int64
49+
for _, expression := range validator.attributesToSumPathExpressions {
50+
matchedPaths, diags := request.Config.PathMatches(ctx, expression)
51+
response.Diagnostics.Append(diags...)
5152

52-
response.Diagnostics.Append(request.Config.GetAttribute(ctx, p, &attribToSum)...)
53-
if response.Diagnostics.HasError() {
54-
return
55-
}
56-
57-
if attribToSum.Null {
53+
// Collect all errors
54+
if diags.HasError() {
5855
continue
5956
}
6057

61-
if attribToSum.Unknown {
62-
numUnknownAttribsToSum++
63-
continue
64-
}
58+
for _, mp := range matchedPaths {
59+
var attribToSum types.Int64
60+
61+
diags := request.Config.GetAttribute(ctx, mp, &attribToSum)
62+
response.Diagnostics.Append(diags...)
63+
64+
// Collect all errors
65+
if diags.HasError() {
66+
continue
67+
}
6568

66-
sumOfAttribs += attribToSum.Value
69+
if attribToSum.IsNull() {
70+
continue
71+
}
72+
73+
if attribToSum.IsUnknown() {
74+
numUnknownAttribsToSum++
75+
continue
76+
}
77+
78+
sumOfAttribs += attribToSum.Value
79+
}
6780
}
6881

69-
if numUnknownAttribsToSum == len(validator.attributesToSumPaths) {
82+
if numUnknownAttribsToSum == len(validator.attributesToSumPathExpressions) {
7083
return
7184
}
7285

7386
if i > sumOfAttribs {
74-
7587
response.Diagnostics.Append(validatordiag.InvalidAttributeValueDiagnostic(
7688
request.AttributePath,
7789
validator.Description(ctx),
@@ -86,11 +98,9 @@ func (validator atMostSumOfValidator) Validate(ctx context.Context, request tfsd
8698
// attribute value:
8799
//
88100
// - Is a number, which can be represented by a 64-bit integer.
89-
// - Is exclusively at most the sum of the given attributes.
101+
// - Is at most the sum of the given attributes retrieved via the given path expression(s).
90102
//
91103
// Null (unconfigured) and unknown (known after apply) values are skipped.
92-
func AtMostSumOf(attributesToSum ...path.Path) tfsdk.AttributeValidator {
93-
return atMostSumOfValidator{
94-
attributesToSumPaths: attributesToSum,
95-
}
104+
func AtMostSumOf(attributesToSumPathExpressions ...path.Expression) tfsdk.AttributeValidator {
105+
return atMostSumOfValidator{attributesToSumPathExpressions}
96106
}

0 commit comments

Comments
 (0)