Skip to content

Commit cd82393

Browse files
SBGoodsbflad
andauthored
Add All, Any, and AnyWithAllWarnings validators to boolvalidator, providervalidator, resourcevalidator and datasourcevalidator packages (#158)
* Add `All`, `Any`, and `AnyWithAllWarnings` validators to `boolvalidator` package * Add `All`, `Any`, and `AnyWithAllWarnings` validators to `datasourcevalidator` package * Simplify example tests * Add `All`, `Any`, and `AnyWithAllWarnings` validators to `providervalidator` package * Add `All`, `Any`, and `AnyWithAllWarnings` validators to `resourcevalidator` package * Add copyright headers * Add changelog entries * Fix example test typo Co-authored-by: Brian Flad <[email protected]> --------- Co-authored-by: Brian Flad <[email protected]>
1 parent 8e0c86c commit cd82393

38 files changed

+2718
-9
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: 'boolvalidator: Added `All`, `Any`, and `AnyWithAllWarnings` validators'
3+
time: 2023-08-18T18:56:06.051472-04:00
4+
custom:
5+
Issue: "158"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'datasourcevalidator: Added `All`, `Any`, and `AnyWithAllWarnings` validators'
3+
time: 2023-08-18T18:56:53.809569-04:00
4+
custom:
5+
Issue: "158"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'providervalidator: Added `All`, `Any`, and `AnyWithAllWarnings` validators'
3+
time: 2023-08-18T18:57:20.9318-04:00
4+
custom:
5+
Issue: "158"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
kind: ENHANCEMENTS
2+
body: 'resourcevalidator: Added `All`, `Any`, and `AnyWithAllWarnings` validators'
3+
time: 2023-08-18T18:58:06.709077-04:00
4+
custom:
5+
Issue: "158"

boolvalidator/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 boolvalidator
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+
// 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.Bool) validator.Bool {
20+
return allValidator{
21+
validators: validators,
22+
}
23+
}
24+
25+
var _ validator.Bool = allValidator{}
26+
27+
// allValidator implements the validator.
28+
type allValidator struct {
29+
validators []validator.Bool
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+
// ValidateBool performs the validation.
49+
func (v allValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
50+
for _, subValidator := range v.validators {
51+
validateResp := &validator.BoolResponse{}
52+
53+
subValidator.ValidateBool(ctx, req, validateResp)
54+
55+
resp.Diagnostics.Append(validateResp.Diagnostics...)
56+
}
57+
}

boolvalidator/all_example_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package boolvalidator_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/boolvalidator"
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.BoolAttribute{
18+
Required: true,
19+
Validators: []validator.Bool{
20+
// This attribute must satisfy either All validator.
21+
boolvalidator.Any(
22+
boolvalidator.All( /* ... */ ),
23+
boolvalidator.All( /* ... */ ),
24+
),
25+
},
26+
},
27+
},
28+
}
29+
}

boolvalidator/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 boolvalidator
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.Bool) validator.Bool {
22+
return anyValidator{
23+
validators: validators,
24+
}
25+
}
26+
27+
var _ validator.Bool = anyValidator{}
28+
29+
// anyValidator implements the validator.
30+
type anyValidator struct {
31+
validators []validator.Bool
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+
// ValidateBool performs the validation.
51+
func (v anyValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
52+
for _, subValidator := range v.validators {
53+
validateResp := &validator.BoolResponse{}
54+
55+
subValidator.ValidateBool(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+
}

boolvalidator/any_example_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package boolvalidator_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/boolvalidator"
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.BoolAttribute{
18+
Required: true,
19+
Validators: []validator.Bool{
20+
boolvalidator.Any( /* ... */ ),
21+
},
22+
},
23+
},
24+
}
25+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package boolvalidator
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"strings"
10+
11+
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
12+
)
13+
14+
// AnyWithAllWarnings returns a validator which ensures that any configured
15+
// attribute value passes at least one of the given validators. This validator
16+
// returns all warnings, including failed validators.
17+
//
18+
// Use Any() to return warnings only from the passing validator.
19+
func AnyWithAllWarnings(validators ...validator.Bool) validator.Bool {
20+
return anyWithAllWarningsValidator{
21+
validators: validators,
22+
}
23+
}
24+
25+
var _ validator.Bool = anyWithAllWarningsValidator{}
26+
27+
// anyWithAllWarningsValidator implements the validator.
28+
type anyWithAllWarningsValidator struct {
29+
validators []validator.Bool
30+
}
31+
32+
// Description describes the validation in plain text formatting.
33+
func (v anyWithAllWarningsValidator) 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 at least one of the validations: %s", strings.Join(descriptions, " + "))
41+
}
42+
43+
// MarkdownDescription describes the validation in Markdown formatting.
44+
func (v anyWithAllWarningsValidator) MarkdownDescription(ctx context.Context) string {
45+
return v.Description(ctx)
46+
}
47+
48+
// ValidateBool performs the validation.
49+
func (v anyWithAllWarningsValidator) ValidateBool(ctx context.Context, req validator.BoolRequest, resp *validator.BoolResponse) {
50+
anyValid := false
51+
52+
for _, subValidator := range v.validators {
53+
validateResp := &validator.BoolResponse{}
54+
55+
subValidator.ValidateBool(ctx, req, validateResp)
56+
57+
if !validateResp.Diagnostics.HasError() {
58+
anyValid = true
59+
}
60+
61+
resp.Diagnostics.Append(validateResp.Diagnostics...)
62+
}
63+
64+
if anyValid {
65+
resp.Diagnostics = resp.Diagnostics.Warnings()
66+
}
67+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package boolvalidator_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/boolvalidator"
11+
)
12+
13+
func ExampleAnyWithAllWarnings() {
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.BoolAttribute{
18+
Required: true,
19+
Validators: []validator.Bool{
20+
boolvalidator.AnyWithAllWarnings( /* ... */ ),
21+
},
22+
},
23+
},
24+
}
25+
}

0 commit comments

Comments
 (0)