rework domains cache logic

This commit is contained in:
axolotle 2022-02-01 18:23:38 +01:00
parent d1d203726b
commit 6001b0f7af

View file

@ -24,7 +24,7 @@
Manage domains Manage domains
""" """
import os import os
from typing import Dict, Any from typing import List, Any
from moulinette import m18n, Moulinette from moulinette import m18n, Moulinette
from moulinette.core import MoulinetteError from moulinette.core import MoulinetteError
@ -47,7 +47,47 @@ logger = getActionLogger("yunohost.domain")
DOMAIN_SETTINGS_DIR = "/etc/yunohost/domains" DOMAIN_SETTINGS_DIR = "/etc/yunohost/domains"
# Lazy dev caching to avoid re-query ldap every time we need the domain list # Lazy dev caching to avoid re-query ldap every time we need the domain list
domain_list_cache: Dict[str, Any] = {} domain_list_cache: List[str] = []
main_domain_cache: str = None
def _get_maindomain(no_cache=False):
global main_domain_cache
if not main_domain_cache or no_cache:
with open("/etc/yunohost/current_host", "r") as f:
main_domain_cache = f.readline().rstrip()
return main_domain_cache
def _get_domains(exclude_subdomains=False, no_cache=False):
global domain_list_cache
if not domain_list_cache or no_cache:
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
result = [
entry["virtualdomain"][0]
for entry in ldap.search("ou=domains", "virtualdomain=*", ["virtualdomain"])
]
def cmp_domain(domain):
# Keep the main part of the domain and the extension together
# eg: this.is.an.example.com -> ['example.com', 'an', 'is', 'this']
domain = domain.split(".")
domain[-1] = domain[-2] + domain.pop()
return list(reversed(domain))
domain_list_cache = sorted(result, key=cmp_domain)
if exclude_subdomains:
return [
domain
for domain in domain_list_cache
if not _get_parent_domain_of(domain, return_self=False)
]
return domain_list_cache
def domain_list(exclude_subdomains=False): def domain_list(exclude_subdomains=False):
@ -58,47 +98,11 @@ def domain_list(exclude_subdomains=False):
exclude_subdomains -- Filter out domains that are subdomains of other declared domains exclude_subdomains -- Filter out domains that are subdomains of other declared domains
""" """
global domain_list_cache return {"domains": _get_domains(exclude_subdomains), "main": _get_maindomain()}
if not exclude_subdomains and domain_list_cache:
return domain_list_cache
from yunohost.utils.ldap import _get_ldap_interface
ldap = _get_ldap_interface()
result = [
entry["virtualdomain"][0]
for entry in ldap.search("ou=domains", "virtualdomain=*", ["virtualdomain"])
]
result_list = []
for domain in result:
if exclude_subdomains:
parent_domain = domain.split(".", 1)[1]
if parent_domain in result:
continue
result_list.append(domain)
def cmp_domain(domain):
# Keep the main part of the domain and the extension together
# eg: this.is.an.example.com -> ['example.com', 'an', 'is', 'this']
domain = domain.split(".")
domain[-1] = domain[-2] + domain.pop()
domain = list(reversed(domain))
return domain
result_list = sorted(result_list, key=cmp_domain)
# Don't cache answer if using exclude_subdomains
if exclude_subdomains:
return {"domains": result_list, "main": _get_maindomain()}
domain_list_cache = {"domains": result_list, "main": _get_maindomain()}
return domain_list_cache
def _assert_domain_exists(domain): def _assert_domain_exists(domain):
if domain not in domain_list()["domains"]: if domain not in _get_domains():
raise YunohostValidationError("domain_unknown", domain=domain) raise YunohostValidationError("domain_unknown", domain=domain)
@ -107,26 +111,24 @@ def _list_subdomains_of(parent_domain):
_assert_domain_exists(parent_domain) _assert_domain_exists(parent_domain)
out = [] out = []
for domain in domain_list()["domains"]: for domain in _get_domains():
if domain.endswith(f".{parent_domain}"): if domain.endswith(f".{parent_domain}"):
out.append(domain) out.append(domain)
return out return out
def _get_parent_domain_of(domain): def _get_parent_domain_of(domain, return_self=True):
_assert_domain_exists(domain) _assert_domain_exists(domain)
if "." not in domain: domains = _get_domains()
return domain while "." in domain:
domain = domain.split(".", 1)[1]
if domain in domains:
return domain
parent_domain = domain.split(".", 1)[-1] return domain if return_self else None
if parent_domain not in domain_list()["domains"]:
return domain # Domain is its own parent
else:
return _get_parent_domain_of(parent_domain)
@is_unit_operation() @is_unit_operation()
@ -198,7 +200,7 @@ def domain_add(operation_logger, domain, dyndns=False):
raise YunohostError("domain_creation_failed", domain=domain, error=e) raise YunohostError("domain_creation_failed", domain=domain, error=e)
finally: finally:
global domain_list_cache global domain_list_cache
domain_list_cache = {} domain_list_cache = []
# Don't regen these conf if we're still in postinstall # Don't regen these conf if we're still in postinstall
if os.path.exists("/etc/yunohost/installed"): if os.path.exists("/etc/yunohost/installed"):
@ -255,7 +257,7 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
# Check domain is not the main domain # Check domain is not the main domain
if domain == _get_maindomain(): if domain == _get_maindomain():
other_domains = domain_list()["domains"] other_domains = _get_domains()
other_domains.remove(domain) other_domains.remove(domain)
if other_domains: if other_domains:
@ -316,7 +318,7 @@ def domain_remove(operation_logger, domain, remove_apps=False, force=False):
raise YunohostError("domain_deletion_failed", domain=domain, error=e) raise YunohostError("domain_deletion_failed", domain=domain, error=e)
finally: finally:
global domain_list_cache global domain_list_cache
domain_list_cache = {} domain_list_cache = []
stuff_to_delete = [ stuff_to_delete = [
f"/etc/yunohost/certs/{domain}", f"/etc/yunohost/certs/{domain}",
@ -380,8 +382,8 @@ def domain_main_domain(operation_logger, new_main_domain=None):
# Apply changes to ssl certs # Apply changes to ssl certs
try: try:
write_to_file("/etc/yunohost/current_host", new_main_domain) write_to_file("/etc/yunohost/current_host", new_main_domain)
global domain_list_cache global main_domain_cache
domain_list_cache = {} main_domain_cache = None
_set_hostname(new_main_domain) _set_hostname(new_main_domain)
except Exception as e: except Exception as e:
logger.warning(str(e), exc_info=1) logger.warning(str(e), exc_info=1)
@ -409,12 +411,6 @@ def domain_url_available(domain, path):
return len(_get_conflicting_apps(domain, path)) == 0 return len(_get_conflicting_apps(domain, path)) == 0
def _get_maindomain():
with open("/etc/yunohost/current_host", "r") as f:
maindomain = f.readline().rstrip()
return maindomain
def domain_config_get(domain, key="", full=False, export=False): def domain_config_get(domain, key="", full=False, export=False):
""" """
Display a domain configuration Display a domain configuration