diff --git a/Makefile b/Makefile index 316a4e4b5881ebf33227f5dfefd25703e13576ef..26bc3790417d0dbee0516000de54897ba6f15cc7 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,7 @@ test-install-pypi: bash install_test/test_install.bash test-install-wheel: dist - PULSAR_INSTALL_TARGET=$(shell pwd)/dist/pulsar_app*.whl bash install_test/test_install.bash + PULSAR_INSTALL_TARGET=$(shell pwd)/dist/pulsar_app*.whl bash install_test/test_install_conda.bash coverage: coverage run --source $(SOURCE_DIR) setup.py $(TEST_DIR) diff --git a/install_test/common_functions.bash b/install_test/common_functions.bash index f19745a4634c5a46b63438afb0796e52f67e431d..2d0e8a4cf8aca2c6ef2f6ca7ddba7194d1ace803 100644 --- a/install_test/common_functions.bash +++ b/install_test/common_functions.bash @@ -2,6 +2,7 @@ set -e shopt -s nullglob +PULSAR_TARGET_POORT="${PULSAR_TARGET_POORT:-8913}" PULSAR_INSTALL_TARGET="${PULSAR_INSTALL_TARGET:-pulsar-app}" PLANEMO_INSTALL_TARGET="${PLANEMO_INSTALL_TARGET:-planemo==0.36.1}" @@ -38,9 +39,20 @@ stop_pulsar() { check_pulsar() { cd pulsar + if curl -s "http://localhost:$PULSAR_TARGET_POORT" + then + echo "Port $PULSAR_TARGET_POORT already bound, Pulsar will fail to start." + exit 1; + fi + echo "Starting Pulsar in daemon mode." pulsar --daemon echo "Waiting for Pulsar to start." + while ! curl -s "http://localhost:$PULSAR_TARGET_POORT"; + do + printf "." + sleep 1; + done sleep 2 echo "Running a standalone Pulsar job." pulsar-check # runs a test job diff --git a/install_test/test_install_conda.bash b/install_test/test_install_conda.bash new file mode 100755 index 0000000000000000000000000000000000000000..959e277f86629d14ddd7cd5c9295d1db4c76b81d --- /dev/null +++ b/install_test/test_install_conda.bash @@ -0,0 +1,24 @@ +#!/bin/bash + +set -e + +SCRIPT_DIR="$( cd "$(dirname "$0")" ; pwd )" +. "$SCRIPT_DIR/common_functions.bash" + +init_temp_dir + +init_pulsar + +cd pulsar +echo "Running pulsar-config with --auto_conda" +pulsar-config --auto_conda + +cd .. + +check_pulsar + +init_planemo "conda_testing" + +run_planemo --job_config_file "$SCRIPT_DIR/galaxy_job_conf.xml" test_tools/bwa.xml + +stop_pulsar diff --git a/pulsar/core.py b/pulsar/core.py index e4547d27ec83749b5b9b9fd1eb43ad8506921f35..346dcc38abbec44472eb4c3e30b864079a8392ef 100644 --- a/pulsar/core.py +++ b/pulsar/core.py @@ -124,7 +124,11 @@ class PulsarApp(object): def __setup_dependency_manager(self, conf): dependencies_dir = conf.get("tool_dependency_dir", "dependencies") resolvers_config_file = conf.get("dependency_resolvers_config_file", "dependency_resolvers_conf.xml") - self.dependency_manager = DependencyManager(dependencies_dir, resolvers_config_file) + conda_config = {} + for key, value in conf.items(): + if key.startswith("conda_"): + conda_config[key] = value + self.dependency_manager = DependencyManager(dependencies_dir, resolvers_config_file, **conda_config) def __setup_job_metrics(self, conf): job_metrics = conf.get("job_metrics", None) diff --git a/pulsar/managers/base/__init__.py b/pulsar/managers/base/__init__.py index 513e9f6a27967346cdd98d26f1ec1398ebeebde7..91d275703d3abaeee8d3cc977d922e84641a2432 100644 --- a/pulsar/managers/base/__init__.py +++ b/pulsar/managers/base/__init__.py @@ -176,7 +176,7 @@ class BaseManager(ManagerInterface): else: return listdir(directory_or_none) - def _expand_command_line(self, command_line, dependencies_description): + def _expand_command_line(self, command_line, dependencies_description, job_directory=None): if dependencies_description is None: return command_line @@ -184,7 +184,8 @@ class BaseManager(ManagerInterface): installed_tool_dependencies = dependencies_description.installed_tool_dependencies dependency_commands = self.dependency_manager.dependency_shell_commands( requirements=requirements, - installed_tool_dependencies=installed_tool_dependencies + installed_tool_dependencies=installed_tool_dependencies, + job_directory=job_directory, ) if dependency_commands: command_line = "%s; %s" % ("; ".join(dependency_commands), command_line) diff --git a/pulsar/managers/base/directory.py b/pulsar/managers/base/directory.py index 90308bef5c59c1ab9adb53b09aa1ffcf6486ed61..0463b84c9b0c2ba4de0a091cd2a882418047eece 100644 --- a/pulsar/managers/base/directory.py +++ b/pulsar/managers/base/directory.py @@ -105,7 +105,7 @@ class DirectoryBaseManager(BaseManager): # Helpers methods related to setting up job script files. def _setup_job_file(self, job_id, command_line, dependencies_description=None, env=[]): - command_line = self._expand_command_line(command_line, dependencies_description) + command_line = self._expand_command_line(command_line, dependencies_description, job_directory=self.job_directory(job_id).job_directory) script_env = self._job_template_env(job_id, command_line=command_line, env=env) script = job_script(**script_env) return self._write_job_script(job_id, script) diff --git a/pulsar/managers/queued_cli.py b/pulsar/managers/queued_cli.py index 65fc442c0612890f77b7f0b404d89553454495f4..016cd6c62e81c99389586854155f4be56c6b84e7 100644 --- a/pulsar/managers/queued_cli.py +++ b/pulsar/managers/queued_cli.py @@ -26,7 +26,7 @@ class CliQueueManager(ExternalBaseManager): stdout_path = self._stdout_path(job_id) stderr_path = self._stderr_path(job_id) job_name = self._job_name(job_id) - command_line = self._expand_command_line(command_line, dependencies_description) + command_line = self._expand_command_line(command_line, dependencies_description, job_directory=self.job_directory(job_id).job_directory) job_script_kwargs = self._job_template_env(job_id, command_line=command_line, env=env) extra_kwargs = job_interface.job_script_kwargs(stdout_path, stderr_path, job_name) job_script_kwargs.update(extra_kwargs) diff --git a/pulsar/managers/unqueued.py b/pulsar/managers/unqueued.py index 705b72e1aa0dd18d150cccffb71684d01ee62fee..525215a58391c8881e826d7a5d79302f24343843 100644 --- a/pulsar/managers/unqueued.py +++ b/pulsar/managers/unqueued.py @@ -152,7 +152,7 @@ class Manager(DirectoryBaseManager): if platform.system().lower() == "windows": # TODO: Don't ignore requirements and env without warning. Ideally # process them or at least warn about them being ignored. - command_line = self._expand_command_line(command_line, dependencies_description) + command_line = self._expand_command_line(command_line, dependencies_description, job_directory=self.job_directory(job_id).job_directory) else: command_line = self._setup_job_file(job_id, command_line, dependencies_description=dependencies_description, env=env) return command_line diff --git a/pulsar/scripts/config.py b/pulsar/scripts/config.py index efb7a738e38cc08187ed919eafb265671d4b8123..abde0d7433b4a5f277524a499bb586f9fd733948 100644 --- a/pulsar/scripts/config.py +++ b/pulsar/scripts/config.py @@ -29,6 +29,8 @@ DESCRIPTION = "Initialize a directory with a minimal pulsar config." HELP_DIRECTORY = "Directory containing the configuration files for Pulsar." HELP_MQ = ("Write configuration files for message queue server deployment " "instead of more traditional RESTful web based pulsar.") +HELP_AUTO_CONDA = ("Auto initialize Conda for tool resolution and auto install " + "dependencies on demand.") HELP_NO_LOGGING = ("Do not write Pulsar's default logging configuration to server.ini " "and if uwsgi is configured do not configure its logging either.") HELP_SUPERVISOR = ("Write a supervisord configuration file for " @@ -145,6 +147,10 @@ def main(argv=None): arg_parser.add_argument("--directory", default=".", help=HELP_DIRECTORY) + arg_parser.add_argument("--auto_conda", + action="store_true", + default=False, + help=HELP_AUTO_CONDA) arg_parser.add_argument("--mq", action="store_true", default=False, @@ -198,6 +204,10 @@ def main(argv=None): if not os.path.exists(directory): os.makedirs(directory) + default_dependencies_dir = os.path.join(directory, "dependencies") + if not os.path.exists(default_dependencies_dir): + os.makedirs(default_dependencies_dir) + print("Bootstrapping pulsar configuration into directory %s" % relative_directory) _handle_app_yaml(args, directory) _handle_server_ini(args, directory) @@ -298,6 +308,9 @@ def _handle_app_yaml(args, directory): contents += 'private_token: %s\n' % args.private_token if args.mq: contents += 'message_queue_url: "amqp://guest:guest@localhost:5672//"\n' + if args.auto_conda: + contents += 'conda_auto_init: true\n' + contents += 'conda_auto_install: true\n' else: if not IS_WINDOWS and args.libdrmaa_path: contents += 'manager:\n type: queued_drmaa\n'