diff --git a/lib/galaxy/main_config.py b/lib/galaxy/main_config.py new file mode 100644 index 00000000000..c1f981ab148 --- /dev/null +++ b/lib/galaxy/main_config.py @@ -0,0 +1,36 @@ +"""Utilities for finding Galaxy's configuration file. + +This is for use by web framework code and scripts (e.g. scripts/galaxy_main.py). +""" +import os + +DEFAULT_INIS = ["config/galaxy.yml", "config/galaxy.ini", "universe_wsgi.ini", "config/galaxy.yml.sample"] +DEFAULT_INI_APP = "main" +DEFAULT_CONFIG_SECTION = "galaxy" + + +def absolute_config_path(path, galaxy_root): + if path and not os.path.isabs(path): + path = os.path.join(galaxy_root, path) + return path + + +def config_is_ini(config_file): + return config_file and (config_file.endswith('.ini') or config_file.endswith('.ini.sample')) + + +def find_config(supplied_config, galaxy_root): + if supplied_config: + return supplied_config + + if galaxy_root is None: + return os.path.abspath('galaxy.yml') + + # If not explicitly supplied an config, check galaxy.ini and then + # just resort to sample if that has not been configured. + for guess in DEFAULT_INIS: + config_path = os.path.join(galaxy_root, guess) + if os.path.exists(config_path): + return config_path + + return guess diff --git a/lib/galaxy/webapps/galaxy/fast_factory.py b/lib/galaxy/webapps/galaxy/fast_factory.py new file mode 100644 index 00000000000..4480c7a397f --- /dev/null +++ b/lib/galaxy/webapps/galaxy/fast_factory.py @@ -0,0 +1,82 @@ +"""Module containing factory class for building uvicorn app for Galaxy. + +Information on uvicorn, its various settings, and how to invoke it can +be found at https://www.uvicorn.org/. + +Galaxy can be launched with uvicorn using the following invocation: + +:: + + uvicorn --app-dir lib --factory galaxy.webapps.galaxy.fast_factory:factory + +Use the environment variable ``GALAXY_CONFIG_FILE`` to specify a Galaxy +configuration file. Galaxy configuration can be loading from a YAML +or an .ini file (reads app:main currently but can be overridden with +GALAXY_CONFIG_SECTION). + +:: + + GALAXY_CONFIG_FILE=config/galaxy.yml uvicorn --app-dir lib --factory galaxy.webapps.galaxy.fast_factory:factory + +.. note:: + + Information on additional ways to configure uvicorn can be found at + https://www.uvicorn.org/. + +.. warning:: + + If an ini file is supplied via GALAXY_CONFIG_FILE, the server properties + such as host and port are not read from the file like older forms of + configuring Galaxy. + +`Gunicorn `__ is a server with +more complex management options. + +This factory function can be executed as a uvicorn worker managed with gunicorn +with the following command-line. + +:: + + gunicorn 'galaxy.webapps.galaxy.fast_factory:factory()' --env GALAXY_CONFIG_FILE=config/galaxy.ini --pythonpath lib -w 4 -k uvicorn.workers.UvicornWorker + +""" +import os + +from galaxy.main_config import ( + absolute_config_path, + config_is_ini, + DEFAULT_CONFIG_SECTION, + DEFAULT_INI_APP, + find_config, +) +from galaxy.web_stack import get_app_kwds +from galaxy.webapps.galaxy.buildapp import app_factory +from .fast_app import initialize_fast_app + + +def factory(): + kwds = get_app_kwds("galaxy", "galaxy") + config_file = kwds.get("config_file") + if not config_file and "GALAXY_CONFIG_FILE" in os.environ: + config_file = os.path.abspath(os.environ["GALAXY_CONFIG_FILE"]) + else: + galaxy_root = kwds.get("galaxy_root") + config_file = find_config(config_file, galaxy_root) + config_file = absolute_config_path(config_file, galaxy_root=galaxy_root) + + if "GALAXY_CONFIG_SECTION" in os.environ: + config_section = os.environ["GALAXY_CONFIG_SECTION"] + elif config_is_ini(config_file): + config_section = "app:%s" % DEFAULT_INI_APP + else: + config_section = DEFAULT_CONFIG_SECTION + + if 'config_file' not in kwds: + kwds['config_file'] = config_file + if 'config_section' not in kwds: + kwds['config_section'] = config_section + global_conf = {} + if config_is_ini(config_file): + global_conf["__file__"] = config_file + gx = app_factory(global_conf=global_conf, load_app_kwds=kwds) + return initialize_fast_app(gx) diff --git a/packages/app/galaxy/main_config.py b/packages/app/galaxy/main_config.py new file mode 120000 index 00000000000..f26b2577893 --- /dev/null +++ b/packages/app/galaxy/main_config.py @@ -0,0 +1 @@ +../../../lib/galaxy/main_config.py \ No newline at end of file diff --git a/scripts/galaxy_main.py b/scripts/galaxy_main.py index cc4cdea7374..c6a49f20bcc 100755 --- a/scripts/galaxy_main.py +++ b/scripts/galaxy_main.py @@ -57,15 +57,18 @@ else: except Exception: log.exception("Failed to add Galaxy to sys.path") raise +from galaxy.main_config import ( + absolute_config_path, + config_is_ini, + DEFAULT_CONFIG_SECTION, + DEFAULT_INI_APP, + find_config, +) from galaxy.util import unicodify from galaxy.web_stack import get_app_kwds REQUIRES_DAEMONIZE_MESSAGE = "Attempted to use Galaxy in daemon mode, but daemonize is unavailable." -DEFAULT_INI_APP = "main" -DEFAULT_CONFIG_SECTION = "galaxy" -DEFAULT_INIS = ["config/galaxy.yml", "config/galaxy.ini", "universe_wsgi.ini", "config/galaxy.yml.sample"] - DEFAULT_PID = "galaxy.pid" DEFAULT_VERBOSE = True DESCRIPTION = "Daemonized entry point for Galaxy." @@ -156,29 +159,6 @@ def app_loop(args, log): raise -def absolute_config_path(path, galaxy_root): - if path and not os.path.isabs(path): - path = os.path.join(galaxy_root, path) - return path - - -def find_config(supplied_config, galaxy_root): - if supplied_config: - return supplied_config - - if galaxy_root is None: - return os.path.abspath('galaxy.yml') - - # If not explicitly supplied an config, check galaxy.ini and then - # just resort to sample if that has not been configured. - for guess in DEFAULT_INIS: - config_path = os.path.join(galaxy_root, guess) - if os.path.exists(config_path): - return config_path - - return guess - - class GalaxyConfigBuilder: """ Generate paste-like configuration from supplied command-line arguments. """ @@ -218,7 +198,7 @@ class GalaxyConfigBuilder: @property def config_is_ini(self): - return self.config_file.endswith('.ini') or self.config_file.endswith('.ini.sample') + return config_is_ini(self.config_file) def app_kwds(self): kwds = get_app_kwds(self.app_name, app_name=self.app_name)