github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/validators_test.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 8 "github.com/aws/aws-sdk-go/service/s3" 9 ) 10 11 func TestValidateEcrRepositoryName(t *testing.T) { 12 validNames := []string{ 13 "nginx-web-app", 14 "project-a/nginx-web-app", 15 "domain.ltd/nginx-web-app", 16 "3chosome-thing.com/01different-pattern", 17 "0123456789/999999999", 18 "double/forward/slash", 19 "000000000000000", 20 } 21 for _, v := range validNames { 22 _, errors := validateEcrRepositoryName(v, "name") 23 if len(errors) != 0 { 24 t.Fatalf("%q should be a valid ECR repository name: %q", v, errors) 25 } 26 } 27 28 invalidNames := []string{ 29 // length > 256 30 "3cho_some-thing.com/01different.-_pattern01different.-_pattern01diff" + 31 "erent.-_pattern01different.-_pattern01different.-_pattern01different" + 32 ".-_pattern01different.-_pattern01different.-_pattern01different.-_pa" + 33 "ttern01different.-_pattern01different.-_pattern234567", 34 // length < 2 35 "i", 36 "special@character", 37 "different+special=character", 38 "double//slash", 39 "double..dot", 40 "/slash-at-the-beginning", 41 "slash-at-the-end/", 42 } 43 for _, v := range invalidNames { 44 _, errors := validateEcrRepositoryName(v, "name") 45 if len(errors) == 0 { 46 t.Fatalf("%q should be an invalid ECR repository name", v) 47 } 48 } 49 } 50 51 func TestValidateCloudWatchEventRuleName(t *testing.T) { 52 validNames := []string{ 53 "HelloWorl_d", 54 "hello-world", 55 "hello.World0125", 56 } 57 for _, v := range validNames { 58 _, errors := validateCloudWatchEventRuleName(v, "name") 59 if len(errors) != 0 { 60 t.Fatalf("%q should be a valid CW event rule name: %q", v, errors) 61 } 62 } 63 64 invalidNames := []string{ 65 "special@character", 66 "slash/in-the-middle", 67 // Length > 64 68 "TooLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName", 69 } 70 for _, v := range invalidNames { 71 _, errors := validateCloudWatchEventRuleName(v, "name") 72 if len(errors) == 0 { 73 t.Fatalf("%q should be an invalid CW event rule name", v) 74 } 75 } 76 } 77 78 func TestValidateLambdaFunctionName(t *testing.T) { 79 validNames := []string{ 80 "arn:aws:lambda:us-west-2:123456789012:function:ThumbNail", 81 "arn:aws-us-gov:lambda:us-west-2:123456789012:function:ThumbNail", 82 "FunctionName", 83 "function-name", 84 } 85 for _, v := range validNames { 86 _, errors := validateLambdaFunctionName(v, "name") 87 if len(errors) != 0 { 88 t.Fatalf("%q should be a valid Lambda function name: %q", v, errors) 89 } 90 } 91 92 invalidNames := []string{ 93 "/FunctionNameWithSlash", 94 "function.name.with.dots", 95 // length > 140 96 "arn:aws:lambda:us-west-2:123456789012:function:TooLoooooo" + 97 "ooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + 98 "ooooooooooooooooongFunctionName", 99 } 100 for _, v := range invalidNames { 101 _, errors := validateLambdaFunctionName(v, "name") 102 if len(errors) == 0 { 103 t.Fatalf("%q should be an invalid Lambda function name", v) 104 } 105 } 106 } 107 108 func TestValidateLambdaQualifier(t *testing.T) { 109 validNames := []string{ 110 "123", 111 "prod", 112 "PROD", 113 "MyTestEnv", 114 "contains-dashes", 115 "contains_underscores", 116 "$LATEST", 117 } 118 for _, v := range validNames { 119 _, errors := validateLambdaQualifier(v, "name") 120 if len(errors) != 0 { 121 t.Fatalf("%q should be a valid Lambda function qualifier: %q", v, errors) 122 } 123 } 124 125 invalidNames := []string{ 126 // No ARNs allowed 127 "arn:aws:lambda:us-west-2:123456789012:function:prod", 128 // length > 128 129 "TooLooooooooooooooooooooooooooooooooooooooooooooooooooo" + 130 "ooooooooooooooooooooooooooooooooooooooooooooooooooo" + 131 "oooooooooooongQualifier", 132 } 133 for _, v := range invalidNames { 134 _, errors := validateLambdaQualifier(v, "name") 135 if len(errors) == 0 { 136 t.Fatalf("%q should be an invalid Lambda function qualifier", v) 137 } 138 } 139 } 140 141 func TestValidateLambdaPermissionAction(t *testing.T) { 142 validNames := []string{ 143 "lambda:*", 144 "lambda:InvokeFunction", 145 "*", 146 } 147 for _, v := range validNames { 148 _, errors := validateLambdaPermissionAction(v, "action") 149 if len(errors) != 0 { 150 t.Fatalf("%q should be a valid Lambda permission action: %q", v, errors) 151 } 152 } 153 154 invalidNames := []string{ 155 "yada", 156 "lambda:123", 157 "*:*", 158 "lambda:Invoke*", 159 } 160 for _, v := range invalidNames { 161 _, errors := validateLambdaPermissionAction(v, "action") 162 if len(errors) == 0 { 163 t.Fatalf("%q should be an invalid Lambda permission action", v) 164 } 165 } 166 } 167 168 func TestValidateAwsAccountId(t *testing.T) { 169 validNames := []string{ 170 "123456789012", 171 "999999999999", 172 } 173 for _, v := range validNames { 174 _, errors := validateAwsAccountId(v, "account_id") 175 if len(errors) != 0 { 176 t.Fatalf("%q should be a valid AWS Account ID: %q", v, errors) 177 } 178 } 179 180 invalidNames := []string{ 181 "12345678901", // too short 182 "1234567890123", // too long 183 "invalid", 184 "x123456789012", 185 } 186 for _, v := range invalidNames { 187 _, errors := validateAwsAccountId(v, "account_id") 188 if len(errors) == 0 { 189 t.Fatalf("%q should be an invalid AWS Account ID", v) 190 } 191 } 192 } 193 194 func TestValidateArn(t *testing.T) { 195 v := "" 196 _, errors := validateArn(v, "arn") 197 if len(errors) != 0 { 198 t.Fatalf("%q should not be validated as an ARN: %q", v, errors) 199 } 200 201 validNames := []string{ 202 "arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment", // Beanstalk 203 "arn:aws:iam::123456789012:user/David", // IAM User 204 "arn:aws:rds:eu-west-1:123456789012:db:mysql-db", // RDS 205 "arn:aws:s3:::my_corporate_bucket/exampleobject.png", // S3 object 206 "arn:aws:events:us-east-1:319201112229:rule/rule_name", // CloudWatch Rule 207 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction", // Lambda function 208 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction:Qualifier", // Lambda func qualifier 209 "arn:aws-us-gov:s3:::corp_bucket/object.png", // GovCloud ARN 210 } 211 for _, v := range validNames { 212 _, errors := validateArn(v, "arn") 213 if len(errors) != 0 { 214 t.Fatalf("%q should be a valid ARN: %q", v, errors) 215 } 216 } 217 218 invalidNames := []string{ 219 "arn", 220 "123456789012", 221 "arn:aws", 222 "arn:aws:logs", 223 "arn:aws:logs:region:*:*", 224 } 225 for _, v := range invalidNames { 226 _, errors := validateArn(v, "arn") 227 if len(errors) == 0 { 228 t.Fatalf("%q should be an invalid ARN", v) 229 } 230 } 231 } 232 233 func TestValidatePolicyStatementId(t *testing.T) { 234 validNames := []string{ 235 "YadaHereAndThere", 236 "Valid-5tatement_Id", 237 "1234", 238 } 239 for _, v := range validNames { 240 _, errors := validatePolicyStatementId(v, "statement_id") 241 if len(errors) != 0 { 242 t.Fatalf("%q should be a valid Statement ID: %q", v, errors) 243 } 244 } 245 246 invalidNames := []string{ 247 "Invalid/StatementId/with/slashes", 248 "InvalidStatementId.with.dots", 249 // length > 100 250 "TooooLoooooooooooooooooooooooooooooooooooooooooooo" + 251 "ooooooooooooooooooooooooooooooooooooooooStatementId", 252 } 253 for _, v := range invalidNames { 254 _, errors := validatePolicyStatementId(v, "statement_id") 255 if len(errors) == 0 { 256 t.Fatalf("%q should be an invalid Statement ID", v) 257 } 258 } 259 } 260 261 func TestValidateCIDRNetworkAddress(t *testing.T) { 262 cases := []struct { 263 CIDR string 264 ExpectedErrSubstr string 265 }{ 266 {"notacidr", `must contain a valid CIDR`}, 267 {"10.0.1.0/16", `must contain a valid network CIDR`}, 268 {"10.0.1.0/24", ``}, 269 } 270 271 for i, tc := range cases { 272 _, errs := validateCIDRNetworkAddress(tc.CIDR, "foo") 273 if tc.ExpectedErrSubstr == "" { 274 if len(errs) != 0 { 275 t.Fatalf("%d/%d: Expected no error, got errs: %#v", 276 i+1, len(cases), errs) 277 } 278 } else { 279 if len(errs) != 1 { 280 t.Fatalf("%d/%d: Expected 1 err containing %q, got %d errs", 281 i+1, len(cases), tc.ExpectedErrSubstr, len(errs)) 282 } 283 if !strings.Contains(errs[0].Error(), tc.ExpectedErrSubstr) { 284 t.Fatalf("%d/%d: Expected err: %q, to include %q", 285 i+1, len(cases), errs[0], tc.ExpectedErrSubstr) 286 } 287 } 288 } 289 } 290 291 func TestValidateHTTPMethod(t *testing.T) { 292 type testCases struct { 293 Value string 294 ErrCount int 295 } 296 297 invalidCases := []testCases{ 298 { 299 Value: "incorrect", 300 ErrCount: 1, 301 }, 302 { 303 Value: "delete", 304 ErrCount: 1, 305 }, 306 } 307 308 for _, tc := range invalidCases { 309 _, errors := validateHTTPMethod(tc.Value, "http_method") 310 if len(errors) != tc.ErrCount { 311 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 312 } 313 } 314 315 validCases := []testCases{ 316 { 317 Value: "ANY", 318 ErrCount: 0, 319 }, 320 { 321 Value: "DELETE", 322 ErrCount: 0, 323 }, 324 { 325 Value: "OPTIONS", 326 ErrCount: 0, 327 }, 328 } 329 330 for _, tc := range validCases { 331 _, errors := validateHTTPMethod(tc.Value, "http_method") 332 if len(errors) != tc.ErrCount { 333 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 334 } 335 } 336 } 337 338 func TestValidateLogMetricFilterName(t *testing.T) { 339 validNames := []string{ 340 "YadaHereAndThere", 341 "Valid-5Metric_Name", 342 "This . is also %% valid@!)+(", 343 "1234", 344 strings.Repeat("W", 512), 345 } 346 for _, v := range validNames { 347 _, errors := validateLogMetricFilterName(v, "name") 348 if len(errors) != 0 { 349 t.Fatalf("%q should be a valid Log Metric Filter Name: %q", v, errors) 350 } 351 } 352 353 invalidNames := []string{ 354 "Here is a name with: colon", 355 "and here is another * invalid name", 356 "*", 357 // length > 512 358 strings.Repeat("W", 513), 359 } 360 for _, v := range invalidNames { 361 _, errors := validateLogMetricFilterName(v, "name") 362 if len(errors) == 0 { 363 t.Fatalf("%q should be an invalid Log Metric Filter Name", v) 364 } 365 } 366 } 367 368 func TestValidateLogMetricTransformationName(t *testing.T) { 369 validNames := []string{ 370 "YadaHereAndThere", 371 "Valid-5Metric_Name", 372 "This . is also %% valid@!)+(", 373 "1234", 374 "", 375 strings.Repeat("W", 255), 376 } 377 for _, v := range validNames { 378 _, errors := validateLogMetricFilterTransformationName(v, "name") 379 if len(errors) != 0 { 380 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 381 } 382 } 383 384 invalidNames := []string{ 385 "Here is a name with: colon", 386 "and here is another * invalid name", 387 "also $ invalid", 388 "*", 389 // length > 255 390 strings.Repeat("W", 256), 391 } 392 for _, v := range invalidNames { 393 _, errors := validateLogMetricFilterTransformationName(v, "name") 394 if len(errors) == 0 { 395 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 396 } 397 } 398 } 399 400 func TestValidateLogGroupName(t *testing.T) { 401 validNames := []string{ 402 "ValidLogGroupName", 403 "ValidLogGroup.Name", 404 "valid/Log-group", 405 "1234", 406 "YadaValid#0123", 407 "Also_valid-name", 408 strings.Repeat("W", 512), 409 } 410 for _, v := range validNames { 411 _, errors := validateLogGroupName(v, "name") 412 if len(errors) != 0 { 413 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 414 } 415 } 416 417 invalidNames := []string{ 418 "Here is a name with: colon", 419 "and here is another * invalid name", 420 "also $ invalid", 421 "This . is also %% invalid@!)+(", 422 "*", 423 "", 424 // length > 512 425 strings.Repeat("W", 513), 426 } 427 for _, v := range invalidNames { 428 _, errors := validateLogGroupName(v, "name") 429 if len(errors) == 0 { 430 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 431 } 432 } 433 } 434 435 func TestValidateS3BucketLifecycleTimestamp(t *testing.T) { 436 validDates := []string{ 437 "2016-01-01", 438 "2006-01-02", 439 } 440 441 for _, v := range validDates { 442 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 443 if len(errors) != 0 { 444 t.Fatalf("%q should be valid date: %q", v, errors) 445 } 446 } 447 448 invalidDates := []string{ 449 "Jan 01 2016", 450 "20160101", 451 } 452 453 for _, v := range invalidDates { 454 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 455 if len(errors) == 0 { 456 t.Fatalf("%q should be invalid date", v) 457 } 458 } 459 } 460 461 func TestValidateS3BucketLifecycleStorageClass(t *testing.T) { 462 validStorageClass := []string{ 463 "STANDARD_IA", 464 "GLACIER", 465 } 466 467 for _, v := range validStorageClass { 468 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 469 if len(errors) != 0 { 470 t.Fatalf("%q should be valid storage class: %q", v, errors) 471 } 472 } 473 474 invalidStorageClass := []string{ 475 "STANDARD", 476 "1234", 477 } 478 for _, v := range invalidStorageClass { 479 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 480 if len(errors) == 0 { 481 t.Fatalf("%q should be invalid storage class", v) 482 } 483 } 484 } 485 486 func TestValidateS3BucketReplicationRuleId(t *testing.T) { 487 validId := []string{ 488 "YadaHereAndThere", 489 "Valid-5Rule_ID", 490 "This . is also %% valid@!)+*(:ID", 491 "1234", 492 strings.Repeat("W", 255), 493 } 494 for _, v := range validId { 495 _, errors := validateS3BucketReplicationRuleId(v, "id") 496 if len(errors) != 0 { 497 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 498 } 499 } 500 501 invalidId := []string{ 502 // length > 255 503 strings.Repeat("W", 256), 504 } 505 for _, v := range invalidId { 506 _, errors := validateS3BucketReplicationRuleId(v, "id") 507 if len(errors) == 0 { 508 t.Fatalf("%q should be an invalid replication configuration rule id", v) 509 } 510 } 511 } 512 513 func TestValidateS3BucketReplicationRulePrefix(t *testing.T) { 514 validId := []string{ 515 "YadaHereAndThere", 516 "Valid-5Rule_ID", 517 "This . is also %% valid@!)+*(:ID", 518 "1234", 519 strings.Repeat("W", 1024), 520 } 521 for _, v := range validId { 522 _, errors := validateS3BucketReplicationRulePrefix(v, "id") 523 if len(errors) != 0 { 524 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 525 } 526 } 527 528 invalidId := []string{ 529 // length > 1024 530 strings.Repeat("W", 1025), 531 } 532 for _, v := range invalidId { 533 _, errors := validateS3BucketReplicationRulePrefix(v, "id") 534 if len(errors) == 0 { 535 t.Fatalf("%q should be an invalid replication configuration rule id", v) 536 } 537 } 538 } 539 540 func TestValidateS3BucketReplicationDestinationStorageClass(t *testing.T) { 541 validStorageClass := []string{ 542 s3.StorageClassStandard, 543 s3.StorageClassStandardIa, 544 s3.StorageClassReducedRedundancy, 545 } 546 547 for _, v := range validStorageClass { 548 _, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class") 549 if len(errors) != 0 { 550 t.Fatalf("%q should be valid storage class: %q", v, errors) 551 } 552 } 553 554 invalidStorageClass := []string{ 555 "FOO", 556 "1234", 557 } 558 for _, v := range invalidStorageClass { 559 _, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class") 560 if len(errors) == 0 { 561 t.Fatalf("%q should be invalid storage class", v) 562 } 563 } 564 } 565 566 func TestValidateS3BucketReplicationRuleStatus(t *testing.T) { 567 validRuleStatuses := []string{ 568 s3.ReplicationRuleStatusEnabled, 569 s3.ReplicationRuleStatusDisabled, 570 } 571 572 for _, v := range validRuleStatuses { 573 _, errors := validateS3BucketReplicationRuleStatus(v, "status") 574 if len(errors) != 0 { 575 t.Fatalf("%q should be valid rule status: %q", v, errors) 576 } 577 } 578 579 invalidRuleStatuses := []string{ 580 "FOO", 581 "1234", 582 } 583 for _, v := range invalidRuleStatuses { 584 _, errors := validateS3BucketReplicationRuleStatus(v, "status") 585 if len(errors) == 0 { 586 t.Fatalf("%q should be invalid rule status", v) 587 } 588 } 589 } 590 591 func TestValidateS3BucketLifecycleRuleId(t *testing.T) { 592 validId := []string{ 593 "YadaHereAndThere", 594 "Valid-5Rule_ID", 595 "This . is also %% valid@!)+*(:ID", 596 "1234", 597 strings.Repeat("W", 255), 598 } 599 for _, v := range validId { 600 _, errors := validateS3BucketLifecycleRuleId(v, "id") 601 if len(errors) != 0 { 602 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 603 } 604 } 605 606 invalidId := []string{ 607 // length > 255 608 strings.Repeat("W", 256), 609 } 610 for _, v := range invalidId { 611 _, errors := validateS3BucketLifecycleRuleId(v, "id") 612 if len(errors) == 0 { 613 t.Fatalf("%q should be an invalid lifecycle rule id", v) 614 } 615 } 616 } 617 618 func TestValidateIntegerInRange(t *testing.T) { 619 validIntegers := []int{-259, 0, 1, 5, 999} 620 min := -259 621 max := 999 622 for _, v := range validIntegers { 623 _, errors := validateIntegerInRange(min, max)(v, "name") 624 if len(errors) != 0 { 625 t.Fatalf("%q should be an integer in range (%d, %d): %q", v, min, max, errors) 626 } 627 } 628 629 invalidIntegers := []int{-260, -99999, 1000, 25678} 630 for _, v := range invalidIntegers { 631 _, errors := validateIntegerInRange(min, max)(v, "name") 632 if len(errors) == 0 { 633 t.Fatalf("%q should be an integer outside range (%d, %d)", v, min, max) 634 } 635 } 636 } 637 638 func TestResourceAWSElastiCacheClusterIdValidation(t *testing.T) { 639 cases := []struct { 640 Value string 641 ErrCount int 642 }{ 643 { 644 Value: "tEsting", 645 ErrCount: 1, 646 }, 647 { 648 Value: "t.sting", 649 ErrCount: 1, 650 }, 651 { 652 Value: "t--sting", 653 ErrCount: 1, 654 }, 655 { 656 Value: "1testing", 657 ErrCount: 1, 658 }, 659 { 660 Value: "testing-", 661 ErrCount: 1, 662 }, 663 { 664 Value: randomString(65), 665 ErrCount: 1, 666 }, 667 } 668 669 for _, tc := range cases { 670 _, errors := validateElastiCacheClusterId(tc.Value, "aws_elasticache_cluster_cluster_id") 671 672 if len(errors) != tc.ErrCount { 673 t.Fatalf("Expected the ElastiCache Cluster cluster_id to trigger a validation error") 674 } 675 } 676 } 677 678 func TestValidateDbEventSubscriptionName(t *testing.T) { 679 validNames := []string{ 680 "valid-name", 681 "valid02-name", 682 "Valid-Name1", 683 } 684 for _, v := range validNames { 685 _, errors := validateDbEventSubscriptionName(v, "name") 686 if len(errors) != 0 { 687 t.Fatalf("%q should be a valid RDS Event Subscription Name: %q", v, errors) 688 } 689 } 690 691 invalidNames := []string{ 692 "Here is a name with: colon", 693 "and here is another * invalid name", 694 "also $ invalid", 695 "This . is also %% invalid@!)+(", 696 "*", 697 "", 698 " ", 699 "_", 700 // length > 255 701 strings.Repeat("W", 256), 702 } 703 for _, v := range invalidNames { 704 _, errors := validateDbEventSubscriptionName(v, "name") 705 if len(errors) == 0 { 706 t.Fatalf("%q should be an invalid RDS Event Subscription Name", v) 707 } 708 } 709 } 710 711 func TestValidateJsonString(t *testing.T) { 712 type testCases struct { 713 Value string 714 ErrCount int 715 } 716 717 invalidCases := []testCases{ 718 { 719 Value: `{0:"1"}`, 720 ErrCount: 1, 721 }, 722 { 723 Value: `{'abc':1}`, 724 ErrCount: 1, 725 }, 726 { 727 Value: `{"def":}`, 728 ErrCount: 1, 729 }, 730 { 731 Value: `{"xyz":[}}`, 732 ErrCount: 1, 733 }, 734 } 735 736 for _, tc := range invalidCases { 737 _, errors := validateJsonString(tc.Value, "json") 738 if len(errors) != tc.ErrCount { 739 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 740 } 741 } 742 743 validCases := []testCases{ 744 { 745 Value: ``, 746 ErrCount: 0, 747 }, 748 { 749 Value: `{}`, 750 ErrCount: 0, 751 }, 752 { 753 Value: `{"abc":["1","2"]}`, 754 ErrCount: 0, 755 }, 756 } 757 758 for _, tc := range validCases { 759 _, errors := validateJsonString(tc.Value, "json") 760 if len(errors) != tc.ErrCount { 761 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 762 } 763 } 764 } 765 766 func TestValidateCloudFormationTemplate(t *testing.T) { 767 type testCases struct { 768 Value string 769 ErrCount int 770 } 771 772 invalidCases := []testCases{ 773 { 774 Value: `{"abc":"`, 775 ErrCount: 1, 776 }, 777 { 778 Value: "abc: [", 779 ErrCount: 1, 780 }, 781 } 782 783 for _, tc := range invalidCases { 784 _, errors := validateCloudFormationTemplate(tc.Value, "template") 785 if len(errors) != tc.ErrCount { 786 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 787 } 788 } 789 790 validCases := []testCases{ 791 { 792 Value: `{"abc":"1"}`, 793 ErrCount: 0, 794 }, 795 { 796 Value: `abc: 1`, 797 ErrCount: 0, 798 }, 799 } 800 801 for _, tc := range validCases { 802 _, errors := validateCloudFormationTemplate(tc.Value, "template") 803 if len(errors) != tc.ErrCount { 804 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 805 } 806 } 807 } 808 809 func TestValidateApiGatewayIntegrationType(t *testing.T) { 810 type testCases struct { 811 Value string 812 ErrCount int 813 } 814 815 invalidCases := []testCases{ 816 { 817 Value: "incorrect", 818 ErrCount: 1, 819 }, 820 { 821 Value: "aws_proxy", 822 ErrCount: 1, 823 }, 824 } 825 826 for _, tc := range invalidCases { 827 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 828 if len(errors) != tc.ErrCount { 829 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 830 } 831 } 832 833 validCases := []testCases{ 834 { 835 Value: "MOCK", 836 ErrCount: 0, 837 }, 838 { 839 Value: "AWS_PROXY", 840 ErrCount: 0, 841 }, 842 } 843 844 for _, tc := range validCases { 845 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 846 if len(errors) != tc.ErrCount { 847 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 848 } 849 } 850 } 851 852 func TestValidateSQSQueueName(t *testing.T) { 853 validNames := []string{ 854 "valid-name", 855 "valid02-name", 856 "Valid-Name1", 857 "_", 858 "-", 859 strings.Repeat("W", 80), 860 } 861 for _, v := range validNames { 862 if errors := validateSQSQueueName(v, "name"); len(errors) > 0 { 863 t.Fatalf("%q should be a valid SQS queue Name", v) 864 } 865 } 866 867 invalidNames := []string{ 868 "Here is a name with: colon", 869 "another * invalid name", 870 "also $ invalid", 871 "This . is also %% invalid@!)+(", 872 "*", 873 "", 874 " ", 875 ".", 876 strings.Repeat("W", 81), // length > 80 877 } 878 for _, v := range invalidNames { 879 if errors := validateSQSQueueName(v, "name"); len(errors) == 0 { 880 t.Fatalf("%q should be an invalid SQS queue Name", v) 881 } 882 } 883 } 884 885 func TestValidateSQSFifoQueueName(t *testing.T) { 886 validNames := []string{ 887 "valid-name.fifo", 888 "valid02-name.fifo", 889 "Valid-Name1.fifo", 890 "_.fifo", 891 "a.fifo", 892 "A.fifo", 893 "9.fifo", 894 "-.fifo", 895 fmt.Sprintf("%s.fifo", strings.Repeat("W", 75)), 896 } 897 for _, v := range validNames { 898 if errors := validateSQSFifoQueueName(v, "name"); len(errors) > 0 { 899 t.Fatalf("%q should be a valid SQS FIFO queue Name: %v", v, errors) 900 } 901 } 902 903 invalidNames := []string{ 904 "Here is a name with: colon", 905 "another * invalid name", 906 "also $ invalid", 907 "This . is also %% invalid@!)+(", 908 ".fifo", 909 "*", 910 "", 911 " ", 912 ".", 913 strings.Repeat("W", 81), // length > 80 914 } 915 for _, v := range invalidNames { 916 if errors := validateSQSFifoQueueName(v, "name"); len(errors) == 0 { 917 t.Fatalf("%q should be an invalid SQS FIFO queue Name: %v", v, errors) 918 } 919 } 920 } 921 922 func TestValidateSNSSubscriptionProtocol(t *testing.T) { 923 validProtocols := []string{ 924 "lambda", 925 "sqs", 926 "sqs", 927 "application", 928 "http", 929 "https", 930 } 931 for _, v := range validProtocols { 932 if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) > 0 { 933 t.Fatalf("%q should be a valid SNS Subscription protocol: %v", v, errors) 934 } 935 } 936 937 invalidProtocols := []string{ 938 "Email", 939 "email", 940 "Email-JSON", 941 "email-json", 942 "SMS", 943 "sms", 944 } 945 for _, v := range invalidProtocols { 946 if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) == 0 { 947 t.Fatalf("%q should be an invalid SNS Subscription protocol: %v", v, errors) 948 } 949 } 950 } 951 952 func TestValidateSecurityRuleType(t *testing.T) { 953 validTypes := []string{ 954 "ingress", 955 "egress", 956 } 957 for _, v := range validTypes { 958 if _, errors := validateSecurityRuleType(v, "type"); len(errors) > 0 { 959 t.Fatalf("%q should be a valid Security Group Rule type: %v", v, errors) 960 } 961 } 962 963 invalidTypes := []string{ 964 "foo", 965 "ingresss", 966 } 967 for _, v := range invalidTypes { 968 if _, errors := validateSecurityRuleType(v, "type"); len(errors) == 0 { 969 t.Fatalf("%q should be an invalid Security Group Rule type: %v", v, errors) 970 } 971 } 972 } 973 974 func TestValidateOnceAWeekWindowFormat(t *testing.T) { 975 cases := []struct { 976 Value string 977 ErrCount int 978 }{ 979 { 980 // once a day window format 981 Value: "04:00-05:00", 982 ErrCount: 1, 983 }, 984 { 985 // invalid day of week 986 Value: "san:04:00-san:05:00", 987 ErrCount: 1, 988 }, 989 { 990 // invalid hour 991 Value: "sun:24:00-san:25:00", 992 ErrCount: 1, 993 }, 994 { 995 // invalid min 996 Value: "sun:04:00-sun:04:60", 997 ErrCount: 1, 998 }, 999 { 1000 // valid format 1001 Value: "sun:04:00-sun:05:00", 1002 ErrCount: 0, 1003 }, 1004 { 1005 // "Sun" can also be used 1006 Value: "Sun:04:00-Sun:05:00", 1007 ErrCount: 0, 1008 }, 1009 { 1010 // valid format 1011 Value: "", 1012 ErrCount: 0, 1013 }, 1014 } 1015 1016 for _, tc := range cases { 1017 _, errors := validateOnceAWeekWindowFormat(tc.Value, "maintenance_window") 1018 1019 if len(errors) != tc.ErrCount { 1020 t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value) 1021 } 1022 } 1023 } 1024 1025 func TestValidateOnceADayWindowFormat(t *testing.T) { 1026 cases := []struct { 1027 Value string 1028 ErrCount int 1029 }{ 1030 { 1031 // once a week window format 1032 Value: "sun:04:00-sun:05:00", 1033 ErrCount: 1, 1034 }, 1035 { 1036 // invalid hour 1037 Value: "24:00-25:00", 1038 ErrCount: 1, 1039 }, 1040 { 1041 // invalid min 1042 Value: "04:00-04:60", 1043 ErrCount: 1, 1044 }, 1045 { 1046 // valid format 1047 Value: "04:00-05:00", 1048 ErrCount: 0, 1049 }, 1050 { 1051 // valid format 1052 Value: "", 1053 ErrCount: 0, 1054 }, 1055 } 1056 1057 for _, tc := range cases { 1058 _, errors := validateOnceADayWindowFormat(tc.Value, "backup_window") 1059 1060 if len(errors) != tc.ErrCount { 1061 t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value) 1062 } 1063 } 1064 } 1065 1066 func TestValidateRoute53RecordType(t *testing.T) { 1067 validTypes := []string{ 1068 "AAAA", 1069 "SOA", 1070 "A", 1071 "TXT", 1072 "CNAME", 1073 "MX", 1074 "NAPTR", 1075 "PTR", 1076 "SPF", 1077 "SRV", 1078 "NS", 1079 } 1080 1081 invalidTypes := []string{ 1082 "a", 1083 "alias", 1084 "SpF", 1085 "Txt", 1086 "AaAA", 1087 } 1088 1089 for _, v := range validTypes { 1090 _, errors := validateRoute53RecordType(v, "route53_record") 1091 if len(errors) != 0 { 1092 t.Fatalf("%q should be a valid Route53 record type: %v", v, errors) 1093 } 1094 } 1095 1096 for _, v := range invalidTypes { 1097 _, errors := validateRoute53RecordType(v, "route53_record") 1098 if len(errors) == 0 { 1099 t.Fatalf("%q should not be a valid Route53 record type", v) 1100 } 1101 } 1102 } 1103 1104 func TestValidateEcsPlacementConstraint(t *testing.T) { 1105 cases := []struct { 1106 constType string 1107 constExpr string 1108 Err bool 1109 }{ 1110 { 1111 constType: "distinctInstance", 1112 constExpr: "", 1113 Err: false, 1114 }, 1115 { 1116 constType: "memberOf", 1117 constExpr: "", 1118 Err: true, 1119 }, 1120 { 1121 constType: "distinctInstance", 1122 constExpr: "expression", 1123 Err: false, 1124 }, 1125 { 1126 constType: "memberOf", 1127 constExpr: "expression", 1128 Err: false, 1129 }, 1130 } 1131 1132 for _, tc := range cases { 1133 if err := validateAwsEcsPlacementConstraint(tc.constType, tc.constExpr); err != nil && !tc.Err { 1134 t.Fatalf("Unexpected validation error for \"%s:%s\": %s", 1135 tc.constType, tc.constExpr, err) 1136 } 1137 1138 } 1139 } 1140 1141 func TestValidateEcsPlacementStrategy(t *testing.T) { 1142 cases := []struct { 1143 stratType string 1144 stratField string 1145 Err bool 1146 }{ 1147 { 1148 stratType: "random", 1149 stratField: "", 1150 Err: false, 1151 }, 1152 { 1153 stratType: "spread", 1154 stratField: "instanceID", 1155 Err: false, 1156 }, 1157 { 1158 stratType: "binpack", 1159 stratField: "cpu", 1160 Err: false, 1161 }, 1162 { 1163 stratType: "binpack", 1164 stratField: "memory", 1165 Err: false, 1166 }, 1167 { 1168 stratType: "binpack", 1169 stratField: "disk", 1170 Err: true, 1171 }, 1172 { 1173 stratType: "fakeType", 1174 stratField: "", 1175 Err: true, 1176 }, 1177 } 1178 1179 for _, tc := range cases { 1180 if err := validateAwsEcsPlacementStrategy(tc.stratType, tc.stratField); err != nil && !tc.Err { 1181 t.Fatalf("Unexpected validation error for \"%s:%s\": %s", 1182 tc.stratType, tc.stratField, err) 1183 } 1184 } 1185 } 1186 1187 func TestValidateStepFunctionActivityName(t *testing.T) { 1188 validTypes := []string{ 1189 "foo", 1190 "FooBar123", 1191 } 1192 1193 invalidTypes := []string{ 1194 strings.Repeat("W", 81), // length > 80 1195 } 1196 1197 for _, v := range validTypes { 1198 _, errors := validateSfnActivityName(v, "name") 1199 if len(errors) != 0 { 1200 t.Fatalf("%q should be a valid Step Function Activity name: %v", v, errors) 1201 } 1202 } 1203 1204 for _, v := range invalidTypes { 1205 _, errors := validateSfnActivityName(v, "name") 1206 if len(errors) == 0 { 1207 t.Fatalf("%q should not be a valid Step Function Activity name", v) 1208 } 1209 } 1210 } 1211 1212 func TestValidateStepFunctionStateMachineDefinition(t *testing.T) { 1213 validDefinitions := []string{ 1214 "foobar", 1215 strings.Repeat("W", 1048576), 1216 } 1217 1218 invalidDefinitions := []string{ 1219 strings.Repeat("W", 1048577), // length > 1048576 1220 } 1221 1222 for _, v := range validDefinitions { 1223 _, errors := validateSfnStateMachineDefinition(v, "definition") 1224 if len(errors) != 0 { 1225 t.Fatalf("%q should be a valid Step Function State Machine definition: %v", v, errors) 1226 } 1227 } 1228 1229 for _, v := range invalidDefinitions { 1230 _, errors := validateSfnStateMachineDefinition(v, "definition") 1231 if len(errors) == 0 { 1232 t.Fatalf("%q should not be a valid Step Function State Machine definition", v) 1233 } 1234 } 1235 } 1236 1237 func TestValidateStepFunctionStateMachineName(t *testing.T) { 1238 validTypes := []string{ 1239 "foo", 1240 "BAR", 1241 "FooBar123", 1242 "FooBar123Baz-_", 1243 } 1244 1245 invalidTypes := []string{ 1246 "foo bar", 1247 "foo<bar>", 1248 "foo{bar}", 1249 "foo[bar]", 1250 "foo*bar", 1251 "foo?bar", 1252 "foo#bar", 1253 "foo%bar", 1254 "foo\bar", 1255 "foo^bar", 1256 "foo|bar", 1257 "foo~bar", 1258 "foo$bar", 1259 "foo&bar", 1260 "foo,bar", 1261 "foo:bar", 1262 "foo;bar", 1263 "foo/bar", 1264 strings.Repeat("W", 81), // length > 80 1265 } 1266 1267 for _, v := range validTypes { 1268 _, errors := validateSfnStateMachineName(v, "name") 1269 if len(errors) != 0 { 1270 t.Fatalf("%q should be a valid Step Function State Machine name: %v", v, errors) 1271 } 1272 } 1273 1274 for _, v := range invalidTypes { 1275 _, errors := validateSfnStateMachineName(v, "name") 1276 if len(errors) == 0 { 1277 t.Fatalf("%q should not be a valid Step Function State Machine name", v) 1278 } 1279 } 1280 } 1281 1282 func TestValidateEmrEbsVolumeType(t *testing.T) { 1283 cases := []struct { 1284 VolType string 1285 ErrCount int 1286 }{ 1287 { 1288 VolType: "gp2", 1289 ErrCount: 0, 1290 }, 1291 { 1292 VolType: "io1", 1293 ErrCount: 0, 1294 }, 1295 { 1296 VolType: "standard", 1297 ErrCount: 0, 1298 }, 1299 { 1300 VolType: "stand", 1301 ErrCount: 1, 1302 }, 1303 { 1304 VolType: "io", 1305 ErrCount: 1, 1306 }, 1307 { 1308 VolType: "gp1", 1309 ErrCount: 1, 1310 }, 1311 { 1312 VolType: "fast-disk", 1313 ErrCount: 1, 1314 }, 1315 } 1316 1317 for _, tc := range cases { 1318 _, errors := validateAwsEmrEbsVolumeType(tc.VolType, "volume") 1319 1320 if len(errors) != tc.ErrCount { 1321 t.Fatalf("Expected %d errors, got %d: %s", tc.ErrCount, len(errors), errors) 1322 } 1323 } 1324 } 1325 1326 func TestValidateAppautoscalingScalableDimension(t *testing.T) { 1327 cases := []struct { 1328 Value string 1329 ErrCount int 1330 }{ 1331 { 1332 Value: "ecs:service:DesiredCount", 1333 ErrCount: 0, 1334 }, 1335 { 1336 Value: "ec2:spot-fleet-request:TargetCapacity", 1337 ErrCount: 0, 1338 }, 1339 { 1340 Value: "ec2:service:DesiredCount", 1341 ErrCount: 1, 1342 }, 1343 { 1344 Value: "ecs:spot-fleet-request:TargetCapacity", 1345 ErrCount: 1, 1346 }, 1347 { 1348 Value: "", 1349 ErrCount: 1, 1350 }, 1351 } 1352 1353 for _, tc := range cases { 1354 _, errors := validateAppautoscalingScalableDimension(tc.Value, "scalable_dimension") 1355 if len(errors) != tc.ErrCount { 1356 t.Fatalf("Scalable Dimension validation failed for value %q: %q", tc.Value, errors) 1357 } 1358 } 1359 } 1360 1361 func TestValidateAppautoscalingServiceNamespace(t *testing.T) { 1362 cases := []struct { 1363 Value string 1364 ErrCount int 1365 }{ 1366 { 1367 Value: "ecs", 1368 ErrCount: 0, 1369 }, 1370 { 1371 Value: "ec2", 1372 ErrCount: 0, 1373 }, 1374 { 1375 Value: "autoscaling", 1376 ErrCount: 1, 1377 }, 1378 { 1379 Value: "s3", 1380 ErrCount: 1, 1381 }, 1382 { 1383 Value: "es", 1384 ErrCount: 1, 1385 }, 1386 { 1387 Value: "", 1388 ErrCount: 1, 1389 }, 1390 } 1391 1392 for _, tc := range cases { 1393 _, errors := validateAppautoscalingServiceNamespace(tc.Value, "service_namespace") 1394 if len(errors) != tc.ErrCount { 1395 t.Fatalf("Service Namespace validation failed for value %q: %q", tc.Value, errors) 1396 } 1397 } 1398 } 1399 1400 func TestValidateDmsEndpointId(t *testing.T) { 1401 validIds := []string{ 1402 "tf-test-endpoint-1", 1403 "tfTestEndpoint", 1404 } 1405 1406 for _, s := range validIds { 1407 _, errors := validateDmsEndpointId(s, "endpoint_id") 1408 if len(errors) > 0 { 1409 t.Fatalf("%q should be a valid endpoint id: %v", s, errors) 1410 } 1411 } 1412 1413 invalidIds := []string{ 1414 "tf_test_endpoint_1", 1415 "tf.test.endpoint.1", 1416 "tf test endpoint 1", 1417 "tf-test-endpoint-1!", 1418 "tf-test-endpoint-1-", 1419 "tf-test-endpoint--1", 1420 "tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1tf-test-endpoint-1", 1421 } 1422 1423 for _, s := range invalidIds { 1424 _, errors := validateDmsEndpointId(s, "endpoint_id") 1425 if len(errors) == 0 { 1426 t.Fatalf("%q should not be a valid endpoint id: %v", s, errors) 1427 } 1428 } 1429 } 1430 1431 func TestValidateDmsCertificateId(t *testing.T) { 1432 validIds := []string{ 1433 "tf-test-certificate-1", 1434 "tfTestEndpoint", 1435 } 1436 1437 for _, s := range validIds { 1438 _, errors := validateDmsCertificateId(s, "certificate_id") 1439 if len(errors) > 0 { 1440 t.Fatalf("%q should be a valid certificate id: %v", s, errors) 1441 } 1442 } 1443 1444 invalidIds := []string{ 1445 "tf_test_certificate_1", 1446 "tf.test.certificate.1", 1447 "tf test certificate 1", 1448 "tf-test-certificate-1!", 1449 "tf-test-certificate-1-", 1450 "tf-test-certificate--1", 1451 "tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1tf-test-certificate-1", 1452 } 1453 1454 for _, s := range invalidIds { 1455 _, errors := validateDmsEndpointId(s, "certificate_id") 1456 if len(errors) == 0 { 1457 t.Fatalf("%q should not be a valid certificate id: %v", s, errors) 1458 } 1459 } 1460 } 1461 1462 func TestValidateDmsReplicationInstanceId(t *testing.T) { 1463 validIds := []string{ 1464 "tf-test-replication-instance-1", 1465 "tfTestReplicaitonInstance", 1466 } 1467 1468 for _, s := range validIds { 1469 _, errors := validateDmsReplicationInstanceId(s, "replicaiton_instance_id") 1470 if len(errors) > 0 { 1471 t.Fatalf("%q should be a valid replication instance id: %v", s, errors) 1472 } 1473 } 1474 1475 invalidIds := []string{ 1476 "tf_test_replication-instance_1", 1477 "tf.test.replication.instance.1", 1478 "tf test replication instance 1", 1479 "tf-test-replication-instance-1!", 1480 "tf-test-replication-instance-1-", 1481 "tf-test-replication-instance--1", 1482 "tf-test-replication-instance-1tf-test-replication-instance-1tf-test-replication-instance-1", 1483 } 1484 1485 for _, s := range invalidIds { 1486 _, errors := validateDmsReplicationInstanceId(s, "replication_instance_id") 1487 if len(errors) == 0 { 1488 t.Fatalf("%q should not be a valid replication instance id: %v", s, errors) 1489 } 1490 } 1491 } 1492 1493 func TestValidateDmsReplicationSubnetGroupId(t *testing.T) { 1494 validIds := []string{ 1495 "tf-test-replication-subnet-group-1", 1496 "tf_test_replication_subnet_group_1", 1497 "tf.test.replication.subnet.group.1", 1498 "tf test replication subnet group 1", 1499 "tfTestReplicationSubnetGroup", 1500 } 1501 1502 for _, s := range validIds { 1503 _, errors := validateDmsReplicationSubnetGroupId(s, "replication_subnet_group_id") 1504 if len(errors) > 0 { 1505 t.Fatalf("%q should be a valid replication subnet group id: %v", s, errors) 1506 } 1507 } 1508 1509 invalidIds := []string{ 1510 "default", 1511 "tf-test-replication-subnet-group-1!", 1512 "tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1tf-test-replication-subnet-group-1", 1513 } 1514 1515 for _, s := range invalidIds { 1516 _, errors := validateDmsReplicationSubnetGroupId(s, "replication_subnet_group_id") 1517 if len(errors) == 0 { 1518 t.Fatalf("%q should not be a valid replication subnet group id: %v", s, errors) 1519 } 1520 } 1521 } 1522 1523 func TestValidateDmsReplicationTaskId(t *testing.T) { 1524 validIds := []string{ 1525 "tf-test-replication-task-1", 1526 "tfTestReplicationTask", 1527 } 1528 1529 for _, s := range validIds { 1530 _, errors := validateDmsReplicationTaskId(s, "replication_task_id") 1531 if len(errors) > 0 { 1532 t.Fatalf("%q should be a valid replication task id: %v", s, errors) 1533 } 1534 } 1535 1536 invalidIds := []string{ 1537 "tf_test_replication_task_1", 1538 "tf.test.replication.task.1", 1539 "tf test replication task 1", 1540 "tf-test-replication-task-1!", 1541 "tf-test-replication-task-1-", 1542 "tf-test-replication-task--1", 1543 "tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1tf-test-replication-task-1", 1544 } 1545 1546 for _, s := range invalidIds { 1547 _, errors := validateDmsReplicationTaskId(s, "replication_task_id") 1548 if len(errors) == 0 { 1549 t.Fatalf("%q should not be a valid replication task id: %v", s, errors) 1550 } 1551 } 1552 }