diff options
Diffstat (limited to 'testapi/testapi-client/testapiclient/utils')
4 files changed, 173 insertions, 0 deletions
diff --git a/testapi/testapi-client/testapiclient/utils/__init__.py b/testapi/testapi-client/testapiclient/utils/__init__.py new file mode 100644 index 0000000..ebb891f --- /dev/null +++ b/testapi/testapi-client/testapiclient/utils/__init__.py @@ -0,0 +1,8 @@ +def get_item_properties(item, fields): + """Return a tuple containing the item properties. + + :param item: a single item resource (e.g. Server, Project, etc) + :param fields: tuple of strings with the desired field names + """ + + return tuple([item.get(field, '') for field in fields]) diff --git a/testapi/testapi-client/testapiclient/utils/clientmanager.py b/testapi/testapi-client/testapiclient/utils/clientmanager.py new file mode 100644 index 0000000..cbfd723 --- /dev/null +++ b/testapi/testapi-client/testapiclient/utils/clientmanager.py @@ -0,0 +1,87 @@ +import httplib +import json +import os +import urllib +import logging + +import requests + +LOG = logging.getLogger(__name__) + + +class ClientManager(object): + headers = { + 'Content-type': 'application/json', + 'Accept': 'text/plain'} + + def __init__(self, cli_options=None): + self.cli_options = cli_options + self.session = requests.Session() + self._auth_completed = False + + @property + def auth_required(self): + return self._auth() + + def _auth(self): + return { + 'name': self.cli_options.u, + 'pass': self.cli_options.p + } if self.cli_options.u else None + + def auth(self): + + if self._auth_completed: + return + + hostname = '{}{}{}'.format(os.environ.get('testapi_cas_auth_url'), + urllib.quote(os.environ.get('testapi_url')), + os.environ.get('testapi_cas_signin_return')) + data = self._auth() + data.update({'form_id': 'user_login'}) + LOG.debug('authenticating.....') + response = self.session.post(hostname, data) + if "login" in response.text: + raise Exception('Authenticate failed') + self._auth_completed = True + + def get(self, url): + return self._parse_response('Get', + self._request('get', url, + headers=self.headers)) + + def post(self, url, data): + if 'results' in url or 'deployresults' in url: + self.headers['X-Auth-Token'] = os.environ.get('testapi_token') + return self._parse_response('Create', + self._request('post', url, + data=json.dumps(data), + headers=self.headers)) + + def put(self, url, data): + return self._parse_response('Update', + self._request('put', url, + data=json.dumps(data), + headers=self.headers)) + + def delete(self, url, *args): + data = json.dumps(args[0]) if len(args) > 0 else None + return self._parse_response('Delete', + self._request('delete', url, + data=data, + headers=self.headers)) + + def _request(self, method, *args, **kwargs): + return getattr(self.session, method)(*args, **kwargs) + + def _raise_failure(self, op, response): + raise Exception('{} failed: {}'.format(op, response.reason)) + + def _parse_response(self, op, response): + if response.status_code == httplib.OK: + if op != 'Delete' and response.text != '': + return response.json() + else: + return None + else: + self._raise_failure(op, response) diff --git a/testapi/testapi-client/testapiclient/utils/command.py b/testapi/testapi-client/testapiclient/utils/command.py new file mode 100644 index 0000000..b9d1ce8 --- /dev/null +++ b/testapi/testapi-client/testapiclient/utils/command.py @@ -0,0 +1,38 @@ +import abc +import logging + +from cliff import command +from cliff import lister +from cliff import show +import six + +from testapiclient import utils + + +class CommandMeta(abc.ABCMeta): + + def __new__(mcs, name, bases, cls_dict): + if 'log' not in cls_dict: + cls_dict['log'] = logging.getLogger( + cls_dict['__module__'] + '.' + name) + return super(CommandMeta, mcs).__new__(mcs, name, bases, cls_dict) + + +@six.add_metaclass(CommandMeta) +class Command(command.Command): + def run(self, parsed_args): + self.log.debug('run(%s)', parsed_args) + return super(Command, self).run(parsed_args) + + +class Lister(Command, lister.Lister): + @staticmethod + def format_output(columns, data): + return (columns, + (utils.get_item_properties(s, columns) for s in data)) + + +class ShowOne(Command, show.ShowOne): + @staticmethod + def format_output(body): + return zip(*sorted(six.iteritems(body))) diff --git a/testapi/testapi-client/testapiclient/utils/urlparse.py b/testapi/testapi-client/testapiclient/utils/urlparse.py new file mode 100644 index 0000000..47d40d5 --- /dev/null +++ b/testapi/testapi-client/testapiclient/utils/urlparse.py @@ -0,0 +1,40 @@ +import os + +from six.moves.urllib import parse + + +def path_join(base, *urls): + def _path_join(base, url): + if not base.endswith('/'): + base += '/' + return parse.urljoin(base, url) + + urls = (base,) + urls + return reduce(_path_join, urls) + + +def query_join(base, **queries): + return base + '?' + parse.urlencode(queries) + + +def resource_join(*url): + testapi_url = os.environ.get('testapi_url') + return path_join(testapi_url, *url) + + +def get_queries(queries, parsed_args): + if not isinstance(queries, list): + queries = [queries] + + return {query: getattr(parsed_args, query) + for query in queries + if hasattr(parsed_args, query) and getattr(parsed_args, query)} + + +def query_by(base, queries, parsed_args): + qs = get_queries(queries, parsed_args) + return query_join(base, **qs) if qs else base + + +def url_format(base, parsed_args): + return base.format(**(parsed_args.__dict__)) |