From cdb917e5652bc3782ef861272be9ae3acf32d0db Mon Sep 17 00:00:00 2001 From: ljf Date: Mon, 27 Apr 2020 18:09:07 +0200 Subject: [PATCH] [enh] Explain why domain expiration not found --- data/hooks/diagnosis/12-dnsrecords.py | 47 +++++++++++++++------------ locales/en.json | 2 ++ tests/test_i18n_keys.py | 3 +- 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/data/hooks/diagnosis/12-dnsrecords.py b/data/hooks/diagnosis/12-dnsrecords.py index b6d87aed0..f03e92df3 100644 --- a/data/hooks/diagnosis/12-dnsrecords.py +++ b/data/hooks/diagnosis/12-dnsrecords.py @@ -14,6 +14,7 @@ from yunohost.domain import domain_list, _build_dns_conf, _get_maindomain SMALL_SUFFIX_LIST = ['noho.st', 'nohost.me', 'ynh.fr', 'netlib.re'] + class DNSRecordsDiagnoser(Diagnoser): id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] @@ -33,12 +34,13 @@ class DNSRecordsDiagnoser(Diagnoser): all_domains = domain_list()["domains"] for domain in all_domains: self.logger_debug("Diagnosing DNS conf for %s" % domain) - is_subdomain = domain.split(".",1)[1] in all_domains + is_subdomain = domain.split(".", 1)[1] in all_domains for report in self.check_domain(domain, domain == main_domain, is_subdomain=is_subdomain): yield report - + # Check if a domain buy by the user will expire soon domains_from_registrar = ['.'.join(domain.split('.')[-2:]) for domain in all_domains] + domains_from_registrar = ['ynh.local', 'grimaud.me', 'netlib.re', 'arn-fai.net'] domains_from_registrar = set(domains_from_registrar) - set(SMALL_SUFFIX_LIST) for report in self.check_expiration_date(domains_from_registrar): yield report @@ -74,7 +76,6 @@ class DNSRecordsDiagnoser(Diagnoser): results[id_] = "WRONG" discrepancies.append(("diagnosis_dns_discrepancy", r)) - def its_important(): # Every mail DNS records are important for main domain # For other domain, we only report it as a warning for now... @@ -135,7 +136,7 @@ class DNSRecordsDiagnoser(Diagnoser): if r["name"] == "@": current = {part for part in current if not part.startswith("ip4:") and not part.startswith("ip6:")} return expected == current - elif r["type"] == "MX": + elif r["type"] == "MX": # For MX, we want to ignore the priority expected = r["value"].split()[-1] current = r["current"].split()[-1] @@ -143,14 +144,11 @@ class DNSRecordsDiagnoser(Diagnoser): else: return r["current"] == r["value"] - def check_expiration_date(self, domains): """ Alert if expiration date of a domain is soon """ - # FIXME find a way to ignore a specific domain without - # create a report by domain each time. We need something small details = { "not_found": [], "error": [], @@ -161,9 +159,9 @@ class DNSRecordsDiagnoser(Diagnoser): for domain in domains: expire_date = self.get_domain_expiration(domain) - if not expire_date: + if isinstance(expire_date, str): details["not_found"].append(( - "diagnosis_domain_expiration_not_found", + "diagnosis_%s_details" % (expire_date), {"domain": domain})) continue @@ -184,9 +182,17 @@ class DNSRecordsDiagnoser(Diagnoser): for alert_type in ["error", "warning", "not_found", "info"]: if details[alert_type]: - yield dict(meta={"category": "expiration"}, + if alert_type == "not_found": + meta = {"test": "domain_not_found"} + else: + meta = {"test": "domain_expiration"} + # Allow to ignor specifically a single domain + if len(details[alert_type]) == 1: + meta["domain"] = details[alert_type][0][1]["domain"] + meta["domain"] = details[alert_type][0][1]["domain"] + yield dict(meta=meta, data={}, - status=alert_type.upper() if alert_type != "not_found" else "INFO", + status=alert_type.upper() if alert_type != "not_found" else "WARNING", summary="diagnosis_domain_expiration_" + alert_type, details=details[alert_type]) @@ -194,19 +200,20 @@ class DNSRecordsDiagnoser(Diagnoser): """ Return the expiration datetime of a domain or None """ + # "echo failed" avoid to trigger CalledProcessError + command = "whois -H %s || echo failed" % (domain) + out = check_output(command).strip().split("\n") - p1 = Popen(['whois', domain], stdout=PIPE) - p2 = Popen(['grep', 'Expir'], stdin=p1.stdout, stdout=PIPE) - out, err = p2.communicate() - out = out.decode("utf-8").split('\n') - p1.terminate() - #p2.terminate() + # If there is less 5 lines, it's NOT FOUND response + if len(out) <= 4: + return "domain_not_found" for line in out: - match = re.search(r'\d{4}-\d{2}-\d{2}', line) + match = re.search(r'Expir.+(\d{4}-\d{2}-\d{2})', line) if match is not None: - return datetime.strptime(match.group(), '%Y-%m-%d') - return None + return datetime.strptime(match.group(1), '%Y-%m-%d') + return "domain_expiration_not_found" + def main(args, env, loggers): return DNSRecordsDiagnoser(args, env, loggers).diagnose() diff --git a/locales/en.json b/locales/en.json index 7f6d9ce34..a0e7454f1 100644 --- a/locales/en.json +++ b/locales/en.json @@ -173,6 +173,8 @@ "diagnosis_dns_discrepancy": "The following DNS record does not seem to follow the recommended configuration:
Type: {type}
Name: {name}
Current value: {current}
Excepted value: {value}", "diagnosis_dns_point_to_doc": "Please check the documentation at https://yunohost.org/dns_config if you need help about configuring DNS records.", "diagnosis_domain_expiration_not_found": "Unable to check the expiration date of some domains", + "diagnosis_domain_not_found_details": "The domain {domain} doesn't exist in WHOIS database !", + "diagnosis_domain_expiration_not_found_details": "The WHOIS returns some info about the domain {domain} but we are not able to found the expiration date inside those info.", "diagnosis_domain_expiration_info": "Domains expiration dates", "diagnosis_domain_expiration_warning": "Some domains expire in less than a month", "diagnosis_domain_expiration_error": "Some domains expire in less than a week", diff --git a/tests/test_i18n_keys.py b/tests/test_i18n_keys.py index 6dcfd5c70..6ddfa9c4a 100644 --- a/tests/test_i18n_keys.py +++ b/tests/test_i18n_keys.py @@ -119,8 +119,9 @@ def find_expected_string_keys(): for level in ["danger", "thirdparty", "warning"]: yield "confirm_app_install_%s" % level - for errortype in ["not_found", "error", "warning", "info"]: + for errortype in ["not_found", "error", "warning", "info", "not_found_details"]: yield "diagnosis_domain_expiration_%s" % errortype + yield "diagnosis_domain_not_found_details" for errortype in ["bad_status_code", "connection_error", "timeout"]: yield "diagnosis_http_%s" % errortype