mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[enh] Allow applications to ship a script to change its url (#185)
* [enh] add app_change_url * [fix] avoid unecessary io and reuse already existing variable * [fix] bad comment * [fix] another bad comment * [fix] I need to be able to call yunohost during change_url scripts * [mod] global variables are now uppercased * [mod] compress condition * [enh] don't change_url if old/new domain_path are identical * [mod] i18n * [enh] ensure that nginx doesn't failed at the end of change_url * [fix] forgot to call this damn m18n * [mod] m18n * [enh] ask and requires new domain/path for change_url * [fix] missing translation key * [mod] ordering * [mod] lisibility * [enh] avoid common mistakes * [fix] check_output is annoying * [fix] locale: typo. * Adding changeurl unit test draft * [mod] remove useless imports * [mod] style * [mod] change_url -> changeurl * Moving comment about checkurl near checkurl call * Normalize new path and domain format * Adding test about trying to changeurl to same url * Internationalizing change app success message * Removing 'trimed' stuff * Moving check for change_url script at beginning of function * Use _run_service_command to reload nginx * Changing changeurl back to change-url, gomennasai :s
This commit is contained in:
parent
7718ed6000
commit
1516f48699
4 changed files with 191 additions and 1 deletions
|
@ -544,6 +544,31 @@ app:
|
|||
full: --file
|
||||
help: Folder or tarball for upgrade
|
||||
|
||||
### app_change_url()
|
||||
change-url:
|
||||
action_help: Change app's URL
|
||||
api: PUT /apps/<app>/changeurl
|
||||
configuration:
|
||||
authenticate: all
|
||||
authenticator: ldap-anonymous
|
||||
lock: false
|
||||
arguments:
|
||||
app:
|
||||
help: Target app instance name
|
||||
-d:
|
||||
full: --domain
|
||||
help: New app domain on which the application will be moved
|
||||
extra:
|
||||
ask: ask_main_domain
|
||||
pattern: *pattern_domain
|
||||
required: True
|
||||
-p:
|
||||
full: --path
|
||||
help: New path at which the application will be moved
|
||||
extra:
|
||||
ask: ask_path
|
||||
required: True
|
||||
|
||||
### app_setting()
|
||||
setting:
|
||||
action_help: Set or get an app setting value
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
"app_argument_choice_invalid": "Invalid choice for argument '{name:s}', it must be one of {choices:s}",
|
||||
"app_argument_invalid": "Invalid value for argument '{name:s}': {error:s}",
|
||||
"app_argument_required": "Argument '{name:s}' is required",
|
||||
"app_change_no_change_url_script": "The application {app_name:s} doesn't support changing it's URL yet, you might need to upgrade it.",
|
||||
"app_change_url_failed_nginx_reload": "Failed to reload nginx. Here is the output of 'nginx -t':\n{nginx_errors:s}",
|
||||
"app_change_url_identical_domains": "The old and new domain/url_path are identical ('{domain:s}{path:s}'), nothing to do.",
|
||||
"app_change_url_no_script": "This application '{app_name:s}' doesn't support url modification yet. Maybe you should upgrade the application.",
|
||||
"app_change_url_success": "Successfully changed {app:s} url to {domain:s}{path:s}",
|
||||
"app_extraction_failed": "Unable to extract installation files",
|
||||
"app_id_invalid": "Invalid app id",
|
||||
"app_incompatible": "The app is incompatible with your YunoHost version",
|
||||
|
|
|
@ -41,7 +41,7 @@ from collections import OrderedDict
|
|||
from moulinette.core import MoulinetteError
|
||||
from moulinette.utils.log import getActionLogger
|
||||
|
||||
from yunohost.service import service_log
|
||||
from yunohost.service import service_log, _run_service_command
|
||||
from yunohost.utils import packages
|
||||
|
||||
logger = getActionLogger('yunohost.app')
|
||||
|
@ -419,6 +419,105 @@ def app_map(app=None, raw=False, user=None):
|
|||
return result
|
||||
|
||||
|
||||
def app_change_url(auth, app, domain, path):
|
||||
"""
|
||||
Modify the URL at which an application is installed.
|
||||
|
||||
Keyword argument:
|
||||
app -- Taget app instance name
|
||||
domain -- New app domain on which the application will be moved
|
||||
path -- New path at which the application will be move
|
||||
|
||||
"""
|
||||
from yunohost.hook import hook_exec
|
||||
|
||||
installed = _is_installed(app)
|
||||
if not installed:
|
||||
raise MoulinetteError(errno.ENOPKG,
|
||||
m18n.n('app_not_installed', app=app))
|
||||
|
||||
if not os.path.exists(os.path.join(APPS_SETTING_PATH, app, "scripts", "change_url")):
|
||||
raise MoulinetteError(errno.EINVAL, m18n.n("app_change_no_change_url_script", app_name=app))
|
||||
|
||||
old_domain = app_setting(app, "domain")
|
||||
old_path = app_setting(app, "path")
|
||||
|
||||
# Normalize path and domain format
|
||||
domain = domain.strip().lower()
|
||||
old_path = '/' + old_path.strip("/").strip() + '/'
|
||||
path = '/' + path.strip("/").strip() + '/'
|
||||
|
||||
if (domain, path) == (old_domain, old_path):
|
||||
raise MoulinetteError(errno.EINVAL, m18n.n("app_change_url_identical_domains", domain=domain, path=path))
|
||||
|
||||
# WARNING / FIXME : checkurl will modify the settings
|
||||
# (this is a non intuitive behavior that should be changed)
|
||||
# (or checkurl renamed in reserve_url)
|
||||
app_checkurl(auth, '%s%s' % (domain, path), app)
|
||||
|
||||
manifest = json.load(open(os.path.join(APPS_SETTING_PATH, app, "manifest.json")))
|
||||
|
||||
# Retrieve arguments list for change_url script
|
||||
# TODO: Allow to specify arguments
|
||||
args_odict = _parse_args_from_manifest(manifest, 'change_url', auth=auth)
|
||||
args_list = args_odict.values()
|
||||
args_list.append(app)
|
||||
|
||||
# Prepare env. var. to pass to script
|
||||
env_dict = _make_environment_dict(args_odict)
|
||||
app_id, app_instance_nb = _parse_app_instance_name(app)
|
||||
env_dict["YNH_APP_ID"] = app_id
|
||||
env_dict["YNH_APP_INSTANCE_NAME"] = app
|
||||
env_dict["YNH_APP_INSTANCE_NUMBER"] = str(app_instance_nb)
|
||||
|
||||
env_dict["YNH_APP_OLD_DOMAIN"] = old_domain
|
||||
env_dict["YNH_APP_OLD_PATH"] = old_path.rstrip("/")
|
||||
env_dict["YNH_APP_NEW_DOMAIN"] = domain
|
||||
env_dict["YNH_APP_NEW_PATH"] = path.rstrip("/")
|
||||
|
||||
if os.path.exists(os.path.join(APP_TMP_FOLDER, "scripts")):
|
||||
shutil.rmtree(os.path.join(APP_TMP_FOLDER, "scripts"))
|
||||
|
||||
shutil.copytree(os.path.join(APPS_SETTING_PATH, app, "scripts"),
|
||||
os.path.join(APP_TMP_FOLDER, "scripts"))
|
||||
|
||||
# Execute App change_url script
|
||||
os.system('chown -R admin: %s' % INSTALL_TMP)
|
||||
os.system('chmod +x %s' % os.path.join(os.path.join(APP_TMP_FOLDER, "scripts")))
|
||||
os.system('chmod +x %s' % os.path.join(os.path.join(APP_TMP_FOLDER, "scripts", "change_url")))
|
||||
|
||||
# XXX journal
|
||||
if hook_exec(os.path.join(APP_TMP_FOLDER, 'scripts/change_url'), args=args_list, env=env_dict) != 0:
|
||||
logger.error("Failed to change '%s' url." % app)
|
||||
|
||||
# restore values modified by app_checkurl
|
||||
# see begining of the function
|
||||
app_setting(app, "domain", value=old_domain)
|
||||
app_setting(app, "path", value=old_path)
|
||||
|
||||
return
|
||||
|
||||
# this should idealy be done in the change_url script but let's avoid common mistakes
|
||||
app_setting(app, 'domain', value=domain)
|
||||
app_setting(app, 'path', value=path)
|
||||
|
||||
app_ssowatconf(auth)
|
||||
|
||||
# avoid common mistakes
|
||||
if _run_service_command("reload", "nginx") == False:
|
||||
# grab nginx errors
|
||||
# the "exit 0" is here to avoid check_output to fail because 'nginx -t'
|
||||
# will return != 0 since we are in a failed state
|
||||
nginx_errors = subprocess.check_output("nginx -t; exit 0",
|
||||
stderr=subprocess.STDOUT,
|
||||
shell=True).rstrip()
|
||||
|
||||
raise MoulinetteError(errno.EINVAL, m18n.n("app_change_url_failed_nginx_reload", nginx_errors=nginx_errors))
|
||||
|
||||
logger.success(m18n.n("app_change_url_success",
|
||||
app=app, domain=domain, path=path))
|
||||
|
||||
|
||||
def app_upgrade(auth, app=[], url=None, file=None):
|
||||
"""
|
||||
Upgrade app
|
||||
|
|
61
src/yunohost/tests/test_changeurl.py
Normal file
61
src/yunohost/tests/test_changeurl.py
Normal file
|
@ -0,0 +1,61 @@
|
|||
import pytest
|
||||
import time
|
||||
import requests
|
||||
|
||||
from moulinette.core import init_authenticator
|
||||
from yunohost.app import app_install, app_change_url, app_remove, app_map
|
||||
from yunohost.domain import _get_maindomain
|
||||
|
||||
from moulinette.core import MoulinetteError
|
||||
|
||||
# Instantiate LDAP Authenticator
|
||||
AUTH_IDENTIFIER = ('ldap', 'ldap-anonymous')
|
||||
AUTH_PARAMETERS = {'uri': 'ldap://localhost:389', 'base_dn': 'dc=yunohost,dc=org'}
|
||||
|
||||
auth = init_authenticator(AUTH_IDENTIFIER, AUTH_PARAMETERS)
|
||||
|
||||
# Get main domain
|
||||
maindomain = _get_maindomain()
|
||||
|
||||
|
||||
def setup_function(function):
|
||||
pass
|
||||
|
||||
|
||||
def teardown_function(function):
|
||||
app_remove(auth, "change_url_app")
|
||||
|
||||
|
||||
def install_changeurl_app(path):
|
||||
app_install(auth, "./tests/apps/change_url_app_ynh",
|
||||
args="domain=%s&path=%s" % (maindomain, path))
|
||||
|
||||
|
||||
def check_changeurl_app(path):
|
||||
appmap = app_map(raw=True)
|
||||
|
||||
assert path + "/" in appmap[maindomain].keys()
|
||||
|
||||
assert appmap[maindomain][path + "/"]["id"] == "change_url_app"
|
||||
|
||||
r = requests.get("https://%s%s/" % (maindomain, path))
|
||||
assert r.status_code == 200
|
||||
|
||||
|
||||
def test_appchangeurl():
|
||||
install_changeurl_app("/changeurl")
|
||||
check_changeurl_app("/changeurl")
|
||||
|
||||
app_change_url(auth, "change_url_app", maindomain, "/newchangeurl")
|
||||
|
||||
# For some reason the nginx reload can take some time to propagate ...?
|
||||
time.sleep(2)
|
||||
|
||||
check_changeurl_app("/newchangeurl")
|
||||
|
||||
def test_appchangeurl_sameurl():
|
||||
install_changeurl_app("/changeurl")
|
||||
check_changeurl_app("/changeurl")
|
||||
|
||||
with pytest.raises(MoulinetteError):
|
||||
app_change_url(auth, "change_url_app", maindomain, "changeurl")
|
Loading…
Add table
Reference in a new issue