Merge pull request #9857 from hashicorp/paddy_8822_fix_spot_fleet_ebs

provider/aws: Fix hashing of EBS volumes in spot fleet requests to prevent panics
This commit is contained in:
Paddy 2016-11-04 09:38:38 -07:00 committed by GitHub
commit a15726d069
2 changed files with 111 additions and 3 deletions

View File

@ -805,7 +805,7 @@ func launchSpecToMap(
}
func ebsBlockDevicesToSet(bdm []*ec2.BlockDeviceMapping, rootDevName *string) *schema.Set {
set := &schema.Set{F: hashEphemeralBlockDevice}
set := &schema.Set{F: hashEbsBlockDevice}
for _, val := range bdm {
if val.Ebs != nil {
@ -1009,7 +1009,11 @@ func hashLaunchSpecification(v interface{}) int {
func hashEbsBlockDevice(v interface{}) int {
var buf bytes.Buffer
m := v.(map[string]interface{})
buf.WriteString(fmt.Sprintf("%s-", m["device_name"].(string)))
buf.WriteString(fmt.Sprintf("%s-", m["snapshot_id"].(string)))
if name, ok := m["device_name"]; ok {
buf.WriteString(fmt.Sprintf("%s-", name.(string)))
}
if id, ok := m["snapshot_id"]; ok {
buf.WriteString(fmt.Sprintf("%s-", id.(string)))
}
return hashcode.String(buf.String())
}

View File

@ -293,6 +293,28 @@ func TestAccAWSSpotFleetRequest_withWeightedCapacity(t *testing.T) {
})
}
func TestAccAWSSpotFleetRequest_withEBSDisk(t *testing.T) {
var config ec2.SpotFleetRequestConfig
rName := acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSpotFleetRequestDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSSpotFleetRequestEBSConfig(rName),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckAWSSpotFleetRequestExists(
"aws_spot_fleet_request.foo", &config),
testAccCheckAWSSpotFleetRequest_EBSAttributes(
&config),
),
},
},
})
}
func TestAccAWSSpotFleetRequest_CannotUseEmptyKeyName(t *testing.T) {
_, errors := validateSpotFleetRequestKeyName("", "key_name")
if len(errors) == 0 {
@ -376,6 +398,31 @@ func testAccCheckAWSSpotFleetRequest_LaunchSpecAttributes(
}
}
func testAccCheckAWSSpotFleetRequest_EBSAttributes(
sfr *ec2.SpotFleetRequestConfig) resource.TestCheckFunc {
return func(s *terraform.State) error {
if len(sfr.SpotFleetRequestConfig.LaunchSpecifications) == 0 {
return fmt.Errorf("Missing launch specification")
}
spec := *sfr.SpotFleetRequestConfig.LaunchSpecifications[0]
ebs := spec.BlockDeviceMappings
if len(ebs) < 2 {
return fmt.Errorf("Expected %d block device mappings, got %d", 2, len(ebs))
}
if *ebs[0].DeviceName != "/dev/xvda" {
return fmt.Errorf("Expected device 0's name to be %s, got %s", "/dev/xvda", *ebs[0].DeviceName)
}
if *ebs[1].DeviceName != "/dev/xvdcz" {
return fmt.Errorf("Expected device 1's name to be %s, got %s", "/dev/xvdcz", *ebs[1].DeviceName)
}
return nil
}
}
func testAccCheckAWSSpotFleetRequestDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*AWSClient).ec2conn
@ -940,3 +987,60 @@ resource "aws_spot_fleet_request" "foo" {
}
`, rName, rName)
}
func testAccAWSSpotFleetRequestEBSConfig(rName string) string {
return fmt.Sprintf(`
resource "aws_iam_policy_attachment" "test-attach" {
name = "test-attachment"
roles = ["${aws_iam_role.test-role.name}"]
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2SpotFleetRole"
}
resource "aws_iam_role" "test-role" {
name = "test-role-%s"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": [
"spotfleet.amazonaws.com",
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_spot_fleet_request" "foo" {
iam_fleet_role = "${aws_iam_role.test-role.arn}"
spot_price = "0.005"
target_capacity = 1
valid_until = "2019-11-04T20:44:20Z"
terminate_instances_with_expiration = true
launch_specification {
instance_type = "m1.small"
ami = "ami-d06a90b0"
ebs_block_device {
device_name = "/dev/xvda"
volume_type = "gp2"
volume_size = "8"
}
ebs_block_device {
device_name = "/dev/xvdcz"
volume_type = "gp2"
volume_size = "100"
}
}
depends_on = ["aws_iam_policy_attachment.test-attach"]
}
`, rName)
}