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 }