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,
|
ForceNew: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
"device_name": &schema.Schema{
|
|
||||||
Type: schema.TypeString,
|
|
||||||
Optional: true,
|
|
||||||
ForceNew: true,
|
|
||||||
Default: "/dev/sda1",
|
|
||||||
},
|
|
||||||
|
|
||||||
"iops": &schema.Schema{
|
"iops": &schema.Schema{
|
||||||
Type: schema.TypeInt,
|
Type: schema.TypeInt,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
@ -298,7 +291,6 @@ func resourceAwsInstance() *schema.Resource {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
m := v.(map[string]interface{})
|
m := v.(map[string]interface{})
|
||||||
buf.WriteString(fmt.Sprintf("%t-", m["delete_on_termination"].(bool)))
|
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.
|
// 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["iops"].(int)))
|
||||||
buf.WriteString(fmt.Sprintf("%d-", m["volume_size"].(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)
|
ebs.IOPS = aws.Integer(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dn, err := fetchRootDeviceName(d.Get("ami").(string), ec2conn); err == nil {
|
||||||
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
|
blockDevices = append(blockDevices, ec2.BlockDeviceMapping{
|
||||||
DeviceName: aws.String(bd["device_name"].(string)),
|
DeviceName: dn,
|
||||||
EBS: ebs,
|
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 {
|
if instanceBd.EBS != nil && instanceBd.EBS.DeleteOnTermination != nil {
|
||||||
bd["delete_on_termination"] = *instanceBd.EBS.DeleteOnTermination
|
bd["delete_on_termination"] = *instanceBd.EBS.DeleteOnTermination
|
||||||
}
|
}
|
||||||
if instanceBd.DeviceName != nil {
|
|
||||||
bd["device_name"] = *instanceBd.DeviceName
|
|
||||||
}
|
|
||||||
if vol.Size != nil {
|
if vol.Size != nil {
|
||||||
bd["volume_size"] = *vol.Size
|
bd["volume_size"] = *vol.Size
|
||||||
}
|
}
|
||||||
|
@ -794,6 +787,9 @@ func readBlockDevicesFromInstance(instance *ec2.Instance, ec2conn *ec2.EC2) (map
|
||||||
if blockDeviceIsRoot(instanceBd, instance) {
|
if blockDeviceIsRoot(instanceBd, instance) {
|
||||||
blockDevices["root"] = bd
|
blockDevices["root"] = bd
|
||||||
} else {
|
} else {
|
||||||
|
if instanceBd.DeviceName != nil {
|
||||||
|
bd["device_name"] = *instanceBd.DeviceName
|
||||||
|
}
|
||||||
if vol.Encrypted != nil {
|
if vol.Encrypted != nil {
|
||||||
bd["encrypted"] = *vol.Encrypted
|
bd["encrypted"] = *vol.Encrypted
|
||||||
}
|
}
|
||||||
|
@ -813,3 +809,21 @@ func blockDeviceIsRoot(bd ec2.InstanceBlockDeviceMapping, instance *ec2.Instance
|
||||||
instance.RootDeviceName != nil &&
|
instance.RootDeviceName != nil &&
|
||||||
*bd.DeviceName == *instance.RootDeviceName)
|
*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(
|
resource.TestCheckResourceAttr(
|
||||||
"aws_instance.foo", "root_block_device.#", "1"),
|
"aws_instance.foo", "root_block_device.#", "1"),
|
||||||
resource.TestCheckResourceAttr(
|
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(
|
resource.TestCheckResourceAttr(
|
||||||
"aws_instance.foo", "root_block_device.1246122048.volume_size", "11"),
|
"aws_instance.foo", "root_block_device.1023169747.volume_type", "gp2"),
|
||||||
resource.TestCheckResourceAttr(
|
|
||||||
"aws_instance.foo", "root_block_device.1246122048.volume_type", "gp2"),
|
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr(
|
||||||
"aws_instance.foo", "ebs_block_device.#", "2"),
|
"aws_instance.foo", "ebs_block_device.#", "2"),
|
||||||
resource.TestCheckResourceAttr(
|
resource.TestCheckResourceAttr(
|
||||||
|
@ -467,7 +465,6 @@ resource "aws_instance" "foo" {
|
||||||
instance_type = "m1.small"
|
instance_type = "m1.small"
|
||||||
|
|
||||||
root_block_device {
|
root_block_device {
|
||||||
device_name = "/dev/sda1"
|
|
||||||
volume_type = "gp2"
|
volume_type = "gp2"
|
||||||
volume_size = 11
|
volume_size = 11
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,9 +66,6 @@ to understand the implications of using these attributes.
|
||||||
|
|
||||||
The `root_block_device` mapping supports the following:
|
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"`,
|
* `volume_type` - (Optional) The type of volume. Can be `"standard"`, `"gp2"`,
|
||||||
or `"io1"`. (Default: `"standard"`).
|
or `"io1"`. (Default: `"standard"`).
|
||||||
* `volume_size` - (Optional) The size of the volume in gigabytes.
|
* `volume_size` - (Optional) The size of the volume in gigabytes.
|
||||||
|
|
Loading…
Reference in New Issue