builder/amazon: fix when using security_group_id

If `security_group_id` was specified with a group that didn't exist, packer
would go into an infinite loop waiting for it. We shouldn't make assumptions
about the status of explicitely set security groups, so let's just error out
right away if we can't find it.
This commit is contained in:
Matthew Hooker 2017-01-18 15:11:52 -08:00
parent ba90140b1a
commit b265d2614f
No known key found for this signature in database
GPG Key ID: 7B5F933D9CE8C6A1
2 changed files with 54 additions and 58 deletions

View File

@ -9,7 +9,6 @@ import (
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/private/waiter"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
@ -23,8 +22,9 @@ type StepRunSourceInstance struct {
Debug bool
EbsOptimized bool
ExpectedRootDevice string
InstanceType string
IamInstanceProfile string
InstanceInitiatedShutdownBehavior string
InstanceType string
SourceAMI string
SpotPrice string
SpotPriceProduct string
@ -32,7 +32,6 @@ type StepRunSourceInstance struct {
Tags map[string]string
UserData string
UserDataFile string
InstanceInitiatedShutdownBehavior string
instanceId string
spotRequest *ec2.SpotInstanceRequest
@ -41,28 +40,9 @@ type StepRunSourceInstance struct {
func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
keyName := state.Get("keyPair").(string)
tempSecurityGroupIds := state.Get("securityGroupIds").([]string)
securityGroupIds := aws.StringSlice(state.Get("securityGroupIds").([]string))
ui := state.Get("ui").(packer.Ui)
securityGroupIds := make([]*string, len(tempSecurityGroupIds))
for i, sg := range tempSecurityGroupIds {
log.Printf("[DEBUG] Waiting for tempSecurityGroup: %s", sg)
err := WaitUntilSecurityGroupExists(ec2conn,
&ec2.DescribeSecurityGroupsInput{
GroupIds: []*string{aws.String(sg)},
},
)
if err == nil {
log.Printf("[DEBUG] Found security group %s", sg)
securityGroupIds[i] = aws.String(sg)
} else {
err := fmt.Errorf("Timed out waiting for security group %s: %s", sg, err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
}
userData := s.UserData
if s.UserDataFile != "" {
contents, err := ioutil.ReadFile(s.UserDataFile)
@ -368,38 +348,3 @@ func (s *StepRunSourceInstance) Cleanup(state multistep.StateBag) {
WaitForState(&stateChange)
}
}
func WaitUntilSecurityGroupExists(c *ec2.EC2, input *ec2.DescribeSecurityGroupsInput) error {
waiterCfg := waiter.Config{
Operation: "DescribeSecurityGroups",
Delay: 15,
MaxAttempts: 40,
Acceptors: []waiter.WaitAcceptor{
{
State: "success",
Matcher: "path",
Argument: "length(SecurityGroups[]) > `0`",
Expected: true,
},
{
State: "retry",
Matcher: "error",
Argument: "",
Expected: "InvalidGroup.NotFound",
},
{
State: "retry",
Matcher: "error",
Argument: "",
Expected: "InvalidSecurityGroupID.NotFound",
},
},
}
w := waiter.Waiter{
Client: c,
Input: input,
Config: waiterCfg,
}
return w.Wait()
}

View File

@ -6,6 +6,7 @@ import (
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/private/waiter"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common/uuid"
@ -87,6 +88,21 @@ func (s *StepSecurityGroup) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
log.Printf("[DEBUG] Waiting for temporary security group: %s", s.createdGroupId)
err = waitUntilSecurityGroupExists(ec2conn,
&ec2.DescribeSecurityGroupsInput{
GroupIds: []*string{aws.String(s.createdGroupId)},
},
)
if err == nil {
log.Printf("[DEBUG] Found security group %s", s.createdGroupId)
} else {
err := fmt.Errorf("Timed out waiting for security group %s: %s", s.createdGroupId, err)
log.Printf("[DEBUG] %s", err.Error())
state.Put("error", err)
return multistep.ActionHalt
}
// Set some state data for use in future steps
state.Put("securityGroupIds", []string{s.createdGroupId})
@ -119,3 +135,38 @@ func (s *StepSecurityGroup) Cleanup(state multistep.StateBag) {
"Error cleaning up security group. Please delete the group manually: %s", s.createdGroupId))
}
}
func waitUntilSecurityGroupExists(c *ec2.EC2, input *ec2.DescribeSecurityGroupsInput) error {
waiterCfg := waiter.Config{
Operation: "DescribeSecurityGroups",
Delay: 15,
MaxAttempts: 40,
Acceptors: []waiter.WaitAcceptor{
{
State: "success",
Matcher: "path",
Argument: "length(SecurityGroups[]) > `0`",
Expected: true,
},
{
State: "retry",
Matcher: "error",
Argument: "",
Expected: "InvalidGroup.NotFound",
},
{
State: "retry",
Matcher: "error",
Argument: "",
Expected: "InvalidSecurityGroupID.NotFound",
},
},
}
w := waiter.Waiter{
Client: c,
Input: input,
Config: waiterCfg,
}
return w.Wait()
}