Do not use endpoint's names
Use the URL structure directly to build the requests directly The mapping name <-> endpoint is no longer used See discusion in #1 for details
This commit is contained in:
parent
2deb99c51c
commit
c3277c2e6e
3 changed files with 39 additions and 215 deletions
|
@ -174,7 +174,7 @@ class Re2oAPIClient:
|
|||
|
||||
# Perform the authentication request
|
||||
response = requests.post(
|
||||
self.get_url_for('token'),
|
||||
self.get_url_for('token-auth'),
|
||||
data={'username': self._username, 'password': self._password}
|
||||
)
|
||||
self.log.debug("Response code: "+str(response.status_code))
|
||||
|
@ -423,11 +423,11 @@ class Re2oAPIClient:
|
|||
"""
|
||||
return self._request('put', *args, **kwargs)
|
||||
|
||||
def get_url_for(self, name, **kwargs):
|
||||
def get_url_for(self, endpoint):
|
||||
"""Retrieve the complete URL to use for a given endpoint's name.
|
||||
|
||||
Args:
|
||||
name: The name of the endpoint to look for.
|
||||
endpoint: The path of the endpoint.
|
||||
**kwargs: A dictionnary with the parameter to use to build the
|
||||
URL (using .format() syntax)
|
||||
|
||||
|
@ -438,23 +438,24 @@ class Re2oAPIClient:
|
|||
re2oapi.exception.NameNotExists: The provided name does not
|
||||
correspond to any endpoint.
|
||||
"""
|
||||
return '{proto}://{host}{endpoint}'.format(
|
||||
return '{proto}://{host}/{namespace}/{endpoint}'.format(
|
||||
proto=('https' if self.use_tls else 'http'),
|
||||
host=self.hostname,
|
||||
endpoint=endpoints.get_endpoint_for(name, self.log, **kwargs)
|
||||
namespace='api',
|
||||
endpoint=endpoint
|
||||
)
|
||||
|
||||
def _list_for(self, obj_name, max_results=None, params={}, **kwargs):
|
||||
"""List all '{obj_name}' objects on the server.
|
||||
def list(self, endpoint, max_results=None, params={}):
|
||||
"""List all objects on the server that corresponds to the given
|
||||
endpoint. The endpoint must be valid for listing objects.
|
||||
|
||||
Args:
|
||||
endpoint: The path of the endpoint.
|
||||
max_results: A limit on the number of result to return
|
||||
params: See `requests.get` params.
|
||||
**kwargs: A dictionnary used to defines the required parameters
|
||||
in order to build the URL (using `.format()`).
|
||||
|
||||
Returns:
|
||||
The list of all the {obj_name} objects serialized
|
||||
as returned by the API.
|
||||
The list of all the objects serialized as returned by the API.
|
||||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
|
@ -462,18 +463,19 @@ class Re2oAPIClient:
|
|||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting listing {} objects".format(obj_name))
|
||||
self.log.info("Starting listing objects under '{}'"
|
||||
.format(endpoint))
|
||||
self.log.debug("max_results = "+str(max_results))
|
||||
|
||||
# For optimization, list all results in one page unless the user
|
||||
# is forcing the use of a different `page_size`.
|
||||
if not 'page_size' in params.keys():
|
||||
self.log.debug("Forcing 'page_size' parameter to 'all'.")
|
||||
params['page_size'] = 'all'
|
||||
params['page_size'] = max_results or 'all'
|
||||
|
||||
# Performs the request for the first page
|
||||
response = self.get(
|
||||
self.get_url_for('%s-list' % obj_name, **kwargs),
|
||||
self.get_url_for(endpoint),
|
||||
params=params
|
||||
)
|
||||
results = response['results']
|
||||
|
@ -486,20 +488,20 @@ class Re2oAPIClient:
|
|||
|
||||
# Returns the exact number of results if applicable
|
||||
ret = results[:max_results] if max_results else results
|
||||
self.log.debug("Listing {} objects successful".format(obj_name))
|
||||
self.log.debug("Listing objects under '{}' successful"
|
||||
.format(endpoint))
|
||||
return ret
|
||||
|
||||
def _count_for(self, obj_name, params={}, **kwargs):
|
||||
"""Count all '{obj_name}' objects on the server:
|
||||
def count(self, endpoint, params={}):
|
||||
"""Count all objects on the server that corresponds to the given
|
||||
endpoint. The endpoint must be valid for listing objects.
|
||||
|
||||
Args:
|
||||
endpoint: The path of the endpoint.
|
||||
params: See `requests.get` params.
|
||||
**kwargs: A dictionnary used to defines the required parameters
|
||||
in order to build the URL (using `.format()`).
|
||||
|
||||
Returns:
|
||||
The number of {obj_name} objects on the server as returned by the
|
||||
API.
|
||||
The number of objects on the server as returned by the API.
|
||||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
|
@ -507,9 +509,10 @@ class Re2oAPIClient:
|
|||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting counting {} objects".format(obj_name))
|
||||
self.log.info("Starting counting objects under '{}'"
|
||||
.format(endpoint))
|
||||
|
||||
# For optimization, ask fo only 1 result (so the server will take
|
||||
# For optimization, ask for only 1 result (so the server will take
|
||||
# less time to process the request) unless the user is forcing the
|
||||
# use of a different `page_size`.
|
||||
if not 'page_size' in params.keys():
|
||||
|
@ -518,24 +521,24 @@ class Re2oAPIClient:
|
|||
|
||||
# Performs the request and return the `count` value in the response.
|
||||
ret = self.get(
|
||||
self.get_url_for('%s-list' % obj_name, **kwargs),
|
||||
self.get_url_for(endpoint),
|
||||
params=params
|
||||
)['count']
|
||||
|
||||
self.log.debug("Counting {} objects successful".format(obj_name))
|
||||
self.log.debug("Counting objects under '{}' successful"
|
||||
.format(endpoint))
|
||||
return ret
|
||||
|
||||
def _view_for(self, obj_name, params={}, **kwargs):
|
||||
"""Retrieved the details of a '{obj_name}' object from the server.
|
||||
def view(self, endpoint, params={}):
|
||||
"""Retrieved the details of an object from the server that corresponds
|
||||
to the given endpoint.
|
||||
|
||||
Args:
|
||||
endpoint: The path of the endpoint.
|
||||
params: See `requests.get` params.
|
||||
**kwargs: A dictionnary used to defines the required parameters
|
||||
in order to build the URL (using `.format()`).
|
||||
|
||||
Returns:
|
||||
The serialized data of the queried {obj_name} object as returned
|
||||
by the API.
|
||||
The serialized data of the queried object as returned by the API.
|
||||
|
||||
Raises:
|
||||
requests.exceptions.RequestException: An error occured while
|
||||
|
@ -543,53 +546,13 @@ class Re2oAPIClient:
|
|||
exceptions.PermissionDenied: The user does not have the right
|
||||
to perform this request.
|
||||
"""
|
||||
self.log.info("Starting viewing a {} object".format(obj_name))
|
||||
self.log.info("Starting viewing an object under '{}'"
|
||||
.format(endpoint))
|
||||
ret = self.get(
|
||||
self.get_url_for('%s-detail' % obj_name, **kwargs),
|
||||
self.get_url_for(endpoint),
|
||||
params=params
|
||||
)
|
||||
|
||||
self.log.debug("Viewing {} object successful".format(obj_name))
|
||||
self.log.debug("Viewing object under '{}' successful"
|
||||
.format(endpoint))
|
||||
return ret
|
||||
|
||||
def __getattr__(self, item):
|
||||
|
||||
if item.startswith('list_'):
|
||||
obj_name = item[len('list_'):]
|
||||
def f(*args, **kwargs):
|
||||
return self._list_for(obj_name, *args, **kwargs)
|
||||
f.__doc__ = self._list_for.__doc__.format(obj_name=obj_name)
|
||||
f.__name__ = "list_"+obj_name
|
||||
return f
|
||||
|
||||
elif item.startswith('count_'):
|
||||
obj_name = item[len('count_'):]
|
||||
def f(*args, **kwargs):
|
||||
return self._count_for(obj_name, *args, **kwargs)
|
||||
f.__doc__ = self._count_for.__doc__.format(obj_name=obj_name)
|
||||
f.__name__ = "count_"+obj_name
|
||||
return f
|
||||
|
||||
elif item.startswith('view_'):
|
||||
obj_name = item[len('view_'):]
|
||||
def f(*args, **kwargs):
|
||||
return self._view_for(obj_name, *args, **kwargs)
|
||||
f.__doc__ = self._view_for.__doc__.format(obj_name=obj_name)
|
||||
f.__name__ = "view_"+obj_name
|
||||
return f
|
||||
|
||||
else:
|
||||
raise AttributeError(item)
|
||||
|
||||
def __dir__(self):
|
||||
ret = ['use_tls', 'token_file', 'hostname', 'token',
|
||||
'need_renew_token', 'get_token', 'delete', 'get', 'patch',
|
||||
'post', 'put', 'get_url_for']
|
||||
for name in endpoints.get_names():
|
||||
if name.endswith('-list'):
|
||||
ret.append('list_%s' % name[:-len('-list')])
|
||||
ret.append('count_%s' % name[:-len('-list')])
|
||||
elif name.endswith('-detail'):
|
||||
ret.append('view_%s' % name[:-len('-detail')])
|
||||
return ret
|
||||
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
from . import exceptions
|
||||
|
||||
urls = {
|
||||
'root': '/api/',
|
||||
'article-list': '/api/cotisations/article/',
|
||||
'article-detail': '/api/cotisations/article/{pk}/',
|
||||
'banque-list': '/api/cotisations/banque/',
|
||||
'banque-detail': '/api/cotisations/banque/{pk}/',
|
||||
'cotisation-list': '/api/cotisations/cotisation/',
|
||||
'cotisation-detail': '/api/cotisations/cotisation/{pk}/',
|
||||
'facture-list': '/api/cotisations/facture/',
|
||||
'facture-detail': '/api/cotisations/facture/{pk}/',
|
||||
'paiment-list': '/api/cotisations/paiement/',
|
||||
'paiement-detail': '/api/cotisations/paiement/{pk}/',
|
||||
'vente-list': '/api/cotisations/vente/',
|
||||
'vente-detail': '/api/cotisations/vente/{pk}/',
|
||||
'domain-list': '/api/machines/domain/',
|
||||
'domain-detail': '/api/machines/domain/{pk}/',
|
||||
'extension-list': '/api/machines/extension/',
|
||||
'extension-detail': '/api/machines/extension/{pk}/',
|
||||
'interface-list': '/api/machines/interface/',
|
||||
'interface-detail': '/api/machines/interface/{pk}/',
|
||||
'iplist-list': '/api/machines/iplist/',
|
||||
'iplist-detail': '/api/machines/iplist/{pk}/',
|
||||
'iptype-list': '/api/machines/iptype/',
|
||||
'iptype-detail': '/api/machines/iptype/{pk}/',
|
||||
'ipv6list-list': '/api/machines/ipv6list/',
|
||||
'ipv6list-detail': '/api/machines/ipv6list/{pk}/',
|
||||
'machine-list': '/api/machines/machine/',
|
||||
'machine-detail': '/api/machines/machine/{pk}/',
|
||||
'machinetype-list': '/api/machines/machinetype/',
|
||||
'machinetype-detail': '/api/machines/machinetype/{pk}/',
|
||||
'mx-list': '/api/machines/mx/',
|
||||
'mx-detail': '/api/machines/mx/{pk}/',
|
||||
'nas-list': '/api/machines/nas/',
|
||||
'nas-detail': '/api/machines/nas/{pk}/',
|
||||
'ns-list': '/api/machines/ns/',
|
||||
'ns-detail': '/api/machines/ns/{pk}/',
|
||||
'ouvertureportlist-list': '/api/machines/ouvertureportlist/',
|
||||
'ouvertureportlist-detail': '/api/machines/ouvertureportlist/{pk}/',
|
||||
'ouvertureport-list': '/api/machines/ouvertureport/',
|
||||
'ouvertureport-detail': '/api/machines/ouvertureport/{pk}/',
|
||||
'servicelink-list': '/api/machines/servicelink/',
|
||||
'servicelink-detail': '/api/machines/servicelink/{pk}/',
|
||||
'service-list': '/api/machines/service/',
|
||||
'service-detail': '/api/machines/service/{pk}/',
|
||||
'soa-list': '/api/machines/soa/',
|
||||
'soa-detail': '/api/machines/soa/{pk}/',
|
||||
'srv-list': '/api/machines/srv/',
|
||||
'srv-detail': '/api/machines/srv/{pk}/',
|
||||
'txt-list': '/api/machines/txt/',
|
||||
'txt-detail': '/api/machines/txt/{pk}/',
|
||||
'vlan-list': '/api/machines/vlan/',
|
||||
'vlan-detail': '/api/machines/vlan/{pk}/',
|
||||
'optionaluser-detail': '/api/preferences/optionaluser/',
|
||||
'optionalmachine-detail': '/api/preferences/optionalmachine/',
|
||||
'optionaltopologie-detail': '/api/preferences/optionaltopologie/',
|
||||
'generaloption-detail': '/api/preferences/generaloption/',
|
||||
'homeservice-list': '/api/preferences/service/',
|
||||
'homeservice-detail': '/api/preferences/service/{pk}/',
|
||||
'assooption-detail': '/api/preferences/assooption/',
|
||||
'homeoption-detail': '/api/preferences/homeoption/',
|
||||
'mailmessageoption-detail': '/api/preferences/mailmessageoption/',
|
||||
'accesspoint-list': '/api/topologie/acesspoint/',
|
||||
'accesspoint-detail': '/api/topologie/acesspoint/{pk}/',
|
||||
'building-list': '/api/topologie/building/',
|
||||
'building-detail': '/api/topologie/building/{pk}/',
|
||||
'constructorswitch-list': '/api/topologie/constructorswitch/',
|
||||
'constructorswitch-detail': '/api/topologie/constructorswitch/{pk}/',
|
||||
'modelswitch-list': '/api/topologie/modelswitch/',
|
||||
'modelswitch-detail': '/api/topologie/modelswitch/{pk}/',
|
||||
'room-list': '/api/topologie/room/',
|
||||
'room-detail': '/api/topologie/room/{pk}/',
|
||||
'server-list': '/api/topologie/server/',
|
||||
'server-detail': '/api/topologie/server/{pk}/',
|
||||
'stack-list': '/api/topologie/stack/',
|
||||
'stack-detail': '/api/topologie/stack/{pk}/',
|
||||
'switch-list': '/api/topologie/switch/',
|
||||
'switch-detail': '/api/topologie/switch/{pk}/',
|
||||
'switchbay-list': '/api/topologie/switchbay/',
|
||||
'switchbay-detail': '/api/topologie/switchbay/{pk}/',
|
||||
'switchport-list': '/api/topologie/switchport/',
|
||||
'switchport-detail': '/api/topologie/switchport/{pk}/',
|
||||
'adherent-list': '/api/users/adherent/',
|
||||
'adherent-detail': '/api/users/adherent/{pk}/',
|
||||
'ban-list': '/api/users/ban/',
|
||||
'ban-detail': '/api/users/ban/{pk}/',
|
||||
'club-list': '/api/users/club/',
|
||||
'club-detail': '/api/users/club/{pk}/',
|
||||
'listright-list': '/api/users/listright/',
|
||||
'listright-detail': '/api/users/listright/{pk}/',
|
||||
'school-list': '/api/users/school/',
|
||||
'school-detail': '/api/users/school/{pk}/',
|
||||
'serviceuser-list': '/api/users/serviceuser/',
|
||||
'serviceuser-detail': '/api/users/serviceuser/{pk}/',
|
||||
'shell-list': '/api/users/shell/',
|
||||
'shell-detail': '/api/users/shell/{pk}/',
|
||||
'user-list': '/api/users/user/',
|
||||
'user-detail': '/api/users/user/{pk}/',
|
||||
'whitelist-list': '/api/users/whitelist/',
|
||||
'whitelist-detail': '/api/users/whitelist/{pk}/',
|
||||
'dnszones-list': '/api/dns/zones/',
|
||||
'hostmacip-list': '/api/dhcp/hostmacip/',
|
||||
'mailingstandard-list': '/api/mailing/standard/',
|
||||
'mailingclub-list': '/api/mailing/club/',
|
||||
'servicesregen-list': '/api/services/regen/',
|
||||
'servicesregen-detail': '/api/services/regen/{pk}/',
|
||||
'token': '/api/token-auth/',
|
||||
}
|
||||
|
||||
|
||||
def get_names():
|
||||
return urls.keys()
|
||||
|
||||
|
||||
def get_endpoint_for(name, logger=None, **kwargs):
|
||||
try:
|
||||
url=urls[name]
|
||||
except KeyError:
|
||||
e = exceptions.URLNameDoesNotExists(name)
|
||||
if logger is not None:
|
||||
logger.warning(e)
|
||||
raise e
|
||||
else:
|
||||
try:
|
||||
return url.format_map(kwargs)
|
||||
except KeyError as e:
|
||||
e = exceptions.URLParameterMissing(name, e)
|
||||
if logger is not None:
|
||||
logger.warning(e)
|
||||
raise e
|
|
@ -7,14 +7,6 @@ class APIClientGenericError(ValueError):
|
|||
super(APIClientGenericError, self).__init__(self.message)
|
||||
|
||||
|
||||
class URLNameDoesNotExists(APIClientGenericError):
|
||||
template = "The name '{}' was not foud among the possible endpoints."
|
||||
|
||||
|
||||
class URLParameterMissing(APIClientGenericError):
|
||||
template = "The url named '{}' requires the parameter {} to be built."
|
||||
|
||||
|
||||
class InvalidCredentials(APIClientGenericError):
|
||||
template = "The credentials for {}@{} are not valid."
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue