From 9eb5c25e25630a55ee73e21e3f0b9d62cf270d07 Mon Sep 17 00:00:00 2001 From: Lubos Kocman Date: Wed, 13 Jul 2016 10:31:13 +0200 Subject: [PATCH] Add rida/pdc.py - A rida related product definition center calls * renamed and split config.pdc to config.pdc_url, config.pdc_insecure, config.pdc_develop * test-pdc.py contains example usage Signed-off-by: Lubos Kocman --- rida.conf | 6 +- rida/config.py | 36 ++++++++--- rida/pdc.py | 161 ++++++++++++++++++++++++++++++++++++++++++++++++- test-pdc.py | 22 +++++++ 4 files changed, 215 insertions(+), 10 deletions(-) create mode 100755 test-pdc.py diff --git a/rida.conf b/rida.conf index 93f6003d..a0f0ac5e 100644 --- a/rida.conf +++ b/rida.conf @@ -2,9 +2,11 @@ system = koji messaging = fedmsg koji_config = /etc/rida/koji.conf -koji_profile = stage +koji_profile = koji db = sqlite:///rida.db -pdc = http://pdc.stg.fedoraproject.org/ +pdc_url = http://fed-mod.org:8000/rest_api/v1 +pdc_insecure = True +pdc_develop = True scmurls = ["git://pkgs.stg.fedoraproject.org/modules/"] # How often should we resort to polling, in seconds diff --git a/rida/config.py b/rida/config.py index 51f861ce..53ffcecc 100644 --- a/rida/config.py +++ b/rida/config.py @@ -50,7 +50,9 @@ def from_file(filename=None): conf.db = default.get("db") conf.system = default.get("system") conf.messaging = default.get("messaging") - conf.pdc = default.get("pdc") + conf.pdc_url = default.get("pdc_url") + conf.pdc_insecure = default.get("pdc_insecure") + conf.pdc_develop = default.get("pdc_develop") conf.koji_config = default.get("koji_config") conf.koji_profile = default.get("koji_profile") conf.scmurls = json.loads(default.get("scmurls")) @@ -78,8 +80,10 @@ class Config(object): self._system = "" self._messaging = "" self._db = "" - self._pdc = "" self._polling_interval = 0 + self._pdc_url = "" + self._pdc_insecure = False + self._pdc_develop = False self._koji_config = None self._koji_profile = None self._koji_arches = None @@ -129,13 +133,31 @@ class Config(object): self._db = str(s) @property - def pdc(self): + def pdc_url(self): """PDC URL.""" - return self._pdc + return self._pdc_url - @pdc.setter - def pdc(self, s): - self._pdc = str(s) + @pdc_url.setter + def pdc_url(self, s): + self._pdc_url = str(s) + + @property + def pdc_insecure(self): + """Allow insecure connection to PDC.""" + return self._pdc_insecure + + @pdc_insecure.setter + def pdc_insecure(self, b): + self._pdc_insecure = bool(b) + + @property + def pdc_develop(self): + """PDC Development mode, basically noauth.""" + return self._pdc_develop + + @pdc_develop.setter + def pdc_develop(self, b): + self._pdc_develop = bool(b) @property def polling_interval(self): diff --git a/rida/pdc.py b/rida/pdc.py index 708f5285..0d7bddbe 100644 --- a/rida/pdc.py +++ b/rida/pdc.py @@ -21,6 +21,165 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # -# Written by Petr Ĺ abata +# Written by Lubos Kocman """PDC handler functions.""" + +import modulemd +from pdc_client import PDCClient + + + +def get_pdc_client_session(config): + """ + :param config: instance of rida.config.Config + :return pdc_client.PDCClient instance + """ + return PDCClient(config.pdc_url, config.pdc_develop, config.pdc_insecure) # hardcoded devel env + +def get_variant_dict(data): + """ + :param data: one of following + pdc variant_dict {'variant_name': value, 'variant_version': value, } + module dict {'name': value, 'version': value } + modulemd + + :return final list of module_info which pass repoclosure + """ + def is_module_dict(data): + if not isinstance(data, dict): + return False + + for attr in ('name', 'version'): + if attr not in data.keys(): + return False + return True + + def is_variant_dict(data): + if not isinstance(data, dict): + return False + + for attr in ('variant_name', 'variant_version'): + if attr not in data.keys(): + return False + return True + + def is_modulemd(data): + return isinstance(data, modulemd.ModuleMetadata) + + def is_module_str(data): + return isinstance(data, str) + + result = None + + if is_module_str(data): + result = variant_dict_from_str(data) + + elif is_modulemd(data): + result = {'variant_name': data.name, 'variant_version': data.version } + + elif is_variant_dict(data): + result = data + # ensure that variant_type is in result + if 'variant_type' not in result.keys(): + result['variant_type'] = 'module' + + elif is_module_dict(data): + result = {'variant_name': data['name'], 'variant_version': data['version']} + + if not result: + raise ValueError("Couldn't get variant_dict from %s" % data) + + return result + + + +def variant_dict_from_str(module_str): + """ + :param module_str: a string to match in PDC + :return module_info dict + + Example minimal module_info {'variant_name': module_name, 'variant_version': module_version, 'variant_type': 'module'} + """ + # best match due several filters not being provided such as variant type ... + + module_info = {} + + module_info['variant_name'] = module_str[:module_str.find('-')] + module_info['variant_version'] = module_str[module_str.find('-')+1:] + module_info['variant_type'] = 'module' + + return module_info + +def get_module(session, module_info): + """ + :param session : PDCClient instance + :param module_info: pdc variant_dict, str, mmd or module dict + :return final list of module_info which pass repoclosure + """ + + module_info = get_variant_dict(module_info) + + module_info = session['unreleasedvariant'](page_size=-1, **module_info) + assert len(module_info) <= 1 + + if not module_info: + return None + + return module_info[0] + +def get_module_tag(session, module_info): + """ + :param session : PDCClient instance + :param module_info: list of module_info dicts + :return: koji tag string + """ + return get_module(session, module_info)['koji_tag'] + +def module_depsolving_wrapper(session, module_list): + """ + :param session : PDCClient instance + :param module_list: list of module_info dicts + :return final list of module_info which pass repoclosure + """ + # TODO: implement this + + # Make sure that these are dicts from PDC ... ensures all values + module_infos = [get_module(session, module) for module in module_list] + + return module_infos + +def get_module_dependencies(session, module_info): + """ + :param session : PDCClient instance + :param module_infos : a dict containing filters for pdc + + Example minimal module_info {'variant_name': module_name, 'variant_version': module_version, 'variant_type': 'module'} + """ + # XXX get definitive list of modules + + deps = [] + module_info = get_module(session, module_info) + if 'deps' in module_info and module_info['deps']: + deps = module_depsolving_wrapper(session, module_info['deps']) + + return deps + +def get_module_build_dependencies(session, module_info): + """ + :param session : PDCClient instance + :param module_info : a dict containing filters for pdc + :return final list of module_infos which pass repoclosure + + Example minimal module_info {'variant_name': module_name, 'variant_version': module_version, 'variant_type': 'module'} + """ + # XXX get definitive list of modules + + deps = [] + module_info = get_module(session, module_info) + if 'build_deps' in module_info and module_info['build_deps']: + deps = module_depsolving_wrapper(session, module_info['build_deps']) + + return deps + + diff --git a/test-pdc.py b/test-pdc.py new file mode 100755 index 00000000..448ece61 --- /dev/null +++ b/test-pdc.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python3 +""" A little script to test pdc interaction. """ + +from rida.pdc import * +from rida.config import Config + + +cfg = Config() +cfg.pdc_url = "http://fed-mod.org:8000/rest_api/v1" +cfg.pdc_insecure = True +cfg.pdc_develop = True + +pdc_session = get_pdc_client_session(cfg) +module = get_module(pdc_session, {'name': 'testmodule', 'version': '1.0'}) + +if module: + print ("pdc_data=%s" % str(module)) + print ("deps=[%s]" % ", ".join(get_module_dependencies(pdc_session, module))) + print ("build_deps=[%s]" % ", ".join(get_module_build_dependencies(pdc_session, module))) + print ("tag=%s" % get_module_tag(pdc_session, module)) +else: + print ('module was not found')