idmtools-platform-container 0.0.0.dev0__py3-none-any.whl → 0.0.3__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.3.dist-info/METADATA +212 -0
  33. idmtools_platform_container-0.0.3.dist-info/RECORD +69 -0
  34. idmtools_platform_container-0.0.3.dist-info/entry_points.txt +5 -0
  35. idmtools_platform_container-0.0.3.dist-info/licenses/LICENSE.TXT +3 -0
  36. {idmtools_platform_container-0.0.0.dev0.dist-info → idmtools_platform_container-0.0.3.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.3.dist-info}/WHEEL +0 -0
tests/inputs/run.sh ADDED
@@ -0,0 +1 @@
1
+ python3 -m pip list
tests/inputs/sleep.py ADDED
@@ -0,0 +1,9 @@
1
+ import sys
2
+ import time
3
+
4
+ if __name__ == "__main__":
5
+ if len(sys.argv) > 1:
6
+ sleep_time = int(sys.argv[1])
7
+ else:
8
+ sleep_time = 100
9
+ time.sleep(sleep_time)
File without changes
@@ -0,0 +1,57 @@
1
+ import re
2
+
3
+ from rich.table import Table
4
+
5
+
6
+ def get_actual_rich_table_values(mock_console):
7
+ """
8
+ Get actual table values from the mock console
9
+ Args:
10
+ mock_console: rich.console.Console
11
+
12
+ Returns:
13
+ list for actual table values
14
+ """
15
+ actual_table = []
16
+ head = []
17
+ for call in mock_console.call_args_list:
18
+ args, _ = call
19
+
20
+ for arg in args:
21
+ if isinstance(arg, Table):
22
+ actual_rows = []
23
+ if len(head) == 0:
24
+ head = [column.header for column in arg.columns]
25
+ actual_table.append(head)
26
+ for c in arg.columns:
27
+ actual_rows.append(c._cells[0])
28
+ actual_table.append(actual_rows)
29
+ return actual_table
30
+
31
+
32
+ def found_job_id_by_experiment(actual_jobs_table, experiment_id=None):
33
+ """
34
+ Find job id by experiment id
35
+ Args:
36
+ actual_jobs_table: the actual jobs table from 'idmtools container jobs' cli command
37
+ experiment_id:
38
+
39
+ Returns:
40
+ job_id, container_id
41
+ """
42
+ for row in actual_jobs_table:
43
+ if row[1] == experiment_id:
44
+ return row[2], row[3]
45
+ return None
46
+
47
+
48
+ def cleaned_str(input_string):
49
+ """
50
+ Remove all substrings enclosed in brackets, leading spaces, and newlines
51
+ Args:
52
+ input_string: str
53
+
54
+ Returns:
55
+ cleaned string
56
+ """
57
+ return re.sub(r'^\s+|\[.*?\]|\n', '', input_string)
@@ -0,0 +1,14 @@
1
+ import unittest
2
+ import os
3
+ import pytest
4
+ from click.testing import CliRunner
5
+ from idmtools.core.platform_factory import Platform
6
+
7
+
8
+ class TestContainerPlatformCliBase(unittest.TestCase):
9
+
10
+ @classmethod
11
+ def setUpClass(cls):
12
+ cls.runner = CliRunner()
13
+ cls.job_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "DEST")
14
+ cls.platform = Platform("Container", job_directory=cls.job_directory)
@@ -0,0 +1,96 @@
1
+ import os
2
+ import sys
3
+ from time import sleep
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
+
11
+ script_dir = os.path.dirname(os.path.abspath(__file__))
12
+ sys.path.append(script_dir)
13
+ from test_base import TestContainerPlatformCliBase
14
+ from helper import found_job_id_by_experiment, get_actual_rich_table_values
15
+
16
+
17
+ @pytest.mark.serial
18
+ class TestContainerPlatformCancelCli(TestContainerPlatformCliBase):
19
+ @patch('rich.console.Console.print')
20
+ def test_cancel_with_experiment_id(self, mock_console):
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
+ sleep(1)
26
+ # test cancel with experiment id
27
+ result = self.runner.invoke(container_cli.container, ['cancel', experiment.id])
28
+ self.assertEqual(result.exit_code, 0)
29
+ self.assertIn('Successfully killed EXPERIMENT', mock_console.call_args_list[0].args[0])
30
+
31
+ @patch('rich.console.Console.print')
32
+ def test_cancel_with_simulation_id(self, mock_console1):
33
+ command = "python3 Assets/sleep.py"
34
+ task = CommandTask(command=command)
35
+ task.common_assets.add_asset(os.path.join(script_dir, "..", "inputs", "sleep.py"))
36
+ experiment = Experiment.from_task(task, name="run_command")
37
+ experiment.run(wait_until_done=False)
38
+ sleep(1)
39
+ # test cancel with simulation id
40
+ result = self.runner.invoke(container_cli.container, ['cancel', experiment.simulations[0].id])
41
+ self.assertEqual(result.exit_code, 0)
42
+ self.assertIn('Successfully killed SIMULATION', mock_console1.call_args_list[0].args[0])
43
+
44
+ @patch('rich.console.Console.print')
45
+ def test_cancel_with_experiment_job_id_and_container_id(self, mock_console):
46
+ command = "sleep 100"
47
+ task = CommandTask(command=command)
48
+ experiment = Experiment.from_task(task, name="run_command")
49
+ experiment.run(wait_until_done=False)
50
+ sleep(1)
51
+ result = self.runner.invoke(container_cli.container, ['jobs'])
52
+ self.assertEqual(result.exit_code, 0)
53
+ actual_table = get_actual_rich_table_values(mock_console)
54
+ job_id, container_id = found_job_id_by_experiment(actual_table[1:], experiment.id)
55
+ # test cancel with job_id and container_id
56
+ result = self.runner.invoke(container_cli.container, ['cancel', job_id, '-c', container_id])
57
+ self.assertTrue(f'Successfully killed EXPERIMENT {job_id}', mock_console.call_args[0][0])
58
+ self.assertEqual(result.exit_code, 0)
59
+
60
+ @patch('rich.console.Console.print')
61
+ def test_cancel_with_job_id_only(self, mock_console):
62
+ command = "sleep 100"
63
+ task = CommandTask(command=command)
64
+ experiment = Experiment.from_task(task, name="run_command")
65
+ experiment.run(wait_until_done=False)
66
+ sleep(1)
67
+ result = self.runner.invoke(container_cli.container, ['jobs'])
68
+ self.assertEqual(result.exit_code, 0)
69
+ actual_table = get_actual_rich_table_values(mock_console)
70
+ job_id, container_id = found_job_id_by_experiment(actual_table[1:], experiment.id)
71
+ # test cancel with job_id and container_id
72
+ result = self.runner.invoke(container_cli.container, ['cancel', job_id])
73
+ self.assertTrue(f'Successfully killed EXPERIMENT {job_id}', mock_console.call_args[0][0])
74
+ self.assertEqual(result.exit_code, 0)
75
+
76
+ def test_cancel_help(self):
77
+ result = self.runner.invoke(container_cli.container, ['cancel', "--help"])
78
+ expected_help = (
79
+ "Usage: container cancel [OPTIONS] ITEM_ID\n"
80
+ "\n"
81
+ " Cancel an Experiment/Simulation job.\n"
82
+ "\n"
83
+ " Arguments:\n"
84
+ "\n"
85
+ " ITEM_ID: Experiment/Simulation ID or Job ID\n"
86
+ "\n"
87
+ "Options:\n"
88
+ " -c, --container_id TEXT Container Id\n"
89
+ " --help Show this message and exit.\n"
90
+ )
91
+ self.assertEqual(result.exit_code, 0)
92
+ self.assertEqual(result.output, expected_help)
93
+
94
+
95
+ if __name__ == '__main__':
96
+ unittest.main()
@@ -0,0 +1,54 @@
1
+ import os
2
+ import sys
3
+ import pytest
4
+ import idmtools_platform_container.cli.container as container_cli
5
+ from idmtools.entities.command_task import CommandTask
6
+ from idmtools.entities.experiment import Experiment
7
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
8
+ from test_base import TestContainerPlatformCliBase
9
+
10
+
11
+ @pytest.mark.serial
12
+ class TestContainerPlatformClearResultsCli(TestContainerPlatformCliBase):
13
+
14
+ def test_clear_results(self):
15
+ command = "sleep 100"
16
+ task = CommandTask(command=command)
17
+ experiment = Experiment.from_task(task, name="run_command")
18
+ experiment.run(wait_until_done=False)
19
+ result = self.runner.invoke(container_cli.container, ['clear-results', experiment.id])
20
+ self.assertEqual(result.exit_code, 0)
21
+ # check if the EXPERIMENT_FILES are removed
22
+ for f in container_cli.EXPERIMENT_FILES:
23
+ self.assertFalse(os.path.exists(os.path.join(self.job_directory, experiment.id, f)))
24
+ # check if the SIMULATION_FILES are removed
25
+ for f in container_cli.SIMULATION_FILES:
26
+ self.assertFalse(os.path.exists(
27
+ os.path.join(self.job_directory,experiment.id, experiment.simulations[0].id, f)))
28
+ # clear-results Assets for simulation extra folder
29
+ result = self.runner.invoke(container_cli.container, ['clear-results', experiment.id, '-r',
30
+ os.path.join(self.job_directory,
31
+ experiment.id, experiment.simulations[0].id,
32
+ "Assets")])
33
+ self.assertFalse(os.path.exists(
34
+ os.path.join(self.job_directory, experiment.id, experiment.simulations[0].id,
35
+ "Assets")))
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_clear_results_help(self):
41
+ result = self.runner.invoke(container_cli.container, ['clear-results', "--help"])
42
+ expected_help = ('Usage: container clear-results [OPTIONS] ITEM_ID\n'
43
+ '\n'
44
+ ' Clear job results files and folders.\n'
45
+ '\n'
46
+ ' Arguments:\n'
47
+ '\n'
48
+ ' ITEM_ID: Experiment/Simulation ID\n'
49
+ '\n'
50
+ 'Options:\n'
51
+ ' -r, --remove TEXT Extra files/folders to be removed from simulation\n'
52
+ ' --help Show this message and exit.\n')
53
+ self.assertEqual(result.exit_code, 0)
54
+ self.assertEqual(result.output, expected_help)
@@ -0,0 +1,72 @@
1
+ import os
2
+ import sys
3
+ import pytest
4
+ import idmtools_platform_container.cli.container as container_cli
5
+
6
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
7
+ from test_base import TestContainerPlatformCliBase
8
+
9
+
10
+ class TestContainerPlatformCliContainer(TestContainerPlatformCliBase):
11
+
12
+ def test_container_help(self):
13
+ result = self.runner.invoke(container_cli.container, ["--help"])
14
+ expected_help = ('Usage: container [OPTIONS] COMMAND [ARGS]...\n'
15
+ '\n'
16
+ ' Container Platform CLI commands.\n'
17
+ '\n'
18
+ ' Args: all: Bool, show all commands\n'
19
+ '\n'
20
+ ' Returns: None\n'
21
+ '\n'
22
+ 'Options:\n'
23
+ ' --all Show all commands\n'
24
+ ' --help Show this message and exit.\n'
25
+ '\n'
26
+ 'Commands:\n'
27
+ ' cancel Cancel an Experiment/Simulation job.\n'
28
+ ' history View the job history.\n'
29
+ ' jobs List running Experiment/Simulation jobs.\n'
30
+ ' status Check the status of an Experiment/Simulation.\n'
31
+ )
32
+ self.assertEqual(result.exit_code, 0)
33
+ self.assertEqual(result.output, expected_help)
34
+
35
+ def test_container_help_all(self):
36
+ result = self.runner.invoke(container_cli.container, ["--all", "--help"])
37
+ expected_help_all = ('Usage: container [OPTIONS] COMMAND [ARGS]...\n'
38
+ '\n'
39
+ ' Container Platform CLI commands.\n'
40
+ '\n'
41
+ ' Args: all: Bool, show all commands\n'
42
+ '\n'
43
+ ' Returns: None\n'
44
+ '\n'
45
+ 'Options:\n'
46
+ ' --all Show all commands\n'
47
+ ' --help Show this message and exit.\n'
48
+ '\n'
49
+ 'Commands:\n'
50
+ ' cancel Cancel an Experiment/Simulation job.\n'
51
+ ' clear-history Clear the job history.\n'
52
+ ' clear-results Clear job results files and folders.\n'
53
+ ' get-detail Retrieve Experiment history.\n'
54
+ ' history View the job history.\n'
55
+ ' history-count Get the count of count histories.\n'
56
+ ' inspect Inspect a container.\n'
57
+ ' install pip install a package on a container.\n'
58
+ ' is-running Check if an Experiment/Simulation is running.\n'
59
+ ' jobs List running Experiment/Simulation jobs.\n'
60
+ ' list-containers List all available containers.\n'
61
+ ' packages List packages installed on a container.\n'
62
+ ' path Locate Suite/Experiment/Simulation file directory.\n'
63
+ ' ps List running processes in a container.\n'
64
+ ' remove-container Remove stopped containers.\n'
65
+ ' status Check the status of an Experiment/Simulation.\n'
66
+ ' stop-container Stop running container(s).\n'
67
+ ' sync-history Sync the file system with job history.\n'
68
+ ' verify-docker Verify the Docker environment.\n'
69
+ ' volume Check the history volume.\n'
70
+ )
71
+ self.assertEqual(result.exit_code, 0)
72
+ self.assertEqual(result.output, expected_help_all)
@@ -0,0 +1,121 @@
1
+ import json
2
+ import os
3
+ import shutil
4
+ import unittest
5
+ from pathlib import Path
6
+ from unittest.mock import patch
7
+ import pytest
8
+ from click.testing import CliRunner
9
+ import idmtools_platform_file.cli.file as file_cli
10
+ from idmtools.core import EntityStatus, ItemType
11
+ from idmtools.core.platform_factory import Platform
12
+ from idmtools.entities.command_task import CommandTask
13
+ from idmtools.entities.experiment import Experiment
14
+ from idmtools_platform_container.container_operations.docker_operations import stop_container
15
+
16
+
17
+ @pytest.mark.serial
18
+ @pytest.mark.cli
19
+ class TestFileContainerPlatformCli(unittest.TestCase):
20
+ @classmethod
21
+ def setUpClass(cls):
22
+ cls.runner = CliRunner()
23
+ cls.job_directory = os.path.join(os.path.dirname(os.path.abspath(__file__)), "DEST")
24
+ cls.platform = Platform("Container", job_directory=cls.job_directory)
25
+ command = "ls -lat"
26
+ task = CommandTask(command=command)
27
+ cls.experiment = Experiment.from_task(task, name="run_command")
28
+ cls.experiment.run(wait_until_done=True)
29
+
30
+
31
+ @classmethod
32
+ def tearDownClass(cls) -> None:
33
+ try:
34
+ stop_container(cls.platform.container_id, remove=True)
35
+ except Exception as e:
36
+ pass
37
+ shutil.rmtree(os.path.join(os.path.dirname(os.path.abspath(__file__)), "DEST"))
38
+
39
+ # Test cli: test status
40
+ # idmtools file DEST status-report --exp-id <exp_id>
41
+ @patch('idmtools_platform_file.tools.status_report.status_report.user_logger')
42
+ def test_status_report(self, mock_user_logger):
43
+ result = self.runner.invoke(file_cli.file,
44
+ [self.job_directory, 'status-report', '--exp-id', self.experiment.id])
45
+ self.assertEqual(result.exit_code, 0)
46
+ actual_messages = [call[0][0] for call in mock_user_logger.info.call_args_list]
47
+
48
+ # verify there are total 18 lines for this cli command
49
+ self.assertEqual(mock_user_logger.info.call_count, 17)
50
+
51
+ # verify first 2 lines as expected messages
52
+ expected_messages_first_2_lines = [
53
+ f"{'experiment: '.ljust(20)} {self.experiment.id}",
54
+ f"{'job directory: '.ljust(20)} {self.job_directory}",
55
+ ]
56
+ self.assertEqual(actual_messages[:2], expected_messages_first_2_lines)
57
+
58
+ # verify last 8 lines as expected messages
59
+ expected_messages_last_few_lines = [
60
+ f"{'status filter: '.ljust(20)} ('0', '-1', '100')",
61
+ f"{'sim filter: '.ljust(20)} None",
62
+ f"{'verbose: '.ljust(20)} True",
63
+ f"{'display: '.ljust(20)} True",
64
+ f"{'Simulation Count: '.ljust(20)} {self.experiment.simulation_count}",
65
+ f"{'Match Count: '.ljust(20)} 1 ({{'0': 1}})",
66
+ f"{'Not Running Count: '.ljust(20)} 0",
67
+ "\nExperiment Status: SUCCEEDED"
68
+ ]
69
+ self.assertEqual(actual_messages[-8:], expected_messages_last_few_lines)
70
+
71
+ # Test cli: get latest experiment info
72
+ # idmtools file job_directory get-latest
73
+ @patch('idmtools_platform_file.cli.file.user_logger')
74
+ def test_get_latest(self, mock_user_logger):
75
+ result = self.runner.invoke(file_cli.file, [self.job_directory, 'get-latest'])
76
+ self.assertEqual(result.exit_code, 0)
77
+ exp_dir = str(self.platform.get_directory_by_id(self.experiment.id, ItemType.EXPERIMENT))
78
+ expected_dict = dict(experiment_id=Path(exp_dir).name,
79
+ experiment_directory=exp_dir,
80
+ job_directory=self.job_directory)
81
+ actual_messages = [call[0][0] for call in mock_user_logger.info.call_args_list]
82
+ self.assertEqual(actual_messages[0], json.dumps(expected_dict, indent=3))
83
+
84
+ # Test cli: Get simulation/experiment's status
85
+ # idmtools file job_directory status --exp-id <exp_id>
86
+ @patch('idmtools_platform_file.tools.status_report.utils.user_logger')
87
+ def test_status(self, mock_user_logger):
88
+ result = self.runner.invoke(file_cli.file, [self.job_directory, 'status', '--exp-id', self.experiment.id])
89
+ self.assertEqual(result.exit_code, 0)
90
+ actual_messages = [call[0][0] for call in mock_user_logger.info.call_args_list]
91
+ exp_dir = str(self.platform.get_directory_by_id(self.experiment.id, ItemType.EXPERIMENT))
92
+ expected_messages = [
93
+ f"\nExperiment Directory: \n{exp_dir}",
94
+ "\nSimulation Count: 1\n",
95
+ "SUCCEEDED (1)",
96
+ "FAILED (0)",
97
+ "RUNNING (0)",
98
+ "PENDING (0)",
99
+ f"\nExperiment Status: SUCCEEDED\n"]
100
+ self.assertEqual(actual_messages, expected_messages)
101
+
102
+ # Test cli: get status of experiment/simulation
103
+ # idmtools file job_directory get-status --exp-id <exp_id>
104
+ @patch('idmtools_platform_file.cli.file.user_logger')
105
+ def test_get_status(self, mock_user_logger):
106
+ result = self.runner.invoke(file_cli.file, [self.job_directory, 'get-status', '--exp-id', self.experiment.id])
107
+ self.assertEqual(result.exit_code, 0)
108
+ mock_user_logger.info.assert_called_with("SUCCEEDED")
109
+
110
+ # Test cli: get path of experiment/simulation
111
+ # idmtools file job_directory get-path --exp-id <exp_id>
112
+ @patch('idmtools_platform_file.cli.file.user_logger')
113
+ def test_get_path(self, mock_user_logger):
114
+ result = self.runner.invoke(file_cli.file, [self.job_directory, 'get-path', '--exp-id', self.experiment.id])
115
+ self.assertEqual(result.exit_code, 0)
116
+ exp_dir = str(self.platform.get_directory_by_id(self.experiment.id, ItemType.EXPERIMENT))
117
+ mock_user_logger.info.assert_called_with(Path(exp_dir))
118
+
119
+
120
+ if __name__ == '__main__':
121
+ unittest.main()
@@ -0,0 +1,60 @@
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.core import ItemType
8
+ from idmtools.entities.command_task import CommandTask
9
+ from idmtools.entities.experiment import Experiment
10
+ from idmtools_platform_container.utils.general import normalize_path
11
+
12
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
13
+ from test_base import TestContainerPlatformCliBase
14
+
15
+
16
+ @pytest.mark.serial
17
+ @pytest.mark.cli
18
+ class TestContainerPlatformGetDetailCli(TestContainerPlatformCliBase):
19
+
20
+ @patch('rich.console.Console.print')
21
+ def test_get_details(self, mock_console):
22
+ command = "sleep 100"
23
+ task = CommandTask(command=command)
24
+ experiment = Experiment.from_task(task, name="run_command")
25
+ experiment.run(wait_until_done=False)
26
+ sleep(1)
27
+ result = self.runner.invoke(container_cli.container, ['get-detail', experiment.id])
28
+ self.assertEqual(result.exit_code, 0)
29
+ self.assertIn(f'"JOB_DIRECTORY": "{normalize_path(self.job_directory)}",',
30
+ mock_console.call_args_list[0].args[0].text)
31
+ exp_dir = self.platform.get_directory_by_id(experiment.id, ItemType.EXPERIMENT)
32
+ self.assertIn(
33
+ f'"EXPERIMENT_DIR": "{normalize_path(exp_dir)}",',
34
+ mock_console.call_args_list[0].args[0].text)
35
+ self.assertIn(f'"EXPERIMENT_NAME": "run_command",',
36
+ mock_console.call_args_list[0].args[0].text)
37
+ self.assertIn(f'"EXPERIMENT_ID": "{experiment.id}",',
38
+ mock_console.call_args_list[0].args[0].text)
39
+ self.assertIn(f'"CONTAINER": "{self.platform.container_id}",',
40
+ mock_console.call_args_list[0].args[0].text)
41
+ self.assertIn(f'"CREATED": ',
42
+ mock_console.call_args_list[0].args[0].text)
43
+ # clean up container
44
+ result = self.runner.invoke(container_cli.container, ['stop-container', self.platform.container_id], '--remove')
45
+ self.assertEqual(result.exit_code, 0)
46
+
47
+ def test_get_detail_help(self):
48
+ result = self.runner.invoke(container_cli.container, ['get-detail', "--help"])
49
+ expected_help = ('Usage: container get-detail [OPTIONS] EXP_ID\n'
50
+ '\n'
51
+ ' Retrieve Experiment history.\n'
52
+ '\n'
53
+ ' Arguments:\n'
54
+ '\n'
55
+ ' EXP_ID: Experiment ID\n'
56
+ '\n'
57
+ 'Options:\n'
58
+ ' --help Show this message and exit.\n')
59
+ self.assertEqual(result.exit_code, 0)
60
+ self.assertEqual(result.output, expected_help)
@@ -0,0 +1,136 @@
1
+ import os
2
+ import re
3
+ import sys
4
+ import unittest
5
+ from pathlib import Path
6
+ from unittest.mock import patch
7
+ import pytest
8
+
9
+ from idmtools.entities import Suite
10
+ from idmtools.entities.command_task import CommandTask
11
+ from idmtools.entities.experiment import Experiment
12
+ import idmtools_platform_container.cli.container as container_cli
13
+ from idmtools_platform_container.container_platform import ContainerPlatform
14
+ from idmtools_platform_container.utils.general import normalize_path
15
+
16
+ sys.path.append(os.path.dirname(os.path.abspath(__file__)))
17
+ from test_base import TestContainerPlatformCliBase
18
+ from helper import cleaned_str
19
+
20
+
21
+ @pytest.mark.serial
22
+ @pytest.mark.cli
23
+ class TestContainerPlatformHistoryCli(TestContainerPlatformCliBase):
24
+ @patch('rich.console.Console.print')
25
+ def test_history(self, mock_console):
26
+ # first clear the history
27
+ result = self.runner.invoke(container_cli.container, ['clear-history'])
28
+ self.assertEqual(result.exit_code, 0)
29
+ command = "sleep 100"
30
+ platform = ContainerPlatform(job_directory=self.job_directory, new_container=True)
31
+ task = CommandTask(command=command)
32
+ experiment = Experiment.from_task(task, name="run_command")
33
+ experiment.run(wait_until_done=False, platform=platform)
34
+ # test history
35
+ result = self.runner.invoke(container_cli.container, ['history'])
36
+ self.assertEqual(result.exit_code, 0)
37
+ self.assertEqual('There are 1 Experiment cache in history.', mock_console.call_args_list[0].args[0])
38
+ self.assertIn(normalize_path(f"{platform.job_directory}"),
39
+ mock_console.call_args_list[2].args[0])
40
+ self.assertEqual('EXPERIMENT_NAME : run_command', cleaned_str(mock_console.call_args_list[3][0][0]))
41
+ self.assertEqual(f'EXPERIMENT_ID : {experiment.id}', cleaned_str(mock_console.call_args_list[4][0][0]))
42
+ self.assertEqual(f'CONTAINER : {platform.container_id}',
43
+ cleaned_str(mock_console.call_args_list[5][0][0]))
44
+ match_created_time = re.match(r'^CREATED : \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$',
45
+ cleaned_str(mock_console.call_args_list[6][0][0]))
46
+ self.assertTrue(match_created_time)
47
+ # Verify history path:
48
+ JOB_HISTORY_DIR = "idmtools_experiment_history"
49
+ history_path = Path.home().joinpath(".idmtools").joinpath(JOB_HISTORY_DIR)
50
+ self.assertTrue(history_path.is_dir())
51
+ self.assertTrue(any(history_path.iterdir())) # verify history path has some files
52
+
53
+ # clean up container
54
+ result = self.runner.invoke(container_cli.container, ['stop-container', platform.container_id, '--remove'])
55
+ self.assertEqual(result.exit_code, 0)
56
+
57
+ @patch('rich.console.Console.print')
58
+ def test_history_with_container(self, mock_console):
59
+ # first clear the history
60
+ result = self.runner.invoke(container_cli.container, ['clear-history'])
61
+ self.assertEqual(result.exit_code, 0)
62
+ command = "sleep 100"
63
+ task = CommandTask(command=command)
64
+ platform = ContainerPlatform(job_directory=self.job_directory, new_container=True)
65
+ experiment = Experiment.from_task(task, name="run_command")
66
+ experiment.run(wait_until_done=False, platform=platform)
67
+ # test history
68
+ result = self.runner.invoke(container_cli.container, ['history', platform.container_id])
69
+ self.assertEqual(result.exit_code, 0)
70
+ self.assertEqual('There are 1 Experiment cache in history.', mock_console.call_args_list[0].args[0])
71
+ self.assertIn(normalize_path(f"{platform.job_directory}"),
72
+ mock_console.call_args_list[2].args[0])
73
+ self.assertEqual('EXPERIMENT_NAME : run_command', cleaned_str(mock_console.call_args_list[3][0][0]))
74
+ self.assertEqual(f'EXPERIMENT_ID : {experiment.id}', cleaned_str(mock_console.call_args_list[4][0][0]))
75
+ self.assertEqual(f'CONTAINER : {platform.container_id}',
76
+ cleaned_str(mock_console.call_args_list[5][0][0]))
77
+ match_created_time = re.match(r'^CREATED : \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$',
78
+ cleaned_str(mock_console.call_args_list[6][0][0]))
79
+ self.assertTrue(match_created_time)
80
+
81
+ # clean up container
82
+ result = self.runner.invoke(container_cli.container, ['stop-container', platform.container_id, '--remove'])
83
+ self.assertEqual(result.exit_code, 0)
84
+
85
+ @patch('rich.console.Console.print')
86
+ def test_history_with_container_suite(self, mock_console):
87
+ # first clear the history
88
+ result = self.runner.invoke(container_cli.container, ['clear-history'])
89
+ self.assertEqual(result.exit_code, 0)
90
+ command = "sleep 100"
91
+ platform = ContainerPlatform(job_directory=self.job_directory, new_container=True)
92
+ task = CommandTask(command=command)
93
+ experiment = Experiment.from_task(task, name="run_command")
94
+ suite = Suite(name="suite_name")
95
+ suite.add_experiment(experiment)
96
+ suite.run(wait_until_done=False)
97
+ # test history
98
+ result = self.runner.invoke(container_cli.container, ['history', platform.container_id])
99
+ self.assertEqual(result.exit_code, 0)
100
+ self.assertEqual('There are 1 Experiment cache in history.', mock_console.call_args_list[0].args[0])
101
+ self.assertIn(normalize_path(f"{platform.job_directory}"),
102
+ mock_console.call_args_list[2].args[0])
103
+ self.assertEqual(f'SUITE_NAME : {suite.name}', cleaned_str(mock_console.call_args_list[3][0][0]))
104
+ self.assertEqual(f'SUITE_ID : {suite.id}', cleaned_str(mock_console.call_args_list[4][0][0]))
105
+ self.assertEqual(f'EXPERIMENT_NAME : {experiment.name}', cleaned_str(mock_console.call_args_list[5][0][0]))
106
+ self.assertEqual(f'EXPERIMENT_ID : {experiment.id}', cleaned_str(mock_console.call_args_list[6][0][0]))
107
+ self.assertEqual(f'CONTAINER : {platform.container_id}',
108
+ cleaned_str(mock_console.call_args_list[7][0][0]))
109
+ match_created_time = re.match(r'^CREATED : \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$',
110
+ cleaned_str(mock_console.call_args_list[8][0][0]))
111
+ self.assertTrue(match_created_time)
112
+
113
+ # clean up container
114
+ result = self.runner.invoke(container_cli.container, ['stop-container', platform.container_id, '--remove'])
115
+ self.assertEqual(result.exit_code, 0)
116
+
117
+ def test_history_help(self):
118
+ result = self.runner.invoke(container_cli.container, ['history', "--help"])
119
+ expected_help = ('Usage: container history [OPTIONS] [CONTAINER_ID]\n'
120
+ '\n'
121
+ ' View the job history.\n'
122
+ '\n'
123
+ ' Arguments:\n'
124
+ '\n'
125
+ ' CONTAINER_ID: Container ID\n'
126
+ '\n'
127
+ 'Options:\n'
128
+ ' -l, --limit INTEGER Max number of jobs to show\n'
129
+ ' -n, --next INTEGER Next number of jobs to show\n'
130
+ ' --help Show this message and exit.\n')
131
+ self.assertEqual(result.exit_code, 0)
132
+ self.assertEqual(result.output, expected_help)
133
+
134
+
135
+ if __name__ == '__main__':
136
+ unittest.main()