github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/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 if value == "" { 296 return 297 } 298 299 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 300 pattern := `^arn:aws:([a-zA-Z0-9\-])+:([a-z]{2}-[a-z]+-\d{1})?:(\d{12})?:(.*)$` 301 if !regexp.MustCompile(pattern).MatchString(value) { 302 errors = append(errors, fmt.Errorf( 303 "%q doesn't look like a valid ARN (%q): %q", 304 k, pattern, value)) 305 } 306 307 return 308 } 309 310 func validatePolicyStatementId(v interface{}, k string) (ws []string, errors []error) { 311 value := v.(string) 312 313 if len(value) > 100 { 314 errors = append(errors, fmt.Errorf( 315 "%q cannot be longer than 100 characters: %q", k, value)) 316 } 317 318 // http://docs.aws.amazon.com/lambda/latest/dg/API_AddPermission.html 319 pattern := `^[a-zA-Z0-9-_]+$` 320 if !regexp.MustCompile(pattern).MatchString(value) { 321 errors = append(errors, fmt.Errorf( 322 "%q doesn't look like a valid statement ID (%q): %q", 323 k, pattern, value)) 324 } 325 326 return 327 } 328 329 // validateCIDRNetworkAddress ensures that the string value is a valid CIDR that 330 // represents a network address - it adds an error otherwise 331 func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []error) { 332 value := v.(string) 333 _, ipnet, err := net.ParseCIDR(value) 334 if err != nil { 335 errors = append(errors, fmt.Errorf( 336 "%q must contain a valid CIDR, got error parsing: %s", k, err)) 337 return 338 } 339 340 if ipnet == nil || value != ipnet.String() { 341 errors = append(errors, fmt.Errorf( 342 "%q must contain a valid network CIDR, expected %q, got %q", 343 k, ipnet, value)) 344 } 345 346 return 347 } 348 349 func validateHTTPMethod(v interface{}, k string) (ws []string, errors []error) { 350 value := v.(string) 351 352 validMethods := map[string]bool{ 353 "ANY": true, 354 "DELETE": true, 355 "GET": true, 356 "HEAD": true, 357 "OPTIONS": true, 358 "PATCH": true, 359 "POST": true, 360 "PUT": true, 361 } 362 363 if _, ok := validMethods[value]; !ok { 364 errors = append(errors, fmt.Errorf( 365 "%q contains an invalid method %q. Valid methods are either %q, %q, %q, %q, %q, %q, %q, or %q.", 366 k, value, "ANY", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT")) 367 } 368 return 369 } 370 371 func validateLogMetricFilterName(v interface{}, k string) (ws []string, errors []error) { 372 value := v.(string) 373 374 if len(value) > 512 { 375 errors = append(errors, fmt.Errorf( 376 "%q cannot be longer than 512 characters: %q", k, value)) 377 } 378 379 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutMetricFilter.html 380 pattern := `^[^:*]+$` 381 if !regexp.MustCompile(pattern).MatchString(value) { 382 errors = append(errors, fmt.Errorf( 383 "%q isn't a valid log metric name (must not contain colon nor asterisk): %q", 384 k, value)) 385 } 386 387 return 388 } 389 390 func validateLogMetricFilterTransformationName(v interface{}, k string) (ws []string, errors []error) { 391 value := v.(string) 392 393 if len(value) > 255 { 394 errors = append(errors, fmt.Errorf( 395 "%q cannot be longer than 255 characters: %q", k, value)) 396 } 397 398 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_MetricTransformation.html 399 pattern := `^[^:*$]*$` 400 if !regexp.MustCompile(pattern).MatchString(value) { 401 errors = append(errors, fmt.Errorf( 402 "%q isn't a valid log metric transformation name (must not contain"+ 403 " colon, asterisk nor dollar sign): %q", 404 k, value)) 405 } 406 407 return 408 } 409 410 func validateLogGroupName(v interface{}, k string) (ws []string, errors []error) { 411 value := v.(string) 412 413 if len(value) > 512 { 414 errors = append(errors, fmt.Errorf( 415 "%q cannot be longer than 512 characters: %q", k, value)) 416 } 417 418 // http://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_CreateLogGroup.html 419 pattern := `^[\.\-_/#A-Za-z0-9]+$` 420 if !regexp.MustCompile(pattern).MatchString(value) { 421 errors = append(errors, fmt.Errorf( 422 "%q isn't a valid log group name (alphanumeric characters, underscores,"+ 423 " hyphens, slashes, hash signs and dots are allowed): %q", 424 k, value)) 425 } 426 427 return 428 } 429 430 func validateS3BucketLifecycleTimestamp(v interface{}, k string) (ws []string, errors []error) { 431 value := v.(string) 432 _, err := time.Parse(time.RFC3339, fmt.Sprintf("%sT00:00:00Z", value)) 433 if err != nil { 434 errors = append(errors, fmt.Errorf( 435 "%q cannot be parsed as RFC3339 Timestamp Format", value)) 436 } 437 438 return 439 } 440 441 func validateS3BucketLifecycleStorageClass(v interface{}, k string) (ws []string, errors []error) { 442 value := v.(string) 443 if value != s3.TransitionStorageClassStandardIa && value != s3.TransitionStorageClassGlacier { 444 errors = append(errors, fmt.Errorf( 445 "%q must be one of '%q', '%q'", k, s3.TransitionStorageClassStandardIa, s3.TransitionStorageClassGlacier)) 446 } 447 448 return 449 } 450 451 func validateS3BucketReplicationRuleId(v interface{}, k string) (ws []string, errors []error) { 452 value := v.(string) 453 if len(value) > 255 { 454 errors = append(errors, fmt.Errorf( 455 "%q cannot be longer than 255 characters: %q", k, value)) 456 } 457 458 return 459 } 460 461 func validateS3BucketReplicationRulePrefix(v interface{}, k string) (ws []string, errors []error) { 462 value := v.(string) 463 if len(value) > 1024 { 464 errors = append(errors, fmt.Errorf( 465 "%q cannot be longer than 1024 characters: %q", k, value)) 466 } 467 468 return 469 } 470 471 func validateS3BucketReplicationDestinationStorageClass(v interface{}, k string) (ws []string, errors []error) { 472 value := v.(string) 473 if value != s3.StorageClassStandard && value != s3.StorageClassStandardIa && value != s3.StorageClassReducedRedundancy { 474 errors = append(errors, fmt.Errorf( 475 "%q must be one of '%q', '%q' or '%q'", k, s3.StorageClassStandard, s3.StorageClassStandardIa, s3.StorageClassReducedRedundancy)) 476 } 477 478 return 479 } 480 481 func validateS3BucketReplicationRuleStatus(v interface{}, k string) (ws []string, errors []error) { 482 value := v.(string) 483 if value != s3.ReplicationRuleStatusEnabled && value != s3.ReplicationRuleStatusDisabled { 484 errors = append(errors, fmt.Errorf( 485 "%q must be one of '%q' or '%q'", k, s3.ReplicationRuleStatusEnabled, s3.ReplicationRuleStatusDisabled)) 486 } 487 488 return 489 } 490 491 func validateS3BucketLifecycleRuleId(v interface{}, k string) (ws []string, errors []error) { 492 value := v.(string) 493 if len(value) > 255 { 494 errors = append(errors, fmt.Errorf( 495 "%q cannot exceed 255 characters", k)) 496 } 497 return 498 } 499 500 func validateDbEventSubscriptionName(v interface{}, k string) (ws []string, errors []error) { 501 value := v.(string) 502 if !regexp.MustCompile(`^[0-9A-Za-z-]+$`).MatchString(value) { 503 errors = append(errors, fmt.Errorf( 504 "only alphanumeric characters and hyphens allowed in %q", k)) 505 } 506 if len(value) > 255 { 507 errors = append(errors, fmt.Errorf( 508 "%q cannot be longer than 255 characters", k)) 509 } 510 return 511 } 512 513 func validateApiGatewayIntegrationPassthroughBehavior(v interface{}, k string) (ws []string, errors []error) { 514 value := v.(string) 515 if value != "WHEN_NO_MATCH" && value != "WHEN_NO_TEMPLATES" && value != "NEVER" { 516 errors = append(errors, fmt.Errorf( 517 "%q must be one of 'WHEN_NO_MATCH', 'WHEN_NO_TEMPLATES', 'NEVER'", k)) 518 } 519 return 520 } 521 522 func validateJsonString(v interface{}, k string) (ws []string, errors []error) { 523 if _, err := normalizeJsonString(v); err != nil { 524 errors = append(errors, fmt.Errorf("%q contains an invalid JSON: %s", k, err)) 525 } 526 return 527 } 528 529 func validateApiGatewayIntegrationType(v interface{}, k string) (ws []string, errors []error) { 530 value := v.(string) 531 532 validTypes := map[string]bool{ 533 "AWS": true, 534 "AWS_PROXY": true, 535 "HTTP": true, 536 "HTTP_PROXY": true, 537 "MOCK": true, 538 } 539 540 if _, ok := validTypes[value]; !ok { 541 errors = append(errors, fmt.Errorf( 542 "%q contains an invalid integration type %q. Valid types are either %q, %q, %q, %q, or %q.", 543 k, value, "AWS", "AWS_PROXY", "HTTP", "HTTP_PROXY", "MOCK")) 544 } 545 return 546 } 547 548 func validateApiGatewayIntegrationContentHandling(v interface{}, k string) (ws []string, errors []error) { 549 value := v.(string) 550 551 validTypes := map[string]bool{ 552 "CONVERT_TO_BINARY": true, 553 "CONVERT_TO_TEXT": true, 554 } 555 556 if _, ok := validTypes[value]; !ok { 557 errors = append(errors, fmt.Errorf( 558 "%q contains an invalid integration type %q. Valid types are either %q or %q.", 559 k, value, "CONVERT_TO_BINARY", "CONVERT_TO_TEXT")) 560 } 561 return 562 } 563 564 func validateSQSQueueName(v interface{}, k string) (errors []error) { 565 value := v.(string) 566 if len(value) > 80 { 567 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 568 } 569 570 if !regexp.MustCompile(`^[0-9A-Za-z-_]+$`).MatchString(value) { 571 errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k)) 572 } 573 return 574 } 575 576 func validateSQSFifoQueueName(v interface{}, k string) (errors []error) { 577 value := v.(string) 578 579 if len(value) > 80 { 580 errors = append(errors, fmt.Errorf("%q cannot be longer than 80 characters", k)) 581 } 582 583 if !regexp.MustCompile(`^[0-9A-Za-z-_.]+$`).MatchString(value) { 584 errors = append(errors, fmt.Errorf("only alphanumeric characters and hyphens allowed in %q", k)) 585 } 586 587 if regexp.MustCompile(`^[^a-zA-Z0-9-_]`).MatchString(value) { 588 errors = append(errors, fmt.Errorf("FIFO queue name must start with one of these characters [a-zA-Z0-9-_]: %v", value)) 589 } 590 591 if !regexp.MustCompile(`\.fifo$`).MatchString(value) { 592 errors = append(errors, fmt.Errorf("FIFO queue name should ends with \".fifo\": %v", value)) 593 } 594 595 return 596 } 597 598 func validateSNSSubscriptionProtocol(v interface{}, k string) (ws []string, errors []error) { 599 value := strings.ToLower(v.(string)) 600 forbidden := []string{"email", "sms"} 601 for _, f := range forbidden { 602 if strings.Contains(value, f) { 603 errors = append( 604 errors, 605 fmt.Errorf("Unsupported protocol (%s) for SNS Topic", value), 606 ) 607 } 608 } 609 return 610 } 611 612 func validateSecurityRuleType(v interface{}, k string) (ws []string, errors []error) { 613 value := strings.ToLower(v.(string)) 614 615 validTypes := map[string]bool{ 616 "ingress": true, 617 "egress": true, 618 } 619 620 if _, ok := validTypes[value]; !ok { 621 errors = append(errors, fmt.Errorf( 622 "%q contains an invalid Security Group Rule type %q. Valid types are either %q or %q.", 623 k, value, "ingress", "egress")) 624 } 625 return 626 } 627 628 func validateOnceAWeekWindowFormat(v interface{}, k string) (ws []string, errors []error) { 629 // valid time format is "ddd:hh24:mi" 630 validTimeFormat := "(sun|mon|tue|wed|thu|fri|sat):([0-1][0-9]|2[0-3]):([0-5][0-9])" 631 632 value := strings.ToLower(v.(string)) 633 if !regexp.MustCompile(validTimeFormat + "-" + validTimeFormat).MatchString(value) { 634 errors = append(errors, fmt.Errorf( 635 "%q must satisfy the format of \"ddd:hh24:mi-ddd:hh24:mi\".", k)) 636 } 637 return 638 } 639 640 func validateOnceADayWindowFormat(v interface{}, k string) (ws []string, errors []error) { 641 // valid time format is "hh24:mi" 642 validTimeFormat := "([0-1][0-9]|2[0-3]):([0-5][0-9])" 643 644 value := v.(string) 645 if !regexp.MustCompile(validTimeFormat + "-" + validTimeFormat).MatchString(value) { 646 errors = append(errors, fmt.Errorf( 647 "%q must satisfy the format of \"hh24:mi-hh24:mi\".", k)) 648 } 649 return 650 } 651 652 func validateRoute53RecordType(v interface{}, k string) (ws []string, errors []error) { 653 // Valid Record types 654 // SOA, A, TXT, NS, CNAME, MX, NAPTR, PTR, SRV, SPF, AAAA 655 validTypes := map[string]struct{}{ 656 "SOA": {}, 657 "A": {}, 658 "TXT": {}, 659 "NS": {}, 660 "CNAME": {}, 661 "MX": {}, 662 "NAPTR": {}, 663 "PTR": {}, 664 "SRV": {}, 665 "SPF": {}, 666 "AAAA": {}, 667 } 668 669 value := v.(string) 670 if _, ok := validTypes[value]; !ok { 671 errors = append(errors, fmt.Errorf( 672 "%q must be one of [SOA, A, TXT, NS, CNAME, MX, NAPTR, PTR, SRV, SPF, AAAA]", k)) 673 } 674 return 675 }