X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/27b9247e0c42700e0c7d94f7721e2164610b1e4c..305cee61ba4a122f7d63a01f4a7b9b98737b8646:/sdk/go/arvadosclient/arvadosclient.go diff --git a/sdk/go/arvadosclient/arvadosclient.go b/sdk/go/arvadosclient/arvadosclient.go index 68c0632a30..aeb81f9317 100644 --- a/sdk/go/arvadosclient/arvadosclient.go +++ b/sdk/go/arvadosclient/arvadosclient.go @@ -86,6 +86,12 @@ type ArvadosClient struct { // the client is outside the cluster. External bool + // Base URIs of Keep services, e.g., {"https://host1:8443", + // "https://host2:8443"}. If this is nil, Keep clients will + // use the arvados.v1.keep_services.accessible API to discover + // available services. + KeepServiceURIs []string + // Discovery document DiscoveryDoc Dict @@ -95,9 +101,10 @@ type ArvadosClient struct { Retries int } -// Create a new ArvadosClient, initialized with standard Arvados environment -// variables ARVADOS_API_HOST, ARVADOS_API_TOKEN, and (optionally) -// ARVADOS_API_HOST_INSECURE. +// MakeArvadosClient creates a new ArvadosClient using the standard +// environment variables ARVADOS_API_HOST, ARVADOS_API_TOKEN, +// ARVADOS_API_HOST_INSECURE, ARVADOS_EXTERNAL_CLIENT, and +// ARVADOS_KEEP_SERVICES. func MakeArvadosClient() (ac ArvadosClient, err error) { var matchTrue = regexp.MustCompile("^(?i:1|yes|true)$") insecure := matchTrue.MatchString(os.Getenv("ARVADOS_API_HOST_INSECURE")) @@ -113,6 +120,18 @@ func MakeArvadosClient() (ac ArvadosClient, err error) { External: external, Retries: 2} + for _, s := range strings.Split(os.Getenv("ARVADOS_KEEP_SERVICES"), " ") { + if s == "" { + continue + } + if u, err := url.Parse(s); err != nil { + return ac, fmt.Errorf("ARVADOS_KEEP_SERVICES: %q: %s", s, err) + } else if !u.IsAbs() { + return ac, fmt.Errorf("ARVADOS_KEEP_SERVICES: %q: not an absolute URI", s) + } + ac.KeepServiceURIs = append(ac.KeepServiceURIs, s) + } + if ac.ApiServer == "" { return ac, MissingArvadosApiHost } @@ -165,13 +184,13 @@ func (c ArvadosClient) CallRaw(method string, resourceType string, uuid string, retryable := false switch method { - case "GET", "HEAD", "PUT", "OPTIONS", "POST", "DELETE": + case "GET", "HEAD", "PUT", "OPTIONS", "DELETE": retryable = true } - // POST and DELETE are not safe to retry automatically, so we minimize - // such failures by always using a new or recently active socket - if method == "POST" || method == "DELETE" { + // Non-retryable methods such as POST are not safe to retry automatically, + // so we minimize such failures by always using a new or recently active socket + if !retryable { if time.Since(c.lastClosedIdlesAt) > MaxIdleConnectionDuration { c.lastClosedIdlesAt = time.Now() c.Client.Transport.(*http.Transport).CloseIdleConnections() @@ -228,9 +247,8 @@ func (c ArvadosClient) CallRaw(method string, resourceType string, uuid string, if resp != nil { return nil, newAPIServerError(c.ApiServer, resp) - } else { - return nil, err } + return nil, err } func newAPIServerError(ServerAddress string, resp *http.Response) APIServerError { @@ -274,7 +292,7 @@ func newAPIServerError(ServerAddress string, resp *http.Response) APIServerError // Returns a non-nil error if an error occurs making the API call, the // API responds with a non-successful HTTP status, or an error occurs // parsing the response body. -func (c ArvadosClient) Call(method string, resourceType string, uuid string, action string, parameters Dict, output interface{}) error { +func (c ArvadosClient) Call(method, resourceType, uuid, action string, parameters Dict, output interface{}) error { reader, err := c.CallRaw(method, resourceType, uuid, action, parameters) if reader != nil { defer reader.Close()