2014-06-04 14:58:11 -07:00
|
|
|
package common
|
2013-07-29 17:37:22 -07:00
|
|
|
|
|
|
|
|
import (
|
2018-01-22 15:32:33 -08:00
|
|
|
"context"
|
2013-07-29 17:37:22 -07:00
|
|
|
"fmt"
|
2016-08-20 23:08:45 +00:00
|
|
|
"log"
|
|
|
|
|
"sort"
|
|
|
|
|
"time"
|
2014-06-04 14:58:11 -07:00
|
|
|
|
2015-06-03 17:13:52 -04:00
|
|
|
"github.com/aws/aws-sdk-go/service/ec2"
|
2019-08-22 13:17:35 -07:00
|
|
|
confighelper "github.com/hashicorp/packer/helper/config"
|
2018-01-19 16:18:44 -08:00
|
|
|
"github.com/hashicorp/packer/helper/multistep"
|
2017-04-04 13:39:01 -07:00
|
|
|
"github.com/hashicorp/packer/packer"
|
2013-07-29 17:37:22 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// StepSourceAMIInfo extracts critical information from the source AMI
|
|
|
|
|
// that is used throughout the AMI creation process.
|
|
|
|
|
//
|
|
|
|
|
// Produces:
|
|
|
|
|
// source_image *ec2.Image - the source AMI info
|
2014-06-04 14:58:11 -07:00
|
|
|
type StepSourceAMIInfo struct {
|
2017-08-28 09:18:23 -07:00
|
|
|
SourceAmi string
|
|
|
|
|
EnableAMISriovNetSupport bool
|
2019-08-22 13:17:35 -07:00
|
|
|
EnableAMIENASupport confighelper.Trilean
|
2018-09-04 18:13:18 -07:00
|
|
|
AMIVirtType string
|
2017-08-28 09:18:23 -07:00
|
|
|
AmiFilters AmiFilterOptions
|
2016-08-20 18:58:36 +00:00
|
|
|
}
|
|
|
|
|
|
2016-08-20 23:08:45 +00:00
|
|
|
type imageSort []*ec2.Image
|
|
|
|
|
|
|
|
|
|
func (a imageSort) Len() int { return len(a) }
|
|
|
|
|
func (a imageSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
|
|
|
func (a imageSort) Less(i, j int) bool {
|
|
|
|
|
itime, _ := time.Parse(time.RFC3339, *a[i].CreationDate)
|
|
|
|
|
jtime, _ := time.Parse(time.RFC3339, *a[j].CreationDate)
|
|
|
|
|
return itime.Unix() < jtime.Unix()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Returns the most recent AMI out of a slice of images.
|
|
|
|
|
func mostRecentAmi(images []*ec2.Image) *ec2.Image {
|
|
|
|
|
sortedImages := images
|
|
|
|
|
sort.Sort(imageSort(sortedImages))
|
|
|
|
|
return sortedImages[len(sortedImages)-1]
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 16:50:02 +01:00
|
|
|
func (s *StepSourceAMIInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
2013-08-31 12:58:55 -07:00
|
|
|
ec2conn := state.Get("ec2").(*ec2.EC2)
|
|
|
|
|
ui := state.Get("ui").(packer.Ui)
|
2013-07-29 17:37:22 -07:00
|
|
|
|
2016-08-20 18:58:36 +00:00
|
|
|
params := &ec2.DescribeImagesInput{}
|
2016-08-20 23:08:45 +00:00
|
|
|
|
|
|
|
|
if s.SourceAmi != "" {
|
|
|
|
|
params.ImageIds = []*string{&s.SourceAmi}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We have filters to apply
|
|
|
|
|
if len(s.AmiFilters.Filters) > 0 {
|
2018-06-12 12:05:16 +02:00
|
|
|
params.Filters = buildEc2Filters(s.AmiFilters.Filters)
|
2016-08-20 23:08:45 +00:00
|
|
|
}
|
2016-12-01 14:29:31 +01:00
|
|
|
if len(s.AmiFilters.Owners) > 0 {
|
2019-10-14 15:56:49 +02:00
|
|
|
params.Owners = s.AmiFilters.GetOwners()
|
2016-12-01 14:29:31 +01:00
|
|
|
}
|
2016-08-20 23:08:45 +00:00
|
|
|
|
|
|
|
|
log.Printf("Using AMI Filters %v", params)
|
2016-08-20 18:58:36 +00:00
|
|
|
imageResp, err := ec2conn.DescribeImages(params)
|
2013-07-29 17:37:22 -07:00
|
|
|
if err != nil {
|
|
|
|
|
err := fmt.Errorf("Error querying AMI: %s", err)
|
2013-08-31 12:58:55 -07:00
|
|
|
state.Put("error", err)
|
2013-07-29 17:37:22 -07:00
|
|
|
ui.Error(err.Error())
|
|
|
|
|
return multistep.ActionHalt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(imageResp.Images) == 0 {
|
2016-08-20 23:08:45 +00:00
|
|
|
err := fmt.Errorf("No AMI was found matching filters: %v", params)
|
2013-08-31 12:58:55 -07:00
|
|
|
state.Put("error", err)
|
2013-07-29 17:37:22 -07:00
|
|
|
ui.Error(err.Error())
|
|
|
|
|
return multistep.ActionHalt
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-28 18:29:55 -07:00
|
|
|
if len(imageResp.Images) > 1 && !s.AmiFilters.MostRecent {
|
2016-08-20 23:08:45 +00:00
|
|
|
err := fmt.Errorf("Your query returned more than one result. Please try a more specific search, or set most_recent to true.")
|
|
|
|
|
state.Put("error", err)
|
|
|
|
|
ui.Error(err.Error())
|
|
|
|
|
return multistep.ActionHalt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var image *ec2.Image
|
|
|
|
|
if s.AmiFilters.MostRecent {
|
|
|
|
|
image = mostRecentAmi(imageResp.Images)
|
|
|
|
|
} else {
|
|
|
|
|
image = imageResp.Images[0]
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-01 15:26:43 -07:00
|
|
|
ui.Message(fmt.Sprintf("Found Image ID: %s", *image.ImageId))
|
2013-07-29 17:37:22 -07:00
|
|
|
|
2017-02-21 17:46:16 -08:00
|
|
|
// Enhanced Networking can only be enabled on HVM AMIs.
|
2014-06-04 14:58:11 -07:00
|
|
|
// See http://goo.gl/icuXh5
|
2019-08-22 13:17:35 -07:00
|
|
|
if s.EnableAMIENASupport.True() || s.EnableAMISriovNetSupport {
|
2018-09-04 18:13:18 -07:00
|
|
|
err = s.canEnableEnhancedNetworking(image)
|
|
|
|
|
if err != nil {
|
|
|
|
|
state.Put("error", err)
|
|
|
|
|
ui.Error(err.Error())
|
|
|
|
|
return multistep.ActionHalt
|
|
|
|
|
}
|
2013-07-29 17:37:22 -07:00
|
|
|
}
|
|
|
|
|
|
2013-08-31 12:58:55 -07:00
|
|
|
state.Put("source_image", image)
|
2013-07-29 17:37:22 -07:00
|
|
|
return multistep.ActionContinue
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-31 12:58:55 -07:00
|
|
|
func (s *StepSourceAMIInfo) Cleanup(multistep.StateBag) {}
|
2018-09-04 18:13:18 -07:00
|
|
|
|
|
|
|
|
func (s *StepSourceAMIInfo) canEnableEnhancedNetworking(image *ec2.Image) error {
|
|
|
|
|
if s.AMIVirtType == "hvm" {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
if s.AMIVirtType != "" {
|
|
|
|
|
return fmt.Errorf("Cannot enable enhanced networking, AMIVirtType '%s' is not HVM", s.AMIVirtType)
|
|
|
|
|
}
|
|
|
|
|
if *image.VirtualizationType != "hvm" {
|
|
|
|
|
return fmt.Errorf("Cannot enable enhanced networking, source AMI '%s' is not HVM", s.SourceAmi)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|