builder/amazon: Extend timeout and allow user override [GH-1533]

- help resolve https://github.com/mitchellh/packer/issues/1533
  (although timeouts are always ultimately useless in a distributed
  system!)
- makes packer no more idempotent or janitorial than before
- derive maximum number of ticks from timeout
- default timeout to 300s (5m) to cater for global AMI copying
- allow user to override with AWS_TIMEOUT_SECONDS environment variable
This commit is contained in:
Josh Graham 2014-09-30 11:14:52 +10:00 committed by Josh Graham
parent 5c74cfff54
commit 5a2c4fe8a0
2 changed files with 27 additions and 2 deletions

View File

@ -11,6 +11,7 @@ BUG FIXES:
* builder/vmware: Wait some time so that post-VMX update aren't * builder/vmware: Wait some time so that post-VMX update aren't
overwritten. [GH-1504] overwritten. [GH-1504]
* builder/vmware-vmx: Fix issue with order of boot command support [GH-1492] * builder/vmware-vmx: Fix issue with order of boot command support [GH-1492]
* builder/amazon: Extend timeout and allow user override [GH-1533]
* builder/parallels: Ignore 'The fdd0 device does not exist' [GH-1501] * builder/parallels: Ignore 'The fdd0 device does not exist' [GH-1501]
* builder/parallels: Rely on Cleanup functions to detach devices [GH-1502] * builder/parallels: Rely on Cleanup functions to detach devices [GH-1502]
* builder/parallels: Create VM without hdd and then add it later [GH-1548] * builder/parallels: Create VM without hdd and then add it later [GH-1548]

View File

@ -7,6 +7,8 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
"log" "log"
"net" "net"
"os"
"strconv"
"time" "time"
) )
@ -122,6 +124,8 @@ func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefre
func WaitForState(conf *StateChangeConf) (i interface{}, err error) { func WaitForState(conf *StateChangeConf) (i interface{}, err error) {
log.Printf("Waiting for state to become: %s", conf.Target) log.Printf("Waiting for state to become: %s", conf.Target)
sleepSeconds := 2
maxTicks := int(TimeoutSeconds() / sleepSeconds) + 1
notfoundTick := 0 notfoundTick := 0
for { for {
@ -135,7 +139,7 @@ func WaitForState(conf *StateChangeConf) (i interface{}, err error) {
// If we didn't find the resource, check if we have been // If we didn't find the resource, check if we have been
// not finding it for awhile, and if so, report an error. // not finding it for awhile, and if so, report an error.
notfoundTick += 1 notfoundTick += 1
if notfoundTick > 20 { if notfoundTick > maxTicks {
return nil, errors.New("couldn't find resource") return nil, errors.New("couldn't find resource")
} }
} else { } else {
@ -166,7 +170,7 @@ func WaitForState(conf *StateChangeConf) (i interface{}, err error) {
} }
} }
time.Sleep(2 * time.Second) time.Sleep(time.Duration(sleepSeconds) * time.Second)
} }
return return
@ -179,3 +183,23 @@ func isTransientNetworkError(err error) bool {
return false return false
} }
// Returns 300 seconds (5 minutes) by default
// Some AWS operations, like copying an AMI to a distant region, take a very long time
// Allow user to override with AWS_TIMEOUT_SECONDS environment variable
func TimeoutSeconds() (seconds int) {
seconds = 300
override := os.Getenv("AWS_TIMEOUT_SECONDS")
if override != "" {
n, err := strconv.Atoi(override)
if err != nil {
log.Printf("Invalid timeout seconds '%s', using default", override)
} else {
seconds = n
}
}
log.Printf("Allowing %ds to complete (change with AWS_TIMEOUT_SECONDS)", seconds)
return seconds
}