From 6a23f561310589cf6909e1e28e6a7f5b9b15f286 Mon Sep 17 00:00:00 2001 From: FrantiĊĦek Zatloukal Date: Jun 23 2020 12:12:31 +0000 Subject: Adapt to new orphans.json format --- diff --git a/oraculum/controllers/packager_dashboard.py b/oraculum/controllers/packager_dashboard.py index 6f49dbd..71fb242 100644 --- a/oraculum/controllers/packager_dashboard.py +++ b/oraculum/controllers/packager_dashboard.py @@ -58,7 +58,7 @@ def dashboard_user_data_static(user): 'packages': packages["combined"], 'group_packages': packages["group"], 'primary_packages': packages["primary"], - 'orphans': dashboard.get_orphans(packages["combined"], CACHE.get('orphans_json')), + 'orphans': dashboard.get_orphans(packages["combined"]), 'fails_to_install': dashboard.get_health_check_user_data(packages["combined"]), 'updates': dashboard.get_updates(packages["combined"], CACHE.get('bodhi_updates')), 'overrides': dashboard.get_user_overrides(packages["combined"], CACHE.get('bodhi_overrides')), diff --git a/oraculum/utils/dashboard.py b/oraculum/utils/dashboard.py index 35504ae..335458d 100644 --- a/oraculum/utils/dashboard.py +++ b/oraculum/utils/dashboard.py @@ -152,22 +152,90 @@ def process_override(override): "release": release_from_nevra(override["nvr"]) } +def orphan_reason(package, orphans_json, reason_tree=[]): + """ + TODO: WIP + Returns chain of dependencies that caused the package to depend on something orphaned + """ + for p in orphans_json["affected_packages"][package]: + if p not in reason_tree: + reason_tree.append(p) + reason_tree = orphan_reason(p, orphans_json, reason_tree=reason_tree) + return reason_tree + +def is_directly_orphaned(package, orphans_json): + """ + Returns True if a package itself is orphaned + """ + if package in orphans_json["status_change"]: + return True + return False + +def filter_indirectly_orphaned(packages, orphans_json): + """ + Filters list containing orphaned and depending on orphaned packages to contain only directly orphaned packages + """ + ret = [] + for package in packages: + if is_directly_orphaned(package, orphans_json): + ret.append(package) + return ret + -def get_orphans(packages, orphans_json): +def orphan_since_earliest(reason_tree, orphans_json): """ - Returns dict of dictionaries (all packages), where orphaned package has orphaned == True + Returns the oldest time from reason_tree """ + times = [] + for reason in reason_tree: + try: + times.append(orphans_json["status_change"][reason]) + except KeyError: + continue + return min(times) + +def get_orphans(packages, orphans_json=None): + """ + Returns dict of dictionaries (all packages): { + "orphaned": directly orphaned package has orphaned == True, + "depends_on_orphaned": Package that depends on something orphaned (even indirectly), + "problematic_since": oldest time when something in the chain was orphaned + } + Example of orphans_json: { + "affected_packages": { + "package_a": [package_b, package_c,...], + "package_b": [package_c, package_d,...], + ... + }, + "status_change": { + "package_a": "time", + "package_b": "time", + ... + } + } + """ + if not orphans_json: + orphans_json = CACHE.get('orphans_json') orphans = {} for package in packages: orphans[package] = { "orphaned": False, - "orphaned_since": None + "depends_on_orphaned": False, + "reason_tree": [], + "problematic_since": None } - if package in orphans_json: + if package in orphans_json["affected_packages"]: + reason = orphan_reason(package, orphans_json) orphans[package] = { - "orphaned": True, - "orphaned_since": orphans_json[package] + "orphaned": is_directly_orphaned(package, orphans_json), + "depends_on_orphaned": True if len(orphans_json["affected_packages"][package]) != 0 else False, + "reason_tree": filter_indirectly_orphaned(reason, orphans_json), + "problematic_since": None } + if len(reason) != 0: + orphans[package]["problematic_since"] = orphan_since_earliest(reason, orphans_json) + else: + orphans[package]["problematic_since"] = orphans_json["status_change"][package] return orphans @@ -617,5 +685,35 @@ def get_health_check_user_data(packages): if __name__ == "__main__": - import ipdb - ipdb.set_trace() + def test_simple_orphans(): + EXPECTED_OUTPUT = {'directly_orphaned_package': { + 'orphaned': True, + 'depends_on_orphaned': False, + 'reason_tree': [], + 'problematic_since': '2020-05-13T05:50:55'}, + 'indirectly_orphaned_package': { + 'orphaned': True, + 'depends_on_orphaned': True, + 'reason_tree': ['directly_orphaned_package'], + 'problematic_since': '2020-05-13T05:50:55'}} + DATA = { + "affected_packages": { + "directly_orphaned_package": [], + "indirectly_orphaned_package": ["directly_orphaned_package"] + }, + "status_change": { + "directly_orphaned_package": "2020-05-13T05:50:55", + "indirectly_orphaned_package": "2020-06-04T18:08:34" + } + } + if get_orphans(["directly_orphaned_package","indirectly_orphaned_package"], DATA) == EXPECTED_OUTPUT: + print("simple orphans parsing seems to work FINE...") + else: + print("simple orphans parsing seems to be BROKEN!") + + def test_advanced_orphans(): + EXPECTED_OUTPUT = "" + DATA = "" + pass + + test_simple_orphans()