idmtools-platform-container 0.0.0.dev0__py3-none-any.whl → 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docker_image/BASE_VERSION +1 -0
- docker_image/Dockerfile +48 -0
- docker_image/Dockerfile_buildenv +46 -0
- docker_image/ImageName +1 -0
- docker_image/README.md +78 -0
- docker_image/__init__.py +6 -0
- docker_image/build_docker_image.py +145 -0
- docker_image/debian/BASE_VERSION +1 -0
- docker_image/debian/Dockerfile +40 -0
- docker_image/debian/ImageName +1 -0
- docker_image/debian/README.md +48 -0
- docker_image/debian/pip.conf +3 -0
- docker_image/debian/requirements.txt +1 -0
- docker_image/docker_image_history.py +101 -0
- docker_image/pip.conf +3 -0
- docker_image/push_docker_image.py +62 -0
- docker_image/requirements.txt +1 -0
- docker_image/rocky_meta_runtime.txt +37 -0
- idmtools_platform_container/__init__.py +18 -8
- idmtools_platform_container/cli/__init__.py +5 -0
- idmtools_platform_container/cli/container.py +682 -0
- idmtools_platform_container/container_operations/__init__.py +5 -0
- idmtools_platform_container/container_operations/docker_operations.py +593 -0
- idmtools_platform_container/container_platform.py +375 -0
- idmtools_platform_container/platform_operations/__init__.py +5 -0
- idmtools_platform_container/platform_operations/experiment_operations.py +112 -0
- idmtools_platform_container/platform_operations/simulation_operations.py +58 -0
- idmtools_platform_container/plugin_info.py +79 -0
- idmtools_platform_container/utils/__init__.py +5 -0
- idmtools_platform_container/utils/general.py +136 -0
- idmtools_platform_container/utils/status.py +130 -0
- idmtools_platform_container-0.0.2.dist-info/METADATA +212 -0
- idmtools_platform_container-0.0.2.dist-info/RECORD +69 -0
- idmtools_platform_container-0.0.2.dist-info/entry_points.txt +5 -0
- idmtools_platform_container-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
- {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.2.dist-info}/top_level.txt +2 -0
- tests/inputs/Assets/MyLib/functions.py +2 -0
- tests/inputs/__init__.py +0 -0
- tests/inputs/model.py +28 -0
- tests/inputs/model1.py +31 -0
- tests/inputs/model3.py +21 -0
- tests/inputs/model_file.py +18 -0
- tests/inputs/run.sh +1 -0
- tests/inputs/sleep.py +9 -0
- tests/test_container_cli/__init__.py +0 -0
- tests/test_container_cli/helper.py +57 -0
- tests/test_container_cli/test_base.py +14 -0
- tests/test_container_cli/test_cancel.py +96 -0
- tests/test_container_cli/test_clear_results.py +54 -0
- tests/test_container_cli/test_container.py +72 -0
- tests/test_container_cli/test_file_container_cli.py +121 -0
- tests/test_container_cli/test_get_detail.py +60 -0
- tests/test_container_cli/test_history.py +136 -0
- tests/test_container_cli/test_history_count.py +53 -0
- tests/test_container_cli/test_inspect.py +53 -0
- tests/test_container_cli/test_install.py +48 -0
- tests/test_container_cli/test_is_running.py +69 -0
- tests/test_container_cli/test_jobs.py +138 -0
- tests/test_container_cli/test_list_containers.py +99 -0
- tests/test_container_cli/test_packages.py +41 -0
- tests/test_container_cli/test_path.py +96 -0
- tests/test_container_cli/test_ps.py +47 -0
- tests/test_container_cli/test_remove_container.py +78 -0
- tests/test_container_cli/test_status.py +149 -0
- tests/test_container_cli/test_stop_container.py +71 -0
- tests/test_container_cli/test_sync_history.py +98 -0
- tests/test_container_cli/test_verify_docker.py +28 -0
- tests/test_container_cli/test_volume.py +28 -0
- idmtools_platform_container-0.0.0.dev0.dist-info/METADATA +0 -41
- idmtools_platform_container-0.0.0.dev0.dist-info/RECORD +0 -5
- {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.2.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import unittest
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
import pytest
|
|
6
|
+
from idmtools.entities.command_task import CommandTask
|
|
7
|
+
from idmtools.entities.experiment import Experiment
|
|
8
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
9
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
10
|
+
from test_base import TestContainerPlatformCliBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.serial
|
|
14
|
+
@pytest.mark.cli
|
|
15
|
+
class TestContainerPlatformHistoryCountCli(TestContainerPlatformCliBase):
|
|
16
|
+
@patch('rich.console.Console.print')
|
|
17
|
+
def test_history_count(self, mock_console):
|
|
18
|
+
# first clear the history
|
|
19
|
+
result = self.runner.invoke(container_cli.container, ['clear-history'])
|
|
20
|
+
self.assertEqual(result.exit_code, 0)
|
|
21
|
+
command = "sleep 100"
|
|
22
|
+
task = CommandTask(command=command)
|
|
23
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
24
|
+
experiment.run(wait_until_done=False)
|
|
25
|
+
# run another experiment job
|
|
26
|
+
experiment1 = Experiment.from_task(task, name="run_command")
|
|
27
|
+
experiment1.run(wait_until_done=False)
|
|
28
|
+
# test history
|
|
29
|
+
result = self.runner.invoke(container_cli.container, ['history-count'])
|
|
30
|
+
self.assertEqual(result.exit_code, 0)
|
|
31
|
+
self.assertTrue(mock_console.call_args_list[0].args[0] == 2) # Make sure there are 2 jobs in history
|
|
32
|
+
# clean up container
|
|
33
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
34
|
+
self.assertEqual(result.exit_code, 0)
|
|
35
|
+
|
|
36
|
+
def test_history_count_help(self):
|
|
37
|
+
result = self.runner.invoke(container_cli.container, ['history-count', "--help"])
|
|
38
|
+
expected_help = ('Usage: container history-count [OPTIONS] [CONTAINER_ID]\n'
|
|
39
|
+
'\n'
|
|
40
|
+
' Get the count of count histories.\n'
|
|
41
|
+
'\n'
|
|
42
|
+
' Arguments:\n'
|
|
43
|
+
'\n'
|
|
44
|
+
' CONTAINER_ID: Container ID (optional)\n'
|
|
45
|
+
'\n'
|
|
46
|
+
'Options:\n'
|
|
47
|
+
' --help Show this message and exit.\n')
|
|
48
|
+
self.assertEqual(result.exit_code, 0)
|
|
49
|
+
self.assertEqual(result.output, expected_help)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == '__main__':
|
|
53
|
+
unittest.main()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from time import sleep
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
import pytest
|
|
6
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
7
|
+
from idmtools.entities.command_task import CommandTask
|
|
8
|
+
from idmtools.entities.experiment import Experiment
|
|
9
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
10
|
+
from test_base import TestContainerPlatformCliBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.serial
|
|
14
|
+
@pytest.mark.cli
|
|
15
|
+
class TestContainerPlatformInspectCli(TestContainerPlatformCliBase):
|
|
16
|
+
|
|
17
|
+
@patch('rich.console.Console.print')
|
|
18
|
+
def test_inspect(self, mock_console):
|
|
19
|
+
command = "sleep 100"
|
|
20
|
+
task = CommandTask(command=command)
|
|
21
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
22
|
+
experiment.run(wait_until_done=False)
|
|
23
|
+
sleep(1)
|
|
24
|
+
result = self.runner.invoke(container_cli.container, ['inspect', self.platform.container_id])
|
|
25
|
+
self.assertIn('Container ID', mock_console.call_args_list[1][0][0])
|
|
26
|
+
self.assertIn(f'{self.platform.container_id}', mock_console.call_args_list[1][0][0])
|
|
27
|
+
self.assertIn('Container Name', mock_console.call_args_list[2][0][0])
|
|
28
|
+
self.assertIn('Status', mock_console.call_args_list[3][0][0])
|
|
29
|
+
self.assertIn('Created', mock_console.call_args_list[4][0][0])
|
|
30
|
+
self.assertIn('StartedAt', mock_console.call_args_list[5][0][0])
|
|
31
|
+
self.assertIn('Image', mock_console.call_args_list[6][0][0])
|
|
32
|
+
self.assertIn(f'{self.platform.docker_image}', mock_console.call_args_list[7][0][0].text.plain)
|
|
33
|
+
self.assertIn('Image Tags', mock_console.call_args_list[8][0][0])
|
|
34
|
+
self.assertIn('State', mock_console.call_args_list[10][0][0])
|
|
35
|
+
self.assertIn('Mounts', mock_console.call_args_list[12][0][0])
|
|
36
|
+
# clean up container
|
|
37
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
38
|
+
self.assertEqual(result.exit_code, 0)
|
|
39
|
+
|
|
40
|
+
def test_inspect_help(self):
|
|
41
|
+
result = self.runner.invoke(container_cli.container, ['inspect', "--help"])
|
|
42
|
+
expected_help = ('Usage: container inspect [OPTIONS] CONTAINER_ID\n'
|
|
43
|
+
'\n'
|
|
44
|
+
' Inspect a container.\n'
|
|
45
|
+
'\n'
|
|
46
|
+
' Arguments:\n'
|
|
47
|
+
'\n'
|
|
48
|
+
' CONTAINER_ID: Container ID\n'
|
|
49
|
+
'\n'
|
|
50
|
+
'Options:\n'
|
|
51
|
+
' --help Show this message and exit.\n')
|
|
52
|
+
self.assertEqual(result.exit_code, 0)
|
|
53
|
+
self.assertEqual(result.output, expected_help)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from time import sleep
|
|
4
|
+
from unittest.mock import patch
|
|
5
|
+
import pytest
|
|
6
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
7
|
+
from idmtools.entities.command_task import CommandTask
|
|
8
|
+
from idmtools.entities.experiment import Experiment
|
|
9
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
10
|
+
from test_base import TestContainerPlatformCliBase
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.serial
|
|
14
|
+
@pytest.mark.cli
|
|
15
|
+
class TestContainerPlatformInstallCli(TestContainerPlatformCliBase):
|
|
16
|
+
|
|
17
|
+
@patch('rich.console.Console.print')
|
|
18
|
+
def test_install(self, mock_console):
|
|
19
|
+
command = "sleep 100"
|
|
20
|
+
task = CommandTask(command=command)
|
|
21
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
22
|
+
experiment.run(wait_until_done=False)
|
|
23
|
+
sleep(1)
|
|
24
|
+
result = self.runner.invoke(container_cli.container, ['install', 'astor', '-c', self.platform.container_id])
|
|
25
|
+
# verify that the package was installed with container packages cli
|
|
26
|
+
result = self.runner.invoke(container_cli.container, ['packages', self.platform.container_id])
|
|
27
|
+
self.assertIn('astor', mock_console.call_args_list[1][0][0])
|
|
28
|
+
# clean up container
|
|
29
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
30
|
+
self.assertEqual(result.exit_code, 0)
|
|
31
|
+
|
|
32
|
+
def test_install_help(self):
|
|
33
|
+
result = self.runner.invoke(container_cli.container, ['install', "--help"])
|
|
34
|
+
expected_help = ('Usage: container install [OPTIONS] PACKAGE\n'
|
|
35
|
+
'\n'
|
|
36
|
+
' pip install a package on a container.\n'
|
|
37
|
+
'\n'
|
|
38
|
+
' Arguments:\n'
|
|
39
|
+
'\n'
|
|
40
|
+
' PACKAGE: package to be installed\n'
|
|
41
|
+
'\n'
|
|
42
|
+
'Options:\n'
|
|
43
|
+
' -c, --container-id TEXT Container ID\n'
|
|
44
|
+
' -i, --index-url TEXT index-url for pip install\n'
|
|
45
|
+
' -e, --extra-index-url TEXT extra-index-url for pip install\n'
|
|
46
|
+
' --help Show this message and exit.\n')
|
|
47
|
+
self.assertEqual(result.exit_code, 0)
|
|
48
|
+
self.assertEqual(result.output, expected_help)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import unittest
|
|
4
|
+
from time import sleep
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
import pytest
|
|
7
|
+
from idmtools.entities.command_task import CommandTask
|
|
8
|
+
from idmtools.entities.experiment import Experiment
|
|
9
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
10
|
+
|
|
11
|
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
12
|
+
sys.path.append(script_dir)
|
|
13
|
+
from test_base import TestContainerPlatformCliBase
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.serial
|
|
17
|
+
@pytest.mark.cli
|
|
18
|
+
class TestContainerPlatformIsRunningCli(TestContainerPlatformCliBase):
|
|
19
|
+
|
|
20
|
+
def test_is_running(self):
|
|
21
|
+
command = "python3 Assets/sleep.py"
|
|
22
|
+
task = CommandTask(command=command)
|
|
23
|
+
task.common_assets.add_asset(os.path.join(script_dir, "..", "inputs", "sleep.py"))
|
|
24
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
25
|
+
experiment.run(wait_until_done=False)
|
|
26
|
+
sleep(10)
|
|
27
|
+
# test is-running with experiment id
|
|
28
|
+
with patch('rich.console.Console.print') as mock_console_exp:
|
|
29
|
+
result = self.runner.invoke(container_cli.container, ['is-running', experiment.id])
|
|
30
|
+
self.assertEqual(result.exit_code, 0)
|
|
31
|
+
self.assertEqual(f'EXPERIMENT {experiment.id} is running on container {self.platform.container_id}.',
|
|
32
|
+
mock_console_exp.call_args_list[0][0][0])
|
|
33
|
+
# test is-running with simulation id
|
|
34
|
+
with patch('rich.console.Console.print') as mock_console_sim:
|
|
35
|
+
result = self.runner.invoke(container_cli.container, ['is-running', experiment.simulations[0].id])
|
|
36
|
+
self.assertEqual(result.exit_code, 0)
|
|
37
|
+
self.assertEqual(
|
|
38
|
+
f'SIMULATION {experiment.simulations[0].id} is running on container {self.platform.container_id}.',
|
|
39
|
+
mock_console_sim.call_args_list[0][0][0])
|
|
40
|
+
# test is-running with invalid id
|
|
41
|
+
with patch('rich.console.Console.print') as mock_console_invalid:
|
|
42
|
+
result = self.runner.invoke(container_cli.container, ['is-running', "abc"])
|
|
43
|
+
self.assertEqual(result.exit_code, 0)
|
|
44
|
+
self.assertEqual(f'Job abc is not found.', mock_console_invalid.call_args_list[0][0][0])
|
|
45
|
+
|
|
46
|
+
# clean up container
|
|
47
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
48
|
+
self.assertEqual(result.exit_code, 0)
|
|
49
|
+
|
|
50
|
+
def test_is_running_help(self):
|
|
51
|
+
result = self.runner.invoke(container_cli.container, ['is-running', "--help"])
|
|
52
|
+
expected_help = (
|
|
53
|
+
'Usage: container is-running [OPTIONS] ITEM_ID\n'
|
|
54
|
+
'\n'
|
|
55
|
+
' Check if an Experiment/Simulation is running.\n'
|
|
56
|
+
'\n'
|
|
57
|
+
' Arguments:\n'
|
|
58
|
+
'\n'
|
|
59
|
+
' ITEM_ID: Experiment/Simulation ID\n'
|
|
60
|
+
'\n'
|
|
61
|
+
'Options:\n'
|
|
62
|
+
' --help Show this message and exit.\n'
|
|
63
|
+
)
|
|
64
|
+
self.assertEqual(result.exit_code, 0)
|
|
65
|
+
self.assertEqual(result.output, expected_help)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if __name__ == '__main__':
|
|
69
|
+
unittest.main()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import unittest
|
|
4
|
+
import re
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from idmtools.entities import Suite
|
|
9
|
+
from idmtools.entities.command_task import CommandTask
|
|
10
|
+
from idmtools.entities.experiment import Experiment
|
|
11
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
12
|
+
from idmtools_platform_container.container_platform import ContainerPlatform
|
|
13
|
+
from idmtools_platform_file.tools.job_history import JobHistory
|
|
14
|
+
|
|
15
|
+
script_dir = os.path.dirname(os.path.abspath(__file__))
|
|
16
|
+
sys.path.append(script_dir)
|
|
17
|
+
from test_base import TestContainerPlatformCliBase
|
|
18
|
+
from helper import get_actual_rich_table_values
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.serial
|
|
22
|
+
@pytest.mark.cli
|
|
23
|
+
class TestContainerPlatformJobCli(TestContainerPlatformCliBase):
|
|
24
|
+
|
|
25
|
+
@patch('rich.console.Console.print')
|
|
26
|
+
def test_jobs(self, mock_console):
|
|
27
|
+
command = "python3 Assets/sleep.py 100"
|
|
28
|
+
task = CommandTask(command=command)
|
|
29
|
+
task.common_assets.add_asset(os.path.join(script_dir, "..", "inputs", "sleep.py"))
|
|
30
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
31
|
+
experiment.run(wait_until_done=False)
|
|
32
|
+
job = JobHistory.get_job(experiment.id)
|
|
33
|
+
|
|
34
|
+
# second experiment
|
|
35
|
+
experiment2 = Experiment.from_task(task, name="run_command")
|
|
36
|
+
experiment2.run(wait_until_done=False)
|
|
37
|
+
job2 = JobHistory.get_job(experiment2.id)
|
|
38
|
+
|
|
39
|
+
# test jobs
|
|
40
|
+
result = self.runner.invoke(container_cli.container, ['jobs'])
|
|
41
|
+
self.assertEqual(result.exit_code, 0)
|
|
42
|
+
actual_table = get_actual_rich_table_values(mock_console)
|
|
43
|
+
expected_job = ['EXPERIMENT', experiment.id, job['CONTAINER']]
|
|
44
|
+
expected_job2 = ['EXPERIMENT', experiment2.id, job2['CONTAINER']]
|
|
45
|
+
elapsed_ok = False
|
|
46
|
+
job_ok = False
|
|
47
|
+
expected_head = ['Entity Type', 'Entity ID', 'Job ID', 'Container', 'Status', 'Elapsed']
|
|
48
|
+
self.assertEqual(actual_table[0], expected_head)
|
|
49
|
+
for row in actual_table[1:]:
|
|
50
|
+
if row[1] == experiment.id: # if experiment id is found
|
|
51
|
+
# make sure all items in expected_job are in row
|
|
52
|
+
self.assertTrue(all(item in row for item in expected_job))
|
|
53
|
+
if row[1] == experiment2.id: # if experiment2 id is found
|
|
54
|
+
self.assertTrue(all(item in row for item in expected_job2))
|
|
55
|
+
|
|
56
|
+
# verify last item (Elapsed) in row is in format of 'HH:MM'
|
|
57
|
+
match = re.match(r'^\d{2}:\d{2}$', row[-1])
|
|
58
|
+
elapsed_ok = True if match else False
|
|
59
|
+
|
|
60
|
+
# verify job is found
|
|
61
|
+
match_job = re.match(r'^\d+$', row[2])
|
|
62
|
+
job_ok = True if match_job else False
|
|
63
|
+
self.assertEqual(job_ok, True)
|
|
64
|
+
self.assertEqual(elapsed_ok, True)
|
|
65
|
+
# # clean up container
|
|
66
|
+
# result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
67
|
+
# self.assertEqual(result.exit_code, 0)
|
|
68
|
+
|
|
69
|
+
@patch('rich.console.Console.print')
|
|
70
|
+
def test_jobs_with_container_id(self, mock_console):
|
|
71
|
+
command = "sleep 100"
|
|
72
|
+
task = CommandTask(command=command)
|
|
73
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
74
|
+
experiment.run(wait_until_done=False)
|
|
75
|
+
job = JobHistory.get_job(experiment.id)
|
|
76
|
+
# test jobs with container id
|
|
77
|
+
result = self.runner.invoke(container_cli.container, ['jobs'], self.platform.container_id)
|
|
78
|
+
self.assertEqual(result.exit_code, 0)
|
|
79
|
+
actual_table = get_actual_rich_table_values(mock_console)
|
|
80
|
+
expected_job = ['EXPERIMENT', experiment.id, job['CONTAINER']]
|
|
81
|
+
found = False
|
|
82
|
+
for row in actual_table[1:]:
|
|
83
|
+
if all(item in row for item in expected_job): # if all items in expected_job are in row
|
|
84
|
+
found = True # set found to True
|
|
85
|
+
self.assertEqual(found, True)
|
|
86
|
+
# clean up by stop the job
|
|
87
|
+
result = self.runner.invoke(container_cli.container, ['cancel', experiment.id])
|
|
88
|
+
self.assertEqual(result.exit_code, 0)
|
|
89
|
+
|
|
90
|
+
@patch('rich.console.Console.print')
|
|
91
|
+
def test_jobs_with_container_suite(self, mock_console):
|
|
92
|
+
# first clear the history
|
|
93
|
+
result = self.runner.invoke(container_cli.container, ['clear-history'])
|
|
94
|
+
self.assertEqual(result.exit_code, 0)
|
|
95
|
+
command = "sleep 100"
|
|
96
|
+
platform = ContainerPlatform(job_directory=self.job_directory, new_container=True)
|
|
97
|
+
task = CommandTask(command=command)
|
|
98
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
99
|
+
suite = Suite(name="suite_name")
|
|
100
|
+
suite.add_experiment(experiment)
|
|
101
|
+
suite.run(wait_until_done=False, platform=platform)
|
|
102
|
+
job = JobHistory.get_job(experiment.id)
|
|
103
|
+
# test history
|
|
104
|
+
result = self.runner.invoke(container_cli.container, ['jobs'], platform.container_id)
|
|
105
|
+
self.assertEqual(result.exit_code, 0)
|
|
106
|
+
actual_table = get_actual_rich_table_values(mock_console)
|
|
107
|
+
expected_job = ['EXPERIMENT', experiment.id, job['CONTAINER']]
|
|
108
|
+
found = False
|
|
109
|
+
for row in actual_table[1:]:
|
|
110
|
+
if all(item in row for item in expected_job): # if all items in expected_job are in row
|
|
111
|
+
found = True # set found to True
|
|
112
|
+
self.assertEqual(found, True)
|
|
113
|
+
# clean up by stop the job
|
|
114
|
+
result = self.runner.invoke(container_cli.container, ['cancel', experiment.id])
|
|
115
|
+
self.assertEqual(result.exit_code, 0)
|
|
116
|
+
|
|
117
|
+
def test_jobs_help(self):
|
|
118
|
+
result = self.runner.invoke(container_cli.container, ['jobs', "--help"])
|
|
119
|
+
expected_help = (
|
|
120
|
+
'Usage: container jobs [OPTIONS] [CONTAINER_ID]\n'
|
|
121
|
+
'\n'
|
|
122
|
+
' List running Experiment/Simulation jobs.\n'
|
|
123
|
+
'\n'
|
|
124
|
+
' Arguments:\n'
|
|
125
|
+
'\n'
|
|
126
|
+
' CONTAINER_ID: Container ID (optional)\n'
|
|
127
|
+
'\n'
|
|
128
|
+
'Options:\n'
|
|
129
|
+
' -l, --limit INTEGER Max number of simulations to show\n'
|
|
130
|
+
' -n, --next INTEGER Next number of jobs to show\n'
|
|
131
|
+
' --help Show this message and exit.\n'
|
|
132
|
+
)
|
|
133
|
+
self.assertEqual(result.exit_code, 0)
|
|
134
|
+
self.assertEqual(result.output, expected_help)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
if __name__ == '__main__':
|
|
138
|
+
unittest.main()
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import sys
|
|
4
|
+
import unittest
|
|
5
|
+
from unittest.mock import patch
|
|
6
|
+
import pytest
|
|
7
|
+
from idmtools.entities.command_task import CommandTask
|
|
8
|
+
from idmtools.entities.experiment import Experiment
|
|
9
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
10
|
+
from idmtools_platform_container.container_platform import ContainerPlatform
|
|
11
|
+
|
|
12
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
13
|
+
from test_base import TestContainerPlatformCliBase
|
|
14
|
+
from helper import get_actual_rich_table_values, cleaned_str
|
|
15
|
+
|
|
16
|
+
upper_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
|
17
|
+
sys.path.append(upper_dir)
|
|
18
|
+
from utils import delete_containers_by_image_prefix
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.serial
|
|
22
|
+
@pytest.mark.cli
|
|
23
|
+
class TestContainerPlatformListContainersCli(TestContainerPlatformCliBase):
|
|
24
|
+
def setUp(self):
|
|
25
|
+
super(TestContainerPlatformListContainersCli, self).setUpClass()
|
|
26
|
+
delete_containers_by_image_prefix(self.platform.docker_image)
|
|
27
|
+
|
|
28
|
+
@patch('rich.console.Console.print')
|
|
29
|
+
def test_list_containers(self, mock_console):
|
|
30
|
+
command = "sleep 100"
|
|
31
|
+
task = CommandTask(command=command)
|
|
32
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
33
|
+
experiment.run(wait_until_done=False, platform=self.platform)
|
|
34
|
+
result = self.runner.invoke(container_cli.container, ['list-containers'])
|
|
35
|
+
self.assertEqual(result.exit_code, 0)
|
|
36
|
+
# verify there are at least 1 container show up in result
|
|
37
|
+
expected_result = bool(re.match(r'There are 1 container\(s\)\.', mock_console.call_args_list[0].args[0]))
|
|
38
|
+
self.assertTrue(expected_result)
|
|
39
|
+
table = get_actual_rich_table_values(mock_console)
|
|
40
|
+
expected_head = ["Container ID", "Image", "Status", "Created", "Started", "Name"]
|
|
41
|
+
self.assertEqual(table[0], expected_head)
|
|
42
|
+
self.assertEqual(self.platform.container_id, table[1][0])
|
|
43
|
+
self.assertEqual(self.platform.docker_image, table[1][1])
|
|
44
|
+
self.assertIn("running", cleaned_str(table[1][2]))
|
|
45
|
+
match_created_time = re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', table[1][3])
|
|
46
|
+
match_started_time = re.match(r'^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$', table[1][4])
|
|
47
|
+
self.assertTrue(match_created_time)
|
|
48
|
+
self.assertTrue(match_started_time)
|
|
49
|
+
# clean up container
|
|
50
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id])
|
|
51
|
+
self.assertEqual(result.exit_code, 0)
|
|
52
|
+
|
|
53
|
+
@patch('rich.console.Console.print')
|
|
54
|
+
def test_list_containers_all(self, mock_console):
|
|
55
|
+
# create first job then stop it
|
|
56
|
+
platform1 = ContainerPlatform(job_directory=self.job_directory)
|
|
57
|
+
command = "sleep 100"
|
|
58
|
+
task = CommandTask(command=command)
|
|
59
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
60
|
+
experiment.run(wait_until_done=False, platform=platform1)
|
|
61
|
+
# stop container
|
|
62
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', platform1.container_id])
|
|
63
|
+
self.assertEqual(result.exit_code, 0)
|
|
64
|
+
# create another job
|
|
65
|
+
platform2 = ContainerPlatform(job_directory=self.job_directory, new_container=True)
|
|
66
|
+
command = "sleep 100"
|
|
67
|
+
task = CommandTask(command=command)
|
|
68
|
+
experiment2 = Experiment.from_task(task, name="run_command")
|
|
69
|
+
experiment2.run(wait_until_done=False, platform=platform2)
|
|
70
|
+
with patch('rich.console.Console.print') as mock_console:
|
|
71
|
+
result = self.runner.invoke(container_cli.container, ['list-containers', '--all'])
|
|
72
|
+
self.assertEqual(result.exit_code, 0)
|
|
73
|
+
# verify there are at least 2 container show up in result
|
|
74
|
+
expected_result = bool(
|
|
75
|
+
re.match(r'There are [1-9]\d* container\(s\)\.', mock_console.call_args_list[0].args[0]))
|
|
76
|
+
self.assertTrue(expected_result)
|
|
77
|
+
|
|
78
|
+
# clean up container
|
|
79
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', platform1.container_id])
|
|
80
|
+
self.assertEqual(result.exit_code, 0)
|
|
81
|
+
# clean up container
|
|
82
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', platform2.container_id])
|
|
83
|
+
self.assertEqual(result.exit_code, 0)
|
|
84
|
+
|
|
85
|
+
def test_list_containers_help(self):
|
|
86
|
+
result = self.runner.invoke(container_cli.container, ['list-containers', "--help"])
|
|
87
|
+
expected_help = ('Usage: container list-containers [OPTIONS]\n'
|
|
88
|
+
'\n'
|
|
89
|
+
' List all available containers.\n'
|
|
90
|
+
'\n'
|
|
91
|
+
'Options:\n'
|
|
92
|
+
' --all / --no-all Include stopped containers or not\n'
|
|
93
|
+
' --help Show this message and exit.\n')
|
|
94
|
+
self.assertEqual(result.exit_code, 0)
|
|
95
|
+
self.assertEqual(result.output, expected_help)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if __name__ == '__main__':
|
|
99
|
+
unittest.main()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
import pytest
|
|
5
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
6
|
+
from idmtools.entities.command_task import CommandTask
|
|
7
|
+
from idmtools.entities.experiment import Experiment
|
|
8
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
9
|
+
from test_base import TestContainerPlatformCliBase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.serial
|
|
13
|
+
@pytest.mark.cli
|
|
14
|
+
class TestContainerPlatformPackagesCli(TestContainerPlatformCliBase):
|
|
15
|
+
|
|
16
|
+
@patch('rich.console.Console.print')
|
|
17
|
+
def test_packages(self, mock_console):
|
|
18
|
+
command = "sleep 100"
|
|
19
|
+
task = CommandTask(command=command)
|
|
20
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
21
|
+
experiment.run(wait_until_done=False)
|
|
22
|
+
result = self.runner.invoke(container_cli.container, ['packages', self.platform.container_id])
|
|
23
|
+
self.assertEqual(result.exit_code, 0)
|
|
24
|
+
# clean up container
|
|
25
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
26
|
+
self.assertEqual(result.exit_code, 0)
|
|
27
|
+
|
|
28
|
+
def test_packages_help(self):
|
|
29
|
+
result = self.runner.invoke(container_cli.container, ['packages', "--help"])
|
|
30
|
+
expected_help = ('Usage: container packages [OPTIONS] CONTAINER_ID\n'
|
|
31
|
+
'\n'
|
|
32
|
+
' List packages installed on a container.\n'
|
|
33
|
+
'\n'
|
|
34
|
+
' Arguments:\n'
|
|
35
|
+
'\n'
|
|
36
|
+
' CONTAINER_ID: Container ID\n'
|
|
37
|
+
'\n'
|
|
38
|
+
'Options:\n'
|
|
39
|
+
' --help Show this message and exit.\n')
|
|
40
|
+
self.assertEqual(result.exit_code, 0)
|
|
41
|
+
self.assertEqual(result.output, expected_help)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
7
|
+
from idmtools.core import ItemType
|
|
8
|
+
from idmtools.entities import Suite
|
|
9
|
+
from idmtools.entities.command_task import CommandTask
|
|
10
|
+
from idmtools.entities.experiment import Experiment
|
|
11
|
+
from idmtools_platform_container.utils.general import normalize_path
|
|
12
|
+
|
|
13
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
14
|
+
from test_base import TestContainerPlatformCliBase
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.serial
|
|
18
|
+
@pytest.mark.cli
|
|
19
|
+
class TestContainerPlatformPathCli(TestContainerPlatformCliBase):
|
|
20
|
+
|
|
21
|
+
def test_path_help(self):
|
|
22
|
+
result = self.runner.invoke(container_cli.container, ['path', "--help"])
|
|
23
|
+
expected_help = ('Usage: container path [OPTIONS] ITEM_ID\n'
|
|
24
|
+
'\n'
|
|
25
|
+
' Locate Suite/Experiment/Simulation file directory.\n'
|
|
26
|
+
'\n'
|
|
27
|
+
' Arguments:\n'
|
|
28
|
+
'\n'
|
|
29
|
+
' ITEM_ID: Suite/Experiment/Simulation ID\n'
|
|
30
|
+
'\n'
|
|
31
|
+
'Options:\n'
|
|
32
|
+
' --help Show this message and exit.\n')
|
|
33
|
+
self.assertEqual(result.exit_code, 0)
|
|
34
|
+
self.assertEqual(result.output, expected_help)
|
|
35
|
+
|
|
36
|
+
@patch('rich.console.Console.print')
|
|
37
|
+
def test_path_new_no_suite(self, mock_console):
|
|
38
|
+
command = "sleep 100"
|
|
39
|
+
task = CommandTask(command=command)
|
|
40
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
41
|
+
experiment.run(wait_until_done=False)
|
|
42
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.id])
|
|
43
|
+
self.assertEqual(result.exit_code, 0)
|
|
44
|
+
# check path
|
|
45
|
+
exp_dir = self.platform.get_directory_by_id(experiment.id, ItemType.EXPERIMENT)
|
|
46
|
+
self.assertIn(normalize_path(normalize_path(exp_dir)),
|
|
47
|
+
normalize_path(mock_console.call_args.args[0].split(' ')[1]))
|
|
48
|
+
# Test simulation path
|
|
49
|
+
with patch("rich.console.Console.print") as mock_console:
|
|
50
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.simulations[0].id])
|
|
51
|
+
self.assertEqual(result.exit_code, 0)
|
|
52
|
+
sim_dir = self.platform.get_directory_by_id(experiment.simulations[0].id, ItemType.SIMULATION)
|
|
53
|
+
self.assertIn(normalize_path(normalize_path(sim_dir)),
|
|
54
|
+
normalize_path(mock_console.call_args.args[0].split(' ')[1]))
|
|
55
|
+
# Test suite path
|
|
56
|
+
with patch("rich.console.Console.print") as mock_console:
|
|
57
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.parent_id])
|
|
58
|
+
self.assertEqual(result.exit_code, 1)
|
|
59
|
+
|
|
60
|
+
@patch('rich.console.Console.print')
|
|
61
|
+
def test_path_new_suite(self, mock_console):
|
|
62
|
+
command = "sleep 100"
|
|
63
|
+
task = CommandTask(command=command)
|
|
64
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
65
|
+
suite = Suite(name="suite_name")
|
|
66
|
+
suite.add_experiment(experiment)
|
|
67
|
+
# Run via Suite (mirrors your original with-suite behavior)
|
|
68
|
+
experiment.run(platform=self.platform, wait_until_done=False)
|
|
69
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.id])
|
|
70
|
+
self.assertEqual(result.exit_code, 0)
|
|
71
|
+
# check path
|
|
72
|
+
exp_dir = self.platform.get_directory_by_id(experiment.id, ItemType.EXPERIMENT)
|
|
73
|
+
self.assertIn(normalize_path(normalize_path(exp_dir)),
|
|
74
|
+
normalize_path(mock_console.call_args.args[0].split(' ')[1]))
|
|
75
|
+
# Test simulation path
|
|
76
|
+
with patch("rich.console.Console.print") as mock_console:
|
|
77
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.simulations[0].id])
|
|
78
|
+
self.assertEqual(result.exit_code, 0)
|
|
79
|
+
sim_dir = self.platform.get_directory_by_id(experiment.simulations[0].id, ItemType.SIMULATION)
|
|
80
|
+
self.assertIn(normalize_path(normalize_path(sim_dir)),
|
|
81
|
+
normalize_path(mock_console.call_args.args[0].split(' ')[1]))
|
|
82
|
+
# Test suite path
|
|
83
|
+
with patch("rich.console.Console.print") as mock_console:
|
|
84
|
+
result = self.runner.invoke(container_cli.container, ['path', experiment.parent_id])
|
|
85
|
+
self.assertEqual(result.exit_code, 0)
|
|
86
|
+
suite_dir = self.platform.get_directory_by_id(suite.id, ItemType.SUITE)
|
|
87
|
+
self.assertIn(normalize_path(normalize_path(suite_dir)),
|
|
88
|
+
normalize_path(mock_console.call_args.args[0].split(' ')[1]))
|
|
89
|
+
|
|
90
|
+
# Test invalid path
|
|
91
|
+
with patch("idmtools_platform_file.tools.job_history.logger") as mock_logger:
|
|
92
|
+
result = self.runner.invoke(container_cli.container, ['path', "abc"])
|
|
93
|
+
mock_logger.debug.assert_called_with("Invalid item id: abc")
|
|
94
|
+
# clean up container
|
|
95
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
96
|
+
self.assertEqual(result.exit_code, 0)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
import pytest
|
|
5
|
+
import idmtools_platform_container.cli.container as container_cli
|
|
6
|
+
from idmtools.entities.command_task import CommandTask
|
|
7
|
+
from idmtools.entities.experiment import Experiment
|
|
8
|
+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
|
9
|
+
from test_base import TestContainerPlatformCliBase
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.serial
|
|
13
|
+
@pytest.mark.cli
|
|
14
|
+
class TestContainerPlatformProcessCli(TestContainerPlatformCliBase):
|
|
15
|
+
|
|
16
|
+
@patch('rich.console.Console.print')
|
|
17
|
+
def test_ps(self, mock_console):
|
|
18
|
+
command = "sleep 100"
|
|
19
|
+
task = CommandTask(command=command)
|
|
20
|
+
experiment = Experiment.from_task(task, name="run_command")
|
|
21
|
+
experiment.run(wait_until_done=False)
|
|
22
|
+
result = self.runner.invoke(container_cli.container, ['ps', self.platform.container_id])
|
|
23
|
+
self.assertEqual(result.exit_code, 0)
|
|
24
|
+
# check ps
|
|
25
|
+
self.assertIn(f'EXPERIMENT:{experiment.id}', mock_console.call_args_list[0].args[0])
|
|
26
|
+
self.assertIn(f'batch.sh', mock_console.call_args_list[0].args[0])
|
|
27
|
+
# self.assertIn(
|
|
28
|
+
# "xargs -d \\n -P 4 -I% bash -c cd $(pwd) && $(pwd)/run_simulation.sh % 1>> stdout.txt 2>> stderr.txt",
|
|
29
|
+
# mock_console.call_args_list[0].args[0])
|
|
30
|
+
# clean up container
|
|
31
|
+
result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
|
|
32
|
+
self.assertEqual(result.exit_code, 0)
|
|
33
|
+
|
|
34
|
+
def test_ps_help(self):
|
|
35
|
+
result = self.runner.invoke(container_cli.container, ['ps', "--help"])
|
|
36
|
+
expected_help = ('Usage: container ps [OPTIONS] CONTAINER_ID\n'
|
|
37
|
+
'\n'
|
|
38
|
+
' List running processes in a container.\n'
|
|
39
|
+
'\n'
|
|
40
|
+
' Arguments:\n'
|
|
41
|
+
'\n'
|
|
42
|
+
' CONTAINER_ID: Container ID\n'
|
|
43
|
+
'\n'
|
|
44
|
+
'Options:\n'
|
|
45
|
+
' --help Show this message and exit.\n')
|
|
46
|
+
self.assertEqual(result.exit_code, 0)
|
|
47
|
+
self.assertEqual(result.output, expected_help)
|