github.com/aspring/terraform@v0.8.2-0.20161216122603-6a8619a5db2e/builtin/providers/aws/validators.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"regexp"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/aws/aws-sdk-go/service/s3"
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
    15  	value := v.(string)
    16  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    17  		errors = append(errors, fmt.Errorf(
    18  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    19  	}
    20  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    21  		errors = append(errors, fmt.Errorf(
    22  			"first character of %q must be a letter", k))
    23  	}
    24  	if regexp.MustCompile(`--`).MatchString(value) {
    25  		errors = append(errors, fmt.Errorf(
    26  			"%q cannot contain two consecutive hyphens", k))
    27  	}
    28  	if regexp.MustCompile(`-$`).MatchString(value) {
    29  		errors = append(errors, fmt.Errorf(
    30  			"%q cannot end with a hyphen", k))
    31  	}
    32  	return
    33  }
    34  
    35  func validateElastiCacheClusterId(v interface{}, k string) (ws []string, errors []error) {
    36  	value := v.(string)
    37  	if (len(value) < 1) || (len(value) > 20) {
    38  		errors = append(errors, fmt.Errorf(
    39  			"%q must contain from 1 to 20 alphanumeric characters or hyphens", k))
    40  	}
    41  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    42  		errors = append(errors, fmt.Errorf(
    43  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    44  	}
    45  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    46  		errors = append(errors, fmt.Errorf(
    47  			"first character of %q must be a letter", k))
    48  	}
    49  	if regexp.MustCompile(`--`).MatchString(value) {
    50  		errors = append(errors, fmt.Errorf(
    51  			"%q cannot contain two consecutive hyphens", k))
    52  	}
    53  	if regexp.MustCompile(`-$`).MatchString(value) {
    54  		errors = append(errors, fmt.Errorf(
    55  			"%q cannot end with a hyphen", k))
    56  	}
    57  	return
    58  }
    59  
    60  func validateASGScheduleTimestamp(v interface{}, k string) (ws []string, errors []error) {
    61  	value := v.(string)
    62  	_, err := time.Parse(awsAutoscalingScheduleTimeLayout, value)
    63  	if err != nil {
    64  		errors = append(errors, fmt.Errorf(
    65  			"%q cannot be parsed as iso8601 Timestamp Format", value))
    66  	}
    67  
    68  	return
    69  }
    70  
    71  // validateTagFilters confirms the "value" component of a tag filter is one of
    72  // AWS's three allowed types.
    73  func validateTagFilters(v interface{}, k string) (ws []string, errors []error) {
    74  	value := v.(string)
    75  	if value != "KEY_ONLY" && value != "VALUE_ONLY" && value != "KEY_AND_VALUE" {
    76  		errors = append(errors, fmt.Errorf(
    77  			"%q must be one of \"KEY_ONLY\", \"VALUE_ONLY\", or \"KEY_AND_VALUE\"", k))
    78  	}
    79  	return
    80  }
    81  
    82  func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []error) {
    83  	value := v.(string)
    84  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    85  		errors = append(errors, fmt.Errorf(
    86  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    87  	}
    88  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    89  		errors = append(errors, fmt.Errorf(
    90  			"first character of %q must be a letter", k))
    91  	}
    92  	if regexp.MustCompile(`--`).MatchString(value) {
    93  		errors = append(errors, fmt.Errorf(
    94  			"%q cannot contain two consecutive hyphens", k))
    95  	}
    96  	if regexp.MustCompile(`-$`).MatchString(value) {
    97  		errors = append(errors, fmt.Errorf(
    98  			"%q cannot end with a hyphen", k))
    99  	}
   100  	if len(value) > 255 {
   101  		errors = append(errors, fmt.Errorf(
   102  			"%q cannot be greater than 255 characters", k))
   103  	}
   104  	return
   105  
   106  }
   107  
   108  func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) {
   109  	value := v.(string)
   110  	viewTypes := map[string]bool{
   111  		"KEYS_ONLY":          true,
   112  		"NEW_IMAGE":          true,
   113  		"OLD_IMAGE":          true,
   114  		"NEW_AND_OLD_IMAGES": true,
   115  	}
   116  
   117  	if !viewTypes[value] {
   118  		errors = append(errors, fmt.Errorf("%q be a valid DynamoDB StreamViewType", k))
   119  	}
   120  	return
   121  }
   122  
   123  func validateElbName(v interface{}, k string) (ws []string, errors []error) {
   124  	value := v.(string)
   125  	if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
   126  		errors = append(errors, fmt.Errorf(
   127  			"only alphanumeric characters and hyphens allowed in %q: %q",
   128  			k, value))
   129  	}
   130  	if len(value) > 32 {
   131  		errors = append(errors, fmt.Errorf(
   132  			"%q cannot be longer than 32 characters: %q", k, value))
   133  	}
   134  	if regexp.MustCompile(`^-`).MatchString(value) {
   135  		errors = append(errors, fmt.Errorf(
   136  			"%q cannot begin with a hyphen: %q", k, value))
   137  	}
   138  	if regexp.MustCompile(`-$`).MatchString(value) {
   139  		errors = append(errors, fmt.Errorf(
   140  			"%q cannot end with a hyphen: %q", k, value))
   141  	}
   142  	return
   143  
   144  }
   145  
   146  func validateEcrRepositoryName(v interface{}, k string) (ws []string, errors []error) {
   147  	value := v.(string)
   148  	if len(value) < 2 {
   149  		errors = append(errors, fmt.Errorf(
   150  			"%q must be at least 2 characters long: %q", k, value))
   151  	}
   152  	if len(value) > 256 {
   153  		errors = append(errors, fmt.Errorf(
   154  			"%q cannot be longer than 256 characters: %q", k, value))
   155  	}
   156  
   157  	// http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_CreateRepository.html
   158  	pattern := `^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$`
   159  	if !regexp.MustCompile(pattern).MatchString(value) {
   160  		errors = append(errors, fmt.Errorf(
   161  			"%q doesn't comply with restrictions (%q): %q",
   162  			k, pattern, value))
   163  	}
   164  
   165  	return
   166  }
   167  
   168  func validateCloudWatchEventRuleName(v interface{}, k string) (ws []string, errors []error) {
   169  	value := v.(string)
   170  	if len(value) > 64 {
   171  		errors = append(errors, fmt.Errorf(
   172  			"%q cannot be longer than 64 characters: %q", k, value))
   173  	}
   174  
   175  	// http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_PutRule.html
   176  	pattern := `^[\.\-_A-Za-z0-9]+$`
   177  	if !regexp.MustCompile(pattern).MatchString(value) {
   178  		errors = append(errors, fmt.Errorf(
   179  			"%q doesn't comply with restrictions (%q): %q",
   180  			k, pattern, value))
   181  	}
   182  
   183  	return
   184  }
   185  
   186  func validateMaxLength(length int) schema.SchemaValidateFunc {
   187  	return func(v interface{}, k string) (ws []string, errors []error) {
   188  		value := v.(string)
   189  		if len(value) > length {
   190  			errors = append(errors, fmt.Errorf(
   191  				"%q cannot be longer than %d characters: %q", k, length, value))
   192  		}
   193  		return
   194  	}
   195  }
   196  
   197  func validateIntegerInRange(min, max int) schema.SchemaValidateFunc {
   198  	return func(v interface{}, k string) (ws []string, errors []error) {
   199  		value := v.(int)
   200  		if value < min {
   201  			errors = append(errors, fmt.Errorf(
   202  				"%q cannot be lower than %d: %d", k, min, value))
   203  		}
   204  		if value > max {
   205  			errors = append(errors, fmt.Errorf(
   206  				"%q cannot be higher than %d: %d", k, max, value))
   207  		}
   208  		return
   209  	}
   210  }
   211  
   212  func validateCloudWatchEventTargetId(v interface{}, k string) (ws []string, errors []error) {
   213  	value := v.(string)
   214  	if len(value) > 64 {
   215  		errors = append(errors, fmt.Errorf(
   216  			"%q cannot be longer than 64 characters: %q", k, value))
   217  	}
   218  
   219  	// http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_Target.html
   220  	pattern := `^[\.\-_A-Za-z0-9]+$`
   221  	if !regexp.MustCompile(pattern).MatchString(value) {
   222  		errors = append(errors, fmt.Errorf(
   223  			"%q doesn't comply with restrictions (%q): %q",
   224  			k, pattern, value))
   225  	}
   226  
   227  	return
   228  }
   229  
   230  func validateLambdaFunctionName(v interface{}, k string) (ws []string, errors []error) {
   231  	value := v.(string)
   232  	if len(value) > 140 {
   233  		errors = append(errors, fmt.Errorf(
   234  			"%q cannot be longer than 140 characters: %q", k, value))
   235  	}
   236  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   237  	pattern := `^(arn:aws:lambda:)?([a-z]{2}-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?$`
   238  	if !regexp.MustCompile(pattern).MatchString(value) {
   239  		errors = append(errors, fmt.Errorf(
   240  			"%q doesn't comply with restrictions (%q): %q",
   241  			k, pattern, value))
   242  	}
   243  
   244  	return
   245  }
   246  
   247  func validateLambdaQualifier(v interface{}, k string) (ws []string, errors []error) {
   248  	value := v.(string)
   249  	if len(value) > 128 {
   250  		errors = append(errors, fmt.Errorf(
   251  			"%q cannot be longer than 128 characters: %q", k, value))
   252  	}
   253  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   254  	pattern := `^[a-zA-Z0-9$_]+$`
   255  	if !regexp.MustCompile(pattern).MatchString(value) {
   256  		errors = append(errors, fmt.Errorf(
   257  			"%q doesn't comply with restrictions (%q): %q",
   258  			k, pattern, value))
   259  	}
   260  
   261  	return
   262  }
   263  
   264  func validateLambdaPermissionAction(v interface{}, k string) (ws []string, errors []error) {
   265  	value := v.(string)
   266  
   267  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   268  	pattern := `^(lambda:[*]|lambda:[a-zA-Z]+|[*])$`
   269  	if !regexp.MustCompile(pattern).MatchString(value) {
   270  		errors = append(errors, fmt.Errorf(
   271  			"%q doesn't comply with restrictions (%q): %q",
   272  			k, pattern, value))
   273  	}
   274  
   275  	return
   276  }
   277  
   278  func validateAwsAccountId(v interface{}, k string) (ws []string, errors []error) {
   279  	value := v.(string)
   280  
   281  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   282  	pattern := `^\d{12}$`
   283  	if !regexp.MustCompile(pattern).MatchString(value) {
   284  		errors = append(errors, fmt.Errorf(
   285  			"%q doesn't look like AWS Account ID (exactly 12 digits): %q",
   286  			k, value))
   287  	}
   288  
   289  	return
   290  }
   291  
   292  func validateArn(v interface{}, k string) (ws []string, errors []error) {
   293  	value := v.(string)
   294  
   295  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   296  	pattern := `^arn:aws:([a-zA-Z0-9\-])+:([a-z]{2}-[a-z]+-\d{1})?:(\d{12})?:(.*)$`
   297  	if !regexp.MustCompile(pattern).MatchString(value) {
   298  		errors = append(errors, fmt.Errorf(
   299  			"%q doesn't look like a valid ARN (%q): %q",
   300  			k, pattern, value))
   301  	}
   302  
   303  	return
   304  }
   305  
   306  func validatePolicyStatementId(v interface{}, k string) (ws []string, errors []error) {
   307  	value := v.(string)
   308  
   309  	if len(value) > 100 {
   310  		errors = append(errors, fmt.Errorf(
   311  			"%q cannot be longer than 100 characters: %q", k, value))
   312  	}
   313  
   314  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   315  	pattern := `^[a-zA-Z0-9-_]+$`
   316  	if !regexp.MustCompile(pattern).MatchString(value) {
   317  		errors = append(errors, fmt.Errorf(
   318  			"%q doesn't look like a valid statement ID (%q): %q",
   319  			k, pattern, value))
   320  	}
   321  
   322  	return
   323  }
   324  
   325  // validateCIDRNetworkAddress ensures that the string value is a valid CIDR that
   326  // represents a network address - it adds an error otherwise
   327  func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
   328  	value := v.(string)
   329  	_, ipnet, err := net.ParseCIDR(value)
   330  	if err != nil {
   331  		errors = append(errors, fmt.Errorf(
   332  			"%q must contain a valid CIDR, got error parsing: %s", k, err))
   333  		return
   334  	}
   335  
   336  	if ipnet == nil || value != ipnet.String() {
   337  		errors = append(errors, fmt.Errorf(
   338  			"%q must contain a valid network CIDR, expected %q, got %q",
   339  			k, ipnet, value))
   340  	}
   341  
   342  	return
   343  }
   344  
   345  func validateHTTPMethod(v interface{}, k string) (ws []string, errors []error) {
   346  	value := v.(string)
   347  
   348  	validMethods := map[string]bool{
   349  		"ANY":     true,
   350  		"DELETE":  true,
   351  		"GET":     true,
   352  		"HEAD":    true,
   353  		"OPTIONS": true,
   354  		"PATCH":   true,
   355  		"POST":    true,
   356  		"PUT":     true,
   357  	}
   358  
   359  	if _, ok := validMethods[value]; !ok {
   360  		errors = append(errors, fmt.Errorf(
   361  			"%q contains an invalid method %q. Valid methods are either %q, %q, %q, %q, %q, %q, %q, or %q.",
   362  			k, value, "ANY", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"))
   363  	}
   364  	return
   365  }
   366  
   367  func validateLogMetricFilterName(v interface{}, k string) (ws []string, errors []error) {
   368  	value := v.(string)
   369  
   370  	if len(value) > 512 {
   371  		errors = append(errors, fmt.Errorf(
   372  			"%q cannot be longer than 512 characters: %q", k, value))
   373  	}
   374  
   375  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutMetricFilter.html
   376  	pattern := `^[^:*]+$`
   377  	if !regexp.MustCompile(pattern).MatchString(value) {
   378  		errors = append(errors, fmt.Errorf(
   379  			"%q isn't a valid log metric name (must not contain colon nor asterisk): %q",
   380  			k, value))
   381  	}
   382  
   383  	return
   384  }
   385  
   386  func validateLogMetricFilterTransformationName(v interface{}, k string) (ws []string, errors []error) {
   387  	value := v.(string)
   388  
   389  	if len(value) > 255 {
   390  		errors = append(errors, fmt.Errorf(
   391  			"%q cannot be longer than 255 characters: %q", k, value))
   392  	}
   393  
   394  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_MetricTransformation.html
   395  	pattern := `^[^:*$]*$`
   396  	if !regexp.MustCompile(pattern).MatchString(value) {
   397  		errors = append(errors, fmt.Errorf(
   398  			"%q isn't a valid log metric transformation name (must not contain"+
   399  				" colon, asterisk nor dollar sign): %q",
   400  			k, value))
   401  	}
   402  
   403  	return
   404  }
   405  
   406  func validateLogGroupName(v interface{}, k string) (ws []string, errors []error) {
   407  	value := v.(string)
   408  
   409  	if len(value) > 512 {
   410  		errors = append(errors, fmt.Errorf(
   411  			"%q cannot be longer than 512 characters: %q", k, value))
   412  	}
   413  
   414  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html
   415  	pattern := `^[\.\-_/#A-Za-z0-9]+$`
   416  	if !regexp.MustCompile(pattern).MatchString(value) {
   417  		errors = append(errors, fmt.Errorf(
   418  			"%q isn't a valid log group name (alphanumeric characters, underscores,"+
   419  				" hyphens, slashes, hash signs and dots are allowed): %q",
   420  			k, value))
   421  	}
   422  
   423  	return
   424  }
   425  
   426  func validateS3BucketLifecycleTimestamp(v interface{}, k string) (ws []string, errors []error) {
   427  	value := v.(string)
   428  	_, err := time.Parse(time.RFC3339, fmt.Sprintf("%sT00:00:00Z", value))
   429  	if err != nil {
   430  		errors = append(errors, fmt.Errorf(
   431  			"%q cannot be parsed as RFC3339 Timestamp Format", value))
   432  	}
   433  
   434  	return
   435  }
   436  
   437  func validateS3BucketLifecycleStorageClass(v interface{}, k string) (ws []string, errors []error) {
   438  	value := v.(string)
   439  	if value != s3.TransitionStorageClassStandardIa && value != s3.TransitionStorageClassGlacier {
   440  		errors = append(errors, fmt.Errorf(
   441  			"%q must be one of '%q', '%q'", k, s3.TransitionStorageClassStandardIa, s3.TransitionStorageClassGlacier))
   442  	}
   443  
   444  	return
   445  }
   446  
   447  func validateS3BucketReplicationRuleId(v interface{}, k string) (ws []string, errors []error) {
   448  	value := v.(string)
   449  	if len(value) > 255 {
   450  		errors = append(errors, fmt.Errorf(
   451  			"%q cannot be longer than 255 characters: %q", k, value))
   452  	}
   453  
   454  	return
   455  }
   456  
   457  func validateS3BucketReplicationRulePrefix(v interface{}, k string) (ws []string, errors []error) {
   458  	value := v.(string)
   459  	if len(value) > 1024 {
   460  		errors = append(errors, fmt.Errorf(
   461  			"%q cannot be longer than 1024 characters: %q", k, value))
   462  	}
   463  
   464  	return
   465  }
   466  
   467  func validateS3BucketReplicationDestinationStorageClass(v interface{}, k string) (ws []string, errors []error) {
   468  	value := v.(string)
   469  	if value != s3.StorageClassStandard && value != s3.StorageClassStandardIa && value != s3.StorageClassReducedRedundancy {
   470  		errors = append(errors, fmt.Errorf(
   471  			"%q must be one of '%q', '%q' or '%q'", k, s3.StorageClassStandard, s3.StorageClassStandardIa, s3.StorageClassReducedRedundancy))
   472  	}
   473  
   474  	return
   475  }
   476  
   477  func validateS3BucketReplicationRuleStatus(v interface{}, k string) (ws []string, errors []error) {
   478  	value := v.(string)
   479  	if value != s3.ReplicationRuleStatusEnabled && value != s3.ReplicationRuleStatusDisabled {
   480  		errors = append(errors, fmt.Errorf(
   481  			"%q must be one of '%q' or '%q'", k, s3.ReplicationRuleStatusEnabled, s3.ReplicationRuleStatusDisabled))
   482  	}
   483  
   484  	return
   485  }
   486  
   487  func validateS3BucketLifecycleRuleId(v interface{}, k string) (ws []string, errors []error) {
   488  	value := v.(string)
   489  	if len(value) > 255 {
   490  		errors = append(errors, fmt.Errorf(
   491  			"%q cannot exceed 255 characters", k))
   492  	}
   493  	return
   494  }
   495  
   496  func validateDbEventSubscriptionName(v interface{}, k string) (ws []string, errors []error) {
   497  	value := v.(string)
   498  	if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
   499  		errors = append(errors, fmt.Errorf(
   500  			"only alphanumeric characters and hyphens allowed in %q", k))
   501  	}
   502  	if len(value) > 255 {
   503  		errors = append(errors, fmt.Errorf(
   504  			"%q cannot be longer than 255 characters", k))
   505  	}
   506  	return
   507  }
   508  
   509  func validateApiGatewayIntegrationPassthroughBehavior(v interface{}, k string) (ws []string, errors []error) {
   510  	value := v.(string)
   511  	if value != "WHEN_NO_MATCH" && value != "WHEN_NO_TEMPLATES" && value != "NEVER" {
   512  		errors = append(errors, fmt.Errorf(
   513  			"%q must be one of 'WHEN_NO_MATCH', 'WHEN_NO_TEMPLATES', 'NEVER'", k))
   514  	}
   515  	return
   516  }
   517  
   518  func validateJsonString(v interface{}, k string) (ws []string, errors []error) {
   519  	if _, err := normalizeJsonString(v); err != nil {
   520  		errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err))
   521  	}
   522  	return
   523  }
   524  
   525  func validateApiGatewayIntegrationType(v interface{}, k string) (ws []string, errors []error) {
   526  	value := v.(string)
   527  
   528  	validTypes := map[string]bool{
   529  		"AWS":        true,
   530  		"AWS_PROXY":  true,
   531  		"HTTP":       true,
   532  		"HTTP_PROXY": true,
   533  		"MOCK":       true,
   534  	}
   535  
   536  	if _, ok := validTypes[value]; !ok {
   537  		errors = append(errors, fmt.Errorf(
   538  			"%q contains an invalid integration type %q. Valid types are either %q, %q, %q, %q, or %q.",
   539  			k, value, "AWS", "AWS_PROXY", "HTTP", "HTTP_PROXY", "MOCK"))
   540  	}
   541  	return
   542  }
   543  
   544  func validateApiGatewayIntegrationContentHandling(v interface{}, k string) (ws []string, errors []error) {
   545  	value := v.(string)
   546  
   547  	validTypes := map[string]bool{
   548  		"CONVERT_TO_BINARY": true,
   549  		"CONVERT_TO_TEXT":   true,
   550  	}
   551  
   552  	if _, ok := validTypes[value]; !ok {
   553  		errors = append(errors, fmt.Errorf(
   554  			"%q contains an invalid integration type %q. Valid types are either %q or %q.",
   555  			k, value, "CONVERT_TO_BINARY", "CONVERT_TO_TEXT"))
   556  	}
   557  	return
   558  }
   559  
   560  func validateSQSQueueName(v interface{}, k string) (errors []error) {
   561  	value := v.(string)
   562  	if len(value) > 80 {
   563  		errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k))
   564  	}
   565  
   566  	if !regexp.MustCompile(`^[0-9A-Za-z-_]+$`).MatchString(value) {
   567  		errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k))
   568  	}
   569  	return
   570  }
   571  
   572  func validateSQSFifoQueueName(v interface{}, k string) (errors []error) {
   573  	value := v.(string)
   574  
   575  	if len(value) > 80 {
   576  		errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k))
   577  	}
   578  
   579  	if !regexp.MustCompile(`^[0-9A-Za-z-_.]+$`).MatchString(value) {
   580  		errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k))
   581  	}
   582  
   583  	if regexp.MustCompile(`^[^a-zA-Z0-9-_]`).MatchString(value) {
   584  		errors = append(errors, fmt.Errorf("FIFO queue name must start with one of these characters [a-zA-Z0-9-_]: %v", value))
   585  	}
   586  
   587  	if !regexp.MustCompile(`\.fifo$`).MatchString(value) {
   588  		errors = append(errors, fmt.Errorf("FIFO queue name should ends with \".fifo\": %v", value))
   589  	}
   590  
   591  	return
   592  }
   593  
   594  func validateSNSSubscriptionProtocol(v interface{}, k string) (ws []string, errors []error) {
   595  	value := strings.ToLower(v.(string))
   596  	forbidden := []string{"email", "sms"}
   597  	for _, f := range forbidden {
   598  		if strings.Contains(value, f) {
   599  			errors = append(
   600  				errors,
   601  				fmt.Errorf("Unsupported protocol (%s) for SNS Topic", value),
   602  			)
   603  		}
   604  	}
   605  	return
   606  }