From b265d2614f7ee7a1000558af7ba3f0e6f0f66dfd Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Wed, 18 Jan 2017 15:11:52 -0800 Subject: [PATCH] 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. --- .../amazon/common/step_run_source_instance.go | 61 +------------------ builder/amazon/common/step_security_group.go | 51 ++++++++++++++++ 2 files changed, 54 insertions(+), 58 deletions(-) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index 649ddfdec..a26144270 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -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() -} diff --git a/builder/amazon/common/step_security_group.go b/builder/amazon/common/step_security_group.go index 43b9fd4c7..4900b1117 100644 --- a/builder/amazon/common/step_security_group.go +++ b/builder/amazon/common/step_security_group.go @@ -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() +}