Skip to content

Commit

Permalink
Merge 55a1c2f into 3dfe33e
Browse files Browse the repository at this point in the history
  • Loading branch information
shabazpatel committed Jul 24, 2018
2 parents 3dfe33e + 55a1c2f commit d359c79
Show file tree
Hide file tree
Showing 13 changed files with 277 additions and 19 deletions.
2 changes: 0 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ more granular control and workflow integration.
Requirements
------------

- `openssl <https://github.com/openssl/openssl/blob/master/INSTALL>`__
- `git <https://git-scm.com/book/en/v2/Getting-Started-Installing-Git>`__
- `docker <https://docs.docker.com/engine/installation/>`__

Installation
Expand Down
6 changes: 3 additions & 3 deletions datmo/cli/command/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def setup(self, **kwargs):
# TODO: remove business logic from here and create common helper
# environment types
environment_types = self.environment_controller.get_environment_types()
if not environment_type or environment_type not in environment_types:
if environment_types and environment_type not in environment_types:
environment_type = self.cli_helper.prompt_available_options(
environment_types, option_type="type")
# environment frameworks
Expand All @@ -37,13 +37,13 @@ def setup(self, **kwargs):
available_frameworks = [
item[0] for item in available_framework_details
]
if not environment_framework or environment_framework not in available_frameworks:
if available_frameworks and environment_framework not in available_frameworks:
environment_framework = self.cli_helper.prompt_available_options(
available_framework_details, option_type="framework")
# environment languages
available_environment_languages = self.environment_controller.get_supported_languages(
environment_type, environment_framework)
if available_environment_languages and not environment_language or environment_language not in available_environment_languages:
if available_environment_languages and environment_language not in available_environment_languages:
environment_language = self.cli_helper.prompt_available_options(
available_environment_languages, option_type="language")
try:
Expand Down
3 changes: 2 additions & 1 deletion datmo/cli/command/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ def rerun(self, **kwargs):
"ports": task_obj.ports,
"interactive": task_obj.interactive,
"mem_limit": task_obj.mem_limit,
"command_list": command
"command_list": command,
"workspace": task_obj.workspace
}
# Run task and return Task object result
new_task_obj = self.task_run_helper(task_dict, snapshot_dict,
Expand Down
48 changes: 42 additions & 6 deletions datmo/cli/command/tests/test_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import glob
import time
import pytest
import uuid
import tempfile
import shutil
Expand Down Expand Up @@ -138,6 +139,19 @@ def dummy(self):
assert "FROM datmo/data-analytics:cpu-py27" in open(
definition_filepath, "r").read()

# Test success with correct prompt input using numbers
self.environment_command.parse(["environment", "setup"])

@self.environment_command.cli_helper.input(
"cpu\ncaffe2\n")
def dummy(self):
return self.environment_command.execute()
result = dummy(self)
assert result
assert os.path.isfile(definition_filepath)
assert "FROM datmo/caffe2:cpu" in open(
definition_filepath, "r").read()

# Test success with correct prompt input using string
self.environment_command.parse(["environment", "setup"])

Expand Down Expand Up @@ -166,16 +180,38 @@ def dummy(self):
# Test with prompt input string incorrect
self.environment_command.parse(["environment", "setup"])

@self.environment_command.cli_helper.input("random\n\n\n")
# quit at environment type
@self.environment_command.cli_helper.input("quit\n")
def dummy(self):
return self.environment_command.execute()

result = dummy(self)
with pytest.raises(SystemExit) as pytest_wrapped_e:
dummy(self)

assert result
assert os.path.isfile(definition_filepath)
assert "FROM datmo/python-base:cpu-py27" in open(
definition_filepath, "r").read()
assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0

# quit at environment framework
@self.environment_command.cli_helper.input("\nquit\n")
def dummy(self):
return self.environment_command.execute()

with pytest.raises(SystemExit) as pytest_wrapped_e:
dummy(self)

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0

# quit at environment language
@self.environment_command.cli_helper.input("\n\nquit\n")
def dummy(self):
return self.environment_command.execute()

with pytest.raises(SystemExit) as pytest_wrapped_e:
dummy(self)

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0

def test_environment_create(self):
# 1) Environment definition file in project environment directory (with name / description)
Expand Down
4 changes: 2 additions & 2 deletions datmo/cli/command/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def notebook(self, **kwargs):
"mem_limit": kwargs["mem_limit"],
"workspace": "notebook"
}

self.cli_helper.echo(__("info", "cli.workspace.run.notebook"))
# Run task and return Task object result
return self.task_run_helper(task_dict, snapshot_dict,
"cli.workspace.notebook")
Expand All @@ -52,7 +52,7 @@ def jupyterlab(self, **kwargs):
"mem_limit": kwargs["mem_limit"],
"workspace": "jupyterlab"
}

self.cli_helper.echo(__("info", "cli.workspace.run.jupyterlab"))
# Run task and return Task object result
return self.task_run_helper(task_dict, snapshot_dict,
"cli.workspace.jupyterlab")
Expand Down
7 changes: 7 additions & 0 deletions datmo/cli/driver/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ def get_command_choices(self):

