From e0ac7de432c7e565fef3c07b319bffa7d8cf7945 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 20:17:58 +0100 Subject: [PATCH 01/14] We ain't using argument user nor no_trace --- src/yunohost/hook.py | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 22d1ef623..c505a2d30 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -211,7 +211,7 @@ def hook_list(action, list_by='name', show_info=False): return {'hooks': result} -def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, +def hook_callback(action, hooks=[], args=None, chdir=None, env=None, pre_callback=None, post_callback=None): """ Execute all scripts binded to an action @@ -220,7 +220,6 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, action -- Action name hooks -- List of hooks names to execute args -- Ordered list of arguments to pass to the scripts - no_trace -- Do not print each command that will be executed chdir -- The directory from where the scripts will be executed env -- Dictionnary of environment variables to export pre_callback -- An object to call before each script execution with @@ -281,7 +280,7 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, hook_args = pre_callback(name=name, priority=priority, path=path, args=args) hook_return = hook_exec(path, args=hook_args, chdir=chdir, env=env, - no_trace=no_trace, raise_on_error=True)[1] + raise_on_error=True)[1] except YunohostError as e: state = 'failed' hook_return = {} @@ -297,8 +296,8 @@ def hook_callback(action, hooks=[], args=None, no_trace=False, chdir=None, return result -def hook_exec(path, args=None, raise_on_error=False, no_trace=False, - chdir=None, env=None, user="root", return_format="json"): +def hook_exec(path, args=None, raise_on_error=False, + chdir=None, env=None, return_format="json"): """ Execute hook from a file with arguments @@ -306,11 +305,8 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, path -- Path of the script to execute args -- Ordered list of arguments to pass to the script raise_on_error -- Raise if the script returns a non-zero exit code - no_trace -- Do not print each command that will be executed chdir -- The directory from where the script will be executed env -- Dictionnary of environment variables to export - user -- User with which to run the command - """ # Validate hook path @@ -348,7 +344,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, if hook_type == 'text/x-python': returncode, returndata = _hook_exec_python(path, args, env, loggers) else: - returncode, returndata = _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers) + returncode, returndata = _hook_exec_bash(path, args, chdir, env, return_format, loggers) # Check and return process' return code if returncode is None: @@ -363,7 +359,7 @@ def hook_exec(path, args=None, raise_on_error=False, no_trace=False, return returncode, returndata -def _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, loggers): +def _hook_exec_bash(path, args, chdir, env, return_format, loggers): from moulinette.utils.process import call_async_output @@ -395,16 +391,10 @@ def _hook_exec_bash(path, args, no_trace, chdir, env, user, return_format, logge env['YNH_STDRETURN'] = stdreturn # Construct command to execute - if user == "root": - command = ['sh', '-c'] - else: - command = ['sudo', '-n', '-u', user, '-H', 'sh', '-c'] + command = ['sh', '-c'] - if no_trace: - cmd = '/bin/bash "{script}" {args}' - else: - # use xtrace on fd 7 which is redirected to stdout - cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1' + # use xtrace on fd 7 which is redirected to stdout + cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1' # prepend environment variables cmd = '{0} {1}'.format( From 14f6f09993d0963f7c3e1b723aec0edeb819e3ca Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 20:19:53 +0100 Subject: [PATCH 02/14] Do not write the env explicitly in the command to avoid leaking secrets in ps -ef... --- src/yunohost/hook.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index c505a2d30..039737737 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -396,17 +396,13 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): # use xtrace on fd 7 which is redirected to stdout cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1' - # prepend environment variables - cmd = '{0} {1}'.format( - ' '.join(['{0}={1}'.format(k, shell_quote(v)) - for k, v in env.items()]), cmd) command.append(cmd.format(script=cmd_script, args=cmd_args)) logger.debug("Executing command '%s'" % ' '.join(command)) returncode = call_async_output( command, loggers, shell=False, cwd=chdir, - stdinfo=stdinfo + stdinfo=stdinfo, env=env ) raw_content = None From d6d45cf7a6acdf2d5c3d663c8100afb8dc96264f Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 20:28:45 +0100 Subject: [PATCH 03/14] Simplify command call, no need to wrap this in a dummy 'sh -c' --- src/yunohost/hook.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 039737737..af9897851 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -390,18 +390,15 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): f.write('') env['YNH_STDRETURN'] = stdreturn - # Construct command to execute - command = ['sh', '-c'] - # use xtrace on fd 7 which is redirected to stdout - cmd = 'BASH_XTRACEFD=7 /bin/bash -x "{script}" {args} 7>&1' + env['BASH_XTRACEFD'] = 7 + cmd = '/bin/bash -x "{script}" {args} 7>&1' + cmd = cmd.format(script=cmd_script, args=cmd_args) - command.append(cmd.format(script=cmd_script, args=cmd_args)) - - logger.debug("Executing command '%s'" % ' '.join(command)) + logger.debug("Executing command '%s'" % cmd) returncode = call_async_output( - command, loggers, shell=False, cwd=chdir, + cmd, loggers, shell=True, cwd=chdir, stdinfo=stdinfo, env=env ) From 2428f0152183ff791e76248f20bc3d2d171c5ebc Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 20:35:53 +0100 Subject: [PATCH 04/14] Do not pass app args to the command line, they're already provided in the env... --- src/yunohost/app.py | 27 +++++++-------------------- src/yunohost/backup.py | 9 +++++---- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 71aaca316..93ffbbb5b 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -356,8 +356,6 @@ def app_change_url(operation_logger, app, domain, path): # Retrieve arguments list for change_url script # TODO: Allow to specify arguments args_odict = _parse_args_from_manifest(manifest, 'change_url') - args_list = [value[0] for value in args_odict.values()] - args_list.append(app) # Prepare env. var. to pass to script env_dict = _make_environment_for_app_script(app, args=args_odict) @@ -389,7 +387,7 @@ def app_change_url(operation_logger, app, domain, path): os.system('chmod +x %s' % os.path.join(os.path.join(APP_TMP_FOLDER, "scripts", "change_url"))) if hook_exec(os.path.join(APP_TMP_FOLDER, 'scripts/change_url'), - args=args_list, env=env_dict)[0] != 0: + env=env_dict)[0] != 0: msg = "Failed to change '%s' url." % app logger.error(msg) operation_logger.error(msg) @@ -420,7 +418,7 @@ def app_change_url(operation_logger, app, domain, path): logger.success(m18n.n("app_change_url_success", app=app, domain=domain, path=path)) - hook_callback('post_app_change_url', args=args_list, env=env_dict) + hook_callback('post_app_change_url', env=env_dict) def app_upgrade(app=[], url=None, file=None, force=False): @@ -518,8 +516,6 @@ def app_upgrade(app=[], url=None, file=None, force=False): # Retrieve arguments list for upgrade script # TODO: Allow to specify arguments args_odict = _parse_args_from_manifest(manifest, 'upgrade') - args_list = [value[0] for value in args_odict.values()] - args_list.append(app_instance_name) # Prepare env. var. to pass to script env_dict = _make_environment_for_app_script(app_instance_name, args=args_odict) @@ -548,7 +544,7 @@ def app_upgrade(app=[], url=None, file=None, force=False): upgrade_failed = True try: upgrade_retcode = hook_exec(extracted_app_folder + '/scripts/upgrade', - args=args_list, env=env_dict)[0] + env=env_dict)[0] upgrade_failed = True if upgrade_retcode != 0 else False if upgrade_failed: @@ -625,7 +621,7 @@ def app_upgrade(app=[], url=None, file=None, force=False): # So much win logger.success(m18n.n('app_upgraded', app=app_instance_name)) - hook_callback('post_app_upgrade', args=args_list, env=env_dict) + hook_callback('post_app_upgrade', env=env_dict) operation_logger.success() permission_sync_to_user() @@ -742,10 +738,6 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu # Validate domain / path availability for webapps _validate_and_normalize_webpath(manifest, args_odict, extracted_app_folder) - # build arg list tq - args_list = [value[0] for value in args_odict.values()] - args_list.append(app_instance_name) - # Attempt to patch legacy helpers ... _patch_legacy_helpers(extracted_app_folder) @@ -818,7 +810,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu try: install_retcode = hook_exec( os.path.join(extracted_app_folder, 'scripts/install'), - args=args_list, env=env_dict + env=env_dict )[0] # "Common" app install failure : the script failed and returned exit code != 0 install_failed = True if install_retcode != 0 else False @@ -934,7 +926,7 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu logger.success(m18n.n('installation_complete')) - hook_callback('post_app_install', args=args_list, env=env_dict) + hook_callback('post_app_install', env=env_dict) def dump_app_log_extract_for_debugging(operation_logger): @@ -1021,8 +1013,6 @@ def app_remove(operation_logger, app): os.system('chown -R admin: /tmp/yunohost_remove') os.system('chmod -R u+rX /tmp/yunohost_remove') - args_list = [app] - env_dict = {} app_id, app_instance_nb = _parse_app_instance_name(app) env_dict["YNH_APP_ID"] = app_id @@ -1034,7 +1024,6 @@ def app_remove(operation_logger, app): try: ret = hook_exec('/tmp/yunohost_remove/scripts/remove', - args=args_list, env=env_dict)[0] # Here again, calling hook_exec could fail miserably, or get # manually interrupted (by mistake or because script was stuck) @@ -1047,7 +1036,7 @@ def app_remove(operation_logger, app): if ret == 0: logger.success(m18n.n('app_removed', app=app)) - hook_callback('post_app_remove', args=args_list, env=env_dict) + hook_callback('post_app_remove', env=env_dict) else: logger.warning(m18n.n('app_not_properly_removed', app=app)) @@ -1460,7 +1449,6 @@ def app_action_run(operation_logger, app, action, args=None): # Retrieve arguments list for install script args_dict = dict(urlparse.parse_qsl(args, keep_blank_values=True)) if args else {} args_odict = _parse_args_for_action(actions[action], args=args_dict) - args_list = [value[0] for value in args_odict.values()] env_dict = _make_environment_for_app_script(app, args=args_odict, args_prefix="ACTION_") env_dict["YNH_ACTION"] = action @@ -1479,7 +1467,6 @@ def app_action_run(operation_logger, app, action, args=None): retcode = hook_exec( path, - args=args_list, env=env_dict, chdir=cwd, user=action_declaration.get("user", "root"), diff --git a/src/yunohost/backup.py b/src/yunohost/backup.py index c0f11eae8..4bafa8455 100644 --- a/src/yunohost/backup.py +++ b/src/yunohost/backup.py @@ -685,8 +685,10 @@ class BackupManager(): app_script = os.path.join(app_setting_path, 'scripts/backup') subprocess.call(['install', '-Dm555', app_script, tmp_script]) - hook_exec(tmp_script, args=[tmp_app_bkp_dir, app], - raise_on_error=True, chdir=tmp_app_bkp_dir, env=env_dict)[0] + hook_exec(tmp_script, + raise_on_error=True, + chdir=tmp_app_bkp_dir, + env=env_dict)[0] self._import_to_list_to_backup(env_dict["YNH_BACKUP_CSV"]) @@ -1382,7 +1384,6 @@ class RestoreManager(): # Execute app restore script hook_exec(restore_script, - args=[app_backup_in_archive, app_instance_name], chdir=app_backup_in_archive, raise_on_error=True, env=env_dict)[0] @@ -1407,7 +1408,7 @@ class RestoreManager(): operation_logger.start() # Execute remove script - if hook_exec(remove_script, args=[app_instance_name], + if hook_exec(remove_script, env=env_dict_remove)[0] != 0: msg = m18n.n('app_not_properly_removed', app=app_instance_name) logger.warning(msg) From 81f3b493e49415c3b2d7ddde82da4bd34d85dcb7 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 21:06:23 +0100 Subject: [PATCH 05/14] Also copy the script env --- src/yunohost/hook.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index af9897851..1758a1167 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -397,9 +397,12 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): logger.debug("Executing command '%s'" % cmd) + _env = os.environ.copy() + _env.update(env) + returncode = call_async_output( cmd, loggers, shell=True, cwd=chdir, - stdinfo=stdinfo, env=env + stdinfo=stdinfo, env=_env ) raw_content = None From efdb2ee6b5874fd4ee7645b2a6a0d0ad7411412d Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 5 Dec 2020 21:06:37 +0100 Subject: [PATCH 06/14] Gotta make sure everything is a string --- src/yunohost/app.py | 2 +- src/yunohost/hook.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 93ffbbb5b..686209225 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -2761,7 +2761,7 @@ def _make_environment_for_app_script(app, args={}, args_prefix="APP_ARG_"): } for arg_name, arg_value_and_type in args.items(): - env_dict["YNH_%s%s" % (args_prefix, arg_name.upper())] = arg_value_and_type[0] + env_dict["YNH_%s%s" % (args_prefix, arg_name.upper())] = str(arg_value_and_type[0]) return env_dict diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 1758a1167..53ed5f2e5 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -391,7 +391,7 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): env['YNH_STDRETURN'] = stdreturn # use xtrace on fd 7 which is redirected to stdout - env['BASH_XTRACEFD'] = 7 + env['BASH_XTRACEFD'] = "7" cmd = '/bin/bash -x "{script}" {args} 7>&1' cmd = cmd.format(script=cmd_script, args=cmd_args) From 792643607bea29e89c4c27f60e54c56819216965 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 8 Dec 2020 17:55:29 +0100 Subject: [PATCH 07/14] [fix] Avoid password are given in users hooks --- src/yunohost/user.py | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 67fd43a03..6ecfffb48 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -218,12 +218,28 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor user_group_create(groupname=username, gid=uid, primary_group=True, sync_perm=False) user_group_update(groupname='all_users', add=username, force=True, sync_perm=True) + # Trigger post_user_create hooks + env_dict = { + "YNH_USER_USERNAME": username, + "YNH_USER_MAIL": mail, + "YNH_USER_PASSWORD": password, + "YNH_USER_FIRSTNAME": firstname, + "YNH_USER_LASTNAME": lastname + } + + # Put a random password instead of the true one to force + # packagers to change this + # FIXME: Remove this in future version + chars = string.ascii_letters + string.digits + string.punctuation + fake_password = "".join([random.choice(chars) for i in range(20)]) + fake_password += " num args are deprecated, please use YNH_USER_PASSWORD" + hook_callback('post_user_create', + args=[username, mail, fake_password, firstname, lastname], + env=env_dict) + # TODO: Send a welcome mail to user logger.success(m18n.n('user_created')) - hook_callback('post_user_create', - args=[username, mail, password, firstname, lastname]) - return {'fullname': fullname, 'username': username, 'mail': mail} @@ -311,16 +327,21 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= if not result: raise YunohostError('user_unknown', user=username) user = result[0] + env_dict = { + "YNH_USER_USERNAME": username + } # Get modifications from arguments new_attr_dict = {} if firstname: new_attr_dict['givenName'] = [firstname] # TODO: Validate new_attr_dict['cn'] = new_attr_dict['displayName'] = [firstname + ' ' + user['sn'][0]] + env_dict["YNH_USER_FIRSTNAME"] = firstname if lastname: new_attr_dict['sn'] = [lastname] # TODO: Validate new_attr_dict['cn'] = new_attr_dict['displayName'] = [user['givenName'][0] + ' ' + lastname] + env_dict["YNH_USER_LASTNAME"] = lastname if lastname and firstname: new_attr_dict['cn'] = new_attr_dict['displayName'] = [firstname + ' ' + lastname] @@ -330,6 +351,7 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= assert_password_is_strong_enough("user", change_password) new_attr_dict['userPassword'] = [_hash_user_password(change_password)] + env_dict["YNH_USER_PASSWORD"] = change_password if mail: main_domain = _get_maindomain() @@ -374,6 +396,9 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= raise YunohostError('mail_alias_remove_failed', mail=mail) new_attr_dict['mail'] = user['mail'] + if 'mail' in new_attr_dict: + env_dict["YNH_USER_MAILS"] = ','.join(new_attr_dict['mail']) + if add_mailforward: if not isinstance(add_mailforward, list): add_mailforward = [add_mailforward] @@ -393,8 +418,12 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= raise YunohostError('mail_forward_remove_failed', mail=mail) new_attr_dict['maildrop'] = user['maildrop'] + if 'maildrop' in new_attr_dict: + env_dict["YNH_USER_MAILFORWARDS"] = ','.join(new_attr_dict['maildrop']) + if mailbox_quota is not None: new_attr_dict['mailuserquota'] = [mailbox_quota] + env_dict["YNH_USER_MAILQUOTA"] = mailbox_quota operation_logger.start() @@ -403,6 +432,9 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= except Exception as e: raise YunohostError('user_update_failed', user=username, error=e) + # Trigger post_user_update hooks + hook_callback('post_user_update', env=env_dict) + logger.success(m18n.n('user_updated')) app_ssowatconf() return user_info(username) From 2ebef4ebb42840c5bc623453f9378035903ab684 Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 8 Dec 2020 17:57:48 +0100 Subject: [PATCH 08/14] [fix] Missing hook_callback --- src/yunohost/user.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yunohost/user.py b/src/yunohost/user.py index 6ecfffb48..c11ec58a2 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -317,6 +317,7 @@ def user_update(operation_logger, username, firstname=None, lastname=None, mail= from yunohost.app import app_ssowatconf from yunohost.utils.password import assert_password_is_strong_enough from yunohost.utils.ldap import _get_ldap_interface + from yunohost.hook import hook_callback domains = domain_list()['domains'] From cdb1d83eae09d8b10bfda628f9014e4ac54fd78c Mon Sep 17 00:00:00 2001 From: ljf Date: Tue, 8 Dec 2020 18:06:42 +0100 Subject: [PATCH 09/14] [fix] No need for fake password, no app use ,4,5 --- src/yunohost/user.py | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/yunohost/user.py b/src/yunohost/user.py index c11ec58a2..b4e20311a 100644 --- a/src/yunohost/user.py +++ b/src/yunohost/user.py @@ -227,15 +227,7 @@ def user_create(operation_logger, username, firstname, lastname, domain, passwor "YNH_USER_LASTNAME": lastname } - # Put a random password instead of the true one to force - # packagers to change this - # FIXME: Remove this in future version - chars = string.ascii_letters + string.digits + string.punctuation - fake_password = "".join([random.choice(chars) for i in range(20)]) - fake_password += " num args are deprecated, please use YNH_USER_PASSWORD" - hook_callback('post_user_create', - args=[username, mail, fake_password, firstname, lastname], - env=env_dict) + hook_callback('post_user_create', args=[username, mail], env=env_dict) # TODO: Send a welcome mail to user logger.success(m18n.n('user_created')) From fee888d330e834ed27443a57cf31d95db2e60895 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 3 Jan 2021 23:02:57 +0100 Subject: [PATCH 10/14] Small debug line to try to understand why the test are failing on the CI --- src/yunohost/hook.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 53ed5f2e5..80afa4890 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -400,6 +400,9 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): _env = os.environ.copy() _env.update(env) + # FIXME : this is a temporary debug to better understand why the test are failing on the CI but not when ran manually... + logger.debug(_env) + returncode = call_async_output( cmd, loggers, shell=True, cwd=chdir, stdinfo=stdinfo, env=_env From 9bf4a12f3299319ffe6fa57592d50011bb8bc0dc Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 3 Jan 2021 23:26:46 +0100 Subject: [PATCH 11/14] Zblerg debug ain't displayed on the CI --- src/yunohost/hook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index d0e7166a0..3b899e0ad 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -402,7 +402,7 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): _env.update(env) # FIXME : this is a temporary debug to better understand why the test are failing on the CI but not when ran manually... - logger.debug(_env) + logger.warning(_env) returncode = call_async_output( cmd, loggers, shell=True, cwd=chdir, From 9807b76d3430aa74c917d360b12a52bf32634f70 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sun, 3 Jan 2021 23:53:00 +0100 Subject: [PATCH 12/14] Turns out msettings interface is None is ran from pytest because we bypass the usual moulinette init :/ --- src/yunohost/hook.py | 3 --- src/yunohost/tests/conftest.py | 3 ++- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/yunohost/hook.py b/src/yunohost/hook.py index 3b899e0ad..8361b8505 100644 --- a/src/yunohost/hook.py +++ b/src/yunohost/hook.py @@ -401,9 +401,6 @@ def _hook_exec_bash(path, args, chdir, env, return_format, loggers): _env = os.environ.copy() _env.update(env) - # FIXME : this is a temporary debug to better understand why the test are failing on the CI but not when ran manually... - logger.warning(_env) - returncode = call_async_output( cmd, loggers, shell=True, cwd=chdir, stdinfo=stdinfo, env=_env diff --git a/src/yunohost/tests/conftest.py b/src/yunohost/tests/conftest.py index 2bda72852..1aaefb993 100644 --- a/src/yunohost/tests/conftest.py +++ b/src/yunohost/tests/conftest.py @@ -3,7 +3,7 @@ import pytest import sys import moulinette -from moulinette import m18n +from moulinette import m18n, msettings from yunohost.utils.error import YunohostError from contextlib import contextmanager sys.path.append("..") @@ -78,3 +78,4 @@ def pytest_cmdline_main(config): sys.path.insert(0, "/usr/lib/moulinette/") import yunohost yunohost.init(debug=config.option.yunodebug) + msettings["interface"] = "test" From b0accd506ee99f21c26fa7023fd281d58de1b8d0 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 4 Jan 2021 01:06:19 +0100 Subject: [PATCH 13/14] Report / patch old usage of foo= in install/backup/restore scripts --- src/yunohost/app.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index 625cac9a7..eeb657cdd 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -3138,6 +3138,26 @@ def _patch_legacy_helpers(app_folder): "pattern": r"(Automatic diagnosis data from YunoHost( *\n)*)? *(__\w+__)? *\$\(yunohost tools diagnosis.*\)(__\w+__)?", "replace": r"", "important": False + }, + # Old $1, $2 in backup/restore scripts... + "app=$2": { + "only_for": ["scripts/backup", "scripts/restore"], + "pattern": r"app=\$2", + "replace": r"app=$YNH_APP_INSTANCE_NAME", + "important": True + }, + # Old $1, $2 in backup/restore scripts... + "backup_dir=$1": { + "only_for": ["scripts/backup", "scripts/restore"], + "pattern": r"backup_dir=\$1", + "replace": r"backup_dir=.", + "important": True + }, + # Old $1, $2 in install scripts... + # We ain't patching that shit because it ain't trivial to patch all args... + "domain=$1": { + "only_for": ["scripts/install"], + "important": True } } @@ -3156,6 +3176,11 @@ def _patch_legacy_helpers(app_folder): show_warning = False for helper, infos in stuff_to_replace.items(): + + # Ignore if not relevant for this file + if infos.get("only_for") and not any(filename.endswith(f) for f in infos["only_for"]): + continue + # If helper is used, attempt to patch the file if helper in content and infos["pattern"]: content = infos["pattern"].sub(infos["replace"], content) @@ -3163,11 +3188,11 @@ def _patch_legacy_helpers(app_folder): if infos["important"]: show_warning = True - # If the helpert is *still* in the content, it means that we + # If the helper is *still* in the content, it means that we # couldn't patch the deprecated helper in the previous lines. In # that case, abort the install or whichever step is performed if helper in content and infos["important"]: - raise YunohostError("This app is likely pretty old and uses deprecated / outdated helpers that can't be migrated easily. It can't be installed anymore.") + raise YunohostError("This app is likely pretty old and uses deprecated / outdated helpers that can't be migrated easily. It can't be installed anymore.", raw_msg=True) if replaced_stuff: From 25ed25e6e93bc6ab07e628a55d6a1eca3905057c Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Mon, 4 Jan 2021 03:50:25 +0100 Subject: [PATCH 14/14] Annnnd our legacy app is using restore_dir in restore script... --- src/yunohost/app.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/yunohost/app.py b/src/yunohost/app.py index eeb657cdd..c0408006c 100644 --- a/src/yunohost/app.py +++ b/src/yunohost/app.py @@ -3153,6 +3153,13 @@ def _patch_legacy_helpers(app_folder): "replace": r"backup_dir=.", "important": True }, + # Old $1, $2 in backup/restore scripts... + "restore_dir=$1": { + "only_for": ["scripts/restore"], + "pattern": r"restore_dir=\$1", + "replace": r"restore_dir=.", + "important": True + }, # Old $1, $2 in install scripts... # We ain't patching that shit because it ain't trivial to patch all args... "domain=$1": {