github.com/mohanarpit/terraform@v0.6.16-0.20160909104007-291f29853544/builtin/providers/aws/validators.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"regexp"
     7  	"time"
     8  
     9  	"github.com/aws/aws-sdk-go/service/s3"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  )
    12  
    13  func validateRdsId(v interface{}, k string) (ws []string, errors []error) {
    14  	value := v.(string)
    15  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    16  		errors = append(errors, fmt.Errorf(
    17  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    18  	}
    19  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    20  		errors = append(errors, fmt.Errorf(
    21  			"first character of %q must be a letter", k))
    22  	}
    23  	if regexp.MustCompile(`--`).MatchString(value) {
    24  		errors = append(errors, fmt.Errorf(
    25  			"%q cannot contain two consecutive hyphens", k))
    26  	}
    27  	if regexp.MustCompile(`-$`).MatchString(value) {
    28  		errors = append(errors, fmt.Errorf(
    29  			"%q cannot end with a hyphen", k))
    30  	}
    31  	return
    32  }
    33  
    34  func validateElastiCacheClusterId(v interface{}, k string) (ws []string, errors []error) {
    35  	value := v.(string)
    36  	if (len(value) < 1) || (len(value) > 20) {
    37  		errors = append(errors, fmt.Errorf(
    38  			"%q must contain from 1 to 20 alphanumeric characters or hyphens", k))
    39  	}
    40  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    41  		errors = append(errors, fmt.Errorf(
    42  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    43  	}
    44  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    45  		errors = append(errors, fmt.Errorf(
    46  			"first character of %q must be a letter", k))
    47  	}
    48  	if regexp.MustCompile(`--`).MatchString(value) {
    49  		errors = append(errors, fmt.Errorf(
    50  			"%q cannot contain two consecutive hyphens", k))
    51  	}
    52  	if regexp.MustCompile(`-$`).MatchString(value) {
    53  		errors = append(errors, fmt.Errorf(
    54  			"%q cannot end with a hyphen", k))
    55  	}
    56  	return
    57  }
    58  
    59  func validateASGScheduleTimestamp(v interface{}, k string) (ws []string, errors []error) {
    60  	value := v.(string)
    61  	_, err := time.Parse(awsAutoscalingScheduleTimeLayout, value)
    62  	if err != nil {
    63  		errors = append(errors, fmt.Errorf(
    64  			"%q cannot be parsed as iso8601 Timestamp Format", value))
    65  	}
    66  
    67  	return
    68  }
    69  
    70  // validateTagFilters confirms the "value" component of a tag filter is one of
    71  // AWS's three allowed types.
    72  func validateTagFilters(v interface{}, k string) (ws []string, errors []error) {
    73  	value := v.(string)
    74  	if value != "KEY_ONLY" && value != "VALUE_ONLY" && value != "KEY_AND_VALUE" {
    75  		errors = append(errors, fmt.Errorf(
    76  			"%q must be one of \"KEY_ONLY\", \"VALUE_ONLY\", or \"KEY_AND_VALUE\"", k))
    77  	}
    78  	return
    79  }
    80  
    81  func validateDbParamGroupName(v interface{}, k string) (ws []string, errors []error) {
    82  	value := v.(string)
    83  	if !regexp.MustCompile(`^[0-9a-z-]+$`).MatchString(value) {
    84  		errors = append(errors, fmt.Errorf(
    85  			"only lowercase alphanumeric characters and hyphens allowed in %q", k))
    86  	}
    87  	if !regexp.MustCompile(`^[a-z]`).MatchString(value) {
    88  		errors = append(errors, fmt.Errorf(
    89  			"first character of %q must be a letter", k))
    90  	}
    91  	if regexp.MustCompile(`--`).MatchString(value) {
    92  		errors = append(errors, fmt.Errorf(
    93  			"%q cannot contain two consecutive hyphens", k))
    94  	}
    95  	if regexp.MustCompile(`-$`).MatchString(value) {
    96  		errors = append(errors, fmt.Errorf(
    97  			"%q cannot end with a hyphen", k))
    98  	}
    99  	if len(value) > 255 {
   100  		errors = append(errors, fmt.Errorf(
   101  			"%q cannot be greater than 255 characters", k))
   102  	}
   103  	return
   104  
   105  }
   106  
   107  func validateStreamViewType(v interface{}, k string) (ws []string, errors []error) {
   108  	value := v.(string)
   109  	viewTypes := map[string]bool{
   110  		"KEYS_ONLY":          true,
   111  		"NEW_IMAGE":          true,
   112  		"OLD_IMAGE":          true,
   113  		"NEW_AND_OLD_IMAGES": true,
   114  	}
   115  
   116  	if !viewTypes[value] {
   117  		errors = append(errors, fmt.Errorf("%q be a valid DynamoDB StreamViewType", k))
   118  	}
   119  	return
   120  }
   121  
   122  func validateElbName(v interface{}, k string) (ws []string, errors []error) {
   123  	value := v.(string)
   124  	if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
   125  		errors = append(errors, fmt.Errorf(
   126  			"only alphanumeric characters and hyphens allowed in %q: %q",
   127  			k, value))
   128  	}
   129  	if len(value) > 32 {
   130  		errors = append(errors, fmt.Errorf(
   131  			"%q cannot be longer than 32 characters: %q", k, value))
   132  	}
   133  	if regexp.MustCompile(`^-`).MatchString(value) {
   134  		errors = append(errors, fmt.Errorf(
   135  			"%q cannot begin with a hyphen: %q", k, value))
   136  	}
   137  	if regexp.MustCompile(`-$`).MatchString(value) {
   138  		errors = append(errors, fmt.Errorf(
   139  			"%q cannot end with a hyphen: %q", k, value))
   140  	}
   141  	return
   142  
   143  }
   144  
   145  func validateEcrRepositoryName(v interface{}, k string) (ws []string, errors []error) {
   146  	value := v.(string)
   147  	if len(value) < 2 {
   148  		errors = append(errors, fmt.Errorf(
   149  			"%q must be at least 2 characters long: %q", k, value))
   150  	}
   151  	if len(value) > 256 {
   152  		errors = append(errors, fmt.Errorf(
   153  			"%q cannot be longer than 256 characters: %q", k, value))
   154  	}
   155  
   156  	// http://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_CreateRepository.html
   157  	pattern := `^(?:[a-z0-9]+(?:[._-][a-z0-9]+)*/)*[a-z0-9]+(?:[._-][a-z0-9]+)*$`
   158  	if !regexp.MustCompile(pattern).MatchString(value) {
   159  		errors = append(errors, fmt.Errorf(
   160  			"%q doesn't comply with restrictions (%q): %q",
   161  			k, pattern, value))
   162  	}
   163  
   164  	return
   165  }
   166  
   167  func validateCloudWatchEventRuleName(v interface{}, k string) (ws []string, errors []error) {
   168  	value := v.(string)
   169  	if len(value) > 64 {
   170  		errors = append(errors, fmt.Errorf(
   171  			"%q cannot be longer than 64 characters: %q", k, value))
   172  	}
   173  
   174  	// http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_PutRule.html
   175  	pattern := `^[\.\-_A-Za-z0-9]+$`
   176  	if !regexp.MustCompile(pattern).MatchString(value) {
   177  		errors = append(errors, fmt.Errorf(
   178  			"%q doesn't comply with restrictions (%q): %q",
   179  			k, pattern, value))
   180  	}
   181  
   182  	return
   183  }
   184  
   185  func validateMaxLength(length int) schema.SchemaValidateFunc {
   186  	return func(v interface{}, k string) (ws []string, errors []error) {
   187  		value := v.(string)
   188  		if len(value) > length {
   189  			errors = append(errors, fmt.Errorf(
   190  				"%q cannot be longer than %d characters: %q", k, length, value))
   191  		}
   192  		return
   193  	}
   194  }
   195  
   196  func validateIntegerInRange(min, max int) schema.SchemaValidateFunc {
   197  	return func(v interface{}, k string) (ws []string, errors []error) {
   198  		value := v.(int)
   199  		if value < min {
   200  			errors = append(errors, fmt.Errorf(
   201  				"%q cannot be lower than %d: %d", k, min, value))
   202  		}
   203  		if value > max {
   204  			errors = append(errors, fmt.Errorf(
   205  				"%q cannot be higher than %d: %d", k, max, value))
   206  		}
   207  		return
   208  	}
   209  }
   210  
   211  func validateCloudWatchEventTargetId(v interface{}, k string) (ws []string, errors []error) {
   212  	value := v.(string)
   213  	if len(value) > 64 {
   214  		errors = append(errors, fmt.Errorf(
   215  			"%q cannot be longer than 64 characters: %q", k, value))
   216  	}
   217  
   218  	// http://docs.aws.amazon.com/AmazonCloudWatchEvents/latest/APIReference/API_Target.html
   219  	pattern := `^[\.\-_A-Za-z0-9]+$`
   220  	if !regexp.MustCompile(pattern).MatchString(value) {
   221  		errors = append(errors, fmt.Errorf(
   222  			"%q doesn't comply with restrictions (%q): %q",
   223  			k, pattern, value))
   224  	}
   225  
   226  	return
   227  }
   228  
   229  func validateLambdaFunctionName(v interface{}, k string) (ws []string, errors []error) {
   230  	value := v.(string)
   231  	if len(value) > 140 {
   232  		errors = append(errors, fmt.Errorf(
   233  			"%q cannot be longer than 140 characters: %q", k, value))
   234  	}
   235  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   236  	pattern := `^(arn:aws:lambda:)?([a-z]{2}-[a-z]+-\d{1}:)?(\d{12}:)?(function:)?([a-zA-Z0-9-_]+)(:(\$LATEST|[a-zA-Z0-9-_]+))?$`
   237  	if !regexp.MustCompile(pattern).MatchString(value) {
   238  		errors = append(errors, fmt.Errorf(
   239  			"%q doesn't comply with restrictions (%q): %q",
   240  			k, pattern, value))
   241  	}
   242  
   243  	return
   244  }
   245  
   246  func validateLambdaQualifier(v interface{}, k string) (ws []string, errors []error) {
   247  	value := v.(string)
   248  	if len(value) > 128 {
   249  		errors = append(errors, fmt.Errorf(
   250  			"%q cannot be longer than 128 characters: %q", k, value))
   251  	}
   252  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   253  	pattern := `^[a-zA-Z0-9$_]+$`
   254  	if !regexp.MustCompile(pattern).MatchString(value) {
   255  		errors = append(errors, fmt.Errorf(
   256  			"%q doesn't comply with restrictions (%q): %q",
   257  			k, pattern, value))
   258  	}
   259  
   260  	return
   261  }
   262  
   263  func validateLambdaPermissionAction(v interface{}, k string) (ws []string, errors []error) {
   264  	value := v.(string)
   265  
   266  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   267  	pattern := `^(lambda:[*]|lambda:[a-zA-Z]+|[*])$`
   268  	if !regexp.MustCompile(pattern).MatchString(value) {
   269  		errors = append(errors, fmt.Errorf(
   270  			"%q doesn't comply with restrictions (%q): %q",
   271  			k, pattern, value))
   272  	}
   273  
   274  	return
   275  }
   276  
   277  func validateAwsAccountId(v interface{}, k string) (ws []string, errors []error) {
   278  	value := v.(string)
   279  
   280  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   281  	pattern := `^\d{12}$`
   282  	if !regexp.MustCompile(pattern).MatchString(value) {
   283  		errors = append(errors, fmt.Errorf(
   284  			"%q doesn't look like AWS Account ID (exactly 12 digits): %q",
   285  			k, value))
   286  	}
   287  
   288  	return
   289  }
   290  
   291  func validateArn(v interface{}, k string) (ws []string, errors []error) {
   292  	value := v.(string)
   293  
   294  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   295  	pattern := `^arn:aws:([a-zA-Z0-9\-])+:([a-z]{2}-[a-z]+-\d{1})?:(\d{12})?:(.*)$`
   296  	if !regexp.MustCompile(pattern).MatchString(value) {
   297  		errors = append(errors, fmt.Errorf(
   298  			"%q doesn't look like a valid ARN (%q): %q",
   299  			k, pattern, value))
   300  	}
   301  
   302  	return
   303  }
   304  
   305  func validatePolicyStatementId(v interface{}, k string) (ws []string, errors []error) {
   306  	value := v.(string)
   307  
   308  	if len(value) > 100 {
   309  		errors = append(errors, fmt.Errorf(
   310  			"%q cannot be longer than 100 characters: %q", k, value))
   311  	}
   312  
   313  	// http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html
   314  	pattern := `^[a-zA-Z0-9-_]+$`
   315  	if !regexp.MustCompile(pattern).MatchString(value) {
   316  		errors = append(errors, fmt.Errorf(
   317  			"%q doesn't look like a valid statement ID (%q): %q",
   318  			k, pattern, value))
   319  	}
   320  
   321  	return
   322  }
   323  
   324  // validateCIDRNetworkAddress ensures that the string value is a valid CIDR that
   325  // represents a network address - it adds an error otherwise
   326  func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) {
   327  	value := v.(string)
   328  	_, ipnet, err := net.ParseCIDR(value)
   329  	if err != nil {
   330  		errors = append(errors, fmt.Errorf(
   331  			"%q must contain a valid CIDR, got error parsing: %s", k, err))
   332  		return
   333  	}
   334  
   335  	if ipnet == nil || value != ipnet.String() {
   336  		errors = append(errors, fmt.Errorf(
   337  			"%q must contain a valid network CIDR, expected %q, got %q",
   338  			k, ipnet, value))
   339  	}
   340  
   341  	return
   342  }
   343  
   344  func validateHTTPMethod(v interface{}, k string) (ws []string, errors []error) {
   345  	value := v.(string)
   346  	if value != "GET" && value != "HEAD" && value != "OPTIONS" && value != "PUT" && value != "POST" && value != "PATCH" && value != "DELETE" {
   347  		errors = append(errors, fmt.Errorf(
   348  			"%q must be one of 'GET', 'HEAD', 'OPTIONS', 'PUT', 'POST', 'PATCH', 'DELETE'", k))
   349  	}
   350  	return
   351  }
   352  
   353  func validateLogMetricFilterName(v interface{}, k string) (ws []string, errors []error) {
   354  	value := v.(string)
   355  
   356  	if len(value) > 512 {
   357  		errors = append(errors, fmt.Errorf(
   358  			"%q cannot be longer than 512 characters: %q", k, value))
   359  	}
   360  
   361  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutMetricFilter.html
   362  	pattern := `^[^:*]+$`
   363  	if !regexp.MustCompile(pattern).MatchString(value) {
   364  		errors = append(errors, fmt.Errorf(
   365  			"%q isn't a valid log metric name (must not contain colon nor asterisk): %q",
   366  			k, value))
   367  	}
   368  
   369  	return
   370  }
   371  
   372  func validateLogMetricFilterTransformationName(v interface{}, k string) (ws []string, errors []error) {
   373  	value := v.(string)
   374  
   375  	if len(value) > 255 {
   376  		errors = append(errors, fmt.Errorf(
   377  			"%q cannot be longer than 255 characters: %q", k, value))
   378  	}
   379  
   380  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_MetricTransformation.html
   381  	pattern := `^[^:*$]*$`
   382  	if !regexp.MustCompile(pattern).MatchString(value) {
   383  		errors = append(errors, fmt.Errorf(
   384  			"%q isn't a valid log metric transformation name (must not contain"+
   385  				" colon, asterisk nor dollar sign): %q",
   386  			k, value))
   387  	}
   388  
   389  	return
   390  }
   391  
   392  func validateLogGroupName(v interface{}, k string) (ws []string, errors []error) {
   393  	value := v.(string)
   394  
   395  	if len(value) > 512 {
   396  		errors = append(errors, fmt.Errorf(
   397  			"%q cannot be longer than 512 characters: %q", k, value))
   398  	}
   399  
   400  	// http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html
   401  	pattern := `^[\.\-_/#A-Za-z0-9]+$`
   402  	if !regexp.MustCompile(pattern).MatchString(value) {
   403  		errors = append(errors, fmt.Errorf(
   404  			"%q isn't a valid log group name (alphanumeric characters, underscores,"+
   405  				" hyphens, slashes, hash signs and dots are allowed): %q",
   406  			k, value))
   407  	}
   408  
   409  	return
   410  }
   411  
   412  func validateS3BucketLifecycleTimestamp(v interface{}, k string) (ws []string, errors []error) {
   413  	value := v.(string)
   414  	_, err := time.Parse(time.RFC3339, fmt.Sprintf("%sT00:00:00Z", value))
   415  	if err != nil {
   416  		errors = append(errors, fmt.Errorf(
   417  			"%q cannot be parsed as RFC3339 Timestamp Format", value))
   418  	}
   419  
   420  	return
   421  }
   422  
   423  func validateS3BucketLifecycleStorageClass(v interface{}, k string) (ws []string, errors []error) {
   424  	value := v.(string)
   425  	if value != s3.TransitionStorageClassStandardIa && value != s3.TransitionStorageClassGlacier {
   426  		errors = append(errors, fmt.Errorf(
   427  			"%q must be one of '%q', '%q'", k, s3.TransitionStorageClassStandardIa, s3.TransitionStorageClassGlacier))
   428  	}
   429  
   430  	return
   431  }
   432  
   433  func validateS3BucketLifecycleRuleId(v interface{}, k string) (ws []string, errors []error) {
   434  	value := v.(string)
   435  	if len(value) > 255 {
   436  		errors = append(errors, fmt.Errorf(
   437  			"%q cannot exceed 255 characters", k))
   438  	}
   439  	return
   440  }
   441  
   442  func validateDbEventSubscriptionName(v interface{}, k string) (ws []string, errors []error) {
   443  	value := v.(string)
   444  	if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) {
   445  		errors = append(errors, fmt.Errorf(
   446  			"only alphanumeric characters and hyphens allowed in %q", k))
   447  	}
   448  	if len(value) > 255 {
   449  		errors = append(errors, fmt.Errorf(
   450  			"%q cannot be longer than 255 characters", k))
   451  	}
   452  	return
   453  }
   454  
   455  func validateApiGatewayIntegrationPassthroughBehavior(v interface{}, k string) (ws []string, errors []error) {
   456  	value := v.(string)
   457  	if value != "WHEN_NO_MATCH" && value != "WHEN_NO_TEMPLATES" && value != "NEVER" {
   458  		errors = append(errors, fmt.Errorf(
   459  			"%q must be one of 'WHEN_NO_MATCH', 'WHEN_NO_TEMPLATES', 'NEVER'", k))
   460  	}
   461  	return
   462  }