diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d48aabf3..db2bb9941 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ BUG FIXES: * builder/vmware: Wait some time so that post-VMX update aren't overwritten. [GH-1504] * 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: Rely on Cleanup functions to detach devices [GH-1502] * builder/parallels: Create VM without hdd and then add it later [GH-1548] diff --git a/builder/amazon/common/state.go b/builder/amazon/common/state.go index fe6f7ca62..aead0161b 100644 --- a/builder/amazon/common/state.go +++ b/builder/amazon/common/state.go @@ -7,6 +7,8 @@ import ( "github.com/mitchellh/multistep" "log" "net" + "os" + "strconv" "time" ) @@ -122,6 +124,8 @@ func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefre func WaitForState(conf *StateChangeConf) (i interface{}, err error) { log.Printf("Waiting for state to become: %s", conf.Target) + sleepSeconds := 2 + maxTicks := int(TimeoutSeconds() / sleepSeconds) + 1 notfoundTick := 0 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 // not finding it for awhile, and if so, report an error. notfoundTick += 1 - if notfoundTick > 20 { + if notfoundTick > maxTicks { return nil, errors.New("couldn't find resource") } } 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 @@ -179,3 +183,23 @@ func isTransientNetworkError(err error) bool { 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 +}