[dynamic-source-ami] make most_recent work

This commit is contained in:
Chris Lundquist 2016-08-20 23:08:45 +00:00
parent ec1abb9448
commit 0e248f1516
2 changed files with 53 additions and 19 deletions

View File

@ -15,13 +15,13 @@ import (
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
type DynamicAmiOptions struct {
Filters map[*string]*string
Owners []*string
Most_recent bool
Filters map[*string]*string
Owners []*string
MostRecent bool `mapstructure:"most_recent"`
}
func (d *DynamicAmiOptions) Validate() bool {
return true
func (d *DynamicAmiOptions) Empty() bool {
return len(d.Owners) == 0 && len(d.Filters) == 0
}
// RunConfig contains configuration for running an instance from a source
@ -67,7 +67,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
// Validation
errs := c.Comm.Prepare(ctx)
if c.SourceAmi == "" {
if c.SourceAmi == "" && c.DynamicSourceAmi.Empty() {
errs = append(errs, errors.New("A source_ami or dynamic_source_ami must be specified"))
}

View File

@ -2,6 +2,9 @@ package common
import (
"fmt"
"log"
"sort"
"time"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
@ -23,11 +26,6 @@ type StepSourceAMIInfo struct {
func buildAmiFilters(input map[*string]*string) []*ec2.Filter {
var filters []*ec2.Filter
for k, v := range input {
/*m := v.(map[string]interface{})
var filterValues []*string
for _, e := range m["values"].([]interface{}) {
filterValues = append(filterValues, aws.String(e.(string)))
}*/
filters = append(filters, &ec2.Filter{
Name: k,
Values: []*string{v},
@ -36,17 +34,40 @@ func buildAmiFilters(input map[*string]*string) []*ec2.Filter {
return filters
}
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]
}
func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
params := &ec2.DescribeImagesInput{}
params.Filters = buildAmiFilters(s.AmiFilters.Filters)
params.Owners = s.AmiFilters.Owners
ui.Say(fmt.Sprintf("Using AMI Filters %v", params))
if s.SourceAmi != "" {
params.ImageIds = []*string{&s.SourceAmi}
}
// We have filters to apply
if len(s.AmiFilters.Filters) > 0 {
params.Filters = buildAmiFilters(s.AmiFilters.Filters)
}
log.Printf("Using AMI Filters %v", params)
imageResp, err := ec2conn.DescribeImages(params)
//ui.Say(fmt.Sprintf("Inspecting the source AMI (%s)...", s.SourceAmi))
//imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{&s.SourceAmi}})
if err != nil {
err := fmt.Errorf("Error querying AMI: %s", err)
state.Put("error", err)
@ -55,14 +76,27 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
}
if len(imageResp.Images) == 0 {
err := fmt.Errorf("Source AMI '%s' was not found!", s.SourceAmi)
err := fmt.Errorf("No AMI was found matching filters: %v", params)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
image := imageResp.Images[0]
ui.Say(fmt.Sprintf("Got Image %v", image))
if len(imageResp.Images) > 1 && s.AmiFilters.MostRecent == false {
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]
}
log.Printf(fmt.Sprintf("Got Image %v", image))
// Enhanced Networking (SriovNetSupport) can only be enabled on HVM AMIs.
// See http://goo.gl/icuXh5