Skip to content

Commit

Permalink
Allow serve command to serve daemon Galaxy process.
Browse files Browse the repository at this point in the history
 - Add a ``--daemon`` flag and a ``--pid-file`` option.
 - Refactor API interactions to be slightly higher-level and usable outside planemo.shed.
 - Implement test case for this.
  • Loading branch information
jmchilton committed Apr 13, 2016
1 parent f7554d1 commit 776773c
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 30 deletions.
2 changes: 1 addition & 1 deletion planemo/bioblend.py
Expand Up @@ -12,6 +12,6 @@
"bioblend`")


def ensure_module(mod):
def ensure_module():
if toolshed is None:
raise Exception(BIOBLEND_UNAVAILABLE)
39 changes: 39 additions & 0 deletions planemo/galaxy/api.py
@@ -0,0 +1,39 @@
"""A high-level interface to local Galaxy instances using bioblend."""
from planemo.bioblend import ensure_module
from planemo.bioblend import galaxy

DEFAULT_MASTER_API_KEY = "test_key"


def gi(port, key=None):
"""Return a bioblend ``GalaxyInstance`` for Galaxy on this port."""
ensure_module()
if key is None:
key = DEFAULT_MASTER_API_KEY
return galaxy.GalaxyInstance(
url="http://localhost:%d" % int(port),
key=key
)


def user_api_key(admin_gi):
"""Use an admin authenticated account to generate a user API key."""
ensure_module()
# TODO: thread-safe
users = admin_gi.users
# Allow override with --user_api_key.
user_response = users.create_local_user(
"planemo",
"planemo@galaxyproject.org",
"planemo",
)
user_id = user_response["id"]

return users.create_user_apikey(user_id)


__all__ = [
"DEFAULT_MASTER_API_KEY",
"gi",
"user_api_key",
]
40 changes: 15 additions & 25 deletions planemo/galaxy/config.py
Expand Up @@ -18,6 +18,11 @@
setup_venv,
DOWNLOAD_GALAXY,
)
from .api import (
DEFAULT_MASTER_API_KEY,
gi,
user_api_key,
)
from planemo.conda import build_conda_context
from planemo.io import warn
from planemo.io import shell
Expand All @@ -27,10 +32,6 @@
from planemo.io import wait_on
from planemo import git
from planemo.shed import tool_shed_url
from planemo.bioblend import (
galaxy,
ensure_module,
)


