Add a 'yunohost diagnosis get' to get one specific raw info

This commit is contained in:
Alexandre Aubin 2020-04-07 00:16:18 +02:00
parent 7cfd553c3f
commit 8e83f8aa29
4 changed files with 70 additions and 27 deletions

View file

@ -1676,7 +1676,7 @@ diagnosis:
action: store_true
run:
action_help: Show most recents diagnosis results
action_help: Run diagnosis
api: POST /diagnosis/run
arguments:
categories:
@ -1701,3 +1701,14 @@ diagnosis:
--list:
help: List active ignore filters
action: store_true
get:
action_help: Low-level command to fetch raw data and status about a specific diagnosis test
api: GET /diagnosis/item/<category>
arguments:
category:
help: Diagnosis category to fetch results from
item:
help: "List of criteria describing the test. Must correspond exactly to the 'meta' infos in 'yunohost diagnosis show'"
metavar: CRITERIA
nargs: "*"

View file

@ -72,13 +72,13 @@ class IPDiagnoser(Diagnoser):
ipv4 = self.get_public_ip(4) if can_ping_ipv4 else None
ipv6 = self.get_public_ip(6) if can_ping_ipv6 else None
yield dict(meta={"test": "ip", "version": 4},
yield dict(meta={"test": "ip", "version": '4'},
data=ipv4,
status="SUCCESS" if ipv4 else "ERROR",
summary=("diagnosis_ip_connected_ipv4", {}) if ipv4
else ("diagnosis_ip_no_ipv4", {}))
yield dict(meta={"test": "ip", "version": 6},
yield dict(meta={"test": "ip", "version": '6'},
data=ipv6,
status="SUCCESS" if ipv6 else "WARNING",
summary=("diagnosis_ip_connected_ipv6", {}) if ipv6

View file

@ -46,12 +46,12 @@ class PortsDiagnoser(Diagnoser):
for port, service in sorted(ports.items()):
category = services[service].get("category", "[?]")
if r["ports"].get(str(port), None) is not True:
yield dict(meta={"port": port, "needed_by": service},
yield dict(meta={"port": str(port)},
status="ERROR",
summary=("diagnosis_ports_unreachable", {"port": port}),
details=[("diagnosis_ports_needed_by", (service, category)), ("diagnosis_ports_forwarding_tip", ())])
else:
yield dict(meta={"port": port, "needed_by": service},
yield dict(meta={"port": str(port)},
status="SUCCESS",
summary=("diagnosis_ports_ok", {"port": port}),
details=[("diagnosis_ports_needed_by", (service, category))])

View file

@ -44,6 +44,25 @@ def diagnosis_list():
return {"categories": all_categories_names}
def diagnosis_get(category, item):
# Get all the categories
all_categories = _list_diagnosis_categories()
all_categories_names = [c for c, _ in all_categories]
if category not in all_categories_names:
raise YunohostError('diagnosis_unknown_categories', categories=category)
if isinstance(item, list):
if any("=" not in criteria for criteria in item):
raise YunohostError("Criterias should be of the form key=value (e.g. domain=yolo.test)")
# Convert the provided criteria into a nice dict
item = {c.split("=")[0]: c.split("=")[1] for c in item}
return Diagnoser.get_cached_report(category, item=item)
def diagnosis_show(categories=[], issues=False, full=False, share=False):
# Get all the categories
@ -56,7 +75,7 @@ def diagnosis_show(categories=[], issues=False, full=False, share=False):
else:
unknown_categories = [c for c in categories if c not in all_categories_names]
if unknown_categories:
raise YunohostError('diagnosis_unknown_categories', categories=", ".join(categories))
raise YunohostError('diagnosis_unknown_categories', categories=", ".join(unknown_categories))
if not os.path.exists(DIAGNOSIS_CACHE):
logger.warning(m18n.n("diagnosis_never_ran_yet"))
@ -65,20 +84,15 @@ def diagnosis_show(categories=[], issues=False, full=False, share=False):
# Fetch all reports
all_reports = []
for category in categories:
if not os.path.exists(Diagnoser.cache_file(category)):
logger.warning(m18n.n("diagnosis_no_cache", category=category))
report = {"id": category,
"cached_for": -1,
"timestamp": -1,
"items": []}
Diagnoser.i18n(report)
else:
try:
report = Diagnoser.get_cached_report(category)
except Exception as e:
logger.error(m18n.n("diagnosis_failed", category=category, error=str(e)))
continue
Diagnoser.i18n(report)
add_ignore_flag_to_issues(report)
if not full:
del report["timestamp"]
@ -221,7 +235,7 @@ def diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
if category not in all_categories_names:
raise YunohostError("%s is not a diagnosis category" % category)
if any("=" not in criteria for criteria in filter_[1:]):
raise YunohostError("Extra criterias should be of the form key=value (e.g. domain=yolo.test)")
raise YunohostError("Criterias should be of the form key=value (e.g. domain=yolo.test)")
# Convert the provided criteria into a nice dict
criterias = {c.split("=")[0]: c.split("=")[1] for c in filter_[1:]}
@ -356,7 +370,12 @@ class Diagnoser():
for dependency in self.dependencies:
dep_report = Diagnoser.get_cached_report(dependency)
if dep_report["timestamp"] == -1: # No cache yet for this dep
dep_errors = True
else:
dep_errors = [item for item in dep_report["items"] if item["status"] == "ERROR"]
if dep_errors:
logger.error(m18n.n("diagnosis_cant_run_because_of_dep", category=self.description, dep=Diagnoser.get_description(dependency)))
return 1, {}
@ -396,11 +415,24 @@ class Diagnoser():
return os.path.join(DIAGNOSIS_CACHE, "%s.json" % id_)
@staticmethod
def get_cached_report(id_):
filename = Diagnoser.cache_file(id_)
report = read_json(filename)
report["timestamp"] = int(os.path.getmtime(filename))
Diagnoser.i18n(report)
def get_cached_report(id_, item=None):
cache_file = Diagnoser.cache_file(id_)
if not os.path.exists(cache_file):
logger.warning(m18n.n("diagnosis_no_cache", category=id_))
report = {"id": category,
"cached_for": -1,
"timestamp": -1,
"items": []}
else:
report = read_json(cache_file)
report["timestamp"] = int(os.path.getmtime(cache_file))
if item:
for report_item in report["items"]:
if report_item.get("meta") == item:
return report_item
return {}
else:
return report
@staticmethod