github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/amazon/ebs/step_cleanup_volumes.go (about) 1 package ebs 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/aws/aws-sdk-go/aws" 8 "github.com/aws/aws-sdk-go/service/ec2" 9 "github.com/hashicorp/packer/builder/amazon/common" 10 "github.com/hashicorp/packer/helper/multistep" 11 "github.com/hashicorp/packer/packer" 12 ) 13 14 // stepCleanupVolumes cleans up any orphaned volumes that were not designated to 15 // remain after termination of the instance. These volumes are typically ones 16 // that are marked as "delete on terminate:false" in the source_ami of a build. 17 type stepCleanupVolumes struct { 18 BlockDevices common.BlockDevices 19 } 20 21 func (s *stepCleanupVolumes) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 22 // stepCleanupVolumes is for Cleanup only 23 return multistep.ActionContinue 24 } 25 26 func (s *stepCleanupVolumes) Cleanup(state multistep.StateBag) { 27 ec2conn := state.Get("ec2").(*ec2.EC2) 28 instanceRaw := state.Get("instance") 29 var instance *ec2.Instance 30 if instanceRaw != nil { 31 instance = instanceRaw.(*ec2.Instance) 32 } 33 ui := state.Get("ui").(packer.Ui) 34 if instance == nil { 35 ui.Say("No volumes to clean up, skipping") 36 return 37 } 38 39 ui.Say("Cleaning up any extra volumes...") 40 41 // Collect Volume information from the cached Instance as a map of volume-id 42 // to device name, to compare with save list below 43 var vl []*string 44 volList := make(map[string]string) 45 for _, bdm := range instance.BlockDeviceMappings { 46 if bdm.Ebs != nil { 47 vl = append(vl, bdm.Ebs.VolumeId) 48 volList[*bdm.Ebs.VolumeId] = *bdm.DeviceName 49 } 50 } 51 52 // Using the volume list from the cached Instance, check with AWS for up to 53 // date information on them 54 resp, err := ec2conn.DescribeVolumes(&ec2.DescribeVolumesInput{ 55 Filters: []*ec2.Filter{ 56 { 57 Name: aws.String("volume-id"), 58 Values: vl, 59 }, 60 }, 61 }) 62 63 if err != nil { 64 ui.Say(fmt.Sprintf("Error describing volumes: %s", err)) 65 return 66 } 67 68 // If any of the returned volumes are in a "deleting" stage or otherwise not 69 // available, remove them from the list of volumes 70 for _, v := range resp.Volumes { 71 if v.State != nil && *v.State != "available" { 72 delete(volList, *v.VolumeId) 73 } 74 } 75 76 if len(resp.Volumes) == 0 { 77 ui.Say("No volumes to clean up, skipping") 78 return 79 } 80 81 // Filter out any devices created as part of the launch mappings, since 82 // we'll let amazon follow the `delete_on_termination` setting. 83 for _, b := range s.BlockDevices.LaunchMappings { 84 for volKey, volName := range volList { 85 if volName == b.DeviceName { 86 delete(volList, volKey) 87 } 88 } 89 } 90 91 // Destroy remaining volumes 92 for k := range volList { 93 ui.Say(fmt.Sprintf("Destroying volume (%s)...", k)) 94 _, err := ec2conn.DeleteVolume(&ec2.DeleteVolumeInput{VolumeId: aws.String(k)}) 95 if err != nil { 96 ui.Say(fmt.Sprintf("Error deleting volume: %s", err)) 97 } 98 99 } 100 }