Succeed creating aws_volume_attachment if identical attachment exists (#11060)
If an `aws_volume_attachment` is identical to one that already exists in the API, don't attempt to re-create it (which fails), simply act as though the creation command had already been run and continue. This allows Terraform to cleanly recover from a situation where a volume attachment action hangs indefinitely, possibly due to a bad instance state, requiring manual intervention such as an instance reboot. In such a situation, Terraform believes the attachment has failed, when in fact it succeeded after the timeout had expired. On the subsequent retry run, attempting to re-create the attachment will fail outright, due to the AttachVolume API call being non-idempotent. This patch implements the idempotency client-side by matching the (name, vID, iID) tuple. Note that volume attachments are not assigned an ID by the API.
This commit is contained in:
parent
c83a971efb
commit
babc52202c
|
@ -59,20 +59,40 @@ func resourceAwsVolumeAttachmentCreate(d *schema.ResourceData, meta interface{})
|
|||
iID := d.Get("instance_id").(string)
|
||||
vID := d.Get("volume_id").(string)
|
||||
|
||||
opts := &ec2.AttachVolumeInput{
|
||||
Device: aws.String(name),
|
||||
InstanceId: aws.String(iID),
|
||||
VolumeId: aws.String(vID),
|
||||
// Find out if the volume is already attached to the instance, in which case
|
||||
// we have nothing to do
|
||||
request := &ec2.DescribeVolumesInput{
|
||||
VolumeIds: []*string{aws.String(vID)},
|
||||
Filters: []*ec2.Filter{
|
||||
&ec2.Filter{
|
||||
Name: aws.String("attachment.instance-id"),
|
||||
Values: []*string{aws.String(iID)},
|
||||
},
|
||||
&ec2.Filter{
|
||||
Name: aws.String("attachment.device"),
|
||||
Values: []*string{aws.String(name)},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Attaching Volume (%s) to Instance (%s)", vID, iID)
|
||||
_, err := conn.AttachVolume(opts)
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
return fmt.Errorf("[WARN] Error attaching volume (%s) to instance (%s), message: \"%s\", code: \"%s\"",
|
||||
vID, iID, awsErr.Message(), awsErr.Code())
|
||||
vols, err := conn.DescribeVolumes(request)
|
||||
if (err != nil) || (len(vols.Volumes) == 0) {
|
||||
// not attached
|
||||
opts := &ec2.AttachVolumeInput{
|
||||
Device: aws.String(name),
|
||||
InstanceId: aws.String(iID),
|
||||
VolumeId: aws.String(vID),
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Attaching Volume (%s) to Instance (%s)", vID, iID)
|
||||
_, err := conn.AttachVolume(opts)
|
||||
if err != nil {
|
||||
if awsErr, ok := err.(awserr.Error); ok {
|
||||
return fmt.Errorf("[WARN] Error attaching volume (%s) to instance (%s), message: \"%s\", code: \"%s\"",
|
||||
vID, iID, awsErr.Message(), awsErr.Code())
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
stateConf := &resource.StateChangeConf{
|
||||
|
|
Loading…
Reference in New Issue