hashicorp / terraform-plugin-framework-validators

Common Use Case Validators for terraform-plugin-framework
Mozilla Public License 2.0
25 stars 12 forks source link

RequiredWhenStringValueAtAnyOf() #113

Open chrismarget opened 1 year ago

chrismarget commented 1 year ago

Terraform CLI and Framework Versions

any

Use Cases or Problem Statement

I have a need for schema attributes to be recognized as mandatory when certain values appear in other attributes.

For example, when mode is "complicated", complicated_mode_params should be required.

I'm thinking something like this:

        "mode": schema.StringAttribute{
            Required:   true,
            Validators: []validator.String{stringvalidator.OneOf("simple", "complicated")},
        },
        "complicated_mode_params": schema.MapNestedAttribute{
            Optional: true,
            Validators: []validator.Map{
                mapvalidator.RequiredWhenStringValueAtAnyOf("complicated",
                    path.Expressions{path.MatchRelative().AtName("mode")}...),
            },
            NestedObject: schema.NestedAttributeObject{
                Attributes: map[string]schema.Attribute{
                    "mode_one_param_one": schema.StringAttribute{
                        Required: true,
                    },
                    "mode_one_param_two": schema.StringAttribute{
                        Required: true,
                    },
                },
            },
        },

Proposal

This situation could be generalized with validators for each attribute type which check for trigger values in other attributes of all types:

stringValidator.RequiredWhenStringValueAtAnyOf(val string, attributesToSumPathExpressions ...path.Expression) validator.String
stringValidator.RequiredWhenInt64ValueAtAnyOf(val int64, attributesToSumPathExpressions ...path.Expression) validator.String
stringValidator.RequiredWhenBoolValueAtAnyOf(val bool, attributesToSumPathExpressions ...path.Expression) validator.String

Same for int64Validator, mapValidator, boolValidator, etc...

Comments elsewhere from @bflad indicate you're planning to set ground rules for validator inclusion this Friday, so I'm opening this issue with that in mind.

If there's interest, I could take a crack at it.

Additional Information

No response

Code of Conduct

bflad commented 1 year ago

Thanks for raising this, @chrismarget. 👍 My focus is elsewhere at the moment, but I wanted to drop some potential considerations here for you and future travelers.

A potential concern (outside booleans) is that using a single, static value associated with a Go built-in value type may become a scalability issue for this Go module. For example, strings might be desirable to be tested against regular expressions or numbers against ranges.

To mitigate that sort of concern, something to potentially consider in this context is whether something like a generic validation framework around "if" conditionals may be a less-specific solution to reduce the surface area to introduce type of functionality. Back with terraform-plugin-sdk, the customdiff package implemented conditional helpers so it was possible to potentially decouple the conditional logic from needing to be re-introduced for every possible permutation (or at least made it consistent). Maybe something like stringvalidator.RequiredWhen(/* if logic */).

Potentially more outlandish in that space would be meta if-then support. Maybe something like stringvalidator.If(/* if logic*/, []validator.String). Then there is nothing new in this Go module required to make other validators conditional.

Another way to potentially frame this problem and potential solution is validating the opposite way -- similar to the existing AlsoRequires validators but accepting a value based on the current attribute to trigger the behavior. e.g. stringvalidator.AlsoRequiresIfString(string, path.Expressions). Otherwise, this would already be covered with the "if-then" meta support mentioned above.

The joy of trying to design these. 😄

chrismarget commented 1 year ago

Hi @bflad,

I really like the stringvalidator.If() idea.

Did ground rules for validator inclusion in this repo come together last week?