[CI] Format code with Black

This commit is contained in:
yunohost-bot 2023-02-01 17:10:08 +00:00
parent ade92e431d
commit b943c69c8b
67 changed files with 0 additions and 500 deletions

View file

@ -31,7 +31,6 @@ def get_dict_actions(OPTION_SUBTREE, category):
with open(ACTIONSMAP_FILE, "r") as stream:
# Getting the dictionary containning what actions are possible per category
OPTION_TREE = yaml.safe_load(stream)
@ -65,7 +64,6 @@ with open(ACTIONSMAP_FILE, "r") as stream:
os.makedirs(BASH_COMPLETION_FOLDER, exist_ok=True)
with open(BASH_COMPLETION_FILE, "w") as generated_file:
# header of the file
generated_file.write("#\n")
generated_file.write("# completion for yunohost\n")

View file

@ -20,7 +20,6 @@ def get_current_commit():
def render(helpers):
current_commit = get_current_commit()
data = {
@ -56,20 +55,17 @@ def render(helpers):
class Parser:
def __init__(self, filename):
self.filename = filename
self.file = open(filename, "r").readlines()
self.blocks = None
def parse_blocks(self):
self.blocks = []
current_reading = "void"
current_block = {"name": None, "line": -1, "comments": [], "code": []}
for i, line in enumerate(self.file):
if line.startswith("#!/bin/bash"):
continue
@ -117,7 +113,6 @@ class Parser:
current_reading = "code"
elif current_reading == "code":
if line == "}":
# We're getting out of the function
current_reading = "void"
@ -138,7 +133,6 @@ class Parser:
continue
def parse_block(self, b):
b["brief"] = ""
b["details"] = ""
b["usage"] = ""
@ -164,7 +158,6 @@ class Parser:
elif subblock.startswith("usage"):
for line in subblock.split("\n"):
if line.startswith("| arg"):
linesplit = line.split()
argname = linesplit[2]
@ -216,7 +209,6 @@ def malformed_error(line_number):
def main():
helper_files = sorted(glob.glob("../helpers/*"))
helpers = []

View file

@ -60,7 +60,6 @@ def main():
# man pages of "yunohost *"
with open(ACTIONSMAP_FILE, "r") as actionsmap:
# Getting the dictionary containning what actions are possible per domain
actionsmap = ordered_yaml_load(actionsmap)

View file

@ -3,7 +3,6 @@ from yunohost.utils.resources import AppResourceClassesByType
resources = sorted(AppResourceClassesByType.values(), key=lambda r: r.priority)
for klass in resources:
doc = klass.__doc__.replace("\n ", "\n")
print("")

View file

@ -32,7 +32,6 @@ def autofix_i18n_placeholders():
# We iterate over all keys/string in en.json
for key, string in reference.items():
# Ignore check if there's no translation yet for this key
if key not in this_locale:
continue
@ -89,7 +88,6 @@ Please fix it manually !
def autofix_orthotypography_and_standardized_words():
def reformat(lang, transformations):
locale = open(f"{LOCALE_FOLDER}{lang}.json").read()
for pattern, replace in transformations.items():
locale = re.compile(pattern).sub(replace, locale)
@ -146,11 +144,9 @@ def autofix_orthotypography_and_standardized_words():
def remove_stale_translated_strings():
reference = json.loads(open(LOCALE_FOLDER + "en.json").read())
for locale_file in TRANSLATION_FILES:
print(locale_file)
this_locale = json.loads(
open(LOCALE_FOLDER + locale_file).read(), object_pairs_hook=OrderedDict

View file

@ -19,7 +19,6 @@ REFERENCE_FILE = LOCALE_FOLDER + "en.json"
def find_expected_string_keys():
# Try to find :
# m18n.n( "foo"
# YunohostError("foo"
@ -197,7 +196,6 @@ undefined_keys = sorted(undefined_keys)
mode = sys.argv[1].strip("-")
if mode == "check":
# Unused keys are not too problematic, will be automatically
# removed by the other autoreformat script,
# but still informative to display them

View file

@ -32,7 +32,6 @@ def is_installed():
def cli(debug, quiet, output_as, timeout, args, parser):
init_logging(interface="cli", debug=debug, quiet=quiet)
# Check that YunoHost is installed
@ -51,7 +50,6 @@ def cli(debug, quiet, output_as, timeout, args, parser):
def api(debug, host, port):
init_logging(interface="api", debug=debug)
def is_installed_api():
@ -71,7 +69,6 @@ def api(debug, host, port):
def check_command_is_valid_before_postinstall(args):
allowed_if_not_postinstalled = [
"tools postinstall",
"tools versions",
@ -109,7 +106,6 @@ def init_i18n():
def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yunohost"):
logfile = os.path.join(logdir, "yunohost-%s.log" % interface)
if not os.path.isdir(logdir):

View file

@ -238,7 +238,6 @@ def app_info(app, full=False, upgradable=False):
def _app_upgradable(app_infos):
# Determine upgradability
app_in_catalog = app_infos.get("from_catalog")
@ -374,7 +373,6 @@ def app_map(app=None, raw=False, user=None):
)
for url in perm_all_urls:
# Here, we decide to completely ignore regex-type urls ...
# Because :
# - displaying them in regular "yunohost app map" output creates
@ -716,7 +714,6 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
),
)
finally:
# If upgrade failed, try to restore the safety backup
if (
upgrade_failed
@ -762,7 +759,6 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
# If upgrade failed or broke the system,
# raise an error and interrupt all other pending upgrades
if upgrade_failed or broke_the_system:
# display this if there are remaining apps
if apps[number + 1 :]:
not_upgraded_apps = apps[number:]
@ -843,7 +839,6 @@ def app_upgrade(app=[], url=None, file=None, force=False, no_safety_backup=False
def app_manifest(app, with_screenshot=False):
manifest, extracted_app_folder = _extract_app(app)
raw_questions = manifest.get("install", {}).values()
@ -886,7 +881,6 @@ def app_manifest(app, with_screenshot=False):
def _confirm_app_install(app, force=False):
# Ignore if there's nothing for confirm (good quality app), if --force is used
# or if request on the API (confirm already implemented on the API side)
if force or Moulinette.interface.type == "api":
@ -1036,7 +1030,6 @@ def app_install(
# If packaging_format v2+, save all install questions as settings
if packaging_format >= 2:
for question in questions:
# Except user-provider passwords
if question.type == "password":
continue
@ -1135,7 +1128,6 @@ def app_install(
# If the install failed or broke the system, we remove it
if install_failed or broke_the_system:
# This option is meant for packagers to debug their apps more easily
if no_remove_on_failure:
raise YunohostError(
@ -1390,7 +1382,6 @@ def app_setting(app, key, value=None, delete=False):
)
if is_legacy_permission_setting:
from yunohost.permission import (
user_permission_list,
user_permission_update,
@ -1433,7 +1424,6 @@ def app_setting(app, key, value=None, delete=False):
# SET
else:
urls = value
# If the request is about the root of the app (/), ( = the vast majority of cases)
# we interpret this as a change for the main permission
@ -1445,7 +1435,6 @@ def app_setting(app, key, value=None, delete=False):
else:
user_permission_update(app + ".main", remove="visitors")
else:
urls = urls.split(",")
if key.endswith("_regex"):
urls = ["re:" + url for url in urls]
@ -1604,7 +1593,6 @@ def app_ssowatconf():
)
for app in _installed_apps():
app_settings = read_yaml(APPS_SETTING_PATH + app + "/settings.yml") or {}
# Redirected
@ -1630,7 +1618,6 @@ def app_ssowatconf():
# New permission system
for perm_name, perm_info in all_permissions.items():
uris = (
[]
+ ([perm_info["url"]] if perm_info["url"] else [])
@ -1694,13 +1681,11 @@ def app_change_label(app, new_label):
def app_action_list(app):
return AppConfigPanel(app).list_actions()
@is_unit_operation()
def app_action_run(operation_logger, app, action, args=None, args_file=None):
return AppConfigPanel(app).run_action(
action, args=args, args_file=args_file, operation_logger=operation_logger
)
@ -2036,12 +2021,10 @@ def _get_manifest_of_app(path):
def _parse_app_doc_and_notifications(path):
doc = {}
notification_names = ["PRE_INSTALL", "POST_INSTALL", "PRE_UPGRADE", "POST_UPGRADE"]
for filepath in glob.glob(os.path.join(path, "doc") + "/*.md"):
# to be improved : [a-z]{2,3} is a clumsy way of parsing the
# lang code ... some lang code are more complex that this é_è
m = re.match("([A-Z]*)(_[a-z]{2,3})?.md", filepath.split("/")[-1])
@ -2091,11 +2074,9 @@ def _parse_app_doc_and_notifications(path):
def _hydrate_app_template(template, data):
stuff_to_replace = set(re.findall(r"__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__", template))
for stuff in stuff_to_replace:
varname = stuff.strip("_").lower()
if varname in data:
@ -2105,7 +2086,6 @@ def _hydrate_app_template(template, data):
def _convert_v1_manifest_to_v2(manifest):
manifest = copy.deepcopy(manifest)
if "upstream" not in manifest:
@ -2186,7 +2166,6 @@ def _convert_v1_manifest_to_v2(manifest):
def _set_default_ask_questions(questions, script_name="install"):
# arguments is something like
# { "domain":
# {
@ -2244,7 +2223,6 @@ def _set_default_ask_questions(questions, script_name="install"):
def _is_app_repo_url(string: str) -> bool:
string = string.strip()
# Dummy test for ssh-based stuff ... should probably be improved somehow
@ -2261,7 +2239,6 @@ def _app_quality(src: str) -> str:
raw_app_catalog = _load_apps_catalog()["apps"]
if src in raw_app_catalog or _is_app_repo_url(src):
# If we got an app name directly (e.g. just "wordpress"), we gonna test this name
if src in raw_app_catalog:
app_name_to_test = src
@ -2274,7 +2251,6 @@ def _app_quality(src: str) -> str:
return "thirdparty"
if app_name_to_test in raw_app_catalog:
state = raw_app_catalog[app_name_to_test].get("state", "notworking")
level = raw_app_catalog[app_name_to_test].get("level", None)
if state in ["working", "validated"]:
@ -2385,7 +2361,6 @@ def _extract_app_from_folder(path: str) -> Tuple[Dict, str]:
def _extract_app_from_gitrepo(
url: str, branch: Optional[str] = None, revision: str = "HEAD", app_info: Dict = {}
) -> Tuple[Dict, str]:
logger.debug("Checking default branch")
try:
@ -2635,7 +2610,6 @@ def _check_manifest_requirements(
def _guess_webapp_path_requirement(app_folder: str) -> str:
# If there's only one "domain" and "path", validate that domain/path
# is an available url and normalize the path.
@ -2681,7 +2655,6 @@ def _guess_webapp_path_requirement(app_folder: str) -> str:
def _validate_webpath_requirement(
args: Dict[str, Any], path_requirement: str, ignore_app=None
) -> None:
domain = args.get("domain")
path = args.get("path")
@ -2729,7 +2702,6 @@ def _get_conflicting_apps(domain, path, ignore_app=None):
def _assert_no_conflicting_apps(domain, path, ignore_app=None, full_domain=False):
conflicts = _get_conflicting_apps(domain, path, ignore_app)
if conflicts:
@ -2748,7 +2720,6 @@ def _assert_no_conflicting_apps(domain, path, ignore_app=None, full_domain=False
def _make_environment_for_app_script(
app, args={}, args_prefix="APP_ARG_", workdir=None, action=None
):
app_setting_path = os.path.join(APPS_SETTING_PATH, app)
manifest = _get_manifest_of_app(app_setting_path)
@ -2777,7 +2748,6 @@ def _make_environment_for_app_script(
if manifest["packaging_format"] >= 2:
env_dict["app"] = app
for setting_name, setting_value in _get_app_settings(app).items():
# Ignore special internal settings like checksum__
# (not a huge deal to load them but idk...)
if setting_name.startswith("checksum__"):
@ -2822,7 +2792,6 @@ def _parse_app_instance_name(app_instance_name: str) -> Tuple[str, int]:
def _next_instance_number_for_app(app):
# Get list of sibling apps, such as {app}, {app}__2, {app}__4
apps = _installed_apps()
sibling_app_ids = [a for a in apps if a == app or a.startswith(f"{app}__")]
@ -2840,7 +2809,6 @@ def _next_instance_number_for_app(app):
def _make_tmp_workdir_for_app(app=None):
# Create parent dir if it doesn't exists yet
if not os.path.exists(APP_TMP_WORKDIRS):
os.makedirs(APP_TMP_WORKDIRS)
@ -2870,12 +2838,10 @@ def _make_tmp_workdir_for_app(app=None):
def unstable_apps():
output = []
deprecated_apps = ["mailman", "ffsync"]
for infos in app_list(full=True)["apps"]:
if (
not infos.get("from_catalog")
or infos.get("from_catalog").get("state")
@ -2891,7 +2857,6 @@ def unstable_apps():
def _assert_system_is_sane_for_app(manifest, when):
from yunohost.service import service_status
logger.debug("Checking that required services are up and running...")
@ -2954,7 +2919,6 @@ def _assert_system_is_sane_for_app(manifest, when):
def app_dismiss_notification(app, name):
assert isinstance(name, str)
name = name.lower()
assert name in ["post_install", "post_upgrade"]

View file

@ -157,7 +157,6 @@ def _read_apps_catalog_list():
def _actual_apps_catalog_api_url(base_url):
return f"{base_url}/v{APPS_CATALOG_API_VERSION}/apps.json"
@ -269,7 +268,6 @@ def _load_apps_catalog():
merged_catalog = {"apps": {}, "categories": [], "antifeatures": []}
for apps_catalog_id in [L["id"] for L in _read_apps_catalog_list()]:
# Let's load the json from cache for this catalog
cache_file = f"{APPS_CATALOG_CACHE}/{apps_catalog_id}.json"
@ -298,7 +296,6 @@ def _load_apps_catalog():
# Add apps from this catalog to the output
for app, info in apps_catalog_content["apps"].items():
# (N.B. : there's a small edge case where multiple apps catalog could be listing the same apps ...
# in which case we keep only the first one found)
if app in merged_catalog["apps"]:

View file

@ -38,14 +38,12 @@ AUTH_DN = "uid={uid},ou=users,dc=yunohost,dc=org"
class Authenticator(BaseAuthenticator):
name = "ldap_admin"
def __init__(self, *args, **kwargs):
pass
def _authenticate_credentials(self, credentials=None):
try:
admins = (
_get_ldap_interface()
@ -125,7 +123,6 @@ class Authenticator(BaseAuthenticator):
con.unbind_s()
def set_session_cookie(self, infos):
from bottle import response
assert isinstance(infos, dict)
@ -145,7 +142,6 @@ class Authenticator(BaseAuthenticator):
)
def get_session_cookie(self, raise_if_no_session_exists=True):
from bottle import request
try:
@ -174,7 +170,6 @@ class Authenticator(BaseAuthenticator):
return infos
def delete_session_cookie(self):
from bottle import response
response.set_cookie("yunohost.admin", "", max_age=-1)

View file

@ -93,7 +93,6 @@ class BackupRestoreTargetsManager:
"""
def __init__(self):
self.targets = {}
self.results = {"system": {}, "apps": {}}
@ -349,7 +348,6 @@ class BackupManager:
if not os.path.isdir(self.work_dir):
mkdir(self.work_dir, 0o750, parents=True)
elif self.is_tmp_work_dir:
logger.debug(
"temporary directory for backup '%s' already exists... attempting to clean it",
self.work_dir,
@ -887,7 +885,6 @@ class RestoreManager:
@property
def success(self):
successful_apps = self.targets.list("apps", include=["Success", "Warning"])
successful_system = self.targets.list("system", include=["Success", "Warning"])
@ -1443,7 +1440,6 @@ class RestoreManager:
existing_groups = user_group_list()["groups"]
for permission_name, permission_infos in permissions.items():
if "allowed" not in permission_infos:
logger.warning(
f"'allowed' key corresponding to allowed groups for permission {permission_name} not found when restoring app {app_instance_name} … You might have to reconfigure permissions yourself."
@ -1547,7 +1543,6 @@ class RestoreManager:
self.targets.set_result("apps", app_instance_name, "Success")
operation_logger.success()
else:
self.targets.set_result("apps", app_instance_name, "Error")
remove_script = os.path.join(app_scripts_in_archive, "remove")
@ -1938,12 +1933,10 @@ class CopyBackupMethod(BackupMethod):
class TarBackupMethod(BackupMethod):
method_name = "tar"
@property
def _archive_file(self):
if isinstance(self.manager, BackupManager) and settings_get(
"misc.backup.backup_compress_tar_archives"
):
@ -2430,7 +2423,6 @@ def backup_list(with_info=False, human_readable=False):
def backup_download(name):
if Moulinette.interface.type != "api":
logger.error(
"This option is only meant for the API/webadmin and doesn't make sense for the command line."
@ -2571,7 +2563,6 @@ def backup_info(name, with_details=False, human_readable=False):
if "size_details" in info.keys():
for category in ["apps", "system"]:
for name, key_info in info[category].items():
if category == "system":
# Stupid legacy fix for weird format between 3.5 and 3.6
if isinstance(key_info, dict):

View file

@ -124,10 +124,8 @@ def certificate_install(domain_list, force=False, no_checks=False, self_signed=F
def _certificate_install_selfsigned(domain_list, force=False):
failed_cert_install = []
for domain in domain_list:
operation_logger = OperationLogger(
"selfsigned_cert_install", [("domain", domain)], args={"force": force}
)
@ -238,7 +236,6 @@ def _certificate_install_letsencrypt(domains, force=False, no_checks=False):
# certificates
if domains == []:
for domain in domain_list()["domains"]:
status = _get_status(domain)
if status["CA_type"] != "selfsigned":
continue
@ -260,7 +257,6 @@ def _certificate_install_letsencrypt(domains, force=False, no_checks=False):
# Actual install steps
failed_cert_install = []
for domain in domains:
if not no_checks:
try:
_check_domain_is_ready_for_ACME(domain)
@ -317,7 +313,6 @@ def certificate_renew(domains, force=False, no_checks=False, email=False):
# certificates
if domains == []:
for domain in domain_list()["domains"]:
# Does it have a Let's Encrypt cert?
status = _get_status(domain)
if status["CA_type"] != "letsencrypt":
@ -342,7 +337,6 @@ def certificate_renew(domains, force=False, no_checks=False, email=False):
# Else, validate the domain list given
else:
for domain in domains:
# Is it in Yunohost domain list?
_assert_domain_exists(domain)
@ -369,7 +363,6 @@ def certificate_renew(domains, force=False, no_checks=False, email=False):
# Actual renew steps
failed_cert_install = []
for domain in domains:
if not no_checks:
try:
_check_domain_is_ready_for_ACME(domain)
@ -468,13 +461,11 @@ investigate :
def _check_acme_challenge_configuration(domain):
domain_conf = f"/etc/nginx/conf.d/{domain}.conf"
return "include /etc/nginx/conf.d/acme-challenge.conf.inc" in read_file(domain_conf)
def _fetch_and_enable_new_certificate(domain, no_checks=False):
if not os.path.exists(ACCOUNT_KEY_FILE):
_generate_account_key()
@ -628,7 +619,6 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder):
def _get_status(domain):
cert_file = os.path.join(CERT_FOLDER, domain, "crt.pem")
if not os.path.isfile(cert_file):
@ -777,7 +767,6 @@ def _backup_current_cert(domain):
def _check_domain_is_ready_for_ACME(domain):
from yunohost.domain import _get_parent_domain_of
from yunohost.dns import _get_dns_zone_for_domain
from yunohost.utils.dns import is_yunohost_dyndns_domain
@ -866,7 +855,6 @@ def _regen_dnsmasq_if_needed():
# For all domain files in DNSmasq conf...
domainsconf = glob.glob("/etc/dnsmasq.d/*.*")
for domainconf in domainsconf:
# Look for the IP, it's in the lines with this format :
# host-record=the.domain.tld,11.22.33.44
for line in open(domainconf).readlines():

View file

@ -35,13 +35,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = []
def run(self):
virt = system_virt()
if virt.lower() == "none":
virt = "bare-metal"
@ -193,7 +191,6 @@ class MyDiagnoser(Diagnoser):
)
def bad_sury_packages(self):
packages_to_check = ["openssl", "libssl1.1", "libssl-dev"]
for package in packages_to_check:
cmd = "dpkg --list | grep '^ii' | grep gbp | grep -q -w %s" % package
@ -209,12 +206,10 @@ class MyDiagnoser(Diagnoser):
yield (package, version_to_downgrade_to)
def backports_in_sources_list(self):
cmd = "grep -q -nr '^ *deb .*-backports' /etc/apt/sources.list*"
return os.system(cmd) == 0
def number_of_recent_auth_failure(self):
# Those syslog facilities correspond to auth and authpriv
# c.f. https://unix.stackexchange.com/a/401398
# and https://wiki.archlinux.org/title/Systemd/Journal#Facility

View file

@ -34,13 +34,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = []
def run(self):
# ############################################################ #
# PING : Check that we can ping outside at least in ipv4 or v6 #
# ############################################################ #
@ -155,7 +153,6 @@ class MyDiagnoser(Diagnoser):
# TODO / FIXME : add some attempt to detect ISP (using whois ?) ?
def can_ping_outside(self, protocol=4):
assert protocol in [
4,
6,
@ -234,7 +231,6 @@ class MyDiagnoser(Diagnoser):
return len(content) == 1 and content[0].split() == ["nameserver", "127.0.0.1"]
def get_public_ip(self, protocol=4):
# FIXME - TODO : here we assume that DNS resolution for ip.yunohost.org is working
# but if we want to be able to diagnose DNS resolution issues independently from
# internet connectivity, we gotta rely on fixed IPs first....

View file

@ -43,13 +43,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = ["ip"]
def run(self):
main_domain = _get_maindomain()
major_domains = domain_list(exclude_subdomains=True)["domains"]
@ -77,7 +75,6 @@ class MyDiagnoser(Diagnoser):
yield report
def check_domain(self, domain, is_main_domain):
if is_special_use_tld(domain):
yield dict(
meta={"domain": domain},
@ -97,13 +94,11 @@ class MyDiagnoser(Diagnoser):
categories = ["basic", "mail", "xmpp", "extra"]
for category in categories:
records = expected_configuration[category]
discrepancies = []
results = {}
for r in records:
id_ = r["type"] + ":" + r["name"]
fqdn = r["name"] + "." + base_dns_zone if r["name"] != "@" else domain
@ -182,7 +177,6 @@ class MyDiagnoser(Diagnoser):
yield output
def get_current_record(self, fqdn, type_):
success, answers = dig(fqdn, type_, resolvers="force_external")
if success != "ok":

View file

@ -25,13 +25,11 @@ from yunohost.settings import settings_get
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = ["ip"]
def run(self):
# TODO: report a warning if port 53 or 5353 is exposed to the outside world...
# This dict is something like :

View file

@ -32,17 +32,14 @@ DIAGNOSIS_SERVER = "diagnosis.yunohost.org"
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = ["ip"]
def run(self):
all_domains = domain_list()["domains"]
domains_to_check = []
for domain in all_domains:
# If the diagnosis location ain't defined, can't do diagnosis,
# probably because nginx conf manually modified...
nginx_conf = "/etc/nginx/conf.d/%s.conf" % domain
@ -119,7 +116,6 @@ class MyDiagnoser(Diagnoser):
pass
def test_http(self, domains, ipversions):
results = {}
for ipversion in ipversions:
try:
@ -144,7 +140,6 @@ class MyDiagnoser(Diagnoser):
return
for domain in domains:
# i18n: diagnosis_http_bad_status_code
# i18n: diagnosis_http_connection_error
# i18n: diagnosis_http_timeout

View file

@ -39,13 +39,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 600
dependencies: List[str] = ["ip"]
def run(self):
self.ehlo_domain = _get_maindomain()
self.mail_domains = domain_list()["domains"]
self.ipversions, self.ips = self.get_ips_checked()

View file

@ -24,17 +24,14 @@ from yunohost.service import service_status
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies: List[str] = []
def run(self):
all_result = service_status()
for service, result in sorted(all_result.items()):
item = dict(
meta={"service": service},
data={

View file

@ -28,13 +28,11 @@ from yunohost.diagnosis import Diagnoser
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies: List[str] = []
def run(self):
MB = 1024**2
GB = MB * 1024
@ -189,7 +187,6 @@ class MyDiagnoser(Diagnoser):
return []
def analyzed_kern_log():
cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true'
out = check_output(cmd)
lines = out.split("\n") if out else []

View file

@ -27,13 +27,11 @@ from moulinette.utils.filesystem import read_file
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies: List[str] = []
def run(self):
regenconf_modified_files = list(self.manually_modified_files())
if not regenconf_modified_files:
@ -82,7 +80,6 @@ class MyDiagnoser(Diagnoser):
)
def manually_modified_files(self):
for category, infos in _get_regenconf_infos().items():
for path, hash_ in infos["conffiles"].items():
if hash_ != _calculate_hash(path):

View file

@ -25,13 +25,11 @@ from yunohost.diagnosis import Diagnoser
class MyDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
cache_duration = 300
dependencies: List[str] = []
def run(self):
apps = app_list(full=True)["apps"]
for app in apps:
app["issues"] = list(self.issues(app))
@ -44,7 +42,6 @@ class MyDiagnoser(Diagnoser):
)
else:
for app in apps:
if not app["issues"]:
continue
@ -62,7 +59,6 @@ class MyDiagnoser(Diagnoser):
)
def issues(self, app):
# Check quality level in catalog
if not app.get("from_catalog") or app["from_catalog"].get("state") != "working":

View file

@ -45,7 +45,6 @@ def diagnosis_list():
def diagnosis_get(category, item):
# Get all the categories
all_categories_names = _list_diagnosis_categories()
@ -69,7 +68,6 @@ def diagnosis_get(category, item):
def diagnosis_show(
categories=[], issues=False, full=False, share=False, human_readable=False
):
if not os.path.exists(DIAGNOSIS_CACHE):
logger.warning(m18n.n("diagnosis_never_ran_yet"))
return
@ -90,7 +88,6 @@ def diagnosis_show(
# Fetch all reports
all_reports = []
for category in categories:
try:
report = Diagnoser.get_cached_report(category)
except Exception as e:
@ -139,7 +136,6 @@ def diagnosis_show(
def _dump_human_readable_reports(reports):
output = ""
for report in reports:
@ -159,7 +155,6 @@ def _dump_human_readable_reports(reports):
def diagnosis_run(
categories=[], force=False, except_if_never_ran_yet=False, email=False
):
if (email or except_if_never_ran_yet) and not os.path.exists(DIAGNOSIS_CACHE):
return
@ -263,7 +258,6 @@ def _diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
return {"ignore_filters": configuration.get("ignore_filters", {})}
def validate_filter_criterias(filter_):
# Get all the categories
all_categories_names = _list_diagnosis_categories()
@ -286,7 +280,6 @@ def _diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
return category, criterias
if add_filter:
category, criterias = validate_filter_criterias(add_filter)
# Fetch current issues for the requested category
@ -320,7 +313,6 @@ def _diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
return
if remove_filter:
category, criterias = validate_filter_criterias(remove_filter)
# Make sure the subdicts/lists exists
@ -394,12 +386,10 @@ def add_ignore_flag_to_issues(report):
class Diagnoser:
def __init__(self):
self.cache_file = Diagnoser.cache_file(self.id_)
self.description = Diagnoser.get_description(self.id_)
def cached_time_ago(self):
if not os.path.exists(self.cache_file):
return 99999999
return time.time() - os.path.getmtime(self.cache_file)
@ -410,7 +400,6 @@ class Diagnoser:
return write_to_json(self.cache_file, report)
def diagnose(self, force=False):
if not force and self.cached_time_ago() < self.cache_duration:
logger.debug(f"Cache still valid : {self.cache_file}")
logger.info(
@ -548,7 +537,6 @@ class Diagnoser:
@staticmethod
def i18n(report, force_remove_html_tags=False):
# "Render" the strings with m18n.n
# N.B. : we do those m18n.n right now instead of saving the already-translated report
# because we can't be sure we'll redisplay the infos with the same locale as it
@ -558,7 +546,6 @@ class Diagnoser:
report["description"] = Diagnoser.get_description(report["id"])
for item in report["items"]:
# For the summary and each details, we want to call
# m18n() on the string, with the appropriate data for string
# formatting which can come from :
@ -597,7 +584,6 @@ class Diagnoser:
@staticmethod
def remote_diagnosis(uri, data, ipversion, timeout=30):
# Lazy loading for performance
import requests
import socket
@ -646,7 +632,6 @@ class Diagnoser:
def _list_diagnosis_categories():
paths = glob.glob(os.path.dirname(__file__) + "/diagnosers/??-*.py")
names = [
name.split("-")[-1]
@ -657,7 +642,6 @@ def _list_diagnosis_categories():
def _load_diagnoser(diagnoser_name):
logger.debug(f"Loading diagnoser {diagnoser_name}")
paths = glob.glob(os.path.dirname(__file__) + f"/diagnosers/??-{diagnoser_name}.py")

View file

@ -169,7 +169,6 @@ def _build_dns_conf(base_domain, include_empty_AAAA_if_no_ipv6=False):
base_dns_zone = _get_dns_zone_for_domain(base_domain)
for domain, settings in domains_settings.items():
# Domain # Base DNS zone # Basename # Suffix #
# ------------------ # ----------------- # --------- # -------- #
# domain.tld # domain.tld # @ # #
@ -462,7 +461,6 @@ def _get_dns_zone_for_domain(domain):
# We don't wan't to do A NS request on the tld
for parent in parent_list[0:-1]:
# Check if there's a NS record for that domain
answer = dig(parent, rdtype="NS", full_answers=True, resolvers="force_external")
@ -503,7 +501,6 @@ def _get_relative_name_for_dns_zone(domain, base_dns_zone):
def _get_registrar_config_section(domain):
from lexicon.providers.auto import _relevant_provider_for_domain
registrar_infos = {
@ -517,7 +514,6 @@ def _get_registrar_config_section(domain):
# If parent domain exists in yunohost
parent_domain = _get_parent_domain_of(domain, topest=True)
if parent_domain:
# Dirty hack to have a link on the webadmin
if Moulinette.interface.type == "api":
parent_domain_link = f"[{parent_domain}](#/domains/{parent_domain}/dns)"
@ -572,7 +568,6 @@ def _get_registrar_config_section(domain):
}
)
else:
registrar_infos["registrar"] = OrderedDict(
{
"type": "alert",
@ -606,7 +601,6 @@ def _get_registrar_config_section(domain):
def _get_registar_settings(domain):
_assert_domain_exists(domain)
settings = domain_config_get(domain, key="dns.registrar", export=True)
@ -670,7 +664,6 @@ def domain_dns_push(operation_logger, domain, dry_run=False, force=False, purge=
wanted_records = []
for records in _build_dns_conf(domain).values():
for record in records:
# Make sure the name is a FQDN
name = (
f"{record['name']}.{base_dns_zone}"
@ -745,7 +738,6 @@ def domain_dns_push(operation_logger, domain, dry_run=False, force=False, purge=
]
for record in current_records:
# Try to get rid of weird stuff like ".domain.tld" or "@.domain.tld"
record["name"] = record["name"].strip("@").strip(".")
@ -795,7 +787,6 @@ def domain_dns_push(operation_logger, domain, dry_run=False, force=False, purge=
comparison[(record["type"], record["name"])]["wanted"].append(record)
for type_and_name, records in comparison.items():
#
# Step 1 : compute a first "diff" where we remove records which are the same on both sides
#
@ -939,9 +930,7 @@ def domain_dns_push(operation_logger, domain, dry_run=False, force=False, purge=
results = {"warnings": [], "errors": []}
for action in ["delete", "create", "update"]:
for record in changes[action]:
relative_name = _get_relative_name_for_dns_zone(
record["name"], base_dns_zone
)
@ -1026,7 +1015,6 @@ def _set_managed_dns_records_hashes(domain: str, hashes: list) -> None:
def _hash_dns_record(record: dict) -> int:
fields = ["name", "type", "content"]
record_ = {f: record.get(f) for f in fields}

View file

@ -187,7 +187,6 @@ def _assert_domain_exists(domain):
def _list_subdomains_of(parent_domain):
_assert_domain_exists(parent_domain)
out = []
@ -199,7 +198,6 @@ def _list_subdomains_of(parent_domain):
def _get_parent_domain_of(domain, return_self=False, topest=False):
domains = _get_domains(exclude_subdomains=topest)
domain_ = domain
@ -248,7 +246,6 @@ def domain_add(operation_logger, domain, dyndns=False):
# DynDNS domain
if dyndns:
from yunohost.utils.dns import is_yunohost_dyndns_domain
from yunohost.dyndns import _guess_current_dyndns_domain
@ -589,7 +586,6 @@ class DomainConfigPanel(ConfigPanel):
regen_conf(names=stuff_to_regen_conf)
def _get_toml(self):
toml = super()._get_toml()
toml["feature"]["xmpp"]["xmpp"]["default"] = (
@ -611,7 +607,6 @@ class DomainConfigPanel(ConfigPanel):
# Cert stuff
if not filter_key or filter_key[0] == "cert":
from yunohost.certificate import certificate_status
status = certificate_status([self.entity], full=True)["certificates"][
@ -638,7 +633,6 @@ class DomainConfigPanel(ConfigPanel):
return toml
def _load_current_values(self):
# TODO add mechanism to share some settings with other domains on the same zone
super()._load_current_values()
@ -656,7 +650,6 @@ class DomainConfigPanel(ConfigPanel):
def domain_action_run(domain, action, args=None):
import urllib.parse
if action == "cert.cert.cert_install":
@ -671,7 +664,6 @@ def domain_action_run(domain, action, args=None):
def _get_domain_settings(domain: str) -> dict:
_assert_domain_exists(domain)
if os.path.exists(f"{DOMAIN_SETTINGS_DIR}/{domain}.yml"):
@ -681,7 +673,6 @@ def _get_domain_settings(domain: str) -> dict:
def _set_domain_settings(domain: str, settings: dict) -> None:
_assert_domain_exists(domain)
write_to_yaml(f"{DOMAIN_SETTINGS_DIR}/{domain}.yml", settings)

View file

@ -227,7 +227,6 @@ def dyndns_update(
for dns_auth in DYNDNS_DNS_AUTH:
for type_ in ["A", "AAAA"]:
ok, result = dig(dns_auth, type_)
if ok == "ok" and len(result) and result[0]:
auth_resolvers.append(result[0])
@ -238,7 +237,6 @@ def dyndns_update(
)
def resolve_domain(domain, rdtype):
ok, result = dig(domain, rdtype, resolvers=auth_resolvers)
if ok == "ok":
return result[0] if len(result) else None

View file

@ -415,7 +415,6 @@ def firewall_upnp(action="status", no_refresh=False):
for protocol in ["TCP", "UDP"]:
if protocol + "_TO_CLOSE" in firewall["uPnP"]:
for port in firewall["uPnP"][protocol + "_TO_CLOSE"]:
if not isinstance(port, int):
# FIXME : how should we handle port ranges ?
logger.warning("Can't use UPnP to close '%s'" % port)
@ -430,7 +429,6 @@ def firewall_upnp(action="status", no_refresh=False):
firewall["uPnP"][protocol + "_TO_CLOSE"] = []
for port in firewall["uPnP"][protocol]:
if not isinstance(port, int):
# FIXME : how should we handle port ranges ?
logger.warning("Can't use UPnP to open '%s'" % port)

View file

@ -339,7 +339,6 @@ def hook_exec(
raise YunohostError("file_does_not_exist", path=path)
def is_relevant_warning(msg):
# Ignore empty warning messages...
if not msg:
return False
@ -389,7 +388,6 @@ def hook_exec(
def _hook_exec_bash(path, args, chdir, env, user, return_format, loggers):
from moulinette.utils.process import call_async_output
# Construct command variables
@ -477,7 +475,6 @@ def _hook_exec_bash(path, args, chdir, env, user, return_format, loggers):
def _hook_exec_python(path, args, env, loggers):
dir_ = os.path.dirname(path)
name = os.path.splitext(os.path.basename(path))[0]
@ -497,7 +494,6 @@ def _hook_exec_python(path, args, env, loggers):
def hook_exec_with_script_debug_if_failure(*args, **kwargs):
operation_logger = kwargs.pop("operation_logger")
error_message_if_failed = kwargs.pop("error_message_if_failed")
error_message_if_script_failed = kwargs.pop("error_message_if_script_failed")

View file

@ -95,7 +95,6 @@ def log_list(limit=None, with_details=False, with_suboperations=False):
logs = logs[: limit * 5]
for log in logs:
base_filename = log[: -len(METADATA_FILE_EXT)]
md_path = os.path.join(OPERATIONS_PATH, log)
@ -264,7 +263,6 @@ def log_show(
return
for filename in os.listdir(OPERATIONS_PATH):
if not filename.endswith(METADATA_FILE_EXT):
continue
@ -438,7 +436,6 @@ class RedactingFormatter(Formatter):
return msg
def identify_data_to_redact(self, record):
# Wrapping this in a try/except because we don't want this to
# break everything in case it fails miserably for some reason :s
try:
@ -497,7 +494,6 @@ class OperationLogger:
os.makedirs(self.path)
def parent_logger(self):
# If there are other operation logger instances
for instance in reversed(self._instances):
# Is one of these operation logger started but not yet done ?
@ -732,7 +728,6 @@ class OperationLogger:
self.error(m18n.n("log_operation_unit_unclosed_properly"))
def dump_script_log_extract_for_debugging(self):
with open(self.log_path, "r") as f:
lines = f.readlines()
@ -774,7 +769,6 @@ class OperationLogger:
def _get_datetime_from_name(name):
# Filenames are expected to follow the format:
# 20200831-170740-short_description-and-stuff

View file

@ -72,13 +72,11 @@ def _backup_pip_freeze_for_python_app_venvs():
class MyMigration(Migration):
"Upgrade the system to Debian Bullseye and Yunohost 11.x"
mode = "manual"
def run(self):
self.check_assertions()
logger.info(m18n.n("migration_0021_start"))
@ -389,7 +387,6 @@ class MyMigration(Migration):
return int(get_ynh_package_version("yunohost")["version"].split(".")[0])
def check_assertions(self):
# Be on buster (10.x) and yunohost 4.x
# NB : we do both check to cover situations where the upgrade crashed
# in the middle and debian version could be > 9.x but yunohost package
@ -453,7 +450,6 @@ class MyMigration(Migration):
@property
def disclaimer(self):
# Avoid having a super long disclaimer + uncessary check if we ain't
# on buster / yunohost 4.x anymore
# NB : we do both check to cover situations where the upgrade crashed
@ -494,7 +490,6 @@ class MyMigration(Migration):
return message
def patch_apt_sources_list(self):
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
if os.path.exists("/etc/apt/sources.list"):
sources_list.append("/etc/apt/sources.list")
@ -516,7 +511,6 @@ class MyMigration(Migration):
os.system(command)
def get_apps_equivs_packages(self):
command = (
"dpkg --get-selections"
" | grep -v deinstall"

View file

@ -27,7 +27,6 @@ MIGRATION_COMMENT = (
class MyMigration(Migration):
"Migrate php7.3-fpm 'pool' conf files to php7.4"
dependencies = ["migrate_to_bullseye"]
@ -43,7 +42,6 @@ class MyMigration(Migration):
oldphp_pool_files = [f for f in oldphp_pool_files if f != "www.conf"]
for pf in oldphp_pool_files:
# Copy the files to the php7.3 pool
src = "{}/{}".format(OLDPHP_POOLS, pf)
dest = "{}/{}".format(NEWPHP_POOLS, pf)

View file

@ -13,13 +13,11 @@ logger = getActionLogger("yunohost.migration")
class MyMigration(Migration):
"Migrate DBs from Postgresql 11 to 13 after migrating to Bullseye"
dependencies = ["migrate_to_bullseye"]
def run(self):
if (
os.system(
'grep -A10 "ynh-deps" /var/lib/dpkg/status | grep -E "Package:|Depends:" | grep -B1 postgresql'
@ -63,7 +61,6 @@ class MyMigration(Migration):
self.runcmd("systemctl start postgresql")
def package_is_installed(self, package_name):
(returncode, out, err) = self.runcmd(
"dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name),
raise_on_errors=False,
@ -71,7 +68,6 @@ class MyMigration(Migration):
return returncode == 0
def runcmd(self, cmd, raise_on_errors=True):
logger.debug("Running command: " + cmd)
p = subprocess.Popen(

View file

@ -14,7 +14,6 @@ VENV_REQUIREMENTS_SUFFIX = ".requirements_backup_for_bullseye_upgrade.txt"
def extract_app_from_venv_path(venv_path):
venv_path = venv_path.replace("/var/www/", "")
venv_path = venv_path.replace("/opt/yunohost/", "")
venv_path = venv_path.replace("/opt/", "")
@ -137,13 +136,11 @@ class MyMigration(Migration):
return msg
def run(self):
if self.mode == "auto":
return
venvs = _get_all_venvs("/opt/") + _get_all_venvs("/var/www/")
for venv in venvs:
app_corresponding_to_venv = extract_app_from_venv_path(venv)
# Search for ignore apps

View file

@ -14,7 +14,6 @@ OLD_SETTINGS_PATH = "/etc/yunohost/settings.json"
class MyMigration(Migration):
"Migrate old global settings to the new ConfigPanel global settings"
dependencies = ["migrate_to_bullseye"]

View file

@ -21,7 +21,6 @@ class MyMigration(Migration):
@Migration.ldap_migration
def run(self, *args):
from yunohost.user import (
user_list,
user_info,

View file

@ -79,7 +79,6 @@ def user_permission_list(
permissions = {}
for infos in permissions_infos:
name = infos["cn"][0]
app = name.split(".")[0]
@ -654,7 +653,6 @@ def permission_sync_to_user():
permissions = user_permission_list(full=True)["permissions"]
for permission_name, permission_infos in permissions.items():
# These are the users currently allowed because there's an 'inheritPermission' object corresponding to it
currently_allowed_users = set(permission_infos["corresponding_users"])
@ -740,7 +738,6 @@ def _update_ldap_group_permission(
update["isProtected"] = [str(protected).upper()]
if show_tile is not None:
if show_tile is True:
if not existing_permission["url"]:
logger.warning(
@ -876,7 +873,6 @@ def _validate_and_sanitize_permission_url(url, app_base_path, app):
raise YunohostValidationError("invalid_regex", regex=regex)
if url.startswith("re:"):
# regex without domain
# we check for the first char after 're:'
if url[3] in ["/", "^", "\\"]:

View file

@ -77,7 +77,6 @@ def regen_conf(
for category, conf_files in pending_conf.items():
for system_path, pending_path in conf_files.items():
pending_conf[category][system_path] = {
"pending_conf": pending_path,
"diff": _get_files_diff(system_path, pending_path, True),
@ -595,7 +594,6 @@ def _update_conf_hashes(category, hashes):
def _force_clear_hashes(paths):
categories = _get_regenconf_infos()
for path in paths:
for category in categories.keys():
@ -675,7 +673,6 @@ def _process_regen_conf(system_conf, new_conf=None, save=True):
def manually_modified_files():
output = []
regenconf_categories = _get_regenconf_infos()
for category, infos in regenconf_categories.items():
@ -690,7 +687,6 @@ def manually_modified_files():
def manually_modified_files_compared_to_debian_default(
ignore_handled_by_regenconf=False,
):
# from https://serverfault.com/a/90401
files = check_output(
"dpkg-query -W -f='${Conffiles}\n' '*' \

View file

@ -249,12 +249,10 @@ def service_reload_or_restart(names, test_conf=True):
services = _get_services()
for name in names:
logger.debug(f"Reloading service {name}")
test_conf_cmd = services.get(name, {}).get("test_conf")
if test_conf and test_conf_cmd:
p = subprocess.Popen(
test_conf_cmd,
shell=True,
@ -393,7 +391,6 @@ def _get_service_information_from_systemd(service):
def _get_and_format_service_status(service, infos):
systemd_service = infos.get("actual_systemd_service", service)
raw_status, raw_service = _get_service_information_from_systemd(systemd_service)
@ -414,7 +411,6 @@ def _get_and_format_service_status(service, infos):
# If no description was there, try to get it from the .json locales
if not description:
translation_key = f"service_description_{service}"
if m18n.key_exists(translation_key):
description = m18n.n(translation_key)
@ -521,7 +517,6 @@ def service_log(name, number=50):
result["journalctl"] = _get_journalctl_logs(name, number).splitlines()
for log_path in log_list:
if not os.path.exists(log_path):
continue
@ -620,7 +615,6 @@ def _run_service_command(action, service):
def _give_lock(action, service, p):
# Depending of the action, systemctl calls the PID differently :/
if action == "start" or action == "restart":
systemctl_PID_name = "MainPID"
@ -744,7 +738,6 @@ def _save_services(services):
diff = {}
for service_name, service_infos in services.items():
# Ignore php-fpm services, they are to be added dynamically by the core,
# but not actually saved
if service_name.startswith("php") and service_name.endswith("-fpm"):

View file

@ -59,7 +59,6 @@ def settings_get(key="", full=False, export=False):
def settings_list(full=False):
settings = settings_get(full=full)
if full:
@ -126,7 +125,6 @@ class SettingsConfigPanel(ConfigPanel):
super().__init__("settings")
def _apply(self):
root_password = self.new_values.pop("root_password", None)
root_password_confirm = self.new_values.pop("root_password_confirm", None)
passwordless_sudo = self.new_values.pop("passwordless_sudo", None)
@ -141,7 +139,6 @@ class SettingsConfigPanel(ConfigPanel):
assert all(v not in self.future_values for v in self.virtual_settings)
if root_password and root_password.strip():
if root_password != root_password_confirm:
raise YunohostValidationError("password_confirmation_not_the_same")
@ -173,7 +170,6 @@ class SettingsConfigPanel(ConfigPanel):
raise
def _get_toml(self):
toml = super()._get_toml()
# Dynamic choice list for portal themes
@ -187,7 +183,6 @@ class SettingsConfigPanel(ConfigPanel):
return toml
def _load_current_values(self):
super()._load_current_values()
# Specific logic for those settings who are "virtual" settings
@ -207,7 +202,6 @@ class SettingsConfigPanel(ConfigPanel):
self.values["passwordless_sudo"] = False
def get(self, key="", mode="classic"):
result = super().get(key=key, mode=mode)
if mode == "full":

View file

@ -51,7 +51,6 @@ old_translate = moulinette.core.Translator.translate
def new_translate(self, key, *args, **kwargs):
if key not in self._translations[self.default_locale].keys():
raise KeyError("Unable to retrieve key %s for default locale !" % key)
@ -67,7 +66,6 @@ moulinette.core.Translator.translate = new_translate
def pytest_cmdline_main(config):
import sys
sys.path.insert(0, "/usr/lib/moulinette/")
@ -76,7 +74,6 @@ def pytest_cmdline_main(config):
yunohost.init(debug=config.option.yunodebug)
class DummyInterface:
type = "cli"
def prompt(self, *args, **kwargs):

View file

@ -44,7 +44,6 @@ class AnyStringWith(str):
def setup_function(function):
# Clear apps catalog cache
shutil.rmtree(APPS_CATALOG_CACHE, ignore_errors=True)
@ -54,7 +53,6 @@ def setup_function(function):
def teardown_function(function):
# Clear apps catalog cache
# Otherwise when using apps stuff after running the test,
# we'll still have the dummy unusable list
@ -67,7 +65,6 @@ def teardown_function(function):
def test_apps_catalog_init(mocker):
# Cache is empty
assert not glob.glob(APPS_CATALOG_CACHE + "/*")
# Conf doesn't exist yet
@ -91,7 +88,6 @@ def test_apps_catalog_init(mocker):
def test_apps_catalog_emptylist():
# Initialize ...
_initialize_apps_catalog_system()
@ -104,7 +100,6 @@ def test_apps_catalog_emptylist():
def test_apps_catalog_update_nominal(mocker):
# Initialize ...
_initialize_apps_catalog_system()
@ -113,7 +108,6 @@ def test_apps_catalog_update_nominal(mocker):
# Update
with requests_mock.Mocker() as m:
_actual_apps_catalog_api_url,
# Mock the server response with a dummy apps catalog
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
@ -139,12 +133,10 @@ def test_apps_catalog_update_nominal(mocker):
def test_apps_catalog_update_404(mocker):
# Initialize ...
_initialize_apps_catalog_system()
with requests_mock.Mocker() as m:
# 404 error
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, status_code=404)
@ -155,12 +147,10 @@ def test_apps_catalog_update_404(mocker):
def test_apps_catalog_update_timeout(mocker):
# Initialize ...
_initialize_apps_catalog_system()
with requests_mock.Mocker() as m:
# Timeout
m.register_uri(
"GET", APPS_CATALOG_DEFAULT_URL_FULL, exc=requests.exceptions.ConnectTimeout
@ -173,12 +163,10 @@ def test_apps_catalog_update_timeout(mocker):
def test_apps_catalog_update_sslerror(mocker):
# Initialize ...
_initialize_apps_catalog_system()
with requests_mock.Mocker() as m:
# SSL error
m.register_uri(
"GET", APPS_CATALOG_DEFAULT_URL_FULL, exc=requests.exceptions.SSLError
@ -191,12 +179,10 @@ def test_apps_catalog_update_sslerror(mocker):
def test_apps_catalog_update_corrupted(mocker):
# Initialize ...
_initialize_apps_catalog_system()
with requests_mock.Mocker() as m:
# Corrupted json
m.register_uri(
"GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG[:-2]
@ -209,7 +195,6 @@ def test_apps_catalog_update_corrupted(mocker):
def test_apps_catalog_load_with_empty_cache(mocker):
# Initialize ...
_initialize_apps_catalog_system()
@ -218,7 +203,6 @@ def test_apps_catalog_load_with_empty_cache(mocker):
# Update
with requests_mock.Mocker() as m:
# Mock the server response with a dummy apps catalog
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
@ -237,7 +221,6 @@ def test_apps_catalog_load_with_empty_cache(mocker):
def test_apps_catalog_load_with_conflicts_between_lists(mocker):
# Initialize ...
_initialize_apps_catalog_system()
@ -253,7 +236,6 @@ def test_apps_catalog_load_with_conflicts_between_lists(mocker):
# Update
with requests_mock.Mocker() as m:
# Mock the server response with a dummy apps catalog
# + the same apps catalog for the second list
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
@ -277,13 +259,11 @@ def test_apps_catalog_load_with_conflicts_between_lists(mocker):
def test_apps_catalog_load_with_oudated_api_version(mocker):
# Initialize ...
_initialize_apps_catalog_system()
# Update
with requests_mock.Mocker() as m:
mocker.spy(m18n, "n")
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
_update_apps_catalog()
@ -300,7 +280,6 @@ def test_apps_catalog_load_with_oudated_api_version(mocker):
# Update
with requests_mock.Mocker() as m:
# Mock the server response with a dummy apps catalog
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)

View file

@ -25,17 +25,14 @@ from yunohost.utils.error import YunohostError, YunohostValidationError
def setup_function(function):
clean()
def teardown_function(function):
clean()
def clean():
# Make sure we have a ssowat
os.system("mkdir -p /etc/ssowat/")
app_ssowatconf()
@ -43,7 +40,6 @@ def clean():
test_apps = ["config_app", "legacy_app"]
for test_app in test_apps:
if _is_installed(test_app):
app_remove(test_app)
@ -66,7 +62,6 @@ def clean():
@pytest.fixture()
def legacy_app(request):
main_domain = _get_maindomain()
app_install(
@ -85,7 +80,6 @@ def legacy_app(request):
@pytest.fixture()
def config_app(request):
app_install(
os.path.join(get_test_apps_dir(), "config_app_ynh"),
args="",
@ -101,7 +95,6 @@ def config_app(request):
def test_app_config_get(config_app):
user_create("alice", _get_maindomain(), "test123Ynh", fullname="Alice White")
assert isinstance(app_config_get(config_app), dict)
@ -115,13 +108,11 @@ def test_app_config_get(config_app):
def test_app_config_nopanel(legacy_app):
with pytest.raises(YunohostValidationError):
app_config_get(legacy_app)
def test_app_config_get_nonexistentstuff(config_app):
with pytest.raises(YunohostValidationError):
app_config_get("nonexistent")
@ -140,7 +131,6 @@ def test_app_config_get_nonexistentstuff(config_app):
def test_app_config_regular_setting(config_app):
assert app_config_get(config_app, "main.components.boolean") == 0
app_config_set(config_app, "main.components.boolean", "no")
@ -160,7 +150,6 @@ def test_app_config_regular_setting(config_app):
def test_app_config_bind_on_file(config_app):
# c.f. conf/test.php in the config app
assert '$arg5= "Arg5 value";' in read_file("/var/www/config_app/test.php")
assert app_config_get(config_app, "bind.variable.arg5") == "Arg5 value"
@ -184,7 +173,6 @@ def test_app_config_bind_on_file(config_app):
def test_app_config_custom_validator(config_app):
# c.f. the config script
# arg8 is a password that must be at least 8 chars
assert not os.path.exists("/var/www/config_app/password")
@ -198,7 +186,6 @@ def test_app_config_custom_validator(config_app):
def test_app_config_custom_set(config_app):
assert not os.path.exists("/var/www/config_app/password")
assert app_setting(config_app, "arg8") is None

View file

@ -17,7 +17,6 @@ dummyfile = "/tmp/dummyappresource-testapp"
class DummyAppResource(AppResource):
type = "dummy"
default_properties = {
@ -26,14 +25,12 @@ class DummyAppResource(AppResource):
}
def provision_or_update(self, context):
open(self.file, "w").write(self.content)
if self.content == "forbiddenvalue":
raise Exception("Emeged you used the forbidden value!1!£&")
def deprovision(self, context):
os.system(f"rm -f {self.file}")
@ -41,7 +38,6 @@ AppResourceClassesByType["dummy"] = DummyAppResource
def setup_function(function):
clean()
os.system("mkdir /etc/yunohost/apps/testapp")
@ -51,12 +47,10 @@ def setup_function(function):
def teardown_function(function):
clean()
def clean():
os.system(f"rm -f {dummyfile}")
os.system("rm -rf /etc/yunohost/apps/testapp")
os.system("rm -rf /var/www/testapp")
@ -70,7 +64,6 @@ def clean():
def test_provision_dummy():
current = {"resources": {}}
wanted = {"resources": {"dummy": {}}}
@ -82,7 +75,6 @@ def test_provision_dummy():
def test_deprovision_dummy():
current = {"resources": {"dummy": {}}}
wanted = {"resources": {}}
@ -96,7 +88,6 @@ def test_deprovision_dummy():
def test_provision_dummy_nondefaultvalue():
current = {"resources": {}}
wanted = {"resources": {"dummy": {"content": "bar"}}}
@ -108,7 +99,6 @@ def test_provision_dummy_nondefaultvalue():
def test_update_dummy():
current = {"resources": {"dummy": {}}}
wanted = {"resources": {"dummy": {"content": "bar"}}}
@ -122,7 +112,6 @@ def test_update_dummy():
def test_update_dummy_failwithrollback():
current = {"resources": {"dummy": {}}}
wanted = {"resources": {"dummy": {"content": "forbiddenvalue"}}}
@ -137,7 +126,6 @@ def test_update_dummy_failwithrollback():
def test_resource_system_user():
r = AppResourceClassesByType["system_user"]
conf = {}
@ -161,7 +149,6 @@ def test_resource_system_user():
def test_resource_install_dir():
r = AppResourceClassesByType["install_dir"]
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
@ -196,7 +183,6 @@ def test_resource_install_dir():
def test_resource_data_dir():
r = AppResourceClassesByType["data_dir"]
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
@ -228,7 +214,6 @@ def test_resource_data_dir():
def test_resource_ports():
r = AppResourceClassesByType["ports"]
conf = {}
@ -244,7 +229,6 @@ def test_resource_ports():
def test_resource_ports_several():
r = AppResourceClassesByType["ports"]
conf = {"main": {"default": 12345}, "foobar": {"default": 23456}}
@ -263,7 +247,6 @@ def test_resource_ports_several():
def test_resource_ports_firewall():
r = AppResourceClassesByType["ports"]
conf = {"main": {"default": 12345}}
@ -283,7 +266,6 @@ def test_resource_ports_firewall():
def test_resource_database():
r = AppResourceClassesByType["database"]
conf = {"type": "mysql"}
@ -308,7 +290,6 @@ def test_resource_database():
def test_resource_apt():
r = AppResourceClassesByType["apt"]
conf = {
"packages": "nyancat, sl",
@ -356,7 +337,6 @@ def test_resource_apt():
def test_resource_permissions():
maindomain = _get_maindomain()
os.system(f"echo 'domain: {maindomain}' >> /etc/yunohost/apps/testapp/settings.yml")
os.system("echo 'path: /testapp' >> /etc/yunohost/apps/testapp/settings.yml")

View file

@ -28,17 +28,14 @@ from yunohost.permission import user_permission_list, permission_delete
def setup_function(function):
clean()
def teardown_function(function):
clean()
def clean():
# Make sure we have a ssowat
os.system("mkdir -p /etc/ssowat/")
app_ssowatconf()
@ -53,7 +50,6 @@ def clean():
]
for test_app in test_apps:
if _is_installed(test_app):
app_remove(test_app)
@ -95,7 +91,6 @@ def check_permission_for_apps_call():
@pytest.fixture(scope="module")
def secondary_domain(request):
if "example.test" not in domain_list()["domains"]:
domain_add("example.test")
@ -113,7 +108,6 @@ def secondary_domain(request):
def app_expected_files(domain, app):
yield "/etc/nginx/conf.d/{}.d/{}.conf".format(domain, app)
if app.startswith("legacy_app"):
yield "/var/www/%s/index.html" % app
@ -127,21 +121,18 @@ def app_expected_files(domain, app):
def app_is_installed(domain, app):
return _is_installed(app) and all(
os.path.exists(f) for f in app_expected_files(domain, app)
)
def app_is_not_installed(domain, app):
return not _is_installed(app) and not all(
os.path.exists(f) for f in app_expected_files(domain, app)
)
def app_is_exposed_on_http(domain, path, message_in_page):
try:
r = requests.get(
"https://127.0.0.1" + path + "/",
@ -155,7 +146,6 @@ def app_is_exposed_on_http(domain, path, message_in_page):
def install_legacy_app(domain, path, public=True):
app_install(
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
args="domain={}&path={}&is_public={}".format(domain, path, 1 if public else 0),
@ -164,7 +154,6 @@ def install_legacy_app(domain, path, public=True):
def install_manifestv2_app(domain, path, public=True):
app_install(
os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"),
args="domain={}&path={}&init_main_permission={}".format(
@ -175,7 +164,6 @@ def install_manifestv2_app(domain, path, public=True):
def install_full_domain_app(domain):
app_install(
os.path.join(get_test_apps_dir(), "full_domain_app_ynh"),
args="domain=%s" % domain,
@ -184,7 +172,6 @@ def install_full_domain_app(domain):
def install_break_yo_system(domain, breakwhat):
app_install(
os.path.join(get_test_apps_dir(), "break_yo_system_ynh"),
args="domain={}&breakwhat={}".format(domain, breakwhat),
@ -193,7 +180,6 @@ def install_break_yo_system(domain, breakwhat):
def test_legacy_app_install_main_domain():
main_domain = _get_maindomain()
install_legacy_app(main_domain, "/legacy")
@ -213,7 +199,6 @@ def test_legacy_app_install_main_domain():
def test_legacy_app_manifest_preinstall():
m = app_manifest(os.path.join(get_test_apps_dir(), "legacy_app_ynh"))
# v1 manifesto are expected to have been autoconverted to v2
@ -231,7 +216,6 @@ def test_legacy_app_manifest_preinstall():
def test_manifestv2_app_manifest_preinstall():
m = app_manifest(os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"))
assert "id" in m
@ -258,7 +242,6 @@ def test_manifestv2_app_manifest_preinstall():
def test_manifestv2_app_install_main_domain():
main_domain = _get_maindomain()
install_manifestv2_app(main_domain, "/manifestv2")
@ -278,7 +261,6 @@ def test_manifestv2_app_install_main_domain():
def test_manifestv2_app_info_postinstall():
main_domain = _get_maindomain()
install_manifestv2_app(main_domain, "/manifestv2")
m = app_info("manifestv2_app", full=True)["manifest"]
@ -308,13 +290,11 @@ def test_manifestv2_app_info_postinstall():
def test_manifestv2_app_info_preupgrade(monkeypatch):
manifest = app_manifest(os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"))
from yunohost.app_catalog import _load_apps_catalog as original_load_apps_catalog
def custom_load_apps_catalog(*args, **kwargs):
res = original_load_apps_catalog(*args, **kwargs)
res["apps"]["manifestv2_app"] = {
"id": "manifestv2_app",
@ -372,7 +352,6 @@ def test_app_from_catalog():
def test_legacy_app_install_secondary_domain(secondary_domain):
install_legacy_app(secondary_domain, "/legacy")
assert app_is_installed(secondary_domain, "legacy_app")
@ -384,7 +363,6 @@ def test_legacy_app_install_secondary_domain(secondary_domain):
def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
install_legacy_app(secondary_domain, "/")
app_map_ = app_map(raw=True)
@ -402,7 +380,6 @@ def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
def test_legacy_app_install_private(secondary_domain):
install_legacy_app(secondary_domain, "/legacy", public=False)
assert app_is_installed(secondary_domain, "legacy_app")
@ -416,7 +393,6 @@ def test_legacy_app_install_private(secondary_domain):
def test_legacy_app_install_unknown_domain(mocker):
with pytest.raises(YunohostError):
with message(mocker, "app_argument_invalid"):
install_legacy_app("whatever.nope", "/legacy")
@ -425,7 +401,6 @@ def test_legacy_app_install_unknown_domain(mocker):
def test_legacy_app_install_multiple_instances(secondary_domain):
install_legacy_app(secondary_domain, "/foo")
install_legacy_app(secondary_domain, "/bar")
@ -447,7 +422,6 @@ def test_legacy_app_install_multiple_instances(secondary_domain):
def test_legacy_app_install_path_unavailable(mocker, secondary_domain):
# These will be removed in teardown
install_legacy_app(secondary_domain, "/legacy")
@ -460,7 +434,6 @@ def test_legacy_app_install_path_unavailable(mocker, secondary_domain):
def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
os.system("systemctl stop nginx")
with raiseYunohostError(
@ -470,7 +443,6 @@ def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
def test_legacy_app_failed_install(mocker, secondary_domain):
# This will conflict with the folder that the app
# attempts to create, making the install fail
mkdir("/var/www/legacy_app/", 0o750)
@ -483,7 +455,6 @@ def test_legacy_app_failed_install(mocker, secondary_domain):
def test_legacy_app_failed_remove(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy")
# The remove script runs with set -eu and attempt to remove this
@ -503,14 +474,12 @@ def test_legacy_app_failed_remove(mocker, secondary_domain):
def test_full_domain_app(secondary_domain):
install_full_domain_app(secondary_domain)
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
def test_full_domain_app_with_conflicts(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy")
with raiseYunohostError(mocker, "app_full_domain_unavailable"):
@ -518,7 +487,6 @@ def test_full_domain_app_with_conflicts(mocker, secondary_domain):
def test_systemfuckedup_during_app_install(mocker, secondary_domain):
with pytest.raises(YunohostError):
with message(mocker, "app_install_failed"):
with message(mocker, "app_action_broke_system"):
@ -528,7 +496,6 @@ def test_systemfuckedup_during_app_install(mocker, secondary_domain):
def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
install_break_yo_system(secondary_domain, breakwhat="remove")
with pytest.raises(YunohostError):
@ -540,7 +507,6 @@ def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
with pytest.raises(YunohostError):
with message(mocker, "app_install_failed"):
with message(mocker, "app_action_broke_system"):
@ -550,7 +516,6 @@ def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
install_break_yo_system(secondary_domain, breakwhat="upgrade")
with pytest.raises(YunohostError):
@ -562,7 +527,6 @@ def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
def test_failed_multiple_app_upgrade(mocker, secondary_domain):
install_legacy_app(secondary_domain, "/legacy")
install_break_yo_system(secondary_domain, breakwhat="upgrade")

View file

@ -18,7 +18,6 @@ maindomain = _get_maindomain()
def setup_function(function):
try:
app_remove("register_url_app")
except Exception:
@ -26,7 +25,6 @@ def setup_function(function):
def teardown_function(function):
try:
app_remove("register_url_app")
except Exception:
@ -34,7 +32,6 @@ def teardown_function(function):
def test_parse_app_instance_name():
assert _parse_app_instance_name("yolo") == ("yolo", 1)
assert _parse_app_instance_name("yolo1") == ("yolo1", 1)
assert _parse_app_instance_name("yolo__0") == ("yolo__0", 1)
@ -86,7 +83,6 @@ def test_repo_url_definition():
def test_urlavailable():
# Except the maindomain/macnuggets to be available
assert domain_url_available(maindomain, "/macnuggets")
@ -96,7 +92,6 @@ def test_urlavailable():
def test_registerurl():
app_install(
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),
args="domain={}&path={}".format(maindomain, "/urlregisterapp"),
@ -115,7 +110,6 @@ def test_registerurl():
def test_registerurl_baddomain():
with pytest.raises(YunohostError):
app_install(
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),

View file

@ -30,7 +30,6 @@ maindomain = ""
def setup_function(function):
global maindomain
maindomain = _get_maindomain()
@ -89,7 +88,6 @@ def setup_function(function):
def teardown_function(function):
assert tmp_backup_directory_is_empty()
reset_ssowat_conf()
@ -133,7 +131,6 @@ def check_permission_for_apps_call():
def app_is_installed(app):
if app == "permissions_app":
return _is_installed(app)
@ -147,7 +144,6 @@ def app_is_installed(app):
def backup_test_dependencies_are_met():
# Dummy test apps (or backup archives)
assert os.path.exists(
os.path.join(get_test_apps_dir(), "backup_wordpress_from_4p2")
@ -161,7 +157,6 @@ def backup_test_dependencies_are_met():
def tmp_backup_directory_is_empty():
if not os.path.exists("/home/yunohost.backup/tmp/"):
return True
else:
@ -169,7 +164,6 @@ def tmp_backup_directory_is_empty():
def clean_tmp_backup_directory():
if tmp_backup_directory_is_empty():
return
@ -191,27 +185,23 @@ def clean_tmp_backup_directory():
def reset_ssowat_conf():
# Make sure we have a ssowat
os.system("mkdir -p /etc/ssowat/")
app_ssowatconf()
def delete_all_backups():
for archive in backup_list()["archives"]:
backup_delete(archive)
def uninstall_test_apps_if_needed():
for app in ["legacy_app", "backup_recommended_app", "wordpress", "permissions_app"]:
if _is_installed(app):
app_remove(app)
def install_app(app, path, additionnal_args=""):
app_install(
os.path.join(get_test_apps_dir(), app),
args="domain={}&path={}{}".format(maindomain, path, additionnal_args),
@ -220,7 +210,6 @@ def install_app(app, path, additionnal_args=""):
def add_archive_wordpress_from_4p2():
os.system("mkdir -p /home/yunohost.backup/archives")
os.system(
@ -231,7 +220,6 @@ def add_archive_wordpress_from_4p2():
def add_archive_system_from_4p2():
os.system("mkdir -p /home/yunohost.backup/archives")
os.system(
@ -247,7 +235,6 @@ def add_archive_system_from_4p2():
def test_backup_only_ldap(mocker):
# Create the backup
with message(mocker, "backup_created"):
backup_create(system=["conf_ldap"], apps=None)
@ -262,7 +249,6 @@ def test_backup_only_ldap(mocker):
def test_backup_system_part_that_does_not_exists(mocker):
# Create the backup
with message(mocker, "backup_hook_unknown", hook="doesnt_exist"):
with raiseYunohostError(mocker, "backup_nothings_done"):
@ -275,7 +261,6 @@ def test_backup_system_part_that_does_not_exists(mocker):
def test_backup_and_restore_all_sys(mocker):
# Create the backup
with message(mocker, "backup_created"):
backup_create(system=[], apps=None)
@ -309,7 +294,6 @@ def test_backup_and_restore_all_sys(mocker):
@pytest.mark.with_system_archive_from_4p2
def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
# Backup current system
with message(mocker, "backup_created"):
backup_create(system=[], apps=None)
@ -337,7 +321,6 @@ def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
@pytest.mark.with_backup_recommended_app_installed
def test_backup_script_failure_handling(monkeypatch, mocker):
def custom_hook_exec(name, *args, **kwargs):
if os.path.basename(name).startswith("backup_"):
raise Exception
else:
@ -373,7 +356,6 @@ def test_backup_not_enough_free_space(monkeypatch, mocker):
def test_backup_app_not_installed(mocker):
assert not _is_installed("wordpress")
with message(mocker, "unbackup_app", app="wordpress"):
@ -383,7 +365,6 @@ def test_backup_app_not_installed(mocker):
@pytest.mark.with_backup_recommended_app_installed
def test_backup_app_with_no_backup_script(mocker):
backup_script = "/etc/yunohost/apps/backup_recommended_app/scripts/backup"
os.system("rm %s" % backup_script)
assert not os.path.exists(backup_script)
@ -397,7 +378,6 @@ def test_backup_app_with_no_backup_script(mocker):
@pytest.mark.with_backup_recommended_app_installed
def test_backup_app_with_no_restore_script(mocker):
restore_script = "/etc/yunohost/apps/backup_recommended_app/scripts/restore"
os.system("rm %s" % restore_script)
assert not os.path.exists(restore_script)
@ -413,7 +393,6 @@ def test_backup_app_with_no_restore_script(mocker):
@pytest.mark.clean_opt_dir
def test_backup_with_different_output_directory(mocker):
# Create the backup
with message(mocker, "backup_created"):
backup_create(
@ -436,7 +415,6 @@ def test_backup_with_different_output_directory(mocker):
@pytest.mark.clean_opt_dir
def test_backup_using_copy_method(mocker):
# Create the backup
with message(mocker, "backup_created"):
backup_create(
@ -458,7 +436,6 @@ def test_backup_using_copy_method(mocker):
@pytest.mark.with_wordpress_archive_from_4p2
@pytest.mark.with_custom_domain("yolo.test")
def test_restore_app_wordpress_from_Ynh4p2(mocker):
with message(mocker, "restore_complete"):
backup_restore(
system=None, name=backup_list()["archives"][0], apps=["wordpress"]
@ -507,7 +484,6 @@ def test_restore_app_not_enough_free_space(monkeypatch, mocker):
@pytest.mark.with_wordpress_archive_from_4p2
def test_restore_app_not_in_backup(mocker):
assert not _is_installed("wordpress")
assert not _is_installed("yoloswag")
@ -524,7 +500,6 @@ def test_restore_app_not_in_backup(mocker):
@pytest.mark.with_wordpress_archive_from_4p2
@pytest.mark.with_custom_domain("yolo.test")
def test_restore_app_already_installed(mocker):
assert not _is_installed("wordpress")
with message(mocker, "restore_complete"):
@ -544,25 +519,21 @@ def test_restore_app_already_installed(mocker):
@pytest.mark.with_legacy_app_installed
def test_backup_and_restore_legacy_app(mocker):
_test_backup_and_restore_app(mocker, "legacy_app")
@pytest.mark.with_backup_recommended_app_installed
def test_backup_and_restore_recommended_app(mocker):
_test_backup_and_restore_app(mocker, "backup_recommended_app")
@pytest.mark.with_backup_recommended_app_installed_with_ynh_restore
def test_backup_and_restore_with_ynh_restore(mocker):
_test_backup_and_restore_app(mocker, "backup_recommended_app")
@pytest.mark.with_permission_app_installed
def test_backup_and_restore_permission_app(mocker):
res = user_permission_list(full=True)["permissions"]
assert "permissions_app.main" in res
assert "permissions_app.admin" in res
@ -593,7 +564,6 @@ def test_backup_and_restore_permission_app(mocker):
def _test_backup_and_restore_app(mocker, app):
# Create a backup of this app
with message(mocker, "backup_created"):
backup_create(system=None, apps=[app])
@ -628,7 +598,6 @@ def _test_backup_and_restore_app(mocker, app):
def test_restore_archive_with_no_json(mocker):
# Create a backup with no info.json associated
os.system("touch /tmp/afile")
os.system("tar -cvf /home/yunohost.backup/archives/badbackup.tar /tmp/afile")
@ -641,7 +610,6 @@ def test_restore_archive_with_no_json(mocker):
@pytest.mark.with_wordpress_archive_from_4p2
def test_restore_archive_with_bad_archive(mocker):
# Break the archive
os.system(
"head -n 1000 /home/yunohost.backup/archives/backup_wordpress_from_4p2.tar > /home/yunohost.backup/archives/backup_wordpress_from_4p2_bad.tar"
@ -656,7 +624,6 @@ def test_restore_archive_with_bad_archive(mocker):
def test_restore_archive_with_custom_hook(mocker):
custom_restore_hook_folder = os.path.join(CUSTOM_HOOK_FOLDER, "restore")
os.system("touch %s/99-yolo" % custom_restore_hook_folder)

View file

@ -12,12 +12,10 @@ from yunohost.dns import (
def setup_function(function):
clean()
def teardown_function(function):
clean()
@ -76,7 +74,6 @@ def example_domain():
def test_domain_dns_suggest(example_domain):
assert _build_dns_conf(example_domain)

View file

@ -19,7 +19,6 @@ TEST_DOMAINS = ["example.tld", "sub.example.tld", "other-example.com"]
def setup_function(function):
# Save domain list in variable to avoid multiple calls to domain_list()
domains = domain_list()["domains"]
@ -52,7 +51,6 @@ def setup_function(function):
def teardown_function(function):
clean()
@ -102,7 +100,6 @@ def test_domain_config_get_default():
def test_domain_config_get_export():
assert domain_config_get(TEST_DOMAINS[0], export=True)["xmpp"] == 1
assert domain_config_get(TEST_DOMAINS[1], export=True)["xmpp"] == 0

View file

@ -10,7 +10,6 @@ from moulinette.core import MoulinetteError
def setup_function(function):
for u in user_list()["users"]:
user_delete(u, purge=True)
@ -24,7 +23,6 @@ def setup_function(function):
def teardown_function():
os.system("systemctl is-active slapd >/dev/null || systemctl start slapd; sleep 5")
for u in user_list()["users"]:
@ -36,7 +34,6 @@ def test_authenticate():
def test_authenticate_with_no_user():
with pytest.raises(MoulinetteError):
LDAPAuth().authenticate_credentials(credentials="Yunohost")
@ -45,7 +42,6 @@ def test_authenticate_with_no_user():
def test_authenticate_with_user_who_is_not_admin():
with pytest.raises(MoulinetteError) as exception:
LDAPAuth().authenticate_credentials(credentials="bob:test123Ynh")
@ -70,7 +66,6 @@ def test_authenticate_server_down(mocker):
def test_authenticate_change_password():
LDAPAuth().authenticate_credentials(credentials="alice:Yunohost")
user_update("alice", change_password="plopette")

View file

@ -354,7 +354,6 @@ def check_permission_for_apps():
def can_access_webpage(webpath, logged_as=None):
webpath = webpath.rstrip("/")
sso_url = "https://" + maindomain + "/yunohost/sso/"
@ -1094,7 +1093,6 @@ def test_permission_protection_management_by_helper():
@pytest.mark.other_domains(number=1)
def test_permission_app_propagation_on_ssowat():
app_install(
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=1&admin=%s"
@ -1131,7 +1129,6 @@ def test_permission_app_propagation_on_ssowat():
@pytest.mark.other_domains(number=1)
def test_permission_legacy_app_propagation_on_ssowat():
app_install(
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
args="domain=%s&domain_2=%s&path=%s&is_public=1"

View file

@ -49,7 +49,6 @@ def test_question_empty():
def test_question_string():
questions = {
"some_string": {
"type": "string",
@ -65,7 +64,6 @@ def test_question_string():
def test_question_string_from_query_string():
questions = {
"some_string": {
"type": "string",
@ -1539,7 +1537,6 @@ def test_question_user_two_users_default_input():
os, "isatty", return_value=True
):
with patch.object(user, "user_info", return_value={}):
with patch.object(Moulinette, "prompt", return_value=username):
out = ask_questions_and_parse_answers(questions, answers)[0]
@ -1843,7 +1840,6 @@ def test_question_display_text():
def test_question_file_from_cli():
FileQuestion.clean_upload_dirs()
filename = "/tmp/ynh_test_question_file"
@ -1874,7 +1870,6 @@ def test_question_file_from_cli():
def test_question_file_from_api():
FileQuestion.clean_upload_dirs()
from base64 import b64encode
@ -1907,7 +1902,6 @@ def test_question_file_from_api():
def test_normalize_boolean_nominal():
assert BooleanQuestion.normalize("yes") == 1
assert BooleanQuestion.normalize("Yes") == 1
assert BooleanQuestion.normalize(" yes ") == 1
@ -1937,7 +1931,6 @@ def test_normalize_boolean_nominal():
def test_normalize_boolean_humanize():
assert BooleanQuestion.humanize("yes") == "yes"
assert BooleanQuestion.humanize("true") == "yes"
assert BooleanQuestion.humanize("on") == "yes"
@ -1948,7 +1941,6 @@ def test_normalize_boolean_humanize():
def test_normalize_boolean_invalid():
with pytest.raises(YunohostValidationError):
BooleanQuestion.normalize("yesno")
with pytest.raises(YunohostValidationError):
@ -1958,7 +1950,6 @@ def test_normalize_boolean_invalid():
def test_normalize_boolean_special_yesno():
customyesno = {"yes": "enabled", "no": "disabled"}
assert BooleanQuestion.normalize("yes", customyesno) == "enabled"
@ -1977,14 +1968,12 @@ def test_normalize_boolean_special_yesno():
def test_normalize_domain():
assert DomainQuestion.normalize("https://yolo.swag/") == "yolo.swag"
assert DomainQuestion.normalize("http://yolo.swag") == "yolo.swag"
assert DomainQuestion.normalize("yolo.swag/") == "yolo.swag"
def test_normalize_path():
assert PathQuestion.normalize("") == "/"
assert PathQuestion.normalize("") == "/"
assert PathQuestion.normalize("macnuggets") == "/macnuggets"

View file

@ -16,19 +16,16 @@ SSHD_CONFIG = "/etc/ssh/sshd_config"
def setup_function(function):
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
clean()
def teardown_function(function):
clean()
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
def clean():
assert os.system("pgrep slapd >/dev/null") == 0
assert os.system("pgrep nginx >/dev/null") == 0
@ -48,7 +45,6 @@ def clean():
def test_add_domain():
domain_add(TEST_DOMAIN)
assert TEST_DOMAIN in domain_list()["domains"]
@ -60,7 +56,6 @@ def test_add_domain():
def test_add_and_edit_domain_conf():
domain_add(TEST_DOMAIN)
assert os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
@ -73,7 +68,6 @@ def test_add_and_edit_domain_conf():
def test_add_domain_conf_already_exists():
os.system("echo ' ' >> %s" % TEST_DOMAIN_NGINX_CONFIG)
domain_add(TEST_DOMAIN)
@ -84,7 +78,6 @@ def test_add_domain_conf_already_exists():
def test_ssh_conf_unmanaged():
_force_clear_hashes([SSHD_CONFIG])
assert SSHD_CONFIG not in _get_conf_hashes("ssh")
@ -95,7 +88,6 @@ def test_ssh_conf_unmanaged():
def test_ssh_conf_unmanaged_and_manually_modified(mocker):
_force_clear_hashes([SSHD_CONFIG])
os.system("echo ' ' >> %s" % SSHD_CONFIG)

View file

@ -14,17 +14,14 @@ from yunohost.service import (
def setup_function(function):
clean()
def teardown_function(function):
clean()
def clean():
# To run these tests, we assume ssh(d) service exists and is running
assert os.system("pgrep sshd >/dev/null") == 0
@ -45,46 +42,39 @@ def clean():
def test_service_status_all():
status = service_status()
assert "ssh" in status.keys()
assert status["ssh"]["status"] == "running"
def test_service_status_single():
status = service_status("ssh")
assert "status" in status.keys()
assert status["status"] == "running"
def test_service_log():
logs = service_log("ssh")
assert "journalctl" in logs.keys()
assert "/var/log/auth.log" in logs.keys()
def test_service_status_unknown_service(mocker):
with raiseYunohostError(mocker, "service_unknown"):
service_status(["ssh", "doesnotexists"])
def test_service_add():
service_add("dummyservice", description="A dummy service to run tests")
assert "dummyservice" in service_status().keys()
def test_service_add_real_service():
service_add("networking")
assert "networking" in service_status().keys()
def test_service_remove():
service_add("dummyservice", description="A dummy service to run tests")
assert "dummyservice" in service_status().keys()
service_remove("dummyservice")
@ -92,7 +82,6 @@ def test_service_remove():
def test_service_remove_service_that_doesnt_exists(mocker):
assert "dummyservice" not in service_status().keys()
with raiseYunohostError(mocker, "service_unknown"):
@ -102,7 +91,6 @@ def test_service_remove_service_that_doesnt_exists(mocker):
def test_service_update_to_add_properties():
service_add("dummyservice", description="dummy")
assert not _get_services()["dummyservice"].get("test_status")
service_add("dummyservice", description="dummy", test_status="true")
@ -110,7 +98,6 @@ def test_service_update_to_add_properties():
def test_service_update_to_change_properties():
service_add("dummyservice", description="dummy", test_status="false")
assert _get_services()["dummyservice"].get("test_status") == "false"
service_add("dummyservice", description="dummy", test_status="true")
@ -118,7 +105,6 @@ def test_service_update_to_change_properties():
def test_service_update_to_remove_properties():
service_add("dummyservice", description="dummy", test_status="false")
assert _get_services()["dummyservice"].get("test_status") == "false"
service_add("dummyservice", description="dummy", test_status="")
@ -126,7 +112,6 @@ def test_service_update_to_remove_properties():
def test_service_conf_broken():
os.system("echo pwet > /etc/nginx/conf.d/broken.conf")
status = service_status("nginx")

View file

@ -65,7 +65,6 @@ old_translate = moulinette.core.Translator.translate
def _monkeypatch_translator(self, key, *args, **kwargs):
if key.startswith("global_settings_setting_"):
return f"Dummy translation for {key}"
@ -175,7 +174,6 @@ def test_settings_set_doesexit():
def test_settings_set_bad_type_bool():
with patch.object(os, "isatty", return_value=False):
with pytest.raises(YunohostError):
settings_set("example.example.boolean", 42)

View file

@ -92,7 +92,6 @@ def test_list_groups():
def test_create_user(mocker):
with message(mocker, "user_created"):
user_create("albert", maindomain, "test123Ynh", fullname="Albert Good")
@ -104,7 +103,6 @@ def test_create_user(mocker):
def test_del_user(mocker):
with message(mocker, "user_deleted"):
user_delete("alice")
@ -185,7 +183,6 @@ def test_export_user(mocker):
def test_create_group(mocker):
with message(mocker, "group_created", group="adminsys"):
user_group_create("adminsys")
@ -196,7 +193,6 @@ def test_create_group(mocker):
def test_del_group(mocker):
with message(mocker, "group_deleted", group="dev"):
user_group_delete("dev")

View file

@ -62,7 +62,6 @@ def tools_versions():
def tools_rootpw(new_password, check_strength=True):
from yunohost.user import _hash_user_password
from yunohost.utils.password import (
assert_password_is_strong_enough,
@ -154,7 +153,6 @@ def tools_postinstall(
ignore_dyndns=False,
force_diskspace=False,
):
from yunohost.dyndns import _dyndns_available
from yunohost.utils.dns import is_yunohost_dyndns_domain
from yunohost.utils.password import (
@ -193,7 +191,6 @@ def tools_postinstall(
# If this is a nohost.me/noho.st, actually check for availability
if not ignore_dyndns and is_yunohost_dyndns_domain(domain):
available = None
# Check if the domain is available...
@ -281,7 +278,6 @@ def tools_postinstall(
def tools_regen_conf(
names=[], with_diff=False, force=False, dry_run=False, list_pending=False
):
# Make sure the settings are migrated before running the migration,
# which may otherwise fuck things up such as the ssh config ...
# We do this here because the regen-conf is called before the migration in debian/postinst
@ -312,7 +308,6 @@ def tools_update(target=None):
upgradable_system_packages = []
if target in ["system", "all"]:
# Update APT cache
# LC_ALL=C is here to make sure the results are in english
command = (
@ -426,7 +421,6 @@ def tools_upgrade(operation_logger, target=None):
#
if target == "apps":
# Make sure there's actually something to upgrade
upgradable_apps = [app["id"] for app in app_list(upgradable=True)["apps"]]
@ -450,7 +444,6 @@ def tools_upgrade(operation_logger, target=None):
#
if target == "system":
# Check that there's indeed some packages to upgrade
upgradables = list(_list_upgradable_apt_packages())
if not upgradables:
@ -498,7 +491,6 @@ def tools_upgrade(operation_logger, target=None):
any(p["name"] == "yunohost" for p in upgradables)
and Moulinette.interface.type == "api"
):
# Restart the API after 10 sec (at now doesn't support sub-minute times...)
# We do this so that the API / webadmin still gets the proper HTTP response
# It's then up to the webadmin to implement a proper UX process to wait 10 sec and then auto-fresh the webadmin
@ -722,7 +714,6 @@ def tools_migrations_run(
# Actually run selected migrations
for migration in targets:
# If we are migrating in "automatic mode" (i.e. from debian configure
# during an upgrade of the package) but we are asked for running
# migrations to be ran manually by the user, stop there and ask the
@ -778,7 +769,6 @@ def tools_migrations_run(
_write_migration_state(migration.id, "skipped")
operation_logger.success()
else:
try:
migration.operation_logger = operation_logger
logger.info(m18n.n("migrations_running_forward", id=migration.id))
@ -810,14 +800,12 @@ def tools_migrations_state():
def _write_migration_state(migration_id, state):
current_states = tools_migrations_state()
current_states["migrations"][migration_id] = state
write_to_yaml(MIGRATIONS_STATE_PATH, current_states)
def _get_migrations_list():
# states is a datastructure that represents the last run migration
# it has this form:
# {
@ -868,7 +856,6 @@ def _get_migration_by_name(migration_name):
def _load_migration(migration_file):
migration_id = migration_file[: -len(".py")]
logger.debug(m18n.n("migrations_loading_migration", id=migration_id))
@ -903,7 +890,6 @@ def _skip_all_migrations():
def _tools_migrations_run_after_system_restore(backup_version):
all_migrations = _get_migrations_list()
current_version = version.parse(ynh_packages_version()["yunohost"]["version"])
@ -930,7 +916,6 @@ def _tools_migrations_run_after_system_restore(backup_version):
def _tools_migrations_run_before_app_restore(backup_version, app_id):
all_migrations = _get_migrations_list()
current_version = version.parse(ynh_packages_version()["yunohost"]["version"])
@ -957,7 +942,6 @@ def _tools_migrations_run_before_app_restore(backup_version, app_id):
class Migration:
# Those are to be implemented by daughter classes
mode = "auto"
@ -985,7 +969,6 @@ class Migration:
def ldap_migration(run):
def func(self):
# Backup LDAP before the migration
logger.info(m18n.n("migration_ldap_backup_before_migration"))
try:

View file

@ -53,7 +53,6 @@ ADMIN_ALIASES = ["root", "admin", "admins", "webmaster", "postmaster", "abuse"]
def user_list(fields=None):
from yunohost.utils.ldap import _get_ldap_interface
ldap_attrs = {
@ -149,7 +148,6 @@ def user_create(
from_import=False,
loginShell=None,
):
if firstname or lastname:
logger.warning(
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
@ -319,7 +317,6 @@ def user_create(
@is_unit_operation([("username", "user")])
def user_delete(operation_logger, username, purge=False, from_import=False):
from yunohost.hook import hook_callback
from yunohost.utils.ldap import _get_ldap_interface
@ -380,7 +377,6 @@ def user_update(
fullname=None,
loginShell=None,
):
if firstname or lastname:
logger.warning(
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
@ -735,7 +731,6 @@ def user_import(operation_logger, csvfile, update=False, delete=False):
)
for user in reader:
# Validate column values against regexes
format_errors = [
f"{key}: '{user[key]}' doesn't match the expected format"
@ -991,7 +986,6 @@ def user_group_list(short=False, full=False, include_primary_groups=True):
users = user_list()["users"]
groups = {}
for infos in groups_infos:
name = infos["cn"][0]
if not include_primary_groups and name in users:
@ -1141,7 +1135,6 @@ def user_group_update(
sync_perm=True,
from_import=False,
):
from yunohost.permission import permission_sync_to_user
from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract
@ -1184,7 +1177,6 @@ def user_group_update(
new_attr_dict = {}
if add:
users_to_add = [add] if not isinstance(add, list) else add
for user in users_to_add:
@ -1225,7 +1217,6 @@ def user_group_update(
# Check the whole alias situation
if add_mailalias:
from yunohost.domain import domain_list
domains = domain_list()["domains"]
@ -1269,7 +1260,6 @@ def user_group_update(
raise YunohostValidationError("mail_alias_remove_failed", mail=mail)
if set(new_group_mail) != set(current_group_mail):
logger.info(m18n.n("group_update_aliases", group=groupname))
new_attr_dict["mail"] = set(new_group_mail)
@ -1477,7 +1467,6 @@ def _hash_user_password(password):
def _update_admins_group_aliases(old_main_domain, new_main_domain):
current_admin_aliases = user_group_info("admins")["mail-aliases"]
aliases_to_remove = [

View file

@ -264,7 +264,6 @@ class ConfigPanel:
# In 'classic' mode, we display the current value if key refer to an option
if self.filter_key.count(".") == 2 and mode == "classic":
option = self.filter_key.split(".")[-1]
value = self.values.get(option, None)
@ -280,7 +279,6 @@ class ConfigPanel:
logger.debug(f"Formating result in '{mode}' mode")
result = {}
for panel, section, option in self._iterate():
if section["is_action_section"] and mode != "full":
continue
@ -323,7 +321,6 @@ class ConfigPanel:
return result
def list_actions(self):
actions = {}
# FIXME : meh, loading the entire config panel is again going to cause
@ -462,7 +459,6 @@ class ConfigPanel:
return read_toml(self.config_path)
def _get_config_panel(self):
# Split filter_key
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
if len(filter_key) > 3:
@ -639,7 +635,6 @@ class ConfigPanel:
# Hydrating config panel with current value
for _, section, option in self._iterate():
if option["id"] not in self.values:
allowed_empty_types = [
"alert",
"display_text",
@ -701,7 +696,6 @@ class ConfigPanel:
Moulinette.display(colorize(message, "purple"))
for panel, section, obj in self._iterate(["panel", "section"]):
if (
section
and section.get("visible")
@ -814,7 +808,6 @@ class ConfigPanel:
write_to_yaml(self.save_path, values_to_save)
def _reload_services(self):
from yunohost.service import service_reload_or_restart
services_to_reload = set()
@ -905,7 +898,6 @@ class Question:
)
def ask_if_needed(self):
if self.visible and not evaluate_simple_js_expression(
self.visible, context=self.context
):
@ -980,7 +972,6 @@ class Question:
)
def _format_text_for_user_input_in_cli(self):
text_for_user_input_in_cli = _value_for_locale(self.ask)
if self.readonly:
@ -991,7 +982,6 @@ class Question:
)
return text_for_user_input_in_cli + f" {self.humanize(self.current_value)}"
elif self.choices:
# Prevent displaying a shitload of choices
# (e.g. 100+ available users when choosing an app admin...)
choices = (
@ -1160,7 +1150,6 @@ class PathQuestion(Question):
@staticmethod
def normalize(value, option={}):
option = option.__dict__ if isinstance(option, Question) else option
if not value.strip():
@ -1187,7 +1176,6 @@ class BooleanQuestion(Question):
@staticmethod
def humanize(value, option={}):
option = option.__dict__ if isinstance(option, Question) else option
yes = option.get("yes", 1)
@ -1211,7 +1199,6 @@ class BooleanQuestion(Question):
@staticmethod
def normalize(value, option={}):
option = option.__dict__ if isinstance(option, Question) else option
if isinstance(value, str):
@ -1368,7 +1355,6 @@ class GroupQuestion(Question):
def __init__(
self, question, context: Mapping[str, Any] = {}, hooks: Dict[str, Callable] = {}
):
from yunohost.user import user_group_list
super().__init__(question, context)
@ -1401,7 +1387,6 @@ class NumberQuestion(Question):
@staticmethod
def normalize(value, option={}):
if isinstance(value, int):
return value

View file

@ -31,19 +31,16 @@ external_resolvers_: List[str] = []
def is_yunohost_dyndns_domain(domain):
return any(
domain.endswith(f".{dyndns_domain}") for dyndns_domain in YNH_DYNDNS_DOMAINS
)
def is_special_use_tld(domain):
return any(domain.endswith(f".{tld}") for tld in SPECIAL_USE_TLDS)
def external_resolvers():
global external_resolvers_
if not external_resolvers_:

View file

@ -21,7 +21,6 @@ from moulinette import m18n
class YunohostError(MoulinetteError):
http_code = 500
"""
@ -43,7 +42,6 @@ class YunohostError(MoulinetteError):
super(YunohostError, self).__init__(msg, raw_msg=True)
def content(self):
if not self.log_ref:
return super().content()
else:
@ -51,14 +49,11 @@ class YunohostError(MoulinetteError):
class YunohostValidationError(YunohostError):
http_code = 400
def content(self):
return {"error": self.strerror, "error_key": self.key, **self.kwargs}
class YunohostAuthenticationError(MoulinetteAuthenticationError):
pass

View file

@ -36,7 +36,6 @@ _ldap_interface = None
def _get_ldap_interface():
global _ldap_interface
if _ldap_interface is None:

View file

@ -193,7 +193,6 @@ LEGACY_PHP_VERSION_REPLACEMENTS = [
def _patch_legacy_php_versions(app_folder):
files_to_patch = []
files_to_patch.extend(glob.glob("%s/conf/*" % app_folder))
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
@ -203,7 +202,6 @@ def _patch_legacy_php_versions(app_folder):
files_to_patch.append("%s/manifest.toml" % app_folder)
for filename in files_to_patch:
# Ignore non-regular files
if not os.path.isfile(filename):
continue
@ -217,7 +215,6 @@ def _patch_legacy_php_versions(app_folder):
def _patch_legacy_php_versions_in_settings(app_folder):
settings = read_yaml(os.path.join(app_folder, "settings.yml"))
if settings.get("fpm_config_dir") in ["/etc/php/7.0/fpm", "/etc/php/7.3/fpm"]:
@ -243,7 +240,6 @@ def _patch_legacy_php_versions_in_settings(app_folder):
def _patch_legacy_helpers(app_folder):
files_to_patch = []
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
files_to_patch.extend(glob.glob("%s/scripts/.*" % app_folder))
@ -291,7 +287,6 @@ def _patch_legacy_helpers(app_folder):
infos["replace"] = infos.get("replace")
for filename in files_to_patch:
# Ignore non-regular files
if not os.path.isfile(filename):
continue
@ -305,7 +300,6 @@ def _patch_legacy_helpers(app_folder):
show_warning = False
for helper, infos in stuff_to_replace.items():
# Ignore if not relevant for this file
if infos.get("only_for") and not any(
filename.endswith(f) for f in infos["only_for"]
@ -329,7 +323,6 @@ def _patch_legacy_helpers(app_folder):
)
if replaced_stuff:
# Check the app do load the helper
# If it doesn't, add the instruction ourselve (making sure it's after the #!/bin/bash if it's there...
if filename.split("/")[-1] in [

View file

@ -29,7 +29,6 @@ logger = logging.getLogger("yunohost.utils.network")
def get_public_ip(protocol=4):
assert protocol in [4, 6], (
"Invalid protocol version for get_public_ip: %s, expected 4 or 6" % protocol
)
@ -90,7 +89,6 @@ def get_public_ip_from_remote_server(protocol=4):
def get_network_interfaces():
# Get network devices and their addresses (raw infos from 'ip addr')
devices_raw = {}
output = check_output("ip addr show")
@ -111,7 +109,6 @@ def get_network_interfaces():
def get_gateway():
output = check_output("ip route show")
m = re.search(r"default via (.*) dev ([a-z]+[0-9]?)", output)
if not m:

View file

@ -58,7 +58,6 @@ def assert_password_is_compatible(password):
"""
if len(password) >= 127:
# Note that those imports are made here and can't be put
# on top (at least not the moulinette ones)
# because the moulinette needs to be correctly initialized
@ -69,7 +68,6 @@ def assert_password_is_compatible(password):
def assert_password_is_strong_enough(profile, password):
PasswordValidator(profile).validate(password)
@ -197,7 +195,6 @@ class PasswordValidator:
return strength_level
def is_in_most_used_list(self, password):
# Decompress file if compressed
if os.path.exists("%s.gz" % MOST_USED_PASSWORDS):
os.system("gzip -fd %s.gz" % MOST_USED_PASSWORDS)

View file

@ -37,7 +37,6 @@ logger = getActionLogger("yunohost.app_resources")
class AppResourceManager:
def __init__(self, app: str, current: Dict, wanted: Dict):
self.app = app
self.current = current
self.wanted = wanted
@ -50,7 +49,6 @@ class AppResourceManager:
def apply(
self, rollback_and_raise_exception_if_failure, operation_logger=None, **context
):
todos = list(self.compute_todos())
completed = []
rollback = False
@ -121,7 +119,6 @@ class AppResourceManager:
logger.error(exception)
def compute_todos(self):
for name, infos in reversed(self.current["resources"].items()):
if name not in self.wanted["resources"].keys():
resource = AppResourceClassesByType[name](infos, self.app, self)
@ -140,12 +137,10 @@ class AppResourceManager:
class AppResource:
type: str = ""
default_properties: Dict[str, Any] = {}
def __init__(self, properties: Dict[str, Any], app: str, manager=None):
self.app = app
self.manager = manager
@ -175,7 +170,6 @@ class AppResource:
app_setting(self.app, key, delete=True)
def _run_script(self, action, script, env={}, user="root"):
from yunohost.app import (
_make_tmp_workdir_for_app,
_make_environment_for_app_script,
@ -295,7 +289,6 @@ class PermissionsResource(AppResource):
permissions: Dict[str, Dict[str, Any]] = {}
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
# FIXME : if url != None, we should check that there's indeed a domain/path defined ? ie that app is a webapp
for perm, infos in properties.items():
@ -315,7 +308,6 @@ class PermissionsResource(AppResource):
super().__init__({"permissions": properties}, *args, **kwargs)
def provision_or_update(self, context: Dict = {}):
from yunohost.permission import (
permission_create,
permission_url,
@ -375,7 +367,6 @@ class PermissionsResource(AppResource):
permission_sync_to_user()
def deprovision(self, context: Dict = {}):
from yunohost.permission import (
permission_delete,
user_permission_list,
@ -432,7 +423,6 @@ class SystemuserAppResource(AppResource):
allow_sftp: bool = False
def provision_or_update(self, context: Dict = {}):
# FIXME : validate that no yunohost user exists with that name?
# and/or that no system user exists during install ?
@ -462,7 +452,6 @@ class SystemuserAppResource(AppResource):
os.system(f"usermod -G {','.join(groups)} {self.app}")
def deprovision(self, context: Dict = {}):
if check_output(f"getent passwd {self.app} &>/dev/null || true").strip():
os.system(f"deluser {self.app} >/dev/null")
if check_output(f"getent passwd {self.app} &>/dev/null || true").strip():
@ -528,7 +517,6 @@ class InstalldirAppResource(AppResource):
# FIXME: change default dir to /opt/stuff if app ain't a webapp ...
def provision_or_update(self, context: Dict = {}):
assert self.dir.strip() # Be paranoid about self.dir being empty...
assert self.owner.strip()
assert self.group.strip()
@ -582,7 +570,6 @@ class InstalldirAppResource(AppResource):
self.delete_setting("final_path") # Legacy
def deprovision(self, context: Dict = {}):
assert self.dir.strip() # Be paranoid about self.dir being empty...
assert self.owner.strip()
assert self.group.strip()
@ -643,7 +630,6 @@ class DatadirAppResource(AppResource):
group: str = ""
def provision_or_update(self, context: Dict = {}):
assert self.dir.strip() # Be paranoid about self.dir being empty...
assert self.owner.strip()
assert self.group.strip()
@ -686,7 +672,6 @@ class DatadirAppResource(AppResource):
self.delete_setting("datadir") # Legacy
def deprovision(self, context: Dict = {}):
assert self.dir.strip() # Be paranoid about self.dir being empty...
assert self.owner.strip()
assert self.group.strip()
@ -737,7 +722,6 @@ class AptDependenciesAppResource(AppResource):
extras: Dict[str, Dict[str, str]] = {}
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
for key, values in properties.get("extras", {}).items():
if not all(
isinstance(values.get(k), str) for k in ["repo", "key", "packages"]
@ -749,7 +733,6 @@ class AptDependenciesAppResource(AppResource):
super().__init__(properties, *args, **kwargs)
def provision_or_update(self, context: Dict = {}):
script = [f"ynh_install_app_dependencies {self.packages}"]
for repo, values in self.extras.items():
script += [
@ -760,7 +743,6 @@ class AptDependenciesAppResource(AppResource):
self._run_script("provision_or_update", "\n".join(script))
def deprovision(self, context: Dict = {}):
self._run_script("deprovision", "ynh_remove_app_dependencies")
@ -818,7 +800,6 @@ class PortsResource(AppResource):
ports: Dict[str, Dict[str, Any]]
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
if "main" not in properties:
properties["main"] = {}
@ -832,7 +813,6 @@ class PortsResource(AppResource):
super().__init__({"ports": properties}, *args, **kwargs)
def _port_is_used(self, port):
# FIXME : this could be less brutal than two os.system ...
cmd1 = (
"ss --numeric --listening --tcp --udp | awk '{print$5}' | grep --quiet --extended-regexp ':%s$'"
@ -843,11 +823,9 @@ class PortsResource(AppResource):
return os.system(cmd1) == 0 and os.system(cmd2) == 0
def provision_or_update(self, context: Dict = {}):
from yunohost.firewall import firewall_allow, firewall_disallow
for name, infos in self.ports.items():
setting_name = f"port_{name}" if name != "main" else "port"
port_value = self.get_setting(setting_name)
if not port_value and name != "main":
@ -881,7 +859,6 @@ class PortsResource(AppResource):
)
def deprovision(self, context: Dict = {}):
from yunohost.firewall import firewall_disallow
for name, infos in self.ports.items():
@ -938,7 +915,6 @@ class DatabaseAppResource(AppResource):
}
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
if "type" not in properties or properties["type"] not in [
"mysql",
"postgresql",
@ -956,7 +932,6 @@ class DatabaseAppResource(AppResource):
super().__init__(properties, *args, **kwargs)
def db_exists(self, db_name):
if self.dbtype == "mysql":
return os.system(f"mysqlshow '{db_name}' >/dev/null 2>/dev/null") == 0
elif self.dbtype == "postgresql":
@ -970,7 +945,6 @@ class DatabaseAppResource(AppResource):
return False
def provision_or_update(self, context: Dict = {}):
# This is equivalent to ynh_sanitize_dbid
db_name = self.app.replace("-", "_").replace(".", "_")
db_user = db_name
@ -997,7 +971,6 @@ class DatabaseAppResource(AppResource):
self.set_setting("db_pwd", db_pwd)
if not self.db_exists(db_name):
if self.dbtype == "mysql":
self._run_script(
"provision",
@ -1010,7 +983,6 @@ class DatabaseAppResource(AppResource):
)
def deprovision(self, context: Dict = {}):
db_name = self.app.replace("-", "_").replace(".", "_")
db_user = db_name

View file

@ -49,7 +49,6 @@ def free_space_in_directory(dirpath):
def space_used_by_directory(dirpath, follow_symlinks=True):
if not follow_symlinks:
du_output = check_output(["du", "-sb", dirpath], shell=False)
return int(du_output.split()[0])
@ -61,7 +60,6 @@ def space_used_by_directory(dirpath, follow_symlinks=True):
def human_to_binary(size: str) -> int:
symbols = ("K", "M", "G", "T", "P", "E", "Z", "Y")
factor = {}
for i, s in enumerate(symbols):
@ -99,14 +97,12 @@ def binary_to_human(n: int) -> str:
def ram_available():
import psutil
return (psutil.virtual_memory().available, psutil.swap_memory().free)
def get_ynh_package_version(package):
# Returns the installed version and release version ('stable' or 'testing'
# or 'unstable')
@ -152,7 +148,6 @@ def dpkg_lock_available():
def _list_upgradable_apt_packages():
# List upgradable packages
# LC_ALL=C is here to make sure the results are in english
upgradable_raw = check_output("LC_ALL=C apt list --upgradable")
@ -162,7 +157,6 @@ def _list_upgradable_apt_packages():
line.strip() for line in upgradable_raw.split("\n") if line.strip()
]
for line in upgradable_raw:
# Remove stupid warning and verbose messages >.>
if "apt does not have a stable CLI interface" in line or "Listing..." in line:
continue
@ -182,7 +176,6 @@ def _list_upgradable_apt_packages():
def _dump_sources_list():
from glob import glob
filenames = glob("/etc/apt/sources.list") + glob("/etc/apt/sources.list.d/*")

View file

@ -28,7 +28,6 @@ logger = logging.getLogger("yunohost.utils.yunopaste")
def yunopaste(data):
paste_server = "https://paste.yunohost.org"
try: