github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/builder/amazon/ebs/step_create_ami.go (about) 1 package ebs 2 3 import ( 4 "fmt" 5 "github.com/mitchellh/goamz/ec2" 6 "github.com/mitchellh/multistep" 7 awscommon "github.com/mitchellh/packer/builder/amazon/common" 8 "github.com/mitchellh/packer/packer" 9 ) 10 11 type stepCreateAMI struct { 12 image *ec2.Image 13 } 14 15 func (s *stepCreateAMI) Run(state multistep.StateBag) multistep.StepAction { 16 config := state.Get("config").(config) 17 ec2conn := state.Get("ec2").(*ec2.EC2) 18 instance := state.Get("instance").(*ec2.Instance) 19 ui := state.Get("ui").(packer.Ui) 20 21 // Create the image 22 ui.Say(fmt.Sprintf("Creating the AMI: %s", config.AMIName)) 23 createOpts := &ec2.CreateImage{ 24 InstanceId: instance.InstanceId, 25 Name: config.AMIName, 26 BlockDevices: config.BlockDevices.BuildAMIDevices(), 27 } 28 29 createResp, err := ec2conn.CreateImage(createOpts) 30 if err != nil { 31 err := fmt.Errorf("Error creating AMI: %s", err) 32 state.Put("error", err) 33 ui.Error(err.Error()) 34 return multistep.ActionHalt 35 } 36 37 // Set the AMI ID in the state 38 ui.Message(fmt.Sprintf("AMI: %s", createResp.ImageId)) 39 amis := make(map[string]string) 40 amis[ec2conn.Region.Name] = createResp.ImageId 41 state.Put("amis", amis) 42 43 // Wait for the image to become ready 44 stateChange := awscommon.StateChangeConf{ 45 Pending: []string{"pending"}, 46 Target: "available", 47 Refresh: awscommon.AMIStateRefreshFunc(ec2conn, createResp.ImageId), 48 StepState: state, 49 } 50 51 ui.Say("Waiting for AMI to become ready...") 52 if _, err := awscommon.WaitForState(&stateChange); err != nil { 53 err := fmt.Errorf("Error waiting for AMI: %s", err) 54 state.Put("error", err) 55 ui.Error(err.Error()) 56 return multistep.ActionHalt 57 } 58 59 imagesResp, err := ec2conn.Images([]string{createResp.ImageId}, nil) 60 if err != nil { 61 err := fmt.Errorf("Error searching for AMI: %s", err) 62 state.Put("error", err) 63 ui.Error(err.Error()) 64 return multistep.ActionHalt 65 } 66 s.image = &imagesResp.Images[0] 67 68 return multistep.ActionContinue 69 } 70 71 func (s *stepCreateAMI) Cleanup(state multistep.StateBag) { 72 if s.image == nil { 73 return 74 } 75 76 _, cancelled := state.GetOk(multistep.StateCancelled) 77 _, halted := state.GetOk(multistep.StateHalted) 78 if !cancelled && !halted { 79 return 80 } 81 82 ec2conn := state.Get("ec2").(*ec2.EC2) 83 ui := state.Get("ui").(packer.Ui) 84 85 ui.Say("Deregistering the AMI because cancelation or error...") 86 if resp, err := ec2conn.DeregisterImage(s.image.Id); err != nil { 87 ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", err)) 88 return 89 } else if resp.Return == false { 90 ui.Error(fmt.Sprintf("Error deregistering AMI, may still be around: %s", resp.Return)) 91 return 92 } 93 }