def prompt_available_options(self, available_options, option_type):
"""Prompt user to choose an available environment. Returns the environment name"""
# If there are no options
if not available_options:
return None
# If there exists list of options
if option_type == "framework":
available_options_info = available_options
available_options = []
Expand All @@ -171,6 +175,9 @@ def prompt_available_options(self, available_options, option_type):
option_environment_index = None
valid_option = False
while input_environment_option is not None and not valid_option:
# exit when user wants to quit
if input_environment_option in ["q", "quit"]:
sys.exit(0)
try:
option_environment_index = int(input_environment_option)
if 0 < option_environment_index <= len(available_options):
Expand Down
74 changes: 74 additions & 0 deletions datmo/cli/driver/tests/test_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import os
import sys
import pytest
import tempfile
import platform
try:
Expand Down Expand Up @@ -175,6 +176,79 @@ def dummy():
i = dummy()
assert i == False

def test_prompt_available_options(self):

# Setting up environment type
available_options = ["cpu", "gpu"]
option_type = "type"

@self.cli.input("cpu\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "cpu"

@self.cli.input("\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "cpu"

# Setting up environment framework
available_options = [["keras-tensorflow", "has libraries for keras(v2.1.6) and tensorflow(v1.9.0) along with sklearn, opencv etc."],
["mxnet", "has libraries for mxnet(v1.1.0) along with sklearn, opencv etc."]]
option_type = "framework"

@self.cli.input("mxnet\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "mxnet"

@self.cli.input("\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "python-base"

available_options = ["py27", "py35"]
option_type = "language"

@self.cli.input("py27\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "py27"

@self.cli.input("\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

result = dummy(self)
assert result
assert result == "py27"

# quit
@self.cli.input("quit\n")
def dummy(self):
return self.cli.prompt_available_options(available_options, option_type)

with pytest.raises(SystemExit) as pytest_wrapped_e:
dummy(self)

assert pytest_wrapped_e.type == SystemExit
assert pytest_wrapped_e.value.code == 0

def test_prompt_validator(self):
def validate_y(val):
return True if val == "y" else False
Expand Down
18 changes: 18 additions & 0 deletions datmo/core/controller/environment/driver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,24 @@ def build(self, name, path, workspace):
"""
pass

@abstractmethod
def extract_workspace_url(self, container_name, workspace=None):
"""Extract workspace url from the container
Parameters
----------
container_name : str
name of the container being run
workspace : str
workspace being used for the run
Returns
-------
str
web url for the workspace being run, None if it doesn't exist
"""
pass

@abstractmethod
def run(self, name, options, log_filepath):
"""Run and log an instance of the environment with the options given
Expand Down
45 changes: 45 additions & 0 deletions datmo/core/controller/environment/driver/dockerenv.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import ast
import os
import re
import time
import json
import subprocess
import platform
Expand Down Expand Up @@ -437,6 +439,49 @@ def remove_images(self, name=None, all=False, filters=None, force=False):
str(e)))
return True

def extract_workspace_url(self, container_name, workspace=None):
"""Extract workspace url from the container
Parameters
----------
container_name : str
name of the container being run
workspace : str
workspace being used for the run
Returns
-------
str
web url for the workspace being run, None if it doesn't exist
"""
if workspace in ['notebook', 'jupyterlab']:
docker_shell_cmd_list = list(self.prefix)
docker_shell_cmd_list.append("exec")
docker_shell_cmd_list.append(container_name)
docker_shell_cmd_list.append("jupyter")
docker_shell_cmd_list.append("notebook")
docker_shell_cmd_list.append("list")
workspace_url = None
timeout_count = 0
while workspace_url is None and timeout_count < 10:
process = subprocess.Popen(
docker_shell_cmd_list,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if process.returncode > 0:
time.sleep(1)
timeout_count += 1
workspace_url = re.search("(?P<url>https?://[^\s]+)", stdout).group("url") if stdout else None
return workspace_url
elif workspace == 'rstudio':
time.sleep(2)
workspace_url = 'http://localhost:8787'
else:
workspace_url = None
return workspace_url

# running daemon needed
def run_container(self,
image_name,
Expand Down
29 changes: 29 additions & 0 deletions datmo/core/controller/environment/driver/tests/test_dockerenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os
import tempfile
import platform
import threading
import uuid
import timeout_decorator
from io import open
Expand Down Expand Up @@ -663,6 +664,34 @@ def test_run_container(self):
self.image_name, api=True, detach=True)
assert container_obj

@pytest_docker_environment_failed_instantiation(test_datmo_dir)
def test_extract_workspace_url(self):
# TODO: test with all variables provided
with open(self.dockerfile_path, "wb") as f:
f.write(to_bytes("FROM datmo/python-base:cpu-py27-notebook" + os.linesep))
f.write(to_bytes(str("RUN echo " + self.random_text)))
self.docker_environment_driver.build_image(self.image_name,
self.dockerfile_path)

def dummy(self, name, workspace):
workspace_url = self.environment_driver.extract_workspace_url(name, workspace)
assert workspace_url

thread = threading.Thread(target=dummy, args=(self.image_name, "notebook"))
thread.daemon = True # Daemonize thread
thread.start() # Start the execution

@timeout_decorator.timeout(10, use_signals=False)
def timed_run(self):
return_code, container_id = \
self.docker_environment_driver.run_container(self.image_name)
return return_code, container_id

return_code, container_id = timed_run(self)
# teardown container
self.docker_environment_driver.stop(container_id, force=True)


@pytest_docker_environment_failed_instantiation(test_datmo_dir)
def test_get_container(self):
failed = False
Expand Down
Loading

0 comments on commit d359c79

Please sign in to comment.