github.com/mmcquillan/packer@v1.1.1-0.20171009221028-c85cf0483a5d/builder/amazon/ebssurrogate/step_snapshot_new_root.go (about) 1 package ebssurrogate 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/aws/aws-sdk-go/service/ec2" 9 awscommon "github.com/hashicorp/packer/builder/amazon/common" 10 "github.com/hashicorp/packer/packer" 11 "github.com/mitchellh/multistep" 12 ) 13 14 // StepSnapshotNewRootVolume creates a snapshot of the created volume. 15 // 16 // Produces: 17 // snapshot_id string - ID of the created snapshot 18 type StepSnapshotNewRootVolume struct { 19 NewRootMountPoint string 20 snapshotId string 21 } 22 23 func (s *StepSnapshotNewRootVolume) Run(state multistep.StateBag) multistep.StepAction { 24 ec2conn := state.Get("ec2").(*ec2.EC2) 25 ui := state.Get("ui").(packer.Ui) 26 instance := state.Get("instance").(*ec2.Instance) 27 28 var newRootVolume string 29 for _, volume := range instance.BlockDeviceMappings { 30 if *volume.DeviceName == s.NewRootMountPoint { 31 newRootVolume = *volume.Ebs.VolumeId 32 } 33 } 34 35 ui.Say(fmt.Sprintf("Creating snapshot of EBS Volume %s...", newRootVolume)) 36 description := fmt.Sprintf("Packer: %s", time.Now().String()) 37 38 createSnapResp, err := ec2conn.CreateSnapshot(&ec2.CreateSnapshotInput{ 39 VolumeId: &newRootVolume, 40 Description: &description, 41 }) 42 if err != nil { 43 err := fmt.Errorf("Error creating snapshot: %s", err) 44 state.Put("error", err) 45 ui.Error(err.Error()) 46 return multistep.ActionHalt 47 } 48 49 // Set the snapshot ID so we can delete it later 50 s.snapshotId = *createSnapResp.SnapshotId 51 ui.Message(fmt.Sprintf("Snapshot ID: %s", s.snapshotId)) 52 53 // Wait for the snapshot to be ready 54 stateChange := awscommon.StateChangeConf{ 55 Pending: []string{"pending"}, 56 StepState: state, 57 Target: "completed", 58 Refresh: func() (interface{}, string, error) { 59 resp, err := ec2conn.DescribeSnapshots(&ec2.DescribeSnapshotsInput{SnapshotIds: []*string{&s.snapshotId}}) 60 if err != nil { 61 return nil, "", err 62 } 63 64 if len(resp.Snapshots) == 0 { 65 return nil, "", errors.New("No snapshots found.") 66 } 67 68 s := resp.Snapshots[0] 69 return s, *s.State, nil 70 }, 71 } 72 73 _, err = awscommon.WaitForState(&stateChange) 74 if err != nil { 75 err := fmt.Errorf("Error waiting for snapshot: %s", err) 76 state.Put("error", err) 77 ui.Error(err.Error()) 78 return multistep.ActionHalt 79 } 80 81 state.Put("snapshot_id", s.snapshotId) 82 return multistep.ActionContinue 83 } 84 85 func (s *StepSnapshotNewRootVolume) Cleanup(state multistep.StateBag) { 86 if s.snapshotId == "" { 87 return 88 } 89 90 _, cancelled := state.GetOk(multistep.StateCancelled) 91 _, halted := state.GetOk(multistep.StateHalted) 92 93 if cancelled || halted { 94 ec2conn := state.Get("ec2").(*ec2.EC2) 95 ui := state.Get("ui").(packer.Ui) 96 ui.Say("Removing snapshot since we cancelled or halted...") 97 _, err := ec2conn.DeleteSnapshot(&ec2.DeleteSnapshotInput{SnapshotId: &s.snapshotId}) 98 if err != nil { 99 ui.Error(fmt.Sprintf("Error: %s", err)) 100 } 101 } 102 }