github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/builtin/providers/aws/validators_test.go (about) 1 package aws 2 3 import ( 4 "strings" 5 "testing" 6 ) 7 8 func TestValidateEcrRepositoryName(t *testing.T) { 9 validNames := []string{ 10 "nginx-web-app", 11 "project-a/nginx-web-app", 12 "domain.ltd/nginx-web-app", 13 "3chosome-thing.com/01different-pattern", 14 "0123456789/999999999", 15 "double/forward/slash", 16 "000000000000000", 17 } 18 for _, v := range validNames { 19 _, errors := validateEcrRepositoryName(v, "name") 20 if len(errors) != 0 { 21 t.Fatalf("%q should be a valid ECR repository name: %q", v, errors) 22 } 23 } 24 25 invalidNames := []string{ 26 // length > 256 27 "3cho_some-thing.com/01different.-_pattern01different.-_pattern01diff" + 28 "erent.-_pattern01different.-_pattern01different.-_pattern01different" + 29 ".-_pattern01different.-_pattern01different.-_pattern01different.-_pa" + 30 "ttern01different.-_pattern01different.-_pattern234567", 31 // length < 2 32 "i", 33 "special@character", 34 "different+special=character", 35 "double//slash", 36 "double..dot", 37 "/slash-at-the-beginning", 38 "slash-at-the-end/", 39 } 40 for _, v := range invalidNames { 41 _, errors := validateEcrRepositoryName(v, "name") 42 if len(errors) == 0 { 43 t.Fatalf("%q should be an invalid ECR repository name", v) 44 } 45 } 46 } 47 48 func TestValidateCloudWatchEventRuleName(t *testing.T) { 49 validNames := []string{ 50 "HelloWorl_d", 51 "hello-world", 52 "hello.World0125", 53 } 54 for _, v := range validNames { 55 _, errors := validateCloudWatchEventRuleName(v, "name") 56 if len(errors) != 0 { 57 t.Fatalf("%q should be a valid CW event rule name: %q", v, errors) 58 } 59 } 60 61 invalidNames := []string{ 62 "special@character", 63 "slash/in-the-middle", 64 // Length > 64 65 "TooLooooooooooooooooooooooooooooooooooooooooooooooooooooooongName", 66 } 67 for _, v := range invalidNames { 68 _, errors := validateCloudWatchEventRuleName(v, "name") 69 if len(errors) == 0 { 70 t.Fatalf("%q should be an invalid CW event rule name", v) 71 } 72 } 73 } 74 75 func TestValidateLambdaFunctionName(t *testing.T) { 76 validNames := []string{ 77 "arn:aws:lambda:us-west-2:123456789012:function:ThumbNail", 78 "FunctionName", 79 "function-name", 80 } 81 for _, v := range validNames { 82 _, errors := validateLambdaFunctionName(v, "name") 83 if len(errors) != 0 { 84 t.Fatalf("%q should be a valid Lambda function name: %q", v, errors) 85 } 86 } 87 88 invalidNames := []string{ 89 "/FunctionNameWithSlash", 90 "function.name.with.dots", 91 // length > 140 92 "arn:aws:lambda:us-west-2:123456789012:function:TooLoooooo" + 93 "ooooooooooooooooooooooooooooooooooooooooooooooooooooooo" + 94 "ooooooooooooooooongFunctionName", 95 } 96 for _, v := range invalidNames { 97 _, errors := validateLambdaFunctionName(v, "name") 98 if len(errors) == 0 { 99 t.Fatalf("%q should be an invalid Lambda function name", v) 100 } 101 } 102 } 103 104 func TestValidateLambdaQualifier(t *testing.T) { 105 validNames := []string{ 106 "123", 107 "prod", 108 "PROD", 109 "MyTestEnv", 110 "$LATEST", 111 } 112 for _, v := range validNames { 113 _, errors := validateLambdaQualifier(v, "name") 114 if len(errors) != 0 { 115 t.Fatalf("%q should be a valid Lambda function qualifier: %q", v, errors) 116 } 117 } 118 119 invalidNames := []string{ 120 // No ARNs allowed 121 "arn:aws:lambda:us-west-2:123456789012:function:prod", 122 // length > 128 123 "TooLooooooooooooooooooooooooooooooooooooooooooooooooooo" + 124 "ooooooooooooooooooooooooooooooooooooooooooooooooooo" + 125 "oooooooooooongQualifier", 126 } 127 for _, v := range invalidNames { 128 _, errors := validateLambdaQualifier(v, "name") 129 if len(errors) == 0 { 130 t.Fatalf("%q should be an invalid Lambda function qualifier", v) 131 } 132 } 133 } 134 135 func TestValidateLambdaPermissionAction(t *testing.T) { 136 validNames := []string{ 137 "lambda:*", 138 "lambda:InvokeFunction", 139 "*", 140 } 141 for _, v := range validNames { 142 _, errors := validateLambdaPermissionAction(v, "action") 143 if len(errors) != 0 { 144 t.Fatalf("%q should be a valid Lambda permission action: %q", v, errors) 145 } 146 } 147 148 invalidNames := []string{ 149 "yada", 150 "lambda:123", 151 "*:*", 152 "lambda:Invoke*", 153 } 154 for _, v := range invalidNames { 155 _, errors := validateLambdaPermissionAction(v, "action") 156 if len(errors) == 0 { 157 t.Fatalf("%q should be an invalid Lambda permission action", v) 158 } 159 } 160 } 161 162 func TestValidateAwsAccountId(t *testing.T) { 163 validNames := []string{ 164 "123456789012", 165 "999999999999", 166 } 167 for _, v := range validNames { 168 _, errors := validateAwsAccountId(v, "account_id") 169 if len(errors) != 0 { 170 t.Fatalf("%q should be a valid AWS Account ID: %q", v, errors) 171 } 172 } 173 174 invalidNames := []string{ 175 "12345678901", // too short 176 "1234567890123", // too long 177 "invalid", 178 "x123456789012", 179 } 180 for _, v := range invalidNames { 181 _, errors := validateAwsAccountId(v, "account_id") 182 if len(errors) == 0 { 183 t.Fatalf("%q should be an invalid AWS Account ID", v) 184 } 185 } 186 } 187 188 func TestValidateArn(t *testing.T) { 189 validNames := []string{ 190 "arn:aws:elasticbeanstalk:us-east-1:123456789012:environment/My App/MyEnvironment", // Beanstalk 191 "arn:aws:iam::123456789012:user/David", // IAM User 192 "arn:aws:rds:eu-west-1:123456789012:db:mysql-db", // RDS 193 "arn:aws:s3:::my_corporate_bucket/exampleobject.png", // S3 object 194 "arn:aws:events:us-east-1:319201112229:rule/rule_name", // CloudWatch Rule 195 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction", // Lambda function 196 "arn:aws:lambda:eu-west-1:319201112229:function:myCustomFunction:Qualifier", // Lambda func qualifier 197 } 198 for _, v := range validNames { 199 _, errors := validateArn(v, "arn") 200 if len(errors) != 0 { 201 t.Fatalf("%q should be a valid ARN: %q", v, errors) 202 } 203 } 204 205 invalidNames := []string{ 206 "arn", 207 "123456789012", 208 "arn:aws", 209 "arn:aws:logs", 210 "arn:aws:logs:region:*:*", 211 } 212 for _, v := range invalidNames { 213 _, errors := validateArn(v, "arn") 214 if len(errors) == 0 { 215 t.Fatalf("%q should be an invalid ARN", v) 216 } 217 } 218 } 219 220 func TestValidatePolicyStatementId(t *testing.T) { 221 validNames := []string{ 222 "YadaHereAndThere", 223 "Valid-5tatement_Id", 224 "1234", 225 } 226 for _, v := range validNames { 227 _, errors := validatePolicyStatementId(v, "statement_id") 228 if len(errors) != 0 { 229 t.Fatalf("%q should be a valid Statement ID: %q", v, errors) 230 } 231 } 232 233 invalidNames := []string{ 234 "Invalid/StatementId/with/slashes", 235 "InvalidStatementId.with.dots", 236 // length > 100 237 "TooooLoooooooooooooooooooooooooooooooooooooooooooo" + 238 "ooooooooooooooooooooooooooooooooooooooooStatementId", 239 } 240 for _, v := range invalidNames { 241 _, errors := validatePolicyStatementId(v, "statement_id") 242 if len(errors) == 0 { 243 t.Fatalf("%q should be an invalid Statement ID", v) 244 } 245 } 246 } 247 248 func TestValidateCIDRNetworkAddress(t *testing.T) { 249 cases := []struct { 250 CIDR string 251 ExpectedErrSubstr string 252 }{ 253 {"notacidr", `must contain a valid CIDR`}, 254 {"10.0.1.0/16", `must contain a valid network CIDR`}, 255 {"10.0.1.0/24", ``}, 256 } 257 258 for i, tc := range cases { 259 _, errs := validateCIDRNetworkAddress(tc.CIDR, "foo") 260 if tc.ExpectedErrSubstr == "" { 261 if len(errs) != 0 { 262 t.Fatalf("%d/%d: Expected no error, got errs: %#v", 263 i+1, len(cases), errs) 264 } 265 } else { 266 if len(errs) != 1 { 267 t.Fatalf("%d/%d: Expected 1 err containing %q, got %d errs", 268 i+1, len(cases), tc.ExpectedErrSubstr, len(errs)) 269 } 270 if !strings.Contains(errs[0].Error(), tc.ExpectedErrSubstr) { 271 t.Fatalf("%d/%d: Expected err: %q, to include %q", 272 i+1, len(cases), errs[0], tc.ExpectedErrSubstr) 273 } 274 } 275 } 276 } 277 278 func TestValidateHTTPMethod(t *testing.T) { 279 type testCases struct { 280 Value string 281 ErrCount int 282 } 283 284 invalidCases := []testCases{ 285 { 286 Value: "incorrect", 287 ErrCount: 1, 288 }, 289 { 290 Value: "delete", 291 ErrCount: 1, 292 }, 293 } 294 295 for _, tc := range invalidCases { 296 _, errors := validateHTTPMethod(tc.Value, "http_method") 297 if len(errors) != tc.ErrCount { 298 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 299 } 300 } 301 302 validCases := []testCases{ 303 { 304 Value: "ANY", 305 ErrCount: 0, 306 }, 307 { 308 Value: "DELETE", 309 ErrCount: 0, 310 }, 311 { 312 Value: "OPTIONS", 313 ErrCount: 0, 314 }, 315 } 316 317 for _, tc := range validCases { 318 _, errors := validateHTTPMethod(tc.Value, "http_method") 319 if len(errors) != tc.ErrCount { 320 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 321 } 322 } 323 } 324 325 func TestValidateLogMetricFilterName(t *testing.T) { 326 validNames := []string{ 327 "YadaHereAndThere", 328 "Valid-5Metric_Name", 329 "This . is also %% valid@!)+(", 330 "1234", 331 strings.Repeat("W", 512), 332 } 333 for _, v := range validNames { 334 _, errors := validateLogMetricFilterName(v, "name") 335 if len(errors) != 0 { 336 t.Fatalf("%q should be a valid Log Metric Filter Name: %q", v, errors) 337 } 338 } 339 340 invalidNames := []string{ 341 "Here is a name with: colon", 342 "and here is another * invalid name", 343 "*", 344 // length > 512 345 strings.Repeat("W", 513), 346 } 347 for _, v := range invalidNames { 348 _, errors := validateLogMetricFilterName(v, "name") 349 if len(errors) == 0 { 350 t.Fatalf("%q should be an invalid Log Metric Filter Name", v) 351 } 352 } 353 } 354 355 func TestValidateLogMetricTransformationName(t *testing.T) { 356 validNames := []string{ 357 "YadaHereAndThere", 358 "Valid-5Metric_Name", 359 "This . is also %% valid@!)+(", 360 "1234", 361 "", 362 strings.Repeat("W", 255), 363 } 364 for _, v := range validNames { 365 _, errors := validateLogMetricFilterTransformationName(v, "name") 366 if len(errors) != 0 { 367 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 368 } 369 } 370 371 invalidNames := []string{ 372 "Here is a name with: colon", 373 "and here is another * invalid name", 374 "also $ invalid", 375 "*", 376 // length > 255 377 strings.Repeat("W", 256), 378 } 379 for _, v := range invalidNames { 380 _, errors := validateLogMetricFilterTransformationName(v, "name") 381 if len(errors) == 0 { 382 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 383 } 384 } 385 } 386 387 func TestValidateLogGroupName(t *testing.T) { 388 validNames := []string{ 389 "ValidLogGroupName", 390 "ValidLogGroup.Name", 391 "valid/Log-group", 392 "1234", 393 "YadaValid#0123", 394 "Also_valid-name", 395 strings.Repeat("W", 512), 396 } 397 for _, v := range validNames { 398 _, errors := validateLogGroupName(v, "name") 399 if len(errors) != 0 { 400 t.Fatalf("%q should be a valid Log Metric Filter Transformation Name: %q", v, errors) 401 } 402 } 403 404 invalidNames := []string{ 405 "Here is a name with: colon", 406 "and here is another * invalid name", 407 "also $ invalid", 408 "This . is also %% invalid@!)+(", 409 "*", 410 "", 411 // length > 512 412 strings.Repeat("W", 513), 413 } 414 for _, v := range invalidNames { 415 _, errors := validateLogGroupName(v, "name") 416 if len(errors) == 0 { 417 t.Fatalf("%q should be an invalid Log Metric Filter Transformation Name", v) 418 } 419 } 420 } 421 422 func TestValidateS3BucketLifecycleTimestamp(t *testing.T) { 423 validDates := []string{ 424 "2016-01-01", 425 "2006-01-02", 426 } 427 428 for _, v := range validDates { 429 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 430 if len(errors) != 0 { 431 t.Fatalf("%q should be valid date: %q", v, errors) 432 } 433 } 434 435 invalidDates := []string{ 436 "Jan 01 2016", 437 "20160101", 438 } 439 440 for _, v := range invalidDates { 441 _, errors := validateS3BucketLifecycleTimestamp(v, "date") 442 if len(errors) == 0 { 443 t.Fatalf("%q should be invalid date", v) 444 } 445 } 446 } 447 448 func TestValidateS3BucketLifecycleStorageClass(t *testing.T) { 449 validStorageClass := []string{ 450 "STANDARD_IA", 451 "GLACIER", 452 } 453 454 for _, v := range validStorageClass { 455 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 456 if len(errors) != 0 { 457 t.Fatalf("%q should be valid storage class: %q", v, errors) 458 } 459 } 460 461 invalidStorageClass := []string{ 462 "STANDARD", 463 "1234", 464 } 465 for _, v := range invalidStorageClass { 466 _, errors := validateS3BucketLifecycleStorageClass(v, "storage_class") 467 if len(errors) == 0 { 468 t.Fatalf("%q should be invalid storage class", v) 469 } 470 } 471 } 472 473 func TestValidateS3BucketLifecycleRuleId(t *testing.T) { 474 validId := []string{ 475 "YadaHereAndThere", 476 "Valid-5Rule_ID", 477 "This . is also %% valid@!)+*(:ID", 478 "1234", 479 strings.Repeat("W", 255), 480 } 481 for _, v := range validId { 482 _, errors := validateS3BucketLifecycleRuleId(v, "id") 483 if len(errors) != 0 { 484 t.Fatalf("%q should be a valid lifecycle rule id: %q", v, errors) 485 } 486 } 487 488 invalidId := []string{ 489 // length > 255 490 strings.Repeat("W", 256), 491 } 492 for _, v := range invalidId { 493 _, errors := validateS3BucketLifecycleRuleId(v, "id") 494 if len(errors) == 0 { 495 t.Fatalf("%q should be an invalid lifecycle rule id", v) 496 } 497 } 498 } 499 500 func TestValidateIntegerInRange(t *testing.T) { 501 validIntegers := []int{-259, 0, 1, 5, 999} 502 min := -259 503 max := 999 504 for _, v := range validIntegers { 505 _, errors := validateIntegerInRange(min, max)(v, "name") 506 if len(errors) != 0 { 507 t.Fatalf("%q should be an integer in range (%d, %d): %q", v, min, max, errors) 508 } 509 } 510 511 invalidIntegers := []int{-260, -99999, 1000, 25678} 512 for _, v := range invalidIntegers { 513 _, errors := validateIntegerInRange(min, max)(v, "name") 514 if len(errors) == 0 { 515 t.Fatalf("%q should be an integer outside range (%d, %d)", v, min, max) 516 } 517 } 518 } 519 520 func TestResourceAWSElastiCacheClusterIdValidation(t *testing.T) { 521 cases := []struct { 522 Value string 523 ErrCount int 524 }{ 525 { 526 Value: "tEsting", 527 ErrCount: 1, 528 }, 529 { 530 Value: "t.sting", 531 ErrCount: 1, 532 }, 533 { 534 Value: "t--sting", 535 ErrCount: 1, 536 }, 537 { 538 Value: "1testing", 539 ErrCount: 1, 540 }, 541 { 542 Value: "testing-", 543 ErrCount: 1, 544 }, 545 { 546 Value: randomString(65), 547 ErrCount: 1, 548 }, 549 } 550 551 for _, tc := range cases { 552 _, errors := validateElastiCacheClusterId(tc.Value, "aws_elasticache_cluster_cluster_id") 553 554 if len(errors) != tc.ErrCount { 555 t.Fatalf("Expected the ElastiCache Cluster cluster_id to trigger a validation error") 556 } 557 } 558 } 559 560 func TestValidateDbEventSubscriptionName(t *testing.T) { 561 validNames := []string{ 562 "valid-name", 563 "valid02-name", 564 "Valid-Name1", 565 } 566 for _, v := range validNames { 567 _, errors := validateDbEventSubscriptionName(v, "name") 568 if len(errors) != 0 { 569 t.Fatalf("%q should be a valid RDS Event Subscription Name: %q", v, errors) 570 } 571 } 572 573 invalidNames := []string{ 574 "Here is a name with: colon", 575 "and here is another * invalid name", 576 "also $ invalid", 577 "This . is also %% invalid@!)+(", 578 "*", 579 "", 580 " ", 581 "_", 582 // length > 255 583 strings.Repeat("W", 256), 584 } 585 for _, v := range invalidNames { 586 _, errors := validateDbEventSubscriptionName(v, "name") 587 if len(errors) == 0 { 588 t.Fatalf("%q should be an invalid RDS Event Subscription Name", v) 589 } 590 } 591 } 592 593 func TestValidateJsonString(t *testing.T) { 594 type testCases struct { 595 Value string 596 ErrCount int 597 } 598 599 invalidCases := []testCases{ 600 { 601 Value: `{0:"1"}`, 602 ErrCount: 1, 603 }, 604 { 605 Value: `{'abc':1}`, 606 ErrCount: 1, 607 }, 608 { 609 Value: `{"def":}`, 610 ErrCount: 1, 611 }, 612 { 613 Value: `{"xyz":[}}`, 614 ErrCount: 1, 615 }, 616 } 617 618 for _, tc := range invalidCases { 619 _, errors := validateJsonString(tc.Value, "json") 620 if len(errors) != tc.ErrCount { 621 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 622 } 623 } 624 625 validCases := []testCases{ 626 { 627 Value: ``, 628 ErrCount: 0, 629 }, 630 { 631 Value: `{}`, 632 ErrCount: 0, 633 }, 634 { 635 Value: `{"abc":["1","2"]}`, 636 ErrCount: 0, 637 }, 638 } 639 640 for _, tc := range validCases { 641 _, errors := validateJsonString(tc.Value, "json") 642 if len(errors) != tc.ErrCount { 643 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 644 } 645 } 646 } 647 648 func TestValidateApiGatewayIntegrationType(t *testing.T) { 649 type testCases struct { 650 Value string 651 ErrCount int 652 } 653 654 invalidCases := []testCases{ 655 { 656 Value: "incorrect", 657 ErrCount: 1, 658 }, 659 { 660 Value: "aws_proxy", 661 ErrCount: 1, 662 }, 663 } 664 665 for _, tc := range invalidCases { 666 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 667 if len(errors) != tc.ErrCount { 668 t.Fatalf("Expected %q to trigger a validation error.", tc.Value) 669 } 670 } 671 672 validCases := []testCases{ 673 { 674 Value: "MOCK", 675 ErrCount: 0, 676 }, 677 { 678 Value: "AWS_PROXY", 679 ErrCount: 0, 680 }, 681 } 682 683 for _, tc := range validCases { 684 _, errors := validateApiGatewayIntegrationType(tc.Value, "types") 685 if len(errors) != tc.ErrCount { 686 t.Fatalf("Expected %q not to trigger a validation error.", tc.Value) 687 } 688 } 689 }