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:
|
with open(ACTIONSMAP_FILE, "r") as stream:
|
||||||
|
|
||||||
# Getting the dictionary containning what actions are possible per category
|
# Getting the dictionary containning what actions are possible per category
|
||||||
OPTION_TREE = yaml.safe_load(stream)
|
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)
|
os.makedirs(BASH_COMPLETION_FOLDER, exist_ok=True)
|
||||||
|
|
||||||
with open(BASH_COMPLETION_FILE, "w") as generated_file:
|
with open(BASH_COMPLETION_FILE, "w") as generated_file:
|
||||||
|
|
||||||
# header of the file
|
# header of the file
|
||||||
generated_file.write("#\n")
|
generated_file.write("#\n")
|
||||||
generated_file.write("# completion for yunohost\n")
|
generated_file.write("# completion for yunohost\n")
|
||||||
|
|
|
@ -20,7 +20,6 @@ def get_current_commit():
|
||||||
|
|
||||||
|
|
||||||
def render(helpers):
|
def render(helpers):
|
||||||
|
|
||||||
current_commit = get_current_commit()
|
current_commit = get_current_commit()
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
|
@ -56,20 +55,17 @@ def render(helpers):
|
||||||
|
|
||||||
class Parser:
|
class Parser:
|
||||||
def __init__(self, filename):
|
def __init__(self, filename):
|
||||||
|
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
self.file = open(filename, "r").readlines()
|
self.file = open(filename, "r").readlines()
|
||||||
self.blocks = None
|
self.blocks = None
|
||||||
|
|
||||||
def parse_blocks(self):
|
def parse_blocks(self):
|
||||||
|
|
||||||
self.blocks = []
|
self.blocks = []
|
||||||
|
|
||||||
current_reading = "void"
|
current_reading = "void"
|
||||||
current_block = {"name": None, "line": -1, "comments": [], "code": []}
|
current_block = {"name": None, "line": -1, "comments": [], "code": []}
|
||||||
|
|
||||||
for i, line in enumerate(self.file):
|
for i, line in enumerate(self.file):
|
||||||
|
|
||||||
if line.startswith("#!/bin/bash"):
|
if line.startswith("#!/bin/bash"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -117,7 +113,6 @@ class Parser:
|
||||||
current_reading = "code"
|
current_reading = "code"
|
||||||
|
|
||||||
elif current_reading == "code":
|
elif current_reading == "code":
|
||||||
|
|
||||||
if line == "}":
|
if line == "}":
|
||||||
# We're getting out of the function
|
# We're getting out of the function
|
||||||
current_reading = "void"
|
current_reading = "void"
|
||||||
|
@ -138,7 +133,6 @@ class Parser:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
def parse_block(self, b):
|
def parse_block(self, b):
|
||||||
|
|
||||||
b["brief"] = ""
|
b["brief"] = ""
|
||||||
b["details"] = ""
|
b["details"] = ""
|
||||||
b["usage"] = ""
|
b["usage"] = ""
|
||||||
|
@ -164,7 +158,6 @@ class Parser:
|
||||||
|
|
||||||
elif subblock.startswith("usage"):
|
elif subblock.startswith("usage"):
|
||||||
for line in subblock.split("\n"):
|
for line in subblock.split("\n"):
|
||||||
|
|
||||||
if line.startswith("| arg"):
|
if line.startswith("| arg"):
|
||||||
linesplit = line.split()
|
linesplit = line.split()
|
||||||
argname = linesplit[2]
|
argname = linesplit[2]
|
||||||
|
@ -216,7 +209,6 @@ def malformed_error(line_number):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
||||||
helper_files = sorted(glob.glob("../helpers/*"))
|
helper_files = sorted(glob.glob("../helpers/*"))
|
||||||
helpers = []
|
helpers = []
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ def main():
|
||||||
|
|
||||||
# man pages of "yunohost *"
|
# man pages of "yunohost *"
|
||||||
with open(ACTIONSMAP_FILE, "r") as actionsmap:
|
with open(ACTIONSMAP_FILE, "r") as actionsmap:
|
||||||
|
|
||||||
# Getting the dictionary containning what actions are possible per domain
|
# Getting the dictionary containning what actions are possible per domain
|
||||||
actionsmap = ordered_yaml_load(actionsmap)
|
actionsmap = ordered_yaml_load(actionsmap)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ from yunohost.utils.resources import AppResourceClassesByType
|
||||||
resources = sorted(AppResourceClassesByType.values(), key=lambda r: r.priority)
|
resources = sorted(AppResourceClassesByType.values(), key=lambda r: r.priority)
|
||||||
|
|
||||||
for klass in resources:
|
for klass in resources:
|
||||||
|
|
||||||
doc = klass.__doc__.replace("\n ", "\n")
|
doc = klass.__doc__.replace("\n ", "\n")
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
|
|
|
@ -32,7 +32,6 @@ def autofix_i18n_placeholders():
|
||||||
|
|
||||||
# We iterate over all keys/string in en.json
|
# We iterate over all keys/string in en.json
|
||||||
for key, string in reference.items():
|
for key, string in reference.items():
|
||||||
|
|
||||||
# Ignore check if there's no translation yet for this key
|
# Ignore check if there's no translation yet for this key
|
||||||
if key not in this_locale:
|
if key not in this_locale:
|
||||||
continue
|
continue
|
||||||
|
@ -89,7 +88,6 @@ Please fix it manually !
|
||||||
|
|
||||||
def autofix_orthotypography_and_standardized_words():
|
def autofix_orthotypography_and_standardized_words():
|
||||||
def reformat(lang, transformations):
|
def reformat(lang, transformations):
|
||||||
|
|
||||||
locale = open(f"{LOCALE_FOLDER}{lang}.json").read()
|
locale = open(f"{LOCALE_FOLDER}{lang}.json").read()
|
||||||
for pattern, replace in transformations.items():
|
for pattern, replace in transformations.items():
|
||||||
locale = re.compile(pattern).sub(replace, locale)
|
locale = re.compile(pattern).sub(replace, locale)
|
||||||
|
@ -146,11 +144,9 @@ def autofix_orthotypography_and_standardized_words():
|
||||||
|
|
||||||
|
|
||||||
def remove_stale_translated_strings():
|
def remove_stale_translated_strings():
|
||||||
|
|
||||||
reference = json.loads(open(LOCALE_FOLDER + "en.json").read())
|
reference = json.loads(open(LOCALE_FOLDER + "en.json").read())
|
||||||
|
|
||||||
for locale_file in TRANSLATION_FILES:
|
for locale_file in TRANSLATION_FILES:
|
||||||
|
|
||||||
print(locale_file)
|
print(locale_file)
|
||||||
this_locale = json.loads(
|
this_locale = json.loads(
|
||||||
open(LOCALE_FOLDER + locale_file).read(), object_pairs_hook=OrderedDict
|
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():
|
def find_expected_string_keys():
|
||||||
|
|
||||||
# Try to find :
|
# Try to find :
|
||||||
# m18n.n( "foo"
|
# m18n.n( "foo"
|
||||||
# YunohostError("foo"
|
# YunohostError("foo"
|
||||||
|
@ -197,7 +196,6 @@ undefined_keys = sorted(undefined_keys)
|
||||||
|
|
||||||
mode = sys.argv[1].strip("-")
|
mode = sys.argv[1].strip("-")
|
||||||
if mode == "check":
|
if mode == "check":
|
||||||
|
|
||||||
# Unused keys are not too problematic, will be automatically
|
# Unused keys are not too problematic, will be automatically
|
||||||
# removed by the other autoreformat script,
|
# removed by the other autoreformat script,
|
||||||
# but still informative to display them
|
# but still informative to display them
|
||||||
|
|
|
@ -32,7 +32,6 @@ def is_installed():
|
||||||
|
|
||||||
|
|
||||||
def cli(debug, quiet, output_as, timeout, args, parser):
|
def cli(debug, quiet, output_as, timeout, args, parser):
|
||||||
|
|
||||||
init_logging(interface="cli", debug=debug, quiet=quiet)
|
init_logging(interface="cli", debug=debug, quiet=quiet)
|
||||||
|
|
||||||
# Check that YunoHost is installed
|
# Check that YunoHost is installed
|
||||||
|
@ -51,7 +50,6 @@ def cli(debug, quiet, output_as, timeout, args, parser):
|
||||||
|
|
||||||
|
|
||||||
def api(debug, host, port):
|
def api(debug, host, port):
|
||||||
|
|
||||||
init_logging(interface="api", debug=debug)
|
init_logging(interface="api", debug=debug)
|
||||||
|
|
||||||
def is_installed_api():
|
def is_installed_api():
|
||||||
|
@ -71,7 +69,6 @@ def api(debug, host, port):
|
||||||
|
|
||||||
|
|
||||||
def check_command_is_valid_before_postinstall(args):
|
def check_command_is_valid_before_postinstall(args):
|
||||||
|
|
||||||
allowed_if_not_postinstalled = [
|
allowed_if_not_postinstalled = [
|
||||||
"tools postinstall",
|
"tools postinstall",
|
||||||
"tools versions",
|
"tools versions",
|
||||||
|
@ -109,7 +106,6 @@ def init_i18n():
|
||||||
|
|
||||||
|
|
||||||
def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yunohost"):
|
def init_logging(interface="cli", debug=False, quiet=False, logdir="/var/log/yunohost"):
|
||||||
|
|
||||||
logfile = os.path.join(logdir, "yunohost-%s.log" % interface)
|
logfile = os.path.join(logdir, "yunohost-%s.log" % interface)
|
||||||
|
|
||||||
if not os.path.isdir(logdir):
|
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):
|
def _app_upgradable(app_infos):
|
||||||
|
|
||||||
# Determine upgradability
|
# Determine upgradability
|
||||||
|
|
||||||
app_in_catalog = app_infos.get("from_catalog")
|
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:
|
for url in perm_all_urls:
|
||||||
|
|
||||||
# Here, we decide to completely ignore regex-type urls ...
|
# Here, we decide to completely ignore regex-type urls ...
|
||||||
# Because :
|
# Because :
|
||||||
# - displaying them in regular "yunohost app map" output creates
|
# - 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:
|
finally:
|
||||||
|
|
||||||
# If upgrade failed, try to restore the safety backup
|
# If upgrade failed, try to restore the safety backup
|
||||||
if (
|
if (
|
||||||
upgrade_failed
|
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,
|
# If upgrade failed or broke the system,
|
||||||
# raise an error and interrupt all other pending upgrades
|
# raise an error and interrupt all other pending upgrades
|
||||||
if upgrade_failed or broke_the_system:
|
if upgrade_failed or broke_the_system:
|
||||||
|
|
||||||
# display this if there are remaining apps
|
# display this if there are remaining apps
|
||||||
if apps[number + 1 :]:
|
if apps[number + 1 :]:
|
||||||
not_upgraded_apps = apps[number:]
|
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):
|
def app_manifest(app, with_screenshot=False):
|
||||||
|
|
||||||
manifest, extracted_app_folder = _extract_app(app)
|
manifest, extracted_app_folder = _extract_app(app)
|
||||||
|
|
||||||
raw_questions = manifest.get("install", {}).values()
|
raw_questions = manifest.get("install", {}).values()
|
||||||
|
@ -886,7 +881,6 @@ def app_manifest(app, with_screenshot=False):
|
||||||
|
|
||||||
|
|
||||||
def _confirm_app_install(app, force=False):
|
def _confirm_app_install(app, force=False):
|
||||||
|
|
||||||
# Ignore if there's nothing for confirm (good quality app), if --force is used
|
# 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)
|
# or if request on the API (confirm already implemented on the API side)
|
||||||
if force or Moulinette.interface.type == "api":
|
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 v2+, save all install questions as settings
|
||||||
if packaging_format >= 2:
|
if packaging_format >= 2:
|
||||||
for question in questions:
|
for question in questions:
|
||||||
|
|
||||||
# Except user-provider passwords
|
# Except user-provider passwords
|
||||||
if question.type == "password":
|
if question.type == "password":
|
||||||
continue
|
continue
|
||||||
|
@ -1135,7 +1128,6 @@ def app_install(
|
||||||
|
|
||||||
# If the install failed or broke the system, we remove it
|
# If the install failed or broke the system, we remove it
|
||||||
if install_failed or broke_the_system:
|
if install_failed or broke_the_system:
|
||||||
|
|
||||||
# This option is meant for packagers to debug their apps more easily
|
# This option is meant for packagers to debug their apps more easily
|
||||||
if no_remove_on_failure:
|
if no_remove_on_failure:
|
||||||
raise YunohostError(
|
raise YunohostError(
|
||||||
|
@ -1390,7 +1382,6 @@ def app_setting(app, key, value=None, delete=False):
|
||||||
)
|
)
|
||||||
|
|
||||||
if is_legacy_permission_setting:
|
if is_legacy_permission_setting:
|
||||||
|
|
||||||
from yunohost.permission import (
|
from yunohost.permission import (
|
||||||
user_permission_list,
|
user_permission_list,
|
||||||
user_permission_update,
|
user_permission_update,
|
||||||
|
@ -1433,7 +1424,6 @@ def app_setting(app, key, value=None, delete=False):
|
||||||
|
|
||||||
# SET
|
# SET
|
||||||
else:
|
else:
|
||||||
|
|
||||||
urls = value
|
urls = value
|
||||||
# If the request is about the root of the app (/), ( = the vast majority of cases)
|
# 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
|
# we interpret this as a change for the main permission
|
||||||
|
@ -1445,7 +1435,6 @@ def app_setting(app, key, value=None, delete=False):
|
||||||
else:
|
else:
|
||||||
user_permission_update(app + ".main", remove="visitors")
|
user_permission_update(app + ".main", remove="visitors")
|
||||||
else:
|
else:
|
||||||
|
|
||||||
urls = urls.split(",")
|
urls = urls.split(",")
|
||||||
if key.endswith("_regex"):
|
if key.endswith("_regex"):
|
||||||
urls = ["re:" + url for url in urls]
|
urls = ["re:" + url for url in urls]
|
||||||
|
@ -1604,7 +1593,6 @@ def app_ssowatconf():
|
||||||
)
|
)
|
||||||
|
|
||||||
for app in _installed_apps():
|
for app in _installed_apps():
|
||||||
|
|
||||||
app_settings = read_yaml(APPS_SETTING_PATH + app + "/settings.yml") or {}
|
app_settings = read_yaml(APPS_SETTING_PATH + app + "/settings.yml") or {}
|
||||||
|
|
||||||
# Redirected
|
# Redirected
|
||||||
|
@ -1630,7 +1618,6 @@ def app_ssowatconf():
|
||||||
|
|
||||||
# New permission system
|
# New permission system
|
||||||
for perm_name, perm_info in all_permissions.items():
|
for perm_name, perm_info in all_permissions.items():
|
||||||
|
|
||||||
uris = (
|
uris = (
|
||||||
[]
|
[]
|
||||||
+ ([perm_info["url"]] if perm_info["url"] else [])
|
+ ([perm_info["url"]] if perm_info["url"] else [])
|
||||||
|
@ -1694,13 +1681,11 @@ def app_change_label(app, new_label):
|
||||||
|
|
||||||
|
|
||||||
def app_action_list(app):
|
def app_action_list(app):
|
||||||
|
|
||||||
return AppConfigPanel(app).list_actions()
|
return AppConfigPanel(app).list_actions()
|
||||||
|
|
||||||
|
|
||||||
@is_unit_operation()
|
@is_unit_operation()
|
||||||
def app_action_run(operation_logger, app, action, args=None, args_file=None):
|
def app_action_run(operation_logger, app, action, args=None, args_file=None):
|
||||||
|
|
||||||
return AppConfigPanel(app).run_action(
|
return AppConfigPanel(app).run_action(
|
||||||
action, args=args, args_file=args_file, operation_logger=operation_logger
|
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):
|
def _parse_app_doc_and_notifications(path):
|
||||||
|
|
||||||
doc = {}
|
doc = {}
|
||||||
notification_names = ["PRE_INSTALL", "POST_INSTALL", "PRE_UPGRADE", "POST_UPGRADE"]
|
notification_names = ["PRE_INSTALL", "POST_INSTALL", "PRE_UPGRADE", "POST_UPGRADE"]
|
||||||
|
|
||||||
for filepath in glob.glob(os.path.join(path, "doc") + "/*.md"):
|
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
|
# to be improved : [a-z]{2,3} is a clumsy way of parsing the
|
||||||
# lang code ... some lang code are more complex that this é_è
|
# lang code ... some lang code are more complex that this é_è
|
||||||
m = re.match("([A-Z]*)(_[a-z]{2,3})?.md", filepath.split("/")[-1])
|
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):
|
def _hydrate_app_template(template, data):
|
||||||
|
|
||||||
stuff_to_replace = set(re.findall(r"__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__", template))
|
stuff_to_replace = set(re.findall(r"__[A-Z0-9]+?[A-Z0-9_]*?[A-Z0-9]*?__", template))
|
||||||
|
|
||||||
for stuff in stuff_to_replace:
|
for stuff in stuff_to_replace:
|
||||||
|
|
||||||
varname = stuff.strip("_").lower()
|
varname = stuff.strip("_").lower()
|
||||||
|
|
||||||
if varname in data:
|
if varname in data:
|
||||||
|
@ -2105,7 +2086,6 @@ def _hydrate_app_template(template, data):
|
||||||
|
|
||||||
|
|
||||||
def _convert_v1_manifest_to_v2(manifest):
|
def _convert_v1_manifest_to_v2(manifest):
|
||||||
|
|
||||||
manifest = copy.deepcopy(manifest)
|
manifest = copy.deepcopy(manifest)
|
||||||
|
|
||||||
if "upstream" not in 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"):
|
def _set_default_ask_questions(questions, script_name="install"):
|
||||||
|
|
||||||
# arguments is something like
|
# arguments is something like
|
||||||
# { "domain":
|
# { "domain":
|
||||||
# {
|
# {
|
||||||
|
@ -2244,7 +2223,6 @@ def _set_default_ask_questions(questions, script_name="install"):
|
||||||
|
|
||||||
|
|
||||||
def _is_app_repo_url(string: str) -> bool:
|
def _is_app_repo_url(string: str) -> bool:
|
||||||
|
|
||||||
string = string.strip()
|
string = string.strip()
|
||||||
|
|
||||||
# Dummy test for ssh-based stuff ... should probably be improved somehow
|
# 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"]
|
raw_app_catalog = _load_apps_catalog()["apps"]
|
||||||
if src in raw_app_catalog or _is_app_repo_url(src):
|
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 we got an app name directly (e.g. just "wordpress"), we gonna test this name
|
||||||
if src in raw_app_catalog:
|
if src in raw_app_catalog:
|
||||||
app_name_to_test = src
|
app_name_to_test = src
|
||||||
|
@ -2274,7 +2251,6 @@ def _app_quality(src: str) -> str:
|
||||||
return "thirdparty"
|
return "thirdparty"
|
||||||
|
|
||||||
if app_name_to_test in raw_app_catalog:
|
if app_name_to_test in raw_app_catalog:
|
||||||
|
|
||||||
state = raw_app_catalog[app_name_to_test].get("state", "notworking")
|
state = raw_app_catalog[app_name_to_test].get("state", "notworking")
|
||||||
level = raw_app_catalog[app_name_to_test].get("level", None)
|
level = raw_app_catalog[app_name_to_test].get("level", None)
|
||||||
if state in ["working", "validated"]:
|
if state in ["working", "validated"]:
|
||||||
|
@ -2385,7 +2361,6 @@ def _extract_app_from_folder(path: str) -> Tuple[Dict, str]:
|
||||||
def _extract_app_from_gitrepo(
|
def _extract_app_from_gitrepo(
|
||||||
url: str, branch: Optional[str] = None, revision: str = "HEAD", app_info: Dict = {}
|
url: str, branch: Optional[str] = None, revision: str = "HEAD", app_info: Dict = {}
|
||||||
) -> Tuple[Dict, str]:
|
) -> Tuple[Dict, str]:
|
||||||
|
|
||||||
logger.debug("Checking default branch")
|
logger.debug("Checking default branch")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -2635,7 +2610,6 @@ def _check_manifest_requirements(
|
||||||
|
|
||||||
|
|
||||||
def _guess_webapp_path_requirement(app_folder: str) -> str:
|
def _guess_webapp_path_requirement(app_folder: str) -> str:
|
||||||
|
|
||||||
# If there's only one "domain" and "path", validate that domain/path
|
# If there's only one "domain" and "path", validate that domain/path
|
||||||
# is an available url and normalize the 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(
|
def _validate_webpath_requirement(
|
||||||
args: Dict[str, Any], path_requirement: str, ignore_app=None
|
args: Dict[str, Any], path_requirement: str, ignore_app=None
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
domain = args.get("domain")
|
domain = args.get("domain")
|
||||||
path = args.get("path")
|
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):
|
def _assert_no_conflicting_apps(domain, path, ignore_app=None, full_domain=False):
|
||||||
|
|
||||||
conflicts = _get_conflicting_apps(domain, path, ignore_app)
|
conflicts = _get_conflicting_apps(domain, path, ignore_app)
|
||||||
|
|
||||||
if conflicts:
|
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(
|
def _make_environment_for_app_script(
|
||||||
app, args={}, args_prefix="APP_ARG_", workdir=None, action=None
|
app, args={}, args_prefix="APP_ARG_", workdir=None, action=None
|
||||||
):
|
):
|
||||||
|
|
||||||
app_setting_path = os.path.join(APPS_SETTING_PATH, app)
|
app_setting_path = os.path.join(APPS_SETTING_PATH, app)
|
||||||
|
|
||||||
manifest = _get_manifest_of_app(app_setting_path)
|
manifest = _get_manifest_of_app(app_setting_path)
|
||||||
|
@ -2777,7 +2748,6 @@ def _make_environment_for_app_script(
|
||||||
if manifest["packaging_format"] >= 2:
|
if manifest["packaging_format"] >= 2:
|
||||||
env_dict["app"] = app
|
env_dict["app"] = app
|
||||||
for setting_name, setting_value in _get_app_settings(app).items():
|
for setting_name, setting_value in _get_app_settings(app).items():
|
||||||
|
|
||||||
# Ignore special internal settings like checksum__
|
# Ignore special internal settings like checksum__
|
||||||
# (not a huge deal to load them but idk...)
|
# (not a huge deal to load them but idk...)
|
||||||
if setting_name.startswith("checksum__"):
|
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):
|
def _next_instance_number_for_app(app):
|
||||||
|
|
||||||
# Get list of sibling apps, such as {app}, {app}__2, {app}__4
|
# Get list of sibling apps, such as {app}, {app}__2, {app}__4
|
||||||
apps = _installed_apps()
|
apps = _installed_apps()
|
||||||
sibling_app_ids = [a for a in apps if a == app or a.startswith(f"{app}__")]
|
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):
|
def _make_tmp_workdir_for_app(app=None):
|
||||||
|
|
||||||
# Create parent dir if it doesn't exists yet
|
# Create parent dir if it doesn't exists yet
|
||||||
if not os.path.exists(APP_TMP_WORKDIRS):
|
if not os.path.exists(APP_TMP_WORKDIRS):
|
||||||
os.makedirs(APP_TMP_WORKDIRS)
|
os.makedirs(APP_TMP_WORKDIRS)
|
||||||
|
@ -2870,12 +2838,10 @@ def _make_tmp_workdir_for_app(app=None):
|
||||||
|
|
||||||
|
|
||||||
def unstable_apps():
|
def unstable_apps():
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
deprecated_apps = ["mailman", "ffsync"]
|
deprecated_apps = ["mailman", "ffsync"]
|
||||||
|
|
||||||
for infos in app_list(full=True)["apps"]:
|
for infos in app_list(full=True)["apps"]:
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not infos.get("from_catalog")
|
not infos.get("from_catalog")
|
||||||
or infos.get("from_catalog").get("state")
|
or infos.get("from_catalog").get("state")
|
||||||
|
@ -2891,7 +2857,6 @@ def unstable_apps():
|
||||||
|
|
||||||
|
|
||||||
def _assert_system_is_sane_for_app(manifest, when):
|
def _assert_system_is_sane_for_app(manifest, when):
|
||||||
|
|
||||||
from yunohost.service import service_status
|
from yunohost.service import service_status
|
||||||
|
|
||||||
logger.debug("Checking that required services are up and running...")
|
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):
|
def app_dismiss_notification(app, name):
|
||||||
|
|
||||||
assert isinstance(name, str)
|
assert isinstance(name, str)
|
||||||
name = name.lower()
|
name = name.lower()
|
||||||
assert name in ["post_install", "post_upgrade"]
|
assert name in ["post_install", "post_upgrade"]
|
||||||
|
|
|
@ -157,7 +157,6 @@ def _read_apps_catalog_list():
|
||||||
|
|
||||||
|
|
||||||
def _actual_apps_catalog_api_url(base_url):
|
def _actual_apps_catalog_api_url(base_url):
|
||||||
|
|
||||||
return f"{base_url}/v{APPS_CATALOG_API_VERSION}/apps.json"
|
return f"{base_url}/v{APPS_CATALOG_API_VERSION}/apps.json"
|
||||||
|
|
||||||
|
|
||||||
|
@ -269,7 +268,6 @@ def _load_apps_catalog():
|
||||||
merged_catalog = {"apps": {}, "categories": [], "antifeatures": []}
|
merged_catalog = {"apps": {}, "categories": [], "antifeatures": []}
|
||||||
|
|
||||||
for apps_catalog_id in [L["id"] for L in _read_apps_catalog_list()]:
|
for apps_catalog_id in [L["id"] for L in _read_apps_catalog_list()]:
|
||||||
|
|
||||||
# Let's load the json from cache for this catalog
|
# Let's load the json from cache for this catalog
|
||||||
cache_file = f"{APPS_CATALOG_CACHE}/{apps_catalog_id}.json"
|
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
|
# Add apps from this catalog to the output
|
||||||
for app, info in apps_catalog_content["apps"].items():
|
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 ...
|
# (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)
|
# in which case we keep only the first one found)
|
||||||
if app in merged_catalog["apps"]:
|
if app in merged_catalog["apps"]:
|
||||||
|
|
|
@ -38,14 +38,12 @@ AUTH_DN = "uid={uid},ou=users,dc=yunohost,dc=org"
|
||||||
|
|
||||||
|
|
||||||
class Authenticator(BaseAuthenticator):
|
class Authenticator(BaseAuthenticator):
|
||||||
|
|
||||||
name = "ldap_admin"
|
name = "ldap_admin"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _authenticate_credentials(self, credentials=None):
|
def _authenticate_credentials(self, credentials=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
admins = (
|
admins = (
|
||||||
_get_ldap_interface()
|
_get_ldap_interface()
|
||||||
|
@ -125,7 +123,6 @@ class Authenticator(BaseAuthenticator):
|
||||||
con.unbind_s()
|
con.unbind_s()
|
||||||
|
|
||||||
def set_session_cookie(self, infos):
|
def set_session_cookie(self, infos):
|
||||||
|
|
||||||
from bottle import response
|
from bottle import response
|
||||||
|
|
||||||
assert isinstance(infos, dict)
|
assert isinstance(infos, dict)
|
||||||
|
@ -145,7 +142,6 @@ class Authenticator(BaseAuthenticator):
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_session_cookie(self, raise_if_no_session_exists=True):
|
def get_session_cookie(self, raise_if_no_session_exists=True):
|
||||||
|
|
||||||
from bottle import request
|
from bottle import request
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -174,7 +170,6 @@ class Authenticator(BaseAuthenticator):
|
||||||
return infos
|
return infos
|
||||||
|
|
||||||
def delete_session_cookie(self):
|
def delete_session_cookie(self):
|
||||||
|
|
||||||
from bottle import response
|
from bottle import response
|
||||||
|
|
||||||
response.set_cookie("yunohost.admin", "", max_age=-1)
|
response.set_cookie("yunohost.admin", "", max_age=-1)
|
||||||
|
|
|
@ -93,7 +93,6 @@ class BackupRestoreTargetsManager:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.targets = {}
|
self.targets = {}
|
||||||
self.results = {"system": {}, "apps": {}}
|
self.results = {"system": {}, "apps": {}}
|
||||||
|
|
||||||
|
@ -349,7 +348,6 @@ class BackupManager:
|
||||||
if not os.path.isdir(self.work_dir):
|
if not os.path.isdir(self.work_dir):
|
||||||
mkdir(self.work_dir, 0o750, parents=True)
|
mkdir(self.work_dir, 0o750, parents=True)
|
||||||
elif self.is_tmp_work_dir:
|
elif self.is_tmp_work_dir:
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"temporary directory for backup '%s' already exists... attempting to clean it",
|
"temporary directory for backup '%s' already exists... attempting to clean it",
|
||||||
self.work_dir,
|
self.work_dir,
|
||||||
|
@ -887,7 +885,6 @@ class RestoreManager:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def success(self):
|
def success(self):
|
||||||
|
|
||||||
successful_apps = self.targets.list("apps", include=["Success", "Warning"])
|
successful_apps = self.targets.list("apps", include=["Success", "Warning"])
|
||||||
successful_system = self.targets.list("system", include=["Success", "Warning"])
|
successful_system = self.targets.list("system", include=["Success", "Warning"])
|
||||||
|
|
||||||
|
@ -1443,7 +1440,6 @@ class RestoreManager:
|
||||||
existing_groups = user_group_list()["groups"]
|
existing_groups = user_group_list()["groups"]
|
||||||
|
|
||||||
for permission_name, permission_infos in permissions.items():
|
for permission_name, permission_infos in permissions.items():
|
||||||
|
|
||||||
if "allowed" not in permission_infos:
|
if "allowed" not in permission_infos:
|
||||||
logger.warning(
|
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."
|
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")
|
self.targets.set_result("apps", app_instance_name, "Success")
|
||||||
operation_logger.success()
|
operation_logger.success()
|
||||||
else:
|
else:
|
||||||
|
|
||||||
self.targets.set_result("apps", app_instance_name, "Error")
|
self.targets.set_result("apps", app_instance_name, "Error")
|
||||||
|
|
||||||
remove_script = os.path.join(app_scripts_in_archive, "remove")
|
remove_script = os.path.join(app_scripts_in_archive, "remove")
|
||||||
|
@ -1938,12 +1933,10 @@ class CopyBackupMethod(BackupMethod):
|
||||||
|
|
||||||
|
|
||||||
class TarBackupMethod(BackupMethod):
|
class TarBackupMethod(BackupMethod):
|
||||||
|
|
||||||
method_name = "tar"
|
method_name = "tar"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _archive_file(self):
|
def _archive_file(self):
|
||||||
|
|
||||||
if isinstance(self.manager, BackupManager) and settings_get(
|
if isinstance(self.manager, BackupManager) and settings_get(
|
||||||
"misc.backup.backup_compress_tar_archives"
|
"misc.backup.backup_compress_tar_archives"
|
||||||
):
|
):
|
||||||
|
@ -2430,7 +2423,6 @@ def backup_list(with_info=False, human_readable=False):
|
||||||
|
|
||||||
|
|
||||||
def backup_download(name):
|
def backup_download(name):
|
||||||
|
|
||||||
if Moulinette.interface.type != "api":
|
if Moulinette.interface.type != "api":
|
||||||
logger.error(
|
logger.error(
|
||||||
"This option is only meant for the API/webadmin and doesn't make sense for the command line."
|
"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():
|
if "size_details" in info.keys():
|
||||||
for category in ["apps", "system"]:
|
for category in ["apps", "system"]:
|
||||||
for name, key_info in info[category].items():
|
for name, key_info in info[category].items():
|
||||||
|
|
||||||
if category == "system":
|
if category == "system":
|
||||||
# Stupid legacy fix for weird format between 3.5 and 3.6
|
# Stupid legacy fix for weird format between 3.5 and 3.6
|
||||||
if isinstance(key_info, dict):
|
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):
|
def _certificate_install_selfsigned(domain_list, force=False):
|
||||||
|
|
||||||
failed_cert_install = []
|
failed_cert_install = []
|
||||||
for domain in domain_list:
|
for domain in domain_list:
|
||||||
|
|
||||||
operation_logger = OperationLogger(
|
operation_logger = OperationLogger(
|
||||||
"selfsigned_cert_install", [("domain", domain)], args={"force": force}
|
"selfsigned_cert_install", [("domain", domain)], args={"force": force}
|
||||||
)
|
)
|
||||||
|
@ -238,7 +236,6 @@ def _certificate_install_letsencrypt(domains, force=False, no_checks=False):
|
||||||
# certificates
|
# certificates
|
||||||
if domains == []:
|
if domains == []:
|
||||||
for domain in domain_list()["domains"]:
|
for domain in domain_list()["domains"]:
|
||||||
|
|
||||||
status = _get_status(domain)
|
status = _get_status(domain)
|
||||||
if status["CA_type"] != "selfsigned":
|
if status["CA_type"] != "selfsigned":
|
||||||
continue
|
continue
|
||||||
|
@ -260,7 +257,6 @@ def _certificate_install_letsencrypt(domains, force=False, no_checks=False):
|
||||||
# Actual install steps
|
# Actual install steps
|
||||||
failed_cert_install = []
|
failed_cert_install = []
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
|
|
||||||
if not no_checks:
|
if not no_checks:
|
||||||
try:
|
try:
|
||||||
_check_domain_is_ready_for_ACME(domain)
|
_check_domain_is_ready_for_ACME(domain)
|
||||||
|
@ -317,7 +313,6 @@ def certificate_renew(domains, force=False, no_checks=False, email=False):
|
||||||
# certificates
|
# certificates
|
||||||
if domains == []:
|
if domains == []:
|
||||||
for domain in domain_list()["domains"]:
|
for domain in domain_list()["domains"]:
|
||||||
|
|
||||||
# Does it have a Let's Encrypt cert?
|
# Does it have a Let's Encrypt cert?
|
||||||
status = _get_status(domain)
|
status = _get_status(domain)
|
||||||
if status["CA_type"] != "letsencrypt":
|
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, validate the domain list given
|
||||||
else:
|
else:
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
|
|
||||||
# Is it in Yunohost domain list?
|
# Is it in Yunohost domain list?
|
||||||
_assert_domain_exists(domain)
|
_assert_domain_exists(domain)
|
||||||
|
|
||||||
|
@ -369,7 +363,6 @@ def certificate_renew(domains, force=False, no_checks=False, email=False):
|
||||||
# Actual renew steps
|
# Actual renew steps
|
||||||
failed_cert_install = []
|
failed_cert_install = []
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
|
|
||||||
if not no_checks:
|
if not no_checks:
|
||||||
try:
|
try:
|
||||||
_check_domain_is_ready_for_ACME(domain)
|
_check_domain_is_ready_for_ACME(domain)
|
||||||
|
@ -468,13 +461,11 @@ investigate :
|
||||||
|
|
||||||
|
|
||||||
def _check_acme_challenge_configuration(domain):
|
def _check_acme_challenge_configuration(domain):
|
||||||
|
|
||||||
domain_conf = f"/etc/nginx/conf.d/{domain}.conf"
|
domain_conf = f"/etc/nginx/conf.d/{domain}.conf"
|
||||||
return "include /etc/nginx/conf.d/acme-challenge.conf.inc" in read_file(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):
|
def _fetch_and_enable_new_certificate(domain, no_checks=False):
|
||||||
|
|
||||||
if not os.path.exists(ACCOUNT_KEY_FILE):
|
if not os.path.exists(ACCOUNT_KEY_FILE):
|
||||||
_generate_account_key()
|
_generate_account_key()
|
||||||
|
|
||||||
|
@ -628,7 +619,6 @@ def _prepare_certificate_signing_request(domain, key_file, output_folder):
|
||||||
|
|
||||||
|
|
||||||
def _get_status(domain):
|
def _get_status(domain):
|
||||||
|
|
||||||
cert_file = os.path.join(CERT_FOLDER, domain, "crt.pem")
|
cert_file = os.path.join(CERT_FOLDER, domain, "crt.pem")
|
||||||
|
|
||||||
if not os.path.isfile(cert_file):
|
if not os.path.isfile(cert_file):
|
||||||
|
@ -777,7 +767,6 @@ def _backup_current_cert(domain):
|
||||||
|
|
||||||
|
|
||||||
def _check_domain_is_ready_for_ACME(domain):
|
def _check_domain_is_ready_for_ACME(domain):
|
||||||
|
|
||||||
from yunohost.domain import _get_parent_domain_of
|
from yunohost.domain import _get_parent_domain_of
|
||||||
from yunohost.dns import _get_dns_zone_for_domain
|
from yunohost.dns import _get_dns_zone_for_domain
|
||||||
from yunohost.utils.dns import is_yunohost_dyndns_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...
|
# For all domain files in DNSmasq conf...
|
||||||
domainsconf = glob.glob("/etc/dnsmasq.d/*.*")
|
domainsconf = glob.glob("/etc/dnsmasq.d/*.*")
|
||||||
for domainconf in domainsconf:
|
for domainconf in domainsconf:
|
||||||
|
|
||||||
# Look for the IP, it's in the lines with this format :
|
# Look for the IP, it's in the lines with this format :
|
||||||
# host-record=the.domain.tld,11.22.33.44
|
# host-record=the.domain.tld,11.22.33.44
|
||||||
for line in open(domainconf).readlines():
|
for line in open(domainconf).readlines():
|
||||||
|
|
|
@ -35,13 +35,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
virt = system_virt()
|
virt = system_virt()
|
||||||
if virt.lower() == "none":
|
if virt.lower() == "none":
|
||||||
virt = "bare-metal"
|
virt = "bare-metal"
|
||||||
|
@ -193,7 +191,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
)
|
)
|
||||||
|
|
||||||
def bad_sury_packages(self):
|
def bad_sury_packages(self):
|
||||||
|
|
||||||
packages_to_check = ["openssl", "libssl1.1", "libssl-dev"]
|
packages_to_check = ["openssl", "libssl1.1", "libssl-dev"]
|
||||||
for package in packages_to_check:
|
for package in packages_to_check:
|
||||||
cmd = "dpkg --list | grep '^ii' | grep gbp | grep -q -w %s" % package
|
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)
|
yield (package, version_to_downgrade_to)
|
||||||
|
|
||||||
def backports_in_sources_list(self):
|
def backports_in_sources_list(self):
|
||||||
|
|
||||||
cmd = "grep -q -nr '^ *deb .*-backports' /etc/apt/sources.list*"
|
cmd = "grep -q -nr '^ *deb .*-backports' /etc/apt/sources.list*"
|
||||||
return os.system(cmd) == 0
|
return os.system(cmd) == 0
|
||||||
|
|
||||||
def number_of_recent_auth_failure(self):
|
def number_of_recent_auth_failure(self):
|
||||||
|
|
||||||
# Those syslog facilities correspond to auth and authpriv
|
# Those syslog facilities correspond to auth and authpriv
|
||||||
# c.f. https://unix.stackexchange.com/a/401398
|
# c.f. https://unix.stackexchange.com/a/401398
|
||||||
# and https://wiki.archlinux.org/title/Systemd/Journal#Facility
|
# and https://wiki.archlinux.org/title/Systemd/Journal#Facility
|
||||||
|
|
|
@ -34,13 +34,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
# ############################################################ #
|
# ############################################################ #
|
||||||
# PING : Check that we can ping outside at least in ipv4 or v6 #
|
# 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 ?) ?
|
# TODO / FIXME : add some attempt to detect ISP (using whois ?) ?
|
||||||
|
|
||||||
def can_ping_outside(self, protocol=4):
|
def can_ping_outside(self, protocol=4):
|
||||||
|
|
||||||
assert protocol in [
|
assert protocol in [
|
||||||
4,
|
4,
|
||||||
6,
|
6,
|
||||||
|
@ -234,7 +231,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
return len(content) == 1 and content[0].split() == ["nameserver", "127.0.0.1"]
|
return len(content) == 1 and content[0].split() == ["nameserver", "127.0.0.1"]
|
||||||
|
|
||||||
def get_public_ip(self, protocol=4):
|
def get_public_ip(self, protocol=4):
|
||||||
|
|
||||||
# FIXME - TODO : here we assume that DNS resolution for ip.yunohost.org is working
|
# 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
|
# but if we want to be able to diagnose DNS resolution issues independently from
|
||||||
# internet connectivity, we gotta rely on fixed IPs first....
|
# internet connectivity, we gotta rely on fixed IPs first....
|
||||||
|
|
|
@ -43,13 +43,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = ["ip"]
|
dependencies: List[str] = ["ip"]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
main_domain = _get_maindomain()
|
main_domain = _get_maindomain()
|
||||||
|
|
||||||
major_domains = domain_list(exclude_subdomains=True)["domains"]
|
major_domains = domain_list(exclude_subdomains=True)["domains"]
|
||||||
|
@ -77,7 +75,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
yield report
|
yield report
|
||||||
|
|
||||||
def check_domain(self, domain, is_main_domain):
|
def check_domain(self, domain, is_main_domain):
|
||||||
|
|
||||||
if is_special_use_tld(domain):
|
if is_special_use_tld(domain):
|
||||||
yield dict(
|
yield dict(
|
||||||
meta={"domain": domain},
|
meta={"domain": domain},
|
||||||
|
@ -97,13 +94,11 @@ class MyDiagnoser(Diagnoser):
|
||||||
categories = ["basic", "mail", "xmpp", "extra"]
|
categories = ["basic", "mail", "xmpp", "extra"]
|
||||||
|
|
||||||
for category in categories:
|
for category in categories:
|
||||||
|
|
||||||
records = expected_configuration[category]
|
records = expected_configuration[category]
|
||||||
discrepancies = []
|
discrepancies = []
|
||||||
results = {}
|
results = {}
|
||||||
|
|
||||||
for r in records:
|
for r in records:
|
||||||
|
|
||||||
id_ = r["type"] + ":" + r["name"]
|
id_ = r["type"] + ":" + r["name"]
|
||||||
fqdn = r["name"] + "." + base_dns_zone if r["name"] != "@" else domain
|
fqdn = r["name"] + "." + base_dns_zone if r["name"] != "@" else domain
|
||||||
|
|
||||||
|
@ -182,7 +177,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
yield output
|
yield output
|
||||||
|
|
||||||
def get_current_record(self, fqdn, type_):
|
def get_current_record(self, fqdn, type_):
|
||||||
|
|
||||||
success, answers = dig(fqdn, type_, resolvers="force_external")
|
success, answers = dig(fqdn, type_, resolvers="force_external")
|
||||||
|
|
||||||
if success != "ok":
|
if success != "ok":
|
||||||
|
|
|
@ -25,13 +25,11 @@ from yunohost.settings import settings_get
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = ["ip"]
|
dependencies: List[str] = ["ip"]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
# TODO: report a warning if port 53 or 5353 is exposed to the outside world...
|
# TODO: report a warning if port 53 or 5353 is exposed to the outside world...
|
||||||
|
|
||||||
# This dict is something like :
|
# This dict is something like :
|
||||||
|
|
|
@ -32,17 +32,14 @@ DIAGNOSIS_SERVER = "diagnosis.yunohost.org"
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = ["ip"]
|
dependencies: List[str] = ["ip"]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
all_domains = domain_list()["domains"]
|
all_domains = domain_list()["domains"]
|
||||||
domains_to_check = []
|
domains_to_check = []
|
||||||
for domain in all_domains:
|
for domain in all_domains:
|
||||||
|
|
||||||
# If the diagnosis location ain't defined, can't do diagnosis,
|
# If the diagnosis location ain't defined, can't do diagnosis,
|
||||||
# probably because nginx conf manually modified...
|
# probably because nginx conf manually modified...
|
||||||
nginx_conf = "/etc/nginx/conf.d/%s.conf" % domain
|
nginx_conf = "/etc/nginx/conf.d/%s.conf" % domain
|
||||||
|
@ -119,7 +116,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_http(self, domains, ipversions):
|
def test_http(self, domains, ipversions):
|
||||||
|
|
||||||
results = {}
|
results = {}
|
||||||
for ipversion in ipversions:
|
for ipversion in ipversions:
|
||||||
try:
|
try:
|
||||||
|
@ -144,7 +140,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
return
|
return
|
||||||
|
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
|
|
||||||
# i18n: diagnosis_http_bad_status_code
|
# i18n: diagnosis_http_bad_status_code
|
||||||
# i18n: diagnosis_http_connection_error
|
# i18n: diagnosis_http_connection_error
|
||||||
# i18n: diagnosis_http_timeout
|
# i18n: diagnosis_http_timeout
|
||||||
|
|
|
@ -39,13 +39,11 @@ logger = log.getActionLogger("yunohost.diagnosis")
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 600
|
cache_duration = 600
|
||||||
dependencies: List[str] = ["ip"]
|
dependencies: List[str] = ["ip"]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
self.ehlo_domain = _get_maindomain()
|
self.ehlo_domain = _get_maindomain()
|
||||||
self.mail_domains = domain_list()["domains"]
|
self.mail_domains = domain_list()["domains"]
|
||||||
self.ipversions, self.ips = self.get_ips_checked()
|
self.ipversions, self.ips = self.get_ips_checked()
|
||||||
|
|
|
@ -24,17 +24,14 @@ from yunohost.service import service_status
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 300
|
cache_duration = 300
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
all_result = service_status()
|
all_result = service_status()
|
||||||
|
|
||||||
for service, result in sorted(all_result.items()):
|
for service, result in sorted(all_result.items()):
|
||||||
|
|
||||||
item = dict(
|
item = dict(
|
||||||
meta={"service": service},
|
meta={"service": service},
|
||||||
data={
|
data={
|
||||||
|
|
|
@ -28,13 +28,11 @@ from yunohost.diagnosis import Diagnoser
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 300
|
cache_duration = 300
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
MB = 1024**2
|
MB = 1024**2
|
||||||
GB = MB * 1024
|
GB = MB * 1024
|
||||||
|
|
||||||
|
@ -189,7 +187,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def analyzed_kern_log():
|
def analyzed_kern_log():
|
||||||
|
|
||||||
cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true'
|
cmd = 'tail -n 10000 /var/log/kern.log | grep "oom_reaper: reaped process" || true'
|
||||||
out = check_output(cmd)
|
out = check_output(cmd)
|
||||||
lines = out.split("\n") if out else []
|
lines = out.split("\n") if out else []
|
||||||
|
|
|
@ -27,13 +27,11 @@ from moulinette.utils.filesystem import read_file
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 300
|
cache_duration = 300
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
regenconf_modified_files = list(self.manually_modified_files())
|
regenconf_modified_files = list(self.manually_modified_files())
|
||||||
|
|
||||||
if not regenconf_modified_files:
|
if not regenconf_modified_files:
|
||||||
|
@ -82,7 +80,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
)
|
)
|
||||||
|
|
||||||
def manually_modified_files(self):
|
def manually_modified_files(self):
|
||||||
|
|
||||||
for category, infos in _get_regenconf_infos().items():
|
for category, infos in _get_regenconf_infos().items():
|
||||||
for path, hash_ in infos["conffiles"].items():
|
for path, hash_ in infos["conffiles"].items():
|
||||||
if hash_ != _calculate_hash(path):
|
if hash_ != _calculate_hash(path):
|
||||||
|
|
|
@ -25,13 +25,11 @@ from yunohost.diagnosis import Diagnoser
|
||||||
|
|
||||||
|
|
||||||
class MyDiagnoser(Diagnoser):
|
class MyDiagnoser(Diagnoser):
|
||||||
|
|
||||||
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
|
||||||
cache_duration = 300
|
cache_duration = 300
|
||||||
dependencies: List[str] = []
|
dependencies: List[str] = []
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
apps = app_list(full=True)["apps"]
|
apps = app_list(full=True)["apps"]
|
||||||
for app in apps:
|
for app in apps:
|
||||||
app["issues"] = list(self.issues(app))
|
app["issues"] = list(self.issues(app))
|
||||||
|
@ -44,7 +42,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
for app in apps:
|
for app in apps:
|
||||||
|
|
||||||
if not app["issues"]:
|
if not app["issues"]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -62,7 +59,6 @@ class MyDiagnoser(Diagnoser):
|
||||||
)
|
)
|
||||||
|
|
||||||
def issues(self, app):
|
def issues(self, app):
|
||||||
|
|
||||||
# Check quality level in catalog
|
# Check quality level in catalog
|
||||||
|
|
||||||
if not app.get("from_catalog") or app["from_catalog"].get("state") != "working":
|
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):
|
def diagnosis_get(category, item):
|
||||||
|
|
||||||
# Get all the categories
|
# Get all the categories
|
||||||
all_categories_names = _list_diagnosis_categories()
|
all_categories_names = _list_diagnosis_categories()
|
||||||
|
|
||||||
|
@ -69,7 +68,6 @@ def diagnosis_get(category, item):
|
||||||
def diagnosis_show(
|
def diagnosis_show(
|
||||||
categories=[], issues=False, full=False, share=False, human_readable=False
|
categories=[], issues=False, full=False, share=False, human_readable=False
|
||||||
):
|
):
|
||||||
|
|
||||||
if not os.path.exists(DIAGNOSIS_CACHE):
|
if not os.path.exists(DIAGNOSIS_CACHE):
|
||||||
logger.warning(m18n.n("diagnosis_never_ran_yet"))
|
logger.warning(m18n.n("diagnosis_never_ran_yet"))
|
||||||
return
|
return
|
||||||
|
@ -90,7 +88,6 @@ def diagnosis_show(
|
||||||
# Fetch all reports
|
# Fetch all reports
|
||||||
all_reports = []
|
all_reports = []
|
||||||
for category in categories:
|
for category in categories:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
report = Diagnoser.get_cached_report(category)
|
report = Diagnoser.get_cached_report(category)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -139,7 +136,6 @@ def diagnosis_show(
|
||||||
|
|
||||||
|
|
||||||
def _dump_human_readable_reports(reports):
|
def _dump_human_readable_reports(reports):
|
||||||
|
|
||||||
output = ""
|
output = ""
|
||||||
|
|
||||||
for report in reports:
|
for report in reports:
|
||||||
|
@ -159,7 +155,6 @@ def _dump_human_readable_reports(reports):
|
||||||
def diagnosis_run(
|
def diagnosis_run(
|
||||||
categories=[], force=False, except_if_never_ran_yet=False, email=False
|
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):
|
if (email or except_if_never_ran_yet) and not os.path.exists(DIAGNOSIS_CACHE):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -263,7 +258,6 @@ def _diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
|
||||||
return {"ignore_filters": configuration.get("ignore_filters", {})}
|
return {"ignore_filters": configuration.get("ignore_filters", {})}
|
||||||
|
|
||||||
def validate_filter_criterias(filter_):
|
def validate_filter_criterias(filter_):
|
||||||
|
|
||||||
# Get all the categories
|
# Get all the categories
|
||||||
all_categories_names = _list_diagnosis_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
|
return category, criterias
|
||||||
|
|
||||||
if add_filter:
|
if add_filter:
|
||||||
|
|
||||||
category, criterias = validate_filter_criterias(add_filter)
|
category, criterias = validate_filter_criterias(add_filter)
|
||||||
|
|
||||||
# Fetch current issues for the requested category
|
# Fetch current issues for the requested category
|
||||||
|
@ -320,7 +313,6 @@ def _diagnosis_ignore(add_filter=None, remove_filter=None, list=False):
|
||||||
return
|
return
|
||||||
|
|
||||||
if remove_filter:
|
if remove_filter:
|
||||||
|
|
||||||
category, criterias = validate_filter_criterias(remove_filter)
|
category, criterias = validate_filter_criterias(remove_filter)
|
||||||
|
|
||||||
# Make sure the subdicts/lists exists
|
# Make sure the subdicts/lists exists
|
||||||
|
@ -394,12 +386,10 @@ def add_ignore_flag_to_issues(report):
|
||||||
|
|
||||||
class Diagnoser:
|
class Diagnoser:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.cache_file = Diagnoser.cache_file(self.id_)
|
self.cache_file = Diagnoser.cache_file(self.id_)
|
||||||
self.description = Diagnoser.get_description(self.id_)
|
self.description = Diagnoser.get_description(self.id_)
|
||||||
|
|
||||||
def cached_time_ago(self):
|
def cached_time_ago(self):
|
||||||
|
|
||||||
if not os.path.exists(self.cache_file):
|
if not os.path.exists(self.cache_file):
|
||||||
return 99999999
|
return 99999999
|
||||||
return time.time() - os.path.getmtime(self.cache_file)
|
return time.time() - os.path.getmtime(self.cache_file)
|
||||||
|
@ -410,7 +400,6 @@ class Diagnoser:
|
||||||
return write_to_json(self.cache_file, report)
|
return write_to_json(self.cache_file, report)
|
||||||
|
|
||||||
def diagnose(self, force=False):
|
def diagnose(self, force=False):
|
||||||
|
|
||||||
if not force and self.cached_time_ago() < self.cache_duration:
|
if not force and self.cached_time_ago() < self.cache_duration:
|
||||||
logger.debug(f"Cache still valid : {self.cache_file}")
|
logger.debug(f"Cache still valid : {self.cache_file}")
|
||||||
logger.info(
|
logger.info(
|
||||||
|
@ -548,7 +537,6 @@ class Diagnoser:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def i18n(report, force_remove_html_tags=False):
|
def i18n(report, force_remove_html_tags=False):
|
||||||
|
|
||||||
# "Render" the strings with m18n.n
|
# "Render" the strings with m18n.n
|
||||||
# N.B. : we do those m18n.n right now instead of saving the already-translated report
|
# 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
|
# 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"])
|
report["description"] = Diagnoser.get_description(report["id"])
|
||||||
|
|
||||||
for item in report["items"]:
|
for item in report["items"]:
|
||||||
|
|
||||||
# For the summary and each details, we want to call
|
# For the summary and each details, we want to call
|
||||||
# m18n() on the string, with the appropriate data for string
|
# m18n() on the string, with the appropriate data for string
|
||||||
# formatting which can come from :
|
# formatting which can come from :
|
||||||
|
@ -597,7 +584,6 @@ class Diagnoser:
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def remote_diagnosis(uri, data, ipversion, timeout=30):
|
def remote_diagnosis(uri, data, ipversion, timeout=30):
|
||||||
|
|
||||||
# Lazy loading for performance
|
# Lazy loading for performance
|
||||||
import requests
|
import requests
|
||||||
import socket
|
import socket
|
||||||
|
@ -646,7 +632,6 @@ class Diagnoser:
|
||||||
|
|
||||||
|
|
||||||
def _list_diagnosis_categories():
|
def _list_diagnosis_categories():
|
||||||
|
|
||||||
paths = glob.glob(os.path.dirname(__file__) + "/diagnosers/??-*.py")
|
paths = glob.glob(os.path.dirname(__file__) + "/diagnosers/??-*.py")
|
||||||
names = [
|
names = [
|
||||||
name.split("-")[-1]
|
name.split("-")[-1]
|
||||||
|
@ -657,7 +642,6 @@ def _list_diagnosis_categories():
|
||||||
|
|
||||||
|
|
||||||
def _load_diagnoser(diagnoser_name):
|
def _load_diagnoser(diagnoser_name):
|
||||||
|
|
||||||
logger.debug(f"Loading diagnoser {diagnoser_name}")
|
logger.debug(f"Loading diagnoser {diagnoser_name}")
|
||||||
|
|
||||||
paths = glob.glob(os.path.dirname(__file__) + f"/diagnosers/??-{diagnoser_name}.py")
|
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)
|
base_dns_zone = _get_dns_zone_for_domain(base_domain)
|
||||||
|
|
||||||
for domain, settings in domains_settings.items():
|
for domain, settings in domains_settings.items():
|
||||||
|
|
||||||
# Domain # Base DNS zone # Basename # Suffix #
|
# Domain # Base DNS zone # Basename # Suffix #
|
||||||
# ------------------ # ----------------- # --------- # -------- #
|
# ------------------ # ----------------- # --------- # -------- #
|
||||||
# domain.tld # domain.tld # @ # #
|
# 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
|
# We don't wan't to do A NS request on the tld
|
||||||
for parent in parent_list[0:-1]:
|
for parent in parent_list[0:-1]:
|
||||||
|
|
||||||
# Check if there's a NS record for that domain
|
# Check if there's a NS record for that domain
|
||||||
answer = dig(parent, rdtype="NS", full_answers=True, resolvers="force_external")
|
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):
|
def _get_registrar_config_section(domain):
|
||||||
|
|
||||||
from lexicon.providers.auto import _relevant_provider_for_domain
|
from lexicon.providers.auto import _relevant_provider_for_domain
|
||||||
|
|
||||||
registrar_infos = {
|
registrar_infos = {
|
||||||
|
@ -517,7 +514,6 @@ def _get_registrar_config_section(domain):
|
||||||
# If parent domain exists in yunohost
|
# If parent domain exists in yunohost
|
||||||
parent_domain = _get_parent_domain_of(domain, topest=True)
|
parent_domain = _get_parent_domain_of(domain, topest=True)
|
||||||
if parent_domain:
|
if parent_domain:
|
||||||
|
|
||||||
# Dirty hack to have a link on the webadmin
|
# Dirty hack to have a link on the webadmin
|
||||||
if Moulinette.interface.type == "api":
|
if Moulinette.interface.type == "api":
|
||||||
parent_domain_link = f"[{parent_domain}](#/domains/{parent_domain}/dns)"
|
parent_domain_link = f"[{parent_domain}](#/domains/{parent_domain}/dns)"
|
||||||
|
@ -572,7 +568,6 @@ def _get_registrar_config_section(domain):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
registrar_infos["registrar"] = OrderedDict(
|
registrar_infos["registrar"] = OrderedDict(
|
||||||
{
|
{
|
||||||
"type": "alert",
|
"type": "alert",
|
||||||
|
@ -606,7 +601,6 @@ def _get_registrar_config_section(domain):
|
||||||
|
|
||||||
|
|
||||||
def _get_registar_settings(domain):
|
def _get_registar_settings(domain):
|
||||||
|
|
||||||
_assert_domain_exists(domain)
|
_assert_domain_exists(domain)
|
||||||
|
|
||||||
settings = domain_config_get(domain, key="dns.registrar", export=True)
|
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 = []
|
wanted_records = []
|
||||||
for records in _build_dns_conf(domain).values():
|
for records in _build_dns_conf(domain).values():
|
||||||
for record in records:
|
for record in records:
|
||||||
|
|
||||||
# Make sure the name is a FQDN
|
# Make sure the name is a FQDN
|
||||||
name = (
|
name = (
|
||||||
f"{record['name']}.{base_dns_zone}"
|
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:
|
for record in current_records:
|
||||||
|
|
||||||
# Try to get rid of weird stuff like ".domain.tld" or "@.domain.tld"
|
# Try to get rid of weird stuff like ".domain.tld" or "@.domain.tld"
|
||||||
record["name"] = record["name"].strip("@").strip(".")
|
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)
|
comparison[(record["type"], record["name"])]["wanted"].append(record)
|
||||||
|
|
||||||
for type_and_name, records in comparison.items():
|
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
|
# 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": []}
|
results = {"warnings": [], "errors": []}
|
||||||
|
|
||||||
for action in ["delete", "create", "update"]:
|
for action in ["delete", "create", "update"]:
|
||||||
|
|
||||||
for record in changes[action]:
|
for record in changes[action]:
|
||||||
|
|
||||||
relative_name = _get_relative_name_for_dns_zone(
|
relative_name = _get_relative_name_for_dns_zone(
|
||||||
record["name"], base_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:
|
def _hash_dns_record(record: dict) -> int:
|
||||||
|
|
||||||
fields = ["name", "type", "content"]
|
fields = ["name", "type", "content"]
|
||||||
record_ = {f: record.get(f) for f in fields}
|
record_ = {f: record.get(f) for f in fields}
|
||||||
|
|
||||||
|
|
|
@ -187,7 +187,6 @@ def _assert_domain_exists(domain):
|
||||||
|
|
||||||
|
|
||||||
def _list_subdomains_of(parent_domain):
|
def _list_subdomains_of(parent_domain):
|
||||||
|
|
||||||
_assert_domain_exists(parent_domain)
|
_assert_domain_exists(parent_domain)
|
||||||
|
|
||||||
out = []
|
out = []
|
||||||
|
@ -199,7 +198,6 @@ def _list_subdomains_of(parent_domain):
|
||||||
|
|
||||||
|
|
||||||
def _get_parent_domain_of(domain, return_self=False, topest=False):
|
def _get_parent_domain_of(domain, return_self=False, topest=False):
|
||||||
|
|
||||||
domains = _get_domains(exclude_subdomains=topest)
|
domains = _get_domains(exclude_subdomains=topest)
|
||||||
|
|
||||||
domain_ = domain
|
domain_ = domain
|
||||||
|
@ -248,7 +246,6 @@ def domain_add(operation_logger, domain, dyndns=False):
|
||||||
|
|
||||||
# DynDNS domain
|
# DynDNS domain
|
||||||
if dyndns:
|
if dyndns:
|
||||||
|
|
||||||
from yunohost.utils.dns import is_yunohost_dyndns_domain
|
from yunohost.utils.dns import is_yunohost_dyndns_domain
|
||||||
from yunohost.dyndns import _guess_current_dyndns_domain
|
from yunohost.dyndns import _guess_current_dyndns_domain
|
||||||
|
|
||||||
|
@ -589,7 +586,6 @@ class DomainConfigPanel(ConfigPanel):
|
||||||
regen_conf(names=stuff_to_regen_conf)
|
regen_conf(names=stuff_to_regen_conf)
|
||||||
|
|
||||||
def _get_toml(self):
|
def _get_toml(self):
|
||||||
|
|
||||||
toml = super()._get_toml()
|
toml = super()._get_toml()
|
||||||
|
|
||||||
toml["feature"]["xmpp"]["xmpp"]["default"] = (
|
toml["feature"]["xmpp"]["xmpp"]["default"] = (
|
||||||
|
@ -611,7 +607,6 @@ class DomainConfigPanel(ConfigPanel):
|
||||||
|
|
||||||
# Cert stuff
|
# Cert stuff
|
||||||
if not filter_key or filter_key[0] == "cert":
|
if not filter_key or filter_key[0] == "cert":
|
||||||
|
|
||||||
from yunohost.certificate import certificate_status
|
from yunohost.certificate import certificate_status
|
||||||
|
|
||||||
status = certificate_status([self.entity], full=True)["certificates"][
|
status = certificate_status([self.entity], full=True)["certificates"][
|
||||||
|
@ -638,7 +633,6 @@ class DomainConfigPanel(ConfigPanel):
|
||||||
return toml
|
return toml
|
||||||
|
|
||||||
def _load_current_values(self):
|
def _load_current_values(self):
|
||||||
|
|
||||||
# TODO add mechanism to share some settings with other domains on the same zone
|
# TODO add mechanism to share some settings with other domains on the same zone
|
||||||
super()._load_current_values()
|
super()._load_current_values()
|
||||||
|
|
||||||
|
@ -656,7 +650,6 @@ class DomainConfigPanel(ConfigPanel):
|
||||||
|
|
||||||
|
|
||||||
def domain_action_run(domain, action, args=None):
|
def domain_action_run(domain, action, args=None):
|
||||||
|
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
|
||||||
if action == "cert.cert.cert_install":
|
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:
|
def _get_domain_settings(domain: str) -> dict:
|
||||||
|
|
||||||
_assert_domain_exists(domain)
|
_assert_domain_exists(domain)
|
||||||
|
|
||||||
if os.path.exists(f"{DOMAIN_SETTINGS_DIR}/{domain}.yml"):
|
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:
|
def _set_domain_settings(domain: str, settings: dict) -> None:
|
||||||
|
|
||||||
_assert_domain_exists(domain)
|
_assert_domain_exists(domain)
|
||||||
|
|
||||||
write_to_yaml(f"{DOMAIN_SETTINGS_DIR}/{domain}.yml", settings)
|
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 dns_auth in DYNDNS_DNS_AUTH:
|
||||||
for type_ in ["A", "AAAA"]:
|
for type_ in ["A", "AAAA"]:
|
||||||
|
|
||||||
ok, result = dig(dns_auth, type_)
|
ok, result = dig(dns_auth, type_)
|
||||||
if ok == "ok" and len(result) and result[0]:
|
if ok == "ok" and len(result) and result[0]:
|
||||||
auth_resolvers.append(result[0])
|
auth_resolvers.append(result[0])
|
||||||
|
@ -238,7 +237,6 @@ def dyndns_update(
|
||||||
)
|
)
|
||||||
|
|
||||||
def resolve_domain(domain, rdtype):
|
def resolve_domain(domain, rdtype):
|
||||||
|
|
||||||
ok, result = dig(domain, rdtype, resolvers=auth_resolvers)
|
ok, result = dig(domain, rdtype, resolvers=auth_resolvers)
|
||||||
if ok == "ok":
|
if ok == "ok":
|
||||||
return result[0] if len(result) else None
|
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"]:
|
for protocol in ["TCP", "UDP"]:
|
||||||
if protocol + "_TO_CLOSE" in firewall["uPnP"]:
|
if protocol + "_TO_CLOSE" in firewall["uPnP"]:
|
||||||
for port in firewall["uPnP"][protocol + "_TO_CLOSE"]:
|
for port in firewall["uPnP"][protocol + "_TO_CLOSE"]:
|
||||||
|
|
||||||
if not isinstance(port, int):
|
if not isinstance(port, int):
|
||||||
# FIXME : how should we handle port ranges ?
|
# FIXME : how should we handle port ranges ?
|
||||||
logger.warning("Can't use UPnP to close '%s'" % port)
|
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"] = []
|
firewall["uPnP"][protocol + "_TO_CLOSE"] = []
|
||||||
|
|
||||||
for port in firewall["uPnP"][protocol]:
|
for port in firewall["uPnP"][protocol]:
|
||||||
|
|
||||||
if not isinstance(port, int):
|
if not isinstance(port, int):
|
||||||
# FIXME : how should we handle port ranges ?
|
# FIXME : how should we handle port ranges ?
|
||||||
logger.warning("Can't use UPnP to open '%s'" % port)
|
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)
|
raise YunohostError("file_does_not_exist", path=path)
|
||||||
|
|
||||||
def is_relevant_warning(msg):
|
def is_relevant_warning(msg):
|
||||||
|
|
||||||
# Ignore empty warning messages...
|
# Ignore empty warning messages...
|
||||||
if not msg:
|
if not msg:
|
||||||
return False
|
return False
|
||||||
|
@ -389,7 +388,6 @@ def hook_exec(
|
||||||
|
|
||||||
|
|
||||||
def _hook_exec_bash(path, args, chdir, env, user, return_format, loggers):
|
def _hook_exec_bash(path, args, chdir, env, user, return_format, loggers):
|
||||||
|
|
||||||
from moulinette.utils.process import call_async_output
|
from moulinette.utils.process import call_async_output
|
||||||
|
|
||||||
# Construct command variables
|
# 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):
|
def _hook_exec_python(path, args, env, loggers):
|
||||||
|
|
||||||
dir_ = os.path.dirname(path)
|
dir_ = os.path.dirname(path)
|
||||||
name = os.path.splitext(os.path.basename(path))[0]
|
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):
|
def hook_exec_with_script_debug_if_failure(*args, **kwargs):
|
||||||
|
|
||||||
operation_logger = kwargs.pop("operation_logger")
|
operation_logger = kwargs.pop("operation_logger")
|
||||||
error_message_if_failed = kwargs.pop("error_message_if_failed")
|
error_message_if_failed = kwargs.pop("error_message_if_failed")
|
||||||
error_message_if_script_failed = kwargs.pop("error_message_if_script_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]
|
logs = logs[: limit * 5]
|
||||||
|
|
||||||
for log in logs:
|
for log in logs:
|
||||||
|
|
||||||
base_filename = log[: -len(METADATA_FILE_EXT)]
|
base_filename = log[: -len(METADATA_FILE_EXT)]
|
||||||
md_path = os.path.join(OPERATIONS_PATH, log)
|
md_path = os.path.join(OPERATIONS_PATH, log)
|
||||||
|
|
||||||
|
@ -264,7 +263,6 @@ def log_show(
|
||||||
return
|
return
|
||||||
|
|
||||||
for filename in os.listdir(OPERATIONS_PATH):
|
for filename in os.listdir(OPERATIONS_PATH):
|
||||||
|
|
||||||
if not filename.endswith(METADATA_FILE_EXT):
|
if not filename.endswith(METADATA_FILE_EXT):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -438,7 +436,6 @@ class RedactingFormatter(Formatter):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def identify_data_to_redact(self, record):
|
def identify_data_to_redact(self, record):
|
||||||
|
|
||||||
# Wrapping this in a try/except because we don't want this to
|
# Wrapping this in a try/except because we don't want this to
|
||||||
# break everything in case it fails miserably for some reason :s
|
# break everything in case it fails miserably for some reason :s
|
||||||
try:
|
try:
|
||||||
|
@ -497,7 +494,6 @@ class OperationLogger:
|
||||||
os.makedirs(self.path)
|
os.makedirs(self.path)
|
||||||
|
|
||||||
def parent_logger(self):
|
def parent_logger(self):
|
||||||
|
|
||||||
# If there are other operation logger instances
|
# If there are other operation logger instances
|
||||||
for instance in reversed(self._instances):
|
for instance in reversed(self._instances):
|
||||||
# Is one of these operation logger started but not yet done ?
|
# 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"))
|
self.error(m18n.n("log_operation_unit_unclosed_properly"))
|
||||||
|
|
||||||
def dump_script_log_extract_for_debugging(self):
|
def dump_script_log_extract_for_debugging(self):
|
||||||
|
|
||||||
with open(self.log_path, "r") as f:
|
with open(self.log_path, "r") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
|
|
||||||
|
@ -774,7 +769,6 @@ class OperationLogger:
|
||||||
|
|
||||||
|
|
||||||
def _get_datetime_from_name(name):
|
def _get_datetime_from_name(name):
|
||||||
|
|
||||||
# Filenames are expected to follow the format:
|
# Filenames are expected to follow the format:
|
||||||
# 20200831-170740-short_description-and-stuff
|
# 20200831-170740-short_description-and-stuff
|
||||||
|
|
||||||
|
|
|
@ -72,13 +72,11 @@ def _backup_pip_freeze_for_python_app_venvs():
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
class MyMigration(Migration):
|
||||||
|
|
||||||
"Upgrade the system to Debian Bullseye and Yunohost 11.x"
|
"Upgrade the system to Debian Bullseye and Yunohost 11.x"
|
||||||
|
|
||||||
mode = "manual"
|
mode = "manual"
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
self.check_assertions()
|
self.check_assertions()
|
||||||
|
|
||||||
logger.info(m18n.n("migration_0021_start"))
|
logger.info(m18n.n("migration_0021_start"))
|
||||||
|
@ -389,7 +387,6 @@ class MyMigration(Migration):
|
||||||
return int(get_ynh_package_version("yunohost")["version"].split(".")[0])
|
return int(get_ynh_package_version("yunohost")["version"].split(".")[0])
|
||||||
|
|
||||||
def check_assertions(self):
|
def check_assertions(self):
|
||||||
|
|
||||||
# Be on buster (10.x) and yunohost 4.x
|
# Be on buster (10.x) and yunohost 4.x
|
||||||
# NB : we do both check to cover situations where the upgrade crashed
|
# 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
|
# in the middle and debian version could be > 9.x but yunohost package
|
||||||
|
@ -453,7 +450,6 @@ class MyMigration(Migration):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def disclaimer(self):
|
def disclaimer(self):
|
||||||
|
|
||||||
# Avoid having a super long disclaimer + uncessary check if we ain't
|
# Avoid having a super long disclaimer + uncessary check if we ain't
|
||||||
# on buster / yunohost 4.x anymore
|
# on buster / yunohost 4.x anymore
|
||||||
# NB : we do both check to cover situations where the upgrade crashed
|
# NB : we do both check to cover situations where the upgrade crashed
|
||||||
|
@ -494,7 +490,6 @@ class MyMigration(Migration):
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def patch_apt_sources_list(self):
|
def patch_apt_sources_list(self):
|
||||||
|
|
||||||
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
|
sources_list = glob.glob("/etc/apt/sources.list.d/*.list")
|
||||||
if os.path.exists("/etc/apt/sources.list"):
|
if os.path.exists("/etc/apt/sources.list"):
|
||||||
sources_list.append("/etc/apt/sources.list")
|
sources_list.append("/etc/apt/sources.list")
|
||||||
|
@ -516,7 +511,6 @@ class MyMigration(Migration):
|
||||||
os.system(command)
|
os.system(command)
|
||||||
|
|
||||||
def get_apps_equivs_packages(self):
|
def get_apps_equivs_packages(self):
|
||||||
|
|
||||||
command = (
|
command = (
|
||||||
"dpkg --get-selections"
|
"dpkg --get-selections"
|
||||||
" | grep -v deinstall"
|
" | grep -v deinstall"
|
||||||
|
|
|
@ -27,7 +27,6 @@ MIGRATION_COMMENT = (
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
class MyMigration(Migration):
|
||||||
|
|
||||||
"Migrate php7.3-fpm 'pool' conf files to php7.4"
|
"Migrate php7.3-fpm 'pool' conf files to php7.4"
|
||||||
|
|
||||||
dependencies = ["migrate_to_bullseye"]
|
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"]
|
oldphp_pool_files = [f for f in oldphp_pool_files if f != "www.conf"]
|
||||||
|
|
||||||
for pf in oldphp_pool_files:
|
for pf in oldphp_pool_files:
|
||||||
|
|
||||||
# Copy the files to the php7.3 pool
|
# Copy the files to the php7.3 pool
|
||||||
src = "{}/{}".format(OLDPHP_POOLS, pf)
|
src = "{}/{}".format(OLDPHP_POOLS, pf)
|
||||||
dest = "{}/{}".format(NEWPHP_POOLS, pf)
|
dest = "{}/{}".format(NEWPHP_POOLS, pf)
|
||||||
|
|
|
@ -13,13 +13,11 @@ logger = getActionLogger("yunohost.migration")
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
class MyMigration(Migration):
|
||||||
|
|
||||||
"Migrate DBs from Postgresql 11 to 13 after migrating to Bullseye"
|
"Migrate DBs from Postgresql 11 to 13 after migrating to Bullseye"
|
||||||
|
|
||||||
dependencies = ["migrate_to_bullseye"]
|
dependencies = ["migrate_to_bullseye"]
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
if (
|
if (
|
||||||
os.system(
|
os.system(
|
||||||
'grep -A10 "ynh-deps" /var/lib/dpkg/status | grep -E "Package:|Depends:" | grep -B1 postgresql'
|
'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")
|
self.runcmd("systemctl start postgresql")
|
||||||
|
|
||||||
def package_is_installed(self, package_name):
|
def package_is_installed(self, package_name):
|
||||||
|
|
||||||
(returncode, out, err) = self.runcmd(
|
(returncode, out, err) = self.runcmd(
|
||||||
"dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name),
|
"dpkg --list | grep '^ii ' | grep -q -w {}".format(package_name),
|
||||||
raise_on_errors=False,
|
raise_on_errors=False,
|
||||||
|
@ -71,7 +68,6 @@ class MyMigration(Migration):
|
||||||
return returncode == 0
|
return returncode == 0
|
||||||
|
|
||||||
def runcmd(self, cmd, raise_on_errors=True):
|
def runcmd(self, cmd, raise_on_errors=True):
|
||||||
|
|
||||||
logger.debug("Running command: " + cmd)
|
logger.debug("Running command: " + cmd)
|
||||||
|
|
||||||
p = subprocess.Popen(
|
p = subprocess.Popen(
|
||||||
|
|
|
@ -14,7 +14,6 @@ VENV_REQUIREMENTS_SUFFIX = ".requirements_backup_for_bullseye_upgrade.txt"
|
||||||
|
|
||||||
|
|
||||||
def extract_app_from_venv_path(venv_path):
|
def extract_app_from_venv_path(venv_path):
|
||||||
|
|
||||||
venv_path = venv_path.replace("/var/www/", "")
|
venv_path = venv_path.replace("/var/www/", "")
|
||||||
venv_path = venv_path.replace("/opt/yunohost/", "")
|
venv_path = venv_path.replace("/opt/yunohost/", "")
|
||||||
venv_path = venv_path.replace("/opt/", "")
|
venv_path = venv_path.replace("/opt/", "")
|
||||||
|
@ -137,13 +136,11 @@ class MyMigration(Migration):
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
|
||||||
if self.mode == "auto":
|
if self.mode == "auto":
|
||||||
return
|
return
|
||||||
|
|
||||||
venvs = _get_all_venvs("/opt/") + _get_all_venvs("/var/www/")
|
venvs = _get_all_venvs("/opt/") + _get_all_venvs("/var/www/")
|
||||||
for venv in venvs:
|
for venv in venvs:
|
||||||
|
|
||||||
app_corresponding_to_venv = extract_app_from_venv_path(venv)
|
app_corresponding_to_venv = extract_app_from_venv_path(venv)
|
||||||
|
|
||||||
# Search for ignore apps
|
# Search for ignore apps
|
||||||
|
|
|
@ -14,7 +14,6 @@ OLD_SETTINGS_PATH = "/etc/yunohost/settings.json"
|
||||||
|
|
||||||
|
|
||||||
class MyMigration(Migration):
|
class MyMigration(Migration):
|
||||||
|
|
||||||
"Migrate old global settings to the new ConfigPanel global settings"
|
"Migrate old global settings to the new ConfigPanel global settings"
|
||||||
|
|
||||||
dependencies = ["migrate_to_bullseye"]
|
dependencies = ["migrate_to_bullseye"]
|
||||||
|
|
|
@ -21,7 +21,6 @@ class MyMigration(Migration):
|
||||||
|
|
||||||
@Migration.ldap_migration
|
@Migration.ldap_migration
|
||||||
def run(self, *args):
|
def run(self, *args):
|
||||||
|
|
||||||
from yunohost.user import (
|
from yunohost.user import (
|
||||||
user_list,
|
user_list,
|
||||||
user_info,
|
user_info,
|
||||||
|
|
|
@ -79,7 +79,6 @@ def user_permission_list(
|
||||||
|
|
||||||
permissions = {}
|
permissions = {}
|
||||||
for infos in permissions_infos:
|
for infos in permissions_infos:
|
||||||
|
|
||||||
name = infos["cn"][0]
|
name = infos["cn"][0]
|
||||||
app = name.split(".")[0]
|
app = name.split(".")[0]
|
||||||
|
|
||||||
|
@ -654,7 +653,6 @@ def permission_sync_to_user():
|
||||||
permissions = user_permission_list(full=True)["permissions"]
|
permissions = user_permission_list(full=True)["permissions"]
|
||||||
|
|
||||||
for permission_name, permission_infos in permissions.items():
|
for permission_name, permission_infos in permissions.items():
|
||||||
|
|
||||||
# These are the users currently allowed because there's an 'inheritPermission' object corresponding to it
|
# These are the users currently allowed because there's an 'inheritPermission' object corresponding to it
|
||||||
currently_allowed_users = set(permission_infos["corresponding_users"])
|
currently_allowed_users = set(permission_infos["corresponding_users"])
|
||||||
|
|
||||||
|
@ -740,7 +738,6 @@ def _update_ldap_group_permission(
|
||||||
update["isProtected"] = [str(protected).upper()]
|
update["isProtected"] = [str(protected).upper()]
|
||||||
|
|
||||||
if show_tile is not None:
|
if show_tile is not None:
|
||||||
|
|
||||||
if show_tile is True:
|
if show_tile is True:
|
||||||
if not existing_permission["url"]:
|
if not existing_permission["url"]:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
|
@ -876,7 +873,6 @@ def _validate_and_sanitize_permission_url(url, app_base_path, app):
|
||||||
raise YunohostValidationError("invalid_regex", regex=regex)
|
raise YunohostValidationError("invalid_regex", regex=regex)
|
||||||
|
|
||||||
if url.startswith("re:"):
|
if url.startswith("re:"):
|
||||||
|
|
||||||
# regex without domain
|
# regex without domain
|
||||||
# we check for the first char after 're:'
|
# we check for the first char after 're:'
|
||||||
if url[3] in ["/", "^", "\\"]:
|
if url[3] in ["/", "^", "\\"]:
|
||||||
|
|
|
@ -77,7 +77,6 @@ def regen_conf(
|
||||||
|
|
||||||
for category, conf_files in pending_conf.items():
|
for category, conf_files in pending_conf.items():
|
||||||
for system_path, pending_path in conf_files.items():
|
for system_path, pending_path in conf_files.items():
|
||||||
|
|
||||||
pending_conf[category][system_path] = {
|
pending_conf[category][system_path] = {
|
||||||
"pending_conf": pending_path,
|
"pending_conf": pending_path,
|
||||||
"diff": _get_files_diff(system_path, pending_path, True),
|
"diff": _get_files_diff(system_path, pending_path, True),
|
||||||
|
@ -595,7 +594,6 @@ def _update_conf_hashes(category, hashes):
|
||||||
|
|
||||||
|
|
||||||
def _force_clear_hashes(paths):
|
def _force_clear_hashes(paths):
|
||||||
|
|
||||||
categories = _get_regenconf_infos()
|
categories = _get_regenconf_infos()
|
||||||
for path in paths:
|
for path in paths:
|
||||||
for category in categories.keys():
|
for category in categories.keys():
|
||||||
|
@ -675,7 +673,6 @@ def _process_regen_conf(system_conf, new_conf=None, save=True):
|
||||||
|
|
||||||
|
|
||||||
def manually_modified_files():
|
def manually_modified_files():
|
||||||
|
|
||||||
output = []
|
output = []
|
||||||
regenconf_categories = _get_regenconf_infos()
|
regenconf_categories = _get_regenconf_infos()
|
||||||
for category, infos in regenconf_categories.items():
|
for category, infos in regenconf_categories.items():
|
||||||
|
@ -690,7 +687,6 @@ def manually_modified_files():
|
||||||
def manually_modified_files_compared_to_debian_default(
|
def manually_modified_files_compared_to_debian_default(
|
||||||
ignore_handled_by_regenconf=False,
|
ignore_handled_by_regenconf=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
# from https://serverfault.com/a/90401
|
# from https://serverfault.com/a/90401
|
||||||
files = check_output(
|
files = check_output(
|
||||||
"dpkg-query -W -f='${Conffiles}\n' '*' \
|
"dpkg-query -W -f='${Conffiles}\n' '*' \
|
||||||
|
|
|
@ -249,12 +249,10 @@ def service_reload_or_restart(names, test_conf=True):
|
||||||
services = _get_services()
|
services = _get_services()
|
||||||
|
|
||||||
for name in names:
|
for name in names:
|
||||||
|
|
||||||
logger.debug(f"Reloading service {name}")
|
logger.debug(f"Reloading service {name}")
|
||||||
|
|
||||||
test_conf_cmd = services.get(name, {}).get("test_conf")
|
test_conf_cmd = services.get(name, {}).get("test_conf")
|
||||||
if test_conf and test_conf_cmd:
|
if test_conf and test_conf_cmd:
|
||||||
|
|
||||||
p = subprocess.Popen(
|
p = subprocess.Popen(
|
||||||
test_conf_cmd,
|
test_conf_cmd,
|
||||||
shell=True,
|
shell=True,
|
||||||
|
@ -393,7 +391,6 @@ def _get_service_information_from_systemd(service):
|
||||||
|
|
||||||
|
|
||||||
def _get_and_format_service_status(service, infos):
|
def _get_and_format_service_status(service, infos):
|
||||||
|
|
||||||
systemd_service = infos.get("actual_systemd_service", service)
|
systemd_service = infos.get("actual_systemd_service", service)
|
||||||
raw_status, raw_service = _get_service_information_from_systemd(systemd_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 no description was there, try to get it from the .json locales
|
||||||
if not description:
|
if not description:
|
||||||
|
|
||||||
translation_key = f"service_description_{service}"
|
translation_key = f"service_description_{service}"
|
||||||
if m18n.key_exists(translation_key):
|
if m18n.key_exists(translation_key):
|
||||||
description = m18n.n(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()
|
result["journalctl"] = _get_journalctl_logs(name, number).splitlines()
|
||||||
|
|
||||||
for log_path in log_list:
|
for log_path in log_list:
|
||||||
|
|
||||||
if not os.path.exists(log_path):
|
if not os.path.exists(log_path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -620,7 +615,6 @@ def _run_service_command(action, service):
|
||||||
|
|
||||||
|
|
||||||
def _give_lock(action, service, p):
|
def _give_lock(action, service, p):
|
||||||
|
|
||||||
# Depending of the action, systemctl calls the PID differently :/
|
# Depending of the action, systemctl calls the PID differently :/
|
||||||
if action == "start" or action == "restart":
|
if action == "start" or action == "restart":
|
||||||
systemctl_PID_name = "MainPID"
|
systemctl_PID_name = "MainPID"
|
||||||
|
@ -744,7 +738,6 @@ def _save_services(services):
|
||||||
diff = {}
|
diff = {}
|
||||||
|
|
||||||
for service_name, service_infos in services.items():
|
for service_name, service_infos in services.items():
|
||||||
|
|
||||||
# Ignore php-fpm services, they are to be added dynamically by the core,
|
# Ignore php-fpm services, they are to be added dynamically by the core,
|
||||||
# but not actually saved
|
# but not actually saved
|
||||||
if service_name.startswith("php") and service_name.endswith("-fpm"):
|
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):
|
def settings_list(full=False):
|
||||||
|
|
||||||
settings = settings_get(full=full)
|
settings = settings_get(full=full)
|
||||||
|
|
||||||
if full:
|
if full:
|
||||||
|
@ -126,7 +125,6 @@ class SettingsConfigPanel(ConfigPanel):
|
||||||
super().__init__("settings")
|
super().__init__("settings")
|
||||||
|
|
||||||
def _apply(self):
|
def _apply(self):
|
||||||
|
|
||||||
root_password = self.new_values.pop("root_password", None)
|
root_password = self.new_values.pop("root_password", None)
|
||||||
root_password_confirm = self.new_values.pop("root_password_confirm", None)
|
root_password_confirm = self.new_values.pop("root_password_confirm", None)
|
||||||
passwordless_sudo = self.new_values.pop("passwordless_sudo", 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)
|
assert all(v not in self.future_values for v in self.virtual_settings)
|
||||||
|
|
||||||
if root_password and root_password.strip():
|
if root_password and root_password.strip():
|
||||||
|
|
||||||
if root_password != root_password_confirm:
|
if root_password != root_password_confirm:
|
||||||
raise YunohostValidationError("password_confirmation_not_the_same")
|
raise YunohostValidationError("password_confirmation_not_the_same")
|
||||||
|
|
||||||
|
@ -173,7 +170,6 @@ class SettingsConfigPanel(ConfigPanel):
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def _get_toml(self):
|
def _get_toml(self):
|
||||||
|
|
||||||
toml = super()._get_toml()
|
toml = super()._get_toml()
|
||||||
|
|
||||||
# Dynamic choice list for portal themes
|
# Dynamic choice list for portal themes
|
||||||
|
@ -187,7 +183,6 @@ class SettingsConfigPanel(ConfigPanel):
|
||||||
return toml
|
return toml
|
||||||
|
|
||||||
def _load_current_values(self):
|
def _load_current_values(self):
|
||||||
|
|
||||||
super()._load_current_values()
|
super()._load_current_values()
|
||||||
|
|
||||||
# Specific logic for those settings who are "virtual" settings
|
# Specific logic for those settings who are "virtual" settings
|
||||||
|
@ -207,7 +202,6 @@ class SettingsConfigPanel(ConfigPanel):
|
||||||
self.values["passwordless_sudo"] = False
|
self.values["passwordless_sudo"] = False
|
||||||
|
|
||||||
def get(self, key="", mode="classic"):
|
def get(self, key="", mode="classic"):
|
||||||
|
|
||||||
result = super().get(key=key, mode=mode)
|
result = super().get(key=key, mode=mode)
|
||||||
|
|
||||||
if mode == "full":
|
if mode == "full":
|
||||||
|
|
|
@ -51,7 +51,6 @@ old_translate = moulinette.core.Translator.translate
|
||||||
|
|
||||||
|
|
||||||
def new_translate(self, key, *args, **kwargs):
|
def new_translate(self, key, *args, **kwargs):
|
||||||
|
|
||||||
if key not in self._translations[self.default_locale].keys():
|
if key not in self._translations[self.default_locale].keys():
|
||||||
raise KeyError("Unable to retrieve key %s for default locale !" % key)
|
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):
|
def pytest_cmdline_main(config):
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
sys.path.insert(0, "/usr/lib/moulinette/")
|
sys.path.insert(0, "/usr/lib/moulinette/")
|
||||||
|
@ -76,7 +74,6 @@ def pytest_cmdline_main(config):
|
||||||
yunohost.init(debug=config.option.yunodebug)
|
yunohost.init(debug=config.option.yunodebug)
|
||||||
|
|
||||||
class DummyInterface:
|
class DummyInterface:
|
||||||
|
|
||||||
type = "cli"
|
type = "cli"
|
||||||
|
|
||||||
def prompt(self, *args, **kwargs):
|
def prompt(self, *args, **kwargs):
|
||||||
|
|
|
@ -44,7 +44,6 @@ class AnyStringWith(str):
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
# Clear apps catalog cache
|
# Clear apps catalog cache
|
||||||
shutil.rmtree(APPS_CATALOG_CACHE, ignore_errors=True)
|
shutil.rmtree(APPS_CATALOG_CACHE, ignore_errors=True)
|
||||||
|
|
||||||
|
@ -54,7 +53,6 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
# Clear apps catalog cache
|
# Clear apps catalog cache
|
||||||
# Otherwise when using apps stuff after running the test,
|
# Otherwise when using apps stuff after running the test,
|
||||||
# we'll still have the dummy unusable list
|
# we'll still have the dummy unusable list
|
||||||
|
@ -67,7 +65,6 @@ def teardown_function(function):
|
||||||
|
|
||||||
|
|
||||||
def test_apps_catalog_init(mocker):
|
def test_apps_catalog_init(mocker):
|
||||||
|
|
||||||
# Cache is empty
|
# Cache is empty
|
||||||
assert not glob.glob(APPS_CATALOG_CACHE + "/*")
|
assert not glob.glob(APPS_CATALOG_CACHE + "/*")
|
||||||
# Conf doesn't exist yet
|
# Conf doesn't exist yet
|
||||||
|
@ -91,7 +88,6 @@ def test_apps_catalog_init(mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_apps_catalog_emptylist():
|
def test_apps_catalog_emptylist():
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
|
@ -104,7 +100,6 @@ def test_apps_catalog_emptylist():
|
||||||
|
|
||||||
|
|
||||||
def test_apps_catalog_update_nominal(mocker):
|
def test_apps_catalog_update_nominal(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
|
@ -113,7 +108,6 @@ def test_apps_catalog_update_nominal(mocker):
|
||||||
|
|
||||||
# Update
|
# Update
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
_actual_apps_catalog_api_url,
|
_actual_apps_catalog_api_url,
|
||||||
# Mock the server response with a dummy apps catalog
|
# Mock the server response with a dummy apps catalog
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_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):
|
def test_apps_catalog_update_404(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# 404 error
|
# 404 error
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, status_code=404)
|
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):
|
def test_apps_catalog_update_timeout(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# Timeout
|
# Timeout
|
||||||
m.register_uri(
|
m.register_uri(
|
||||||
"GET", APPS_CATALOG_DEFAULT_URL_FULL, exc=requests.exceptions.ConnectTimeout
|
"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):
|
def test_apps_catalog_update_sslerror(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# SSL error
|
# SSL error
|
||||||
m.register_uri(
|
m.register_uri(
|
||||||
"GET", APPS_CATALOG_DEFAULT_URL_FULL, exc=requests.exceptions.SSLError
|
"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):
|
def test_apps_catalog_update_corrupted(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# Corrupted json
|
# Corrupted json
|
||||||
m.register_uri(
|
m.register_uri(
|
||||||
"GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG[:-2]
|
"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):
|
def test_apps_catalog_load_with_empty_cache(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
|
@ -218,7 +203,6 @@ def test_apps_catalog_load_with_empty_cache(mocker):
|
||||||
|
|
||||||
# Update
|
# Update
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# Mock the server response with a dummy apps catalog
|
# Mock the server response with a dummy apps catalog
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_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):
|
def test_apps_catalog_load_with_conflicts_between_lists(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
|
@ -253,7 +236,6 @@ def test_apps_catalog_load_with_conflicts_between_lists(mocker):
|
||||||
|
|
||||||
# Update
|
# Update
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# Mock the server response with a dummy apps catalog
|
# Mock the server response with a dummy apps catalog
|
||||||
# + the same apps catalog for the second list
|
# + the same apps catalog for the second list
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
|
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):
|
def test_apps_catalog_load_with_oudated_api_version(mocker):
|
||||||
|
|
||||||
# Initialize ...
|
# Initialize ...
|
||||||
_initialize_apps_catalog_system()
|
_initialize_apps_catalog_system()
|
||||||
|
|
||||||
# Update
|
# Update
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
mocker.spy(m18n, "n")
|
mocker.spy(m18n, "n")
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
|
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_CATALOG)
|
||||||
_update_apps_catalog()
|
_update_apps_catalog()
|
||||||
|
@ -300,7 +280,6 @@ def test_apps_catalog_load_with_oudated_api_version(mocker):
|
||||||
|
|
||||||
# Update
|
# Update
|
||||||
with requests_mock.Mocker() as m:
|
with requests_mock.Mocker() as m:
|
||||||
|
|
||||||
# Mock the server response with a dummy apps catalog
|
# Mock the server response with a dummy apps catalog
|
||||||
m.register_uri("GET", APPS_CATALOG_DEFAULT_URL_FULL, text=DUMMY_APP_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):
|
def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
# Make sure we have a ssowat
|
# Make sure we have a ssowat
|
||||||
os.system("mkdir -p /etc/ssowat/")
|
os.system("mkdir -p /etc/ssowat/")
|
||||||
app_ssowatconf()
|
app_ssowatconf()
|
||||||
|
@ -43,7 +40,6 @@ def clean():
|
||||||
test_apps = ["config_app", "legacy_app"]
|
test_apps = ["config_app", "legacy_app"]
|
||||||
|
|
||||||
for test_app in test_apps:
|
for test_app in test_apps:
|
||||||
|
|
||||||
if _is_installed(test_app):
|
if _is_installed(test_app):
|
||||||
app_remove(test_app)
|
app_remove(test_app)
|
||||||
|
|
||||||
|
@ -66,7 +62,6 @@ def clean():
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def legacy_app(request):
|
def legacy_app(request):
|
||||||
|
|
||||||
main_domain = _get_maindomain()
|
main_domain = _get_maindomain()
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
|
@ -85,7 +80,6 @@ def legacy_app(request):
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
def config_app(request):
|
def config_app(request):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "config_app_ynh"),
|
os.path.join(get_test_apps_dir(), "config_app_ynh"),
|
||||||
args="",
|
args="",
|
||||||
|
@ -101,7 +95,6 @@ def config_app(request):
|
||||||
|
|
||||||
|
|
||||||
def test_app_config_get(config_app):
|
def test_app_config_get(config_app):
|
||||||
|
|
||||||
user_create("alice", _get_maindomain(), "test123Ynh", fullname="Alice White")
|
user_create("alice", _get_maindomain(), "test123Ynh", fullname="Alice White")
|
||||||
|
|
||||||
assert isinstance(app_config_get(config_app), dict)
|
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):
|
def test_app_config_nopanel(legacy_app):
|
||||||
|
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
app_config_get(legacy_app)
|
app_config_get(legacy_app)
|
||||||
|
|
||||||
|
|
||||||
def test_app_config_get_nonexistentstuff(config_app):
|
def test_app_config_get_nonexistentstuff(config_app):
|
||||||
|
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
app_config_get("nonexistent")
|
app_config_get("nonexistent")
|
||||||
|
|
||||||
|
@ -140,7 +131,6 @@ def test_app_config_get_nonexistentstuff(config_app):
|
||||||
|
|
||||||
|
|
||||||
def test_app_config_regular_setting(config_app):
|
def test_app_config_regular_setting(config_app):
|
||||||
|
|
||||||
assert app_config_get(config_app, "main.components.boolean") == 0
|
assert app_config_get(config_app, "main.components.boolean") == 0
|
||||||
|
|
||||||
app_config_set(config_app, "main.components.boolean", "no")
|
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):
|
def test_app_config_bind_on_file(config_app):
|
||||||
|
|
||||||
# c.f. conf/test.php in the 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 '$arg5= "Arg5 value";' in read_file("/var/www/config_app/test.php")
|
||||||
assert app_config_get(config_app, "bind.variable.arg5") == "Arg5 value"
|
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):
|
def test_app_config_custom_validator(config_app):
|
||||||
|
|
||||||
# c.f. the config script
|
# c.f. the config script
|
||||||
# arg8 is a password that must be at least 8 chars
|
# arg8 is a password that must be at least 8 chars
|
||||||
assert not os.path.exists("/var/www/config_app/password")
|
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):
|
def test_app_config_custom_set(config_app):
|
||||||
|
|
||||||
assert not os.path.exists("/var/www/config_app/password")
|
assert not os.path.exists("/var/www/config_app/password")
|
||||||
assert app_setting(config_app, "arg8") is None
|
assert app_setting(config_app, "arg8") is None
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ dummyfile = "/tmp/dummyappresource-testapp"
|
||||||
|
|
||||||
|
|
||||||
class DummyAppResource(AppResource):
|
class DummyAppResource(AppResource):
|
||||||
|
|
||||||
type = "dummy"
|
type = "dummy"
|
||||||
|
|
||||||
default_properties = {
|
default_properties = {
|
||||||
|
@ -26,14 +25,12 @@ class DummyAppResource(AppResource):
|
||||||
}
|
}
|
||||||
|
|
||||||
def provision_or_update(self, context):
|
def provision_or_update(self, context):
|
||||||
|
|
||||||
open(self.file, "w").write(self.content)
|
open(self.file, "w").write(self.content)
|
||||||
|
|
||||||
if self.content == "forbiddenvalue":
|
if self.content == "forbiddenvalue":
|
||||||
raise Exception("Emeged you used the forbidden value!1!£&")
|
raise Exception("Emeged you used the forbidden value!1!£&")
|
||||||
|
|
||||||
def deprovision(self, context):
|
def deprovision(self, context):
|
||||||
|
|
||||||
os.system(f"rm -f {self.file}")
|
os.system(f"rm -f {self.file}")
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,7 +38,6 @@ AppResourceClassesByType["dummy"] = DummyAppResource
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
os.system("mkdir /etc/yunohost/apps/testapp")
|
os.system("mkdir /etc/yunohost/apps/testapp")
|
||||||
|
@ -51,12 +47,10 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
os.system(f"rm -f {dummyfile}")
|
os.system(f"rm -f {dummyfile}")
|
||||||
os.system("rm -rf /etc/yunohost/apps/testapp")
|
os.system("rm -rf /etc/yunohost/apps/testapp")
|
||||||
os.system("rm -rf /var/www/testapp")
|
os.system("rm -rf /var/www/testapp")
|
||||||
|
@ -70,7 +64,6 @@ def clean():
|
||||||
|
|
||||||
|
|
||||||
def test_provision_dummy():
|
def test_provision_dummy():
|
||||||
|
|
||||||
current = {"resources": {}}
|
current = {"resources": {}}
|
||||||
wanted = {"resources": {"dummy": {}}}
|
wanted = {"resources": {"dummy": {}}}
|
||||||
|
|
||||||
|
@ -82,7 +75,6 @@ def test_provision_dummy():
|
||||||
|
|
||||||
|
|
||||||
def test_deprovision_dummy():
|
def test_deprovision_dummy():
|
||||||
|
|
||||||
current = {"resources": {"dummy": {}}}
|
current = {"resources": {"dummy": {}}}
|
||||||
wanted = {"resources": {}}
|
wanted = {"resources": {}}
|
||||||
|
|
||||||
|
@ -96,7 +88,6 @@ def test_deprovision_dummy():
|
||||||
|
|
||||||
|
|
||||||
def test_provision_dummy_nondefaultvalue():
|
def test_provision_dummy_nondefaultvalue():
|
||||||
|
|
||||||
current = {"resources": {}}
|
current = {"resources": {}}
|
||||||
wanted = {"resources": {"dummy": {"content": "bar"}}}
|
wanted = {"resources": {"dummy": {"content": "bar"}}}
|
||||||
|
|
||||||
|
@ -108,7 +99,6 @@ def test_provision_dummy_nondefaultvalue():
|
||||||
|
|
||||||
|
|
||||||
def test_update_dummy():
|
def test_update_dummy():
|
||||||
|
|
||||||
current = {"resources": {"dummy": {}}}
|
current = {"resources": {"dummy": {}}}
|
||||||
wanted = {"resources": {"dummy": {"content": "bar"}}}
|
wanted = {"resources": {"dummy": {"content": "bar"}}}
|
||||||
|
|
||||||
|
@ -122,7 +112,6 @@ def test_update_dummy():
|
||||||
|
|
||||||
|
|
||||||
def test_update_dummy_failwithrollback():
|
def test_update_dummy_failwithrollback():
|
||||||
|
|
||||||
current = {"resources": {"dummy": {}}}
|
current = {"resources": {"dummy": {}}}
|
||||||
wanted = {"resources": {"dummy": {"content": "forbiddenvalue"}}}
|
wanted = {"resources": {"dummy": {"content": "forbiddenvalue"}}}
|
||||||
|
|
||||||
|
@ -137,7 +126,6 @@ def test_update_dummy_failwithrollback():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_system_user():
|
def test_resource_system_user():
|
||||||
|
|
||||||
r = AppResourceClassesByType["system_user"]
|
r = AppResourceClassesByType["system_user"]
|
||||||
|
|
||||||
conf = {}
|
conf = {}
|
||||||
|
@ -161,7 +149,6 @@ def test_resource_system_user():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_install_dir():
|
def test_resource_install_dir():
|
||||||
|
|
||||||
r = AppResourceClassesByType["install_dir"]
|
r = AppResourceClassesByType["install_dir"]
|
||||||
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
|
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
|
||||||
|
|
||||||
|
@ -196,7 +183,6 @@ def test_resource_install_dir():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_data_dir():
|
def test_resource_data_dir():
|
||||||
|
|
||||||
r = AppResourceClassesByType["data_dir"]
|
r = AppResourceClassesByType["data_dir"]
|
||||||
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
|
conf = {"owner": "nobody:rx", "group": "nogroup:rx"}
|
||||||
|
|
||||||
|
@ -228,7 +214,6 @@ def test_resource_data_dir():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_ports():
|
def test_resource_ports():
|
||||||
|
|
||||||
r = AppResourceClassesByType["ports"]
|
r = AppResourceClassesByType["ports"]
|
||||||
conf = {}
|
conf = {}
|
||||||
|
|
||||||
|
@ -244,7 +229,6 @@ def test_resource_ports():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_ports_several():
|
def test_resource_ports_several():
|
||||||
|
|
||||||
r = AppResourceClassesByType["ports"]
|
r = AppResourceClassesByType["ports"]
|
||||||
conf = {"main": {"default": 12345}, "foobar": {"default": 23456}}
|
conf = {"main": {"default": 12345}, "foobar": {"default": 23456}}
|
||||||
|
|
||||||
|
@ -263,7 +247,6 @@ def test_resource_ports_several():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_ports_firewall():
|
def test_resource_ports_firewall():
|
||||||
|
|
||||||
r = AppResourceClassesByType["ports"]
|
r = AppResourceClassesByType["ports"]
|
||||||
conf = {"main": {"default": 12345}}
|
conf = {"main": {"default": 12345}}
|
||||||
|
|
||||||
|
@ -283,7 +266,6 @@ def test_resource_ports_firewall():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_database():
|
def test_resource_database():
|
||||||
|
|
||||||
r = AppResourceClassesByType["database"]
|
r = AppResourceClassesByType["database"]
|
||||||
conf = {"type": "mysql"}
|
conf = {"type": "mysql"}
|
||||||
|
|
||||||
|
@ -308,7 +290,6 @@ def test_resource_database():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_apt():
|
def test_resource_apt():
|
||||||
|
|
||||||
r = AppResourceClassesByType["apt"]
|
r = AppResourceClassesByType["apt"]
|
||||||
conf = {
|
conf = {
|
||||||
"packages": "nyancat, sl",
|
"packages": "nyancat, sl",
|
||||||
|
@ -356,7 +337,6 @@ def test_resource_apt():
|
||||||
|
|
||||||
|
|
||||||
def test_resource_permissions():
|
def test_resource_permissions():
|
||||||
|
|
||||||
maindomain = _get_maindomain()
|
maindomain = _get_maindomain()
|
||||||
os.system(f"echo 'domain: {maindomain}' >> /etc/yunohost/apps/testapp/settings.yml")
|
os.system(f"echo 'domain: {maindomain}' >> /etc/yunohost/apps/testapp/settings.yml")
|
||||||
os.system("echo 'path: /testapp' >> /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):
|
def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
# Make sure we have a ssowat
|
# Make sure we have a ssowat
|
||||||
os.system("mkdir -p /etc/ssowat/")
|
os.system("mkdir -p /etc/ssowat/")
|
||||||
app_ssowatconf()
|
app_ssowatconf()
|
||||||
|
@ -53,7 +50,6 @@ def clean():
|
||||||
]
|
]
|
||||||
|
|
||||||
for test_app in test_apps:
|
for test_app in test_apps:
|
||||||
|
|
||||||
if _is_installed(test_app):
|
if _is_installed(test_app):
|
||||||
app_remove(test_app)
|
app_remove(test_app)
|
||||||
|
|
||||||
|
@ -95,7 +91,6 @@ def check_permission_for_apps_call():
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def secondary_domain(request):
|
def secondary_domain(request):
|
||||||
|
|
||||||
if "example.test" not in domain_list()["domains"]:
|
if "example.test" not in domain_list()["domains"]:
|
||||||
domain_add("example.test")
|
domain_add("example.test")
|
||||||
|
|
||||||
|
@ -113,7 +108,6 @@ def secondary_domain(request):
|
||||||
|
|
||||||
|
|
||||||
def app_expected_files(domain, app):
|
def app_expected_files(domain, app):
|
||||||
|
|
||||||
yield "/etc/nginx/conf.d/{}.d/{}.conf".format(domain, app)
|
yield "/etc/nginx/conf.d/{}.d/{}.conf".format(domain, app)
|
||||||
if app.startswith("legacy_app"):
|
if app.startswith("legacy_app"):
|
||||||
yield "/var/www/%s/index.html" % app
|
yield "/var/www/%s/index.html" % app
|
||||||
|
@ -127,21 +121,18 @@ def app_expected_files(domain, app):
|
||||||
|
|
||||||
|
|
||||||
def app_is_installed(domain, app):
|
def app_is_installed(domain, app):
|
||||||
|
|
||||||
return _is_installed(app) and all(
|
return _is_installed(app) and all(
|
||||||
os.path.exists(f) for f in app_expected_files(domain, app)
|
os.path.exists(f) for f in app_expected_files(domain, app)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def app_is_not_installed(domain, app):
|
def app_is_not_installed(domain, app):
|
||||||
|
|
||||||
return not _is_installed(app) and not all(
|
return not _is_installed(app) and not all(
|
||||||
os.path.exists(f) for f in app_expected_files(domain, app)
|
os.path.exists(f) for f in app_expected_files(domain, app)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def app_is_exposed_on_http(domain, path, message_in_page):
|
def app_is_exposed_on_http(domain, path, message_in_page):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
r = requests.get(
|
r = requests.get(
|
||||||
"https://127.0.0.1" + path + "/",
|
"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):
|
def install_legacy_app(domain, path, public=True):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
|
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
|
||||||
args="domain={}&path={}&is_public={}".format(domain, path, 1 if public else 0),
|
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):
|
def install_manifestv2_app(domain, path, public=True):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"),
|
os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"),
|
||||||
args="domain={}&path={}&init_main_permission={}".format(
|
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):
|
def install_full_domain_app(domain):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "full_domain_app_ynh"),
|
os.path.join(get_test_apps_dir(), "full_domain_app_ynh"),
|
||||||
args="domain=%s" % domain,
|
args="domain=%s" % domain,
|
||||||
|
@ -184,7 +172,6 @@ def install_full_domain_app(domain):
|
||||||
|
|
||||||
|
|
||||||
def install_break_yo_system(domain, breakwhat):
|
def install_break_yo_system(domain, breakwhat):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "break_yo_system_ynh"),
|
os.path.join(get_test_apps_dir(), "break_yo_system_ynh"),
|
||||||
args="domain={}&breakwhat={}".format(domain, breakwhat),
|
args="domain={}&breakwhat={}".format(domain, breakwhat),
|
||||||
|
@ -193,7 +180,6 @@ def install_break_yo_system(domain, breakwhat):
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_app_install_main_domain():
|
def test_legacy_app_install_main_domain():
|
||||||
|
|
||||||
main_domain = _get_maindomain()
|
main_domain = _get_maindomain()
|
||||||
|
|
||||||
install_legacy_app(main_domain, "/legacy")
|
install_legacy_app(main_domain, "/legacy")
|
||||||
|
@ -213,7 +199,6 @@ def test_legacy_app_install_main_domain():
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_app_manifest_preinstall():
|
def test_legacy_app_manifest_preinstall():
|
||||||
|
|
||||||
m = app_manifest(os.path.join(get_test_apps_dir(), "legacy_app_ynh"))
|
m = app_manifest(os.path.join(get_test_apps_dir(), "legacy_app_ynh"))
|
||||||
# v1 manifesto are expected to have been autoconverted to v2
|
# 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():
|
def test_manifestv2_app_manifest_preinstall():
|
||||||
|
|
||||||
m = app_manifest(os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"))
|
m = app_manifest(os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"))
|
||||||
|
|
||||||
assert "id" in m
|
assert "id" in m
|
||||||
|
@ -258,7 +242,6 @@ def test_manifestv2_app_manifest_preinstall():
|
||||||
|
|
||||||
|
|
||||||
def test_manifestv2_app_install_main_domain():
|
def test_manifestv2_app_install_main_domain():
|
||||||
|
|
||||||
main_domain = _get_maindomain()
|
main_domain = _get_maindomain()
|
||||||
|
|
||||||
install_manifestv2_app(main_domain, "/manifestv2")
|
install_manifestv2_app(main_domain, "/manifestv2")
|
||||||
|
@ -278,7 +261,6 @@ def test_manifestv2_app_install_main_domain():
|
||||||
|
|
||||||
|
|
||||||
def test_manifestv2_app_info_postinstall():
|
def test_manifestv2_app_info_postinstall():
|
||||||
|
|
||||||
main_domain = _get_maindomain()
|
main_domain = _get_maindomain()
|
||||||
install_manifestv2_app(main_domain, "/manifestv2")
|
install_manifestv2_app(main_domain, "/manifestv2")
|
||||||
m = app_info("manifestv2_app", full=True)["manifest"]
|
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):
|
def test_manifestv2_app_info_preupgrade(monkeypatch):
|
||||||
|
|
||||||
manifest = app_manifest(os.path.join(get_test_apps_dir(), "manifestv2_app_ynh"))
|
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
|
from yunohost.app_catalog import _load_apps_catalog as original_load_apps_catalog
|
||||||
|
|
||||||
def custom_load_apps_catalog(*args, **kwargs):
|
def custom_load_apps_catalog(*args, **kwargs):
|
||||||
|
|
||||||
res = original_load_apps_catalog(*args, **kwargs)
|
res = original_load_apps_catalog(*args, **kwargs)
|
||||||
res["apps"]["manifestv2_app"] = {
|
res["apps"]["manifestv2_app"] = {
|
||||||
"id": "manifestv2_app",
|
"id": "manifestv2_app",
|
||||||
|
@ -372,7 +352,6 @@ def test_app_from_catalog():
|
||||||
|
|
||||||
|
|
||||||
def test_legacy_app_install_secondary_domain(secondary_domain):
|
def test_legacy_app_install_secondary_domain(secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
assert app_is_installed(secondary_domain, "legacy_app")
|
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):
|
def test_legacy_app_install_secondary_domain_on_root(secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/")
|
install_legacy_app(secondary_domain, "/")
|
||||||
|
|
||||||
app_map_ = app_map(raw=True)
|
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):
|
def test_legacy_app_install_private(secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/legacy", public=False)
|
install_legacy_app(secondary_domain, "/legacy", public=False)
|
||||||
|
|
||||||
assert app_is_installed(secondary_domain, "legacy_app")
|
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):
|
def test_legacy_app_install_unknown_domain(mocker):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_argument_invalid"):
|
with message(mocker, "app_argument_invalid"):
|
||||||
install_legacy_app("whatever.nope", "/legacy")
|
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):
|
def test_legacy_app_install_multiple_instances(secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/foo")
|
install_legacy_app(secondary_domain, "/foo")
|
||||||
install_legacy_app(secondary_domain, "/bar")
|
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):
|
def test_legacy_app_install_path_unavailable(mocker, secondary_domain):
|
||||||
|
|
||||||
# These will be removed in teardown
|
# These will be removed in teardown
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
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):
|
def test_legacy_app_install_with_nginx_down(mocker, secondary_domain):
|
||||||
|
|
||||||
os.system("systemctl stop nginx")
|
os.system("systemctl stop nginx")
|
||||||
|
|
||||||
with raiseYunohostError(
|
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):
|
def test_legacy_app_failed_install(mocker, secondary_domain):
|
||||||
|
|
||||||
# This will conflict with the folder that the app
|
# This will conflict with the folder that the app
|
||||||
# attempts to create, making the install fail
|
# attempts to create, making the install fail
|
||||||
mkdir("/var/www/legacy_app/", 0o750)
|
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):
|
def test_legacy_app_failed_remove(mocker, secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
# The remove script runs with set -eu and attempt to remove this
|
# 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):
|
def test_full_domain_app(secondary_domain):
|
||||||
|
|
||||||
install_full_domain_app(secondary_domain)
|
install_full_domain_app(secondary_domain)
|
||||||
|
|
||||||
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
|
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
|
||||||
|
|
||||||
|
|
||||||
def test_full_domain_app_with_conflicts(mocker, secondary_domain):
|
def test_full_domain_app_with_conflicts(mocker, secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
with raiseYunohostError(mocker, "app_full_domain_unavailable"):
|
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):
|
def test_systemfuckedup_during_app_install(mocker, secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_install_failed"):
|
with message(mocker, "app_install_failed"):
|
||||||
with message(mocker, "app_action_broke_system"):
|
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):
|
def test_systemfuckedup_during_app_remove(mocker, secondary_domain):
|
||||||
|
|
||||||
install_break_yo_system(secondary_domain, breakwhat="remove")
|
install_break_yo_system(secondary_domain, breakwhat="remove")
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
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):
|
def test_systemfuckedup_during_app_install_and_remove(mocker, secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
with message(mocker, "app_install_failed"):
|
with message(mocker, "app_install_failed"):
|
||||||
with message(mocker, "app_action_broke_system"):
|
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):
|
def test_systemfuckedup_during_app_upgrade(mocker, secondary_domain):
|
||||||
|
|
||||||
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
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):
|
def test_failed_multiple_app_upgrade(mocker, secondary_domain):
|
||||||
|
|
||||||
install_legacy_app(secondary_domain, "/legacy")
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
install_break_yo_system(secondary_domain, breakwhat="upgrade")
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,6 @@ maindomain = _get_maindomain()
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
app_remove("register_url_app")
|
app_remove("register_url_app")
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -26,7 +25,6 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
app_remove("register_url_app")
|
app_remove("register_url_app")
|
||||||
except Exception:
|
except Exception:
|
||||||
|
@ -34,7 +32,6 @@ def teardown_function(function):
|
||||||
|
|
||||||
|
|
||||||
def test_parse_app_instance_name():
|
def test_parse_app_instance_name():
|
||||||
|
|
||||||
assert _parse_app_instance_name("yolo") == ("yolo", 1)
|
assert _parse_app_instance_name("yolo") == ("yolo", 1)
|
||||||
assert _parse_app_instance_name("yolo1") == ("yolo1", 1)
|
assert _parse_app_instance_name("yolo1") == ("yolo1", 1)
|
||||||
assert _parse_app_instance_name("yolo__0") == ("yolo__0", 1)
|
assert _parse_app_instance_name("yolo__0") == ("yolo__0", 1)
|
||||||
|
@ -86,7 +83,6 @@ def test_repo_url_definition():
|
||||||
|
|
||||||
|
|
||||||
def test_urlavailable():
|
def test_urlavailable():
|
||||||
|
|
||||||
# Except the maindomain/macnuggets to be available
|
# Except the maindomain/macnuggets to be available
|
||||||
assert domain_url_available(maindomain, "/macnuggets")
|
assert domain_url_available(maindomain, "/macnuggets")
|
||||||
|
|
||||||
|
@ -96,7 +92,6 @@ def test_urlavailable():
|
||||||
|
|
||||||
|
|
||||||
def test_registerurl():
|
def test_registerurl():
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),
|
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),
|
||||||
args="domain={}&path={}".format(maindomain, "/urlregisterapp"),
|
args="domain={}&path={}".format(maindomain, "/urlregisterapp"),
|
||||||
|
@ -115,7 +110,6 @@ def test_registerurl():
|
||||||
|
|
||||||
|
|
||||||
def test_registerurl_baddomain():
|
def test_registerurl_baddomain():
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),
|
os.path.join(get_test_apps_dir(), "register_url_app_ynh"),
|
||||||
|
|
|
@ -30,7 +30,6 @@ maindomain = ""
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
global maindomain
|
global maindomain
|
||||||
maindomain = _get_maindomain()
|
maindomain = _get_maindomain()
|
||||||
|
|
||||||
|
@ -89,7 +88,6 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
assert tmp_backup_directory_is_empty()
|
assert tmp_backup_directory_is_empty()
|
||||||
|
|
||||||
reset_ssowat_conf()
|
reset_ssowat_conf()
|
||||||
|
@ -133,7 +131,6 @@ def check_permission_for_apps_call():
|
||||||
|
|
||||||
|
|
||||||
def app_is_installed(app):
|
def app_is_installed(app):
|
||||||
|
|
||||||
if app == "permissions_app":
|
if app == "permissions_app":
|
||||||
return _is_installed(app)
|
return _is_installed(app)
|
||||||
|
|
||||||
|
@ -147,7 +144,6 @@ def app_is_installed(app):
|
||||||
|
|
||||||
|
|
||||||
def backup_test_dependencies_are_met():
|
def backup_test_dependencies_are_met():
|
||||||
|
|
||||||
# Dummy test apps (or backup archives)
|
# Dummy test apps (or backup archives)
|
||||||
assert os.path.exists(
|
assert os.path.exists(
|
||||||
os.path.join(get_test_apps_dir(), "backup_wordpress_from_4p2")
|
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():
|
def tmp_backup_directory_is_empty():
|
||||||
|
|
||||||
if not os.path.exists("/home/yunohost.backup/tmp/"):
|
if not os.path.exists("/home/yunohost.backup/tmp/"):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -169,7 +164,6 @@ def tmp_backup_directory_is_empty():
|
||||||
|
|
||||||
|
|
||||||
def clean_tmp_backup_directory():
|
def clean_tmp_backup_directory():
|
||||||
|
|
||||||
if tmp_backup_directory_is_empty():
|
if tmp_backup_directory_is_empty():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -191,27 +185,23 @@ def clean_tmp_backup_directory():
|
||||||
|
|
||||||
|
|
||||||
def reset_ssowat_conf():
|
def reset_ssowat_conf():
|
||||||
|
|
||||||
# Make sure we have a ssowat
|
# Make sure we have a ssowat
|
||||||
os.system("mkdir -p /etc/ssowat/")
|
os.system("mkdir -p /etc/ssowat/")
|
||||||
app_ssowatconf()
|
app_ssowatconf()
|
||||||
|
|
||||||
|
|
||||||
def delete_all_backups():
|
def delete_all_backups():
|
||||||
|
|
||||||
for archive in backup_list()["archives"]:
|
for archive in backup_list()["archives"]:
|
||||||
backup_delete(archive)
|
backup_delete(archive)
|
||||||
|
|
||||||
|
|
||||||
def uninstall_test_apps_if_needed():
|
def uninstall_test_apps_if_needed():
|
||||||
|
|
||||||
for app in ["legacy_app", "backup_recommended_app", "wordpress", "permissions_app"]:
|
for app in ["legacy_app", "backup_recommended_app", "wordpress", "permissions_app"]:
|
||||||
if _is_installed(app):
|
if _is_installed(app):
|
||||||
app_remove(app)
|
app_remove(app)
|
||||||
|
|
||||||
|
|
||||||
def install_app(app, path, additionnal_args=""):
|
def install_app(app, path, additionnal_args=""):
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), app),
|
os.path.join(get_test_apps_dir(), app),
|
||||||
args="domain={}&path={}{}".format(maindomain, path, additionnal_args),
|
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():
|
def add_archive_wordpress_from_4p2():
|
||||||
|
|
||||||
os.system("mkdir -p /home/yunohost.backup/archives")
|
os.system("mkdir -p /home/yunohost.backup/archives")
|
||||||
|
|
||||||
os.system(
|
os.system(
|
||||||
|
@ -231,7 +220,6 @@ def add_archive_wordpress_from_4p2():
|
||||||
|
|
||||||
|
|
||||||
def add_archive_system_from_4p2():
|
def add_archive_system_from_4p2():
|
||||||
|
|
||||||
os.system("mkdir -p /home/yunohost.backup/archives")
|
os.system("mkdir -p /home/yunohost.backup/archives")
|
||||||
|
|
||||||
os.system(
|
os.system(
|
||||||
|
@ -247,7 +235,6 @@ def add_archive_system_from_4p2():
|
||||||
|
|
||||||
|
|
||||||
def test_backup_only_ldap(mocker):
|
def test_backup_only_ldap(mocker):
|
||||||
|
|
||||||
# Create the backup
|
# Create the backup
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(system=["conf_ldap"], apps=None)
|
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):
|
def test_backup_system_part_that_does_not_exists(mocker):
|
||||||
|
|
||||||
# Create the backup
|
# Create the backup
|
||||||
with message(mocker, "backup_hook_unknown", hook="doesnt_exist"):
|
with message(mocker, "backup_hook_unknown", hook="doesnt_exist"):
|
||||||
with raiseYunohostError(mocker, "backup_nothings_done"):
|
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):
|
def test_backup_and_restore_all_sys(mocker):
|
||||||
|
|
||||||
# Create the backup
|
# Create the backup
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(system=[], apps=None)
|
backup_create(system=[], apps=None)
|
||||||
|
@ -309,7 +294,6 @@ def test_backup_and_restore_all_sys(mocker):
|
||||||
|
|
||||||
@pytest.mark.with_system_archive_from_4p2
|
@pytest.mark.with_system_archive_from_4p2
|
||||||
def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
|
def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
|
||||||
|
|
||||||
# Backup current system
|
# Backup current system
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(system=[], apps=None)
|
backup_create(system=[], apps=None)
|
||||||
|
@ -337,7 +321,6 @@ def test_restore_system_from_Ynh4p2(monkeypatch, mocker):
|
||||||
@pytest.mark.with_backup_recommended_app_installed
|
@pytest.mark.with_backup_recommended_app_installed
|
||||||
def test_backup_script_failure_handling(monkeypatch, mocker):
|
def test_backup_script_failure_handling(monkeypatch, mocker):
|
||||||
def custom_hook_exec(name, *args, **kwargs):
|
def custom_hook_exec(name, *args, **kwargs):
|
||||||
|
|
||||||
if os.path.basename(name).startswith("backup_"):
|
if os.path.basename(name).startswith("backup_"):
|
||||||
raise Exception
|
raise Exception
|
||||||
else:
|
else:
|
||||||
|
@ -373,7 +356,6 @@ def test_backup_not_enough_free_space(monkeypatch, mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_backup_app_not_installed(mocker):
|
def test_backup_app_not_installed(mocker):
|
||||||
|
|
||||||
assert not _is_installed("wordpress")
|
assert not _is_installed("wordpress")
|
||||||
|
|
||||||
with message(mocker, "unbackup_app", app="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
|
@pytest.mark.with_backup_recommended_app_installed
|
||||||
def test_backup_app_with_no_backup_script(mocker):
|
def test_backup_app_with_no_backup_script(mocker):
|
||||||
|
|
||||||
backup_script = "/etc/yunohost/apps/backup_recommended_app/scripts/backup"
|
backup_script = "/etc/yunohost/apps/backup_recommended_app/scripts/backup"
|
||||||
os.system("rm %s" % backup_script)
|
os.system("rm %s" % backup_script)
|
||||||
assert not os.path.exists(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
|
@pytest.mark.with_backup_recommended_app_installed
|
||||||
def test_backup_app_with_no_restore_script(mocker):
|
def test_backup_app_with_no_restore_script(mocker):
|
||||||
|
|
||||||
restore_script = "/etc/yunohost/apps/backup_recommended_app/scripts/restore"
|
restore_script = "/etc/yunohost/apps/backup_recommended_app/scripts/restore"
|
||||||
os.system("rm %s" % restore_script)
|
os.system("rm %s" % restore_script)
|
||||||
assert not os.path.exists(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
|
@pytest.mark.clean_opt_dir
|
||||||
def test_backup_with_different_output_directory(mocker):
|
def test_backup_with_different_output_directory(mocker):
|
||||||
|
|
||||||
# Create the backup
|
# Create the backup
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(
|
backup_create(
|
||||||
|
@ -436,7 +415,6 @@ def test_backup_with_different_output_directory(mocker):
|
||||||
|
|
||||||
@pytest.mark.clean_opt_dir
|
@pytest.mark.clean_opt_dir
|
||||||
def test_backup_using_copy_method(mocker):
|
def test_backup_using_copy_method(mocker):
|
||||||
|
|
||||||
# Create the backup
|
# Create the backup
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(
|
backup_create(
|
||||||
|
@ -458,7 +436,6 @@ def test_backup_using_copy_method(mocker):
|
||||||
@pytest.mark.with_wordpress_archive_from_4p2
|
@pytest.mark.with_wordpress_archive_from_4p2
|
||||||
@pytest.mark.with_custom_domain("yolo.test")
|
@pytest.mark.with_custom_domain("yolo.test")
|
||||||
def test_restore_app_wordpress_from_Ynh4p2(mocker):
|
def test_restore_app_wordpress_from_Ynh4p2(mocker):
|
||||||
|
|
||||||
with message(mocker, "restore_complete"):
|
with message(mocker, "restore_complete"):
|
||||||
backup_restore(
|
backup_restore(
|
||||||
system=None, name=backup_list()["archives"][0], apps=["wordpress"]
|
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
|
@pytest.mark.with_wordpress_archive_from_4p2
|
||||||
def test_restore_app_not_in_backup(mocker):
|
def test_restore_app_not_in_backup(mocker):
|
||||||
|
|
||||||
assert not _is_installed("wordpress")
|
assert not _is_installed("wordpress")
|
||||||
assert not _is_installed("yoloswag")
|
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_wordpress_archive_from_4p2
|
||||||
@pytest.mark.with_custom_domain("yolo.test")
|
@pytest.mark.with_custom_domain("yolo.test")
|
||||||
def test_restore_app_already_installed(mocker):
|
def test_restore_app_already_installed(mocker):
|
||||||
|
|
||||||
assert not _is_installed("wordpress")
|
assert not _is_installed("wordpress")
|
||||||
|
|
||||||
with message(mocker, "restore_complete"):
|
with message(mocker, "restore_complete"):
|
||||||
|
@ -544,25 +519,21 @@ def test_restore_app_already_installed(mocker):
|
||||||
|
|
||||||
@pytest.mark.with_legacy_app_installed
|
@pytest.mark.with_legacy_app_installed
|
||||||
def test_backup_and_restore_legacy_app(mocker):
|
def test_backup_and_restore_legacy_app(mocker):
|
||||||
|
|
||||||
_test_backup_and_restore_app(mocker, "legacy_app")
|
_test_backup_and_restore_app(mocker, "legacy_app")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.with_backup_recommended_app_installed
|
@pytest.mark.with_backup_recommended_app_installed
|
||||||
def test_backup_and_restore_recommended_app(mocker):
|
def test_backup_and_restore_recommended_app(mocker):
|
||||||
|
|
||||||
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.with_backup_recommended_app_installed_with_ynh_restore
|
@pytest.mark.with_backup_recommended_app_installed_with_ynh_restore
|
||||||
def test_backup_and_restore_with_ynh_restore(mocker):
|
def test_backup_and_restore_with_ynh_restore(mocker):
|
||||||
|
|
||||||
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
_test_backup_and_restore_app(mocker, "backup_recommended_app")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.with_permission_app_installed
|
@pytest.mark.with_permission_app_installed
|
||||||
def test_backup_and_restore_permission_app(mocker):
|
def test_backup_and_restore_permission_app(mocker):
|
||||||
|
|
||||||
res = user_permission_list(full=True)["permissions"]
|
res = user_permission_list(full=True)["permissions"]
|
||||||
assert "permissions_app.main" in res
|
assert "permissions_app.main" in res
|
||||||
assert "permissions_app.admin" 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):
|
def _test_backup_and_restore_app(mocker, app):
|
||||||
|
|
||||||
# Create a backup of this app
|
# Create a backup of this app
|
||||||
with message(mocker, "backup_created"):
|
with message(mocker, "backup_created"):
|
||||||
backup_create(system=None, apps=[app])
|
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):
|
def test_restore_archive_with_no_json(mocker):
|
||||||
|
|
||||||
# Create a backup with no info.json associated
|
# Create a backup with no info.json associated
|
||||||
os.system("touch /tmp/afile")
|
os.system("touch /tmp/afile")
|
||||||
os.system("tar -cvf /home/yunohost.backup/archives/badbackup.tar /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
|
@pytest.mark.with_wordpress_archive_from_4p2
|
||||||
def test_restore_archive_with_bad_archive(mocker):
|
def test_restore_archive_with_bad_archive(mocker):
|
||||||
|
|
||||||
# Break the archive
|
# Break the archive
|
||||||
os.system(
|
os.system(
|
||||||
"head -n 1000 /home/yunohost.backup/archives/backup_wordpress_from_4p2.tar > /home/yunohost.backup/archives/backup_wordpress_from_4p2_bad.tar"
|
"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):
|
def test_restore_archive_with_custom_hook(mocker):
|
||||||
|
|
||||||
custom_restore_hook_folder = os.path.join(CUSTOM_HOOK_FOLDER, "restore")
|
custom_restore_hook_folder = os.path.join(CUSTOM_HOOK_FOLDER, "restore")
|
||||||
os.system("touch %s/99-yolo" % custom_restore_hook_folder)
|
os.system("touch %s/99-yolo" % custom_restore_hook_folder)
|
||||||
|
|
||||||
|
|
|
@ -12,12 +12,10 @@ from yunohost.dns import (
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
|
@ -76,7 +74,6 @@ def example_domain():
|
||||||
|
|
||||||
|
|
||||||
def test_domain_dns_suggest(example_domain):
|
def test_domain_dns_suggest(example_domain):
|
||||||
|
|
||||||
assert _build_dns_conf(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):
|
def setup_function(function):
|
||||||
|
|
||||||
# Save domain list in variable to avoid multiple calls to domain_list()
|
# Save domain list in variable to avoid multiple calls to domain_list()
|
||||||
domains = domain_list()["domains"]
|
domains = domain_list()["domains"]
|
||||||
|
|
||||||
|
@ -52,7 +51,6 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
|
@ -102,7 +100,6 @@ def test_domain_config_get_default():
|
||||||
|
|
||||||
|
|
||||||
def test_domain_config_get_export():
|
def test_domain_config_get_export():
|
||||||
|
|
||||||
assert domain_config_get(TEST_DOMAINS[0], export=True)["xmpp"] == 1
|
assert domain_config_get(TEST_DOMAINS[0], export=True)["xmpp"] == 1
|
||||||
assert domain_config_get(TEST_DOMAINS[1], export=True)["xmpp"] == 0
|
assert domain_config_get(TEST_DOMAINS[1], export=True)["xmpp"] == 0
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ from moulinette.core import MoulinetteError
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
for u in user_list()["users"]:
|
for u in user_list()["users"]:
|
||||||
user_delete(u, purge=True)
|
user_delete(u, purge=True)
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ def setup_function(function):
|
||||||
|
|
||||||
|
|
||||||
def teardown_function():
|
def teardown_function():
|
||||||
|
|
||||||
os.system("systemctl is-active slapd >/dev/null || systemctl start slapd; sleep 5")
|
os.system("systemctl is-active slapd >/dev/null || systemctl start slapd; sleep 5")
|
||||||
|
|
||||||
for u in user_list()["users"]:
|
for u in user_list()["users"]:
|
||||||
|
@ -36,7 +34,6 @@ def test_authenticate():
|
||||||
|
|
||||||
|
|
||||||
def test_authenticate_with_no_user():
|
def test_authenticate_with_no_user():
|
||||||
|
|
||||||
with pytest.raises(MoulinetteError):
|
with pytest.raises(MoulinetteError):
|
||||||
LDAPAuth().authenticate_credentials(credentials="Yunohost")
|
LDAPAuth().authenticate_credentials(credentials="Yunohost")
|
||||||
|
|
||||||
|
@ -45,7 +42,6 @@ def test_authenticate_with_no_user():
|
||||||
|
|
||||||
|
|
||||||
def test_authenticate_with_user_who_is_not_admin():
|
def test_authenticate_with_user_who_is_not_admin():
|
||||||
|
|
||||||
with pytest.raises(MoulinetteError) as exception:
|
with pytest.raises(MoulinetteError) as exception:
|
||||||
LDAPAuth().authenticate_credentials(credentials="bob:test123Ynh")
|
LDAPAuth().authenticate_credentials(credentials="bob:test123Ynh")
|
||||||
|
|
||||||
|
@ -70,7 +66,6 @@ def test_authenticate_server_down(mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_authenticate_change_password():
|
def test_authenticate_change_password():
|
||||||
|
|
||||||
LDAPAuth().authenticate_credentials(credentials="alice:Yunohost")
|
LDAPAuth().authenticate_credentials(credentials="alice:Yunohost")
|
||||||
|
|
||||||
user_update("alice", change_password="plopette")
|
user_update("alice", change_password="plopette")
|
||||||
|
|
|
@ -354,7 +354,6 @@ def check_permission_for_apps():
|
||||||
|
|
||||||
|
|
||||||
def can_access_webpage(webpath, logged_as=None):
|
def can_access_webpage(webpath, logged_as=None):
|
||||||
|
|
||||||
webpath = webpath.rstrip("/")
|
webpath = webpath.rstrip("/")
|
||||||
sso_url = "https://" + maindomain + "/yunohost/sso/"
|
sso_url = "https://" + maindomain + "/yunohost/sso/"
|
||||||
|
|
||||||
|
@ -1094,7 +1093,6 @@ def test_permission_protection_management_by_helper():
|
||||||
|
|
||||||
@pytest.mark.other_domains(number=1)
|
@pytest.mark.other_domains(number=1)
|
||||||
def test_permission_app_propagation_on_ssowat():
|
def test_permission_app_propagation_on_ssowat():
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
|
os.path.join(get_test_apps_dir(), "permissions_app_ynh"),
|
||||||
args="domain=%s&domain_2=%s&path=%s&is_public=1&admin=%s"
|
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)
|
@pytest.mark.other_domains(number=1)
|
||||||
def test_permission_legacy_app_propagation_on_ssowat():
|
def test_permission_legacy_app_propagation_on_ssowat():
|
||||||
|
|
||||||
app_install(
|
app_install(
|
||||||
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
|
os.path.join(get_test_apps_dir(), "legacy_app_ynh"),
|
||||||
args="domain=%s&domain_2=%s&path=%s&is_public=1"
|
args="domain=%s&domain_2=%s&path=%s&is_public=1"
|
||||||
|
|
|
@ -49,7 +49,6 @@ def test_question_empty():
|
||||||
|
|
||||||
|
|
||||||
def test_question_string():
|
def test_question_string():
|
||||||
|
|
||||||
questions = {
|
questions = {
|
||||||
"some_string": {
|
"some_string": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -65,7 +64,6 @@ def test_question_string():
|
||||||
|
|
||||||
|
|
||||||
def test_question_string_from_query_string():
|
def test_question_string_from_query_string():
|
||||||
|
|
||||||
questions = {
|
questions = {
|
||||||
"some_string": {
|
"some_string": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -1539,7 +1537,6 @@ def test_question_user_two_users_default_input():
|
||||||
os, "isatty", return_value=True
|
os, "isatty", return_value=True
|
||||||
):
|
):
|
||||||
with patch.object(user, "user_info", return_value={}):
|
with patch.object(user, "user_info", return_value={}):
|
||||||
|
|
||||||
with patch.object(Moulinette, "prompt", return_value=username):
|
with patch.object(Moulinette, "prompt", return_value=username):
|
||||||
out = ask_questions_and_parse_answers(questions, answers)[0]
|
out = ask_questions_and_parse_answers(questions, answers)[0]
|
||||||
|
|
||||||
|
@ -1843,7 +1840,6 @@ def test_question_display_text():
|
||||||
|
|
||||||
|
|
||||||
def test_question_file_from_cli():
|
def test_question_file_from_cli():
|
||||||
|
|
||||||
FileQuestion.clean_upload_dirs()
|
FileQuestion.clean_upload_dirs()
|
||||||
|
|
||||||
filename = "/tmp/ynh_test_question_file"
|
filename = "/tmp/ynh_test_question_file"
|
||||||
|
@ -1874,7 +1870,6 @@ def test_question_file_from_cli():
|
||||||
|
|
||||||
|
|
||||||
def test_question_file_from_api():
|
def test_question_file_from_api():
|
||||||
|
|
||||||
FileQuestion.clean_upload_dirs()
|
FileQuestion.clean_upload_dirs()
|
||||||
|
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
|
@ -1907,7 +1902,6 @@ def test_question_file_from_api():
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_nominal():
|
def test_normalize_boolean_nominal():
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("yes") == 1
|
assert BooleanQuestion.normalize("yes") == 1
|
||||||
assert BooleanQuestion.normalize("Yes") == 1
|
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():
|
def test_normalize_boolean_humanize():
|
||||||
|
|
||||||
assert BooleanQuestion.humanize("yes") == "yes"
|
assert BooleanQuestion.humanize("yes") == "yes"
|
||||||
assert BooleanQuestion.humanize("true") == "yes"
|
assert BooleanQuestion.humanize("true") == "yes"
|
||||||
assert BooleanQuestion.humanize("on") == "yes"
|
assert BooleanQuestion.humanize("on") == "yes"
|
||||||
|
@ -1948,7 +1941,6 @@ def test_normalize_boolean_humanize():
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_invalid():
|
def test_normalize_boolean_invalid():
|
||||||
|
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
BooleanQuestion.normalize("yesno")
|
BooleanQuestion.normalize("yesno")
|
||||||
with pytest.raises(YunohostValidationError):
|
with pytest.raises(YunohostValidationError):
|
||||||
|
@ -1958,7 +1950,6 @@ def test_normalize_boolean_invalid():
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_boolean_special_yesno():
|
def test_normalize_boolean_special_yesno():
|
||||||
|
|
||||||
customyesno = {"yes": "enabled", "no": "disabled"}
|
customyesno = {"yes": "enabled", "no": "disabled"}
|
||||||
|
|
||||||
assert BooleanQuestion.normalize("yes", customyesno) == "enabled"
|
assert BooleanQuestion.normalize("yes", customyesno) == "enabled"
|
||||||
|
@ -1977,14 +1968,12 @@ def test_normalize_boolean_special_yesno():
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_domain():
|
def test_normalize_domain():
|
||||||
|
|
||||||
assert DomainQuestion.normalize("https://yolo.swag/") == "yolo.swag"
|
assert DomainQuestion.normalize("https://yolo.swag/") == "yolo.swag"
|
||||||
assert DomainQuestion.normalize("http://yolo.swag") == "yolo.swag"
|
assert DomainQuestion.normalize("http://yolo.swag") == "yolo.swag"
|
||||||
assert DomainQuestion.normalize("yolo.swag/") == "yolo.swag"
|
assert DomainQuestion.normalize("yolo.swag/") == "yolo.swag"
|
||||||
|
|
||||||
|
|
||||||
def test_normalize_path():
|
def test_normalize_path():
|
||||||
|
|
||||||
assert PathQuestion.normalize("") == "/"
|
assert PathQuestion.normalize("") == "/"
|
||||||
assert PathQuestion.normalize("") == "/"
|
assert PathQuestion.normalize("") == "/"
|
||||||
assert PathQuestion.normalize("macnuggets") == "/macnuggets"
|
assert PathQuestion.normalize("macnuggets") == "/macnuggets"
|
||||||
|
|
|
@ -16,19 +16,16 @@ SSHD_CONFIG = "/etc/ssh/sshd_config"
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
|
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
|
_force_clear_hashes([TEST_DOMAIN_NGINX_CONFIG])
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
assert os.system("pgrep slapd >/dev/null") == 0
|
assert os.system("pgrep slapd >/dev/null") == 0
|
||||||
assert os.system("pgrep nginx >/dev/null") == 0
|
assert os.system("pgrep nginx >/dev/null") == 0
|
||||||
|
|
||||||
|
@ -48,7 +45,6 @@ def clean():
|
||||||
|
|
||||||
|
|
||||||
def test_add_domain():
|
def test_add_domain():
|
||||||
|
|
||||||
domain_add(TEST_DOMAIN)
|
domain_add(TEST_DOMAIN)
|
||||||
|
|
||||||
assert TEST_DOMAIN in domain_list()["domains"]
|
assert TEST_DOMAIN in domain_list()["domains"]
|
||||||
|
@ -60,7 +56,6 @@ def test_add_domain():
|
||||||
|
|
||||||
|
|
||||||
def test_add_and_edit_domain_conf():
|
def test_add_and_edit_domain_conf():
|
||||||
|
|
||||||
domain_add(TEST_DOMAIN)
|
domain_add(TEST_DOMAIN)
|
||||||
|
|
||||||
assert os.path.exists(TEST_DOMAIN_NGINX_CONFIG)
|
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():
|
def test_add_domain_conf_already_exists():
|
||||||
|
|
||||||
os.system("echo ' ' >> %s" % TEST_DOMAIN_NGINX_CONFIG)
|
os.system("echo ' ' >> %s" % TEST_DOMAIN_NGINX_CONFIG)
|
||||||
|
|
||||||
domain_add(TEST_DOMAIN)
|
domain_add(TEST_DOMAIN)
|
||||||
|
@ -84,7 +78,6 @@ def test_add_domain_conf_already_exists():
|
||||||
|
|
||||||
|
|
||||||
def test_ssh_conf_unmanaged():
|
def test_ssh_conf_unmanaged():
|
||||||
|
|
||||||
_force_clear_hashes([SSHD_CONFIG])
|
_force_clear_hashes([SSHD_CONFIG])
|
||||||
|
|
||||||
assert SSHD_CONFIG not in _get_conf_hashes("ssh")
|
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):
|
def test_ssh_conf_unmanaged_and_manually_modified(mocker):
|
||||||
|
|
||||||
_force_clear_hashes([SSHD_CONFIG])
|
_force_clear_hashes([SSHD_CONFIG])
|
||||||
os.system("echo ' ' >> %s" % SSHD_CONFIG)
|
os.system("echo ' ' >> %s" % SSHD_CONFIG)
|
||||||
|
|
||||||
|
|
|
@ -14,17 +14,14 @@ from yunohost.service import (
|
||||||
|
|
||||||
|
|
||||||
def setup_function(function):
|
def setup_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
||||||
clean()
|
clean()
|
||||||
|
|
||||||
|
|
||||||
def clean():
|
def clean():
|
||||||
|
|
||||||
# To run these tests, we assume ssh(d) service exists and is running
|
# To run these tests, we assume ssh(d) service exists and is running
|
||||||
assert os.system("pgrep sshd >/dev/null") == 0
|
assert os.system("pgrep sshd >/dev/null") == 0
|
||||||
|
|
||||||
|
@ -45,46 +42,39 @@ def clean():
|
||||||
|
|
||||||
|
|
||||||
def test_service_status_all():
|
def test_service_status_all():
|
||||||
|
|
||||||
status = service_status()
|
status = service_status()
|
||||||
assert "ssh" in status.keys()
|
assert "ssh" in status.keys()
|
||||||
assert status["ssh"]["status"] == "running"
|
assert status["ssh"]["status"] == "running"
|
||||||
|
|
||||||
|
|
||||||
def test_service_status_single():
|
def test_service_status_single():
|
||||||
|
|
||||||
status = service_status("ssh")
|
status = service_status("ssh")
|
||||||
assert "status" in status.keys()
|
assert "status" in status.keys()
|
||||||
assert status["status"] == "running"
|
assert status["status"] == "running"
|
||||||
|
|
||||||
|
|
||||||
def test_service_log():
|
def test_service_log():
|
||||||
|
|
||||||
logs = service_log("ssh")
|
logs = service_log("ssh")
|
||||||
assert "journalctl" in logs.keys()
|
assert "journalctl" in logs.keys()
|
||||||
assert "/var/log/auth.log" in logs.keys()
|
assert "/var/log/auth.log" in logs.keys()
|
||||||
|
|
||||||
|
|
||||||
def test_service_status_unknown_service(mocker):
|
def test_service_status_unknown_service(mocker):
|
||||||
|
|
||||||
with raiseYunohostError(mocker, "service_unknown"):
|
with raiseYunohostError(mocker, "service_unknown"):
|
||||||
service_status(["ssh", "doesnotexists"])
|
service_status(["ssh", "doesnotexists"])
|
||||||
|
|
||||||
|
|
||||||
def test_service_add():
|
def test_service_add():
|
||||||
|
|
||||||
service_add("dummyservice", description="A dummy service to run tests")
|
service_add("dummyservice", description="A dummy service to run tests")
|
||||||
assert "dummyservice" in service_status().keys()
|
assert "dummyservice" in service_status().keys()
|
||||||
|
|
||||||
|
|
||||||
def test_service_add_real_service():
|
def test_service_add_real_service():
|
||||||
|
|
||||||
service_add("networking")
|
service_add("networking")
|
||||||
assert "networking" in service_status().keys()
|
assert "networking" in service_status().keys()
|
||||||
|
|
||||||
|
|
||||||
def test_service_remove():
|
def test_service_remove():
|
||||||
|
|
||||||
service_add("dummyservice", description="A dummy service to run tests")
|
service_add("dummyservice", description="A dummy service to run tests")
|
||||||
assert "dummyservice" in service_status().keys()
|
assert "dummyservice" in service_status().keys()
|
||||||
service_remove("dummyservice")
|
service_remove("dummyservice")
|
||||||
|
@ -92,7 +82,6 @@ def test_service_remove():
|
||||||
|
|
||||||
|
|
||||||
def test_service_remove_service_that_doesnt_exists(mocker):
|
def test_service_remove_service_that_doesnt_exists(mocker):
|
||||||
|
|
||||||
assert "dummyservice" not in service_status().keys()
|
assert "dummyservice" not in service_status().keys()
|
||||||
|
|
||||||
with raiseYunohostError(mocker, "service_unknown"):
|
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():
|
def test_service_update_to_add_properties():
|
||||||
|
|
||||||
service_add("dummyservice", description="dummy")
|
service_add("dummyservice", description="dummy")
|
||||||
assert not _get_services()["dummyservice"].get("test_status")
|
assert not _get_services()["dummyservice"].get("test_status")
|
||||||
service_add("dummyservice", description="dummy", test_status="true")
|
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():
|
def test_service_update_to_change_properties():
|
||||||
|
|
||||||
service_add("dummyservice", description="dummy", test_status="false")
|
service_add("dummyservice", description="dummy", test_status="false")
|
||||||
assert _get_services()["dummyservice"].get("test_status") == "false"
|
assert _get_services()["dummyservice"].get("test_status") == "false"
|
||||||
service_add("dummyservice", description="dummy", test_status="true")
|
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():
|
def test_service_update_to_remove_properties():
|
||||||
|
|
||||||
service_add("dummyservice", description="dummy", test_status="false")
|
service_add("dummyservice", description="dummy", test_status="false")
|
||||||
assert _get_services()["dummyservice"].get("test_status") == "false"
|
assert _get_services()["dummyservice"].get("test_status") == "false"
|
||||||
service_add("dummyservice", description="dummy", test_status="")
|
service_add("dummyservice", description="dummy", test_status="")
|
||||||
|
@ -126,7 +112,6 @@ def test_service_update_to_remove_properties():
|
||||||
|
|
||||||
|
|
||||||
def test_service_conf_broken():
|
def test_service_conf_broken():
|
||||||
|
|
||||||
os.system("echo pwet > /etc/nginx/conf.d/broken.conf")
|
os.system("echo pwet > /etc/nginx/conf.d/broken.conf")
|
||||||
|
|
||||||
status = service_status("nginx")
|
status = service_status("nginx")
|
||||||
|
|
|
@ -65,7 +65,6 @@ old_translate = moulinette.core.Translator.translate
|
||||||
|
|
||||||
|
|
||||||
def _monkeypatch_translator(self, key, *args, **kwargs):
|
def _monkeypatch_translator(self, key, *args, **kwargs):
|
||||||
|
|
||||||
if key.startswith("global_settings_setting_"):
|
if key.startswith("global_settings_setting_"):
|
||||||
return f"Dummy translation for {key}"
|
return f"Dummy translation for {key}"
|
||||||
|
|
||||||
|
@ -175,7 +174,6 @@ def test_settings_set_doesexit():
|
||||||
|
|
||||||
|
|
||||||
def test_settings_set_bad_type_bool():
|
def test_settings_set_bad_type_bool():
|
||||||
|
|
||||||
with patch.object(os, "isatty", return_value=False):
|
with patch.object(os, "isatty", return_value=False):
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
settings_set("example.example.boolean", 42)
|
settings_set("example.example.boolean", 42)
|
||||||
|
|
|
@ -92,7 +92,6 @@ def test_list_groups():
|
||||||
|
|
||||||
|
|
||||||
def test_create_user(mocker):
|
def test_create_user(mocker):
|
||||||
|
|
||||||
with message(mocker, "user_created"):
|
with message(mocker, "user_created"):
|
||||||
user_create("albert", maindomain, "test123Ynh", fullname="Albert Good")
|
user_create("albert", maindomain, "test123Ynh", fullname="Albert Good")
|
||||||
|
|
||||||
|
@ -104,7 +103,6 @@ def test_create_user(mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_del_user(mocker):
|
def test_del_user(mocker):
|
||||||
|
|
||||||
with message(mocker, "user_deleted"):
|
with message(mocker, "user_deleted"):
|
||||||
user_delete("alice")
|
user_delete("alice")
|
||||||
|
|
||||||
|
@ -185,7 +183,6 @@ def test_export_user(mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_create_group(mocker):
|
def test_create_group(mocker):
|
||||||
|
|
||||||
with message(mocker, "group_created", group="adminsys"):
|
with message(mocker, "group_created", group="adminsys"):
|
||||||
user_group_create("adminsys")
|
user_group_create("adminsys")
|
||||||
|
|
||||||
|
@ -196,7 +193,6 @@ def test_create_group(mocker):
|
||||||
|
|
||||||
|
|
||||||
def test_del_group(mocker):
|
def test_del_group(mocker):
|
||||||
|
|
||||||
with message(mocker, "group_deleted", group="dev"):
|
with message(mocker, "group_deleted", group="dev"):
|
||||||
user_group_delete("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):
|
def tools_rootpw(new_password, check_strength=True):
|
||||||
|
|
||||||
from yunohost.user import _hash_user_password
|
from yunohost.user import _hash_user_password
|
||||||
from yunohost.utils.password import (
|
from yunohost.utils.password import (
|
||||||
assert_password_is_strong_enough,
|
assert_password_is_strong_enough,
|
||||||
|
@ -154,7 +153,6 @@ def tools_postinstall(
|
||||||
ignore_dyndns=False,
|
ignore_dyndns=False,
|
||||||
force_diskspace=False,
|
force_diskspace=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
from yunohost.dyndns import _dyndns_available
|
from yunohost.dyndns import _dyndns_available
|
||||||
from yunohost.utils.dns import is_yunohost_dyndns_domain
|
from yunohost.utils.dns import is_yunohost_dyndns_domain
|
||||||
from yunohost.utils.password import (
|
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 this is a nohost.me/noho.st, actually check for availability
|
||||||
if not ignore_dyndns and is_yunohost_dyndns_domain(domain):
|
if not ignore_dyndns and is_yunohost_dyndns_domain(domain):
|
||||||
|
|
||||||
available = None
|
available = None
|
||||||
|
|
||||||
# Check if the domain is available...
|
# Check if the domain is available...
|
||||||
|
@ -281,7 +278,6 @@ def tools_postinstall(
|
||||||
def tools_regen_conf(
|
def tools_regen_conf(
|
||||||
names=[], with_diff=False, force=False, dry_run=False, list_pending=False
|
names=[], with_diff=False, force=False, dry_run=False, list_pending=False
|
||||||
):
|
):
|
||||||
|
|
||||||
# Make sure the settings are migrated before running the migration,
|
# Make sure the settings are migrated before running the migration,
|
||||||
# which may otherwise fuck things up such as the ssh config ...
|
# 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
|
# 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 = []
|
upgradable_system_packages = []
|
||||||
if target in ["system", "all"]:
|
if target in ["system", "all"]:
|
||||||
|
|
||||||
# Update APT cache
|
# Update APT cache
|
||||||
# LC_ALL=C is here to make sure the results are in english
|
# LC_ALL=C is here to make sure the results are in english
|
||||||
command = (
|
command = (
|
||||||
|
@ -426,7 +421,6 @@ def tools_upgrade(operation_logger, target=None):
|
||||||
#
|
#
|
||||||
|
|
||||||
if target == "apps":
|
if target == "apps":
|
||||||
|
|
||||||
# Make sure there's actually something to upgrade
|
# Make sure there's actually something to upgrade
|
||||||
|
|
||||||
upgradable_apps = [app["id"] for app in app_list(upgradable=True)["apps"]]
|
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":
|
if target == "system":
|
||||||
|
|
||||||
# Check that there's indeed some packages to upgrade
|
# Check that there's indeed some packages to upgrade
|
||||||
upgradables = list(_list_upgradable_apt_packages())
|
upgradables = list(_list_upgradable_apt_packages())
|
||||||
if not upgradables:
|
if not upgradables:
|
||||||
|
@ -498,7 +491,6 @@ def tools_upgrade(operation_logger, target=None):
|
||||||
any(p["name"] == "yunohost" for p in upgradables)
|
any(p["name"] == "yunohost" for p in upgradables)
|
||||||
and Moulinette.interface.type == "api"
|
and Moulinette.interface.type == "api"
|
||||||
):
|
):
|
||||||
|
|
||||||
# Restart the API after 10 sec (at now doesn't support sub-minute times...)
|
# 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
|
# 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
|
# 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
|
# Actually run selected migrations
|
||||||
for migration in targets:
|
for migration in targets:
|
||||||
|
|
||||||
# If we are migrating in "automatic mode" (i.e. from debian configure
|
# If we are migrating in "automatic mode" (i.e. from debian configure
|
||||||
# during an upgrade of the package) but we are asked for running
|
# 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
|
# 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")
|
_write_migration_state(migration.id, "skipped")
|
||||||
operation_logger.success()
|
operation_logger.success()
|
||||||
else:
|
else:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
migration.operation_logger = operation_logger
|
migration.operation_logger = operation_logger
|
||||||
logger.info(m18n.n("migrations_running_forward", id=migration.id))
|
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):
|
def _write_migration_state(migration_id, state):
|
||||||
|
|
||||||
current_states = tools_migrations_state()
|
current_states = tools_migrations_state()
|
||||||
current_states["migrations"][migration_id] = state
|
current_states["migrations"][migration_id] = state
|
||||||
write_to_yaml(MIGRATIONS_STATE_PATH, current_states)
|
write_to_yaml(MIGRATIONS_STATE_PATH, current_states)
|
||||||
|
|
||||||
|
|
||||||
def _get_migrations_list():
|
def _get_migrations_list():
|
||||||
|
|
||||||
# states is a datastructure that represents the last run migration
|
# states is a datastructure that represents the last run migration
|
||||||
# it has this form:
|
# it has this form:
|
||||||
# {
|
# {
|
||||||
|
@ -868,7 +856,6 @@ def _get_migration_by_name(migration_name):
|
||||||
|
|
||||||
|
|
||||||
def _load_migration(migration_file):
|
def _load_migration(migration_file):
|
||||||
|
|
||||||
migration_id = migration_file[: -len(".py")]
|
migration_id = migration_file[: -len(".py")]
|
||||||
|
|
||||||
logger.debug(m18n.n("migrations_loading_migration", id=migration_id))
|
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):
|
def _tools_migrations_run_after_system_restore(backup_version):
|
||||||
|
|
||||||
all_migrations = _get_migrations_list()
|
all_migrations = _get_migrations_list()
|
||||||
|
|
||||||
current_version = version.parse(ynh_packages_version()["yunohost"]["version"])
|
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):
|
def _tools_migrations_run_before_app_restore(backup_version, app_id):
|
||||||
|
|
||||||
all_migrations = _get_migrations_list()
|
all_migrations = _get_migrations_list()
|
||||||
|
|
||||||
current_version = version.parse(ynh_packages_version()["yunohost"]["version"])
|
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:
|
class Migration:
|
||||||
|
|
||||||
# Those are to be implemented by daughter classes
|
# Those are to be implemented by daughter classes
|
||||||
|
|
||||||
mode = "auto"
|
mode = "auto"
|
||||||
|
@ -985,7 +969,6 @@ class Migration:
|
||||||
|
|
||||||
def ldap_migration(run):
|
def ldap_migration(run):
|
||||||
def func(self):
|
def func(self):
|
||||||
|
|
||||||
# Backup LDAP before the migration
|
# Backup LDAP before the migration
|
||||||
logger.info(m18n.n("migration_ldap_backup_before_migration"))
|
logger.info(m18n.n("migration_ldap_backup_before_migration"))
|
||||||
try:
|
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):
|
def user_list(fields=None):
|
||||||
|
|
||||||
from yunohost.utils.ldap import _get_ldap_interface
|
from yunohost.utils.ldap import _get_ldap_interface
|
||||||
|
|
||||||
ldap_attrs = {
|
ldap_attrs = {
|
||||||
|
@ -149,7 +148,6 @@ def user_create(
|
||||||
from_import=False,
|
from_import=False,
|
||||||
loginShell=None,
|
loginShell=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
if firstname or lastname:
|
if firstname or lastname:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
|
"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")])
|
@is_unit_operation([("username", "user")])
|
||||||
def user_delete(operation_logger, username, purge=False, from_import=False):
|
def user_delete(operation_logger, username, purge=False, from_import=False):
|
||||||
|
|
||||||
from yunohost.hook import hook_callback
|
from yunohost.hook import hook_callback
|
||||||
from yunohost.utils.ldap import _get_ldap_interface
|
from yunohost.utils.ldap import _get_ldap_interface
|
||||||
|
|
||||||
|
@ -380,7 +377,6 @@ def user_update(
|
||||||
fullname=None,
|
fullname=None,
|
||||||
loginShell=None,
|
loginShell=None,
|
||||||
):
|
):
|
||||||
|
|
||||||
if firstname or lastname:
|
if firstname or lastname:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Options --firstname / --lastname of 'yunohost user create' are deprecated. We recommend using --fullname instead."
|
"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:
|
for user in reader:
|
||||||
|
|
||||||
# Validate column values against regexes
|
# Validate column values against regexes
|
||||||
format_errors = [
|
format_errors = [
|
||||||
f"{key}: '{user[key]}' doesn't match the expected format"
|
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"]
|
users = user_list()["users"]
|
||||||
groups = {}
|
groups = {}
|
||||||
for infos in groups_infos:
|
for infos in groups_infos:
|
||||||
|
|
||||||
name = infos["cn"][0]
|
name = infos["cn"][0]
|
||||||
|
|
||||||
if not include_primary_groups and name in users:
|
if not include_primary_groups and name in users:
|
||||||
|
@ -1141,7 +1135,6 @@ def user_group_update(
|
||||||
sync_perm=True,
|
sync_perm=True,
|
||||||
from_import=False,
|
from_import=False,
|
||||||
):
|
):
|
||||||
|
|
||||||
from yunohost.permission import permission_sync_to_user
|
from yunohost.permission import permission_sync_to_user
|
||||||
from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract
|
from yunohost.utils.ldap import _get_ldap_interface, _ldap_path_extract
|
||||||
|
|
||||||
|
@ -1184,7 +1177,6 @@ def user_group_update(
|
||||||
new_attr_dict = {}
|
new_attr_dict = {}
|
||||||
|
|
||||||
if add:
|
if add:
|
||||||
|
|
||||||
users_to_add = [add] if not isinstance(add, list) else add
|
users_to_add = [add] if not isinstance(add, list) else add
|
||||||
|
|
||||||
for user in users_to_add:
|
for user in users_to_add:
|
||||||
|
@ -1225,7 +1217,6 @@ def user_group_update(
|
||||||
|
|
||||||
# Check the whole alias situation
|
# Check the whole alias situation
|
||||||
if add_mailalias:
|
if add_mailalias:
|
||||||
|
|
||||||
from yunohost.domain import domain_list
|
from yunohost.domain import domain_list
|
||||||
|
|
||||||
domains = domain_list()["domains"]
|
domains = domain_list()["domains"]
|
||||||
|
@ -1269,7 +1260,6 @@ def user_group_update(
|
||||||
raise YunohostValidationError("mail_alias_remove_failed", mail=mail)
|
raise YunohostValidationError("mail_alias_remove_failed", mail=mail)
|
||||||
|
|
||||||
if set(new_group_mail) != set(current_group_mail):
|
if set(new_group_mail) != set(current_group_mail):
|
||||||
|
|
||||||
logger.info(m18n.n("group_update_aliases", group=groupname))
|
logger.info(m18n.n("group_update_aliases", group=groupname))
|
||||||
new_attr_dict["mail"] = set(new_group_mail)
|
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):
|
def _update_admins_group_aliases(old_main_domain, new_main_domain):
|
||||||
|
|
||||||
current_admin_aliases = user_group_info("admins")["mail-aliases"]
|
current_admin_aliases = user_group_info("admins")["mail-aliases"]
|
||||||
|
|
||||||
aliases_to_remove = [
|
aliases_to_remove = [
|
||||||
|
|
|
@ -264,7 +264,6 @@ class ConfigPanel:
|
||||||
|
|
||||||
# In 'classic' mode, we display the current value if key refer to an option
|
# In 'classic' mode, we display the current value if key refer to an option
|
||||||
if self.filter_key.count(".") == 2 and mode == "classic":
|
if self.filter_key.count(".") == 2 and mode == "classic":
|
||||||
|
|
||||||
option = self.filter_key.split(".")[-1]
|
option = self.filter_key.split(".")[-1]
|
||||||
value = self.values.get(option, None)
|
value = self.values.get(option, None)
|
||||||
|
|
||||||
|
@ -280,7 +279,6 @@ class ConfigPanel:
|
||||||
logger.debug(f"Formating result in '{mode}' mode")
|
logger.debug(f"Formating result in '{mode}' mode")
|
||||||
result = {}
|
result = {}
|
||||||
for panel, section, option in self._iterate():
|
for panel, section, option in self._iterate():
|
||||||
|
|
||||||
if section["is_action_section"] and mode != "full":
|
if section["is_action_section"] and mode != "full":
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
@ -323,7 +321,6 @@ class ConfigPanel:
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def list_actions(self):
|
def list_actions(self):
|
||||||
|
|
||||||
actions = {}
|
actions = {}
|
||||||
|
|
||||||
# FIXME : meh, loading the entire config panel is again going to cause
|
# FIXME : meh, loading the entire config panel is again going to cause
|
||||||
|
@ -462,7 +459,6 @@ class ConfigPanel:
|
||||||
return read_toml(self.config_path)
|
return read_toml(self.config_path)
|
||||||
|
|
||||||
def _get_config_panel(self):
|
def _get_config_panel(self):
|
||||||
|
|
||||||
# Split filter_key
|
# Split filter_key
|
||||||
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
|
filter_key = self.filter_key.split(".") if self.filter_key != "" else []
|
||||||
if len(filter_key) > 3:
|
if len(filter_key) > 3:
|
||||||
|
@ -639,7 +635,6 @@ class ConfigPanel:
|
||||||
# Hydrating config panel with current value
|
# Hydrating config panel with current value
|
||||||
for _, section, option in self._iterate():
|
for _, section, option in self._iterate():
|
||||||
if option["id"] not in self.values:
|
if option["id"] not in self.values:
|
||||||
|
|
||||||
allowed_empty_types = [
|
allowed_empty_types = [
|
||||||
"alert",
|
"alert",
|
||||||
"display_text",
|
"display_text",
|
||||||
|
@ -701,7 +696,6 @@ class ConfigPanel:
|
||||||
Moulinette.display(colorize(message, "purple"))
|
Moulinette.display(colorize(message, "purple"))
|
||||||
|
|
||||||
for panel, section, obj in self._iterate(["panel", "section"]):
|
for panel, section, obj in self._iterate(["panel", "section"]):
|
||||||
|
|
||||||
if (
|
if (
|
||||||
section
|
section
|
||||||
and section.get("visible")
|
and section.get("visible")
|
||||||
|
@ -814,7 +808,6 @@ class ConfigPanel:
|
||||||
write_to_yaml(self.save_path, values_to_save)
|
write_to_yaml(self.save_path, values_to_save)
|
||||||
|
|
||||||
def _reload_services(self):
|
def _reload_services(self):
|
||||||
|
|
||||||
from yunohost.service import service_reload_or_restart
|
from yunohost.service import service_reload_or_restart
|
||||||
|
|
||||||
services_to_reload = set()
|
services_to_reload = set()
|
||||||
|
@ -905,7 +898,6 @@ class Question:
|
||||||
)
|
)
|
||||||
|
|
||||||
def ask_if_needed(self):
|
def ask_if_needed(self):
|
||||||
|
|
||||||
if self.visible and not evaluate_simple_js_expression(
|
if self.visible and not evaluate_simple_js_expression(
|
||||||
self.visible, context=self.context
|
self.visible, context=self.context
|
||||||
):
|
):
|
||||||
|
@ -980,7 +972,6 @@ class Question:
|
||||||
)
|
)
|
||||||
|
|
||||||
def _format_text_for_user_input_in_cli(self):
|
def _format_text_for_user_input_in_cli(self):
|
||||||
|
|
||||||
text_for_user_input_in_cli = _value_for_locale(self.ask)
|
text_for_user_input_in_cli = _value_for_locale(self.ask)
|
||||||
|
|
||||||
if self.readonly:
|
if self.readonly:
|
||||||
|
@ -991,7 +982,6 @@ class Question:
|
||||||
)
|
)
|
||||||
return text_for_user_input_in_cli + f" {self.humanize(self.current_value)}"
|
return text_for_user_input_in_cli + f" {self.humanize(self.current_value)}"
|
||||||
elif self.choices:
|
elif self.choices:
|
||||||
|
|
||||||
# Prevent displaying a shitload of choices
|
# Prevent displaying a shitload of choices
|
||||||
# (e.g. 100+ available users when choosing an app admin...)
|
# (e.g. 100+ available users when choosing an app admin...)
|
||||||
choices = (
|
choices = (
|
||||||
|
@ -1160,7 +1150,6 @@ class PathQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize(value, option={}):
|
def normalize(value, option={}):
|
||||||
|
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, Question) else option
|
||||||
|
|
||||||
if not value.strip():
|
if not value.strip():
|
||||||
|
@ -1187,7 +1176,6 @@ class BooleanQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def humanize(value, option={}):
|
def humanize(value, option={}):
|
||||||
|
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, Question) else option
|
||||||
|
|
||||||
yes = option.get("yes", 1)
|
yes = option.get("yes", 1)
|
||||||
|
@ -1211,7 +1199,6 @@ class BooleanQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize(value, option={}):
|
def normalize(value, option={}):
|
||||||
|
|
||||||
option = option.__dict__ if isinstance(option, Question) else option
|
option = option.__dict__ if isinstance(option, Question) else option
|
||||||
|
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
|
@ -1368,7 +1355,6 @@ class GroupQuestion(Question):
|
||||||
def __init__(
|
def __init__(
|
||||||
self, question, context: Mapping[str, Any] = {}, hooks: Dict[str, Callable] = {}
|
self, question, context: Mapping[str, Any] = {}, hooks: Dict[str, Callable] = {}
|
||||||
):
|
):
|
||||||
|
|
||||||
from yunohost.user import user_group_list
|
from yunohost.user import user_group_list
|
||||||
|
|
||||||
super().__init__(question, context)
|
super().__init__(question, context)
|
||||||
|
@ -1401,7 +1387,6 @@ class NumberQuestion(Question):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def normalize(value, option={}):
|
def normalize(value, option={}):
|
||||||
|
|
||||||
if isinstance(value, int):
|
if isinstance(value, int):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
|
@ -31,19 +31,16 @@ external_resolvers_: List[str] = []
|
||||||
|
|
||||||
|
|
||||||
def is_yunohost_dyndns_domain(domain):
|
def is_yunohost_dyndns_domain(domain):
|
||||||
|
|
||||||
return any(
|
return any(
|
||||||
domain.endswith(f".{dyndns_domain}") for dyndns_domain in YNH_DYNDNS_DOMAINS
|
domain.endswith(f".{dyndns_domain}") for dyndns_domain in YNH_DYNDNS_DOMAINS
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_special_use_tld(domain):
|
def is_special_use_tld(domain):
|
||||||
|
|
||||||
return any(domain.endswith(f".{tld}") for tld in SPECIAL_USE_TLDS)
|
return any(domain.endswith(f".{tld}") for tld in SPECIAL_USE_TLDS)
|
||||||
|
|
||||||
|
|
||||||
def external_resolvers():
|
def external_resolvers():
|
||||||
|
|
||||||
global external_resolvers_
|
global external_resolvers_
|
||||||
|
|
||||||
if not external_resolvers_:
|
if not external_resolvers_:
|
||||||
|
|
|
@ -21,7 +21,6 @@ from moulinette import m18n
|
||||||
|
|
||||||
|
|
||||||
class YunohostError(MoulinetteError):
|
class YunohostError(MoulinetteError):
|
||||||
|
|
||||||
http_code = 500
|
http_code = 500
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -43,7 +42,6 @@ class YunohostError(MoulinetteError):
|
||||||
super(YunohostError, self).__init__(msg, raw_msg=True)
|
super(YunohostError, self).__init__(msg, raw_msg=True)
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
|
|
||||||
if not self.log_ref:
|
if not self.log_ref:
|
||||||
return super().content()
|
return super().content()
|
||||||
else:
|
else:
|
||||||
|
@ -51,14 +49,11 @@ class YunohostError(MoulinetteError):
|
||||||
|
|
||||||
|
|
||||||
class YunohostValidationError(YunohostError):
|
class YunohostValidationError(YunohostError):
|
||||||
|
|
||||||
http_code = 400
|
http_code = 400
|
||||||
|
|
||||||
def content(self):
|
def content(self):
|
||||||
|
|
||||||
return {"error": self.strerror, "error_key": self.key, **self.kwargs}
|
return {"error": self.strerror, "error_key": self.key, **self.kwargs}
|
||||||
|
|
||||||
|
|
||||||
class YunohostAuthenticationError(MoulinetteAuthenticationError):
|
class YunohostAuthenticationError(MoulinetteAuthenticationError):
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -36,7 +36,6 @@ _ldap_interface = None
|
||||||
|
|
||||||
|
|
||||||
def _get_ldap_interface():
|
def _get_ldap_interface():
|
||||||
|
|
||||||
global _ldap_interface
|
global _ldap_interface
|
||||||
|
|
||||||
if _ldap_interface is None:
|
if _ldap_interface is None:
|
||||||
|
|
|
@ -193,7 +193,6 @@ LEGACY_PHP_VERSION_REPLACEMENTS = [
|
||||||
|
|
||||||
|
|
||||||
def _patch_legacy_php_versions(app_folder):
|
def _patch_legacy_php_versions(app_folder):
|
||||||
|
|
||||||
files_to_patch = []
|
files_to_patch = []
|
||||||
files_to_patch.extend(glob.glob("%s/conf/*" % app_folder))
|
files_to_patch.extend(glob.glob("%s/conf/*" % app_folder))
|
||||||
files_to_patch.extend(glob.glob("%s/scripts/*" % 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)
|
files_to_patch.append("%s/manifest.toml" % app_folder)
|
||||||
|
|
||||||
for filename in files_to_patch:
|
for filename in files_to_patch:
|
||||||
|
|
||||||
# Ignore non-regular files
|
# Ignore non-regular files
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
continue
|
continue
|
||||||
|
@ -217,7 +215,6 @@ def _patch_legacy_php_versions(app_folder):
|
||||||
|
|
||||||
|
|
||||||
def _patch_legacy_php_versions_in_settings(app_folder):
|
def _patch_legacy_php_versions_in_settings(app_folder):
|
||||||
|
|
||||||
settings = read_yaml(os.path.join(app_folder, "settings.yml"))
|
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"]:
|
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):
|
def _patch_legacy_helpers(app_folder):
|
||||||
|
|
||||||
files_to_patch = []
|
files_to_patch = []
|
||||||
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
|
files_to_patch.extend(glob.glob("%s/scripts/*" % app_folder))
|
||||||
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")
|
infos["replace"] = infos.get("replace")
|
||||||
|
|
||||||
for filename in files_to_patch:
|
for filename in files_to_patch:
|
||||||
|
|
||||||
# Ignore non-regular files
|
# Ignore non-regular files
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
continue
|
continue
|
||||||
|
@ -305,7 +300,6 @@ def _patch_legacy_helpers(app_folder):
|
||||||
show_warning = False
|
show_warning = False
|
||||||
|
|
||||||
for helper, infos in stuff_to_replace.items():
|
for helper, infos in stuff_to_replace.items():
|
||||||
|
|
||||||
# Ignore if not relevant for this file
|
# Ignore if not relevant for this file
|
||||||
if infos.get("only_for") and not any(
|
if infos.get("only_for") and not any(
|
||||||
filename.endswith(f) for f in infos["only_for"]
|
filename.endswith(f) for f in infos["only_for"]
|
||||||
|
@ -329,7 +323,6 @@ def _patch_legacy_helpers(app_folder):
|
||||||
)
|
)
|
||||||
|
|
||||||
if replaced_stuff:
|
if replaced_stuff:
|
||||||
|
|
||||||
# Check the app do load the helper
|
# 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 it doesn't, add the instruction ourselve (making sure it's after the #!/bin/bash if it's there...
|
||||||
if filename.split("/")[-1] in [
|
if filename.split("/")[-1] in [
|
||||||
|
|
|
@ -29,7 +29,6 @@ logger = logging.getLogger("yunohost.utils.network")
|
||||||
|
|
||||||
|
|
||||||
def get_public_ip(protocol=4):
|
def get_public_ip(protocol=4):
|
||||||
|
|
||||||
assert protocol in [4, 6], (
|
assert protocol in [4, 6], (
|
||||||
"Invalid protocol version for get_public_ip: %s, expected 4 or 6" % protocol
|
"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():
|
def get_network_interfaces():
|
||||||
|
|
||||||
# Get network devices and their addresses (raw infos from 'ip addr')
|
# Get network devices and their addresses (raw infos from 'ip addr')
|
||||||
devices_raw = {}
|
devices_raw = {}
|
||||||
output = check_output("ip addr show")
|
output = check_output("ip addr show")
|
||||||
|
@ -111,7 +109,6 @@ def get_network_interfaces():
|
||||||
|
|
||||||
|
|
||||||
def get_gateway():
|
def get_gateway():
|
||||||
|
|
||||||
output = check_output("ip route show")
|
output = check_output("ip route show")
|
||||||
m = re.search(r"default via (.*) dev ([a-z]+[0-9]?)", output)
|
m = re.search(r"default via (.*) dev ([a-z]+[0-9]?)", output)
|
||||||
if not m:
|
if not m:
|
||||||
|
|
|
@ -58,7 +58,6 @@ def assert_password_is_compatible(password):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if len(password) >= 127:
|
if len(password) >= 127:
|
||||||
|
|
||||||
# Note that those imports are made here and can't be put
|
# Note that those imports are made here and can't be put
|
||||||
# on top (at least not the moulinette ones)
|
# on top (at least not the moulinette ones)
|
||||||
# because the moulinette needs to be correctly initialized
|
# 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):
|
def assert_password_is_strong_enough(profile, password):
|
||||||
|
|
||||||
PasswordValidator(profile).validate(password)
|
PasswordValidator(profile).validate(password)
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,7 +195,6 @@ class PasswordValidator:
|
||||||
return strength_level
|
return strength_level
|
||||||
|
|
||||||
def is_in_most_used_list(self, password):
|
def is_in_most_used_list(self, password):
|
||||||
|
|
||||||
# Decompress file if compressed
|
# Decompress file if compressed
|
||||||
if os.path.exists("%s.gz" % MOST_USED_PASSWORDS):
|
if os.path.exists("%s.gz" % MOST_USED_PASSWORDS):
|
||||||
os.system("gzip -fd %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:
|
class AppResourceManager:
|
||||||
def __init__(self, app: str, current: Dict, wanted: Dict):
|
def __init__(self, app: str, current: Dict, wanted: Dict):
|
||||||
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.current = current
|
self.current = current
|
||||||
self.wanted = wanted
|
self.wanted = wanted
|
||||||
|
@ -50,7 +49,6 @@ class AppResourceManager:
|
||||||
def apply(
|
def apply(
|
||||||
self, rollback_and_raise_exception_if_failure, operation_logger=None, **context
|
self, rollback_and_raise_exception_if_failure, operation_logger=None, **context
|
||||||
):
|
):
|
||||||
|
|
||||||
todos = list(self.compute_todos())
|
todos = list(self.compute_todos())
|
||||||
completed = []
|
completed = []
|
||||||
rollback = False
|
rollback = False
|
||||||
|
@ -121,7 +119,6 @@ class AppResourceManager:
|
||||||
logger.error(exception)
|
logger.error(exception)
|
||||||
|
|
||||||
def compute_todos(self):
|
def compute_todos(self):
|
||||||
|
|
||||||
for name, infos in reversed(self.current["resources"].items()):
|
for name, infos in reversed(self.current["resources"].items()):
|
||||||
if name not in self.wanted["resources"].keys():
|
if name not in self.wanted["resources"].keys():
|
||||||
resource = AppResourceClassesByType[name](infos, self.app, self)
|
resource = AppResourceClassesByType[name](infos, self.app, self)
|
||||||
|
@ -140,12 +137,10 @@ class AppResourceManager:
|
||||||
|
|
||||||
|
|
||||||
class AppResource:
|
class AppResource:
|
||||||
|
|
||||||
type: str = ""
|
type: str = ""
|
||||||
default_properties: Dict[str, Any] = {}
|
default_properties: Dict[str, Any] = {}
|
||||||
|
|
||||||
def __init__(self, properties: Dict[str, Any], app: str, manager=None):
|
def __init__(self, properties: Dict[str, Any], app: str, manager=None):
|
||||||
|
|
||||||
self.app = app
|
self.app = app
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
|
||||||
|
@ -175,7 +170,6 @@ class AppResource:
|
||||||
app_setting(self.app, key, delete=True)
|
app_setting(self.app, key, delete=True)
|
||||||
|
|
||||||
def _run_script(self, action, script, env={}, user="root"):
|
def _run_script(self, action, script, env={}, user="root"):
|
||||||
|
|
||||||
from yunohost.app import (
|
from yunohost.app import (
|
||||||
_make_tmp_workdir_for_app,
|
_make_tmp_workdir_for_app,
|
||||||
_make_environment_for_app_script,
|
_make_environment_for_app_script,
|
||||||
|
@ -295,7 +289,6 @@ class PermissionsResource(AppResource):
|
||||||
permissions: Dict[str, Dict[str, Any]] = {}
|
permissions: Dict[str, Dict[str, Any]] = {}
|
||||||
|
|
||||||
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
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
|
# 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():
|
for perm, infos in properties.items():
|
||||||
|
@ -315,7 +308,6 @@ class PermissionsResource(AppResource):
|
||||||
super().__init__({"permissions": properties}, *args, **kwargs)
|
super().__init__({"permissions": properties}, *args, **kwargs)
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
from yunohost.permission import (
|
from yunohost.permission import (
|
||||||
permission_create,
|
permission_create,
|
||||||
permission_url,
|
permission_url,
|
||||||
|
@ -375,7 +367,6 @@ class PermissionsResource(AppResource):
|
||||||
permission_sync_to_user()
|
permission_sync_to_user()
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
from yunohost.permission import (
|
from yunohost.permission import (
|
||||||
permission_delete,
|
permission_delete,
|
||||||
user_permission_list,
|
user_permission_list,
|
||||||
|
@ -432,7 +423,6 @@ class SystemuserAppResource(AppResource):
|
||||||
allow_sftp: bool = False
|
allow_sftp: bool = False
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
# FIXME : validate that no yunohost user exists with that name?
|
# FIXME : validate that no yunohost user exists with that name?
|
||||||
# and/or that no system user exists during install ?
|
# 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}")
|
os.system(f"usermod -G {','.join(groups)} {self.app}")
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
if check_output(f"getent passwd {self.app} &>/dev/null || true").strip():
|
if check_output(f"getent passwd {self.app} &>/dev/null || true").strip():
|
||||||
os.system(f"deluser {self.app} >/dev/null")
|
os.system(f"deluser {self.app} >/dev/null")
|
||||||
if check_output(f"getent passwd {self.app} &>/dev/null || true").strip():
|
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 ...
|
# FIXME: change default dir to /opt/stuff if app ain't a webapp ...
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
||||||
assert self.owner.strip()
|
assert self.owner.strip()
|
||||||
assert self.group.strip()
|
assert self.group.strip()
|
||||||
|
@ -582,7 +570,6 @@ class InstalldirAppResource(AppResource):
|
||||||
self.delete_setting("final_path") # Legacy
|
self.delete_setting("final_path") # Legacy
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
||||||
assert self.owner.strip()
|
assert self.owner.strip()
|
||||||
assert self.group.strip()
|
assert self.group.strip()
|
||||||
|
@ -643,7 +630,6 @@ class DatadirAppResource(AppResource):
|
||||||
group: str = ""
|
group: str = ""
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
||||||
assert self.owner.strip()
|
assert self.owner.strip()
|
||||||
assert self.group.strip()
|
assert self.group.strip()
|
||||||
|
@ -686,7 +672,6 @@ class DatadirAppResource(AppResource):
|
||||||
self.delete_setting("datadir") # Legacy
|
self.delete_setting("datadir") # Legacy
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
assert self.dir.strip() # Be paranoid about self.dir being empty...
|
||||||
assert self.owner.strip()
|
assert self.owner.strip()
|
||||||
assert self.group.strip()
|
assert self.group.strip()
|
||||||
|
@ -737,7 +722,6 @@ class AptDependenciesAppResource(AppResource):
|
||||||
extras: Dict[str, Dict[str, str]] = {}
|
extras: Dict[str, Dict[str, str]] = {}
|
||||||
|
|
||||||
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
||||||
|
|
||||||
for key, values in properties.get("extras", {}).items():
|
for key, values in properties.get("extras", {}).items():
|
||||||
if not all(
|
if not all(
|
||||||
isinstance(values.get(k), str) for k in ["repo", "key", "packages"]
|
isinstance(values.get(k), str) for k in ["repo", "key", "packages"]
|
||||||
|
@ -749,7 +733,6 @@ class AptDependenciesAppResource(AppResource):
|
||||||
super().__init__(properties, *args, **kwargs)
|
super().__init__(properties, *args, **kwargs)
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
script = [f"ynh_install_app_dependencies {self.packages}"]
|
script = [f"ynh_install_app_dependencies {self.packages}"]
|
||||||
for repo, values in self.extras.items():
|
for repo, values in self.extras.items():
|
||||||
script += [
|
script += [
|
||||||
|
@ -760,7 +743,6 @@ class AptDependenciesAppResource(AppResource):
|
||||||
self._run_script("provision_or_update", "\n".join(script))
|
self._run_script("provision_or_update", "\n".join(script))
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
self._run_script("deprovision", "ynh_remove_app_dependencies")
|
self._run_script("deprovision", "ynh_remove_app_dependencies")
|
||||||
|
|
||||||
|
|
||||||
|
@ -818,7 +800,6 @@ class PortsResource(AppResource):
|
||||||
ports: Dict[str, Dict[str, Any]]
|
ports: Dict[str, Dict[str, Any]]
|
||||||
|
|
||||||
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
||||||
|
|
||||||
if "main" not in properties:
|
if "main" not in properties:
|
||||||
properties["main"] = {}
|
properties["main"] = {}
|
||||||
|
|
||||||
|
@ -832,7 +813,6 @@ class PortsResource(AppResource):
|
||||||
super().__init__({"ports": properties}, *args, **kwargs)
|
super().__init__({"ports": properties}, *args, **kwargs)
|
||||||
|
|
||||||
def _port_is_used(self, port):
|
def _port_is_used(self, port):
|
||||||
|
|
||||||
# FIXME : this could be less brutal than two os.system ...
|
# FIXME : this could be less brutal than two os.system ...
|
||||||
cmd1 = (
|
cmd1 = (
|
||||||
"ss --numeric --listening --tcp --udp | awk '{print$5}' | grep --quiet --extended-regexp ':%s$'"
|
"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
|
return os.system(cmd1) == 0 and os.system(cmd2) == 0
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
from yunohost.firewall import firewall_allow, firewall_disallow
|
from yunohost.firewall import firewall_allow, firewall_disallow
|
||||||
|
|
||||||
for name, infos in self.ports.items():
|
for name, infos in self.ports.items():
|
||||||
|
|
||||||
setting_name = f"port_{name}" if name != "main" else "port"
|
setting_name = f"port_{name}" if name != "main" else "port"
|
||||||
port_value = self.get_setting(setting_name)
|
port_value = self.get_setting(setting_name)
|
||||||
if not port_value and name != "main":
|
if not port_value and name != "main":
|
||||||
|
@ -881,7 +859,6 @@ class PortsResource(AppResource):
|
||||||
)
|
)
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
from yunohost.firewall import firewall_disallow
|
from yunohost.firewall import firewall_disallow
|
||||||
|
|
||||||
for name, infos in self.ports.items():
|
for name, infos in self.ports.items():
|
||||||
|
@ -938,7 +915,6 @@ class DatabaseAppResource(AppResource):
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
def __init__(self, properties: Dict[str, Any], *args, **kwargs):
|
||||||
|
|
||||||
if "type" not in properties or properties["type"] not in [
|
if "type" not in properties or properties["type"] not in [
|
||||||
"mysql",
|
"mysql",
|
||||||
"postgresql",
|
"postgresql",
|
||||||
|
@ -956,7 +932,6 @@ class DatabaseAppResource(AppResource):
|
||||||
super().__init__(properties, *args, **kwargs)
|
super().__init__(properties, *args, **kwargs)
|
||||||
|
|
||||||
def db_exists(self, db_name):
|
def db_exists(self, db_name):
|
||||||
|
|
||||||
if self.dbtype == "mysql":
|
if self.dbtype == "mysql":
|
||||||
return os.system(f"mysqlshow '{db_name}' >/dev/null 2>/dev/null") == 0
|
return os.system(f"mysqlshow '{db_name}' >/dev/null 2>/dev/null") == 0
|
||||||
elif self.dbtype == "postgresql":
|
elif self.dbtype == "postgresql":
|
||||||
|
@ -970,7 +945,6 @@ class DatabaseAppResource(AppResource):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def provision_or_update(self, context: Dict = {}):
|
def provision_or_update(self, context: Dict = {}):
|
||||||
|
|
||||||
# This is equivalent to ynh_sanitize_dbid
|
# This is equivalent to ynh_sanitize_dbid
|
||||||
db_name = self.app.replace("-", "_").replace(".", "_")
|
db_name = self.app.replace("-", "_").replace(".", "_")
|
||||||
db_user = db_name
|
db_user = db_name
|
||||||
|
@ -997,7 +971,6 @@ class DatabaseAppResource(AppResource):
|
||||||
self.set_setting("db_pwd", db_pwd)
|
self.set_setting("db_pwd", db_pwd)
|
||||||
|
|
||||||
if not self.db_exists(db_name):
|
if not self.db_exists(db_name):
|
||||||
|
|
||||||
if self.dbtype == "mysql":
|
if self.dbtype == "mysql":
|
||||||
self._run_script(
|
self._run_script(
|
||||||
"provision",
|
"provision",
|
||||||
|
@ -1010,7 +983,6 @@ class DatabaseAppResource(AppResource):
|
||||||
)
|
)
|
||||||
|
|
||||||
def deprovision(self, context: Dict = {}):
|
def deprovision(self, context: Dict = {}):
|
||||||
|
|
||||||
db_name = self.app.replace("-", "_").replace(".", "_")
|
db_name = self.app.replace("-", "_").replace(".", "_")
|
||||||
db_user = db_name
|
db_user = db_name
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ def free_space_in_directory(dirpath):
|
||||||
|
|
||||||
|
|
||||||
def space_used_by_directory(dirpath, follow_symlinks=True):
|
def space_used_by_directory(dirpath, follow_symlinks=True):
|
||||||
|
|
||||||
if not follow_symlinks:
|
if not follow_symlinks:
|
||||||
du_output = check_output(["du", "-sb", dirpath], shell=False)
|
du_output = check_output(["du", "-sb", dirpath], shell=False)
|
||||||
return int(du_output.split()[0])
|
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:
|
def human_to_binary(size: str) -> int:
|
||||||
|
|
||||||
symbols = ("K", "M", "G", "T", "P", "E", "Z", "Y")
|
symbols = ("K", "M", "G", "T", "P", "E", "Z", "Y")
|
||||||
factor = {}
|
factor = {}
|
||||||
for i, s in enumerate(symbols):
|
for i, s in enumerate(symbols):
|
||||||
|
@ -99,14 +97,12 @@ def binary_to_human(n: int) -> str:
|
||||||
|
|
||||||
|
|
||||||
def ram_available():
|
def ram_available():
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
return (psutil.virtual_memory().available, psutil.swap_memory().free)
|
return (psutil.virtual_memory().available, psutil.swap_memory().free)
|
||||||
|
|
||||||
|
|
||||||
def get_ynh_package_version(package):
|
def get_ynh_package_version(package):
|
||||||
|
|
||||||
# Returns the installed version and release version ('stable' or 'testing'
|
# Returns the installed version and release version ('stable' or 'testing'
|
||||||
# or 'unstable')
|
# or 'unstable')
|
||||||
|
|
||||||
|
@ -152,7 +148,6 @@ def dpkg_lock_available():
|
||||||
|
|
||||||
|
|
||||||
def _list_upgradable_apt_packages():
|
def _list_upgradable_apt_packages():
|
||||||
|
|
||||||
# List upgradable packages
|
# List upgradable packages
|
||||||
# LC_ALL=C is here to make sure the results are in english
|
# LC_ALL=C is here to make sure the results are in english
|
||||||
upgradable_raw = check_output("LC_ALL=C apt list --upgradable")
|
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()
|
line.strip() for line in upgradable_raw.split("\n") if line.strip()
|
||||||
]
|
]
|
||||||
for line in upgradable_raw:
|
for line in upgradable_raw:
|
||||||
|
|
||||||
# Remove stupid warning and verbose messages >.>
|
# Remove stupid warning and verbose messages >.>
|
||||||
if "apt does not have a stable CLI interface" in line or "Listing..." in line:
|
if "apt does not have a stable CLI interface" in line or "Listing..." in line:
|
||||||
continue
|
continue
|
||||||
|
@ -182,7 +176,6 @@ def _list_upgradable_apt_packages():
|
||||||
|
|
||||||
|
|
||||||
def _dump_sources_list():
|
def _dump_sources_list():
|
||||||
|
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
filenames = glob("/etc/apt/sources.list") + glob("/etc/apt/sources.list.d/*")
|
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):
|
def yunopaste(data):
|
||||||
|
|
||||||
paste_server = "https://paste.yunohost.org"
|
paste_server = "https://paste.yunohost.org"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Add table
Reference in a new issue