github.com/leeprovoost/terraform@v0.6.10-0.20160119085442-96f3f76118e7/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/ec2" 10 "github.com/aws/aws-sdk-go/service/elasticache" 11 "github.com/aws/aws-sdk-go/service/elb" 12 "github.com/aws/aws-sdk-go/service/rds" 13 "github.com/aws/aws-sdk-go/service/redshift" 14 "github.com/aws/aws-sdk-go/service/route53" 15 "github.com/hashicorp/terraform/flatmap" 16 "github.com/hashicorp/terraform/helper/schema" 17 ) 18 19 // Returns test configuration 20 func testConf() map[string]string { 21 return map[string]string{ 22 "listener.#": "1", 23 "listener.0.lb_port": "80", 24 "listener.0.lb_protocol": "http", 25 "listener.0.instance_port": "8000", 26 "listener.0.instance_protocol": "http", 27 "availability_zones.#": "2", 28 "availability_zones.0": "us-east-1a", 29 "availability_zones.1": "us-east-1b", 30 "ingress.#": "1", 31 "ingress.0.protocol": "icmp", 32 "ingress.0.from_port": "1", 33 "ingress.0.to_port": "-1", 34 "ingress.0.cidr_blocks.#": "1", 35 "ingress.0.cidr_blocks.0": "0.0.0.0/0", 36 "ingress.0.security_groups.#": "2", 37 "ingress.0.security_groups.0": "sg-11111", 38 "ingress.0.security_groups.1": "foo/sg-22222", 39 } 40 } 41 42 func TestExpandIPPerms(t *testing.T) { 43 hash := schema.HashString 44 45 expanded := []interface{}{ 46 map[string]interface{}{ 47 "protocol": "icmp", 48 "from_port": 1, 49 "to_port": -1, 50 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 51 "security_groups": schema.NewSet(hash, []interface{}{ 52 "sg-11111", 53 "foo/sg-22222", 54 }), 55 }, 56 map[string]interface{}{ 57 "protocol": "icmp", 58 "from_port": 1, 59 "to_port": -1, 60 "self": true, 61 }, 62 } 63 group := &ec2.SecurityGroup{ 64 GroupId: aws.String("foo"), 65 VpcId: aws.String("bar"), 66 } 67 perms, err := expandIPPerms(group, expanded) 68 if err != nil { 69 t.Fatalf("error expanding perms: %v", err) 70 } 71 72 expected := []ec2.IpPermission{ 73 ec2.IpPermission{ 74 IpProtocol: aws.String("icmp"), 75 FromPort: aws.Int64(int64(1)), 76 ToPort: aws.Int64(int64(-1)), 77 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 78 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 79 &ec2.UserIdGroupPair{ 80 UserId: aws.String("foo"), 81 GroupId: aws.String("sg-22222"), 82 }, 83 &ec2.UserIdGroupPair{ 84 GroupId: aws.String("sg-22222"), 85 }, 86 }, 87 }, 88 ec2.IpPermission{ 89 IpProtocol: aws.String("icmp"), 90 FromPort: aws.Int64(int64(1)), 91 ToPort: aws.Int64(int64(-1)), 92 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 93 &ec2.UserIdGroupPair{ 94 UserId: aws.String("foo"), 95 }, 96 }, 97 }, 98 } 99 100 exp := expected[0] 101 perm := perms[0] 102 103 if *exp.FromPort != *perm.FromPort { 104 t.Fatalf( 105 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 106 *perm.FromPort, 107 *exp.FromPort) 108 } 109 110 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 111 t.Fatalf( 112 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 113 *perm.IpRanges[0].CidrIp, 114 *exp.IpRanges[0].CidrIp) 115 } 116 117 if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId { 118 t.Fatalf( 119 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 120 *perm.UserIdGroupPairs[0].UserId, 121 *exp.UserIdGroupPairs[0].UserId) 122 } 123 124 } 125 126 func TestExpandIPPerms_NegOneProtocol(t *testing.T) { 127 hash := schema.HashString 128 129 expanded := []interface{}{ 130 map[string]interface{}{ 131 "protocol": "-1", 132 "from_port": 0, 133 "to_port": 0, 134 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 135 "security_groups": schema.NewSet(hash, []interface{}{ 136 "sg-11111", 137 "foo/sg-22222", 138 }), 139 }, 140 } 141 group := &ec2.SecurityGroup{ 142 GroupId: aws.String("foo"), 143 VpcId: aws.String("bar"), 144 } 145 146 perms, err := expandIPPerms(group, expanded) 147 if err != nil { 148 t.Fatalf("error expanding perms: %v", err) 149 } 150 151 expected := []ec2.IpPermission{ 152 ec2.IpPermission{ 153 IpProtocol: aws.String("-1"), 154 FromPort: aws.Int64(int64(0)), 155 ToPort: aws.Int64(int64(0)), 156 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 157 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 158 &ec2.UserIdGroupPair{ 159 UserId: aws.String("foo"), 160 GroupId: aws.String("sg-22222"), 161 }, 162 &ec2.UserIdGroupPair{ 163 GroupId: aws.String("sg-22222"), 164 }, 165 }, 166 }, 167 } 168 169 exp := expected[0] 170 perm := perms[0] 171 172 if *exp.FromPort != *perm.FromPort { 173 t.Fatalf( 174 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 175 *perm.FromPort, 176 *exp.FromPort) 177 } 178 179 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 180 t.Fatalf( 181 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 182 *perm.IpRanges[0].CidrIp, 183 *exp.IpRanges[0].CidrIp) 184 } 185 186 if *exp.UserIdGroupPairs[0].UserId != *perm.UserIdGroupPairs[0].UserId { 187 t.Fatalf( 188 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 189 *perm.UserIdGroupPairs[0].UserId, 190 *exp.UserIdGroupPairs[0].UserId) 191 } 192 193 // Now test the error case. This *should* error when either from_port 194 // or to_port is not zero, but protocol is "-1". 195 errorCase := []interface{}{ 196 map[string]interface{}{ 197 "protocol": "-1", 198 "from_port": 0, 199 "to_port": 65535, 200 "cidr_blocks": []interface{}{"0.0.0.0/0"}, 201 "security_groups": schema.NewSet(hash, []interface{}{ 202 "sg-11111", 203 "foo/sg-22222", 204 }), 205 }, 206 } 207 securityGroups := &ec2.SecurityGroup{ 208 GroupId: aws.String("foo"), 209 VpcId: aws.String("bar"), 210 } 211 212 _, expandErr := expandIPPerms(securityGroups, errorCase) 213 if expandErr == nil { 214 t.Fatal("expandIPPerms should have errored!") 215 } 216 } 217 218 func TestExpandIPPerms_nonVPC(t *testing.T) { 219 hash := schema.HashString 220 221 expanded := []interface{}{ 222 map[string]interface{}{ 223 "protocol": "icmp", 224 "from_port": 1, 225 "to_port": -1, 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 map[string]interface{}{ 233 "protocol": "icmp", 234 "from_port": 1, 235 "to_port": -1, 236 "self": true, 237 }, 238 } 239 group := &ec2.SecurityGroup{ 240 GroupName: aws.String("foo"), 241 } 242 perms, err := expandIPPerms(group, expanded) 243 if err != nil { 244 t.Fatalf("error expanding perms: %v", err) 245 } 246 247 expected := []ec2.IpPermission{ 248 ec2.IpPermission{ 249 IpProtocol: aws.String("icmp"), 250 FromPort: aws.Int64(int64(1)), 251 ToPort: aws.Int64(int64(-1)), 252 IpRanges: []*ec2.IpRange{&ec2.IpRange{CidrIp: aws.String("0.0.0.0/0")}}, 253 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 254 &ec2.UserIdGroupPair{ 255 GroupName: aws.String("sg-22222"), 256 }, 257 &ec2.UserIdGroupPair{ 258 GroupName: aws.String("sg-22222"), 259 }, 260 }, 261 }, 262 ec2.IpPermission{ 263 IpProtocol: aws.String("icmp"), 264 FromPort: aws.Int64(int64(1)), 265 ToPort: aws.Int64(int64(-1)), 266 UserIdGroupPairs: []*ec2.UserIdGroupPair{ 267 &ec2.UserIdGroupPair{ 268 GroupName: aws.String("foo"), 269 }, 270 }, 271 }, 272 } 273 274 exp := expected[0] 275 perm := perms[0] 276 277 if *exp.FromPort != *perm.FromPort { 278 t.Fatalf( 279 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 280 *perm.FromPort, 281 *exp.FromPort) 282 } 283 284 if *exp.IpRanges[0].CidrIp != *perm.IpRanges[0].CidrIp { 285 t.Fatalf( 286 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 287 *perm.IpRanges[0].CidrIp, 288 *exp.IpRanges[0].CidrIp) 289 } 290 } 291 292 func TestExpandListeners(t *testing.T) { 293 expanded := []interface{}{ 294 map[string]interface{}{ 295 "instance_port": 8000, 296 "lb_port": 80, 297 "instance_protocol": "http", 298 "lb_protocol": "http", 299 }, 300 map[string]interface{}{ 301 "instance_port": 8000, 302 "lb_port": 80, 303 "instance_protocol": "https", 304 "lb_protocol": "https", 305 "ssl_certificate_id": "something", 306 }, 307 } 308 listeners, err := expandListeners(expanded) 309 if err != nil { 310 t.Fatalf("bad: %#v", err) 311 } 312 313 expected := &elb.Listener{ 314 InstancePort: aws.Int64(int64(8000)), 315 LoadBalancerPort: aws.Int64(int64(80)), 316 InstanceProtocol: aws.String("http"), 317 Protocol: aws.String("http"), 318 } 319 320 if !reflect.DeepEqual(listeners[0], expected) { 321 t.Fatalf( 322 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 323 listeners[0], 324 expected) 325 } 326 } 327 328 // this test should produce an error from expandlisteners on an invalid 329 // combination 330 func TestExpandListeners_invalid(t *testing.T) { 331 expanded := []interface{}{ 332 map[string]interface{}{ 333 "instance_port": 8000, 334 "lb_port": 80, 335 "instance_protocol": "http", 336 "lb_protocol": "http", 337 "ssl_certificate_id": "something", 338 }, 339 } 340 _, err := expandListeners(expanded) 341 if err != nil { 342 // Check the error we got 343 if !strings.Contains(err.Error(), "ssl_certificate_id may be set only when protocol") { 344 t.Fatalf("Got error in TestExpandListeners_invalid, but not what we expected: %s", err) 345 } 346 } 347 348 if err == nil { 349 t.Fatalf("Expected TestExpandListeners_invalid to fail, but passed") 350 } 351 } 352 353 func TestFlattenHealthCheck(t *testing.T) { 354 cases := []struct { 355 Input *elb.HealthCheck 356 Output []map[string]interface{} 357 }{ 358 { 359 Input: &elb.HealthCheck{ 360 UnhealthyThreshold: aws.Int64(int64(10)), 361 HealthyThreshold: aws.Int64(int64(10)), 362 Target: aws.String("HTTP:80/"), 363 Timeout: aws.Int64(int64(30)), 364 Interval: aws.Int64(int64(30)), 365 }, 366 Output: []map[string]interface{}{ 367 map[string]interface{}{ 368 "unhealthy_threshold": int64(10), 369 "healthy_threshold": int64(10), 370 "target": "HTTP:80/", 371 "timeout": int64(30), 372 "interval": int64(30), 373 }, 374 }, 375 }, 376 } 377 378 for _, tc := range cases { 379 output := flattenHealthCheck(tc.Input) 380 if !reflect.DeepEqual(output, tc.Output) { 381 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 382 } 383 } 384 } 385 386 func TestExpandStringList(t *testing.T) { 387 expanded := flatmap.Expand(testConf(), "availability_zones").([]interface{}) 388 stringList := expandStringList(expanded) 389 expected := []*string{ 390 aws.String("us-east-1a"), 391 aws.String("us-east-1b"), 392 } 393 394 if !reflect.DeepEqual(stringList, expected) { 395 t.Fatalf( 396 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 397 stringList, 398 expected) 399 } 400 401 } 402 403 func TestExpandParameters(t *testing.T) { 404 expanded := []interface{}{ 405 map[string]interface{}{ 406 "name": "character_set_client", 407 "value": "utf8", 408 "apply_method": "immediate", 409 }, 410 } 411 parameters, err := expandParameters(expanded) 412 if err != nil { 413 t.Fatalf("bad: %#v", err) 414 } 415 416 expected := &rds.Parameter{ 417 ParameterName: aws.String("character_set_client"), 418 ParameterValue: aws.String("utf8"), 419 ApplyMethod: aws.String("immediate"), 420 } 421 422 if !reflect.DeepEqual(parameters[0], expected) { 423 t.Fatalf( 424 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 425 parameters[0], 426 expected) 427 } 428 } 429 430 func TestexpandRedshiftParameters(t *testing.T) { 431 expanded := []interface{}{ 432 map[string]interface{}{ 433 "name": "character_set_client", 434 "value": "utf8", 435 }, 436 } 437 parameters, err := expandRedshiftParameters(expanded) 438 if err != nil { 439 t.Fatalf("bad: %#v", err) 440 } 441 442 expected := &redshift.Parameter{ 443 ParameterName: aws.String("character_set_client"), 444 ParameterValue: aws.String("utf8"), 445 } 446 447 if !reflect.DeepEqual(parameters[0], expected) { 448 t.Fatalf( 449 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 450 parameters[0], 451 expected) 452 } 453 } 454 455 func TestexpandElasticacheParameters(t *testing.T) { 456 expanded := []interface{}{ 457 map[string]interface{}{ 458 "name": "activerehashing", 459 "value": "yes", 460 "apply_method": "immediate", 461 }, 462 } 463 parameters, err := expandElastiCacheParameters(expanded) 464 if err != nil { 465 t.Fatalf("bad: %#v", err) 466 } 467 468 expected := &elasticache.ParameterNameValue{ 469 ParameterName: aws.String("activerehashing"), 470 ParameterValue: aws.String("yes"), 471 } 472 473 if !reflect.DeepEqual(parameters[0], expected) { 474 t.Fatalf( 475 "Got:\n\n%#v\n\nExpected:\n\n%#v\n", 476 parameters[0], 477 expected) 478 } 479 } 480 481 func TestFlattenParameters(t *testing.T) { 482 cases := []struct { 483 Input []*rds.Parameter 484 Output []map[string]interface{} 485 }{ 486 { 487 Input: []*rds.Parameter{ 488 &rds.Parameter{ 489 ParameterName: aws.String("character_set_client"), 490 ParameterValue: aws.String("utf8"), 491 }, 492 }, 493 Output: []map[string]interface{}{ 494 map[string]interface{}{ 495 "name": "character_set_client", 496 "value": "utf8", 497 }, 498 }, 499 }, 500 } 501 502 for _, tc := range cases { 503 output := flattenParameters(tc.Input) 504 if !reflect.DeepEqual(output, tc.Output) { 505 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 506 } 507 } 508 } 509 510 func TestflattenRedshiftParameters(t *testing.T) { 511 cases := []struct { 512 Input []*redshift.Parameter 513 Output []map[string]interface{} 514 }{ 515 { 516 Input: []*redshift.Parameter{ 517 &redshift.Parameter{ 518 ParameterName: aws.String("character_set_client"), 519 ParameterValue: aws.String("utf8"), 520 }, 521 }, 522 Output: []map[string]interface{}{ 523 map[string]interface{}{ 524 "name": "character_set_client", 525 "value": "utf8", 526 }, 527 }, 528 }, 529 } 530 531 for _, tc := range cases { 532 output := flattenRedshiftParameters(tc.Input) 533 if !reflect.DeepEqual(output, tc.Output) { 534 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 535 } 536 } 537 } 538 539 func TestflattenElasticacheParameters(t *testing.T) { 540 cases := []struct { 541 Input []*elasticache.Parameter 542 Output []map[string]interface{} 543 }{ 544 { 545 Input: []*elasticache.Parameter{ 546 &elasticache.Parameter{ 547 ParameterName: aws.String("activerehashing"), 548 ParameterValue: aws.String("yes"), 549 }, 550 }, 551 Output: []map[string]interface{}{ 552 map[string]interface{}{ 553 "name": "activerehashing", 554 "value": "yes", 555 }, 556 }, 557 }, 558 } 559 560 for _, tc := range cases { 561 output := flattenElastiCacheParameters(tc.Input) 562 if !reflect.DeepEqual(output, tc.Output) { 563 t.Fatalf("Got:\n\n%#v\n\nExpected:\n\n%#v", output, tc.Output) 564 } 565 } 566 } 567 568 func TestExpandInstanceString(t *testing.T) { 569 570 expected := []*elb.Instance{ 571 &elb.Instance{InstanceId: aws.String("test-one")}, 572 &elb.Instance{InstanceId: aws.String("test-two")}, 573 } 574 575 ids := []interface{}{ 576 "test-one", 577 "test-two", 578 } 579 580 expanded := expandInstanceString(ids) 581 582 if !reflect.DeepEqual(expanded, expected) { 583 t.Fatalf("Expand Instance String output did not match.\nGot:\n%#v\n\nexpected:\n%#v", expanded, expected) 584 } 585 } 586 587 func TestFlattenNetworkInterfacesPrivateIPAddresses(t *testing.T) { 588 expanded := []*ec2.NetworkInterfacePrivateIpAddress{ 589 &ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.1")}, 590 &ec2.NetworkInterfacePrivateIpAddress{PrivateIpAddress: aws.String("192.168.0.2")}, 591 } 592 593 result := flattenNetworkInterfacesPrivateIPAddresses(expanded) 594 595 if result == nil { 596 t.Fatal("result was nil") 597 } 598 599 if len(result) != 2 { 600 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 601 } 602 603 if result[0] != "192.168.0.1" { 604 t.Fatalf("expected ip to be 192.168.0.1, but was %s", result[0]) 605 } 606 607 if result[1] != "192.168.0.2" { 608 t.Fatalf("expected ip to be 192.168.0.2, but was %s", result[1]) 609 } 610 } 611 612 func TestFlattenGroupIdentifiers(t *testing.T) { 613 expanded := []*ec2.GroupIdentifier{ 614 &ec2.GroupIdentifier{GroupId: aws.String("sg-001")}, 615 &ec2.GroupIdentifier{GroupId: aws.String("sg-002")}, 616 } 617 618 result := flattenGroupIdentifiers(expanded) 619 620 if len(result) != 2 { 621 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 622 } 623 624 if result[0] != "sg-001" { 625 t.Fatalf("expected id to be sg-001, but was %s", result[0]) 626 } 627 628 if result[1] != "sg-002" { 629 t.Fatalf("expected id to be sg-002, but was %s", result[1]) 630 } 631 } 632 633 func TestExpandPrivateIPAddresses(t *testing.T) { 634 635 ip1 := "192.168.0.1" 636 ip2 := "192.168.0.2" 637 flattened := []interface{}{ 638 ip1, 639 ip2, 640 } 641 642 result := expandPrivateIPAddresses(flattened) 643 644 if len(result) != 2 { 645 t.Fatalf("expected result had %d elements, but got %d", 2, len(result)) 646 } 647 648 if *result[0].PrivateIpAddress != "192.168.0.1" || !*result[0].Primary { 649 t.Fatalf("expected ip to be 192.168.0.1 and Primary, but got %v, %t", *result[0].PrivateIpAddress, *result[0].Primary) 650 } 651 652 if *result[1].PrivateIpAddress != "192.168.0.2" || *result[1].Primary { 653 t.Fatalf("expected ip to be 192.168.0.2 and not Primary, but got %v, %t", *result[1].PrivateIpAddress, *result[1].Primary) 654 } 655 } 656 657 func TestFlattenAttachment(t *testing.T) { 658 expanded := &ec2.NetworkInterfaceAttachment{ 659 InstanceId: aws.String("i-00001"), 660 DeviceIndex: aws.Int64(int64(1)), 661 AttachmentId: aws.String("at-002"), 662 } 663 664 result := flattenAttachment(expanded) 665 666 if result == nil { 667 t.Fatal("expected result to have value, but got nil") 668 } 669 670 if result["instance"] != "i-00001" { 671 t.Fatalf("expected instance to be i-00001, but got %s", result["instance"]) 672 } 673 674 if result["device_index"] != int64(1) { 675 t.Fatalf("expected device_index to be 1, but got %d", result["device_index"]) 676 } 677 678 if result["attachment_id"] != "at-002" { 679 t.Fatalf("expected attachment_id to be at-002, but got %s", result["attachment_id"]) 680 } 681 } 682 683 func TestFlattenResourceRecords(t *testing.T) { 684 expanded := []*route53.ResourceRecord{ 685 &route53.ResourceRecord{ 686 Value: aws.String("127.0.0.1"), 687 }, 688 &route53.ResourceRecord{ 689 Value: aws.String("127.0.0.3"), 690 }, 691 } 692 693 result := flattenResourceRecords(expanded) 694 695 if result == nil { 696 t.Fatal("expected result to have value, but got nil") 697 } 698 699 if len(result) != 2 { 700 t.Fatal("expected result to have value, but got nil") 701 } 702 }