providers/aws: derive instance root_block_device name
I was working on building a validation to check the user-provided "device_name" for "root_block_device" on AWS Instances, when I realized that if I can check it, I might as well just derive it automatically! So that's what we do here - when you customize the details of the root block device, device name is just comes from the selected AMI.
This commit is contained in:
parent
55d682482a
commit
a4e80b6313
|
@ -265,13 +265,6 @@ func resourceAwsInstance() *schema.Resource {
|
|||
ForceNew: true,
|
||||
},
|
||||
|
||||
"device_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
ForceNew: true,
|
||||
Default: "/dev/sda1",
|
||||
},
|
||||
|
||||
"iops": &schema.Schema{
|
||||
Type: schema.TypeInt,
|
||||
Optional: true,
|
||||
|
@ -298,7 +291,6 @@ func resourceAwsInstance() *schema.Resource {
|
|||
var buf bytes.Buffer
|
||||
m := v.(map[string]interface{})
|
||||
buf.WriteString(fmt.Sprintf("%t-", m["delete_on_termination"].(bool)))
|
||||
buf.WriteString(fmt.Sprintf("%s-", m["device_name"].(string)))
|
||||
// See the NOTE in "ebs_block_device" for why we skip iops here.
|
||||
// buf.WriteString(fmt.Sprintf("%d-", m["iops"].(int)))
|
||||
buf.WriteString(fmt.Sprintf("%d-", m["volume_size"].(int)))
|
||||
|
@ -478,10 +470,14 @@ func resourceAwsInstanceCreate(d *schema.ResourceData, meta interface{}) error {
|
|||
ebs.IOPS = aws.Integer(v)
|
||||
}
|
||||
|
||||
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
|
||||
DeviceName: aws.String(bd["device_name"].(string)),
|
||||
EBS: ebs,
|
||||
})
|
||||
if dn, err := fetchRootDeviceName(d.Get("ami").(string), ec2conn); err == nil {
|
||||
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
|
||||
DeviceName: dn,
|
||||
EBS: ebs,
|
||||
})
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -778,9 +774,6 @@ func readBlockDevicesFromInstance(instance *ec2.Instance, ec2conn *ec2.EC2) (map
|
|||
if instanceBd.EBS != nil && instanceBd.EBS.DeleteOnTermination != nil {
|
||||
bd["delete_on_termination"] = *instanceBd.EBS.DeleteOnTermination
|
||||
}
|
||||
if instanceBd.DeviceName != nil {
|
||||
bd["device_name"] = *instanceBd.DeviceName
|
||||
}
|
||||
if vol.Size != nil {
|
||||
bd["volume_size"] = *vol.Size
|
||||
}
|
||||
|
@ -794,6 +787,9 @@ func readBlockDevicesFromInstance(instance *ec2.Instance, ec2conn *ec2.EC2) (map
|
|||
if blockDeviceIsRoot(instanceBd, instance) {
|
||||
blockDevices["root"] = bd
|
||||
} else {
|
||||
if instanceBd.DeviceName != nil {
|
||||
bd["device_name"] = *instanceBd.DeviceName
|
||||
}
|
||||
if vol.Encrypted != nil {
|
||||
bd["encrypted"] = *vol.Encrypted
|
||||
}
|
||||
|
@ -813,3 +809,21 @@ func blockDeviceIsRoot(bd ec2.InstanceBlockDeviceMapping, instance *ec2.Instance
|
|||
instance.RootDeviceName != nil &&
|
||||
*bd.DeviceName == *instance.RootDeviceName)
|
||||
}
|
||||
|
||||
func fetchRootDeviceName(ami string, conn *ec2.EC2) (aws.StringValue, error) {
|
||||
if ami == "" {
|
||||
return nil, fmt.Errorf("Cannot fetch root device name for blank AMI ID.")
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Describing AMI %q to get root block device name", ami)
|
||||
req := &ec2.DescribeImagesRequest{ImageIDs: []string{ami}}
|
||||
if res, err := conn.DescribeImages(req); err == nil {
|
||||
if len(res.Images) == 1 {
|
||||
return res.Images[0].RootDeviceName, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("Expected 1 AMI for ID: %s, got: %#v", ami, res.Images)
|
||||
}
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
@ -140,11 +140,9 @@ func TestAccAWSInstance_blockDevices(t *testing.T) {
|
|||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.#", "1"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.1246122048.device_name", "/dev/sda1"),
|
||||
"aws_instance.foo", "root_block_device.1023169747.volume_size", "11"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.1246122048.volume_size", "11"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "root_block_device.1246122048.volume_type", "gp2"),
|
||||
"aws_instance.foo", "root_block_device.1023169747.volume_type", "gp2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
"aws_instance.foo", "ebs_block_device.#", "2"),
|
||||
resource.TestCheckResourceAttr(
|
||||
|
@ -467,7 +465,6 @@ resource "aws_instance" "foo" {
|
|||
instance_type = "m1.small"
|
||||
|
||||
root_block_device {
|
||||
device_name = "/dev/sda1"
|
||||
volume_type = "gp2"
|
||||
volume_size = 11
|
||||
}
|
||||
|
|
|
@ -66,9 +66,6 @@ to understand the implications of using these attributes.
|
|||
|
||||
The `root_block_device` mapping supports the following:
|
||||
|
||||
* `device_name` - The name of the root device on the target instance. Must
|
||||
match the root device as defined in the AMI. Defaults to `"/dev/sda1"`, which
|
||||
is the typical root volume for Linux instances.
|
||||
* `volume_type` - (Optional) The type of volume. Can be `"standard"`, `"gp2"`,
|
||||
or `"io1"`. (Default: `"standard"`).
|
||||
* `volume_size` - (Optional) The size of the volume in gigabytes.
|
||||
|
|
Loading…
Reference in New Issue