mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[CI] Format code with Black
This commit is contained in:
parent
ade92e431d
commit
b943c69c8b
67 changed files with 0 additions and 500 deletions
|
@ -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")
|
||||
|
|
|
@ -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 = []
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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("")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
36
src/app.py
36
src/app.py
|
@ -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"]
|
||||
|
|
|
@ -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"]:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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....
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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={
|
||||
|
|
|
@ -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 []
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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")
|
||||
|
|
12
src/dns.py
12
src/dns.py
|
@ -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}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -21,7 +21,6 @@ class MyMigration(Migration):
|
|||
|
||||
@Migration.ldap_migration
|
||||
def run(self, *args):
|
||||
|
||||
from yunohost.user import (
|
||||
user_list,
|
||||
user_info,
|
||||
|
|
|
@ -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 ["/", "^", "\\"]:
|
||||
|
|
|
@ -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' '*' \
|
||||
|
|
|
@ -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"):
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
17
src/tools.py
17
src/tools.py
|
@ -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:
|
||||
|
|
11
src/user.py
11
src/user.py
|
@ -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 = [
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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_:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -36,7 +36,6 @@ _ldap_interface = None
|
|||
|
||||
|
||||
def _get_ldap_interface():
|
||||
|
||||
global _ldap_interface
|
||||
|
||||
if _ldap_interface is None:
|
||||
|
|
|
@ -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 [
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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/*")
|
||||
|
|
|
@ -28,7 +28,6 @@ logger = logging.getLogger("yunohost.utils.yunopaste")
|
|||
|
||||
|
||||
def yunopaste(data):
|
||||
|
||||
paste_server = "https://paste.yunohost.org"
|
||||
|
||||
try:
|
||||
|
|
Loading…
Add table
Reference in a new issue