diff --git a/.gitignore b/.gitignore index e7f0bfe..3d856f4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ tmp .images images/test-install/requirements.txt biobox_verify +.biobox_tmp # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/biobox_cli/assets/login_parameters.yml b/biobox_cli/assets/login_parameters.yml index 0e38efc..1126176 100644 --- a/biobox_cli/assets/login_parameters.yml +++ b/biobox_cli/assets/login_parameters.yml @@ -1,2 +1,17 @@ --- -short_read_assembler: "params" +short_read_assembler: + - /bbx/output: + - /bbx/input: + - type: path + src: genome_paired_reads.fq.gz + dst: reads.fq.gz + - type: literal + dst: biobox.yaml + src: | + version: 0.9.0 + arguments: + - fastq: + - value: /bbx/input/reads.fq.gz + type: paired + id: 0 + diff --git a/biobox_cli/command/login.py b/biobox_cli/command/login.py index b0dad74..4964eb4 100644 --- a/biobox_cli/command/login.py +++ b/biobox_cli/command/login.py @@ -14,12 +14,17 @@ """ import yaml +import os.path +import shutil import biobox_cli.util.misc as util import biobox_cli.util.assets as asset import biobox_cli.util.error as error import biobox_cli.container as docker +TEMPORARY_DIRECTORY = '.biobox_tmp' + + def get_login_parameters(biobox_type): """ Determines if the biobox type is currently supported for login. Returns @@ -33,18 +38,22 @@ def get_login_parameters(biobox_type): def create_login_file(dir_, params): - from os.path import join - from shutil import copyfile - is_literal = params['type'] == 'literal' - dst = join(dir_, params['dst']) + dst = os.path.join(dir_, params['dst']) if is_literal: with open(dst, 'w') as f: f.write(params['src']) else: src = asset.get_data_file_path(params['src']) - copyfile(src, dst) + shutil.copyfile(src, dst) + + +def create_login_volume((dir_name, files)): + src = util.mkdir_p(os.path.join(TEMPORARY_DIRECTORY, dir_name.strip("/"))) + for f in files: + create_login_file(src, f) + return docker.mount_string(src, dir_name, False) def run(argv): @@ -55,14 +64,14 @@ def run(argv): tty = not "--no-tty" in opts[""] remove = not "--no-rm" in opts[""] + docker.exit_if_no_image_available(image) + params = get_login_parameters(biobox_type) if params is None: error.err_exit("unknown_command", {"command_type" : "biobox type", "command" : biobox_type}) - - docker.exit_if_no_image_available(image) - - ctnr = docker.create_tty(image, tty) + volumes = map(create_login_volume, params) + ctnr = docker.create_tty(image, tty, volumes) docker.login(ctnr) if remove: diff --git a/biobox_cli/container.py b/biobox_cli/container.py index 5ce46c9..9a055d9 100644 --- a/biobox_cli/container.py +++ b/biobox_cli/container.py @@ -38,6 +38,9 @@ def mount_string(host_dir, container_dir, read_only = True): def output_directory_mount_string(directory): return mount_string(directory, "/bbx/output", False) +def input_directory_mount_string(directory): + return mount_string(directory, "/bbx/input", True) + def biobox_file_mount_string(directory): return mount_string(directory, "/bbx/input") diff --git a/biobox_cli/util/misc.py b/biobox_cli/util/misc.py index 4431ab5..596520a 100644 --- a/biobox_cli/util/misc.py +++ b/biobox_cli/util/misc.py @@ -1,4 +1,5 @@ import sys +import os.path import biobox_cli.util.error as error def select_module(module, name): @@ -20,3 +21,14 @@ def parse_docopt(doc, argv, is_main_module): argv = argv, version = __version__, options_first = is_main_module) + +# http://stackoverflow.com/a/600612 +def mkdir_p(path): + import os, errno + try: + os.makedirs(path) + except OSError as exc: # Python >2.5 + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: raise + return os.path.abspath(path) diff --git a/features/login.feature b/features/login.feature index 923a1f0..9832ed4 100644 --- a/features/login.feature +++ b/features/login.feature @@ -18,3 +18,4 @@ Feature: Allow a user to ssh into an image to test internally input: biobox.yaml reads.fq.gz """ + And the directory ".biobox_tmp" should not exist diff --git a/test/helper.py b/test/helper.py index 921e5b0..7829bb6 100644 --- a/test/helper.py +++ b/test/helper.py @@ -1,4 +1,5 @@ -import os +import os, os.path +import nose.tools as nose import biobox_cli.container as ctn def project_root(): @@ -10,3 +11,12 @@ def is_ci_server(): def remove_container(container): if not is_ci_server(): ctn.remove(container) + +def assert_file_not_empty(file_): + file_size = os.stat(file_).st_size + nose.assert_not_equal(file_size, 0, + "File should not be empty but is: {}".format(file_)) + +def assert_file_contents_equal(file_, contents): + with open(file_, 'r') as f: + nose.assert_equal(f.read(), contents) diff --git a/test/test_login.py b/test/test_login.py index 0f16043..4a9f7a9 100644 --- a/test/test_login.py +++ b/test/test_login.py @@ -3,24 +3,42 @@ import helper as hlpr import tempfile as tmp -from os.path import join -from os import stat +import os.path +import shutil def test_get_login_parameters_with_unknown_type(): nose.assert_equal(None, login.get_login_parameters('unknown')) + +TMP_DIR = tmp.mkdtemp() +TMP_FILE_NAME = 'tmp_file' +TMP_PATH = os.path.join(TMP_DIR, TMP_FILE_NAME) + +def rm_tmp_file(): + if os.path.exists(TMP_PATH): + os.remove(TMP_PATH) + +def rm_tmp_login_dir(): + shutil.rmtree(login.TEMPORARY_DIRECTORY) + +@nose.with_setup(teardown = rm_tmp_file) def test_create_login_file_literal(): - file_name = 'file_name' - value = {'type': 'literal', 'src': 'literal_string', 'dst': file_name} - directory = tmp.mkdtemp() - login.create_login_file(directory, value) - with open(join(directory, file_name)) as f: - nose.assert_equal('literal_string', f.read()) + value = {'type': 'literal', 'src': 'literal_string', 'dst': TMP_FILE_NAME} + login.create_login_file(TMP_DIR, value) + hlpr.assert_file_contents_equal(TMP_PATH, 'literal_string') +@nose.with_setup(teardown = rm_tmp_file) def test_create_login_file_path(): - file_name = 'file_name' - value = {'type': 'path', 'src': 'genome_paired_reads.fq.gz', 'dst': file_name} - directory = tmp.mkdtemp() - login.create_login_file(directory, value) - file_size = stat(join(directory, file_name)).st_size - nose.assert_not_equal(file_size, 0) + value = {'type': 'path', 'src': 'genome_paired_reads.fq.gz', 'dst': TMP_FILE_NAME} + login.create_login_file(TMP_DIR, value) + hlpr.assert_file_not_empty(TMP_PATH) + +@nose.with_setup(teardown = rm_tmp_login_dir) +def test_create_login_volume(): + dst_dir = '/bbx/input' + value = [dst_dir, [{'type': 'literal', 'src': 'literal_string', 'dst': TMP_FILE_NAME}]] + volume = login.create_login_volume(value) + dir_path = os.path.join(login.TEMPORARY_DIRECTORY, dst_dir.strip("/")) + hlpr.assert_file_not_empty(os.path.join(dir_path, TMP_FILE_NAME)) + hlpr.assert_file_contents_equal(os.path.join(dir_path, TMP_FILE_NAME), 'literal_string') + nose.assert_in(':'.join([dir_path, dst_dir, 'rw']), volume)