mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Merge pull request #798 from YunoHost/detect-and-warn-early-about-unavailable-full-domain
[fix] Detect and warn early about unavailable full domains...
This commit is contained in:
commit
ea1fd71def
3 changed files with 62 additions and 6 deletions
|
@ -19,6 +19,7 @@
|
||||||
"app_change_url_no_script": "This application '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.",
|
"app_change_url_no_script": "This application '{app_name:s}' doesn't support URL modification yet. Maybe you should upgrade it.",
|
||||||
"app_change_url_success": "{app:s} URL is now {domain:s}{path:s}",
|
"app_change_url_success": "{app:s} URL is now {domain:s}{path:s}",
|
||||||
"app_extraction_failed": "Could not extract the installation files",
|
"app_extraction_failed": "Could not extract the installation files",
|
||||||
|
"app_full_domain_unavailable": "Sorry, this application requires a full domain to be installed on, but some other apps are already installed on domain '{domain}'. One possible solution is to add and use a subdomain dedicated to this application instead.",
|
||||||
"app_id_invalid": "Invalid app ID",
|
"app_id_invalid": "Invalid app ID",
|
||||||
"app_incompatible": "The app {app} is incompatible with your YunoHost version",
|
"app_incompatible": "The app {app} is incompatible with your YunoHost version",
|
||||||
"app_install_files_invalid": "These files cannot be installed",
|
"app_install_files_invalid": "These files cannot be installed",
|
||||||
|
|
|
@ -862,6 +862,9 @@ def app_install(operation_logger, app, label=None, args=None, no_remove_on_failu
|
||||||
args_list = [ value[0] for value in args_odict.values() ]
|
args_list = [ value[0] for value in args_odict.values() ]
|
||||||
args_list.append(app_instance_name)
|
args_list.append(app_instance_name)
|
||||||
|
|
||||||
|
# Validate domain / path availability for webapps
|
||||||
|
_validate_and_normalize_webpath(manifest, args_odict, extracted_app_folder)
|
||||||
|
|
||||||
# Prepare env. var. to pass to script
|
# Prepare env. var. to pass to script
|
||||||
env_dict = _make_environment_dict(args_odict)
|
env_dict = _make_environment_dict(args_odict)
|
||||||
env_dict["YNH_APP_ID"] = app_id
|
env_dict["YNH_APP_ID"] = app_id
|
||||||
|
@ -2554,8 +2557,7 @@ def _parse_args_for_action(action, args={}):
|
||||||
def _parse_args_in_yunohost_format(args, action_args):
|
def _parse_args_in_yunohost_format(args, action_args):
|
||||||
"""Parse arguments store in either manifest.json or actions.json
|
"""Parse arguments store in either manifest.json or actions.json
|
||||||
"""
|
"""
|
||||||
from yunohost.domain import (domain_list, _get_maindomain,
|
from yunohost.domain import domain_list, _get_maindomain
|
||||||
_get_conflicting_apps, _normalize_domain_path)
|
|
||||||
from yunohost.user import user_info, user_list
|
from yunohost.user import user_info, user_list
|
||||||
|
|
||||||
args_dict = OrderedDict()
|
args_dict = OrderedDict()
|
||||||
|
@ -2673,13 +2675,18 @@ def _parse_args_in_yunohost_format(args, action_args):
|
||||||
assert_password_is_strong_enough('user', arg_value)
|
assert_password_is_strong_enough('user', arg_value)
|
||||||
args_dict[arg_name] = (arg_value, arg_type)
|
args_dict[arg_name] = (arg_value, arg_type)
|
||||||
|
|
||||||
# END loop over action_args...
|
return args_dict
|
||||||
|
|
||||||
|
|
||||||
|
def _validate_and_normalize_webpath(manifest, args_dict, app_folder):
|
||||||
|
|
||||||
|
from yunohost.domain import _get_conflicting_apps, _normalize_domain_path
|
||||||
|
|
||||||
# If there's only one "domain" and "path", validate that domain/path
|
# If there's only one "domain" and "path", validate that domain/path
|
||||||
# is an available url and normalize the path.
|
# is an available url and normalize the path.
|
||||||
|
|
||||||
domain_args = [ (name, value[0]) for name, value in args_dict.items() if value[1] == "domain" ]
|
domain_args = [(name, value[0]) for name, value in args_dict.items() if value[1] == "domain"]
|
||||||
path_args = [ (name, value[0]) for name, value in args_dict.items() if value[1] == "path" ]
|
path_args = [(name, value[0]) for name, value in args_dict.items() if value[1] == "path"]
|
||||||
|
|
||||||
if len(domain_args) == 1 and len(path_args) == 1:
|
if len(domain_args) == 1 and len(path_args) == 1:
|
||||||
|
|
||||||
|
@ -2705,7 +2712,26 @@ def _parse_args_in_yunohost_format(args, action_args):
|
||||||
# standard path format to deal with no matter what the user inputted)
|
# standard path format to deal with no matter what the user inputted)
|
||||||
args_dict[path_args[0][0]] = (path, "path")
|
args_dict[path_args[0][0]] = (path, "path")
|
||||||
|
|
||||||
return args_dict
|
# This is likely to be a full-domain app...
|
||||||
|
elif len(domain_args) == 1 and len(path_args) == 0:
|
||||||
|
|
||||||
|
# Confirm that this is a full-domain app This should cover most cases
|
||||||
|
# ... though anyway the proper solution is to implement some mechanism
|
||||||
|
# in the manifest for app to declare that they require a full domain
|
||||||
|
# (among other thing) so that we can dynamically check/display this
|
||||||
|
# requirement on the webadmin form and not miserably fail at submit time
|
||||||
|
|
||||||
|
# Full-domain apps typically declare something like path_url="/" or path=/
|
||||||
|
# and use ynh_webpath_register or yunohost_app_checkurl inside the install script
|
||||||
|
install_script_content = open(os.path.join(app_folder, 'scripts/install')).read()
|
||||||
|
|
||||||
|
if re.search(r"\npath(_url)?=[\"']?/[\"']?\n", install_script_content) \
|
||||||
|
and re.search(r"(ynh_webpath_register|yunohost app checkurl)", install_script_content):
|
||||||
|
|
||||||
|
domain = domain_args[0][1]
|
||||||
|
conflicts = _get_conflicting_apps(domain, "/")
|
||||||
|
|
||||||
|
raise YunohostError('app_full_domain_unavailable', domain=domain)
|
||||||
|
|
||||||
|
|
||||||
def _make_environment_dict(args_dict, prefix="APP_ARG_"):
|
def _make_environment_dict(args_dict, prefix="APP_ARG_"):
|
||||||
|
|
|
@ -36,16 +36,22 @@ def clean():
|
||||||
if _is_installed("legacy_app"):
|
if _is_installed("legacy_app"):
|
||||||
app_remove("legacy_app")
|
app_remove("legacy_app")
|
||||||
|
|
||||||
|
if _is_installed("full_domain_app"):
|
||||||
|
app_remove("full_domain_app")
|
||||||
|
|
||||||
to_remove = []
|
to_remove = []
|
||||||
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*legacy*")
|
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*legacy*")
|
||||||
|
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*full_domain*")
|
||||||
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*break_yo_system*")
|
to_remove += glob.glob("/etc/nginx/conf.d/*.d/*break_yo_system*")
|
||||||
for filepath in to_remove:
|
for filepath in to_remove:
|
||||||
os.remove(filepath)
|
os.remove(filepath)
|
||||||
|
|
||||||
to_remove = []
|
to_remove = []
|
||||||
to_remove += glob.glob("/etc/yunohost/apps/*legacy_app*")
|
to_remove += glob.glob("/etc/yunohost/apps/*legacy_app*")
|
||||||
|
to_remove += glob.glob("/etc/yunohost/apps/*full_domain_app*")
|
||||||
to_remove += glob.glob("/etc/yunohost/apps/*break_yo_system*")
|
to_remove += glob.glob("/etc/yunohost/apps/*break_yo_system*")
|
||||||
to_remove += glob.glob("/var/www/*legacy*")
|
to_remove += glob.glob("/var/www/*legacy*")
|
||||||
|
to_remove += glob.glob("/var/www/*full_domain*")
|
||||||
for folderpath in to_remove:
|
for folderpath in to_remove:
|
||||||
shutil.rmtree(folderpath, ignore_errors=True)
|
shutil.rmtree(folderpath, ignore_errors=True)
|
||||||
|
|
||||||
|
@ -120,6 +126,13 @@ def install_legacy_app(domain, path):
|
||||||
force=True)
|
force=True)
|
||||||
|
|
||||||
|
|
||||||
|
def install_full_domain_app(domain):
|
||||||
|
|
||||||
|
app_install("./tests/apps/full_domain_app_ynh",
|
||||||
|
args="domain=%s" % domain,
|
||||||
|
force=True)
|
||||||
|
|
||||||
|
|
||||||
def install_break_yo_system(domain, breakwhat):
|
def install_break_yo_system(domain, breakwhat):
|
||||||
|
|
||||||
app_install("./tests/apps/break_yo_system_ynh",
|
app_install("./tests/apps/break_yo_system_ynh",
|
||||||
|
@ -272,6 +285,22 @@ def test_legacy_app_failed_remove(secondary_domain):
|
||||||
assert app_is_not_installed(secondary_domain, "legacy")
|
assert app_is_not_installed(secondary_domain, "legacy")
|
||||||
|
|
||||||
|
|
||||||
|
def test_full_domain_app(secondary_domain):
|
||||||
|
|
||||||
|
install_full_domain_app(secondary_domain)
|
||||||
|
|
||||||
|
assert app_is_exposed_on_http(secondary_domain, "/", "This is a dummy app")
|
||||||
|
|
||||||
|
|
||||||
|
def test_full_domain_app_with_conflicts(secondary_domain):
|
||||||
|
|
||||||
|
install_legacy_app(secondary_domain, "/legacy")
|
||||||
|
|
||||||
|
# TODO : once #808 is merged, add test that the message raised is 'app_full_domain_unavailable'
|
||||||
|
with pytest.raises(YunohostError):
|
||||||
|
install_full_domain_app(secondary_domain)
|
||||||
|
|
||||||
|
|
||||||
def test_systemfuckedup_during_app_install(secondary_domain):
|
def test_systemfuckedup_during_app_install(secondary_domain):
|
||||||
|
|
||||||
with pytest.raises(YunohostError):
|
with pytest.raises(YunohostError):
|
||||||
|
|
Loading…
Add table
Reference in a new issue