Merge pull request #1042 from YunoHost/code-cleanup

Code cleanup
This commit is contained in:
Alexandre Aubin 2020-09-08 16:55:58 +02:00 committed by GitHub
commit 8b98360fd2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 243 additions and 242 deletions

View file

@ -15,15 +15,17 @@ THIS_SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml' ACTIONSMAP_FILE = THIS_SCRIPT_DIR + '/yunohost.yml'
BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost' BASH_COMPLETION_FILE = THIS_SCRIPT_DIR + '/../bash-completion.d/yunohost'
def get_dict_actions(OPTION_SUBTREE, category): def get_dict_actions(OPTION_SUBTREE, category):
ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys() ACTIONS = [action for action in OPTION_SUBTREE[category]["actions"].keys()
if not action.startswith('_')] if not action.startswith('_')]
ACTIONS_STR = '{}'.format(' '.join(ACTIONS)) ACTIONS_STR = '{}'.format(' '.join(ACTIONS))
DICT = { "actions_str": ACTIONS_STR } DICT = {"actions_str": ACTIONS_STR}
return DICT return DICT
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
@ -40,10 +42,10 @@ with open(ACTIONSMAP_FILE, 'r') as stream:
ACTIONS_DICT[category]["subcategories_str"] = "" ACTIONS_DICT[category]["subcategories_str"] = ""
if "subcategories" in OPTION_TREE[category].keys(): if "subcategories" in OPTION_TREE[category].keys():
SUBCATEGORIES = [ subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys() ] SUBCATEGORIES = [subcategory for subcategory in OPTION_TREE[category]["subcategories"].keys()]
SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES)) SUBCATEGORIES_STR = '{}'.format(' '.join(SUBCATEGORIES))
ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR ACTIONS_DICT[category]["subcategories_str"] = SUBCATEGORIES_STR
for subcategory in SUBCATEGORIES: for subcategory in SUBCATEGORIES:

View file

@ -63,10 +63,10 @@ class BaseSystemDiagnoser(Diagnoser):
ynh_core_version = ynh_packages["yunohost"]["version"] ynh_core_version = ynh_packages["yunohost"]["version"]
consistent_versions = all(infos["version"][:3] == ynh_core_version[:3] for infos in ynh_packages.values()) consistent_versions = all(infos["version"][:3] == ynh_core_version[:3] for infos in ynh_packages.values())
ynh_version_details = [("diagnosis_basesystem_ynh_single_version", ynh_version_details = [("diagnosis_basesystem_ynh_single_version",
{"package":package, {"package": package,
"version": infos["version"], "version": infos["version"],
"repo": infos["repo"]} "repo": infos["repo"]}
) )
for package, infos in ynh_packages.items()] for package, infos in ynh_packages.items()]
yield dict(meta={"test": "ynh_versions"}, yield dict(meta={"test": "ynh_versions"},
@ -75,7 +75,6 @@ class BaseSystemDiagnoser(Diagnoser):
summary="diagnosis_basesystem_ynh_main_version" if consistent_versions else "diagnosis_basesystem_ynh_inconsistent_versions", summary="diagnosis_basesystem_ynh_main_version" if consistent_versions else "diagnosis_basesystem_ynh_inconsistent_versions",
details=ynh_version_details) details=ynh_version_details)
if self.is_vulnerable_to_meltdown(): if self.is_vulnerable_to_meltdown():
yield dict(meta={"test": "meltdown"}, yield dict(meta={"test": "meltdown"},
status="ERROR", status="ERROR",

View file

@ -3,9 +3,9 @@
import os import os
from yunohost.diagnosis import Diagnoser from yunohost.diagnosis import Diagnoser
from yunohost.utils.error import YunohostError
from yunohost.service import _get_services from yunohost.service import _get_services
class PortsDiagnoser(Diagnoser): class PortsDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]

View file

@ -8,7 +8,6 @@ from moulinette.utils.filesystem import read_file
from yunohost.diagnosis import Diagnoser from yunohost.diagnosis import Diagnoser
from yunohost.domain import domain_list from yunohost.domain import domain_list
from yunohost.utils.error import YunohostError
DIAGNOSIS_SERVER = "diagnosis.yunohost.org" DIAGNOSIS_SERVER = "diagnosis.yunohost.org"

View file

@ -47,7 +47,6 @@ class MailDiagnoser(Diagnoser):
status="SUCCESS", status="SUCCESS",
summary="diagnosis_mail_" + name + "_ok") summary="diagnosis_mail_" + name + "_ok")
def check_outgoing_port_25(self): def check_outgoing_port_25(self):
""" """
Check outgoing port 25 is open and not blocked by router Check outgoing port 25 is open and not blocked by router
@ -64,7 +63,6 @@ class MailDiagnoser(Diagnoser):
details=["diagnosis_mail_outgoing_port_25_blocked_details", details=["diagnosis_mail_outgoing_port_25_blocked_details",
"diagnosis_mail_outgoing_port_25_blocked_relay_vpn"]) "diagnosis_mail_outgoing_port_25_blocked_relay_vpn"])
def check_ehlo(self): def check_ehlo(self):
""" """
Check the server is reachable from outside and it's the good one Check the server is reachable from outside and it's the good one
@ -99,7 +97,6 @@ class MailDiagnoser(Diagnoser):
summary="diagnosis_mail_ehlo_wrong", summary="diagnosis_mail_ehlo_wrong",
details=["diagnosis_mail_ehlo_wrong_details"]) details=["diagnosis_mail_ehlo_wrong_details"])
def check_fcrdns(self): def check_fcrdns(self):
""" """
Check the reverse DNS is well defined by doing a Forward-confirmed Check the reverse DNS is well defined by doing a Forward-confirmed
@ -148,7 +145,6 @@ class MailDiagnoser(Diagnoser):
summary="diagnosis_mail_fcrdns_different_from_ehlo_domain", summary="diagnosis_mail_fcrdns_different_from_ehlo_domain",
details=details) details=details)
def check_blacklist(self): def check_blacklist(self):
""" """
Check with dig onto blacklist DNS server Check with dig onto blacklist DNS server
@ -225,7 +221,6 @@ class MailDiagnoser(Diagnoser):
status="SUCCESS", status="SUCCESS",
summary="diagnosis_mail_queue_ok") summary="diagnosis_mail_queue_ok")
def get_ips_checked(self): def get_ips_checked(self):
outgoing_ipversions = [] outgoing_ipversions = []
outgoing_ips = [] outgoing_ips = []
@ -245,5 +240,6 @@ class MailDiagnoser(Diagnoser):
outgoing_ips.append(global_ipv6) outgoing_ips.append(global_ipv6)
return (outgoing_ipversions, outgoing_ips) return (outgoing_ipversions, outgoing_ips)
def main(args, env, loggers): def main(args, env, loggers):
return MailDiagnoser(args, env, loggers).diagnose() return MailDiagnoser(args, env, loggers).diagnose()

View file

@ -5,6 +5,7 @@ import os
from yunohost.diagnosis import Diagnoser from yunohost.diagnosis import Diagnoser
from yunohost.service import service_status from yunohost.service import service_status
class ServicesDiagnoser(Diagnoser): class ServicesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@ -36,5 +37,6 @@ class ServicesDiagnoser(Diagnoser):
yield item yield item
def main(args, env, loggers): def main(args, env, loggers):
return ServicesDiagnoser(args, env, loggers).diagnose() return ServicesDiagnoser(args, env, loggers).diagnose()

View file

@ -7,6 +7,7 @@ import re
from yunohost.diagnosis import Diagnoser from yunohost.diagnosis import Diagnoser
class SystemResourcesDiagnoser(Diagnoser): class SystemResourcesDiagnoser(Diagnoser):
id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1] id_ = os.path.splitext(os.path.basename(__file__))[0].split("-")[1]
@ -16,7 +17,7 @@ class SystemResourcesDiagnoser(Diagnoser):
def run(self): def run(self):
MB = 1024**2 MB = 1024**2
GB = MB*1024 GB = MB * 1024
# #
# RAM # RAM
@ -79,7 +80,7 @@ class SystemResourcesDiagnoser(Diagnoser):
# N.B.: we do not use usage.total because we want # N.B.: we do not use usage.total because we want
# to take into account the 5% security margin # to take into account the 5% security margin
# correctly (c.f. the doc of psutil ...) # correctly (c.f. the doc of psutil ...)
"total": human_size(usage.used+usage.free), "total": human_size(usage.used + usage.free),
"free": human_size(usage.free), "free": human_size(usage.free),
"free_percent": free_percent}) "free_percent": free_percent})
@ -96,7 +97,6 @@ class SystemResourcesDiagnoser(Diagnoser):
item["status"] = "SUCCESS" item["status"] = "SUCCESS"
item["summary"] = "diagnosis_diskusage_ok" item["summary"] = "diagnosis_diskusage_ok"
yield item yield item
# #
@ -112,7 +112,6 @@ class SystemResourcesDiagnoser(Diagnoser):
summary="diagnosis_processes_killed_by_oom_reaper", summary="diagnosis_processes_killed_by_oom_reaper",
data={"kills_summary": kills_summary}) data={"kills_summary": kills_summary})
def recent_kills_by_oom_reaper(self): def recent_kills_by_oom_reaper(self):
if not os.path.exists("/var/log/kern.log"): if not os.path.exists("/var/log/kern.log"):
return [] return []
@ -145,7 +144,7 @@ class SystemResourcesDiagnoser(Diagnoser):
def human_size(bytes_): def human_size(bytes_):
# Adapted from https://stackoverflow.com/a/1094933 # Adapted from https://stackoverflow.com/a/1094933
for unit in ['','ki','Mi','Gi','Ti','Pi','Ei','Zi']: for unit in ['', 'ki', 'Mi', 'Gi', 'Ti', 'Pi', 'Ei', 'Zi']:
if abs(bytes_) < 1024.0: if abs(bytes_) < 1024.0:
return "%s %sB" % (round_(bytes_), unit) return "%s %sB" % (round_(bytes_), unit)
bytes_ /= 1024.0 bytes_ /= 1024.0
@ -160,5 +159,6 @@ def round_(n):
n = int(round(n)) n = int(round(n))
return n return n
def main(args, env, loggers): def main(args, env, loggers):
return SystemResourcesDiagnoser(args, env, loggers).diagnose() return SystemResourcesDiagnoser(args, env, loggers).diagnose()

View file

@ -2,7 +2,6 @@
import os import os
import subprocess
from yunohost.diagnosis import Diagnoser from yunohost.diagnosis import Diagnoser
from yunohost.regenconf import _get_regenconf_infos, _calculate_hash from yunohost.regenconf import _get_regenconf_infos, _calculate_hash

View file

