From 6fb2586fb2572a91f986343036ed945b5952ed65 Mon Sep 17 00:00:00 2001 From: Matt Page Date: Mon, 13 Oct 2014 09:22:33 -0700 Subject: [PATCH] fix: Ignore transient network errors when fetching AWS state. Given that state fetching is an idempotent operation, a transient network error should not cause the entire build to fail. Instead, retry when such errors are encountered. --- builder/amazon/common/state.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/builder/amazon/common/state.go b/builder/amazon/common/state.go index 4f7d4b11d..32115b66b 100644 --- a/builder/amazon/common/state.go +++ b/builder/amazon/common/state.go @@ -6,6 +6,7 @@ import ( "github.com/mitchellh/goamz/ec2" "github.com/mitchellh/multistep" "log" + "net" "time" ) @@ -29,6 +30,14 @@ type StateChangeConf struct { Target string } +func isTransientNetworkError(err error) bool { + ret := false + if nerr, ok := err.(net.Error); ok && nerr.Temporary() { + ret = true + } + return ret +} + // AMIStateRefreshFunc returns a StateRefreshFunc that is used to watch // an AMI for state changes. func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc { @@ -38,6 +47,9 @@ func AMIStateRefreshFunc(conn *ec2.EC2, imageId string) StateRefreshFunc { if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidAMIID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil + } else if isTransientNetworkError(err) { + // Transient network error, treat it as if we didn't find anything + resp = nil } else { log.Printf("Error on AMIStateRefresh: %s", err) return nil, "", err @@ -64,6 +76,9 @@ func InstanceStateRefreshFunc(conn *ec2.EC2, i *ec2.Instance) StateRefreshFunc { if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidInstanceID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil + } else if isTransientNetworkError(err) { + // Transient network error, treat it as if we didn't find anything + resp = nil } else { log.Printf("Error on InstanceStateRefresh: %s", err) return nil, "", err @@ -90,6 +105,9 @@ func SpotRequestStateRefreshFunc(conn *ec2.EC2, spotRequestId string) StateRefre if ec2err, ok := err.(*ec2.Error); ok && ec2err.Code == "InvalidSpotInstanceRequestID.NotFound" { // Set this to nil as if we didn't find anything. resp = nil + } else if isTransientNetworkError(err) { + // Transient network error, treat it as if we didn't find anything + resp = nil } else { log.Printf("Error on SpotRequestStateRefresh: %s", err) return nil, "", err