NO_TEST_DATA_MESSAGE = (
Expand Down Expand Up @@ -159,7 +160,7 @@ def config_join(*args):
sheds_config_path = _configure_sheds_config_file(
ctx, config_directory, **kwds
)
master_api_key = kwds.get("master_api_key", "test_key")
master_api_key = kwds.get("master_api_key", DEFAULT_MASTER_API_KEY)
dependency_dir = os.path.join(config_directory, "deps")
preseeded_database = attempt_database_preseed(
galaxy_root,
Expand Down Expand Up @@ -254,8 +255,11 @@ def config_join(*args):
shed_tool_conf_contents = _sub(SHED_TOOL_CONF_TEMPLATE, template_args)
write_file(shed_tool_conf, shed_tool_conf_contents)

pid_file = kwds.get("pid_file") or config_join("galaxy.pid")

yield GalaxyConfig(
galaxy_root,
pid_file,
config_directory,
env,
test_data_dir,
Expand All @@ -274,6 +278,7 @@ class GalaxyConfig(object):
def __init__(
self,
galaxy_root,
pid_file,
config_directory,
env,
test_data_dir,
Expand All @@ -282,6 +287,7 @@ def __init__(
master_api_key,
):
self.galaxy_root = galaxy_root
self._pid_file = pid_file
self.config_directory = config_directory
self.env = env
self.test_data_dir = test_data_dir
Expand All @@ -298,38 +304,22 @@ def kill(self):

@property
def pid_file(self):
return os.path.join(self.galaxy_root, "%s.pid" % self.server_name)
return self._pid_file

@property
def gi(self):
ensure_module(galaxy)
return galaxy.GalaxyInstance(
url="http://localhost:%d" % int(self.port),
key=self.master_api_key
)
return gi(self.port, self.master_api_key)

@property
def user_gi(self):
# TODO: thread-safe
if self._user_api_key is None:
users = self.gi.users
# Allow override with --user_api_key.
user_response = users.create_local_user(
"planemo",
"planemo@galaxyproject.org",
"planemo",
)
user_id = user_response["id"]
self._user_api_key = user_api_key(self.gi)

self._user_api_key = users.create_user_apikey(user_id)
return self._gi_for_key(self._user_api_key)

def _gi_for_key(self, key):
ensure_module(galaxy)
return galaxy.GalaxyInstance(
url="http://localhost:%d" % self.port,
key=key
)
return gi(self.port, key)

def install_repo(self, *args, **kwds):
self.tool_shed_client.install_repository_revision(
Expand Down
3 changes: 2 additions & 1 deletion planemo/galaxy/serve.py
Expand Up @@ -19,12 +19,13 @@ def serve(ctx, paths, **kwds):
kwds["no_cleanup"] = True

with galaxy_config(ctx, paths, **kwds) as config:
pid_file = config.pid_file
# TODO: Allow running dockerized Galaxy here instead.
setup_venv_command = setup_venv(ctx, kwds)
run_script = os.path.join(config.galaxy_root, "run.sh")
run_script += " $COMMON_STARTUP_ARGS"
if daemon:
run_script += " --daemon --wait"
run_script += " --pid-file '%s' --daemon" % pid_file
config.env["GALAXY_RUN_ALL"] = "1"
else:
run_script += " --server-name '%s' --reload" % config.server_name
Expand Down
18 changes: 18 additions & 0 deletions planemo/options.py
Expand Up @@ -674,10 +674,28 @@ def galaxy_target_options():
)


def pid_file_option():
return planemo_option(
"--pid_file",
default=None,
help="Location of pid file is executed with --daemon."
)


def daemon_option():
return planemo_option(
"--daemon",
is_flag=True,
help="Serve Galaxy process as a daemon."
)


def galaxy_serve_options():
return _compose(
galaxy_run_options(),
galaxy_config_options(),
daemon_option(),
pid_file_option(),
)


Expand Down
2 changes: 1 addition & 1 deletion planemo/shed/interface.py
Expand Up @@ -15,7 +15,7 @@


def tool_shed_instance(url, key, email, password):
ensure_module(toolshed)
ensure_module()
tsi = toolshed.ToolShedInstance(
url=url,
key=key,
Expand Down
27 changes: 25 additions & 2 deletions tests/test_cmd_serve.py
Expand Up @@ -3,27 +3,49 @@
import time
import threading

from planemo.galaxy import api

from .test_utils import (
CliTestCase,
skip_if_environ,
TEST_REPOS_DIR,
)
from . import network_util

TEST_HISTORY_NAME = "Cool History 42"


class ServeTestCase(CliTestCase):

@skip_if_environ("PLANEMO_SKIP_GALAXY_TESTS")
def test_serve(self):
port = network_util.get_free_port()
serve = functools.partial(self._run, port)
t = threading.Thread(target=serve)
self._launch_thread_and_wait(serve, port)

@skip_if_environ("PLANEMO_SKIP_GALAXY_TESTS")
def test_serve_daemon(self):
port = network_util.get_free_port()
pid_file = os.path.join(self._home, "test.pid")
extra_args = ["--daemon", "--pid_file", pid_file]
serve = functools.partial(self._run, port, extra_args)
self._launch_thread_and_wait(serve, port)
time.sleep(.1)
assert network_util.wait_net_service("127.0.0.1", port)
admin_gi = api.gi(port)
user_api_key = api.user_api_key(admin_gi)
user_gi = api.gi(port, user_api_key)
assert len(user_gi.histories.get_histories(name=TEST_HISTORY_NAME)) == 0
user_gi.histories.create_history(TEST_HISTORY_NAME)

def _launch_thread_and_wait(self, func, port):
t = threading.Thread(target=func)
t.daemon = True
t.start()
time.sleep(15)
assert network_util.wait_net_service("127.0.0.1", port)

def _run(self, port):
def _run(self, port, serve_args=[]):
cat_path = os.path.join(TEST_REPOS_DIR, "single_tool", "cat.xml")
test_cmd = [
"serve",
Expand All @@ -32,4 +54,5 @@ def _run(self, port):
str(port),
cat_path,
]
test_cmd.extend(serve_args)
self._check_exit_code(test_cmd)

0 comments on commit 776773c

Please sign in to comment.