@ -4,12 +4,13 @@ import os
import glob import glob
import datetime import datetime
def render(helpers): def render(helpers):
data = { "helpers": helpers, data = {"helpers": helpers,
"date": datetime.datetime.now().strftime("%m/%d/%Y"), "date": datetime.datetime.now().strftime("%m/%d/%Y"),
"version": open("../debian/changelog").readlines()[0].split()[1].strip("()") "version": open("../debian/changelog").readlines()[0].split()[1].strip("()")
} }
from jinja2 import Template from jinja2 import Template
from ansi2html import Ansi2HTMLConverter from ansi2html import Ansi2HTMLConverter
@ -22,13 +23,14 @@ def render(helpers):
return conv.convert(shell, False) return conv.convert(shell, False)
template = open("helper_doc_template.html", "r").read() template = open("helper_doc_template.html", "r").read()
t = Template(template) t = Template(template)
t.globals['now'] = datetime.datetime.utcnow t.globals['now'] = datetime.datetime.utcnow
result = t.render(data=data, convert=shell_to_html, shell_css=shell_css) result = t.render(data=data, convert=shell_to_html, shell_css=shell_css)
open("helpers.html", "w").write(result) open("helpers.html", "w").write(result)
############################################################################## ##############################################################################
class Parser(): class Parser():
def __init__(self, filename): def __init__(self, filename):
@ -42,15 +44,15 @@ class Parser():
self.blocks = [] self.blocks = []
current_reading = "void" current_reading = "void"
current_block = { "name": None, current_block = {"name": None,
"line": -1, "line": -1,
"comments": [], "comments": [],
"code": [] } "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
line = line.rstrip().replace("\t", " ") line = line.rstrip().replace("\t", " ")
@ -73,7 +75,7 @@ class Parser():
elif line.strip() == "": elif line.strip() == "":
# Well eh that was not an actual helper definition ... start over ? # Well eh that was not an actual helper definition ... start over ?
current_reading = "void" current_reading = "void"
current_block = { "name": None, current_block = {"name": None,
"line": -1, "line": -1,
"comments": [], "comments": [],
"code": [] "code": []
@ -101,10 +103,10 @@ class Parser():
# (we ignore helpers containing [internal] ...) # (we ignore helpers containing [internal] ...)
if not "[internal]" in current_block["comments"]: if not "[internal]" in current_block["comments"]:
self.blocks.append(current_block) self.blocks.append(current_block)
current_block = { "name": None, current_block = {"name": None,
"line": -1, "line": -1,
"comments": [], "comments": [],
"code": [] } "code": []}
else: else:
current_block["code"].append(line) current_block["code"].append(line)
@ -180,13 +182,14 @@ class Parser():
b["usage"] = b["usage"].strip() b["usage"] = b["usage"].strip()
def is_global_comment(line): def is_global_comment(line):
return line.startswith('#') return line.startswith('#')
def malformed_error(line_number): def malformed_error(line_number):
return "Malformed file line {} ?".format(line_number) return "Malformed file line {} ?".format(line_number)
def main(): def main():
helper_files = sorted(glob.glob("../data/helpers.d/*")) helper_files = sorted(glob.glob("../data/helpers.d/*"))
@ -204,5 +207,5 @@ def main():
render(helpers) render(helpers)
main()
main()

View file

@ -91,7 +91,7 @@ def init_logging(interface="cli",
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):
os.makedirs(logdir, 0750) os.makedirs(logdir, 0o750)
# ####################################################################### # # ####################################################################### #
# Logging configuration for CLI (or any other interface than api...) # # Logging configuration for CLI (or any other interface than api...) #

View file

@ -681,7 +681,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback from yunohost.hook import hook_add, hook_remove, hook_exec, hook_callback
from yunohost.log import OperationLogger from yunohost.log import OperationLogger
from yunohost.permission import user_permission_list, permission_create, permission_url, permission_delete, permission_sync_to_user, user_permission_update from yunohost.permission import user_permission_list, permission_create, permission_url, permission_delete, permission_sync_to_user
from yunohost.regenconf import manually_modified_files from yunohost.regenconf import manually_modified_files
# Fetch or extract sources # Fetch or extract sources

View file

@ -890,8 +890,6 @@ class RestoreManager():
""" """
from permission import permission_sync_to_user from permission import permission_sync_to_user
successfull_apps = self.targets.list("apps", include=["Success", "Warning"])
permission_sync_to_user() permission_sync_to_user()
if os.path.ismount(self.work_dir): if os.path.ismount(self.work_dir):
@ -1156,7 +1154,7 @@ class RestoreManager():
return return
from yunohost.user import user_group_list from yunohost.user import user_group_list
from yunohost.permission import permission_create, permission_delete, user_permission_update, user_permission_list, permission_sync_to_user from yunohost.permission import permission_create, permission_delete, user_permission_list, permission_sync_to_user
# Backup old permission for apps # Backup old permission for apps
# We need to do that because in case of an app is installed we can't remove the permission for this app # We need to do that because in case of an app is installed we can't remove the permission for this app
@ -1253,7 +1251,7 @@ class RestoreManager():
name should be already install) name should be already install)
""" """
from yunohost.user import user_group_list from yunohost.user import user_group_list
from yunohost.permission import permission_create, permission_delete, user_permission_list, user_permission_update, permission_sync_to_user from yunohost.permission import permission_create, permission_delete, user_permission_list, permission_sync_to_user
def copytree(src, dst, symlinks=False, ignore=None): def copytree(src, dst, symlinks=False, ignore=None):
for item in os.listdir(src): for item in os.listdir(src):

View file

@ -4,7 +4,7 @@ from shutil import copy2
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from yunohost.app import _is_installed, _get_app_settings, _set_app_settings, _patch_legacy_php_versions_in_settings from yunohost.app import _is_installed, _patch_legacy_php_versions_in_settings
from yunohost.tools import Migration from yunohost.tools import Migration
from yunohost.service import _run_service_command from yunohost.service import _run_service_command

View file

@ -28,7 +28,7 @@ class MyMigration(Migration):
# Make sure there's a 9.6 cluster # Make sure there's a 9.6 cluster
try: try:
self.runcmd("pg_lsclusters | grep -q '^9.6 '") self.runcmd("pg_lsclusters | grep -q '^9.6 '")
except Exception as e: except Exception:
logger.warning("It looks like there's not active 9.6 cluster, so probably don't need to run this migration") logger.warning("It looks like there's not active 9.6 cluster, so probably don't need to run this migration")
return return
@ -36,7 +36,7 @@ class MyMigration(Migration):
raise YunohostError("migration_0017_not_enough_space", path="/var/lib/postgresql/") raise YunohostError("migration_0017_not_enough_space", path="/var/lib/postgresql/")
self.runcmd("systemctl stop postgresql") self.runcmd("systemctl stop postgresql")
self.runcmd("pg_dropcluster --stop 11 main || true") # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster) self.runcmd("pg_dropcluster --stop 11 main || true") # We do not trigger an exception if the command fails because that probably means cluster 11 doesn't exists, which is fine because it's created during the pg_upgradecluster)
self.runcmd("pg_upgradecluster -m upgrade 9.6 main") self.runcmd("pg_upgradecluster -m upgrade 9.6 main")
self.runcmd("pg_dropcluster --stop 9.6 main") self.runcmd("pg_dropcluster --stop 9.6 main")
self.runcmd("systemctl start postgresql") self.runcmd("systemctl start postgresql")
@ -63,4 +63,3 @@ class MyMigration(Migration):
out = out.strip().split("\n") out = out.strip().split("\n")
return (returncode, out, err) return (returncode, out, err)

View file

@ -106,4 +106,3 @@ class MyMigration(Migration):
out = out.strip().split("\n") out = out.strip().split("\n")
return (returncode, out, err) return (returncode, out, err)

View file

@ -176,7 +176,7 @@ def diagnosis_run(categories=[], force=False, except_if_never_ran_yet=False, ema
code, report = hook_exec(path, args={"force": force}, env=None) code, report = hook_exec(path, args={"force": force}, env=None)
except Exception: except Exception:
import traceback import traceback
logger.error(m18n.n("diagnosis_failed_for_category", category=category, error='\n'+traceback.format_exc())) logger.error(m18n.n("diagnosis_failed_for_category", category=category, error='\n' + traceback.format_exc()))
else: else:
diagnosed_categories.append(category) diagnosed_categories.append(category)
if report != {}: if report != {}:
@ -403,11 +403,11 @@ class Diagnoser():
Diagnoser.i18n(new_report) Diagnoser.i18n(new_report)
add_ignore_flag_to_issues(new_report) add_ignore_flag_to_issues(new_report)
errors = [item for item in new_report["items"] if item["status"] == "ERROR" and not item["ignored"]] errors = [item for item in new_report["items"] if item["status"] == "ERROR" and not item["ignored"]]
warnings = [item for item in new_report["items"] if item["status"] == "WARNING" and not item["ignored"]] warnings = [item for item in new_report["items"] if item["status"] == "WARNING" and not item["ignored"]]
errors_ignored = [item for item in new_report["items"] if item["status"] == "ERROR" and item["ignored"]] errors_ignored = [item for item in new_report["items"] if item["status"] == "ERROR" and item["ignored"]]
warning_ignored = [item for item in new_report["items"] if item["status"] == "WARNING" and item["ignored"]] warning_ignored = [item for item in new_report["items"] if item["status"] == "WARNING" and item["ignored"]]
ignored_msg = " " + m18n.n("diagnosis_ignored_issues", nb_ignored=len(errors_ignored+warning_ignored)) if errors_ignored or warning_ignored else "" ignored_msg = " " + m18n.n("diagnosis_ignored_issues", nb_ignored=len(errors_ignored + warning_ignored)) if errors_ignored or warning_ignored else ""
if errors and warnings: if errors and warnings:
logger.error(m18n.n("diagnosis_found_errors_and_warnings", errors=len(errors), warnings=len(warnings), category=new_report["description"]) + ignored_msg) logger.error(m18n.n("diagnosis_found_errors_and_warnings", errors=len(errors), warnings=len(warnings), category=new_report["description"]) + ignored_msg)
@ -477,6 +477,7 @@ class Diagnoser():
meta_data.update(item.get("data", {})) meta_data.update(item.get("data", {}))
html_tags = re.compile(r'<[^>]+>') html_tags = re.compile(r'<[^>]+>')
def m18n_(info): def m18n_(info):
if not isinstance(info, tuple) and not isinstance(info, list): if not isinstance(info, tuple) and not isinstance(info, list):
info = (info, {}) info = (info, {})
@ -485,7 +486,7 @@ class Diagnoser():
# In cli, we remove the html tags # In cli, we remove the html tags
if msettings.get("interface") != "api" or force_remove_html_tags: if msettings.get("interface") != "api" or force_remove_html_tags:
s = s.replace("<cmd>", "'").replace("</cmd>", "'") s = s.replace("<cmd>", "'").replace("</cmd>", "'")
s = html_tags.sub('', s.replace("<br>","\n")) s = html_tags.sub('', s.replace("<br>", "\n"))
else: else:
s = s.replace("<cmd>", "<code class='cmd'>").replace("</cmd>", "</code>") s = s.replace("<cmd>", "<code class='cmd'>").replace("</cmd>", "</code>")
# Make it so that links open in new tabs # Make it so that links open in new tabs

View file

@ -89,7 +89,7 @@ def domain_add(operation_logger, domain, dyndns=False):
raise YunohostError('domain_exists') raise YunohostError('domain_exists')
operation_logger.start() operation_logger.start()
# Lower domain to avoid some edge cases issues # Lower domain to avoid some edge cases issues
# See: https://forum.yunohost.org/t/invalid-domain-causes-diagnosis-web-to-fail-fr-on-demand/11765 # See: https://forum.yunohost.org/t/invalid-domain-causes-diagnosis-web-to-fail-fr-on-demand/11765
domain = domain.lower() domain = domain.lower()
@ -614,17 +614,17 @@ def _get_DKIM(domain):
if is_legacy_format: if is_legacy_format:
dkim = re.match(( dkim = re.match((
r'^(?P<host>[a-z_\-\.]+)[\s]+([0-9]+[\s]+)?IN[\s]+TXT[\s]+' r'^(?P<host>[a-z_\-\.]+)[\s]+([0-9]+[\s]+)?IN[\s]+TXT[\s]+'
'[^"]*"v=(?P<v>[^";]+);' '[^"]*"v=(?P<v>[^";]+);'
'[\s"]*k=(?P<k>[^";]+);' r'[\s"]*k=(?P<k>[^";]+);'
'[\s"]*p=(?P<p>[^";]+)'), dkim_content, re.M | re.S '[\s"]*p=(?P<p>[^";]+)'), dkim_content, re.M | re.S
) )
else: else:
dkim = re.match(( dkim = re.match((
r'^(?P<host>[a-z_\-\.]+)[\s]+([0-9]+[\s]+)?IN[\s]+TXT[\s]+' r'^(?P<host>[a-z_\-\.]+)[\s]+([0-9]+[\s]+)?IN[\s]+TXT[\s]+'
'[^"]*"v=(?P<v>[^";]+);' '[^"]*"v=(?P<v>[^";]+);'
'[\s"]*h=(?P<h>[^";]+);' r'[\s"]*h=(?P<h>[^";]+);'
'[\s"]*k=(?P<k>[^";]+);' r'[\s"]*k=(?P<k>[^";]+);'
'[\s"]*p=(?P<p>[^";]+)'), dkim_content, re.M | re.S '[\s"]*p=(?P<p>[^";]+)'), dkim_content, re.M | re.S
) )
if not dkim: if not dkim:

View file

@ -24,7 +24,6 @@
Manage firewall rules Manage firewall rules
""" """
import os import os
import sys
import yaml import yaml
import miniupnpc import miniupnpc

View file

@ -268,9 +268,9 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
# Validate callbacks # Validate callbacks
if not callable(pre_callback): if not callable(pre_callback):
pre_callback = lambda name, priority, path, args: args def pre_callback(name, priority, path, args): return args
if not callable(post_callback): if not callable(post_callback):
post_callback = lambda name, priority, path, succeed: None def post_callback(name, priority, path, succeed): return None
# Iterate over hooks and execute them # Iterate over hooks and execute them
for priority in sorted(hooks_dict): for priority in sorted(hooks_dict):
@ -281,7 +281,7 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
hook_args = pre_callback(name=name, priority=priority, hook_args = pre_callback(name=name, priority=priority,
path=path, args=args) path=path, args=args)
hook_return = hook_exec(path, args=hook_args, chdir=chdir, env=env, hook_return = hook_exec(path, args=hook_args, chdir=chdir, env=env,
no_trace=no_trace, raise_on_error=True)[1] no_trace=no_trace, raise_on_error=True)[1]
except YunohostError as e: except YunohostError as e:
state = 'failed' state = 'failed'
hook_return = {} hook_return = {}
@ -291,9 +291,9 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None,
else: else:
post_callback(name=name, priority=priority, path=path, post_callback(name=name, priority=priority, path=path,
succeed=True) succeed=True)
if not name in result: if name not in result:
result[name] = {} result[name] = {}
result[name][path] = {'state' : state, 'stdreturn' : hook_return } result[name][path] = {'state': state, 'stdreturn': hook_return}
return result return result
@ -444,17 +444,17 @@ 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]
if not dir_ in sys.path: if dir_ not in sys.path:
sys.path = [dir_] + sys.path sys.path = [dir_] + sys.path
module = import_module(name) module = import_module(name)
ret = module.main(args, env, loggers) ret = module.main(args, env, loggers)
# # Assert that the return is a (int, dict) tuple # # Assert that the return is a (int, dict) tuple
assert isinstance(ret, tuple) \ assert isinstance(ret, tuple) \
and len(ret) == 2 \ and len(ret) == 2 \
and isinstance(ret[0],int) \ and isinstance(ret[0], int) \
and isinstance(ret[1],dict), \ and isinstance(ret[1], dict), \
"Module %s did not return a (int, dict) tuple !" % module "Module %s did not return a (int, dict) tuple !" % module
return ret return ret

View file

@ -270,7 +270,7 @@ def log_display(path, number=None, share=False, filter_irrelevant=False, with_su
if os.path.exists(log_path): if os.path.exists(log_path):
from yunohost.service import _tail from yunohost.service import _tail
if number and filters: if number and filters:
logs = _tail(log_path, int(number*4)) logs = _tail(log_path, int(number * 4))
elif number: elif number:
logs = _tail(log_path, int(number)) logs = _tail(log_path, int(number))
else: else:

View file

@ -31,7 +31,6 @@ import random
from moulinette import m18n from moulinette import m18n
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from yunohost.utils.error import YunohostError from yunohost.utils.error import YunohostError
from yunohost.user import user_list
from yunohost.log import is_unit_operation from yunohost.log import is_unit_operation
logger = getActionLogger('yunohost.user') logger = getActionLogger('yunohost.user')

View file

@ -21,7 +21,6 @@
import os import os
import yaml import yaml
import json
import subprocess import subprocess
import shutil import shutil
import hashlib import hashlib
@ -31,7 +30,6 @@ from datetime import datetime
from moulinette import m18n from moulinette import m18n
from moulinette.utils import log, filesystem from moulinette.utils import log, filesystem
from moulinette.utils.filesystem import read_file
from yunohost.utils.error import YunohostError from yunohost.utils.error import YunohostError
from yunohost.log import is_unit_operation from yunohost.log import is_unit_operation
@ -49,7 +47,7 @@ logger = log.getActionLogger('yunohost.regenconf')
# FIXME : check for all reference of 'service' close to operation_logger stuff # FIXME : check for all reference of 'service' close to operation_logger stuff
@is_unit_operation([('names', 'configuration')]) @is_unit_operation([('names', 'configuration')])
def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run=False, def regen_conf(operation_logger, names=[], with_diff=False, force=False, dry_run=False,
list_pending=False): list_pending=False):
""" """
Regenerate the configuration file(s) Regenerate the configuration file(s)

View file

@ -654,7 +654,6 @@ def _tail(file, n):
avg_line_length = 74 avg_line_length = 74
to_read = n to_read = n
try: try:
if file.endswith(".gz"): if file.endswith(".gz"):
import gzip import gzip

View file

@ -15,6 +15,7 @@ logger = getActionLogger('yunohost.settings')
SETTINGS_PATH = "/etc/yunohost/settings.json" SETTINGS_PATH = "/etc/yunohost/settings.json"
SETTINGS_PATH_OTHER_LOCATION = "/etc/yunohost/settings-%s.json" SETTINGS_PATH_OTHER_LOCATION = "/etc/yunohost/settings-%s.json"
def is_boolean(value): def is_boolean(value):
""" """
Ensure a string value is intended as a boolean Ensure a string value is intended as a boolean
@ -60,11 +61,11 @@ DEFAULTS = OrderedDict([
("service.ssh.allow_deprecated_dsa_hostkey", {"type": "bool", "default": False}), ("service.ssh.allow_deprecated_dsa_hostkey", {"type": "bool", "default": False}),
("security.ssh.compatibility", {"type": "enum", "default": "modern", ("security.ssh.compatibility", {"type": "enum", "default": "modern",
"choices": ["intermediate", "modern"]}), "choices": ["intermediate", "modern"]}),
("security.nginx.compatibility", {"type": "enum", "default": "intermediate", ("security.nginx.compatibility", {"type": "enum", "default": "intermediate",
"choices": ["intermediate", "modern"]}), "choices": ["intermediate", "modern"]}),
("security.postfix.compatibility", {"type": "enum", "default": "intermediate", ("security.postfix.compatibility", {"type": "enum", "default": "intermediate",
"choices": ["intermediate", "modern"]}), "choices": ["intermediate", "modern"]}),
("pop3.enabled", {"type": "bool", "default": False}), ("pop3.enabled", {"type": "bool", "default": False}),
("smtp.allow_ipv6", {"type": "bool", "default": True}), ("smtp.allow_ipv6", {"type": "bool", "default": True}),
@ -321,17 +322,20 @@ def reconfigure_nginx(setting_name, old_value, new_value):
if old_value != new_value: if old_value != new_value:
service_regen_conf(names=['nginx']) service_regen_conf(names=['nginx'])
@post_change_hook("security.ssh.compatibility") @post_change_hook("security.ssh.compatibility")
def reconfigure_ssh(setting_name, old_value, new_value): def reconfigure_ssh(setting_name, old_value, new_value):
if old_value != new_value: if old_value != new_value:
service_regen_conf(names=['ssh']) service_regen_conf(names=['ssh'])
@post_change_hook("smtp.allow_ipv6") @post_change_hook("smtp.allow_ipv6")
@post_change_hook("security.postfix.compatibility") @post_change_hook("security.postfix.compatibility")
def reconfigure_postfix(setting_name, old_value, new_value): def reconfigure_postfix(setting_name, old_value, new_value):
if old_value != new_value: if old_value != new_value:
service_regen_conf(names=['postfix']) service_regen_conf(names=['postfix'])
@post_change_hook("pop3.enabled") @post_change_hook("pop3.enabled")
def reconfigure_dovecot(setting_name, old_value, new_value): def reconfigure_dovecot(setting_name, old_value, new_value):
dovecot_package = 'dovecot-pop3d' dovecot_package = 'dovecot-pop3d'

View file

@ -18,10 +18,12 @@ def clone_test_app(request):
else: else:
os.system("cd %s/apps && git pull > /dev/null 2>&1" % cwd) os.system("cd %s/apps && git pull > /dev/null 2>&1" % cwd)
def get_test_apps_dir(): def get_test_apps_dir():
cwd = os.path.split(os.path.realpath(__file__))[0] cwd = os.path.split(os.path.realpath(__file__))[0]
return os.path.join(cwd, "apps") return os.path.join(cwd, "apps")
@contextmanager @contextmanager
def message(mocker, key, **kwargs): def message(mocker, key, **kwargs):
mocker.spy(m18n, "n") mocker.spy(m18n, "n")
@ -38,7 +40,6 @@ def raiseYunohostError(mocker, key, **kwargs):
assert e_info._excinfo[1].kwargs == kwargs assert e_info._excinfo[1].kwargs == kwargs
def pytest_addoption(parser): def pytest_addoption(parser):
parser.addoption("--yunodebug", action="store_true", default=False) parser.addoption("--yunodebug", action="store_true", default=False)
@ -56,12 +57,15 @@ def new_translate(self, key, *args, **kwargs):
raise KeyError("Unable to retrieve key %s for default locale !" % key) raise KeyError("Unable to retrieve key %s for default locale !" % key)
return old_translate(self, key, *args, **kwargs) return old_translate(self, key, *args, **kwargs)
moulinette.core.Translator.translate = new_translate moulinette.core.Translator.translate = new_translate
def new_m18nn(self, key, *args, **kwargs): def new_m18nn(self, key, *args, **kwargs):
return self._namespaces[self._current_namespace].translate(key, *args, **kwargs) return self._namespaces[self._current_namespace].translate(key, *args, **kwargs)
moulinette.core.Moulinette18n.n = new_m18nn moulinette.core.Moulinette18n.n = new_m18nn
# #

View file

@ -40,21 +40,21 @@ def test_parse_args_in_yunohost_format_empty():
def test_parse_args_in_yunohost_format_string(): def test_parse_args_in_yunohost_format_string():
questions = [{"name": "some_string", "type": "string",}] questions = [{"name": "some_string", "type": "string", }]
answers = {"some_string": "some_value"} answers = {"some_string": "some_value"}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_string_default_type(): def test_parse_args_in_yunohost_format_string_default_type():
questions = [{"name": "some_string",}] questions = [{"name": "some_string", }]
answers = {"some_string": "some_value"} answers = {"some_string": "some_value"}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_string_no_input(): def test_parse_args_in_yunohost_format_string_no_input():
questions = [{"name": "some_string",}] questions = [{"name": "some_string", }]
answers = {} answers = {}
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
@ -62,7 +62,7 @@ def test_parse_args_in_yunohost_format_string_no_input():
def test_parse_args_in_yunohost_format_string_input(): def test_parse_args_in_yunohost_format_string_input():
questions = [{"name": "some_string", "ask": "some question",}] questions = [{"name": "some_string", "ask": "some question", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
@ -72,7 +72,7 @@ def test_parse_args_in_yunohost_format_string_input():
@pytest.mark.skip # that shit should work x( @pytest.mark.skip # that shit should work x(
def test_parse_args_in_yunohost_format_string_input_no_ask(): def test_parse_args_in_yunohost_format_string_input_no_ask():
questions = [{"name": "some_string",}] questions = [{"name": "some_string", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
@ -81,14 +81,14 @@ def test_parse_args_in_yunohost_format_string_input_no_ask():
def test_parse_args_in_yunohost_format_string_no_input_optional(): def test_parse_args_in_yunohost_format_string_no_input_optional():
questions = [{"name": "some_string", "optional": True,}] questions = [{"name": "some_string", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("", "string")}) expected_result = OrderedDict({"some_string": ("", "string")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_string_optional_with_input(): def test_parse_args_in_yunohost_format_string_optional_with_input():
questions = [{"name": "some_string", "ask": "some question", "optional": True,}] questions = [{"name": "some_string", "ask": "some question", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
@ -98,7 +98,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_input():
@pytest.mark.skip # this should work without ask @pytest.mark.skip # this should work without ask
def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask():
questions = [{"name": "some_string", "optional": True,}] questions = [{"name": "some_string", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
@ -108,7 +108,7 @@ def test_parse_args_in_yunohost_format_string_optional_with_input_without_ask():
def test_parse_args_in_yunohost_format_string_no_input_default(): def test_parse_args_in_yunohost_format_string_no_input_default():
questions = [ questions = [
{"name": "some_string", "ask": "some question", "default": "some_value",} {"name": "some_string", "ask": "some question", "default": "some_value", }
] ]
answers = {} answers = {}
expected_result = OrderedDict({"some_string": ("some_value", "string")}) expected_result = OrderedDict({"some_string": ("some_value", "string")})
@ -117,7 +117,7 @@ def test_parse_args_in_yunohost_format_string_no_input_default():
def test_parse_args_in_yunohost_format_string_input_test_ask(): def test_parse_args_in_yunohost_format_string_input_test_ask():
ask_text = "some question" ask_text = "some question"
questions = [{"name": "some_string", "ask": ask_text,}] questions = [{"name": "some_string", "ask": ask_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -128,7 +128,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask():
def test_parse_args_in_yunohost_format_string_input_test_ask_with_default(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_default():
ask_text = "some question" ask_text = "some question"
default_text = "some example" default_text = "some example"
questions = [{"name": "some_string", "ask": ask_text, "default": default_text,}] questions = [{"name": "some_string", "ask": ask_text, "default": default_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -140,7 +140,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_default():
def test_parse_args_in_yunohost_format_string_input_test_ask_with_example(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_example():
ask_text = "some question" ask_text = "some question"
example_text = "some example" example_text = "some example"
questions = [{"name": "some_string", "ask": ask_text, "example": example_text,}] questions = [{"name": "some_string", "ask": ask_text, "example": example_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -153,7 +153,7 @@ def test_parse_args_in_yunohost_format_string_input_test_ask_with_example():
def test_parse_args_in_yunohost_format_string_input_test_ask_with_help(): def test_parse_args_in_yunohost_format_string_input_test_ask_with_help():
ask_text = "some question" ask_text = "some question"
help_text = "some_help" help_text = "some_help"
questions = [{"name": "some_string", "ask": ask_text, "help": help_text,}] questions = [{"name": "some_string", "ask": ask_text, "help": help_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -188,7 +188,7 @@ def test_parse_args_in_yunohost_format_string_with_choice_bad():
def test_parse_args_in_yunohost_format_string_with_choice_ask(): def test_parse_args_in_yunohost_format_string_with_choice_ask():
ask_text = "some question" ask_text = "some question"
choices = ["fr", "en", "es", "it", "ru"] choices = ["fr", "en", "es", "it", "ru"]
questions = [{"name": "some_string", "ask": ask_text, "choices": choices,}] questions = [{"name": "some_string", "ask": ask_text, "choices": choices, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="ru") as prompt: with patch.object(msignals, "prompt", return_value="ru") as prompt:
@ -214,14 +214,14 @@ def test_parse_args_in_yunohost_format_string_with_choice_default():
def test_parse_args_in_yunohost_format_password(): def test_parse_args_in_yunohost_format_password():
questions = [{"name": "some_password", "type": "password",}] questions = [{"name": "some_password", "type": "password", }]
answers = {"some_password": "some_value"} answers = {"some_password": "some_value"}
expected_result = OrderedDict({"some_password": ("some_value", "password")}) expected_result = OrderedDict({"some_password": ("some_value", "password")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_password_no_input(): def test_parse_args_in_yunohost_format_password_no_input():
questions = [{"name": "some_password", "type": "password",}] questions = [{"name": "some_password", "type": "password", }]
answers = {} answers = {}
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
@ -229,7 +229,7 @@ def test_parse_args_in_yunohost_format_password_no_input():
def test_parse_args_in_yunohost_format_password_input(): def test_parse_args_in_yunohost_format_password_input():
questions = [{"name": "some_password", "type": "password", "ask": "some question",}] questions = [{"name": "some_password", "type": "password", "ask": "some question", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_password": ("some_value", "password")}) expected_result = OrderedDict({"some_password": ("some_value", "password")})
@ -239,7 +239,7 @@ def test_parse_args_in_yunohost_format_password_input():
@pytest.mark.skip # that shit should work x( @pytest.mark.skip # that shit should work x(
def test_parse_args_in_yunohost_format_password_input_no_ask(): def test_parse_args_in_yunohost_format_password_input_no_ask():
questions = [{"name": "some_password", "type": "password",}] questions = [{"name": "some_password", "type": "password", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_password": ("some_value", "password")}) expected_result = OrderedDict({"some_password": ("some_value", "password")})
@ -248,7 +248,7 @@ def test_parse_args_in_yunohost_format_password_input_no_ask():
def test_parse_args_in_yunohost_format_password_no_input_optional(): def test_parse_args_in_yunohost_format_password_no_input_optional():
questions = [{"name": "some_password", "type": "password", "optional": True,}] questions = [{"name": "some_password", "type": "password", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_password": ("", "password")}) expected_result = OrderedDict({"some_password": ("", "password")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
@ -272,7 +272,7 @@ def test_parse_args_in_yunohost_format_password_optional_with_input():
@pytest.mark.skip # this should work without ask @pytest.mark.skip # this should work without ask
def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_password_optional_with_input_without_ask():
questions = [{"name": "some_password", "type": "password", "optional": True,}] questions = [{"name": "some_password", "type": "password", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_password": ("some_value", "password")}) expected_result = OrderedDict({"some_password": ("some_value", "password")})
@ -316,7 +316,7 @@ def test_parse_args_in_yunohost_format_password_no_input_example():
def test_parse_args_in_yunohost_format_password_input_test_ask(): def test_parse_args_in_yunohost_format_password_input_test_ask():
ask_text = "some question" ask_text = "some question"
questions = [{"name": "some_password", "type": "password", "ask": ask_text,}] questions = [{"name": "some_password", "type": "password", "ask": ask_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -365,14 +365,14 @@ def test_parse_args_in_yunohost_format_password_input_test_ask_with_help():
def test_parse_args_in_yunohost_format_path(): def test_parse_args_in_yunohost_format_path():
questions = [{"name": "some_path", "type": "path",}] questions = [{"name": "some_path", "type": "path", }]
answers = {"some_path": "some_value"} answers = {"some_path": "some_value"}
expected_result = OrderedDict({"some_path": ("some_value", "path")}) expected_result = OrderedDict({"some_path": ("some_value", "path")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_path_no_input(): def test_parse_args_in_yunohost_format_path_no_input():
questions = [{"name": "some_path", "type": "path",}] questions = [{"name": "some_path", "type": "path", }]
answers = {} answers = {}
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
@ -380,7 +380,7 @@ def test_parse_args_in_yunohost_format_path_no_input():
def test_parse_args_in_yunohost_format_path_input(): def test_parse_args_in_yunohost_format_path_input():
questions = [{"name": "some_path", "type": "path", "ask": "some question",}] questions = [{"name": "some_path", "type": "path", "ask": "some question", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")}) expected_result = OrderedDict({"some_path": ("some_value", "path")})
@ -390,7 +390,7 @@ def test_parse_args_in_yunohost_format_path_input():
@pytest.mark.skip # that shit should work x( @pytest.mark.skip # that shit should work x(
def test_parse_args_in_yunohost_format_path_input_no_ask(): def test_parse_args_in_yunohost_format_path_input_no_ask():
questions = [{"name": "some_path", "type": "path",}] questions = [{"name": "some_path", "type": "path", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")}) expected_result = OrderedDict({"some_path": ("some_value", "path")})
@ -399,7 +399,7 @@ def test_parse_args_in_yunohost_format_path_input_no_ask():
def test_parse_args_in_yunohost_format_path_no_input_optional(): def test_parse_args_in_yunohost_format_path_no_input_optional():
questions = [{"name": "some_path", "type": "path", "optional": True,}] questions = [{"name": "some_path", "type": "path", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_path": ("", "path")}) expected_result = OrderedDict({"some_path": ("", "path")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
@ -407,7 +407,7 @@ def test_parse_args_in_yunohost_format_path_no_input_optional():
def test_parse_args_in_yunohost_format_path_optional_with_input(): def test_parse_args_in_yunohost_format_path_optional_with_input():
questions = [ questions = [
{"name": "some_path", "ask": "some question", "type": "path", "optional": True,} {"name": "some_path", "ask": "some question", "type": "path", "optional": True, }
] ]
answers = {} answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")}) expected_result = OrderedDict({"some_path": ("some_value", "path")})
@ -418,7 +418,7 @@ def test_parse_args_in_yunohost_format_path_optional_with_input():
@pytest.mark.skip # this should work without ask @pytest.mark.skip # this should work without ask
def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_path_optional_with_input_without_ask():
questions = [{"name": "some_path", "type": "path", "optional": True,}] questions = [{"name": "some_path", "type": "path", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_path": ("some_value", "path")}) expected_result = OrderedDict({"some_path": ("some_value", "path")})
@ -442,7 +442,7 @@ def test_parse_args_in_yunohost_format_path_no_input_default():
def test_parse_args_in_yunohost_format_path_input_test_ask(): def test_parse_args_in_yunohost_format_path_input_test_ask():
ask_text = "some question" ask_text = "some question"
questions = [{"name": "some_path", "type": "path", "ask": ask_text,}] questions = [{"name": "some_path", "type": "path", "ask": ask_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value="some_value") as prompt: with patch.object(msignals, "prompt", return_value="some_value") as prompt:
@ -454,7 +454,7 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_default():
ask_text = "some question" ask_text = "some question"
default_text = "some example" default_text = "some example"
questions = [ questions = [
{"name": "some_path", "type": "path", "ask": ask_text, "default": default_text,} {"name": "some_path", "type": "path", "ask": ask_text, "default": default_text, }
] ]
answers = {} answers = {}
@ -468,7 +468,7 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_example():
ask_text = "some question" ask_text = "some question"
example_text = "some example" example_text = "some example"
questions = [ questions = [
{"name": "some_path", "type": "path", "ask": ask_text, "example": example_text,} {"name": "some_path", "type": "path", "ask": ask_text, "example": example_text, }
] ]
answers = {} answers = {}
@ -483,7 +483,7 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_help():
ask_text = "some question" ask_text = "some question"
help_text = "some_help" help_text = "some_help"
questions = [ questions = [
{"name": "some_path", "type": "path", "ask": ask_text, "help": help_text,} {"name": "some_path", "type": "path", "ask": ask_text, "help": help_text, }
] ]
answers = {} answers = {}
@ -494,89 +494,89 @@ def test_parse_args_in_yunohost_format_path_input_test_ask_with_help():
def test_parse_args_in_yunohost_format_boolean(): def test_parse_args_in_yunohost_format_boolean():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
answers = {"some_boolean": "y"} answers = {"some_boolean": "y"}
expected_result = OrderedDict({"some_boolean": (1, "boolean")}) expected_result = OrderedDict({"some_boolean": (1, "boolean")})
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
def test_parse_args_in_yunohost_format_boolean_all_yes(): def test_parse_args_in_yunohost_format_boolean_all_yes():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
expected_result = OrderedDict({"some_boolean": (1, "boolean")}) expected_result = OrderedDict({"some_boolean": (1, "boolean")})
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "y"}, questions) _parse_args_in_yunohost_format({"some_boolean": "y"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "Y"}, questions) _parse_args_in_yunohost_format({"some_boolean": "Y"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "yes"}, questions) _parse_args_in_yunohost_format({"some_boolean": "yes"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "Yes"}, questions) _parse_args_in_yunohost_format({"some_boolean": "Yes"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "YES"}, questions) _parse_args_in_yunohost_format({"some_boolean": "YES"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "1"}, questions) _parse_args_in_yunohost_format({"some_boolean": "1"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": 1}, questions) _parse_args_in_yunohost_format({"some_boolean": 1}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": True}, questions) _parse_args_in_yunohost_format({"some_boolean": True}, questions) ==
== expected_result expected_result
) )
def test_parse_args_in_yunohost_format_boolean_all_no(): def test_parse_args_in_yunohost_format_boolean_all_no():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) expected_result = OrderedDict({"some_boolean": (0, "boolean")})
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "n"}, questions) _parse_args_in_yunohost_format({"some_boolean": "n"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "N"}, questions) _parse_args_in_yunohost_format({"some_boolean": "N"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "no"}, questions) _parse_args_in_yunohost_format({"some_boolean": "no"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "No"}, questions) _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "No"}, questions) _parse_args_in_yunohost_format({"some_boolean": "No"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": "0"}, questions) _parse_args_in_yunohost_format({"some_boolean": "0"}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": 0}, questions) _parse_args_in_yunohost_format({"some_boolean": 0}, questions) ==
== expected_result expected_result
) )
assert ( assert (
_parse_args_in_yunohost_format({"some_boolean": False}, questions) _parse_args_in_yunohost_format({"some_boolean": False}, questions) ==
== expected_result expected_result
) )
# XXX apparently boolean are always False (0) by default, I'm not sure what to think about that # XXX apparently boolean are always False (0) by default, I'm not sure what to think about that
def test_parse_args_in_yunohost_format_boolean_no_input(): def test_parse_args_in_yunohost_format_boolean_no_input():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) expected_result = OrderedDict({"some_boolean": (0, "boolean")})
@ -584,7 +584,7 @@ def test_parse_args_in_yunohost_format_boolean_no_input():
def test_parse_args_in_yunohost_format_boolean_bad_input(): def test_parse_args_in_yunohost_format_boolean_bad_input():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
answers = {"some_boolean": "stuff"} answers = {"some_boolean": "stuff"}
with pytest.raises(YunohostError): with pytest.raises(YunohostError):
@ -592,7 +592,7 @@ def test_parse_args_in_yunohost_format_boolean_bad_input():
def test_parse_args_in_yunohost_format_boolean_input(): def test_parse_args_in_yunohost_format_boolean_input():
questions = [{"name": "some_boolean", "type": "boolean", "ask": "some question",}] questions = [{"name": "some_boolean", "type": "boolean", "ask": "some question", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_boolean": (1, "boolean")}) expected_result = OrderedDict({"some_boolean": (1, "boolean")})
@ -606,7 +606,7 @@ def test_parse_args_in_yunohost_format_boolean_input():
@pytest.mark.skip # we should work @pytest.mark.skip # we should work
def test_parse_args_in_yunohost_format_boolean_input_no_ask(): def test_parse_args_in_yunohost_format_boolean_input_no_ask():
questions = [{"name": "some_boolean", "type": "boolean",}] questions = [{"name": "some_boolean", "type": "boolean", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_boolean": ("some_value", "boolean")}) expected_result = OrderedDict({"some_boolean": ("some_value", "boolean")})
@ -615,7 +615,7 @@ def test_parse_args_in_yunohost_format_boolean_input_no_ask():
def test_parse_args_in_yunohost_format_boolean_no_input_optional(): def test_parse_args_in_yunohost_format_boolean_no_input_optional():
questions = [{"name": "some_boolean", "type": "boolean", "optional": True,}] questions = [{"name": "some_boolean", "type": "boolean", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false expected_result = OrderedDict({"some_boolean": (0, "boolean")}) # default to false
assert _parse_args_in_yunohost_format(answers, questions) == expected_result assert _parse_args_in_yunohost_format(answers, questions) == expected_result
@ -638,7 +638,7 @@ def test_parse_args_in_yunohost_format_boolean_optional_with_input():
def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask(): def test_parse_args_in_yunohost_format_boolean_optional_with_input_without_ask():
questions = [{"name": "some_boolean", "type": "boolean", "optional": True,}] questions = [{"name": "some_boolean", "type": "boolean", "optional": True, }]
answers = {} answers = {}
expected_result = OrderedDict({"some_boolean": (0, "boolean")}) expected_result = OrderedDict({"some_boolean": (0, "boolean")})
@ -677,7 +677,7 @@ def test_parse_args_in_yunohost_format_boolean_bad_default():
def test_parse_args_in_yunohost_format_boolean_input_test_ask(): def test_parse_args_in_yunohost_format_boolean_input_test_ask():
ask_text = "some question" ask_text = "some question"
questions = [{"name": "some_boolean", "type": "boolean", "ask": ask_text,}] questions = [{"name": "some_boolean", "type": "boolean", "ask": ask_text, }]
answers = {} answers = {}
with patch.object(msignals, "prompt", return_value=0) as prompt: with patch.object(msignals, "prompt", return_value=0) as prompt:
@ -704,7 +704,7 @@ def test_parse_args_in_yunohost_format_boolean_input_test_ask_with_default():
def test_parse_args_in_yunohost_format_domain_empty(): def test_parse_args_in_yunohost_format_domain_empty():
questions = [{"name": "some_domain", "type": "domain",}] questions = [{"name": "some_domain", "type": "domain", }]
answers = {} answers = {}
with patch.object( with patch.object(
@ -719,7 +719,7 @@ def test_parse_args_in_yunohost_format_domain_empty():
def test_parse_args_in_yunohost_format_domain(): def test_parse_args_in_yunohost_format_domain():
main_domain = "my_main_domain.com" main_domain = "my_main_domain.com"
domains = [main_domain] domains = [main_domain]
questions = [{"name": "some_domain", "type": "domain",}] questions = [{"name": "some_domain", "type": "domain", }]
answers = {"some_domain": main_domain} answers = {"some_domain": main_domain}
expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) expected_result = OrderedDict({"some_domain": (main_domain, "domain")})
@ -735,7 +735,7 @@ def test_parse_args_in_yunohost_format_domain_two_domains():
other_domain = "some_other_domain.tld" other_domain = "some_other_domain.tld"
domains = [main_domain, other_domain] domains = [main_domain, other_domain]
questions = [{"name": "some_domain", "type": "domain",}] questions = [{"name": "some_domain", "type": "domain", }]
answers = {"some_domain": other_domain} answers = {"some_domain": other_domain}
expected_result = OrderedDict({"some_domain": (other_domain, "domain")}) expected_result = OrderedDict({"some_domain": (other_domain, "domain")})
@ -758,7 +758,7 @@ def test_parse_args_in_yunohost_format_domain_two_domains_wrong_answer():
other_domain = "some_other_domain.tld" other_domain = "some_other_domain.tld"
domains = [main_domain, other_domain] domains = [main_domain, other_domain]
questions = [{"name": "some_domain", "type": "domain",}] questions = [{"name": "some_domain", "type": "domain", }]
answers = {"some_domain": "doesnt_exist.pouet"} answers = {"some_domain": "doesnt_exist.pouet"}
with patch.object( with patch.object(
@ -774,7 +774,7 @@ def test_parse_args_in_yunohost_format_domain_two_domains_default_no_ask():
other_domain = "some_other_domain.tld" other_domain = "some_other_domain.tld"
domains = [main_domain, other_domain] domains = [main_domain, other_domain]
questions = [{"name": "some_domain", "type": "domain",}] questions = [{"name": "some_domain", "type": "domain", }]
answers = {} answers = {}
expected_result = OrderedDict({"some_domain": (main_domain, "domain")}) expected_result = OrderedDict({"some_domain": (main_domain, "domain")})
@ -831,7 +831,7 @@ def test_parse_args_in_yunohost_format_user_empty():
} }
} }
questions = [{"name": "some_user", "type": "user",}] questions = [{"name": "some_user", "type": "user", }]
answers = {} answers = {}
with patch.object(user, "user_list", return_value={"users": users}): with patch.object(user, "user_list", return_value={"users": users}):
@ -852,7 +852,7 @@ def test_parse_args_in_yunohost_format_user():
} }
} }
questions = [{"name": "some_user", "type": "user",}] questions = [{"name": "some_user", "type": "user", }]
answers = {"some_user": username} answers = {"some_user": username}
expected_result = OrderedDict({"some_user": (username, "user")}) expected_result = OrderedDict({"some_user": (username, "user")})
@ -883,7 +883,7 @@ def test_parse_args_in_yunohost_format_user_two_users():
}, },
} }
questions = [{"name": "some_user", "type": "user",}] questions = [{"name": "some_user", "type": "user", }]
answers = {"some_user": other_user} answers = {"some_user": other_user}
expected_result = OrderedDict({"some_user": (other_user, "user")}) expected_result = OrderedDict({"some_user": (other_user, "user")})
@ -919,7 +919,7 @@ def test_parse_args_in_yunohost_format_user_two_users_wrong_answer():
}, },
} }
questions = [{"name": "some_user", "type": "user",}] questions = [{"name": "some_user", "type": "user", }]
answers = {"some_user": "doesnt_exist.pouet"} answers = {"some_user": "doesnt_exist.pouet"}
with patch.object(user, "user_list", return_value={"users": users}): with patch.object(user, "user_list", return_value={"users": users}):
@ -1002,7 +1002,7 @@ def test_parse_args_in_yunohost_format_app_empty():
} }
] ]
questions = [{"name": "some_app", "type": "app",}] questions = [{"name": "some_app", "type": "app", }]
answers = {} answers = {}
with patch.object(app, "app_list", return_value={"apps": apps}): with patch.object(app, "app_list", return_value={"apps": apps}):
@ -1012,7 +1012,7 @@ def test_parse_args_in_yunohost_format_app_empty():
def test_parse_args_in_yunohost_format_app_no_apps(): def test_parse_args_in_yunohost_format_app_no_apps():
apps = [] apps = []
questions = [{"name": "some_app", "type": "app",}] questions = [{"name": "some_app", "type": "app", }]
answers = {} answers = {}
with patch.object(app, "app_list", return_value={"apps": apps}): with patch.object(app, "app_list", return_value={"apps": apps}):
@ -1041,7 +1041,7 @@ def test_parse_args_in_yunohost_format_app():
} }
] ]
questions = [{"name": "some_app", "type": "app",}] questions = [{"name": "some_app", "type": "app", }]
answers = {"some_app": app_name} answers = {"some_app": app_name}
expected_result = OrderedDict({"some_app": (app_name, "app")}) expected_result = OrderedDict({"some_app": (app_name, "app")})
@ -1072,7 +1072,7 @@ def test_parse_args_in_yunohost_format_app_two_apps():
}, },
] ]
questions = [{"name": "some_app", "type": "app",}] questions = [{"name": "some_app", "type": "app", }]
answers = {"some_app": other_app} answers = {"some_app": other_app}
expected_result = OrderedDict({"some_app": (other_app, "app")}) expected_result = OrderedDict({"some_app": (other_app, "app")})
@ -1112,7 +1112,7 @@ def test_parse_args_in_yunohost_format_app_two_apps_wrong_answer():
}, },
] ]
questions = [{"name": "some_app", "type": "app",}] questions = [{"name": "some_app", "type": "app", }]
answers = {"some_app": "doesnt_exist"} answers = {"some_app": "doesnt_exist"}
with pytest.raises(YunohostError): with pytest.raises(YunohostError):

View file

@ -6,7 +6,7 @@ import glob
import shutil import shutil
from moulinette import m18n from moulinette import m18n
from moulinette.utils.filesystem import read_json, write_to_json, write_to_yaml, mkdir from moulinette.utils.filesystem import read_json, write_to_json, write_to_yaml
from yunohost.utils.error import YunohostError from yunohost.utils.error import YunohostError
from yunohost.app import (_initialize_apps_catalog_system, from yunohost.app import (_initialize_apps_catalog_system,
@ -37,10 +37,12 @@ DUMMY_APP_CATALOG = """{
} }
""" """
class AnyStringWith(str): class AnyStringWith(str):
def __eq__(self, other): def __eq__(self, other):
return self in other return self in other
def setup_function(function): def setup_function(function):
# Clear apps catalog cache # Clear apps catalog cache
@ -165,6 +167,7 @@ def test_apps_catalog_update_404(mocker):
_update_apps_catalog() _update_apps_catalog()
m18n.n.assert_any_call("apps_catalog_failed_to_download") m18n.n.assert_any_call("apps_catalog_failed_to_download")
def test_apps_catalog_update_timeout(mocker): def test_apps_catalog_update_timeout(mocker):
# Initialize ... # Initialize ...
@ -237,7 +240,6 @@ def test_apps_catalog_load_with_empty_cache(mocker):
m18n.n.assert_any_call("apps_catalog_obsolete_cache") m18n.n.assert_any_call("apps_catalog_obsolete_cache")
m18n.n.assert_any_call("apps_catalog_update_success") m18n.n.assert_any_call("apps_catalog_update_success")
# Cache shouldn't be empty anymore empty # Cache shouldn't be empty anymore empty
assert glob.glob(APPS_CATALOG_CACHE + "/*") assert glob.glob(APPS_CATALOG_CACHE + "/*")

View file

@ -16,6 +16,7 @@ from yunohost.hook import CUSTOM_HOOK_FOLDER
# Get main domain # Get main domain
maindomain = "" maindomain = ""
def setup_function(function): def setup_function(function):
global maindomain global maindomain
@ -32,7 +33,7 @@ def setup_function(function):
assert len(backup_list()["archives"]) == 0 assert len(backup_list()["archives"]) == 0
markers = [m.name for m in function.__dict__.get("pytestmark",[])] markers = [m.name for m in function.__dict__.get("pytestmark", [])]
if "with_wordpress_archive_from_2p4" in markers: if "with_wordpress_archive_from_2p4" in markers:
add_archive_wordpress_from_2p4() add_archive_wordpress_from_2p4()
@ -75,7 +76,7 @@ def teardown_function(function):
delete_all_backups() delete_all_backups()
uninstall_test_apps_if_needed() uninstall_test_apps_if_needed()
markers = [m.name for m in function.__dict__.get("pytestmark",[])] markers = [m.name for m in function.__dict__.get("pytestmark", [])]
if "clean_opt_dir" in markers: if "clean_opt_dir" in markers:
shutil.rmtree("/opt/test_backup_output_directory") shutil.rmtree("/opt/test_backup_output_directory")
@ -90,6 +91,7 @@ def check_LDAP_db_integrity_call():
yield yield
check_LDAP_db_integrity() check_LDAP_db_integrity()
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
def check_permission_for_apps_call(): def check_permission_for_apps_call():
check_permission_for_apps() check_permission_for_apps()
@ -100,6 +102,7 @@ def check_permission_for_apps_call():
# Helpers # # Helpers #
# #
def app_is_installed(app): def app_is_installed(app):
if app == "permissions_app": if app == "permissions_app":
@ -184,22 +187,22 @@ def add_archive_wordpress_from_2p4():
os.system("mkdir -p /home/yunohost.backup/archives") os.system("mkdir -p /home/yunohost.backup/archives")
os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.info.json") + \ os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.info.json")
" /home/yunohost.backup/archives/backup_wordpress_from_2p4.info.json") + " /home/yunohost.backup/archives/backup_wordpress_from_2p4.info.json")
os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.tar.gz") + \ os.system("cp " + os.path.join(get_test_apps_dir(), "backup_wordpress_from_2p4/backup.tar.gz")
" /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz") + " /home/yunohost.backup/archives/backup_wordpress_from_2p4.tar.gz")
def add_archive_system_from_2p4(): def add_archive_system_from_2p4():
os.system("mkdir -p /home/yunohost.backup/archives") os.system("mkdir -p /home/yunohost.backup/archives")
os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.info.json") + \ os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.info.json")
" /home/yunohost.backup/archives/backup_system_from_2p4.info.json") + " /home/yunohost.backup/archives/backup_system_from_2p4.info.json")
os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.tar.gz") + \ os.system("cp " + os.path.join(get_test_apps_dir(), "backup_system_from_2p4/backup.tar.gz")
" /home/yunohost.backup/archives/backup_system_from_2p4.tar.gz") + " /home/yunohost.backup/archives/backup_system_from_2p4.tar.gz")
# #
# System backup # # System backup #
@ -309,7 +312,7 @@ def test_backup_script_failure_handling(monkeypatch, mocker):
# with the expected error message key # with the expected error message key
monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec) monkeypatch.setattr("yunohost.backup.hook_exec", custom_hook_exec)
with message(mocker, 'backup_app_failed', app='backup_recommended_app'): with message(mocker, 'backup_app_failed', app='backup_recommended_app'):
with raiseYunohostError(mocker, 'backup_nothings_done'): with raiseYunohostError(mocker, 'backup_nothings_done'):
backup_create(system=None, apps=["backup_recommended_app"]) backup_create(system=None, apps=["backup_recommended_app"])
@ -499,6 +502,7 @@ 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):
@ -548,7 +552,7 @@ def _test_backup_and_restore_app(mocker, app):
# Uninstall the app # Uninstall the app
app_remove(app) app_remove(app)
assert not app_is_installed(app) assert not app_is_installed(app)
assert app+".main" not in user_permission_list()['permissions'] assert app + ".main" not in user_permission_list()['permissions']
# Restore the app # Restore the app
with message(mocker, "restore_complete"): with message(mocker, "restore_complete"):
@ -559,7 +563,7 @@ def _test_backup_and_restore_app(mocker, app):
# Check permission # Check permission
per_list = user_permission_list()['permissions'] per_list = user_permission_list()['permissions']
assert app+".main" in per_list assert app + ".main" in per_list
# #
# Some edge cases # # Some edge cases #
@ -577,6 +581,7 @@ def test_restore_archive_with_no_json(mocker):
with raiseYunohostError(mocker, 'backup_archive_cant_retrieve_info_json'): with raiseYunohostError(mocker, 'backup_archive_cant_retrieve_info_json'):
backup_restore(name="badbackup", force=True) backup_restore(name="badbackup", force=True)
@pytest.mark.with_wordpress_archive_from_2p4 @pytest.mark.with_wordpress_archive_from_2p4
def test_restore_archive_with_bad_archive(mocker): def test_restore_archive_with_bad_archive(mocker):
@ -605,9 +610,9 @@ def test_restore_archive_with_custom_hook(mocker):
# Restore system with custom hook # Restore system with custom hook
with message(mocker, "restore_complete"): with message(mocker, "restore_complete"):
backup_restore(name=backup_list()["archives"][0], backup_restore(name=backup_list()["archives"][0],
system=[], system=[],
apps=None, apps=None,
force=True) force=True)
os.system("rm %s/99-yolo" % custom_restore_hook_folder) os.system("rm %s/99-yolo" % custom_restore_hook_folder)

View file

@ -13,6 +13,7 @@ from yunohost.utils.error import YunohostError
# Get main domain # Get main domain
maindomain = "" maindomain = ""
def setup_function(function): def setup_function(function):
global maindomain global maindomain
maindomain = _get_maindomain() maindomain = _get_maindomain()

View file

@ -1,14 +1,15 @@
import socket
import requests import requests
import pytest import pytest
import os import os
from conftest import message, raiseYunohostError, get_test_apps_dir from conftest import message, raiseYunohostError, get_test_apps_dir
from yunohost.app import app_install, app_remove, app_change_url, app_list, app_map, _installed_apps from yunohost.app import app_install, app_remove, app_change_url, app_map, _installed_apps
from yunohost.user import user_list, user_create, user_delete, \ from yunohost.user import user_list, user_create, user_delete, \
user_group_list, user_group_delete user_group_list, user_group_delete
from yunohost.permission import user_permission_update, user_permission_list, user_permission_reset, \ from yunohost.permission import user_permission_update, user_permission_list, user_permission_reset, \
permission_create, permission_delete, permission_url permission_create, permission_delete, permission_url
from yunohost.domain import _get_maindomain from yunohost.domain import _get_maindomain
# Get main domain # Get main domain
@ -17,10 +18,10 @@ dummy_password = "test123Ynh"
# Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address. # Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address.
# Mainly used for 'can_access_webpage' function # Mainly used for 'can_access_webpage' function
import socket
prv_getaddrinfo = socket.getaddrinfo prv_getaddrinfo = socket.getaddrinfo
def clean_user_groups_permission(): def clean_user_groups_permission():
for u in user_list()['users']: for u in user_list()['users']:
user_delete(u) user_delete(u)
@ -44,6 +45,7 @@ def setup_function(function):
# Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address. # Dirty patch of DNS resolution. Force the DNS to 127.0.0.1 address even if dnsmasq have the public address.
# Mainly used for 'can_access_webpage' function # Mainly used for 'can_access_webpage' function
dns_cache = {(maindomain, 443, 0, 1): [(2, 1, 6, '', ('127.0.0.1', 443))]} dns_cache = {(maindomain, 443, 0, 1): [(2, 1, 6, '', ('127.0.0.1', 443))]}
def new_getaddrinfo(*args): def new_getaddrinfo(*args):
try: try:
return dns_cache[args] return dns_cache[args]
@ -370,16 +372,6 @@ def test_permission_reset_idempotency():
assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"]) assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"])
def test_permission_reset_idempotency():
# Reset permission
user_permission_reset("blog.main")
user_permission_reset("blog.main")
res = user_permission_list(full=True)['permissions']
assert res['blog.main']['allowed'] == ["all_users"]
assert set(res['blog.main']['corresponding_users']) == set(["alice", "bob"])
# #
# Error on update function # Error on update function
# #
@ -407,6 +399,7 @@ def test_permission_redefine_url():
res = user_permission_list(full=True)['permissions'] res = user_permission_list(full=True)['permissions']
assert res["blog.main"]["url"] == "/pwet" assert res["blog.main"]["url"] == "/pwet"
def test_permission_remove_url(): def test_permission_remove_url():
permission_url("blog.main", url=None) permission_url("blog.main", url=None)
@ -499,9 +492,9 @@ def test_permission_app_propagation_on_ssowat():
# alice gotta be allowed on the main permission to access the admin tho # alice gotta be allowed on the main permission to access the admin tho
user_permission_update("permissions_app.main", remove="bob", add="all_users") user_permission_update("permissions_app.main", remove="bob", add="all_users")
assert not can_access_webpage(app_webroot+"/admin", logged_as=None) assert not can_access_webpage(app_webroot + "/admin", logged_as=None)
assert can_access_webpage(app_webroot+"/admin", logged_as="alice") assert can_access_webpage(app_webroot + "/admin", logged_as="alice")
assert not can_access_webpage(app_webroot+"/admin", logged_as="bob") assert not can_access_webpage(app_webroot + "/admin", logged_as="bob")
def test_permission_legacy_app_propagation_on_ssowat(): def test_permission_legacy_app_propagation_on_ssowat():

View file

@ -9,6 +9,7 @@ TEST_DOMAIN_NGINX_CONFIG = "/etc/nginx/conf.d/%s.conf" % TEST_DOMAIN
TEST_DOMAIN_DNSMASQ_CONFIG = "/etc/dnsmasq.d/%s" % TEST_DOMAIN TEST_DOMAIN_DNSMASQ_CONFIG = "/etc/dnsmasq.d/%s" % TEST_DOMAIN
SSHD_CONFIG = "/etc/ssh/sshd_config" 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])
@ -169,7 +170,7 @@ def test_stale_hashes_if_file_manually_deleted():
# ... Anyway, the proper way to write these tests would be to use a dummy # ... Anyway, the proper way to write these tests would be to use a dummy
# regen-conf hook just for tests but meh I'm lazy # regen-conf hook just for tests but meh I'm lazy
# #
#def test_stale_hashes_if_file_manually_modified(): # def test_stale_hashes_if_file_manually_modified():
# """ # """
# Same as other test, but manually delete the file in between and check # Same as other test, but manually delete the file in between and check
# behavior # behavior

View file

@ -64,11 +64,13 @@ 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")

View file

@ -13,6 +13,7 @@ DEFAULTS["example.int"] = {"type": "int", "default": 42}
DEFAULTS["example.string"] = {"type": "string", "default": "yolo swag"} DEFAULTS["example.string"] = {"type": "string", "default": "yolo swag"}
DEFAULTS["example.enum"] = {"type": "enum", "default": "a", "choices": ["a", "b", "c"]} DEFAULTS["example.enum"] = {"type": "enum", "default": "a", "choices": ["a", "b", "c"]}
def setup_function(function): def setup_function(function):
os.system("mv /etc/yunohost/settings.json /etc/yunohost/settings.json.saved") os.system("mv /etc/yunohost/settings.json /etc/yunohost/settings.json.saved")
@ -64,10 +65,11 @@ def test_settings_list():
def test_settings_set(): def test_settings_set():
settings_set("example.bool", False) settings_set("example.bool", False)
assert settings_get("example.bool") == False assert settings_get("example.bool") is False
settings_set("example.bool", "on") settings_set("example.bool", "on")
assert settings_get("example.bool") == True assert settings_get("example.bool") is True
def test_settings_set_int(): def test_settings_set_int():
settings_set("example.int", 21) settings_set("example.int", 21)

View file

@ -3,7 +3,7 @@ import pytest
from conftest import message, raiseYunohostError from conftest import message, raiseYunohostError
from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \ from yunohost.user import user_list, user_info, user_create, user_delete, user_update, \
user_group_list, user_group_create, user_group_delete, user_group_update user_group_list, user_group_create, user_group_delete, user_group_update
from yunohost.domain import _get_maindomain from yunohost.domain import _get_maindomain
from yunohost.tests.test_permission import check_LDAP_db_integrity from yunohost.tests.test_permission import check_LDAP_db_integrity

View file

@ -26,10 +26,8 @@
import re import re
import os import os
import yaml import yaml
import json
import subprocess import subprocess
import pwd import pwd
import socket
from importlib import import_module from importlib import import_module
from moulinette import msignals, m18n from moulinette import msignals, m18n
@ -37,8 +35,8 @@ from moulinette.utils.log import getActionLogger
from moulinette.utils.process import check_output, call_async_output from moulinette.utils.process import check_output, call_async_output
from moulinette.utils.filesystem import read_json, write_to_json, read_yaml, write_to_yaml from moulinette.utils.filesystem import read_json, write_to_json, read_yaml, write_to_yaml
from yunohost.app import _update_apps_catalog, app_info, app_upgrade, app_ssowatconf, app_list, _initialize_apps_catalog_system from yunohost.app import _update_apps_catalog, app_info, app_upgrade, _initialize_apps_catalog_system
from yunohost.domain import domain_add, domain_list from yunohost.domain import domain_add
from yunohost.dyndns import _dyndns_available, _dyndns_provides from yunohost.dyndns import _dyndns_available, _dyndns_provides
from yunohost.firewall import firewall_upnp from yunohost.firewall import firewall_upnp
from yunohost.service import service_start, service_enable from yunohost.service import service_start, service_enable
@ -53,9 +51,11 @@ MIGRATIONS_STATE_PATH = "/etc/yunohost/migrations.yaml"
logger = getActionLogger('yunohost.tools') logger = getActionLogger('yunohost.tools')
def tools_versions(): def tools_versions():
return ynh_packages_version() return ynh_packages_version()
def tools_ldapinit(): def tools_ldapinit():
""" """
YunoHost LDAP initialization YunoHost LDAP initialization
@ -118,7 +118,7 @@ def tools_ldapinit():
if not os.path.isdir('/home/{0}'.format("admin")): if not os.path.isdir('/home/{0}'.format("admin")):
logger.warning(m18n.n('user_home_creation_failed'), logger.warning(m18n.n('user_home_creation_failed'),
exc_info=1) exc_info=1)
logger.success(m18n.n('ldap_initialized')) logger.success(m18n.n('ldap_initialized'))
@ -148,7 +148,7 @@ def tools_adminpw(new_password, check_strength=True):
ldap = _get_ldap_interface() ldap = _get_ldap_interface()
try: try:
ldap.update("cn=admin", {"userPassword": [ new_hash ], }) ldap.update("cn=admin", {"userPassword": [new_hash], })
except: except:
logger.exception('unable to change admin password') logger.exception('unable to change admin password')
raise YunohostError('admin_password_change_failed') raise YunohostError('admin_password_change_failed')
@ -601,7 +601,6 @@ def tools_upgrade(operation_logger, apps=None, system=False, allow_yunohost_upgr
logger.debug("Running apt command :\n{}".format(dist_upgrade)) logger.debug("Running apt command :\n{}".format(dist_upgrade))
def is_relevant(l): def is_relevant(l):
irrelevants = [ irrelevants = [
"service sudo-ldap already provided", "service sudo-ldap already provided",
@ -938,7 +937,7 @@ def _migrate_legacy_migration_json():
# Extract the list of migration ids # Extract the list of migration ids
from . import data_migrations from . import data_migrations
migrations_path = data_migrations.__path__[0] migrations_path = data_migrations.__path__[0]
migration_files = filter(lambda x: re.match("^\d+_[a-zA-Z0-9_]+\.py$", x), os.listdir(migrations_path)) migration_files = filter(lambda x: re.match(r"^\d+_[a-zA-Z0-9_]+\.py$", x), os.listdir(migrations_path))
# (here we remove the .py extension and make sure the ids are sorted) # (here we remove the .py extension and make sure the ids are sorted)
migration_ids = sorted([f.rsplit(".", 1)[0] for f in migration_files]) migration_ids = sorted([f.rsplit(".", 1)[0] for f in migration_files])
@ -987,7 +986,7 @@ def _get_migrations_list():
# (in particular, pending migrations / not already ran are not listed # (in particular, pending migrations / not already ran are not listed
states = tools_migrations_state()["migrations"] states = tools_migrations_state()["migrations"]
for migration_file in filter(lambda x: re.match("^\d+_[a-zA-Z0-9_]+\.py$", x), os.listdir(migrations_path)): for migration_file in filter(lambda x: re.match(r"^\d+_[a-zA-Z0-9_]+\.py$", x), os.listdir(migrations_path)):
m = _load_migration(migration_file) m = _load_migration(migration_file)
m.state = states.get(m.id, "pending") m.state = states.get(m.id, "pending")
migrations.append(m) migrations.append(m)
@ -1006,7 +1005,7 @@ def _get_migration_by_name(migration_name):
raise AssertionError("Unable to find migration with name %s" % migration_name) raise AssertionError("Unable to find migration with name %s" % migration_name)
migrations_path = data_migrations.__path__[0] migrations_path = data_migrations.__path__[0]
migrations_found = filter(lambda x: re.match("^\d+_%s\.py$" % migration_name, x), os.listdir(migrations_path)) migrations_found = filter(lambda x: re.match(r"^\d+_%s\.py$" % migration_name, x), os.listdir(migrations_path))
assert len(migrations_found) == 1, "Unable to find migration with name %s" % migration_name assert len(migrations_found) == 1, "Unable to find migration with name %s" % migration_name
@ -1050,7 +1049,7 @@ class Migration(object):
# Those are to be implemented by daughter classes # Those are to be implemented by daughter classes
mode = "auto" mode = "auto"
dependencies = [] # List of migration ids required before running this migration dependencies = [] # List of migration ids required before running this migration
@property @property
def disclaimer(self): def disclaimer(self):

View file

@ -27,7 +27,6 @@ import os
import re import re
import pwd import pwd
import grp import grp
import json
import crypt import crypt
import random import random
import string import string
@ -36,7 +35,6 @@ import copy
from moulinette import msignals, msettings, m18n from moulinette import msignals, msettings, m18n
from moulinette.utils.log import getActionLogger from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import read_json, write_to_json, read_yaml, write_to_yaml
from yunohost.utils.error import YunohostError from yunohost.utils.error import YunohostError
from yunohost.service import service_status from yunohost.service import service_status
@ -240,7 +238,6 @@ def user_delete(operation_logger, username, purge=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
from yunohost.permission import permission_sync_to_user
if username not in user_list()["users"]: if username not in user_list()["users"]:
raise YunohostError('user_unknown', user=username) raise YunohostError('user_unknown', user=username)

View file

@ -33,8 +33,8 @@ class YunohostError(MoulinetteError):
""" """
def __init__(self, key, raw_msg=False, *args, **kwargs): def __init__(self, key, raw_msg=False, *args, **kwargs):
self.key = key # Saving the key is useful for unit testing self.key = key # Saving the key is useful for unit testing
self.kwargs = kwargs # Saving the key is useful for unit testing self.kwargs = kwargs # Saving the key is useful for unit testing
if raw_msg: if raw_msg:
msg = key msg = key
else: else:

View file

@ -29,19 +29,20 @@ from yunohost.utils.error import YunohostError
# to avoid re-authenticating in case we call _get_ldap_authenticator multiple times # to avoid re-authenticating in case we call _get_ldap_authenticator multiple times
_ldap_interface = None _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:
conf = { "vendor": "ldap", conf = {"vendor": "ldap",
"name": "as-root", "name": "as-root",
"parameters": { 'uri': 'ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi', "parameters": {'uri': 'ldapi://%2Fvar%2Frun%2Fslapd%2Fldapi',
'base_dn': 'dc=yunohost,dc=org', 'base_dn': 'dc=yunohost,dc=org',
'user_rdn': 'gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth' }, 'user_rdn': 'gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth'},
"extra": {} "extra": {}
} }
try: try:
_ldap_interface = ldap.Authenticator(**conf) _ldap_interface = ldap.Authenticator(**conf)
@ -82,4 +83,5 @@ def _destroy_ldap_interface():
if _ldap_interface is not None: if _ldap_interface is not None:
del _ldap_interface del _ldap_interface
atexit.register(_destroy_ldap_interface) atexit.register(_destroy_ldap_interface)

View file

@ -58,6 +58,7 @@ def get_public_ip_from_remote_server(protocol=4):
# If we are indeed connected in ipv4 or ipv6, we should find a default route # If we are indeed connected in ipv4 or ipv6, we should find a default route
routes = check_output("ip -%s route show table all" % protocol).split("\n") routes = check_output("ip -%s route show table all" % protocol).split("\n")
def is_default_route(r): def is_default_route(r):
# Typically the default route starts with "default" # Typically the default route starts with "default"
# But of course IPv6 is more complex ... e.g. on internet cube there's # But of course IPv6 is more complex ... e.g. on internet cube there's

View file

@ -63,7 +63,7 @@ class PasswordValidator(object):
settings = json.load(open('/etc/yunohost/settings.json', "r")) settings = json.load(open('/etc/yunohost/settings.json', "r"))
setting_key = "security.password." + profile + ".strength" setting_key = "security.password." + profile + ".strength"
self.validation_strength = int(settings[setting_key]["value"]) self.validation_strength = int(settings[setting_key]["value"])
except Exception as e: except Exception:
# Fallback to default value if we can't fetch settings for some reason # Fallback to default value if we can't fetch settings for some reason
self.validation_strength = 1 self.validation_strength = 1
@ -83,11 +83,7 @@ class PasswordValidator(object):
# 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
# as well as modules available in python's path. # as well as modules available in python's path.
import logging
from yunohost.utils.error import YunohostError from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
logger = logging.getLogger('yunohost.utils.password')
status, msg = self.validation_summary(password) status, msg = self.validation_summary(password)
if status == "error": if status == "error":

View file

@ -10,6 +10,7 @@ from yunohost.utils.error import YunohostError
logger = logging.getLogger('yunohost.utils.yunopaste') logger = logging.getLogger('yunohost.utils.yunopaste')
def yunopaste(data): def yunopaste(data):
paste_server = "https://paste.yunohost.org" paste_server = "https://paste.yunohost.org"
@ -44,7 +45,6 @@ def anonymize(data):
data = data.replace(domain.replace(".", "%2e"), redact.replace(".", "%2e")) data = data.replace(domain.replace(".", "%2e"), redact.replace(".", "%2e"))
return data return data
# First, let's replace every occurence of the main domain by "domain.tld" # First, let's replace every occurence of the main domain by "domain.tld"
# This should cover a good fraction of the info leaked # This should cover a good fraction of the info leaked
main_domain = _get_maindomain() main_domain = _get_maindomain()

View file

@ -1,4 +1,3 @@
import re
import json import json
import glob import glob
from collections import OrderedDict from collections import OrderedDict
@ -14,6 +13,6 @@ for locale_file in locale_files:
print(locale_file) print(locale_file)
this_locale = json.loads(open(locale_folder + locale_file).read(), object_pairs_hook=OrderedDict) this_locale = json.loads(open(locale_folder + locale_file).read(), object_pairs_hook=OrderedDict)
this_locale_fixed = {k:v for k, v in this_locale.items() if k in reference} this_locale_fixed = {k: v for k, v in this_locale.items() if k in reference}
json.dump(this_locale_fixed, open(locale_folder + locale_file, "w"), indent=4, ensure_ascii=False) json.dump(this_locale_fixed, open(locale_folder + locale_file, "w"), indent=4, ensure_ascii=False)

View file

@ -1,4 +1,5 @@
import yaml import yaml
def test_yaml_syntax(): def test_yaml_syntax():
yaml.load(open("data/actionsmap/yunohost.yml")) yaml.load(open("data/actionsmap/yunohost.yml"))

View file

@ -7,6 +7,6 @@ deps =
py{27,37}-{lint,invalidcode}: flake8 py{27,37}-{lint,invalidcode}: flake8
py37-black: black py37-black: black
commands = commands =
py{27,37}-lint: flake8 src doc data tests py{27,37}-lint: flake8 src doc data tests --ignore E402,E501 --exclude src/yunohost/vendor
py{27,37}-invalidcode: flake8 src data --exclude src/yunohost/tests --select F --ignore F401,F841 py{27,37}-invalidcode: flake8 src data --exclude src/yunohost/tests,src/yunohost/vendor --select F
py37-black: black --check --diff src doc data tests py37-black: black --check --diff src doc data tests