github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/aws/structure_test.go (about) 1 package aws 2 3 import ( 4 "reflect" 5 "strings" 6 "testing" 7 8 "github.com/aws/aws-sdk-go/aws" 9 "github.com/aws/aws-sdk-go/service/apigateway" 10 "github.com/aws/aws-sdk-go/service/autoscaling" 11 "github.com/aws/aws-sdk-go/service/ec2" 12 "github.com/aws/aws-sdk-go/service/elasticache" 13 "github.com/aws/aws-sdk-go/service/elb" 14 "github.com/aws/aws-sdk-go/service/kinesis" 15 "github.com/aws/aws-sdk-go/service/rds" 16 "github.com/aws/aws-sdk-go/service/redshift" 17 "github.com/aws/aws-sdk-go/service/route53" 18 "github.com/hashicorp/terraform/flatmap" 19 "github.com/hashicorp/terraform/helper/schema" 20 ) 21 22 // Returns test configuration 23 func testConf() map[string]string { 24 return map[string]string{ 25 "listener.#": "1", 26 "listener.0.lb_port": "80", 27 "listener.0.lb_protocol": "http", 28 "listener.0.instance_port": "8000", 29 "listener.0.instance_protocol": "http", 30 "availability_zones.#": "2", 31 "availability_zones.0": "us-east-1a", 32 "availability_zones.1": "us-east-1b", 33 "ingress.#": "1", 34 "ingress.0.protocol": "icmp", 35 "ingress.0.from_port": "1", 36 "ingress.0.to_port": "-1", 37 "ingress.0.cidr_blocks.#": "1", 38 "ingress.0.cidr_blocks.0": "0.0.0.0/0", 39 "ingress.0.security_groups.#": "2", 40 "ingress.0.security_groups.0": "sg-11111", 41 "ingress.0.security_groups.1": "foo/sg-22222", 42 } 43 } 44 45 func TestExpandIPPerms(t *testing.T) { 46 hash := schema.HashString 47 48 expanded := []interface{}{ 49 map[string]interface{}{ 50 "protocol": "icmp", 51 "from_port": 1, 52 "to_port": -1, 53 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 54 "security_groups": schema.NewSet(hash, []interface{}{ 55 "sg-11111", 56 "foo/sg-22222", 57 }), 58 }, 59 map[string]interface{}{ 60 "protocol": "icmp", 61 "from_port": 1, 62 "to_port": -1, 63 "self": true, 64 }, 65 } 66 group := &ec2.SecurityGroup{ 67 GroupId: aws.String("foo"), 68 VpcId: aws.String("bar"), 69 } 70 perms, err := expandIPPerms(group, expanded) 71 if err != nil { 72 t.Fatalf("error expanding perms: %v", err) 73 } 74 75 expected := []ec2.IpPermission{ 76 ec2.IpPermission{ 77 IpProtocol: aws.String("icmp"), 78 FromPort: aws.Int64(int64(1)), 79 ToPort: aws.Int64(int64(-1)), 80 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 81 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 82 &ec2.UserIdGroupPair{ 83 UserId: aws.String("foo"), 84 GroupId: aws.String("sg-22222"), 85 }, 86 &ec2.UserIdGroupPair{ 87 GroupId: aws.String("sg-11111"), 88 }, 89 }, 90 }, 91 ec2.IpPermission{ 92 IpProtocol: aws.String("icmp"), 93 FromPort: aws.Int64(int64(1)), 94 ToPort: aws.Int64(int64(-1)), 95 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 96 &ec2.UserIdGroupPair{ 97 GroupId: aws.String("foo"), 98 }, 99 }, 100 }, 101 } 102 103 exp := expected[0] 104 perm := perms[0] 105 106 if *exp.FromPort != *perm.FromPort { 107 t.Fatalf( 108 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 109 *perm.FromPort, 110 *exp.FromPort) 111 } 112 113 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 114 t.Fatalf( 115 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 116 *perm.IpRanges[0].CidrIp, 117 *exp.IpRanges[0].CidrIp) 118 } 119 120 if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId { 121 t.Fatalf( 122 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 123 *perm.UserIdGroupPairs[0].UserId, 124 *exp.UserIdGroupPairs[0].UserId) 125 } 126 127 if *exp.UserIdGroupPairs[0].GroupId != *perm.UserIdGroupPairs[0].GroupId { 128 t.Fatalf( 129 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 130 *perm.UserIdGroupPairs[0].GroupId, 131 *exp.UserIdGroupPairs[0].GroupId) 132 } 133 134 if *exp.UserIdGroupPairs[1].GroupId != *perm.UserIdGroupPairs[1].GroupId { 135 t.Fatalf( 136 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 137 *perm.UserIdGroupPairs[1].GroupId, 138 *exp.UserIdGroupPairs[1].GroupId) 139 } 140 141 exp = expected[1] 142 perm = perms[1] 143 144 if *exp.UserIdGroupPairs[0].GroupId != *perm.UserIdGroupPairs[0].GroupId { 145 t.Fatalf( 146 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 147 *perm.UserIdGroupPairs[0].GroupId, 148 *exp.UserIdGroupPairs[0].GroupId) 149 } 150 } 151 152 func TestExpandIPPerms_NegOneProtocol(t *testing.T) { 153 hash := schema.HashString 154 155 expanded := []interface{}{ 156 map[string]interface{}{ 157 "protocol": "-1", 158 "from_port": 0, 159 "to_port": 0, 160 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 161 "security_groups": schema.NewSet(hash, []interface{}{ 162 "sg-11111", 163 "foo/sg-22222", 164 }), 165 }, 166 } 167 group := &ec2.SecurityGroup{ 168 GroupId: aws.String("foo"), 169 VpcId: aws.String("bar"), 170 } 171 172 perms, err := expandIPPerms(group, expanded) 173 if err != nil { 174 t.Fatalf("error expanding perms: %v", err) 175 } 176 177 expected := []ec2.IpPermission{ 178 ec2.IpPermission{ 179 IpProtocol: aws.String("-1"), 180 FromPort: aws.Int64(int64(0)), 181 ToPort: aws.Int64(int64(0)), 182 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 183 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 184 &ec2.UserIdGroupPair{ 185 UserId: aws.String("foo"), 186 GroupId: aws.String("sg-22222"), 187 }, 188 &ec2.UserIdGroupPair{ 189 GroupId: aws.String("sg-11111"), 190 }, 191 }, 192 }, 193 } 194 195 exp := expected[0] 196 perm := perms[0] 197 198 if *exp.FromPort != *perm.FromPort { 199 t.Fatalf( 200 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 201 *perm.FromPort, 202 *exp.FromPort) 203 } 204 205 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 206 t.Fatalf( 207 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 208 *perm.IpRanges[0].CidrIp, 209 *exp.IpRanges[0].CidrIp) 210 } 211 212 if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId { 213 t.Fatalf( 214 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 215 *perm.UserIdGroupPairs[0].UserId, 216 *exp.UserIdGroupPairs[0].UserId) 217 } 218 219 // Now test the error case. This *should* error when either from_port 220 // or to_port is not zero, but protocol is "-1". 221 errorCase := []interface{}{ 222 map[string]interface{}{ 223 "protocol": "-1", 224 "from_port": 0, 225 "to_port": 65535, 226 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 227 "security_groups": schema.NewSet(hash, []interface{}{ 228 "sg-11111", 229 "foo/sg-22222", 230 }), 231 }, 232 } 233 securityGroups := &ec2.SecurityGroup{ 234 GroupId: aws.String("foo"), 235 VpcId: aws.String("bar"), 236 } 237 238 _, expandErr := expandIPPerms(securityGroups, errorCase) 239 if expandErr == nil { 240 t.Fatal("expandIPPerms should have errored!") 241 } 242 } 243 244 func TestExpandIPPerms_nonVPC(t *testing.T) { 245 hash := schema.HashString 246 247 expanded := []interface{}{ 248 map[string]interface{}{ 249 "protocol": "icmp", 250 "from_port": 1, 251 "to_port": -1, 252 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 253 "security_groups": schema.NewSet(hash, []interface{}{ 254 "sg-11111", 255 "foo/sg-22222", 256 }), 257 }, 258 map[string]interface{}{ 259 "protocol": "icmp", 260 "from_port": 1, 261 "to_port": -1, 262 "self": true, 263 }, 264 } 265 group := &ec2.SecurityGroup{ 266 GroupName: aws.String("foo"), 267 } 268 perms, err := expandIPPerms(group, expanded) 269 if err != nil { 270 t.Fatalf("error expanding perms: %v", err) 271 } 272 273 expected := []ec2.IpPermission{ 274 ec2.IpPermission{ 275 IpProtocol: aws.String("icmp"), 276 FromPort: aws.Int64(int64(1)), 277 ToPort: aws.Int64(int64(-1)), 278 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 279 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 280 &ec2.UserIdGroupPair{ 281 GroupName: aws.String("sg-22222"), 282 }, 283 &ec2.UserIdGroupPair{ 284 GroupName: aws.String("sg-11111"), 285 }, 286 }, 287 }, 288 ec2.IpPermission{ 289 IpProtocol: aws.String("icmp"), 290 FromPort: aws.Int64(int64(1)), 291 ToPort: aws.Int64(int64(-1)), 292 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 293 &ec2.UserIdGroupPair{ 294 GroupName: aws.String("foo"), 295 }, 296 }, 297 }, 298 } 299 300 exp := expected[0] 301 perm := perms[0] 302 303 if *exp.FromPort != *perm.FromPort { 304 t.Fatalf( 305 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 306 *perm.FromPort, 307 *exp.FromPort) 308 } 309 310 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 311 t.Fatalf( 312 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 313 *perm.IpRanges[0].CidrIp, 314 *exp.IpRanges[0].CidrIp) 315 } 316 317 if *exp.UserIdGroupPairs[0].GroupName != *perm.UserIdGroupPairs[0].GroupName { 318 t.Fatalf( 319 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 320 *perm.UserIdGroupPairs[0].GroupName, 321 *exp.UserIdGroupPairs[0].GroupName) 322 } 323 324 if *exp.UserIdGroupPairs[1].GroupName != *perm.UserIdGroupPairs[1].GroupName { 325 t.Fatalf( 326 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 327 *perm.UserIdGroupPairs[1].GroupName, 328 *exp.UserIdGroupPairs[1].GroupName) 329 } 330 331 exp = expected[1] 332 perm = perms[1] 333 334 if *exp.UserIdGroupPairs[0].GroupName != *perm.UserIdGroupPairs[0].GroupName { 335 t.Fatalf( 336 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 337 *perm.UserIdGroupPairs[0].GroupName, 338 *exp.UserIdGroupPairs[0].GroupName) 339 } 340 } 341 342 func TestExpandListeners(t *testing.T) { 343 expanded := []interface{}{ 344 map[string]interface{}{ 345 "instance_port": 8000, 346 "lb_port": 80, 347 "instance_protocol": "http", 348 "lb_protocol": "http", 349 }, 350 map[string]interface{}{ 351 "instance_port": 8000, 352 "lb_port": 80, 353 "instance_protocol": "https", 354 "lb_protocol": "https", 355 "ssl_certificate_id": "something", 356 }, 357 } 358 listeners, err := expandListeners(expanded) 359 if err != nil { 360 t.Fatalf("bad: %#v", err) 361 } 362 363 expected := &elb.Listener{ 364 InstancePort: aws.Int64(int64(8000)), 365 LoadBalancerPort: aws.Int64(int64(80)), 366 InstanceProtocol: aws.String("http"), 367 Protocol: aws.String("http"), 368 } 369 370 if !reflect.DeepEqual(listeners[0], expected) { 371 t.Fatalf( 372 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 373 listeners[0], 374 expected) 375 } 376 } 377 378 // this test should produce an error from expandlisteners on an invalid 379 // combination 380 func TestExpandListeners_invalid(t *testing.T) { 381 expanded := []interface{}{ 382 map[string]interface{}{ 383 "instance_port": 8000, 384 "lb_port": 80, 385 "instance_protocol": "http", 386 "lb_protocol": "http", 387 "ssl_certificate_id": "something", 388 }, 389 } 390 _, err := expandListeners(expanded) 391 if err != nil { 392 // Check the error we got 393 if !strings.Contains(err.Error(), "ssl_certificate_id may be set only when protocol") { 394 t.Fatalf("Got error in TestExpandListeners_invalid, but not what we expected: %s", err) 395 } 396 } 397 398 if err == nil { 399 t.Fatalf("Expected TestExpandListeners_invalid to fail, but passed") 400 } 401 } 402 403 func TestFlattenHealthCheck(t *testing.T) { 404 cases := []struct { 405 Input *elb.HealthCheck 406 Output []map[string]interface{} 407 }{ 408 { 409 Input: &elb.HealthCheck{ 410 UnhealthyThreshold: aws.Int64(int64(10)), 411 HealthyThreshold: aws.Int64(int64(10)), 412 Target: aws.String("HTTP:80/"), 413 Timeout: aws.Int64(int64(30)), 414 Interval: aws.Int64(int64(30)), 415 }, 416 Output: []map[string]interface{}{ 417 map[string]interface{}{ 418 "unhealthy_threshold": int64(10), 419 "healthy_threshold": int64(10), 420 "target": "HTTP:80/", 421 "timeout": int64(30), 422 "interval": int64(30), 423 }, 424 }, 425 }, 426 } 427 428 for _, tc := range cases { 429 output := flattenHealthCheck(tc.Input) 430 if !reflect.DeepEqual(output, tc.Output) { 431 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 432 } 433 } 434 } 435 436 func TestExpandStringList(t *testing.T) { 437 expanded := flatmap.Expand(testConf(), "availability_zones").([]interface{}) 438 stringList := expandStringList(expanded) 439 expected := []*string{ 440 aws.String("us-east-1a"), 441 aws.String("us-east-1b"), 442 } 443 444 if !reflect.DeepEqual(stringList, expected) { 445 t.Fatalf( 446 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 447 stringList, 448 expected) 449 } 450 } 451 452 func TestExpandStringListEmptyItems(t *testing.T) { 453 initialList := []string{"foo", "bar", "", "baz"} 454 l := make([]interface{}, len(initialList)) 455 for i, v := range initialList { 456 l[i] = v 457 } 458 stringList := expandStringList(l) 459 expected := []*string{ 460 aws.String("foo"), 461 aws.String("bar"), 462 aws.String("baz"), 463 } 464 465 if !reflect.DeepEqual(stringList, expected) { 466 t.Fatalf( 467 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 468 stringList, 469 expected) 470 } 471 } 472 473 func TestExpandParameters(t *testing.T) { 474 expanded := []interface{}{ 475 map[string]interface{}{ 476 "name": "character_set_client", 477 "value": "utf8", 478 "apply_method": "immediate", 479 }, 480 } 481 parameters, err := expandParameters(expanded) 482 if err != nil { 483 t.Fatalf("bad: %#v", err) 484 } 485 486 expected := &rds.Parameter{ 487 ParameterName: aws.String("character_set_client"), 488 ParameterValue: aws.String("utf8"), 489 ApplyMethod: aws.String("immediate"), 490 } 491 492 if !reflect.DeepEqual(parameters[0], expected) { 493 t.Fatalf( 494 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 495 parameters[0], 496 expected) 497 } 498 } 499 500 func TestExpandRedshiftParameters(t *testing.T) { 501 expanded := []interface{}{ 502 map[string]interface{}{ 503 "name": "character_set_client", 504 "value": "utf8", 505 }, 506 } 507 parameters, err := expandRedshiftParameters(expanded) 508 if err != nil { 509 t.Fatalf("bad: %#v", err) 510 } 511 512 expected := &redshift.Parameter{ 513 ParameterName: aws.String("character_set_client"), 514 ParameterValue: aws.String("utf8"), 515 } 516 517 if !reflect.DeepEqual(parameters[0], expected) { 518 t.Fatalf( 519 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 520 parameters[0], 521 expected) 522 } 523 } 524 525 func TestExpandElasticacheParameters(t *testing.T) { 526 expanded := []interface{}{ 527 map[string]interface{}{ 528 "name": "activerehashing", 529 "value": "yes", 530 "apply_method": "immediate", 531 }, 532 } 533 parameters, err := expandElastiCacheParameters(expanded) 534 if err != nil { 535 t.Fatalf("bad: %#v", err) 536 } 537 538 expected := &elasticache.ParameterNameValue{ 539 ParameterName: aws.String("activerehashing"), 540 ParameterValue: aws.String("yes"), 541 } 542 543 if !reflect.DeepEqual(parameters[0], expected) { 544 t.Fatalf( 545 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 546 parameters[0], 547 expected) 548 } 549 } 550 551 func TestExpandStepAdjustments(t *testing.T) { 552 expanded := []interface{}{ 553 map[string]interface{}{ 554 "metric_interval_lower_bound": "1.0", 555 "metric_interval_upper_bound": "2.0", 556 "scaling_adjustment": 1, 557 }, 558 } 559 parameters, err := expandStepAdjustments(expanded) 560 if err != nil { 561 t.Fatalf("bad: %#v", err) 562 } 563 564 expected := &autoscaling.StepAdjustment{ 565 MetricIntervalLowerBound: aws.Float64(1.0), 566 MetricIntervalUpperBound: aws.Float64(2.0), 567 ScalingAdjustment: aws.Int64(int64(1)), 568 } 569 570 if !reflect.DeepEqual(parameters[0], expected) { 571 t.Fatalf( 572 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 573 parameters[0], 574 expected) 575 } 576 } 577 578 func TestFlattenParameters(t *testing.T) { 579 cases := []struct { 580 Input []*rds.Parameter 581 Output []map[string]interface{} 582 }{ 583 { 584 Input: []*rds.Parameter{ 585 &rds.Parameter{ 586 ParameterName: aws.String("character_set_client"), 587 ParameterValue: aws.String("utf8"), 588 }, 589 }, 590 Output: []map[string]interface{}{ 591 map[string]interface{}{ 592 "name": "character_set_client", 593 "value": "utf8", 594 }, 595 }, 596 }, 597 } 598 599 for _, tc := range cases { 600 output := flattenParameters(tc.Input) 601 if !reflect.DeepEqual(output, tc.Output) { 602 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 603 } 604 } 605 } 606 607 func TestFlattenRedshiftParameters(t *testing.T) { 608 cases := []struct { 609 Input []*redshift.Parameter 610 Output []map[string]interface{} 611 }{ 612 { 613 Input: []*redshift.Parameter{ 614 &redshift.Parameter{ 615 ParameterName: aws.String("character_set_client"), 616 ParameterValue: aws.String("utf8"), 617 }, 618 }, 619 Output: []map[string]interface{}{ 620 map[string]interface{}{ 621 "name": "character_set_client", 622 "value": "utf8", 623 }, 624 }, 625 }, 626 } 627 628 for _, tc := range cases { 629 output := flattenRedshiftParameters(tc.Input) 630 if !reflect.DeepEqual(output, tc.Output) { 631 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 632 } 633 } 634 } 635 636 func TestFlattenElasticacheParameters(t *testing.T) { 637 cases := []struct { 638 Input []*elasticache.Parameter 639 Output []map[string]interface{} 640 }{ 641 { 642 Input: []*elasticache.Parameter{ 643 &elasticache.Parameter{ 644 ParameterName: aws.String("activerehashing"), 645 ParameterValue: aws.String("yes"), 646 }, 647 }, 648 Output: []map[string]interface{}{ 649 map[string]interface{}{ 650 "name": "activerehashing", 651 "value": "yes", 652 }, 653 }, 654 }, 655 } 656 657 for _, tc := range cases { 658 output := flattenElastiCacheParameters(tc.Input) 659 if !reflect.DeepEqual(output, tc.Output) { 660 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 661 } 662 } 663 } 664 665 func TestExpandInstanceString(t *testing.T) { 666 667 expected := []*elb.Instance{ 668 &elb.Instance{InstanceId: aws.String("test-one")}, 669 &elb.Instance{InstanceId: aws.String("test-two")}, 670 } 671 672 ids := []interface{}{ 673 "test-one", 674 "test-two", 675 } 676 677 expanded := expandInstanceString(ids) 678 679 if !reflect.DeepEqual(expanded, expected) { 680 t.Fatalf("Expand Instance String output did not match.\nGot:\n%#v\n\nexpected:\n%#v", expanded, expected) 681 } 682 } 683 684 func TestFlattenNetworkInterfacesPrivateIPAddresses(t *testing.T) { 685 expanded := []*ec2.NetworkInterfacePrivateIpAddress{ 686 &ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.1")}, 687 &ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.2")}, 688 } 689 690 result := flattenNetworkInterfacesPrivateIPAddresses(expanded) 691 692 if result == nil { 693 t.Fatal("result was nil") 694 } 695 696 if len(result) != 2 { 697 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 698 } 699 700 if result[0] != "192.168.0.1" { 701 t.Fatalf("expected ip to be 192.168.0.1, but was %s", result[0]) 702 } 703 704 if result[1] != "192.168.0.2" { 705 t.Fatalf("expected ip to be 192.168.0.2, but was %s", result[1]) 706 } 707 } 708 709 func TestFlattenGroupIdentifiers(t *testing.T) { 710 expanded := []*ec2.GroupIdentifier{ 711 &ec2.GroupIdentifier{GroupId: aws.String("sg-001")}, 712 &ec2.GroupIdentifier{GroupId: aws.String("sg-002")}, 713 } 714 715 result := flattenGroupIdentifiers(expanded) 716 717 if len(result) != 2 { 718 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 719 } 720 721 if result[0] != "sg-001" { 722 t.Fatalf("expected id to be sg-001, but was %s", result[0]) 723 } 724 725 if result[1] != "sg-002" { 726 t.Fatalf("expected id to be sg-002, but was %s", result[1]) 727 } 728 } 729 730 func TestExpandPrivateIPAddresses(t *testing.T) { 731 732 ip1 := "192.168.0.1" 733 ip2 := "192.168.0.2" 734 flattened := []interface{}{ 735 ip1, 736 ip2, 737 } 738 739 result := expandPrivateIPAddresses(flattened) 740 741 if len(result) != 2 { 742 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 743 } 744 745 if *result[0].PrivateIpAddress != "192.168.0.1" || !*result[0].Primary { 746 t.Fatalf("expected ip to be 192.168.0.1 and Primary, but got %v, %t", *result[0].PrivateIpAddress, *result[0].Primary) 747 } 748 749 if *result[1].PrivateIpAddress != "192.168.0.2" || *result[1].Primary { 750 t.Fatalf("expected ip to be 192.168.0.2 and not Primary, but got %v, %t", *result[1].PrivateIpAddress, *result[1].Primary) 751 } 752 } 753 754 func TestFlattenAttachment(t *testing.T) { 755 expanded := &ec2.NetworkInterfaceAttachment{ 756 InstanceId: aws.String("i-00001"), 757 DeviceIndex: aws.Int64(int64(1)), 758 AttachmentId: aws.String("at-002"), 759 } 760 761 result := flattenAttachment(expanded) 762 763 if result == nil { 764 t.Fatal("expected result to have value, but got nil") 765 } 766 767 if result["instance"] != "i-00001" { 768 t.Fatalf("expected instance to be i-00001, but got %s", result["instance"]) 769 } 770 771 if result["device_index"] != int64(1) { 772 t.Fatalf("expected device_index to be 1, but got %d", result["device_index"]) 773 } 774 775 if result["attachment_id"] != "at-002" { 776 t.Fatalf("expected attachment_id to be at-002, but got %s", result["attachment_id"]) 777 } 778 } 779 780 func TestFlattenAttachmentWhenNoInstanceId(t *testing.T) { 781 expanded := &ec2.NetworkInterfaceAttachment{ 782 DeviceIndex: aws.Int64(int64(1)), 783 AttachmentId: aws.String("at-002"), 784 } 785 786 result := flattenAttachment(expanded) 787 788 if result == nil { 789 t.Fatal("expected result to have value, but got nil") 790 } 791 792 if result["instance"] != nil { 793 t.Fatalf("expected instance to be nil, but got %s", result["instance"]) 794 } 795 } 796 797 func TestFlattenStepAdjustments(t *testing.T) { 798 expanded := []*autoscaling.StepAdjustment{ 799 &autoscaling.StepAdjustment{ 800 MetricIntervalLowerBound: aws.Float64(1.0), 801 MetricIntervalUpperBound: aws.Float64(2.0), 802 ScalingAdjustment: aws.Int64(int64(1)), 803 }, 804 } 805 806 result := flattenStepAdjustments(expanded)[0] 807 if result == nil { 808 t.Fatal("expected result to have value, but got nil") 809 } 810 if result["metric_interval_lower_bound"] != float64(1.0) { 811 t.Fatalf("expected metric_interval_lower_bound to be 1.0, but got %d", result["metric_interval_lower_bound"]) 812 } 813 if result["metric_interval_upper_bound"] != float64(2.0) { 814 t.Fatalf("expected metric_interval_upper_bound to be 1.0, but got %d", result["metric_interval_upper_bound"]) 815 } 816 if result["scaling_adjustment"] != int64(1) { 817 t.Fatalf("expected scaling_adjustment to be 1, but got %d", result["scaling_adjustment"]) 818 } 819 } 820 821 func TestFlattenResourceRecords(t *testing.T) { 822 expanded := []*route53.ResourceRecord{ 823 &route53.ResourceRecord{ 824 Value: aws.String("127.0.0.1"), 825 }, 826 &route53.ResourceRecord{ 827 Value: aws.String("127.0.0.3"), 828 }, 829 } 830 831 result := flattenResourceRecords(expanded) 832 833 if result == nil { 834 t.Fatal("expected result to have value, but got nil") 835 } 836 837 if len(result) != 2 { 838 t.Fatal("expected result to have value, but got nil") 839 } 840 } 841 842 func TestFlattenAsgEnabledMetrics(t *testing.T) { 843 expanded := []*autoscaling.EnabledMetric{ 844 &autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupTotalInstances")}, 845 &autoscaling.EnabledMetric{Granularity: aws.String("1Minute"), Metric: aws.String("GroupMaxSize")}, 846 } 847 848 result := flattenAsgEnabledMetrics(expanded) 849 850 if len(result) != 2 { 851 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 852 } 853 854 if result[0] != "GroupTotalInstances" { 855 t.Fatalf("expected id to be GroupTotalInstances, but was %s", result[0]) 856 } 857 858 if result[1] != "GroupMaxSize" { 859 t.Fatalf("expected id to be GroupMaxSize, but was %s", result[1]) 860 } 861 } 862 863 func TestFlattenKinesisShardLevelMetrics(t *testing.T) { 864 expanded := []*kinesis.EnhancedMetrics{ 865 &kinesis.EnhancedMetrics{ 866 ShardLevelMetrics: []*string{ 867 aws.String("IncomingBytes"), 868 aws.String("IncomingRecords"), 869 }, 870 }, 871 } 872 result := flattenKinesisShardLevelMetrics(expanded) 873 if len(result) != 2 { 874 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 875 } 876 if result[0] != "IncomingBytes" { 877 t.Fatalf("expected element 0 to be IncomingBytes, but was %s", result[0]) 878 } 879 if result[1] != "IncomingRecords" { 880 t.Fatalf("expected element 0 to be IncomingRecords, but was %s", result[1]) 881 } 882 } 883 884 func TestFlattenSecurityGroups(t *testing.T) { 885 cases := []struct { 886 ownerId *string 887 pairs []*ec2.UserIdGroupPair 888 expected []*ec2.GroupIdentifier 889 }{ 890 // simple, no user id included (we ignore it mostly) 891 { 892 ownerId: aws.String("user1234"), 893 pairs: []*ec2.UserIdGroupPair{ 894 &ec2.UserIdGroupPair{ 895 GroupId: aws.String("sg-12345"), 896 }, 897 }, 898 expected: []*ec2.GroupIdentifier{ 899 &ec2.GroupIdentifier{ 900 GroupId: aws.String("sg-12345"), 901 }, 902 }, 903 }, 904 // include the owner id, but keep it consitent with the same account. Tests 905 // EC2 classic situation 906 { 907 ownerId: aws.String("user1234"), 908 pairs: []*ec2.UserIdGroupPair{ 909 &ec2.UserIdGroupPair{ 910 GroupId: aws.String("sg-12345"), 911 UserId: aws.String("user1234"), 912 }, 913 }, 914 expected: []*ec2.GroupIdentifier{ 915 &ec2.GroupIdentifier{ 916 GroupId: aws.String("sg-12345"), 917 }, 918 }, 919 }, 920 921 // include the owner id, but from a different account. This is reflects 922 // EC2 Classic when referring to groups by name 923 { 924 ownerId: aws.String("user1234"), 925 pairs: []*ec2.UserIdGroupPair{ 926 &ec2.UserIdGroupPair{ 927 GroupId: aws.String("sg-12345"), 928 GroupName: aws.String("somegroup"), // GroupName is only included in Classic 929 UserId: aws.String("user4321"), 930 }, 931 }, 932 expected: []*ec2.GroupIdentifier{ 933 &ec2.GroupIdentifier{ 934 GroupId: aws.String("sg-12345"), 935 GroupName: aws.String("user4321/somegroup"), 936 }, 937 }, 938 }, 939 940 // include the owner id, but from a different account. This reflects in 941 // EC2 VPC when referring to groups by id 942 { 943 ownerId: aws.String("user1234"), 944 pairs: []*ec2.UserIdGroupPair{ 945 &ec2.UserIdGroupPair{ 946 GroupId: aws.String("sg-12345"), 947 UserId: aws.String("user4321"), 948 }, 949 }, 950 expected: []*ec2.GroupIdentifier{ 951 &ec2.GroupIdentifier{ 952 GroupId: aws.String("user4321/sg-12345"), 953 }, 954 }, 955 }, 956 } 957 958 for _, c := range cases { 959 out := flattenSecurityGroups(c.pairs, c.ownerId) 960 if !reflect.DeepEqual(out, c.expected) { 961 t.Fatalf("Error matching output and expected: %#v vs %#v", out, c.expected) 962 } 963 } 964 } 965 966 func TestFlattenApiGatewayThrottleSettings(t *testing.T) { 967 expectedBurstLimit := int64(140) 968 expectedRateLimit := 120.0 969 970 ts := &apigateway.ThrottleSettings{ 971 BurstLimit: aws.Int64(expectedBurstLimit), 972 RateLimit: aws.Float64(expectedRateLimit), 973 } 974 result := flattenApiGatewayThrottleSettings(ts) 975 976 if len(result) != 1 { 977 t.Fatalf("Expected map to have exactly 1 element, got %d", len(result)) 978 } 979 980 burstLimit, ok := result[0]["burst_limit"] 981 if !ok { 982 t.Fatal("Expected 'burst_limit' key in the map") 983 } 984 burstLimitInt, ok := burstLimit.(int64) 985 if !ok { 986 t.Fatal("Expected 'burst_limit' to be int") 987 } 988 if burstLimitInt != expectedBurstLimit { 989 t.Fatalf("Expected 'burst_limit' to equal %d, got %d", expectedBurstLimit, burstLimitInt) 990 } 991 992 rateLimit, ok := result[0]["rate_limit"] 993 if !ok { 994 t.Fatal("Expected 'rate_limit' key in the map") 995 } 996 rateLimitFloat, ok := rateLimit.(float64) 997 if !ok { 998 t.Fatal("Expected 'rate_limit' to be float64") 999 } 1000 if rateLimitFloat != expectedRateLimit { 1001 t.Fatalf("Expected 'rate_limit' to equal %f, got %f", expectedRateLimit, rateLimitFloat) 1002 } 1003 } 1004 1005 func TestFlattenApiGatewayStageKeys(t *testing.T) { 1006 cases := []struct { 1007 Input []*string 1008 Output []map[string]interface{} 1009 }{ 1010 { 1011 Input: []*string{ 1012 aws.String("a1b2c3d4e5/dev"), 1013 aws.String("e5d4c3b2a1/test"), 1014 }, 1015 Output: []map[string]interface{}{ 1016 map[string]interface{}{ 1017 "stage_name": "dev", 1018 "rest_api_id": "a1b2c3d4e5", 1019 }, 1020 map[string]interface{}{ 1021 "stage_name": "test", 1022 "rest_api_id": "e5d4c3b2a1", 1023 }, 1024 }, 1025 }, 1026 } 1027 1028 for _, tc := range cases { 1029 output := flattenApiGatewayStageKeys(tc.Input) 1030 if !reflect.DeepEqual(output, tc.Output) { 1031 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 1032 } 1033 } 1034 } 1035 1036 func TestExpandPolicyAttributes(t *testing.T) { 1037 expanded := []interface{}{ 1038 map[string]interface{}{ 1039 "name": "Protocol-TLSv1", 1040 "value": "false", 1041 }, 1042 map[string]interface{}{ 1043 "name": "Protocol-TLSv1.1", 1044 "value": "false", 1045 }, 1046 map[string]interface{}{ 1047 "name": "Protocol-TLSv1.2", 1048 "value": "true", 1049 }, 1050 } 1051 attributes, err := expandPolicyAttributes(expanded) 1052 if err != nil { 1053 t.Fatalf("bad: %#v", err) 1054 } 1055 1056 if len(attributes) != 3 { 1057 t.Fatalf("expected number of attributes to be 3, but got %d", len(attributes)) 1058 } 1059 1060 expected := &elb.PolicyAttribute{ 1061 AttributeName: aws.String("Protocol-TLSv1.2"), 1062 AttributeValue: aws.String("true"), 1063 } 1064 1065 if !reflect.DeepEqual(attributes[2], expected) { 1066 t.Fatalf( 1067 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 1068 attributes[2], 1069 expected) 1070 } 1071 } 1072 1073 func TestExpandPolicyAttributes_invalid(t *testing.T) { 1074 expanded := []interface{}{ 1075 map[string]interface{}{ 1076 "name": "Protocol-TLSv1.2", 1077 "value": "true", 1078 }, 1079 } 1080 attributes, err := expandPolicyAttributes(expanded) 1081 if err != nil { 1082 t.Fatalf("bad: %#v", err) 1083 } 1084 1085 expected := &elb.PolicyAttribute{ 1086 AttributeName: aws.String("Protocol-TLSv1.2"), 1087 AttributeValue: aws.String("false"), 1088 } 1089 1090 if reflect.DeepEqual(attributes[0], expected) { 1091 t.Fatalf( 1092 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 1093 attributes[0], 1094 expected) 1095 } 1096 } 1097 1098 func TestExpandPolicyAttributes_empty(t *testing.T) { 1099 var expanded []interface{} 1100 1101 attributes, err := expandPolicyAttributes(expanded) 1102 if err != nil { 1103 t.Fatalf("bad: %#v", err) 1104 } 1105 1106 if len(attributes) != 0 { 1107 t.Fatalf("expected number of attributes to be 0, but got %d", len(attributes)) 1108 } 1109 } 1110 1111 func TestFlattenPolicyAttributes(t *testing.T) { 1112 cases := []struct { 1113 Input []*elb.PolicyAttributeDescription 1114 Output []interface{} 1115 }{ 1116 { 1117 Input: []*elb.PolicyAttributeDescription{ 1118 &elb.PolicyAttributeDescription{ 1119 AttributeName: aws.String("Protocol-TLSv1.2"), 1120 AttributeValue: aws.String("true"), 1121 }, 1122 }, 1123 Output: []interface{}{ 1124 map[string]string{ 1125 "name": "Protocol-TLSv1.2", 1126 "value": "true", 1127 }, 1128 }, 1129 }, 1130 } 1131 1132 for _, tc := range cases { 1133 output := flattenPolicyAttributes(tc.Input) 1134 if !reflect.DeepEqual(output, tc.Output) { 1135 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 1136 } 1137 } 1138 } 1139 1140 func TestNormalizeJsonString(t *testing.T) { 1141 var err error 1142 var actual string 1143 1144 // Well formatted and valid. 1145 validJson := `{ 1146 "abc": { 1147 "def": 123, 1148 "xyz": [ 1149 { 1150 "a": "ホリネズミ" 1151 }, 1152 { 1153 "b": "1\\n2" 1154 } 1155 ] 1156 } 1157 }` 1158 expected := `{"abc":{"def":123,"xyz":[{"a":"ホリネズミ"},{"b":"1\\n2"}]}}` 1159 1160 actual, err = normalizeJsonString(validJson) 1161 if err != nil { 1162 t.Fatalf("Expected not to throw an error while parsing JSON, but got: %s", err) 1163 } 1164 1165 if actual != expected { 1166 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, expected) 1167 } 1168 1169 // Well formatted but not valid, 1170 // missing closing squre bracket. 1171 invalidJson := `{ 1172 "abc": { 1173 "def": 123, 1174 "xyz": [ 1175 { 1176 "a": "1" 1177 } 1178 } 1179 } 1180 }` 1181 actual, err = normalizeJsonString(invalidJson) 1182 if err == nil { 1183 t.Fatalf("Expected to throw an error while parsing JSON, but got: %s", err) 1184 } 1185 1186 // We expect the invalid JSON to be shown back to us again. 1187 if actual != invalidJson { 1188 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", expected, invalidJson) 1189 } 1190 } 1191 1192 func TestCheckYamlString(t *testing.T) { 1193 var err error 1194 var actual string 1195 1196 validYaml := `--- 1197 abc: 1198 def: 123 1199 xyz: 1200 - 1201 a: "ホリネズミ" 1202 b: "1" 1203 ` 1204 1205 actual, err = checkYamlString(validYaml) 1206 if err != nil { 1207 t.Fatalf("Expected not to throw an error while parsing YAML, but got: %s", err) 1208 } 1209 1210 // We expect the same YAML string back 1211 if actual != validYaml { 1212 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validYaml) 1213 } 1214 1215 invalidYaml := `abc: [` 1216 1217 actual, err = checkYamlString(invalidYaml) 1218 if err == nil { 1219 t.Fatalf("Expected to throw an error while parsing YAML, but got: %s", err) 1220 } 1221 1222 // We expect the invalid YAML to be shown back to us again. 1223 if actual != invalidYaml { 1224 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, invalidYaml) 1225 } 1226 } 1227 1228 func TestNormalizeCloudFormationTemplate(t *testing.T) { 1229 var err error 1230 var actual string 1231 1232 validNormalizedJson := `{"abc":"1"}` 1233 actual, err = normalizeCloudFormationTemplate(validNormalizedJson) 1234 if err != nil { 1235 t.Fatalf("Expected not to throw an error while parsing template, but got: %s", err) 1236 } 1237 if actual != validNormalizedJson { 1238 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validNormalizedJson) 1239 } 1240 1241 validNormalizedYaml := `abc: 1 1242 ` 1243 actual, err = normalizeCloudFormationTemplate(validNormalizedYaml) 1244 if err != nil { 1245 t.Fatalf("Expected not to throw an error while parsing template, but got: %s", err) 1246 } 1247 if actual != validNormalizedYaml { 1248 t.Fatalf("Got:\n\n%s\n\nExpected:\n\n%s\n", actual, validNormalizedYaml) 1249 } 1250 }