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