github.com/rothwerx/packer@v0.9.0/builder/digitalocean/step_snapshot.go (about)

     1  package digitalocean
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"log"
     7  	"time"
     8  
     9  	"github.com/digitalocean/godo"
    10  	"github.com/mitchellh/multistep"
    11  	"github.com/mitchellh/packer/packer"
    12  )
    13  
    14  type stepSnapshot struct{}
    15  
    16  func (s *stepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
    17  	client := state.Get("client").(*godo.Client)
    18  	ui := state.Get("ui").(packer.Ui)
    19  	c := state.Get("config").(Config)
    20  	dropletId := state.Get("droplet_id").(int)
    21  
    22  	ui.Say(fmt.Sprintf("Creating snapshot: %v", c.SnapshotName))
    23  	_, _, err := client.DropletActions.Snapshot(dropletId, c.SnapshotName)
    24  	if err != nil {
    25  		err := fmt.Errorf("Error creating snapshot: %s", err)
    26  		state.Put("error", err)
    27  		ui.Error(err.Error())
    28  		return multistep.ActionHalt
    29  	}
    30  
    31  	// Wait for the droplet to become unlocked first. For snapshots
    32  	// this can end up taking quite a long time, so we hardcode this to
    33  	// 20 minutes.
    34  	if err := waitForDropletUnlocked(client, dropletId, 20*time.Minute); err != nil {
    35  		// If we get an error the first time, actually report it
    36  		err := fmt.Errorf("Error shutting down droplet: %s", err)
    37  		state.Put("error", err)
    38  		ui.Error(err.Error())
    39  		return multistep.ActionHalt
    40  	}
    41  
    42  	// With the pending state over, verify that we're in the active state
    43  	ui.Say("Waiting for snapshot to complete...")
    44  	err = waitForDropletState("active", dropletId, client, c.StateTimeout)
    45  	if err != nil {
    46  		err := fmt.Errorf("Error waiting for snapshot to complete: %s", err)
    47  		state.Put("error", err)
    48  		ui.Error(err.Error())
    49  		return multistep.ActionHalt
    50  	}
    51  
    52  	log.Printf("Looking up snapshot ID for snapshot: %s", c.SnapshotName)
    53  	images, _, err := client.Droplets.Snapshots(dropletId, nil)
    54  	if err != nil {
    55  		err := fmt.Errorf("Error looking up snapshot ID: %s", err)
    56  		state.Put("error", err)
    57  		ui.Error(err.Error())
    58  		return multistep.ActionHalt
    59  	}
    60  
    61  	var imageId int
    62  	if len(images) == 1 {
    63  		imageId = images[0].ID
    64  	} else {
    65  		err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
    66  		state.Put("error", err)
    67  		ui.Error(err.Error())
    68  		return multistep.ActionHalt
    69  	}
    70  
    71  	log.Printf("Snapshot image ID: %d", imageId)
    72  	state.Put("snapshot_image_id", imageId)
    73  	state.Put("snapshot_name", c.SnapshotName)
    74  	state.Put("region", c.Region)
    75  
    76  	return multistep.ActionContinue
    77  }
    78  
    79  func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
    80  	// no cleanup
    81  }