Merge branch 'master' of https://gitlab.federez.net/re2o/re2oapi
This commit is contained in:
commit
ffaed92103
1 changed files with 71 additions and 61 deletions
|
@ -35,23 +35,23 @@ class Re2oAPIClient:
|
|||
username: The username to use.
|
||||
password: The password to use.
|
||||
token_file: An optional path to the file where re2o tokens are
|
||||
stored. Used both for retrieving the token and saving it, so
|
||||
the file must be accessible for reading and writing. The
|
||||
default value is `None`, which indicated to use
|
||||
`$HOME/{DEFAULT_TOKEN_FILENAME}`.
|
||||
stored. Used both for retrieving the token and saving it, so
|
||||
the file must be accessible for reading and writing. The
|
||||
default value is `None`, which indicated to use
|
||||
`$HOME/{DEFAULT_TOKEN_FILENAME}`.
|
||||
use_tls: A boolean to indicate whether the client should us TLS
|
||||
(recommended for production). The default is `True`.
|
||||
(recommended for production). The default is `True`.
|
||||
log_level: Control the logging level to use. The default is
|
||||
`logging.CRITICAL+10`. So nothing is logged.
|
||||
`logging.CRITICAL+10`. So nothing is logged.
|
||||
|
||||
Raises:
|
||||
requests.exceptions.ConnectionError: Unable to resolve the
|
||||
provided hostname.
|
||||
provided hostname.
|
||||
requests.exceptions.HTTPError: The server used does not have a
|
||||
valid Re2o API.
|
||||
valid Re2o API.
|
||||
re2oapi.exceptions.InvalidCredentials: The credentials provided
|
||||
are not valid according to the Re2o server.
|
||||
""".format(DEFAULT_TOKEN_FILENAME=DEFAULT_TOKEN_FILENAME)
|
||||
are not valid according to the Re2o server.
|
||||
""".format(DEFAULT_TOKEN_FILENAME=DEFAULT_TOKEN_FILENAME)
|
||||
|
||||
# Enable logging
|
||||
self.log = logging.getLogger(__name__)
|
||||
|
@ -63,7 +63,7 @@ class Re2oAPIClient:
|
|||
)
|
||||
handler.setFormatter(formatter)
|
||||
self.log.addHandler(handler)
|
||||
self.log.setLevel(log_level)
|
||||
self.log.setLevel(log_level)
|
||||
|
||||
self.log.info("Starting new Re2o API client.")
|
||||
self.log.debug("hostname = " + str(hostname))
|
||||
|
@ -89,8 +89,8 @@ class Re2oAPIClient:
|
|||
|
||||
Returns:
|
||||
True is the token expiration time is within less than
|
||||
{TIME_FOR_RENEW} seconds.
|
||||
""".format(TIME_FOR_RENEW=TIME_FOR_RENEW)
|
||||
{TIME_FOR_RENEW} seconds.
|
||||
""".format(TIME_FOR_RENEW=TIME_FOR_RENEW)
|
||||
|
||||
return self.token['expiration'] < \
|
||||
datetime.datetime.now(datetime.timezone.utc) + \
|
||||
|
@ -133,7 +133,7 @@ class Re2oAPIClient:
|
|||
else:
|
||||
self.log.debug("Token successfully retrieved from token "
|
||||
"file '{}'.".format(self.token_file))
|
||||
return ret
|
||||
return ret
|
||||
|
||||
def _save_token_to_file(self):
|
||||
self.log.debug("Saving token to token file '{}'."
|
||||
|
@ -152,20 +152,20 @@ class Re2oAPIClient:
|
|||
# Insert the new token in the data (replace old token if it exists)
|
||||
if self.hostname not in data.keys():
|
||||
data[self.hostname] = {}
|
||||
data[self.hostname][self._username] = {
|
||||
'token': self.token['token'],
|
||||
'expiration': self.token['expiration'].isoformat()
|
||||
}
|
||||
data[self.hostname][self._username] = {
|
||||
'token': self.token['token'],
|
||||
'expiration': self.token['expiration'].isoformat()
|
||||
}
|
||||
|
||||
# Rewrite the token file and ensure only the user can read it
|
||||
# Fails silently if the file cannot be written.
|
||||
try:
|
||||
with self.token_file.open('w') as f:
|
||||
json.dump(data, f)
|
||||
self.token_file.chmod(stat.S_IWRITE | stat.S_IREAD)
|
||||
self.token_file.chmod(stat.S_IWRITE | stat.S_IREAD)
|
||||
except Exception:
|
||||
self.log.error("Token file '{}' could not be written. Passing."
|
||||
.format(self.token_file))
|
||||
.format(self.token_file))
|
||||
else:
|
||||
self.log.debug("Token sucessfully writen in token file '{}'."
|
||||
.format(self.token_file))
|
||||
|
@ -210,8 +210,8 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
re2oapi.exceptions.InvalidCredentials: The token needs to be
|
||||
renewed but the given credentials are not valid.
|
||||
"""
|
||||
renewed but the given credentials are not valid.
|
||||
"""
|
||||
if self.need_renew_token:
|
||||
# Renew the token only if needed
|
||||
self._force_renew_token()
|
||||
|
@ -222,6 +222,7 @@ class Re2oAPIClient:
|
|||
|
||||
# Update headers to force the 'Authorization' field with the right token
|
||||
self.log.debug("Forcing authentication token.")
|
||||
self.log.debug("Token =" + str(self.get_token()))
|
||||
headers.update({
|
||||
'Authorization': 'Token {}'.format(self.get_token())
|
||||
})
|
||||
|
@ -234,10 +235,19 @@ class Re2oAPIClient:
|
|||
# Perform the request
|
||||
self.log.info("Performing request {} {}".format(method.upper(), url))
|
||||
response = getattr(requests, method)(
|
||||
url, headers=headers, params=params, *args, **kwargs
|
||||
url, headers=headers, params=params,
|
||||
allow_redirects=False, *args, **kwargs
|
||||
)
|
||||
self.log.debug("Response code: "+str(response.status_code))
|
||||
|
||||
if response.is_redirect:
|
||||
self.log.debug("Redirection detected.")
|
||||
response = getattr(requests, method)(
|
||||
response.headers['Location'], headers=headers, params=params,
|
||||
allow_redirects=False, *args, **kwargs
|
||||
)
|
||||
self.log.debug("Response code after redirection: "+str(response.status_code))
|
||||
|
||||
if response.status_code == requests.codes.unauthorized:
|
||||
# Force re-login to the server (case of a wrong token but valid
|
||||
# credentials) and then retry the request without catching errors.
|
||||
|
@ -248,7 +258,7 @@ class Re2oAPIClient:
|
|||
'Authorization': 'Token {}'.format(self.get_token())
|
||||
})
|
||||
self.log.info("Re-performing the request {} {}"
|
||||
.format(method.upper(), url))
|
||||
.format(method.upper(), url))
|
||||
response = getattr(requests, method)(
|
||||
url, headers=headers, params=params, *args, **kwargs
|
||||
)
|
||||
|
@ -261,7 +271,7 @@ class Re2oAPIClient:
|
|||
response.raise_for_status()
|
||||
|
||||
ret = response.json()
|
||||
self.log.debug("Request {} {} successful.".format(method, url))
|
||||
self.log.debug("Request {} {} successful.".format(method, response.url))
|
||||
return ret
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
|
@ -281,10 +291,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('delete', *args, **kwargs)
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
|
@ -304,10 +314,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('get', *args, **kwargs)
|
||||
|
||||
def head(self, *args, **kwargs):
|
||||
|
@ -327,10 +337,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('get', *args, **kwargs)
|
||||
|
||||
def option(self, *args, **kwargs):
|
||||
|
@ -350,10 +360,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('get', *args, **kwargs)
|
||||
|
||||
def patch(self, *args, **kwargs):
|
||||
|
@ -373,10 +383,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('patch', *args, **kwargs)
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
|
@ -396,10 +406,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('post', *args, **kwargs)
|
||||
|
||||
def put(self, *args, **kwargs):
|
||||
|
@ -419,10 +429,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
return self._request('put', *args, **kwargs)
|
||||
|
||||
def get_url_for(self, endpoint):
|
||||
|
@ -431,15 +441,15 @@ class Re2oAPIClient:
|
|||
Args:
|
||||
endpoint: The path of the endpoint.
|
||||
**kwargs: A dictionnary with the parameter to use to build the
|
||||
URL (using .format() syntax)
|
||||
URL (using .format() syntax)
|
||||
|
||||
Returns:
|
||||
The full URL to use.
|
||||
|
||||
Raises:
|
||||
re2oapi.exception.NameNotExists: The provided name does not
|
||||
correspond to any endpoint.
|
||||
"""
|
||||
correspond to any endpoint.
|
||||
"""
|
||||
return '{proto}://{host}/{namespace}/{endpoint}'.format(
|
||||
proto=('https' if self.use_tls else 'http'),
|
||||
host=self.hostname,
|
||||
|
@ -461,12 +471,12 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting listing objects under '{}'"
|
||||
.format(endpoint))
|
||||
.format(endpoint))
|
||||
self.log.debug("max_results = "+str(max_results))
|
||||
|
||||
# For optimization, list all results in one page unless the user
|
||||
|
@ -484,7 +494,7 @@ class Re2oAPIClient:
|
|||
|
||||
# Get all next pages and append the results
|
||||
while response['next'] is not None and \
|
||||
(max_results is None or len(results) < max_results):
|
||||
(max_results is None or len(results) < max_results):
|
||||
response = self.get(response['next'])
|
||||
results += response['results']
|
||||
|
||||
|
@ -507,12 +517,12 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting counting objects under '{}'"
|
||||
.format(endpoint))
|
||||
.format(endpoint))
|
||||
|
||||
# For optimization, ask for only 1 result (so the server will take
|
||||
# less time to process the request) unless the user is forcing the
|
||||
|
@ -544,10 +554,10 @@ class Re2oAPIClient:
|
|||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
performing the request.
|
||||
performing the request.
|
||||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting viewing an object under '{}'"
|
||||
.format(endpoint))
|
||||
ret = self.get(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue