Merge pull request #6374 from rickard-von-essen/aws-filters

builder/amazon: Add suppport for vpc_filter, subnet_filter, and security_group_filter
This commit is contained in:
Megan Marsh 2018-10-18 14:34:02 -07:00 committed by GitHub
commit 57f87f58b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 640 additions and 145 deletions

View File

@ -0,0 +1,17 @@
package common
import (
"github.com/aws/aws-sdk-go/service/ec2"
)
// Build a slice of EC2 (AMI/Subnet/VPC) filter options from the filters provided.
func buildEc2Filters(input map[*string]*string) []*ec2.Filter {
var filters []*ec2.Filter
for k, v := range input {
filters = append(filters, &ec2.Filter{
Name: k,
Values: []*string{v},
})
}
return filters
}

View File

@ -29,33 +29,62 @@ func (d *AmiFilterOptions) NoOwner() bool {
return len(d.Owners) == 0 return len(d.Owners) == 0
} }
type SubnetFilterOptions struct {
Filters map[*string]*string
MostFree bool `mapstructure:"most_free"`
Random bool `mapstructure:"random"`
}
func (d *SubnetFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
type VpcFilterOptions struct {
Filters map[*string]*string
}
func (d *VpcFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
type SecurityGroupFilterOptions struct {
Filters map[*string]*string
}
func (d *SecurityGroupFilterOptions) Empty() bool {
return len(d.Filters) == 0
}
// RunConfig contains configuration for running an instance from a source // RunConfig contains configuration for running an instance from a source
// AMI and details on how to access that launched image. // AMI and details on how to access that launched image.
type RunConfig struct { type RunConfig struct {
AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"` AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"`
AvailabilityZone string `mapstructure:"availability_zone"` AvailabilityZone string `mapstructure:"availability_zone"`
BlockDurationMinutes int64 `mapstructure:"block_duration_minutes"` BlockDurationMinutes int64 `mapstructure:"block_duration_minutes"`
DisableStopInstance bool `mapstructure:"disable_stop_instance"` DisableStopInstance bool `mapstructure:"disable_stop_instance"`
EbsOptimized bool `mapstructure:"ebs_optimized"` EbsOptimized bool `mapstructure:"ebs_optimized"`
EnableT2Unlimited bool `mapstructure:"enable_t2_unlimited"` EnableT2Unlimited bool `mapstructure:"enable_t2_unlimited"`
IamInstanceProfile string `mapstructure:"iam_instance_profile"` IamInstanceProfile string `mapstructure:"iam_instance_profile"`
InstanceInitiatedShutdownBehavior string `mapstructure:"shutdown_behavior"` InstanceInitiatedShutdownBehavior string `mapstructure:"shutdown_behavior"`
InstanceType string `mapstructure:"instance_type"` InstanceType string `mapstructure:"instance_type"`
RunTags map[string]string `mapstructure:"run_tags"` SecurityGroupFilter SecurityGroupFilterOptions `mapstructure:"security_group_filter"`
SecurityGroupId string `mapstructure:"security_group_id"` RunTags map[string]string `mapstructure:"run_tags"`
SecurityGroupIds []string `mapstructure:"security_group_ids"` SecurityGroupId string `mapstructure:"security_group_id"`
SourceAmi string `mapstructure:"source_ami"` SecurityGroupIds []string `mapstructure:"security_group_ids"`
SourceAmiFilter AmiFilterOptions `mapstructure:"source_ami_filter"` SourceAmi string `mapstructure:"source_ami"`
SpotPrice string `mapstructure:"spot_price"` SourceAmiFilter AmiFilterOptions `mapstructure:"source_ami_filter"`
SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product"` SpotPrice string `mapstructure:"spot_price"`
SpotTags map[string]string `mapstructure:"spot_tags"` SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product"`
SubnetId string `mapstructure:"subnet_id"` SpotTags map[string]string `mapstructure:"spot_tags"`
TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` SubnetFilter SubnetFilterOptions `mapstructure:"subnet_filter"`
TemporarySGSourceCidr string `mapstructure:"temporary_security_group_source_cidr"` SubnetId string `mapstructure:"subnet_id"`
UserData string `mapstructure:"user_data"` TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"`
UserDataFile string `mapstructure:"user_data_file"` TemporarySGSourceCidr string `mapstructure:"temporary_security_group_source_cidr"`
VpcId string `mapstructure:"vpc_id"` UserData string `mapstructure:"user_data"`
WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout"` UserDataFile string `mapstructure:"user_data_file"`
VpcFilter VpcFilterOptions `mapstructure:"vpc_filter"`
VpcId string `mapstructure:"vpc_id"`
WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout"`
// Communicator settings // Communicator settings
Comm communicator.Config `mapstructure:",squash"` Comm communicator.Config `mapstructure:",squash"`

View File

@ -0,0 +1,154 @@
package common
import (
"context"
"fmt"
"log"
"math/rand"
"sort"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
// StepNetworkInfo queries AWS for information about
// VPC's and Subnets that is used throughout the AMI creation process.
//
// Produces (adding them to the state bag):
// vpc_id string - the VPC ID
// subnet_id string - the Subnet ID
// availability_zone string - the AZ name
type StepNetworkInfo struct {
VpcId string
VpcFilter VpcFilterOptions
SubnetId string
SubnetFilter SubnetFilterOptions
AvailabilityZone string
SecurityGroupIds []string
SecurityGroupFilter SecurityGroupFilterOptions
}
type subnetsSort []*ec2.Subnet
func (a subnetsSort) Len() int { return len(a) }
func (a subnetsSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a subnetsSort) Less(i, j int) bool {
return *a[i].AvailableIpAddressCount < *a[j].AvailableIpAddressCount
}
// Returns the most recent AMI out of a slice of images.
func mostFreeSubnet(subnets []*ec2.Subnet) *ec2.Subnet {
sortedSubnets := subnets
sort.Sort(subnetsSort(sortedSubnets))
return sortedSubnets[len(sortedSubnets)-1]
}
func (s *StepNetworkInfo) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui)
// VPC
if s.VpcId == "" && !s.VpcFilter.Empty() {
params := &ec2.DescribeVpcsInput{}
params.Filters = buildEc2Filters(s.VpcFilter.Filters)
s.VpcFilter.Filters[aws.String("state")] = aws.String("available")
log.Printf("Using VPC Filters %v", params)
vpcResp, err := ec2conn.DescribeVpcs(params)
if err != nil {
err := fmt.Errorf("Error querying VPCs: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if len(vpcResp.Vpcs) != 1 {
err := fmt.Errorf("Exactly one VPC should match the filter, but %d VPC's was found matching filters: %v", len(vpcResp.Vpcs), params)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
s.VpcId = *vpcResp.Vpcs[0].VpcId
ui.Message(fmt.Sprintf("Found VPC ID: %s", s.VpcId))
}
// Subnet
if s.SubnetId == "" && !s.SubnetFilter.Empty() {
params := &ec2.DescribeSubnetsInput{}
s.SubnetFilter.Filters[aws.String("state")] = aws.String("available")
if s.VpcId != "" {
s.SubnetFilter.Filters[aws.String("vpc-id")] = &s.VpcId
}
if s.AvailabilityZone != "" {
s.SubnetFilter.Filters[aws.String("availability-zone")] = &s.AvailabilityZone
}
params.Filters = buildEc2Filters(s.SubnetFilter.Filters)
log.Printf("Using Subnet Filters %v", params)
subnetsResp, err := ec2conn.DescribeSubnets(params)
if err != nil {
err := fmt.Errorf("Error querying Subnets: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if len(subnetsResp.Subnets) == 0 {
err := fmt.Errorf("No Subnets was found matching filters: %v", params)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if len(subnetsResp.Subnets) > 1 && !s.SubnetFilter.Random && !s.SubnetFilter.MostFree {
err := fmt.Errorf("Your filter matched %d Subnets. Please try a more specific search, or set random or most_free to true.", len(subnetsResp.Subnets))
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
var subnet *ec2.Subnet
switch {
case s.SubnetFilter.MostFree:
subnet = mostFreeSubnet(subnetsResp.Subnets)
case s.SubnetFilter.Random:
subnet = subnetsResp.Subnets[rand.Intn(len(subnetsResp.Subnets))]
default:
subnet = subnetsResp.Subnets[0]
}
s.SubnetId = *subnet.SubnetId
ui.Message(fmt.Sprintf("Found Subnet ID: %s", s.SubnetId))
}
// Try to find AZ and VPC Id from Subnet if they are not yet found/given
if s.SubnetId != "" && (s.AvailabilityZone == "" || s.VpcId == "") {
log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", s.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&s.SubnetId}})
if err != nil {
err := fmt.Errorf("Describing the subnet: %s returned error: %s.", s.SubnetId, err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
if s.AvailabilityZone == "" {
s.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AvailabilityZone found: '%s'", s.AvailabilityZone)
}
if s.VpcId == "" {
s.VpcId = *resp.Subnets[0].VpcId
log.Printf("[INFO] VpcId found: '%s'", s.VpcId)
}
}
state.Put("vpc_id", s.VpcId)
state.Put("availability_zone", s.AvailabilityZone)
state.Put("subnet_id", s.SubnetId)
return multistep.ActionContinue
}
func (s *StepNetworkInfo) Cleanup(multistep.StateBag) {}

View File

@ -20,7 +20,6 @@ import (
type StepRunSourceInstance struct { type StepRunSourceInstance struct {
AssociatePublicIpAddress bool AssociatePublicIpAddress bool
AvailabilityZone string
BlockDevices BlockDevices BlockDevices BlockDevices
Comm *communicator.Config Comm *communicator.Config
Ctx interpolate.Context Ctx interpolate.Context
@ -33,7 +32,6 @@ type StepRunSourceInstance struct {
InstanceType string InstanceType string
IsRestricted bool IsRestricted bool
SourceAMI string SourceAMI string
SubnetId string
Tags TagMap Tags TagMap
UserData string UserData string
UserDataFile string UserDataFile string
@ -104,6 +102,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
return multistep.ActionHalt return multistep.ActionHalt
} }
az := state.Get("availability_zone").(string)
runOpts := &ec2.RunInstancesInput{ runOpts := &ec2.RunInstancesInput{
ImageId: &s.SourceAMI, ImageId: &s.SourceAMI,
InstanceType: &s.InstanceType, InstanceType: &s.InstanceType,
@ -112,7 +111,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
MinCount: aws.Int64(1), MinCount: aws.Int64(1),
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile}, IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(), BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
Placement: &ec2.Placement{AvailabilityZone: &s.AvailabilityZone}, Placement: &ec2.Placement{AvailabilityZone: &az},
EbsOptimized: &s.EbsOptimized, EbsOptimized: &s.EbsOptimized,
} }
@ -153,18 +152,20 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
runOpts.KeyName = &s.Comm.SSHKeyPairName runOpts.KeyName = &s.Comm.SSHKeyPairName
} }
if s.SubnetId != "" && s.AssociatePublicIpAddress { subnetId := state.Get("subnet_id").(string)
if subnetId != "" && s.AssociatePublicIpAddress {
runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{
{ {
DeviceIndex: aws.Int64(0), DeviceIndex: aws.Int64(0),
AssociatePublicIpAddress: &s.AssociatePublicIpAddress, AssociatePublicIpAddress: &s.AssociatePublicIpAddress,
SubnetId: &s.SubnetId, SubnetId: aws.String(subnetId),
Groups: securityGroupIds, Groups: securityGroupIds,
DeleteOnTermination: aws.Bool(true), DeleteOnTermination: aws.Bool(true),
}, },
} }
} else { } else {
runOpts.SubnetId = &s.SubnetId runOpts.SubnetId = aws.String(subnetId)
runOpts.SecurityGroupIds = securityGroupIds runOpts.SecurityGroupIds = securityGroupIds
} }

View File

@ -22,7 +22,6 @@ import (
type StepRunSpotInstance struct { type StepRunSpotInstance struct {
AssociatePublicIpAddress bool AssociatePublicIpAddress bool
AvailabilityZone string
BlockDevices BlockDevices BlockDevices BlockDevices
BlockDurationMinutes int64 BlockDurationMinutes int64
Debug bool Debug bool
@ -36,7 +35,6 @@ type StepRunSpotInstance struct {
SpotPrice string SpotPrice string
SpotPriceProduct string SpotPriceProduct string
SpotTags TagMap SpotTags TagMap
SubnetId string
Tags TagMap Tags TagMap
VolumeTags TagMap VolumeTags TagMap
UserData string UserData string
@ -86,7 +84,12 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
} }
spotPrice := s.SpotPrice spotPrice := s.SpotPrice
availabilityZone := s.AvailabilityZone azConfig := ""
if azRaw, ok := state.GetOk("availability_zone"); ok {
azConfig = azRaw.(string)
}
az := azConfig
if spotPrice == "auto" { if spotPrice == "auto" {
ui.Message(fmt.Sprintf( ui.Message(fmt.Sprintf(
"Finding spot price for %s %s...", "Finding spot price for %s %s...",
@ -97,7 +100,7 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistoryInput{ resp, err := ec2conn.DescribeSpotPriceHistory(&ec2.DescribeSpotPriceHistoryInput{
InstanceTypes: []*string{&s.InstanceType}, InstanceTypes: []*string{&s.InstanceType},
ProductDescriptions: []*string{&s.SpotPriceProduct}, ProductDescriptions: []*string{&s.SpotPriceProduct},
AvailabilityZone: &s.AvailabilityZone, AvailabilityZone: &az,
StartTime: &startTime, StartTime: &startTime,
}) })
if err != nil { if err != nil {
@ -117,8 +120,8 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
} }
if price == 0 || current < price { if price == 0 || current < price {
price = current price = current
if s.AvailabilityZone == "" { if azConfig == "" {
availabilityZone = *history.AvailabilityZone az = *history.AvailabilityZone
} }
} }
} }
@ -162,24 +165,26 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag)
UserData: &userData, UserData: &userData,
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile}, IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
Placement: &ec2.SpotPlacement{ Placement: &ec2.SpotPlacement{
AvailabilityZone: &availabilityZone, AvailabilityZone: &az,
}, },
BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(), BlockDeviceMappings: s.BlockDevices.BuildLaunchDevices(),
EbsOptimized: &s.EbsOptimized, EbsOptimized: &s.EbsOptimized,
} }
if s.SubnetId != "" && s.AssociatePublicIpAddress { subnetId := state.Get("subnet_id").(string)
if subnetId != "" && s.AssociatePublicIpAddress {
runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{ runOpts.NetworkInterfaces = []*ec2.InstanceNetworkInterfaceSpecification{
{ {
DeviceIndex: aws.Int64(0), DeviceIndex: aws.Int64(0),
AssociatePublicIpAddress: &s.AssociatePublicIpAddress, AssociatePublicIpAddress: &s.AssociatePublicIpAddress,
SubnetId: &s.SubnetId, SubnetId: &subnetId,
Groups: securityGroupIds, Groups: securityGroupIds,
DeleteOnTermination: aws.Bool(true), DeleteOnTermination: aws.Bool(true),
}, },
} }
} else { } else {
runOpts.SubnetId = &s.SubnetId runOpts.SubnetId = &subnetId
runOpts.SecurityGroupIds = securityGroupIds runOpts.SecurityGroupIds = securityGroupIds
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"log" "log"
"strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -17,8 +18,8 @@ import (
type StepSecurityGroup struct { type StepSecurityGroup struct {
CommConfig *communicator.Config CommConfig *communicator.Config
SecurityGroupFilter SecurityGroupFilterOptions
SecurityGroupIds []string SecurityGroupIds []string
VpcId string
TemporarySGSourceCidr string TemporarySGSourceCidr string
createdGroupId string createdGroupId string
@ -27,6 +28,7 @@ type StepSecurityGroup struct {
func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2) ec2conn := state.Get("ec2").(*ec2.EC2)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vpcId := state.Get("vpc_id").(string)
if len(s.SecurityGroupIds) > 0 { if len(s.SecurityGroupIds) > 0 {
_, err := ec2conn.DescribeSecurityGroups( _, err := ec2conn.DescribeSecurityGroups(
@ -45,6 +47,35 @@ func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) mul
return multistep.ActionContinue return multistep.ActionContinue
} }
if !s.SecurityGroupFilter.Empty() {
params := &ec2.DescribeSecurityGroupsInput{}
if vpcId != "" {
s.SecurityGroupFilter.Filters[aws.String("vpc-id")] = &vpcId
}
params.Filters = buildEc2Filters(s.SecurityGroupFilter.Filters)
log.Printf("Using SecurityGroup Filters %v", params)
sgResp, err := ec2conn.DescribeSecurityGroups(params)
if err != nil {
err := fmt.Errorf("Couldn't find security groups for filter: %s", err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
securityGroupIds := []string{}
for _, sg := range sgResp.SecurityGroups {
securityGroupIds = append(securityGroupIds, *sg.GroupId)
}
ui.Message(fmt.Sprintf("Found Security Group(s): %s", strings.Join(securityGroupIds, ", ")))
state.Put("securityGroupIds", securityGroupIds)
return multistep.ActionContinue
}
port := s.CommConfig.Port() port := s.CommConfig.Port()
if port == 0 { if port == 0 {
if s.CommConfig.Type != "none" { if s.CommConfig.Type != "none" {
@ -60,9 +91,7 @@ func (s *StepSecurityGroup) Run(_ context.Context, state multistep.StateBag) mul
Description: aws.String("Temporary group for Packer"), Description: aws.String("Temporary group for Packer"),
} }
if s.VpcId != "" { group.VpcId = &vpcId
group.VpcId = &s.VpcId
}
groupResp, err := ec2conn.CreateSecurityGroup(group) groupResp, err := ec2conn.CreateSecurityGroup(group)
if err != nil { if err != nil {

View File

@ -25,18 +25,6 @@ type StepSourceAMIInfo struct {
AmiFilters AmiFilterOptions AmiFilters AmiFilterOptions
} }
// 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 {
filters = append(filters, &ec2.Filter{
Name: k,
Values: []*string{v},
})
}
return filters
}
type imageSort []*ec2.Image type imageSort []*ec2.Image
func (a imageSort) Len() int { return len(a) } func (a imageSort) Len() int { return len(a) }
@ -66,7 +54,7 @@ func (s *StepSourceAMIInfo) Run(_ context.Context, state multistep.StateBag) mul
// We have filters to apply // We have filters to apply
if len(s.AmiFilters.Filters) > 0 { if len(s.AmiFilters.Filters) > 0 {
params.Filters = buildAmiFilters(s.AmiFilters.Filters) params.Filters = buildEc2Filters(s.AmiFilters.Filters)
} }
if len(s.AmiFilters.Owners) > 0 { if len(s.AmiFilters.Owners) > 0 {
params.Owners = s.AmiFilters.Owners params.Owners = s.AmiFilters.Owners

View File

@ -93,23 +93,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
ec2conn := ec2.New(session) ec2conn := ec2.New(session)
// If the subnet is specified but not the VpcId or AZ, try to determine them automatically
if b.config.SubnetId != "" && (b.config.AvailabilityZone == "" || b.config.VpcId == "") {
log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
if b.config.AvailabilityZone == "" {
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AvailabilityZone found: '%s'", b.config.AvailabilityZone)
}
if b.config.VpcId == "" {
b.config.VpcId = *resp.Subnets[0].VpcId
log.Printf("[INFO] VpcId found: '%s'", b.config.VpcId)
}
}
// Setup the state bag and initial state for the steps // Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("config", &b.config) state.Put("config", &b.config)
@ -123,7 +106,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if b.config.IsSpotInstance() { if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{ instanceStep = &awscommon.StepRunSpotInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
BlockDurationMinutes: b.config.BlockDurationMinutes, BlockDurationMinutes: b.config.BlockDurationMinutes,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -138,7 +120,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SpotPrice: b.config.SpotPrice, SpotPrice: b.config.SpotPrice,
SpotPriceProduct: b.config.SpotPriceAutoProduct, SpotPriceProduct: b.config.SpotPriceAutoProduct,
SpotTags: b.config.SpotTags, SpotTags: b.config.SpotTags,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -147,7 +128,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} else { } else {
instanceStep = &awscommon.StepRunSourceInstance{ instanceStep = &awscommon.StepRunSourceInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -160,7 +140,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
InstanceType: b.config.InstanceType, InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(), IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi, SourceAMI: b.config.SourceAmi,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -181,15 +160,24 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
AmiFilters: b.config.SourceAmiFilter, AmiFilters: b.config.SourceAmiFilter,
AMIVirtType: b.config.AMIVirtType, AMIVirtType: b.config.AMIVirtType,
}, },
&awscommon.StepNetworkInfo{
VpcId: b.config.VpcId,
VpcFilter: b.config.VpcFilter,
SecurityGroupIds: b.config.SecurityGroupIds,
SecurityGroupFilter: b.config.SecurityGroupFilter,
SubnetId: b.config.SubnetId,
SubnetFilter: b.config.SubnetFilter,
AvailabilityZone: b.config.AvailabilityZone,
},
&awscommon.StepKeyPair{ &awscommon.StepKeyPair{
Debug: b.config.PackerDebug, Debug: b.config.PackerDebug,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName),
}, },
&awscommon.StepSecurityGroup{ &awscommon.StepSecurityGroup{
SecurityGroupFilter: b.config.SecurityGroupFilter,
SecurityGroupIds: b.config.SecurityGroupIds, SecurityGroupIds: b.config.SecurityGroupIds,
CommConfig: &b.config.RunConfig.Comm, CommConfig: &b.config.RunConfig.Comm,
VpcId: b.config.VpcId,
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr, TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
}, },
&awscommon.StepCleanupVolumes{ &awscommon.StepCleanupVolumes{

View File

@ -107,23 +107,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
ec2conn := ec2.New(session) ec2conn := ec2.New(session)
// If the subnet is specified but not the VpcId or AZ, try to determine them automatically
if b.config.SubnetId != "" && (b.config.AvailabilityZone == "" || b.config.VpcId == "") {
log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
if b.config.AvailabilityZone == "" {
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AvailabilityZone found: '%s'", b.config.AvailabilityZone)
}
if b.config.VpcId == "" {
b.config.VpcId = *resp.Subnets[0].VpcId
log.Printf("[INFO] VpcId found: '%s'", b.config.VpcId)
}
}
// Setup the state bag and initial state for the steps // Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("config", &b.config) state.Put("config", &b.config)
@ -137,7 +120,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if b.config.IsSpotInstance() { if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{ instanceStep = &awscommon.StepRunSpotInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
BlockDurationMinutes: b.config.BlockDurationMinutes, BlockDurationMinutes: b.config.BlockDurationMinutes,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -152,7 +134,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SpotPrice: b.config.SpotPrice, SpotPrice: b.config.SpotPrice,
SpotPriceProduct: b.config.SpotPriceAutoProduct, SpotPriceProduct: b.config.SpotPriceAutoProduct,
SpotTags: b.config.SpotTags, SpotTags: b.config.SpotTags,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -161,7 +142,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} else { } else {
instanceStep = &awscommon.StepRunSourceInstance{ instanceStep = &awscommon.StepRunSourceInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -174,7 +154,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
InstanceType: b.config.InstanceType, InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(), IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi, SourceAMI: b.config.SourceAmi,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -198,15 +177,24 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
AmiFilters: b.config.SourceAmiFilter, AmiFilters: b.config.SourceAmiFilter,
AMIVirtType: b.config.AMIVirtType, AMIVirtType: b.config.AMIVirtType,
}, },
&awscommon.StepNetworkInfo{
VpcId: b.config.VpcId,
VpcFilter: b.config.VpcFilter,
SecurityGroupIds: b.config.SecurityGroupIds,
SecurityGroupFilter: b.config.SecurityGroupFilter,
SubnetId: b.config.SubnetId,
SubnetFilter: b.config.SubnetFilter,
AvailabilityZone: b.config.AvailabilityZone,
},
&awscommon.StepKeyPair{ &awscommon.StepKeyPair{
Debug: b.config.PackerDebug, Debug: b.config.PackerDebug,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName),
}, },
&awscommon.StepSecurityGroup{ &awscommon.StepSecurityGroup{
SecurityGroupFilter: b.config.SecurityGroupFilter,
SecurityGroupIds: b.config.SecurityGroupIds, SecurityGroupIds: b.config.SecurityGroupIds,
CommConfig: &b.config.RunConfig.Comm, CommConfig: &b.config.RunConfig.Comm,
VpcId: b.config.VpcId,
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr, TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
}, },
&awscommon.StepCleanupVolumes{ &awscommon.StepCleanupVolumes{

View File

@ -92,23 +92,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
ec2conn := ec2.New(session) ec2conn := ec2.New(session)
// If the subnet is specified but not the VpcId or AZ, try to determine them automatically
if b.config.SubnetId != "" && (b.config.AvailabilityZone == "" || b.config.VpcId == "") {
log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
if b.config.AvailabilityZone == "" {
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AvailabilityZone found: '%s'", b.config.AvailabilityZone)
}
if b.config.VpcId == "" {
b.config.VpcId = *resp.Subnets[0].VpcId
log.Printf("[INFO] VpcId found: '%s'", b.config.VpcId)
}
}
// Setup the state bag and initial state for the steps // Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("config", &b.config) state.Put("config", &b.config)
@ -121,7 +104,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if b.config.IsSpotInstance() { if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{ instanceStep = &awscommon.StepRunSpotInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.launchBlockDevices, BlockDevices: b.config.launchBlockDevices,
BlockDurationMinutes: b.config.BlockDurationMinutes, BlockDurationMinutes: b.config.BlockDurationMinutes,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -136,7 +118,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SpotPrice: b.config.SpotPrice, SpotPrice: b.config.SpotPrice,
SpotPriceProduct: b.config.SpotPriceAutoProduct, SpotPriceProduct: b.config.SpotPriceAutoProduct,
SpotTags: b.config.SpotTags, SpotTags: b.config.SpotTags,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -144,7 +125,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} else { } else {
instanceStep = &awscommon.StepRunSourceInstance{ instanceStep = &awscommon.StepRunSourceInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.launchBlockDevices, BlockDevices: b.config.launchBlockDevices,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -157,7 +137,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
InstanceType: b.config.InstanceType, InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(), IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi, SourceAMI: b.config.SourceAmi,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -172,15 +151,24 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
EnableAMIENASupport: b.config.AMIENASupport, EnableAMIENASupport: b.config.AMIENASupport,
AmiFilters: b.config.SourceAmiFilter, AmiFilters: b.config.SourceAmiFilter,
}, },
&awscommon.StepNetworkInfo{
VpcId: b.config.VpcId,
VpcFilter: b.config.VpcFilter,
SecurityGroupIds: b.config.SecurityGroupIds,
SecurityGroupFilter: b.config.SecurityGroupFilter,
SubnetId: b.config.SubnetId,
SubnetFilter: b.config.SubnetFilter,
AvailabilityZone: b.config.AvailabilityZone,
},
&awscommon.StepKeyPair{ &awscommon.StepKeyPair{
Debug: b.config.PackerDebug, Debug: b.config.PackerDebug,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName),
}, },
&awscommon.StepSecurityGroup{ &awscommon.StepSecurityGroup{
SecurityGroupFilter: b.config.SecurityGroupFilter,
SecurityGroupIds: b.config.SecurityGroupIds, SecurityGroupIds: b.config.SecurityGroupIds,
CommConfig: &b.config.RunConfig.Comm, CommConfig: &b.config.RunConfig.Comm,
VpcId: b.config.VpcId,
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr, TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
}, },
instanceStep, instanceStep,

View File

@ -177,23 +177,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
ec2conn := ec2.New(session) ec2conn := ec2.New(session)
// If the subnet is specified but not the VpcId or AZ, try to determine them automatically
if b.config.SubnetId != "" && (b.config.AvailabilityZone == "" || b.config.VpcId == "") {
log.Printf("[INFO] Finding AZ and VpcId for the given subnet '%s'", b.config.SubnetId)
resp, err := ec2conn.DescribeSubnets(&ec2.DescribeSubnetsInput{SubnetIds: []*string{&b.config.SubnetId}})
if err != nil {
return nil, err
}
if b.config.AvailabilityZone == "" {
b.config.AvailabilityZone = *resp.Subnets[0].AvailabilityZone
log.Printf("[INFO] AvailabilityZone found: '%s'", b.config.AvailabilityZone)
}
if b.config.VpcId == "" {
b.config.VpcId = *resp.Subnets[0].VpcId
log.Printf("[INFO] VpcId found: '%s'", b.config.VpcId)
}
}
// Setup the state bag and initial state for the steps // Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag) state := new(multistep.BasicStateBag)
state.Put("config", &b.config) state.Put("config", &b.config)
@ -207,7 +190,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
if b.config.IsSpotInstance() { if b.config.IsSpotInstance() {
instanceStep = &awscommon.StepRunSpotInstance{ instanceStep = &awscommon.StepRunSpotInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
BlockDurationMinutes: b.config.BlockDurationMinutes, BlockDurationMinutes: b.config.BlockDurationMinutes,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -219,7 +201,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SourceAMI: b.config.SourceAmi, SourceAMI: b.config.SourceAmi,
SpotPrice: b.config.SpotPrice, SpotPrice: b.config.SpotPrice,
SpotPriceProduct: b.config.SpotPriceAutoProduct, SpotPriceProduct: b.config.SpotPriceAutoProduct,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
SpotTags: b.config.SpotTags, SpotTags: b.config.SpotTags,
UserData: b.config.UserData, UserData: b.config.UserData,
@ -228,7 +209,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} else { } else {
instanceStep = &awscommon.StepRunSourceInstance{ instanceStep = &awscommon.StepRunSourceInstance{
AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AssociatePublicIpAddress: b.config.AssociatePublicIpAddress,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices, BlockDevices: b.config.BlockDevices,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
Ctx: b.config.ctx, Ctx: b.config.ctx,
@ -239,7 +219,6 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
InstanceType: b.config.InstanceType, InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(), IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
SourceAMI: b.config.SourceAmi, SourceAMI: b.config.SourceAmi,
SubnetId: b.config.SubnetId,
Tags: b.config.RunTags, Tags: b.config.RunTags,
UserData: b.config.UserData, UserData: b.config.UserData,
UserDataFile: b.config.UserDataFile, UserDataFile: b.config.UserDataFile,
@ -259,6 +238,15 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
AmiFilters: b.config.SourceAmiFilter, AmiFilters: b.config.SourceAmiFilter,
AMIVirtType: b.config.AMIVirtType, AMIVirtType: b.config.AMIVirtType,
}, },
&awscommon.StepNetworkInfo{
VpcId: b.config.VpcId,
VpcFilter: b.config.VpcFilter,
SecurityGroupIds: b.config.SecurityGroupIds,
SecurityGroupFilter: b.config.SecurityGroupFilter,
SubnetId: b.config.SubnetId,
SubnetFilter: b.config.SubnetFilter,
AvailabilityZone: b.config.AvailabilityZone,
},
&awscommon.StepKeyPair{ &awscommon.StepKeyPair{
Debug: b.config.PackerDebug, Debug: b.config.PackerDebug,
Comm: &b.config.RunConfig.Comm, Comm: &b.config.RunConfig.Comm,
@ -266,8 +254,8 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}, },
&awscommon.StepSecurityGroup{ &awscommon.StepSecurityGroup{
CommConfig: &b.config.RunConfig.Comm, CommConfig: &b.config.RunConfig.Comm,
SecurityGroupFilter: b.config.SecurityGroupFilter,
SecurityGroupIds: b.config.SecurityGroupIds, SecurityGroupIds: b.config.SecurityGroupIds,
VpcId: b.config.VpcId,
TemporarySGSourceCidr: b.config.TemporarySGSourceCidr, TemporarySGSourceCidr: b.config.TemporarySGSourceCidr,
}, },
instanceStep, instanceStep,

View File

@ -278,6 +278,27 @@ builder.
described above. Note that if this is specified, you must omit the described above. Note that if this is specified, you must omit the
`security_group_id`. `security_group_id`.
- `security_group_filter` (object) - Filters used to populate the `security_group_ids` field.
Example:
``` json
{
"security_group_filter": {
"filters": {
"tag:Class": "packer"
}
}
}
```
This selects the SG's with tag `Class` with the value `packer`.
- `filters` (map of strings) - filters used to select a `security_group_ids`.
Any filter described in the docs for [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
is valid.
`security_group_ids` take precendense over this.
- `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized - `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized
access to the instance, when packer is creating a temporary security group. access to the instance, when packer is creating a temporary security group.
The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used
@ -401,6 +422,39 @@ builder.
`subnet-12345def`, where Packer will launch the EC2 instance. This field is `subnet-12345def`, where Packer will launch the EC2 instance. This field is
required if you are using an non-default VPC. required if you are using an non-default VPC.
- `subnet_filter` (object) - Filters used to populate the `subnet_id` field.
Example:
``` json
{
"subnet_filter": {
"filters": {
"tag:Class": "build"
},
"most_free": true,
"random": false
}
}
```
This selects the Subnet with tag `Class` with the value `build`, which has
the most free IP addresses.
NOTE: This will fail unless *exactly* one Subnet is returned. By using
`most_free` or `random` one will be selected from those matching the filter.
- `filters` (map of strings) - filters used to select a `subnet_id`.
NOTE: This will fail unless *exactly* one Subnet is returned.
Any filter described in the docs for [DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
is valid.
- `most_free` (boolean) - The Subnet with the most free IPv4 addresses
will be used if multiple Subnets matches the filter.
- `random` (boolean) - A random Subnet will be used if multiple Subnets
matches the filter. `most_free` have precendence over this.
`subnet_id` take precedence over this.
- `tags` (object of key/value strings) - Tags applied to the AMI and - `tags` (object of key/value strings) - Tags applied to the AMI and
relevant snapshots. This is a relevant snapshots. This is a
[template engine](/docs/templates/engine.html), [template engine](/docs/templates/engine.html),
@ -427,6 +481,32 @@ builder.
to be set. If this field is left blank, Packer will try to get the VPC ID from the to be set. If this field is left blank, Packer will try to get the VPC ID from the
`subnet_id`. `subnet_id`.
- `vpc_filter` (object) - Filters used to populate the `vpc_id` field.
Example:
``` json
{
"vpc_filter": {
"filters": {
"tag:Class": "build",
"isDefault": "false",
"cidr": "/24"
}
}
}
```
This selects the VPC with tag `Class` with the value `build`, which is not the
default VPC, and have a IPv4 CIDR block of `/24`.
NOTE: This will fail unless *exactly* one VPC is returned.
- `filters` (map of strings) - filters used to select a `vpc_id`.
NOTE: This will fail unless *exactly* one VPC is returned.
Any filter described in the docs for [DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
is valid.
`vpc_id` take precedence over this.
- `windows_password_timeout` (string) - The timeout for waiting for a Windows - `windows_password_timeout` (string) - The timeout for waiting for a Windows
password for Windows instances. Defaults to 20 minutes. Example value: `10m` password for Windows instances. Defaults to 20 minutes. Example value: `10m`

View File

@ -271,6 +271,27 @@ builder.
described above. Note that if this is specified, you must omit the described above. Note that if this is specified, you must omit the
`security_group_id`. `security_group_id`.
- `security_group_filter` (object) - Filters used to populate the `security_group_ids` field.
Example:
``` json
{
"security_group_filter": {
"filters": {
"tag:Class": "packer"
}
}
}
```
This selects the SG's with tag `Class` with the value `packer`.
- `filters` (map of strings) - filters used to select a `security_group_ids`.
Any filter described in the docs for [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
is valid.
`security_group_ids` take precendense over this.
- `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized - `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized
access to the instance, when packer is creating a temporary security group. access to the instance, when packer is creating a temporary security group.
The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used
@ -395,6 +416,39 @@ builder.
`subnet-12345def`, where Packer will launch the EC2 instance. This field is `subnet-12345def`, where Packer will launch the EC2 instance. This field is
required if you are using an non-default VPC. required if you are using an non-default VPC.
- `subnet_filter` (object) - Filters used to populate the `subnet_id` field.
Example:
``` json
{
"subnet_filter": {
"filters": {
"tag:Class": "build"
},
"most_free": true,
"random": false
}
}
```
This selects the Subnet with tag `Class` with the value `build`, which has
the most free IP addresses.
NOTE: This will fail unless *exactly* one Subnet is returned. By using
`most_free` or `random` one will be selected from those matching the filter.
- `filters` (map of strings) - filters used to select a `subnet_id`.
NOTE: This will fail unless *exactly* one Subnet is returned.
Any filter described in the docs for [DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
is valid.
- `most_free` (boolean) - The Subnet with the most free IPv4 addresses
will be used if multiple Subnets matches the filter.
- `random` (boolean) - A random Subnet will be used if multiple Subnets
matches the filter. `most_free` have precendence over this.
`subnet_id` take precedence over this.
- `tags` (object of key/value strings) - Tags applied to the AMI and - `tags` (object of key/value strings) - Tags applied to the AMI and
relevant snapshots. This is a relevant snapshots. This is a
[template engine](/docs/templates/engine.html), [template engine](/docs/templates/engine.html),
@ -420,6 +474,32 @@ builder.
to be set. If this field is left blank, Packer will try to get the VPC ID from the to be set. If this field is left blank, Packer will try to get the VPC ID from the
`subnet_id`. `subnet_id`.
- `vpc_filter` (object) - Filters used to populate the `vpc_id` field.
Example:
``` json
{
"vpc_filter": {
"filters": {
"tag:Class": "build",
"isDefault": "false",
"cidr": "/24"
}
}
}
```
This selects the VPC with tag `Class` with the value `build`, which is not the
default VPC, and have a IPv4 CIDR block of `/24`.
NOTE: This will fail unless *exactly* one VPC is returned.
- `filters` (map of strings) - filters used to select a `vpc_id`.
NOTE: This will fail unless *exactly* one VPC is returned.
Any filter described in the docs for [DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
is valid.
`vpc_id` take precedence over this.
- `windows_password_timeout` (string) - The timeout for waiting for a Windows - `windows_password_timeout` (string) - The timeout for waiting for a Windows
password for Windows instances. Defaults to 20 minutes. Example value: `10m` password for Windows instances. Defaults to 20 minutes. Example value: `10m`

View File

@ -204,6 +204,27 @@ builder.
described above. Note that if this is specified, you must omit the described above. Note that if this is specified, you must omit the
`security_group_id`. `security_group_id`.
- `security_group_filter` (object) - Filters used to populate the `security_group_ids` field.
Example:
``` json
{
"security_group_filter": {
"filters": {
"tag:Class": "packer"
}
}
}
```
This selects the SG's with tag `Class` with the value `packer`.
- `filters` (map of strings) - filters used to select a `security_group_ids`.
Any filter described in the docs for [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
is valid.
`security_group_ids` take precendense over this.
- `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized - `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized
access to the instance, when packer is creating a temporary security group. access to the instance, when packer is creating a temporary security group.
The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used
@ -313,6 +334,39 @@ builder.
`subnet-12345def`, where Packer will launch the EC2 instance. This field is `subnet-12345def`, where Packer will launch the EC2 instance. This field is
required if you are using an non-default VPC. required if you are using an non-default VPC.
- `subnet_filter` (object) - Filters used to populate the `subnet_id` field.
Example:
``` json
{
"subnet_filter": {
"filters": {
"tag:Class": "build"
},
"most_free": true,
"random": false
}
}
```
This selects the Subnet with tag `Class` with the value `build`, which has
the most free IP addresses.
NOTE: This will fail unless *exactly* one Subnet is returned. By using
`most_free` or `random` one will be selected from those matching the filter.
- `filters` (map of strings) - filters used to select a `subnet_id`.
NOTE: This will fail unless *exactly* one Subnet is returned.
Any filter described in the docs for [DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
is valid.
- `most_free` (boolean) - The Subnet with the most free IPv4 addresses
will be used if multiple Subnets matches the filter.
- `random` (boolean) - A random Subnet will be used if multiple Subnets
matches the filter. `most_free` have precendence over this.
`subnet_id` take precedence over this.
- `temporary_key_pair_name` (string) - The name of the temporary key pair - `temporary_key_pair_name` (string) - The name of the temporary key pair
to generate. By default, Packer generates a name that looks like to generate. By default, Packer generates a name that looks like
`packer_<UUID>`, where &lt;UUID&gt; is a 36 character unique identifier. `packer_<UUID>`, where &lt;UUID&gt; is a 36 character unique identifier.
@ -334,6 +388,32 @@ builder.
to be set. If this field is left blank, Packer will try to get the VPC ID from the to be set. If this field is left blank, Packer will try to get the VPC ID from the
`subnet_id`. `subnet_id`.
- `vpc_filter` (object) - Filters used to populate the `vpc_id` field.
Example:
``` json
{
"vpc_filter": {
"filters": {
"tag:Class": "build",
"isDefault": "false",
"cidr": "/24"
}
}
}
```
This selects the VPC with tag `Class` with the value `build`, which is not the
default VPC, and have a IPv4 CIDR block of `/24`.
NOTE: This will fail unless *exactly* one VPC is returned.
- `filters` (map of strings) - filters used to select a `vpc_id`.
NOTE: This will fail unless *exactly* one VPC is returned.
Any filter described in the docs for [DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
is valid.
`vpc_id` take precedence over this.
- `windows_password_timeout` (string) - The timeout for waiting for a Windows - `windows_password_timeout` (string) - The timeout for waiting for a Windows
password for Windows instances. Defaults to 20 minutes. Example value: `10m` password for Windows instances. Defaults to 20 minutes. Example value: `10m`

View File

@ -280,6 +280,27 @@ builder.
described above. Note that if this is specified, you must omit the described above. Note that if this is specified, you must omit the
`security_group_id`. `security_group_id`.
- `security_group_filter` (object) - Filters used to populate the `security_group_ids` field.
Example:
``` json
{
"security_group_filter": {
"filters": {
"tag:Class": "packer"
}
}
}
```
This selects the SG's with tag `Class` with the value `packer`.
- `filters` (map of strings) - filters used to select a `security_group_ids`.
Any filter described in the docs for [DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
is valid.
`security_group_ids` take precendense over this.
- `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized - `temporary_security_group_source_cidr` (string) - An IPv4 CIDR block to be authorized
access to the instance, when packer is creating a temporary security group. access to the instance, when packer is creating a temporary security group.
The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used The default is `0.0.0.0/0` (ie, allow any IPv4 source). This is only used
@ -397,6 +418,39 @@ builder.
`subnet-12345def`, where Packer will launch the EC2 instance. This field is `subnet-12345def`, where Packer will launch the EC2 instance. This field is
required if you are using an non-default VPC. required if you are using an non-default VPC.
- `subnet_filter` (object) - Filters used to populate the `subnet_id` field.
Example:
``` json
{
"subnet_filter": {
"filters": {
"tag:Class": "build"
},
"most_free": true,
"random": false
}
}
```
This selects the Subnet with tag `Class` with the value `build`, which has
the most free IP addresses.
NOTE: This will fail unless *exactly* one Subnet is returned. By using
`most_free` or `random` one will be selected from those matching the filter.
- `filters` (map of strings) - filters used to select a `subnet_id`.
NOTE: This will fail unless *exactly* one Subnet is returned.
Any filter described in the docs for [DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
is valid.
- `most_free` (boolean) - The Subnet with the most free IPv4 addresses
will be used if multiple Subnets matches the filter.
- `random` (boolean) - A random Subnet will be used if multiple Subnets
matches the filter. `most_free` have precendence over this.
`subnet_id` take precedence over this.
- `tags` (object of key/value strings) - Tags applied to the AMI. This is a - `tags` (object of key/value strings) - Tags applied to the AMI. This is a
[template engine](/docs/templates/engine.html), [template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information. see [Build template data](#build-template-data) for more information.
@ -417,6 +471,32 @@ builder.
to be set. If this field is left blank, Packer will try to get the VPC ID from the to be set. If this field is left blank, Packer will try to get the VPC ID from the
`subnet_id`. `subnet_id`.
- `vpc_filter` (object) - Filters used to populate the `vpc_id` field.
Example:
``` json
{
"vpc_filter": {
"filters": {
"tag:Class": "build",
"isDefault": "false",
"cidr": "/24"
}
}
}
```
This selects the VPC with tag `Class` with the value `build`, which is not the
default VPC, and have a IPv4 CIDR block of `/24`.
NOTE: This will fail unless *exactly* one VPC is returned.
- `filters` (map of strings) - filters used to select a `vpc_id`.
NOTE: This will fail unless *exactly* one VPC is returned.
Any filter described in the docs for [DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
is valid.
`vpc_id` take precedence over this.
- `x509_upload_path` (string) - The path on the remote machine where the X509 - `x509_upload_path` (string) - The path on the remote machine where the X509
certificate will be uploaded. This path must already exist and be writable. certificate will be uploaded. This path must already exist and be writable.
X509 certificates are uploaded after provisioning is run, so it is perfectly X509 certificates are uploaded after provisioning is run, so it is perfectly