Merge pull request #2271 from hashicorp/b-root-block-device-ami-mismatch
provider/aws: fix root_block_device for odd AMIs
This commit is contained in:
commit
86b9f5aa7a
|
@ -709,18 +709,44 @@ func fetchRootDeviceName(ami string, conn *ec2.EC2) (*string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("[DEBUG] Describing AMI %q to get root block device name", ami)
|
log.Printf("[DEBUG] Describing AMI %q to get root block device name", ami)
|
||||||
req := &ec2.DescribeImagesInput{ImageIDs: []*string{aws.String(ami)}}
|
res, err := conn.DescribeImages(&ec2.DescribeImagesInput{
|
||||||
if res, err := conn.DescribeImages(req); err == nil {
|
ImageIDs: []*string{aws.String(ami)},
|
||||||
if len(res.Images) == 1 {
|
})
|
||||||
return res.Images[0].RootDeviceName, nil
|
if err != nil {
|
||||||
} else if len(res.Images) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("Expected 1 AMI for ID: %s, got: %#v", ami, res.Images)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For a bad image, we just return nil so we don't block a refresh
|
||||||
|
if len(res.Images) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
image := res.Images[0]
|
||||||
|
rootDeviceName := image.RootDeviceName
|
||||||
|
|
||||||
|
// Some AMIs have a RootDeviceName like "/dev/sda1" that does not appear as a
|
||||||
|
// DeviceName in the BlockDeviceMapping list (which will instead have
|
||||||
|
// something like "/dev/sda")
|
||||||
|
//
|
||||||
|
// While this seems like it breaks an invariant of AMIs, it ends up working
|
||||||
|
// on the AWS side, and AMIs like this are common enough that we need to
|
||||||
|
// special case it so Terraform does the right thing.
|
||||||
|
//
|
||||||
|
// Our heuristic is: if the RootDeviceName does not appear in the
|
||||||
|
// BlockDeviceMapping, assume that the DeviceName of the first
|
||||||
|
// BlockDeviceMapping entry serves as the root device.
|
||||||
|
rootDeviceNameInMapping := false
|
||||||
|
for _, bdm := range image.BlockDeviceMappings {
|
||||||
|
if bdm.DeviceName == image.RootDeviceName {
|
||||||
|
rootDeviceNameInMapping = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !rootDeviceNameInMapping && len(image.BlockDeviceMappings) > 0 {
|
||||||
|
rootDeviceName = image.BlockDeviceMappings[0].DeviceName
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootDeviceName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readBlockDeviceMappingsFromConfig(
|
func readBlockDeviceMappingsFromConfig(
|
||||||
|
|
|
@ -491,6 +491,26 @@ func TestAccAWSInstance_keyPairCheck(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAccAWSInstance_rootBlockDeviceMismatch(t *testing.T) {
|
||||||
|
var v ec2.Instance
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckInstanceDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
resource.TestStep{
|
||||||
|
Config: testAccInstanceConfigRootBlockDeviceMismatch,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckInstanceExists("aws_instance.foo", &v),
|
||||||
|
resource.TestCheckResourceAttr(
|
||||||
|
"aws_instance.foo", "root_block_device.0.volume_size", "13"),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func testAccCheckInstanceDestroy(s *terraform.State) error {
|
func testAccCheckInstanceDestroy(s *terraform.State) error {
|
||||||
return testAccCheckInstanceDestroyWithProvider(s, testAccProvider)
|
return testAccCheckInstanceDestroyWithProvider(s, testAccProvider)
|
||||||
}
|
}
|
||||||
|
@ -924,6 +944,7 @@ resource "aws_eip" "foo_eip" {
|
||||||
depends_on = ["aws_internet_gateway.gw"]
|
depends_on = ["aws_internet_gateway.gw"]
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const testAccInstanceConfigKeyPair = `
|
const testAccInstanceConfigKeyPair = `
|
||||||
provider "aws" {
|
provider "aws" {
|
||||||
region = "us-east-1"
|
region = "us-east-1"
|
||||||
|
@ -940,3 +961,24 @@ resource "aws_instance" "foo" {
|
||||||
key_name = "${aws_key_pair.debugging.key_name}"
|
key_name = "${aws_key_pair.debugging.key_name}"
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const testAccInstanceConfigRootBlockDeviceMismatch = `
|
||||||
|
resource "aws_vpc" "foo" {
|
||||||
|
cidr_block = "10.1.0.0/16"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_subnet" "foo" {
|
||||||
|
cidr_block = "10.1.1.0/24"
|
||||||
|
vpc_id = "${aws_vpc.foo.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "foo" {
|
||||||
|
// This is an AMI with RootDeviceName: "/dev/sda1"; actual root: "/dev/sda"
|
||||||
|
ami = "ami-ef5b69df"
|
||||||
|
instance_type = "t1.micro"
|
||||||
|
subnet_id = "${aws_subnet.foo.id}"
|
||||||
|
root_block_device {
|
||||||
|
volume_size = 13
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
Loading…
Reference in New Issue