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