github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/consul/validators.go (about) 1 package consul 2 3 import ( 4 "fmt" 5 "regexp" 6 "strconv" 7 "time" 8 9 "github.com/hashicorp/errwrap" 10 ) 11 12 // An array of inputs used as typed arguments and converted from their type into 13 // function objects that are dynamically constructed and executed. 14 type validatorInputs []interface{} 15 16 // validateDurationMin is the minimum duration to accept as input 17 type validateDurationMin string 18 19 // validateIntMax is the maximum integer value to accept as input 20 type validateIntMax int 21 22 // validateIntMin is the minimum integer value to accept as input 23 type validateIntMin int 24 25 // validateRegexp is a regexp pattern to use to validate schema input. 26 type validateRegexp string 27 28 // makeValidateionFunc takes the name of the attribute and a list of typed 29 // validator inputs in order to create a validation closure that calls each 30 // validator in serial until either a warning or error is returned from the 31 // first validation function. 32 func makeValidationFunc(name string, validators []interface{}) func(v interface{}, key string) (warnings []string, errors []error) { 33 if len(validators) == 0 { 34 return nil 35 } 36 37 fns := make([]func(v interface{}, key string) (warnings []string, errors []error), 0, len(validators)) 38 for _, v := range validators { 39 switch u := v.(type) { 40 case validateDurationMin: 41 fns = append(fns, validateDurationMinFactory(name, string(u))) 42 case validateIntMax: 43 fns = append(fns, validateIntMaxFactory(name, int(u))) 44 case validateIntMin: 45 fns = append(fns, validateIntMinFactory(name, int(u))) 46 case validateRegexp: 47 fns = append(fns, validateRegexpFactory(name, string(u))) 48 } 49 } 50 51 return func(v interface{}, key string) (warnings []string, errors []error) { 52 for _, fn := range fns { 53 warnings, errors = fn(v, key) 54 if len(warnings) > 0 || len(errors) > 0 { 55 break 56 } 57 } 58 return warnings, errors 59 } 60 } 61 62 func validateDurationMinFactory(name, minDuration string) func(v interface{}, key string) (warnings []string, errors []error) { 63 dMin, err := time.ParseDuration(minDuration) 64 if err != nil { 65 return func(interface{}, string) (warnings []string, errors []error) { 66 return nil, []error{ 67 errwrap.Wrapf(fmt.Sprintf("PROVIDER BUG: duration %q not valid: {{err}}", minDuration), err), 68 } 69 } 70 } 71 72 return func(v interface{}, key string) (warnings []string, errors []error) { 73 d, err := time.ParseDuration(v.(string)) 74 if err != nil { 75 errors = append(errors, errwrap.Wrapf(fmt.Sprintf("Invalid %s specified (%q): {{err}}", name, v.(string)), err)) 76 } 77 78 if d < dMin { 79 errors = append(errors, fmt.Errorf("Invalid %s specified: duration %q less than the required minimum %s", name, v.(string), dMin)) 80 } 81 82 return warnings, errors 83 } 84 } 85 86 func validateIntMaxFactory(name string, max int) func(v interface{}, key string) (warnings []string, errors []error) { 87 return func(v interface{}, key string) (warnings []string, errors []error) { 88 switch u := v.(type) { 89 case string: 90 i, err := strconv.ParseInt(u, 10, 64) 91 if err != nil { 92 errors = append(errors, errwrap.Wrapf(fmt.Sprintf("unable to convert %q to an integer: {{err}}", u), err)) 93 break 94 } 95 96 if i > int64(max) { 97 errors = append(errors, fmt.Errorf("Invalid %s specified: %d more than the required maximum %d", name, v.(int), max)) 98 } 99 case int: 100 if u > max { 101 errors = append(errors, fmt.Errorf("Invalid %s specified: %d more than the required maximum %d", name, v.(int), max)) 102 } 103 default: 104 errors = append(errors, fmt.Errorf("Unsupported type in int max validation: %T", v)) 105 } 106 107 return warnings, errors 108 } 109 } 110 111 func validateIntMinFactory(name string, min int) func(v interface{}, key string) (warnings []string, errors []error) { 112 return func(v interface{}, key string) (warnings []string, errors []error) { 113 switch u := v.(type) { 114 case string: 115 i, err := strconv.ParseInt(u, 10, 64) 116 if err != nil { 117 errors = append(errors, errwrap.Wrapf(fmt.Sprintf("unable to convert %q to an integer: {{err}}", u), err)) 118 break 119 } 120 121 if i < int64(min) { 122 errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) 123 } 124 case int: 125 if u < min { 126 errors = append(errors, fmt.Errorf("Invalid %s specified: %d less than the required minimum %d", name, v.(int), min)) 127 } 128 default: 129 errors = append(errors, fmt.Errorf("Unsupported type in int min validation: %T", v)) 130 } 131 132 return warnings, errors 133 } 134 } 135 136 func validateRegexpFactory(name string, reString string) func(v interface{}, key string) (warnings []string, errors []error) { 137 re := regexp.MustCompile(reString) 138 139 return func(v interface{}, key string) (warnings []string, errors []error) { 140 if !re.MatchString(v.(string)) { 141 errors = append(errors, fmt.Errorf("Invalid %s specified (%q): regexp failed to match string", name, v.(string))) 142 } 143 144 return warnings, errors 145 } 146 }