| Index: appengine/swarming/swarming_bot/bot_code/remote_client.py
|
| diff --git a/appengine/swarming/swarming_bot/bot_code/remote_client.py b/appengine/swarming/swarming_bot/bot_code/remote_client.py
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7041aae9e3bee5c57beea59a55c387fc36cfffc2
|
| --- /dev/null
|
| +++ b/appengine/swarming/swarming_bot/bot_code/remote_client.py
|
| @@ -0,0 +1,81 @@
|
| +# Copyright 2016 The LUCI Authors. All rights reserved.
|
| +# Use of this source code is governed under the Apache License, Version 2.0
|
| +# that can be found in the LICENSE file.
|
| +
|
| +import threading
|
| +
|
| +from utils import net
|
| +
|
| +
|
| +# RemoteClient will attempt to refresh the authentication headers once they are
|
| +# this close to the expiration.
|
| +AUTH_HEADERS_EXPIRATION_SEC = 6*60
|
| +
|
| +
|
| +class InitializationError(Exception):
|
| + """Raised by RemoteClient.initialize on fatal errors."""
|
| + def __init__(self, last_error):
|
| + super(InitializationError, self).__init__('Failed to grab auth headers')
|
| + self.last_error = last_error
|
| +
|
| +
|
| +class RemoteClient(object):
|
| + """RemoteClient knows how to make authenticated calls to the backend.
|
| +
|
| + It also holds in-memory cache of authentication headers and periodically
|
| + refreshes them (by calling supplied callback, that usually is implemented in
|
| + terms of bot_config.get_authentication_headers() function).
|
| +
|
| + If the callback is None, skips authentication (this is used during initial
|
| + stages of the bot bootstrap).
|
| + """
|
| +
|
| + def __init__(self, server, auth_headers_callback):
|
| + self._server = server
|
| + self._auth_headers_callback = auth_headers_callback
|
| + self._uses_auth = False
|
| + self._lock = threading.Lock()
|
| +
|
| + def initialize(self, quit_bit):
|
| + """Grabs initial auth headers, retrying on errors a bunch of times.
|
| +
|
| + Raises InitializationError if all attempts fail. Aborts attempts and returns
|
| + if quit_bit is set to signaled state.
|
| + """
|
| + # TODO(vadimsh): Implement.
|
| +
|
| + @property
|
| + def uses_auth(self):
|
| + """Returns True if get_authentication_headers() returns some headers.
|
| +
|
| + If bot_config.get_authentication_headers() is not implement it will return
|
| + False.
|
| + """
|
| + return self._uses_auth
|
| +
|
| + def get_authentication_headers(self):
|
| + """Returns a dict with the headers, refreshing them if necessary.
|
| +
|
| + Will always return a dict (perhaps empty if no auth headers are provided by
|
| + the callback).
|
| + """
|
| + with self._lock:
|
| + # TODO(vadimsh): Implement.
|
| + return {}
|
| +
|
| + def url_read_json(self, url_path, data=None):
|
| + """Does POST (if data is not None) or GET request to a JSON endpoint."""
|
| + return net.url_read_json(
|
| + self._server + url_path,
|
| + data=data,
|
| + headers=self.get_authentication_headers(),
|
| + timeout=AUTH_HEADERS_EXPIRATION_SEC,
|
| + follow_redirects=False)
|
| +
|
| + def url_retrieve(self, filepath, url_path):
|
| + """Fetches the file from the given URL path on the server."""
|
| + return net.url_retrieve(
|
| + filepath,
|
| + self._server + url_path,
|
| + headers=self.get_authentication_headers(),
|
| + timeout=AUTH_HEADERS_EXPIRATION_SEC)
|
|
|