Skip to content

Commit ba395d2

Browse files
SBGoodsaustinvalle
andauthored
all: Add support for Int32 and Float32 Type Validators (#222)
* Add `float32validator` package * Add `int32validator` package * Add `Int32Validator` and `Float32Validator` support to `AlsoRequiresValidator`, `AtLeastOneOfValidator`, `ConflictsWithValidator`, and `ExactlyOneOfValidator` * Add `ValueFloat32sAre` and `ValueInt32sAre` validators to `listvalidator`, `mapvalidator`, and `setvalidator` packages * Update `terraform-plugin-framework` dependency to int32/float32 implementation branch * Add changelog entries * Update comments to use integer constants instead of float Co-authored-by: Austin Valle <[email protected]> * Update `int64validator` example tests to use integers instead of floats --------- Co-authored-by: Austin Valle <[email protected]>
1 parent ea42e33 commit ba395d2

File tree

109 files changed

+6517
-20
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

109 files changed

+6517
-20
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'listvalidator: Added `ValueInt32sAre` and `ValueFloat32sAre` validators'
3+
time: 2024-06-26T17:43:47.501066-04:00
4+
custom:
5+
Issue: "222"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'mapvalidator: Added `ValueInt32sAre` and `ValueFloat32sAre` validators'
3+
time: 2024-06-26T17:44:11.352117-04:00
4+
custom:
5+
Issue: "222"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'setvalidator: Added `ValueInt32sAre` and `ValueFloat32sAre` validators'
3+
time: 2024-06-26T17:44:23.323248-04:00
4+
custom:
5+
Issue: "222"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: FEATURES
2+
body: 'int32validator: New package which contains int32 type specific validators'
3+
time: 2024-06-26T17:41:45.007609-04:00
4+
custom:
5+
Issue: "222"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: FEATURES
2+
body: 'float32validator: New package which contains float32 type specific validators'
3+
time: 2024-06-26T17:42:20.2122-04:00
4+
custom:
5+
Issue: "222"

float32validator/all.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
11+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
12+
)
13+
14+
// All returns a validator which ensures that any configured attribute value
15+
// attribute value validates against all the given validators.
16+
//
17+
// Use of All is only necessary when used in conjunction with Any or AnyWithAllWarnings
18+
// as the Validators field automatically applies a logical AND.
19+
func All(validators ...validator.Float32) validator.Float32 {
20+
return allValidator{
21+
validators: validators,
22+
}
23+
}
24+
25+
var _ validator.Float32 = allValidator{}
26+
27+
// allValidator implements the validator.
28+
type allValidator struct {
29+
validators []validator.Float32
30+
}
31+
32+
// Description describes the validation in plain text formatting.
33+
func (v allValidator) Description(ctx context.Context) string {
34+
var descriptions []string
35+
36+
for _, subValidator := range v.validators {
37+
descriptions = append(descriptions, subValidator.Description(ctx))
38+
}
39+
40+
return fmt.Sprintf("Value must satisfy all of the validations: %s", strings.Join(descriptions, " + "))
41+
}
42+
43+
// MarkdownDescription describes the validation in Markdown formatting.
44+
func (v allValidator) MarkdownDescription(ctx context.Context) string {
45+
return v.Description(ctx)
46+
}
47+
48+
// ValidateFloat32 performs the validation.
49+
func (v allValidator) ValidateFloat32(ctx context.Context, req validator.Float32Request, resp *validator.Float32Response) {
50+
for _, subValidator := range v.validators {
51+
validateResp := &validator.Float32Response{}
52+
53+
subValidator.ValidateFloat32(ctx, req, validateResp)
54+
55+
resp.Diagnostics.Append(validateResp.Diagnostics...)
56+
}
57+
}

float32validator/all_example_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator_test
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
8+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
9+
10+
"github.com/hashicorp/terraform-plugin-framework-validators/float32validator"
11+
)
12+
13+
func ExampleAll() {
14+
// Used within a Schema method of a DataSource, Provider, or Resource
15+
_ = schema.Schema{
16+
Attributes: map[string]schema.Attribute{
17+
"example_attr": schema.Float32Attribute{
18+
Required: true,
19+
Validators: []validator.Float32{
20+
// Validate this Float32 value must either be:
21+
// - 1.0
22+
// - At least 2.0, but not 3.0
23+
float32validator.Any(
24+
float32validator.OneOf(1.0),
25+
float32validator.All(
26+
float32validator.AtLeast(2.0),
27+
float32validator.NoneOf(3.0),
28+
),
29+
),
30+
},
31+
},
32+
},
33+
}
34+
}

