Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more generic error predicates #3116

Merged
merged 5 commits into from
Feb 13, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 56 additions & 6 deletions third_party/terraform/utils/error_retry_predicates.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package google

import (
"fmt"
"io"
"log"
"net"
"net/url"
"strings"

Expand All @@ -14,21 +16,69 @@ type RetryErrorPredicateFunc func(error) (bool, string)
/** ADD GLOBAL ERROR RETRY PREDICATES HERE **/
// Retry predicates that shoud apply to all requests should be added here.
var defaultErrorRetryPredicates = []RetryErrorPredicateFunc{
isUrlTimeoutError,
// Common network errors (usually wrapped by URL error)
isNetworkTemporaryError,
isNetworkTimeoutError,
isIoEOFError,
isConnectionResetNetworkError,

// Common GCP error codes
isCommonRetryableErrorCode,

//While this might apply only to Cloud SQL, historically,
// we had this in our global default error retries, so it is a default
// for now.
// we had this in our global default error retries.
// Keeping it as a default for now.
is409OperationInProgressError,
}

/** END GLOBAL ERROR RETRY PREDICATES HERE **/

func isUrlTimeoutError(err error) (bool, string) {
func isNetworkTemporaryError(err error) (bool, string) {
if netErr, ok := err.(*net.OpError); ok && netErr.Temporary() {
return true, "marked as timeout"
}
if urlerr, ok := err.(*url.Error); ok && urlerr.Temporary() {
return true, "marked as timeout"
}
return false, ""
}

func isNetworkTimeoutError(err error) (bool, string) {
if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
return true, "marked as timeout"
}
if urlerr, ok := err.(*url.Error); ok && urlerr.Timeout() {
log.Printf("[DEBUG] Dismissed an error as retryable based on googleapis.com target: %s", err)
return true, "Got URL timeout error"
return true, "marked as timeout"
}
return false, ""
}

func isIoEOFError(err error) (bool, string) {
if err == io.ErrUnexpectedEOF {
return true, "Got unexpected EOF"
}

if urlerr, urlok := err.(*url.Error); urlok {
wrappedErr := urlerr.Unwrap()
if wrappedErr == io.ErrUnexpectedEOF {
return true, "Got unexpected EOF"
}
}
return false, ""
}

const connectionResetByPeerErr = "connection reset by peer"

func isConnectionResetNetworkError(err error) (bool, string) {
neterr, ok := err.(*net.OpError)
if !ok {
if urlerr, urlok := err.(*url.Error); urlok {
wrappedErr := urlerr.Unwrap()
neterr, ok = wrappedErr.(*net.OpError)
}
}
if ok && neterr.Err.Error() == connectionResetByPeerErr {
return true, fmt.Sprintf("Connection reset by peer")
}
return false, ""
}
Expand Down