[dynamic-source-ami] proof of concept
This commit is contained in:
parent
6cd7ad82bb
commit
ec1abb9448
|
@ -14,6 +14,16 @@ import (
|
|||
|
||||
var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
|
||||
|
||||
type DynamicAmiOptions struct {
|
||||
Filters map[*string]*string
|
||||
Owners []*string
|
||||
Most_recent bool
|
||||
}
|
||||
|
||||
func (d *DynamicAmiOptions) Validate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// RunConfig contains configuration for running an instance from a source
|
||||
// AMI and details on how to access that launched image.
|
||||
type RunConfig struct {
|
||||
|
@ -24,6 +34,7 @@ type RunConfig struct {
|
|||
InstanceType string `mapstructure:"instance_type"`
|
||||
RunTags map[string]string `mapstructure:"run_tags"`
|
||||
SourceAmi string `mapstructure:"source_ami"`
|
||||
DynamicSourceAmi DynamicAmiOptions `mapstructure:"dynamic_source_ami"`
|
||||
SpotPrice string `mapstructure:"spot_price"`
|
||||
SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product"`
|
||||
DisableStopInstance bool `mapstructure:"disable_stop_instance"`
|
||||
|
@ -57,7 +68,7 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
|
|||
// Validation
|
||||
errs := c.Comm.Prepare(ctx)
|
||||
if c.SourceAmi == "" {
|
||||
errs = append(errs, errors.New("A source_ami must be specified"))
|
||||
errs = append(errs, errors.New("A source_ami or dynamic_source_ami must be specified"))
|
||||
}
|
||||
|
||||
if c.InstanceType == "" {
|
||||
|
|
|
@ -84,24 +84,18 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||
}
|
||||
|
||||
ui.Say("Launching a source AWS instance...")
|
||||
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{
|
||||
ImageIds: []*string{&s.SourceAMI},
|
||||
})
|
||||
if err != nil {
|
||||
state.Put("error", fmt.Errorf("There was a problem with the source AMI: %s", err))
|
||||
image, ok := state.Get("source_image").(*ec2.Image)
|
||||
if !ok {
|
||||
state.Put("error", fmt.Errorf("source_image type assertion failed"))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
s.SourceAMI = *image.ImageId
|
||||
|
||||
if len(imageResp.Images) != 1 {
|
||||
state.Put("error", fmt.Errorf("The source AMI '%s' could not be found.", s.SourceAMI))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
if s.ExpectedRootDevice != "" && *imageResp.Images[0].RootDeviceType != s.ExpectedRootDevice {
|
||||
if s.ExpectedRootDevice != "" && *image.RootDeviceType != s.ExpectedRootDevice {
|
||||
state.Put("error", fmt.Errorf(
|
||||
"The provided source AMI has an invalid root device type.\n"+
|
||||
"Expected '%s', got '%s'.",
|
||||
s.ExpectedRootDevice, *imageResp.Images[0].RootDeviceType))
|
||||
s.ExpectedRootDevice, image.RootDeviceType))
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
|
@ -156,16 +150,16 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
|
|||
|
||||
if spotPrice == "" || spotPrice == "0" {
|
||||
runOpts := &ec2.RunInstancesInput{
|
||||
KeyName: &keyName,
|
||||
ImageId: &s.SourceAMI,
|
||||
InstanceType: &s.InstanceType,
|
||||
UserData: &userData,
|
||||
MaxCount: aws.Int64(1),
|
||||
MinCount: aws.Int64(1),
|
||||
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
|
||||
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
|
||||
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone},
|
||||
EbsOptimized: &s.EbsOptimized,
|
||||
KeyName: &keyName,
|
||||
ImageId: &s.SourceAMI,
|
||||
InstanceType: &s.InstanceType,
|
||||
UserData: &userData,
|
||||
MaxCount: aws.Int64(1),
|
||||
MinCount: aws.Int64(1),
|
||||
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
|
||||
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
|
||||
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone},
|
||||
EbsOptimized: &s.EbsOptimized,
|
||||
}
|
||||
|
||||
if s.SubnetId != "" && s.AssociatePublicIpAddress {
|
||||
|
|
|
@ -16,14 +16,37 @@ import (
|
|||
type StepSourceAMIInfo struct {
|
||||
SourceAmi string
|
||||
EnhancedNetworking bool
|
||||
AmiFilters DynamicAmiOptions
|
||||
}
|
||||
|
||||
// Build a slice of AMI filter options from the filters provided.
|
||||
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},
|
||||
})
|
||||
}
|
||||
return filters
|
||||
}
|
||||
|
||||
func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
|
||||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
ui.Say(fmt.Sprintf("Inspecting the source AMI (%s)...", s.SourceAmi))
|
||||
imageResp, err := ec2conn.DescribeImages(&ec2.DescribeImagesInput{ImageIds: []*string{&s.SourceAmi}})
|
||||
params := &ec2.DescribeImagesInput{}
|
||||
params.Filters = buildAmiFilters(s.AmiFilters.Filters)
|
||||
params.Owners = s.AmiFilters.Owners
|
||||
ui.Say(fmt.Sprintf("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)
|
||||
|
@ -39,6 +62,7 @@ func (s *StepSourceAMIInfo) Run(state multistep.StateBag) multistep.StepAction {
|
|||
}
|
||||
|
||||
image := imageResp.Images[0]
|
||||
ui.Say(fmt.Sprintf("Got Image %v", image))
|
||||
|
||||
// Enhanced Networking (SriovNetSupport) can only be enabled on HVM AMIs.
|
||||
// See http://goo.gl/icuXh5
|
||||
|
|
|
@ -100,6 +100,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
&awscommon.StepSourceAMIInfo{
|
||||
SourceAmi: b.config.SourceAmi,
|
||||
EnhancedNetworking: b.config.AMIEnhancedNetworking,
|
||||
AmiFilters: b.config.DynamicSourceAmi,
|
||||
},
|
||||
&awscommon.StepKeyPair{
|
||||
Debug: b.config.PackerDebug,
|
||||
|
|
Loading…
Reference in New Issue