/vendor/github.com/hashicorp/terraform-plugin-sdk/helper/validation/strings.go

https://github.com/terraform-providers/terraform-provider-azurerm · Go · 253 lines · 176 code · 44 blank · 33 comment · 48 complexity · 5ef994a4433d829e16865b5be558a10a MD5 · raw file

  1. package validation
  2. import (
  3. "encoding/base64"
  4. "fmt"
  5. "regexp"
  6. "strings"
  7. "github.com/hashicorp/terraform-plugin-sdk/helper/schema"
  8. "github.com/hashicorp/terraform-plugin-sdk/helper/structure"
  9. )
  10. // StringIsNotEmpty is a ValidateFunc that ensures a string is not empty
  11. func StringIsNotEmpty(i interface{}, k string) ([]string, []error) {
  12. v, ok := i.(string)
  13. if !ok {
  14. return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
  15. }
  16. if v == "" {
  17. return nil, []error{fmt.Errorf("expected %q to not be an empty string, got %v", k, i)}
  18. }
  19. return nil, nil
  20. }
  21. // StringIsNotWhiteSpace is a ValidateFunc that ensures a string is not empty or consisting entirely of whitespace characters
  22. func StringIsNotWhiteSpace(i interface{}, k string) ([]string, []error) {
  23. v, ok := i.(string)
  24. if !ok {
  25. return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
  26. }
  27. if strings.TrimSpace(v) == "" {
  28. return nil, []error{fmt.Errorf("expected %q to not be an empty string or whitespace", k)}
  29. }
  30. return nil, nil
  31. }
  32. // StringIsEmpty is a ValidateFunc that ensures a string has no characters
  33. func StringIsEmpty(i interface{}, k string) ([]string, []error) {
  34. v, ok := i.(string)
  35. if !ok {
  36. return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
  37. }
  38. if v != "" {
  39. return nil, []error{fmt.Errorf("expected %q to be an empty string: got %v", k, v)}
  40. }
  41. return nil, nil
  42. }
  43. // StringIsWhiteSpace is a ValidateFunc that ensures a string is composed of entirely whitespace
  44. func StringIsWhiteSpace(i interface{}, k string) ([]string, []error) {
  45. v, ok := i.(string)
  46. if !ok {
  47. return nil, []error{fmt.Errorf("expected type of %q to be string", k)}
  48. }
  49. if strings.TrimSpace(v) != "" {
  50. return nil, []error{fmt.Errorf("expected %q to be an empty string or whitespace: got %v", k, v)}
  51. }
  52. return nil, nil
  53. }
  54. // StringLenBetween returns a SchemaValidateFunc which tests if the provided value
  55. // is of type string and has length between min and max (inclusive)
  56. func StringLenBetween(min, max int) schema.SchemaValidateFunc {
  57. return func(i interface{}, k string) (warnings []string, errors []error) {
  58. v, ok := i.(string)
  59. if !ok {
  60. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  61. return warnings, errors
  62. }
  63. if len(v) < min || len(v) > max {
  64. errors = append(errors, fmt.Errorf("expected length of %s to be in the range (%d - %d), got %s", k, min, max, v))
  65. }
  66. return warnings, errors
  67. }
  68. }
  69. // StringMatch returns a SchemaValidateFunc which tests if the provided value
  70. // matches a given regexp. Optionally an error message can be provided to
  71. // return something friendlier than "must match some globby regexp".
  72. func StringMatch(r *regexp.Regexp, message string) schema.SchemaValidateFunc {
  73. return func(i interface{}, k string) ([]string, []error) {
  74. v, ok := i.(string)
  75. if !ok {
  76. return nil, []error{fmt.Errorf("expected type of %s to be string", k)}
  77. }
  78. if ok := r.MatchString(v); !ok {
  79. if message != "" {
  80. return nil, []error{fmt.Errorf("invalid value for %s (%s)", k, message)}
  81. }
  82. return nil, []error{fmt.Errorf("expected value of %s to match regular expression %q, got %v", k, r, i)}
  83. }
  84. return nil, nil
  85. }
  86. }
  87. // StringDoesNotMatch returns a SchemaValidateFunc which tests if the provided value
  88. // does not match a given regexp. Optionally an error message can be provided to
  89. // return something friendlier than "must not match some globby regexp".
  90. func StringDoesNotMatch(r *regexp.Regexp, message string) schema.SchemaValidateFunc {
  91. return func(i interface{}, k string) ([]string, []error) {
  92. v, ok := i.(string)
  93. if !ok {
  94. return nil, []error{fmt.Errorf("expected type of %s to be string", k)}
  95. }
  96. if ok := r.MatchString(v); ok {
  97. if message != "" {
  98. return nil, []error{fmt.Errorf("invalid value for %s (%s)", k, message)}
  99. }
  100. return nil, []error{fmt.Errorf("expected value of %s to not match regular expression %q, got %v", k, r, i)}
  101. }
  102. return nil, nil
  103. }
  104. }
  105. // StringInSlice returns a SchemaValidateFunc which tests if the provided value
  106. // is of type string and matches the value of an element in the valid slice
  107. // will test with in lower case if ignoreCase is true
  108. func StringInSlice(valid []string, ignoreCase bool) schema.SchemaValidateFunc {
  109. return func(i interface{}, k string) (warnings []string, errors []error) {
  110. v, ok := i.(string)
  111. if !ok {
  112. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  113. return warnings, errors
  114. }
  115. for _, str := range valid {
  116. if v == str || (ignoreCase && strings.ToLower(v) == strings.ToLower(str)) {
  117. return warnings, errors
  118. }
  119. }
  120. errors = append(errors, fmt.Errorf("expected %s to be one of %v, got %s", k, valid, v))
  121. return warnings, errors
  122. }
  123. }
  124. // StringNotInSlice returns a SchemaValidateFunc which tests if the provided value
  125. // is of type string and does not match the value of any element in the invalid slice
  126. // will test with in lower case if ignoreCase is true
  127. func StringNotInSlice(invalid []string, ignoreCase bool) schema.SchemaValidateFunc {
  128. return func(i interface{}, k string) (warnings []string, errors []error) {
  129. v, ok := i.(string)
  130. if !ok {
  131. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  132. return warnings, errors
  133. }
  134. for _, str := range invalid {
  135. if v == str || (ignoreCase && strings.ToLower(v) == strings.ToLower(str)) {
  136. errors = append(errors, fmt.Errorf("expected %s to not be any of %v, got %s", k, invalid, v))
  137. return warnings, errors
  138. }
  139. }
  140. return warnings, errors
  141. }
  142. }
  143. // StringDoesNotContainAny returns a SchemaValidateFunc which validates that the
  144. // provided value does not contain any of the specified Unicode code points in chars.
  145. func StringDoesNotContainAny(chars string) schema.SchemaValidateFunc {
  146. return func(i interface{}, k string) (warnings []string, errors []error) {
  147. v, ok := i.(string)
  148. if !ok {
  149. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  150. return warnings, errors
  151. }
  152. if strings.ContainsAny(v, chars) {
  153. errors = append(errors, fmt.Errorf("expected value of %s to not contain any of %q, got %v", k, chars, i))
  154. return warnings, errors
  155. }
  156. return warnings, errors
  157. }
  158. }
  159. // StringIsBase64 is a ValidateFunc that ensures a string can be parsed as Base64
  160. func StringIsBase64(i interface{}, k string) (warnings []string, errors []error) {
  161. // Empty string is not allowed
  162. if warnings, errors = StringIsNotEmpty(i, k); len(errors) > 0 {
  163. return
  164. }
  165. // NoEmptyStrings checks it is a string
  166. v, _ := i.(string)
  167. if _, err := base64.StdEncoding.DecodeString(v); err != nil {
  168. errors = append(errors, fmt.Errorf("expected %q to be a base64 string, got %v", k, v))
  169. }
  170. return warnings, errors
  171. }
  172. // ValidateJsonString is a SchemaValidateFunc which tests to make sure the
  173. // supplied string is valid JSON.
  174. //
  175. // Deprecated: use StringIsJSON instead
  176. func ValidateJsonString(i interface{}, k string) (warnings []string, errors []error) {
  177. return StringIsJSON(i, k)
  178. }
  179. // StringIsJSON is a SchemaValidateFunc which tests to make sure the supplied string is valid JSON.
  180. func StringIsJSON(i interface{}, k string) (warnings []string, errors []error) {
  181. v, ok := i.(string)
  182. if !ok {
  183. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  184. return warnings, errors
  185. }
  186. if _, err := structure.NormalizeJsonString(v); err != nil {
  187. errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err))
  188. }
  189. return warnings, errors
  190. }
  191. // ValidateRegexp returns a SchemaValidateFunc which tests to make sure the
  192. // supplied string is a valid regular expression.
  193. //
  194. // Deprecated: use StringIsValidRegExp instead
  195. func ValidateRegexp(i interface{}, k string) (warnings []string, errors []error) {
  196. return StringIsValidRegExp(i, k)
  197. }
  198. // StringIsValidRegExp returns a SchemaValidateFunc which tests to make sure the supplied string is a valid regular expression.
  199. func StringIsValidRegExp(i interface{}, k string) (warnings []string, errors []error) {
  200. v, ok := i.(string)
  201. if !ok {
  202. errors = append(errors, fmt.Errorf("expected type of %s to be string", k))
  203. return warnings, errors
  204. }
  205. if _, err := regexp.Compile(v); err != nil {
  206. errors = append(errors, fmt.Errorf("%q: %s", k, err))
  207. }
  208. return warnings, errors
  209. }