github.com/greysond/terraform@v0.8.5-0.20170124173113-439b5507bbe9/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 "$LATEST", 115 } 116 for _, v := range validNames { 117 _, errors := validateLambdaQualifier(v, "name") 118 if len(errors) != 0 { 119 t.Fatalf("%q should be a valid Lambda function qualifier: %q", v, errors) 120 } 121 } 122 123 invalidNames := []string{ 124 // No ARNs allowed 125 "arn:aws:lambda:us-west-2:123456789012:function:prod", 126 // length > 128 127 "TooLooooooooooooooooooooooooooooooooooooooooooooooooooo" + 128 "ooooooooooooooooooooooooooooooooooooooooooooooooooo" + 129 "oooooooooooongQualifier", 130 } 131 for _, v := range invalidNames { 132 _, errors := validateLambdaQualifier(v, "name") 133 if len(errors) == 0 { 134 t.Fatalf("%q should be an invalid Lambda function qualifier", v) 135 } 136 } 137 } 138 139 func TestValidateLambdaPermissionAction(t *testing.T) { 140 validNames := []string{ 141 "lambda:*", 142 "lambda:InvokeFunction", 143 "*", 144 } 145 for _, v := range validNames { 146 _, errors := validateLambdaPermissionAction(v, "action") 147 if len(errors) != 0 { 148 t.Fatalf("%q should be a valid Lambda permission action: %q", v, errors) 149 } 150 } 151 152 invalidNames := []string{ 153 "yada", 154 "lambda:123", 155 "*:*", 156 "lambda:Invoke*", 157 } 158 for _, v := range invalidNames { 159 _, errors := validateLambdaPermissionAction(v, "action") 160 if len(errors) == 0 { 161 t.Fatalf("%q should be an invalid Lambda permission action", v) 162 } 163 } 164 } 165 166 func TestValidateAwsAccountId(t *testing.T) { 167 validNames := []string{ 168 "123456789012", 169 "999999999999", 170 } 171 for _, v := range validNames { 172 _, errors := validateAwsAccountId(v, "account_id") 173 if len(errors) != 0 { 174 t.Fatalf("%q should be a valid AWS Account ID: %q", v, errors) 175 } 176 } 177 178 invalidNames := []string{ 179 "12345678901", // too short 180 "1234567890123", // too long 181 "invalid", 182 "x123456789012", 183 } 184 for _, v := range invalidNames { 185 _, errors := validateAwsAccountId(v, "account_id") 186 if len(errors) == 0 { 187 t.Fatalf("%q should be an invalid AWS Account ID", v) 188 } 189 } 190 } 191 192 func TestValidateArn(t *testing.T) { 193 v := "" 194 _, errors := validateArn(v, "arn") 195 if len(errors) != 0 { 196 t.Fatalf("%q should not be validated as an ARN: %q", v, errors) 197 } 198 199 validNames := []string{ 200 "arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment", // Beanstalk 201 "arn:aws:iam::123456789012:user/David", // IAM User 202 "arn:aws:rds:eu-west-1:123456789012:db:mysql-db", // RDS 203 "arn:aws:s3:::my_corporate_bucket/exampleobject.png", // S3 object 204 "arn:aws:events:us-east-1:319201112229:rule/rule_name", // CloudWatch Rule 205 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction", // Lambda function 206 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction:Qualifier", // Lambda func qualifier 207 "arn:aws-us-gov:s3:::corp_bucket/object.png", // GovCloud ARN 208 } 209 for _, v := range validNames { 210 _, errors := validateArn(v, "arn") 211 if len(errors) != 0 { 212 t.Fatalf("%q should be a valid ARN: %q", v, errors) 213 } 214 } 215 216 invalidNames := []string{ 217 "arn", 218 "123456789012", 219 "arn:aws", 220 "arn:aws:logs", 221 "arn:aws:logs:region:*:*", 222 } 223 for _, v := range invalidNames { 224 _, errors := validateArn(v, "arn") 225 if len(errors) == 0 { 226 t.Fatalf("%q should be an invalid ARN", v) 227 } 228 } 229 } 230 231 func TestValidatePolicyStatementId(t *testing.T) { 232 validNames := []string{ 233 "YadaHereAndThere", 234 "Valid-5tatement_Id", 235 "1234", 236 } 237 for _, v := range validNames { 238 _, errors := validatePolicyStatementId(v, "statement_id") 239 if len(errors) != 0 { 240 t.Fatalf("%q should be a valid Statement ID: %q", v, errors) 241 } 242 } 243 244 invalidNames := []string{ 245 "Invalid/StatementId/with/slashes", 246 "InvalidStatementId.with.dots", 247 // length > 100 248 "TooooLoooooooooooooooooooooooooooooooooooooooooooo" + 249 "ooooooooooooooooooooooooooooooooooooooooStatementId", 250 } 251 for _, v := range invalidNames { 252 _, errors := validatePolicyStatementId(v, "statement_id") 253 if len(errors) == 0 { 254 t.Fatalf("%q should be an invalid Statement ID", v) 255 } 256 } 257 } 258 259 func TestValidateCIDRNetworkAddress(t *testing.T) { 260 cases := []struct { 261 CIDR string 262 ExpectedErrSubstr string 263 }{ 264 {"notacidr", `must contain a valid CIDR`}, 265 {"10.0.1.0/16", `must contain a valid network CIDR`}, 266 {"10.0.1.0/24", ``}, 267 } 268 269 for i, tc := range cases { 270 _, errs := validateCIDRNetworkAddress(tc.CIDR, "foo") 271 if tc.ExpectedErrSubstr == "" { 272 if len(errs) != 0 { 273 t.Fatalf("%d/%d: Expected no error, got errs: %#v", 274 i+1, len(cases), errs) 275 } 276 } else { 277 if len(errs) != 1 { 278 t.Fatalf("%d/%d: Expected 1 err containing %q, got %d errs", 279 i+1, len(cases), tc.ExpectedErrSubstr, len(errs)) 280 } 281 if !strings.Contains(errs[0].Error(), tc.ExpectedErrSubstr) { 282 t.Fatalf("%d/%d: Expected err: %q, to include %q", 283 i+1, len(cases), errs[0], tc.ExpectedErrSubstr) 284 } 285 } 286 } 287 } 288 289 func TestValidateHTTPMethod(t *testing.T) { 290 type testCases struct { 291 Value string 292 ErrCount int 293 } 294 295 invalidCases := []testCases{ 296 { 297 Value: "incorrect", 298 ErrCount: 1, 299 }, 300 { 301 Value: "delete", 302 ErrCount: 1, 303 }, 304 } 305 306 for _, tc := range invalidCases { 307 _, errors := validateHTTPMethod(tc.Value, "http_method") 308 if len(errors) != tc.ErrCount { 309 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 310 } 311 } 312 313 validCases := []testCases{ 314 { 315 Value: "ANY", 316 ErrCount: 0, 317 }, 318 { 319 Value: "DELETE", 320 ErrCount: 0, 321 }, 322 { 323 Value: "OPTIONS", 324 ErrCount: 0, 325 }, 326 } 327 328 for _, tc := range validCases { 329 _, errors := validateHTTPMethod(tc.Value, "http_method") 330 if len(errors) != tc.ErrCount { 331 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 332 } 333 } 334 } 335 336 func TestValidateLogMetricFilterName(t *testing.T) { 337 validNames := []string{ 338 "YadaHereAndThere", 339 "Valid-5Metric_Name", 340 "This . is also %% valid@!)+(", 341 "1234", 342 strings.Repeat("W", 512), 343 } 344 for _, v := range validNames { 345 _, errors := validateLogMetricFilterName(v, "name") 346 if len(errors) != 0 { 347 t.Fatalf("%q should be a valid Log Metric Filter Name: %q", v, errors) 348 } 349 } 350 351 invalidNames := []string{ 352 "Here is a name with: colon", 353 "and here is another * invalid name", 354 "*", 355 // length > 512 356 strings.Repeat("W", 513), 357 } 358 for _, v := range invalidNames { 359 _, errors := validateLogMetricFilterName(v, "name") 360 if len(errors) == 0 { 361 t.Fatalf("%q should be an invalid Log Metric Filter Name", v) 362 } 363 } 364 } 365 366 func TestValidateLogMetricTransformationName(t *testing.T) { 367 validNames := []string{ 368 "YadaHereAndThere", 369 "Valid-5Metric_Name", 370 "This . is also %% valid@!)+(", 371 "1234", 372 "", 373 strings.Repeat("W", 255), 374 } 375 for _, v := range validNames { 376 _, errors := validateLogMetricFilterTransformationName(v, "name") 377 if len(errors) != 0 { 378 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 379 } 380 } 381 382 invalidNames := []string{ 383 "Here is a name with: colon", 384 "and here is another * invalid name", 385 "also $ invalid", 386 "*", 387 // length > 255 388 strings.Repeat("W", 256), 389 } 390 for _, v := range invalidNames { 391 _, errors := validateLogMetricFilterTransformationName(v, "name") 392 if len(errors) == 0 { 393 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 394 } 395 } 396 } 397 398 func TestValidateLogGroupName(t *testing.T) { 399 validNames := []string{ 400 "ValidLogGroupName", 401 "ValidLogGroup.Name", 402 "valid/Log-group", 403 "1234", 404 "YadaValid#0123", 405 "Also_valid-name", 406 strings.Repeat("W", 512), 407 } 408 for _, v := range validNames { 409 _, errors := validateLogGroupName(v, "name") 410 if len(errors) != 0 { 411 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 412 } 413 } 414 415 invalidNames := []string{ 416 "Here is a name with: colon", 417 "and here is another * invalid name", 418 "also $ invalid", 419 "This . is also %% invalid@!)+(", 420 "*", 421 "", 422 // length > 512 423 strings.Repeat("W", 513), 424 } 425 for _, v := range invalidNames { 426 _, errors := validateLogGroupName(v, "name") 427 if len(errors) == 0 { 428 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 429 } 430 } 431 } 432 433 func TestValidateS3BucketLifecycleTimestamp(t *testing.T) { 434 validDates := []string{ 435 "2016-01-01", 436 "2006-01-02", 437 } 438 439 for _, v := range validDates { 440 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 441 if len(errors) != 0 { 442 t.Fatalf("%q should be valid date: %q", v, errors) 443 } 444 } 445 446 invalidDates := []string{ 447 "Jan 01 2016", 448 "20160101", 449 } 450 451 for _, v := range invalidDates { 452 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 453 if len(errors) == 0 { 454 t.Fatalf("%q should be invalid date", v) 455 } 456 } 457 } 458 459 func TestValidateS3BucketLifecycleStorageClass(t *testing.T) { 460 validStorageClass := []string{ 461 "STANDARD_IA", 462 "GLACIER", 463 } 464 465 for _, v := range validStorageClass { 466 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 467 if len(errors) != 0 { 468 t.Fatalf("%q should be valid storage class: %q", v, errors) 469 } 470 } 471 472 invalidStorageClass := []string{ 473 "STANDARD", 474 "1234", 475 } 476 for _, v := range invalidStorageClass { 477 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 478 if len(errors) == 0 { 479 t.Fatalf("%q should be invalid storage class", v) 480 } 481 } 482 } 483 484 func TestValidateS3BucketReplicationRuleId(t *testing.T) { 485 validId := []string{ 486 "YadaHereAndThere", 487 "Valid-5Rule_ID", 488 "This . is also %% valid@!)+*(:ID", 489 "1234", 490 strings.Repeat("W", 255), 491 } 492 for _, v := range validId { 493 _, errors := validateS3BucketReplicationRuleId(v, "id") 494 if len(errors) != 0 { 495 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 496 } 497 } 498 499 invalidId := []string{ 500 // length > 255 501 strings.Repeat("W", 256), 502 } 503 for _, v := range invalidId { 504 _, errors := validateS3BucketReplicationRuleId(v, "id") 505 if len(errors) == 0 { 506 t.Fatalf("%q should be an invalid replication configuration rule id", v) 507 } 508 } 509 } 510 511 func TestValidateS3BucketReplicationRulePrefix(t *testing.T) { 512 validId := []string{ 513 "YadaHereAndThere", 514 "Valid-5Rule_ID", 515 "This . is also %% valid@!)+*(:ID", 516 "1234", 517 strings.Repeat("W", 1024), 518 } 519 for _, v := range validId { 520 _, errors := validateS3BucketReplicationRulePrefix(v, "id") 521 if len(errors) != 0 { 522 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 523 } 524 } 525 526 invalidId := []string{ 527 // length > 1024 528 strings.Repeat("W", 1025), 529 } 530 for _, v := range invalidId { 531 _, errors := validateS3BucketReplicationRulePrefix(v, "id") 532 if len(errors) == 0 { 533 t.Fatalf("%q should be an invalid replication configuration rule id", v) 534 } 535 } 536 } 537 538 func TestValidateS3BucketReplicationDestinationStorageClass(t *testing.T) { 539 validStorageClass := []string{ 540 s3.StorageClassStandard, 541 s3.StorageClassStandardIa, 542 s3.StorageClassReducedRedundancy, 543 } 544 545 for _, v := range validStorageClass { 546 _, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class") 547 if len(errors) != 0 { 548 t.Fatalf("%q should be valid storage class: %q", v, errors) 549 } 550 } 551 552 invalidStorageClass := []string{ 553 "FOO", 554 "1234", 555 } 556 for _, v := range invalidStorageClass { 557 _, errors := validateS3BucketReplicationDestinationStorageClass(v, "storage_class") 558 if len(errors) == 0 { 559 t.Fatalf("%q should be invalid storage class", v) 560 } 561 } 562 } 563 564 func TestValidateS3BucketReplicationRuleStatus(t *testing.T) { 565 validRuleStatuses := []string{ 566 s3.ReplicationRuleStatusEnabled, 567 s3.ReplicationRuleStatusDisabled, 568 } 569 570 for _, v := range validRuleStatuses { 571 _, errors := validateS3BucketReplicationRuleStatus(v, "status") 572 if len(errors) != 0 { 573 t.Fatalf("%q should be valid rule status: %q", v, errors) 574 } 575 } 576 577 invalidRuleStatuses := []string{ 578 "FOO", 579 "1234", 580 } 581 for _, v := range invalidRuleStatuses { 582 _, errors := validateS3BucketReplicationRuleStatus(v, "status") 583 if len(errors) == 0 { 584 t.Fatalf("%q should be invalid rule status", v) 585 } 586 } 587 } 588 589 func TestValidateS3BucketLifecycleRuleId(t *testing.T) { 590 validId := []string{ 591 "YadaHereAndThere", 592 "Valid-5Rule_ID", 593 "This . is also %% valid@!)+*(:ID", 594 "1234", 595 strings.Repeat("W", 255), 596 } 597 for _, v := range validId { 598 _, errors := validateS3BucketLifecycleRuleId(v, "id") 599 if len(errors) != 0 { 600 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 601 } 602 } 603 604 invalidId := []string{ 605 // length > 255 606 strings.Repeat("W", 256), 607 } 608 for _, v := range invalidId { 609 _, errors := validateS3BucketLifecycleRuleId(v, "id") 610 if len(errors) == 0 { 611 t.Fatalf("%q should be an invalid lifecycle rule id", v) 612 } 613 } 614 } 615 616 func TestValidateIntegerInRange(t *testing.T) { 617 validIntegers := []int{-259, 0, 1, 5, 999} 618 min := -259 619 max := 999 620 for _, v := range validIntegers { 621 _, errors := validateIntegerInRange(min, max)(v, "name") 622 if len(errors) != 0 { 623 t.Fatalf("%q should be an integer in range (%d, %d): %q", v, min, max, errors) 624 } 625 } 626 627 invalidIntegers := []int{-260, -99999, 1000, 25678} 628 for _, v := range invalidIntegers { 629 _, errors := validateIntegerInRange(min, max)(v, "name") 630 if len(errors) == 0 { 631 t.Fatalf("%q should be an integer outside range (%d, %d)", v, min, max) 632 } 633 } 634 } 635 636 func TestResourceAWSElastiCacheClusterIdValidation(t *testing.T) { 637 cases := []struct { 638 Value string 639 ErrCount int 640 }{ 641 { 642 Value: "tEsting", 643 ErrCount: 1, 644 }, 645 { 646 Value: "t.sting", 647 ErrCount: 1, 648 }, 649 { 650 Value: "t--sting", 651 ErrCount: 1, 652 }, 653 { 654 Value: "1testing", 655 ErrCount: 1, 656 }, 657 { 658 Value: "testing-", 659 ErrCount: 1, 660 }, 661 { 662 Value: randomString(65), 663 ErrCount: 1, 664 }, 665 } 666 667 for _, tc := range cases { 668 _, errors := validateElastiCacheClusterId(tc.Value, "aws_elasticache_cluster_cluster_id") 669 670 if len(errors) != tc.ErrCount { 671 t.Fatalf("Expected the ElastiCache Cluster cluster_id to trigger a validation error") 672 } 673 } 674 } 675 676 func TestValidateDbEventSubscriptionName(t *testing.T) { 677 validNames := []string{ 678 "valid-name", 679 "valid02-name", 680 "Valid-Name1", 681 } 682 for _, v := range validNames { 683 _, errors := validateDbEventSubscriptionName(v, "name") 684 if len(errors) != 0 { 685 t.Fatalf("%q should be a valid RDS Event Subscription Name: %q", v, errors) 686 } 687 } 688 689 invalidNames := []string{ 690 "Here is a name with: colon", 691 "and here is another * invalid name", 692 "also $ invalid", 693 "This . is also %% invalid@!)+(", 694 "*", 695 "", 696 " ", 697 "_", 698 // length > 255 699 strings.Repeat("W", 256), 700 } 701 for _, v := range invalidNames { 702 _, errors := validateDbEventSubscriptionName(v, "name") 703 if len(errors) == 0 { 704 t.Fatalf("%q should be an invalid RDS Event Subscription Name", v) 705 } 706 } 707 } 708 709 func TestValidateJsonString(t *testing.T) { 710 type testCases struct { 711 Value string 712 ErrCount int 713 } 714 715 invalidCases := []testCases{ 716 { 717 Value: `{0:"1"}`, 718 ErrCount: 1, 719 }, 720 { 721 Value: `{'abc':1}`, 722 ErrCount: 1, 723 }, 724 { 725 Value: `{"def":}`, 726 ErrCount: 1, 727 }, 728 { 729 Value: `{"xyz":[}}`, 730 ErrCount: 1, 731 }, 732 } 733 734 for _, tc := range invalidCases { 735 _, errors := validateJsonString(tc.Value, "json") 736 if len(errors) != tc.ErrCount { 737 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 738 } 739 } 740 741 validCases := []testCases{ 742 { 743 Value: ``, 744 ErrCount: 0, 745 }, 746 { 747 Value: `{}`, 748 ErrCount: 0, 749 }, 750 { 751 Value: `{"abc":["1","2"]}`, 752 ErrCount: 0, 753 }, 754 } 755 756 for _, tc := range validCases { 757 _, errors := validateJsonString(tc.Value, "json") 758 if len(errors) != tc.ErrCount { 759 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 760 } 761 } 762 } 763 764 func TestValidateCloudFormationTemplate(t *testing.T) { 765 type testCases struct { 766 Value string 767 ErrCount int 768 } 769 770 invalidCases := []testCases{ 771 { 772 Value: `{"abc":"`, 773 ErrCount: 1, 774 }, 775 { 776 Value: "abc: [", 777 ErrCount: 1, 778 }, 779 } 780 781 for _, tc := range invalidCases { 782 _, errors := validateCloudFormationTemplate(tc.Value, "template") 783 if len(errors) != tc.ErrCount { 784 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 785 } 786 } 787 788 validCases := []testCases{ 789 { 790 Value: `{"abc":"1"}`, 791 ErrCount: 0, 792 }, 793 { 794 Value: `abc: 1`, 795 ErrCount: 0, 796 }, 797 } 798 799 for _, tc := range validCases { 800 _, errors := validateCloudFormationTemplate(tc.Value, "template") 801 if len(errors) != tc.ErrCount { 802 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 803 } 804 } 805 } 806 807 func TestValidateApiGatewayIntegrationType(t *testing.T) { 808 type testCases struct { 809 Value string 810 ErrCount int 811 } 812 813 invalidCases := []testCases{ 814 { 815 Value: "incorrect", 816 ErrCount: 1, 817 }, 818 { 819 Value: "aws_proxy", 820 ErrCount: 1, 821 }, 822 } 823 824 for _, tc := range invalidCases { 825 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 826 if len(errors) != tc.ErrCount { 827 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 828 } 829 } 830 831 validCases := []testCases{ 832 { 833 Value: "MOCK", 834 ErrCount: 0, 835 }, 836 { 837 Value: "AWS_PROXY", 838 ErrCount: 0, 839 }, 840 } 841 842 for _, tc := range validCases { 843 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 844 if len(errors) != tc.ErrCount { 845 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 846 } 847 } 848 } 849 850 func TestValidateSQSQueueName(t *testing.T) { 851 validNames := []string{ 852 "valid-name", 853 "valid02-name", 854 "Valid-Name1", 855 "_", 856 "-", 857 strings.Repeat("W", 80), 858 } 859 for _, v := range validNames { 860 if errors := validateSQSQueueName(v, "name"); len(errors) > 0 { 861 t.Fatalf("%q should be a valid SQS queue Name", v) 862 } 863 } 864 865 invalidNames := []string{ 866 "Here is a name with: colon", 867 "another * invalid name", 868 "also $ invalid", 869 "This . is also %% invalid@!)+(", 870 "*", 871 "", 872 " ", 873 ".", 874 strings.Repeat("W", 81), // length > 80 875 } 876 for _, v := range invalidNames { 877 if errors := validateSQSQueueName(v, "name"); len(errors) == 0 { 878 t.Fatalf("%q should be an invalid SQS queue Name", v) 879 } 880 } 881 } 882 883 func TestValidateSQSFifoQueueName(t *testing.T) { 884 validNames := []string{ 885 "valid-name.fifo", 886 "valid02-name.fifo", 887 "Valid-Name1.fifo", 888 "_.fifo", 889 "a.fifo", 890 "A.fifo", 891 "9.fifo", 892 "-.fifo", 893 fmt.Sprintf("%s.fifo", strings.Repeat("W", 75)), 894 } 895 for _, v := range validNames { 896 if errors := validateSQSFifoQueueName(v, "name"); len(errors) > 0 { 897 t.Fatalf("%q should be a valid SQS FIFO queue Name: %v", v, errors) 898 } 899 } 900 901 invalidNames := []string{ 902 "Here is a name with: colon", 903 "another * invalid name", 904 "also $ invalid", 905 "This . is also %% invalid@!)+(", 906 ".fifo", 907 "*", 908 "", 909 " ", 910 ".", 911 strings.Repeat("W", 81), // length > 80 912 } 913 for _, v := range invalidNames { 914 if errors := validateSQSFifoQueueName(v, "name"); len(errors) == 0 { 915 t.Fatalf("%q should be an invalid SQS FIFO queue Name: %v", v, errors) 916 } 917 } 918 } 919 920 func TestValidateSNSSubscriptionProtocol(t *testing.T) { 921 validProtocols := []string{ 922 "lambda", 923 "sqs", 924 "sqs", 925 "application", 926 "http", 927 "https", 928 } 929 for _, v := range validProtocols { 930 if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) > 0 { 931 t.Fatalf("%q should be a valid SNS Subscription protocol: %v", v, errors) 932 } 933 } 934 935 invalidProtocols := []string{ 936 "Email", 937 "email", 938 "Email-JSON", 939 "email-json", 940 "SMS", 941 "sms", 942 } 943 for _, v := range invalidProtocols { 944 if _, errors := validateSNSSubscriptionProtocol(v, "protocol"); len(errors) == 0 { 945 t.Fatalf("%q should be an invalid SNS Subscription protocol: %v", v, errors) 946 } 947 } 948 } 949 950 func TestValidateSecurityRuleType(t *testing.T) { 951 validTypes := []string{ 952 "ingress", 953 "egress", 954 } 955 for _, v := range validTypes { 956 if _, errors := validateSecurityRuleType(v, "type"); len(errors) > 0 { 957 t.Fatalf("%q should be a valid Security Group Rule type: %v", v, errors) 958 } 959 } 960 961 invalidTypes := []string{ 962 "foo", 963 "ingresss", 964 } 965 for _, v := range invalidTypes { 966 if _, errors := validateSecurityRuleType(v, "type"); len(errors) == 0 { 967 t.Fatalf("%q should be an invalid Security Group Rule type: %v", v, errors) 968 } 969 } 970 } 971 972 func TestValidateOnceAWeekWindowFormat(t *testing.T) { 973 cases := []struct { 974 Value string 975 ErrCount int 976 }{ 977 { 978 // once a day window format 979 Value: "04:00-05:00", 980 ErrCount: 1, 981 }, 982 { 983 // invalid day of week 984 Value: "san:04:00-san:05:00", 985 ErrCount: 1, 986 }, 987 { 988 // invalid hour 989 Value: "sun:24:00-san:25:00", 990 ErrCount: 1, 991 }, 992 { 993 // invalid min 994 Value: "sun:04:00-sun:04:60", 995 ErrCount: 1, 996 }, 997 { 998 // valid format 999 Value: "sun:04:00-sun:05:00", 1000 ErrCount: 0, 1001 }, 1002 { 1003 // "Sun" can also be used 1004 Value: "Sun:04:00-Sun:05:00", 1005 ErrCount: 0, 1006 }, 1007 } 1008 1009 for _, tc := range cases { 1010 _, errors := validateOnceAWeekWindowFormat(tc.Value, "maintenance_window") 1011 1012 if len(errors) != tc.ErrCount { 1013 t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value) 1014 } 1015 } 1016 } 1017 1018 func TestValidateOnceADayWindowFormat(t *testing.T) { 1019 cases := []struct { 1020 Value string 1021 ErrCount int 1022 }{ 1023 { 1024 // once a week window format 1025 Value: "sun:04:00-sun:05:00", 1026 ErrCount: 1, 1027 }, 1028 { 1029 // invalid hour 1030 Value: "24:00-25:00", 1031 ErrCount: 1, 1032 }, 1033 { 1034 // invalid min 1035 Value: "04:00-04:60", 1036 ErrCount: 1, 1037 }, 1038 { 1039 // valid format 1040 Value: "04:00-05:00", 1041 ErrCount: 0, 1042 }, 1043 } 1044 1045 for _, tc := range cases { 1046 _, errors := validateOnceADayWindowFormat(tc.Value, "backup_window") 1047 1048 if len(errors) != tc.ErrCount { 1049 t.Fatalf("Expected %d validation errors, But got %d errors for \"%s\"", tc.ErrCount, len(errors), tc.Value) 1050 } 1051 } 1052 } 1053 1054 func TestValidateRoute53RecordType(t *testing.T) { 1055 validTypes := []string{ 1056 "AAAA", 1057 "SOA", 1058 "A", 1059 "TXT", 1060 "CNAME", 1061 "MX", 1062 "NAPTR", 1063 "PTR", 1064 "SPF", 1065 "SRV", 1066 "NS", 1067 } 1068 1069 invalidTypes := []string{ 1070 "a", 1071 "alias", 1072 "SpF", 1073 "Txt", 1074 "AaAA", 1075 } 1076 1077 for _, v := range validTypes { 1078 _, errors := validateRoute53RecordType(v, "route53_record") 1079 if len(errors) != 0 { 1080 t.Fatalf("%q should be a valid Route53 record type: %v", v, errors) 1081 } 1082 } 1083 1084 for _, v := range invalidTypes { 1085 _, errors := validateRoute53RecordType(v, "route53_record") 1086 if len(errors) == 0 { 1087 t.Fatalf("%q should not be a valid Route53 record type", v) 1088 } 1089 } 1090 } 1091 1092 func TestValidateEcsPlacementConstraint(t *testing.T) { 1093 cases := []struct { 1094 constType string 1095 constExpr string 1096 Err bool 1097 }{ 1098 { 1099 constType: "distinctInstance", 1100 constExpr: "", 1101 Err: false, 1102 }, 1103 { 1104 constType: "memberOf", 1105 constExpr: "", 1106 Err: true, 1107 }, 1108 { 1109 constType: "distinctInstance", 1110 constExpr: "expression", 1111 Err: false, 1112 }, 1113 { 1114 constType: "memberOf", 1115 constExpr: "expression", 1116 Err: false, 1117 }, 1118 } 1119 1120 for _, tc := range cases { 1121 if err := validateAwsEcsPlacementConstraint(tc.constType, tc.constExpr); err != nil && !tc.Err { 1122 t.Fatalf("Unexpected validation error for \"%s:%s\": %s", 1123 tc.constType, tc.constExpr, err) 1124 } 1125 1126 } 1127 } 1128 1129 func TestValidateEcsPlacementStrategy(t *testing.T) { 1130 cases := []struct { 1131 stratType string 1132 stratField string 1133 Err bool 1134 }{ 1135 { 1136 stratType: "random", 1137 stratField: "", 1138 Err: false, 1139 }, 1140 { 1141 stratType: "spread", 1142 stratField: "instanceID", 1143 Err: false, 1144 }, 1145 { 1146 stratType: "binpack", 1147 stratField: "cpu", 1148 Err: false, 1149 }, 1150 { 1151 stratType: "binpack", 1152 stratField: "memory", 1153 Err: false, 1154 }, 1155 { 1156 stratType: "binpack", 1157 stratField: "disk", 1158 Err: true, 1159 }, 1160 { 1161 stratType: "fakeType", 1162 stratField: "", 1163 Err: true, 1164 }, 1165 } 1166 1167 for _, tc := range cases { 1168 if err := validateAwsEcsPlacementStrategy(tc.stratType, tc.stratField); err != nil && !tc.Err { 1169 t.Fatalf("Unexpected validation error for \"%s:%s\": %s", 1170 tc.stratType, tc.stratField, err) 1171 } 1172 1173 } 1174 }