[Project] Add Basic Session CLI Commands (#5433)

This commit is contained in:
Simon Mo
2019-08-19 10:14:45 -07:00
committed by Philipp Moritz
parent 658e002cdf
commit 341c6926e7
13 changed files with 452 additions and 4 deletions
+148
View File
@@ -7,9 +7,19 @@ import os
import pytest
import subprocess
import yaml
from click.testing import CliRunner
import sys
from contextlib import contextmanager
from ray.projects.scripts import start
import ray
if sys.version_info >= (3, 3):
from unittest.mock import patch, DEFAULT
else:
from mock import patch, DEFAULT
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
@@ -65,3 +75,141 @@ def test_project_no_validation():
path = os.path.join(TEST_DIR, "project_files")
with pytest.raises(subprocess.CalledProcessError):
subprocess.check_call(["ray", "project", "validate"], cwd=path)
@contextmanager
def _chdir_and_back(d):
old_dir = os.getcwd()
try:
os.chdir(d)
yield
finally:
os.chdir(old_dir)
def test_session_start_default_project():
# Run the CLI commands with patching
test_dir = os.path.join(TEST_DIR,
"project_files/session-tests/project-pass")
with _chdir_and_back(test_dir):
runner = CliRunner()
with patch.multiple(
"ray.projects.scripts",
create_or_update_cluster=DEFAULT,
rsync=DEFAULT,
exec_cluster=DEFAULT,
) as mock_calls:
result = runner.invoke(start, [])
assert result.exit_code == 0
# Check we are calling autoscaler correctly
loaded_project = ray.projects.load_project(test_dir)
# Part 1/3: Cluster Launching Call
create_or_update_cluster_call = mock_calls["create_or_update_cluster"]
assert create_or_update_cluster_call.call_count == 1
_, kwargs = create_or_update_cluster_call.call_args
assert kwargs["config_file"] == loaded_project["cluster"]
# Part 2/3: Rsync Calls
rsync_call = mock_calls["rsync"]
assert rsync_call.call_count == 1
_, kwargs = rsync_call.call_args
assert kwargs["source"] == loaded_project["environment"]["requirements"]
# Part 3/3: Exec Calls
exec_cluster_call = mock_calls["exec_cluster"]
commands_executed = []
for _, kwargs in exec_cluster_call.call_args_list:
commands_executed.append(kwargs["cmd"].replace(
"cd {}; ".format(loaded_project["name"]), ""))
expected_commands = loaded_project["environment"]["shell"]
expected_commands += [
command["command"] for command in loaded_project["commands"]
]
if "requirements" in loaded_project["environment"]:
assert any("pip install -r" for cmd in commands_executed)
# pop the `pip install` off commands executed
commands_executed = [
cmd for cmd in commands_executed if "pip install -r" not in cmd
]
# if we don't have a repo, we will be creating a directory
if "repo" not in loaded_project:
mkdir_command = "mkdir {project_name}".format(
project_name=loaded_project["name"])
assert any(mkdir_command in cmd for cmd in commands_executed)
# pop the `pip install` off commands executed
commands_executed = [
cmd for cmd in commands_executed if mkdir_command not in cmd
]
assert expected_commands == commands_executed
def test_session_start_docker_fail():
# Run the CLI commands with patching
test_dir = os.path.join(TEST_DIR,
"project_files/session-tests/with-docker-fail")
with _chdir_and_back(test_dir):
runner = CliRunner()
with patch.multiple(
"ray.projects.scripts",
create_or_update_cluster=DEFAULT,
rsync=DEFAULT,
exec_cluster=DEFAULT,
) as _:
result = runner.invoke(start, [])
assert result.exit_code == 1
assert ("Docker support in session is currently "
"not implemented") in result.output
def test_session_git_repo_cloned():
# Run the CLI commands with patching
test_dir = os.path.join(TEST_DIR,
"project_files/session-tests/git-repo-pass")
with _chdir_and_back(test_dir):
runner = CliRunner()
with patch.multiple(
"ray.projects.scripts",
create_or_update_cluster=DEFAULT,
rsync=DEFAULT,
exec_cluster=DEFAULT,
) as mock_calls:
result = runner.invoke(start, [])
assert result.exit_code == 0
loaded_project = ray.projects.load_project(test_dir)
exec_cluster_call = mock_calls["exec_cluster"]
commands_executed = []
for _, kwargs in exec_cluster_call.call_args_list:
command_executed = kwargs["cmd"]
# Filter out the cd call that was appended to each command
cd_project_dir_call = "cd {}; ".format(loaded_project["name"])
command_executed = command_executed.replace(cd_project_dir_call, "")
commands_executed.append(command_executed)
assert any("git clone" in cmd for cmd in commands_executed)
def test_session_invalid_config_errored():
# Run the CLI commands with patching
test_dir = os.path.join(TEST_DIR,
"project_files/session-tests/invalid-config-fail")
with _chdir_and_back(test_dir):
runner = CliRunner()
with patch.multiple(
"ray.projects.scripts",
create_or_update_cluster=DEFAULT,
rsync=DEFAULT,
exec_cluster=DEFAULT,
) as _:
result = runner.invoke(start, [])
assert result.exit_code == 1
assert "validation failed" in result.output
# check that we are displaying actional error message
assert "ray project validate" in result.output