github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/builder/amazon/chroot/step_register_ami.go (about) 1 package chroot 2 3 import ( 4 "fmt" 5 6 "github.com/aws/aws-sdk-go/aws" 7 "github.com/aws/aws-sdk-go/service/ec2" 8 "github.com/mitchellh/multistep" 9 awscommon "github.com/mitchellh/packer/builder/amazon/common" 10 "github.com/mitchellh/packer/packer" 11 ) 12 13 // StepRegisterAMI creates the AMI. 14 type StepRegisterAMI struct { 15 RootVolumeSize int64 16 } 17 18 func (s *StepRegisterAMI) Run(state multistep.StateBag) multistep.StepAction { 19 config := state.Get("config").(*Config) 20 ec2conn := state.Get("ec2").(*ec2.EC2) 21 snapshotId := state.Get("snapshot_id").(string) 22 ui := state.Get("ui").(packer.Ui) 23 24 ui.Say("Registering the AMI...") 25 26 var ( 27 registerOpts *ec2.RegisterImageInput 28 mappings []*ec2.BlockDeviceMapping 29 image *ec2.Image 30 rootDeviceName string 31 ) 32 33 if config.FromScratch { 34 mappings = config.AMIBlockDevices.BuildAMIDevices() 35 rootDeviceName = config.RootDeviceName 36 } else { 37 image = state.Get("source_image").(*ec2.Image) 38 mappings = image.BlockDeviceMappings 39 rootDeviceName = *image.RootDeviceName 40 } 41 42 newMappings := make([]*ec2.BlockDeviceMapping, len(mappings)) 43 for i, device := range mappings { 44 newDevice := device 45 if *newDevice.DeviceName == rootDeviceName { 46 if newDevice.Ebs != nil { 47 newDevice.Ebs.SnapshotId = aws.String(snapshotId) 48 } else { 49 newDevice.Ebs = &ec2.EbsBlockDevice{SnapshotId: aws.String(snapshotId)} 50 } 51 52 if config.FromScratch || s.RootVolumeSize > *newDevice.Ebs.VolumeSize { 53 newDevice.Ebs.VolumeSize = aws.Int64(s.RootVolumeSize) 54 } 55 } 56 57 // assume working from a snapshot, so we unset the Encrypted field if set, 58 // otherwise AWS API will return InvalidParameter 59 if newDevice.Ebs != nil && newDevice.Ebs.Encrypted != nil { 60 newDevice.Ebs.Encrypted = nil 61 } 62 63 newMappings[i] = newDevice 64 } 65 66 if config.FromScratch { 67 registerOpts = &ec2.RegisterImageInput{ 68 Name: &config.AMIName, 69 Architecture: aws.String(ec2.ArchitectureValuesX8664), 70 RootDeviceName: aws.String(rootDeviceName), 71 VirtualizationType: aws.String(config.AMIVirtType), 72 BlockDeviceMappings: newMappings, 73 } 74 } else { 75 registerOpts = buildRegisterOpts(config, image, newMappings) 76 } 77 78 // Set SriovNetSupport to "simple". See http://goo.gl/icuXh5 79 if config.AMIEnhancedNetworking { 80 registerOpts.SriovNetSupport = aws.String("simple") 81 } 82 83 registerResp, err := ec2conn.RegisterImage(registerOpts) 84 if err != nil { 85 state.Put("error", fmt.Errorf("Error registering AMI: %s", err)) 86 ui.Error(state.Get("error").(error).Error()) 87 return multistep.ActionHalt 88 } 89 90 // Set the AMI ID in the state 91 ui.Say(fmt.Sprintf("AMI: %s", *registerResp.ImageId)) 92 amis := make(map[string]string) 93 amis[*ec2conn.Config.Region] = *registerResp.ImageId 94 state.Put("amis", amis) 95 96 // Wait for the image to become ready 97 stateChange := awscommon.StateChangeConf{ 98 Pending: []string{"pending"}, 99 Target: "available", 100 Refresh: awscommon.AMIStateRefreshFunc(ec2conn, *registerResp.ImageId), 101 StepState: state, 102 } 103 104 ui.Say("Waiting for AMI to become ready...") 105 if _, err := awscommon.WaitForState(&stateChange); err != nil { 106 err := fmt.Errorf("Error waiting for AMI: %s", err) 107 state.Put("error", err) 108 ui.Error(err.Error()) 109 return multistep.ActionHalt 110 } 111 112 return multistep.ActionContinue 113 } 114 115 func (s *StepRegisterAMI) Cleanup(state multistep.StateBag) {} 116 117 func buildRegisterOpts(config *Config, image *ec2.Image, mappings []*ec2.BlockDeviceMapping) *ec2.RegisterImageInput { 118 registerOpts := &ec2.RegisterImageInput{ 119 Name: &config.AMIName, 120 Architecture: image.Architecture, 121 RootDeviceName: image.RootDeviceName, 122 BlockDeviceMappings: mappings, 123 VirtualizationType: image.VirtualizationType, 124 } 125 126 if config.AMIVirtType != "" { 127 registerOpts.VirtualizationType = aws.String(config.AMIVirtType) 128 } 129 130 if config.AMIVirtType != "hvm" { 131 registerOpts.KernelId = image.KernelId 132 registerOpts.RamdiskId = image.RamdiskId 133 } 134 return registerOpts 135 }