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.
Files changed (71) hide show
  1. docker_image/BASE_VERSION +1 -0
  2. docker_image/Dockerfile +48 -0
  3. docker_image/Dockerfile_buildenv +46 -0
  4. docker_image/ImageName +1 -0
  5. docker_image/README.md +78 -0
  6. docker_image/__init__.py +6 -0
  7. docker_image/build_docker_image.py +145 -0
  8. docker_image/debian/BASE_VERSION +1 -0
  9. docker_image/debian/Dockerfile +40 -0
  10. docker_image/debian/ImageName +1 -0
  11. docker_image/debian/README.md +48 -0
  12. docker_image/debian/pip.conf +3 -0
  13. docker_image/debian/requirements.txt +1 -0
  14. docker_image/docker_image_history.py +101 -0
  15. docker_image/pip.conf +3 -0
  16. docker_image/push_docker_image.py +62 -0
  17. docker_image/requirements.txt +1 -0
  18. docker_image/rocky_meta_runtime.txt +37 -0
  19. idmtools_platform_container/__init__.py +18 -8
  20. idmtools_platform_container/cli/__init__.py +5 -0
  21. idmtools_platform_container/cli/container.py +682 -0
  22. idmtools_platform_container/container_operations/__init__.py +5 -0
  23. idmtools_platform_container/container_operations/docker_operations.py +593 -0
  24. idmtools_platform_container/container_platform.py +375 -0
  25. idmtools_platform_container/platform_operations/__init__.py +5 -0
  26. idmtools_platform_container/platform_operations/experiment_operations.py +112 -0
  27. idmtools_platform_container/platform_operations/simulation_operations.py +58 -0
  28. idmtools_platform_container/plugin_info.py +79 -0
  29. idmtools_platform_container/utils/__init__.py +5 -0
  30. idmtools_platform_container/utils/general.py +136 -0
  31. idmtools_platform_container/utils/status.py +130 -0
  32. idmtools_platform_container-0.0.2.dist-info/METADATA +212 -0
  33. idmtools_platform_container-0.0.2.dist-info/RECORD +69 -0
  34. idmtools_platform_container-0.0.2.dist-info/entry_points.txt +5 -0
  35. idmtools_platform_container-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
  36. {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.2.dist-info}/top_level.txt +2 -0
  37. tests/inputs/Assets/MyLib/functions.py +2 -0
  38. tests/inputs/__init__.py +0 -0
  39. tests/inputs/model.py +28 -0
  40. tests/inputs/model1.py +31 -0
  41. tests/inputs/model3.py +21 -0
  42. tests/inputs/model_file.py +18 -0
  43. tests/inputs/run.sh +1 -0
  44. tests/inputs/sleep.py +9 -0
  45. tests/test_container_cli/__init__.py +0 -0
  46. tests/test_container_cli/helper.py +57 -0
  47. tests/test_container_cli/test_base.py +14 -0
  48. tests/test_container_cli/test_cancel.py +96 -0
  49. tests/test_container_cli/test_clear_results.py +54 -0
  50. tests/test_container_cli/test_container.py +72 -0
  51. tests/test_container_cli/test_file_container_cli.py +121 -0
  52. tests/test_container_cli/test_get_detail.py +60 -0
  53. tests/test_container_cli/test_history.py +136 -0
  54. tests/test_container_cli/test_history_count.py +53 -0
  55. tests/test_container_cli/test_inspect.py +53 -0
  56. tests/test_container_cli/test_install.py +48 -0
  57. tests/test_container_cli/test_is_running.py +69 -0
  58. tests/test_container_cli/test_jobs.py +138 -0
  59. tests/test_container_cli/test_list_containers.py +99 -0
  60. tests/test_container_cli/test_packages.py +41 -0
  61. tests/test_container_cli/test_path.py +96 -0
  62. tests/test_container_cli/test_ps.py +47 -0
  63. tests/test_container_cli/test_remove_container.py +78 -0
  64. tests/test_container_cli/test_status.py +149 -0
  65. tests/test_container_cli/test_stop_container.py +71 -0
  66. tests/test_container_cli/test_sync_history.py +98 -0
  67. tests/test_container_cli/test_verify_docker.py +28 -0
  68. tests/test_container_cli/test_volume.py +28 -0
  69. idmtools_platform_container-0.0.0.dev0.dist-info/METADATA +0 -41
  70. idmtools_platform_container-0.0.0.dev0.dist-info/RECORD +0 -5
  71. {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)