From 61f347aad6ef1e9e50510477d143973368e8e70b Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Mon, 2 Dec 2019 10:30:29 +0100 Subject: [PATCH] configuration support --- script/cucchiaiata | 18 ++-- src/cucchiaiata/__init__.py | 1 + src/cucchiaiata/common.py | 68 +++++++++++++++ src/cucchiaiata/config.py | 1 + src/cucchiaiata/configuration.py | 80 +++++++++++++++++ src/cucchiaiata/parser.py | 143 +++---------------------------- 6 files changed, 174 insertions(+), 137 deletions(-) create mode 100644 src/cucchiaiata/common.py create mode 100644 src/cucchiaiata/configuration.py diff --git a/script/cucchiaiata b/script/cucchiaiata index 1ff1e27..17f66f9 100755 --- a/script/cucchiaiata +++ b/script/cucchiaiata @@ -1,20 +1,22 @@ #!/usr/bin/env python3 """Zephir-cmd-input script """ -from sys import exit +from sys import exit, argv +from json import dumps from traceback import print_exc -from cucchiaiata import Parser, config +from cucchiaiata import Parser, config, Configuration from cucchiaiata.i18n import _ def main(): - # if sys.argv[1] == 'config.session.server.configure' or \ - # sys.argv[1] == 'config.session.servermodel.configure': - # configuration(sys.argv[1]) - # else: try: - parser = Parser() - print(parser.get()) + if argv[1] in ['config.session.server.configure', + 'config.session.servermodel.configure']: + Configuration().get() + else: + parser = Parser() + print(dumps(parser.get(), + indent=config.indent)) except Exception as err: if config.debug: print_exc() diff --git a/src/cucchiaiata/__init__.py b/src/cucchiaiata/__init__.py index dc09ff8..b0a6388 100644 --- a/src/cucchiaiata/__init__.py +++ b/src/cucchiaiata/__init__.py @@ -1,4 +1,5 @@ from .parser import Parser +from .configuration import Configuration from .config import config __all__ = ('Parser', 'config') diff --git a/src/cucchiaiata/common.py b/src/cucchiaiata/common.py new file mode 100644 index 0000000..a3bdb79 --- /dev/null +++ b/src/cucchiaiata/common.py @@ -0,0 +1,68 @@ +from os.path import isfile +from requests import get, post +from json import dumps +from typing import Dict + +from .config import config +from tiramisu_api import Config + + +if config.allow_insecure_https: + import warnings + from urllib3.exceptions import InsecureRequestWarning + warnings.simplefilter('ignore', InsecureRequestWarning) + + +class Common: + def __init__(self): + self.cucchiaiata_config = config + + def get_token(self): + if isfile(self.cucchiaiata_config.token_file): + return open(self.cucchiaiata_config.token_file).read() + return '' + + def get_error_from_http(self, + req): + try: + json = req.json() + err = json['error']['kwargs']['reason'] + except: + err = req.text + return err + + def remote_json_to_config(self, + url=None, + config_type=Config): + "retrieves the remote config from the distant api description" + if url is None: + url = self.cucchiaiata_config.remote_url + token = self.get_token() + headers = {'Authorization':'Bearer {}'.format(token)} + req = get(url, + headers=headers, + verify=False) + code = req.status_code + if code != 200: + err = self.get_error_from_http(req) + raise Exception('unable to load url ({}): {} ({})'.format(url, + err, + code)) + json = req.json() + return config_type(json) + + +def send_data(message: str, + payload: Dict): + final_url = '{}/{}'.format(config.remote_url, message) + ret = post(final_url, + data=dumps(payload), + verify=config.allow_insecure_https) + if ret.status_code != 200: + raise Exception(ret.text) + response = ret.json() + if 'error' in response: + if 'reason' in response['error']['kwargs']: + raise Exception("{}".format(response['error']['kwargs']['reason'])) + raise Exception('erreur inconnue') + return(response['response']) diff --git a/src/cucchiaiata/config.py b/src/cucchiaiata/config.py index 924bcea..2539ae8 100644 --- a/src/cucchiaiata/config.py +++ b/src/cucchiaiata/config.py @@ -33,6 +33,7 @@ version: {version}""" self.remote_url = 'http://{}/api/{}'.format(self.url, self.version) self.token_file = join(expanduser("~"), '.zephir-client.jwt.token') self.indent = config.get('indent', 2) + self.allow_insecure_https = config.get('allow_insecure_https', False) TO_JSON = {'config.session.server.get': ['content'], diff --git a/src/cucchiaiata/configuration.py b/src/cucchiaiata/configuration.py new file mode 100644 index 0000000..f953b56 --- /dev/null +++ b/src/cucchiaiata/configuration.py @@ -0,0 +1,80 @@ +from sys import argv, exit + + +from tiramisu_cmdline_parser import TiramisuCmdlineParser +from tiramisu_api import Config +from cucchiaiata.i18n import _ + + +from .common import send_data, Common + + +class ConfigAPI(Config): + def send_data(self, + data): + for index, payload in enumerate(data['updates']): + payload['session_id'] = self.session_id + if isinstance(payload['value'], list): + payload['value_multi'] = payload['value'] + del payload['value'] + ret = send_data(self.message, + payload) + if ret['status'] == 'error': + msg = _("cannot modify variable {} : {}").format(payload['name'],ret['message']) + raise Exception(msg) + + self.updates = [] + + +class Configuration(Common): + def configure_server(self): + if self.message == 'config.session.server.configure': + type = 'server' + else: + type = 'servermodel' + url = '{}/config/{}/{}'.format(self.cucchiaiata_config.remote_url, + type, + self.session_id) + tconfig = self.remote_json_to_config(url, + ConfigAPI) + tconfig.message = self.message + tconfig.session_id = self.session_id + return tconfig + + def get_parameters(self): + parameters = argv.copy() + + # get and remove config.session.xxxxx.configure + self.message = parameters.pop(1) + + # get and remove commandline name + self.prog = parameters.pop(0) + + # get and remove sessionid + try: + index = parameters.index('-s') + except ValueError: + try: + index = parameters.index('--sessionid') + except ValueError: + tiramisu_config = self.remote_json_to_config(ConfigAPI) + parser = TiramisuCmdlineParser(tiramisu_config, + self.prog, + unrestraint=True, + fullpath=True) + parser.print_help() + exit(1) + parameters.pop(index) + self.session_id = parameters.pop(index) + return parameters + + def get(self): + parameters = self.get_parameters() + tiramisu_config = self.configure_server() + parser = TiramisuCmdlineParser(tiramisu_config, + self.prog, + unrestraint=True, + fullpath=True) + parser.parse_args(parameters, + valid_mandatory=False) + tiramisu_config.send() diff --git a/src/cucchiaiata/parser.py b/src/cucchiaiata/parser.py index 0f25886..325de84 100644 --- a/src/cucchiaiata/parser.py +++ b/src/cucchiaiata/parser.py @@ -1,20 +1,12 @@ """Zephir Client library """ -from os.path import isfile -from requests import get, post -from json import dumps, loads -from typing import Dict -# import warnings -# from urllib3.exceptions import InsecureRequestWarning +from json import loads from tiramisu_cmdline_parser import TiramisuCmdlineParser from argparse import RawDescriptionHelpFormatter -from tiramisu_api import Config -from .config import config, TO_JSON - - -# warnings.simplefilter('ignore', InsecureRequestWarning) +from .config import TO_JSON +from .common import Common, send_data class CucchiaiataParser(TiramisuCmdlineParser): @@ -24,14 +16,11 @@ class CucchiaiataParser(TiramisuCmdlineParser): return super().print_help(*args, **kwargs) -class Parser: +class Parser(Common): def __init__(self): - # retrieve config's option - self.cucchiaiata_config = config - self.remote_url = self.cucchiaiata_config.remote_url - self.remote_config = self.remote_json_to_config() - + super().__init__() # build a tiramisu parser and parse argument + self.remote_config = self.remote_json_to_config() parser = CucchiaiataParser(self.remote_config, fullpath=False, remove_empty_od=True, @@ -40,12 +29,17 @@ class Parser: parser.parse_args() def get(self): + def _to_json(res): + for key, value in res.items(): + if key in TO_JSON[message]: + res[key] = loads(value) + # get current message message = self.remote_config.option('message').value.get() payload = self.get_payload(message) # send message - result = self.send_data(message, - payload) + result = send_data(message, + payload) # convert some results (file) to json if message in TO_JSON: @@ -55,53 +49,7 @@ class Parser: else: _to_json(result) - return dumps(result, indent=config.indent) - - def remote_json_to_config(self, - headers=None, - config_type=Config): - "retrieves the remote config from the distant api description" - req = get(self.remote_url, - headers=headers, - verify=False) - code = req.status_code - if code != 200: - err = self.get_error_from_http(req) - raise Exception('unable to load url ({}): {} ({})'.format(self.remote_url, - err, - code)) - json = req.json() - return config_type(json) - - def send_data(self, - message: str, - payload: Dict): - # get stored token if available - if isfile(self.cucchiaiata_config.token_file): - token = open(self.cucchiaiata_config.token_file).read() - else: - token = '' - final_url = '{}/{}'.format(self.remote_url, message) - headers = {'Authorization':'Bearer {}'.format(token)} - ret = post(final_url, - data=dumps(payload), - headers=headers, - # FIXME - verify=False) - if ret.status_code != 200: - raise Exception(ret.text) - response = ret.json() - if 'error' in response: - if 'reason' in response['error']['kwargs']: - raise Exception("{}".format(response['error']['kwargs']['reason'])) - raise Exception('erreur inconnue') - else: - return(response['response']) - - def _to_json(self, res): - for key, value in res.items(): - if key in TO_JSON[message]: - res[key] = loads(value) + return result def get_payload(self, message: str): @@ -111,66 +59,3 @@ class Parser: if not option.owner.isdefault() and not option.option.issymlinkoption(): payload[option.option.name()] = option.value.get() return payload - - def get_error_from_http(self, - req): - try: - json = req.json() - err = json['error']['kwargs']['reason'] - except: - err = req.text - return err - - -def configure_server(server, session_id, version, message, reporter=None): - url = 'https://{}/config/{}/api'.format(server, session_id) - token = open(config.token_file).read() - headers = {'Authorization':'Bearer {}'.format(token)} - tconfig = remote_json_to_config(url, headers, ConfigConfigurationAPI) - tconfig.version = version - tconfig.message = message - tconfig.url = server - tconfig.session_id = session_id - tconfig.reporter = reporter - return tconfig - - - -def configuration(config, - session_id, - configure): - parameters = sys.argv.copy() - # get sessionid index session_id - try: - index = parameters.index('-s') - except ValueError: - try: - index = parameters.index('--sessionid') - except ValueError: - remote_config = remote_json_to_config(config.remote_url) - parser = cmdline_factory(remote_config) - parser.print_help() - sys.exit(1) - parameters.pop(index) - session_id = parameters.pop(index) - # remove config.session.server.configure - parameters.pop(1) - # remove commandline - prog = parameters.pop(0) - try: - conf = configure_server(config.url, - session_id, - config.version, - configure) - parser = TiramisuCmdlineParser(conf, - prog, - unrestraint=True, - fullpath=True) - parser.parse_args(parameters, - valid_mandatory=False) - config.send() - except Exception as err: - if config.debug: - print_exc() - print(_("Error: {}").format(err)) - sys.exit(1)