helper/validation: Add NoZeroValues

This adds NoZeroValues, a small SchemaValidateFunc that checks that a
defined value is not a zero value. It's useful for situations where you
want to keep someone from explicitly entering a zero value (ie:
literally "0", or an empty string) on a required field, and want to
catch it in the validation stage, versus during apply using GetOk.
This commit is contained in:
Chris Marchesi 2017-09-24 18:18:31 -07:00
parent f846beecbc
commit edb8e8904c
No known key found for this signature in database
GPG Key ID: 335B84AFEC615CE4
2 changed files with 51 additions and 0 deletions

View File

@ -3,6 +3,7 @@ package validation
import (
"fmt"
"net"
"reflect"
"regexp"
"strings"
@ -105,6 +106,24 @@ func StringLenBetween(min, max int) schema.SchemaValidateFunc {
}
}
// NoZeroValues is a SchemaValidateFunc which tests if the provided value is
// not a zero value. It's useful in situations where you want to catch
// explicit zero values on things like required fields during validation.
func NoZeroValues(i interface{}, k string) (s []string, es []error) {
if reflect.ValueOf(i).Interface() == reflect.Zero(reflect.TypeOf(i)).Interface() {
switch reflect.TypeOf(i).Kind() {
case reflect.String:
es = append(es, fmt.Errorf("%s must not be empty", k))
case reflect.Int, reflect.Float64:
es = append(es, fmt.Errorf("%s must not be zero", k))
default:
// this validator should only ever be applied to TypeString, TypeInt and TypeFloat
panic(fmt.Errorf("can't use NoZeroValues with %T attribute %s", i, k))
}
}
return
}
// CIDRNetwork returns a SchemaValidateFunc which tests if the provided value
// is of type string, is in valid CIDR network notation, and has significant bits between min and max (inclusive)
func CIDRNetwork(min, max int) schema.SchemaValidateFunc {

View File

@ -199,6 +199,38 @@ func TestValidateListUniqueStrings(t *testing.T) {
})
}
func TestValidationNoZeroValues(t *testing.T) {
runTestCases(t, []testCase{
{
val: "foo",
f: NoZeroValues,
},
{
val: 1,
f: NoZeroValues,
},
{
val: float64(1),
f: NoZeroValues,
},
{
val: "",
f: NoZeroValues,
expectedErr: regexp.MustCompile("must not be empty"),
},
{
val: 0,
f: NoZeroValues,
expectedErr: regexp.MustCompile("must not be zero"),
},
{
val: float64(0),
f: NoZeroValues,
expectedErr: regexp.MustCompile("must not be zero"),
},
})
}
func runTestCases(t *testing.T, cases []testCase) {
matchErr := func(errs []error, r *regexp.Regexp) bool {
// err must match one provided