Merge pull request #3938 from mitchellh/retrycreatetags

builder/amazon: add retry login when creating tags.
This commit is contained in:
Matthew Hooker 2016-09-29 12:14:57 -07:00 committed by GitHub
commit e14bce7f9f
5 changed files with 34 additions and 17 deletions

View File

@ -4,9 +4,11 @@ import (
"fmt" "fmt"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
retry "github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
) )
@ -71,9 +73,22 @@ func (s *StepCreateTags) Run(state multistep.StateBag) multistep.StepAction {
} }
} }
_, err = regionconn.CreateTags(&ec2.CreateTagsInput{ // Retry creating tags for about 2.5 minutes
Resources: resourceIds, err = retry.Retry(0.2, 30, 11, func() (bool, error) {
Tags: ec2Tags, _, err := regionconn.CreateTags(&ec2.CreateTagsInput{
Resources: resourceIds,
Tags: ec2Tags,
})
if err == nil {
return true, nil
}
if awsErr, ok := err.(awserr.Error); ok {
if awsErr.Code() == "InvalidAMIID.NotFound" ||
awsErr.Code() == "InvalidSnapshot.NotFound" {
return false, nil
}
}
return true, err
}) })
if err != nil { if err != nil {

View File

@ -7,6 +7,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"github.com/mitchellh/packer/version" "github.com/mitchellh/packer/version"
@ -458,7 +459,7 @@ type stateRefreshFunc func() (string, error)
// waitForState will spin in a loop forever waiting for state to // waitForState will spin in a loop forever waiting for state to
// reach a certain target. // reach a certain target.
func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) error { func waitForState(errCh chan<- error, target string, refresh stateRefreshFunc) error {
err := Retry(2, 2, 0, func() (bool, error) { err := common.Retry(2, 2, 0, func() (bool, error) {
state, err := refresh() state, err := refresh()
if err != nil { if err != nil {
return false, err return false, err

View File

@ -1,10 +1,11 @@
package googlecompute package googlecompute
import( import (
"errors" "errors"
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
) )
@ -17,11 +18,11 @@ func (s *StepWaitInstanceStartup) Run(state multistep.StateBag) multistep.StepAc
driver := state.Get("driver").(Driver) driver := state.Get("driver").(Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
instanceName := state.Get("instance_name").(string) instanceName := state.Get("instance_name").(string)
ui.Say("Waiting for any running startup script to finish...") ui.Say("Waiting for any running startup script to finish...")
// Keep checking the serial port output to see if the startup script is done. // Keep checking the serial port output to see if the startup script is done.
err := Retry(10, 60, 0, func() (bool, error) { err := common.Retry(10, 60, 0, func() (bool, error) {
status, err := driver.GetInstanceMetadata(config.Zone, status, err := driver.GetInstanceMetadata(config.Zone,
instanceName, StartupScriptStatusKey) instanceName, StartupScriptStatusKey)

View File

@ -1,4 +1,4 @@
package googlecompute package common
import ( import (
"fmt" "fmt"
@ -25,20 +25,20 @@ func Retry(initialInterval float64, maxInterval float64, numTries uint, function
done := false done := false
interval := initialInterval interval := initialInterval
for i := uint(0); !done && (numTries == 0 || i < numTries); i++ { for i := uint(0); !done && (numTries == 0 || i < numTries); i++ {
done, err = function() done, err = function()
if err != nil { if err != nil {
return err return err
} }
if !done { if !done {
// Retry after delay. Calculate next delay. // Retry after delay. Calculate next delay.
time.Sleep(time.Duration(interval) * time.Second) time.Sleep(time.Duration(interval) * time.Second)
interval = math.Min(interval * 2, maxInterval) interval = math.Min(interval*2, maxInterval)
} }
} }
if !done { if !done {
return RetryExhaustedError return RetryExhaustedError
} }
return nil return nil
} }

View File

@ -1,4 +1,4 @@
package googlecompute package common
import ( import (
"fmt" "fmt"
@ -18,7 +18,7 @@ func TestRetry(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Passing function should not have returned a retry error. Error: %s", err) t.Fatalf("Passing function should not have returned a retry error. Error: %s", err)
} }
// Test that a failing function gets retried (once in this example). // Test that a failing function gets retried (once in this example).
numTries = 0 numTries = 0
results := []bool{false, true} results := []bool{false, true}
@ -33,7 +33,7 @@ func TestRetry(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Successful retried function should not have returned a retry error. Error: %s", err) t.Fatalf("Successful retried function should not have returned a retry error. Error: %s", err)
} }
// Test that a function error gets returned, and the function does not get called again. // Test that a function error gets returned, and the function does not get called again.
numTries = 0 numTries = 0
funcErr := fmt.Errorf("This function had an error!") funcErr := fmt.Errorf("This function had an error!")
@ -47,7 +47,7 @@ func TestRetry(t *testing.T) {
if err != funcErr { if err != funcErr {
t.Fatalf("Errant function did not return the right error %s. Error: %s", funcErr, err) t.Fatalf("Errant function did not return the right error %s. Error: %s", funcErr, err)
} }
// Test when a function exhausts its retries. // Test when a function exhausts its retries.
numTries = 0 numTries = 0
expectedTries := uint(3) expectedTries := uint(3)
@ -61,4 +61,4 @@ func TestRetry(t *testing.T) {
if err != RetryExhaustedError { if err != RetryExhaustedError {
t.Fatalf("Unsuccessful retry function should have returned a retry exhausted error. Actual error: %s", err) t.Fatalf("Unsuccessful retry function should have returned a retry exhausted error. Actual error: %s", err)
} }
} }