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  }