github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/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 action, _, 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 // With the pending state over, verify that we're in the active state 32 ui.Say("Waiting for snapshot to complete...") 33 if err := waitForActionState(godo.ActionCompleted, dropletId, action.ID, 34 client, 20*time.Minute); err != nil { 35 // If we get an error the first time, actually report it 36 err := fmt.Errorf("Error waiting for snapshot: %s", err) 37 state.Put("error", err) 38 ui.Error(err.Error()) 39 return multistep.ActionHalt 40 } 41 42 // Wait for the droplet to become unlocked first. For snapshots 43 // this can end up taking quite a long time, so we hardcode this to 44 // 20 minutes. 45 if err := waitForDropletUnlocked(client, dropletId, 20*time.Minute); err != nil { 46 // If we get an error the first time, actually report it 47 err := fmt.Errorf("Error shutting down droplet: %s", err) 48 state.Put("error", err) 49 ui.Error(err.Error()) 50 return multistep.ActionHalt 51 } 52 53 log.Printf("Looking up snapshot ID for snapshot: %s", c.SnapshotName) 54 images, _, err := client.Droplets.Snapshots(dropletId, nil) 55 if err != nil { 56 err := fmt.Errorf("Error looking up snapshot ID: %s", err) 57 state.Put("error", err) 58 ui.Error(err.Error()) 59 return multistep.ActionHalt 60 } 61 62 var imageId int 63 if len(images) == 1 { 64 imageId = images[0].ID 65 } else { 66 err := errors.New("Couldn't find snapshot to get the image ID. Bug?") 67 state.Put("error", err) 68 ui.Error(err.Error()) 69 return multistep.ActionHalt 70 } 71 72 log.Printf("Snapshot image ID: %d", imageId) 73 state.Put("snapshot_image_id", imageId) 74 state.Put("snapshot_name", c.SnapshotName) 75 state.Put("region", c.Region) 76 77 return multistep.ActionContinue 78 } 79 80 func (s *stepSnapshot) Cleanup(state multistep.StateBag) { 81 // no cleanup 82 }