float32validator/all_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator_test
5+
6+
import (
7+
"context"
8+
"testing"
9+
10+
"github.com/google/go-cmp/cmp"
11+
"github.com/hashicorp/terraform-plugin-framework/diag"
12+
"github.com/hashicorp/terraform-plugin-framework/path"
13+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
14+
"github.com/hashicorp/terraform-plugin-framework/types"
15+
16+
"github.com/hashicorp/terraform-plugin-framework-validators/float32validator"
17+
)
18+
19+
func TestAllValidatorValidateFloat32(t *testing.T) {
20+
t.Parallel()
21+
22+
type testCase struct {
23+
val types.Float32
24+
validators []validator.Float32
25+
expected diag.Diagnostics
26+
}
27+
tests := map[string]testCase{
28+
"invalid": {
29+
val: types.Float32Value(1.2),
30+
validators: []validator.Float32{
31+
float32validator.AtLeast(3),
32+
float32validator.AtLeast(5),
33+
},
34+
expected: diag.Diagnostics{
35+
diag.NewAttributeErrorDiagnostic(
36+
path.Root("test"),
37+
"Invalid Attribute Value",
38+
"Attribute test value must be at least 3.000000, got: 1.200000",
39+
),
40+
diag.NewAttributeErrorDiagnostic(
41+
path.Root("test"),
42+
"Invalid Attribute Value",
43+
"Attribute test value must be at least 5.000000, got: 1.200000",
44+
),
45+
},
46+
},
47+
"valid": {
48+
val: types.Float32Value(1.2),
49+
validators: []validator.Float32{
50+
float32validator.AtLeast(0),
51+
float32validator.AtLeast(1),
52+
},
53+
expected: nil,
54+
},
55+
}
56+
57+
for name, test := range tests {
58+
name, test := name, test
59+
t.Run(name, func(t *testing.T) {
60+
t.Parallel()
61+
request := validator.Float32Request{
62+
Path: path.Root("test"),
63+
PathExpression: path.MatchRoot("test"),
64+
ConfigValue: test.val,
65+
}
66+
response := validator.Float32Response{}
67+
float32validator.All(test.validators...).ValidateFloat32(context.Background(), request, &response)
68+
69+
if diff := cmp.Diff(response.Diagnostics, test.expected); diff != "" {
70+
t.Errorf("unexpected diagnostics difference: %s", diff)
71+
}
72+
})
73+
}
74+
}

float32validator/also_requires.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/path"
8+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
9+
10+
"github.com/hashicorp/terraform-plugin-framework-validators/internal/schemavalidator"
11+
)
12+
13+
// AlsoRequires checks that a set of path.Expression has a non-null value,
14+
// if the current attribute also has a non-null value.
15+
//
16+
// This implements the validation logic declaratively within the schema.
17+
// Refer to [datasourcevalidator.RequiredTogether],
18+
// [providervalidator.RequiredTogether], or [resourcevalidator.RequiredTogether]
19+
// for declaring this type of validation outside the schema definition.
20+
//
21+
// Relative path.Expression will be resolved using the attribute being
22+
// validated.
23+
func AlsoRequires(expressions ...path.Expression) validator.Float32 {
24+
return schemavalidator.AlsoRequiresValidator{
25+
PathExpressions: expressions,
26+
}
27+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator_test
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
8+
"github.com/hashicorp/terraform-plugin-framework/path"
9+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
10+
11+
"github.com/hashicorp/terraform-plugin-framework-validators/float32validator"
12+
)
13+
14+
func ExampleAlsoRequires() {
15+
// Used within a Schema method of a DataSource, Provider, or Resource
16+
_ = schema.Schema{
17+
Attributes: map[string]schema.Attribute{
18+
"example_attr": schema.Float32Attribute{
19+
Optional: true,
20+
Validators: []validator.Float32{
21+
// Validate this attribute must be configured with other_attr.
22+
float32validator.AlsoRequires(path.Expressions{
23+
path.MatchRoot("other_attr"),
24+
}...),
25+
},
26+
},
27+
"other_attr": schema.StringAttribute{
28+
Optional: true,
29+
},
30+
},
31+
}
32+
}

float32validator/any.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
11+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
12+
)
13+
14+
// Any returns a validator which ensures that any configured attribute value
15+
// passes at least one of the given validators.
16+
//
17+
// To prevent practitioner confusion should non-passing validators have
18+
// conflicting logic, only warnings from the passing validator are returned.
19+
// Use AnyWithAllWarnings() to return warnings from non-passing validators
20+
// as well.
21+
func Any(validators ...validator.Float32) validator.Float32 {
22+
return anyValidator{
23+
validators: validators,
24+
}
25+
}
26+
27+
var _ validator.Float32 = anyValidator{}
28+
29+
// anyValidator implements the validator.
30+
type anyValidator struct {
31+
validators []validator.Float32
32+
}
33+
34+
// Description describes the validation in plain text formatting.
35+
func (v anyValidator) Description(ctx context.Context) string {
36+
var descriptions []string
37+
38+
for _, subValidator := range v.validators {
39+
descriptions = append(descriptions, subValidator.Description(ctx))
40+
}
41+
42+
return fmt.Sprintf("Value must satisfy at least one of the validations: %s", strings.Join(descriptions, " + "))
43+
}
44+
45+
// MarkdownDescription describes the validation in Markdown formatting.
46+
func (v anyValidator) MarkdownDescription(ctx context.Context) string {
47+
return v.Description(ctx)
48+
}
49+
50+
// ValidateFloat32 performs the validation.
51+
func (v anyValidator) ValidateFloat32(ctx context.Context, req validator.Float32Request, resp *validator.Float32Response) {
52+
for _, subValidator := range v.validators {
53+
validateResp := &validator.Float32Response{}
54+
55+
subValidator.ValidateFloat32(ctx, req, validateResp)
56+
57+
if !validateResp.Diagnostics.HasError() {
58+
resp.Diagnostics = validateResp.Diagnostics
59+
60+
return
61+
}
62+
63+
resp.Diagnostics.Append(validateResp.Diagnostics...)
64+
}
65+
}

float32validator/any_example_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package float32validator_test
5+
6+
import (
7+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
8+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
9+
10+
"github.com/hashicorp/terraform-plugin-framework-validators/float32validator"
11+
)
12+
13+
func ExampleAny() {
14+
// Used within a Schema method of a DataSource, Provider, or Resource
15+
_ = schema.Schema{
16+
Attributes: map[string]schema.Attribute{
17+
"example_attr": schema.Float32Attribute{
18+
Required: true,
19+
Validators: []validator.Float32{
20+
// Validate this Float32 value must either be:
21+
// - 1.0
22+
// - At least 2.0
23+
float32validator.Any(
24+
float32validator.OneOf(1.0),
25+
float32validator.AtLeast(2.0),
26+
),
27+
},
28+
},
29+
},
30+
}
31+
}

0 commit comments

Comments
 (0)