From e96d2f6b36fe753222b7f3076a6f06f2e7f870be Mon Sep 17 00:00:00 2001 From: janosmurai Date: Tue, 8 Oct 2024 17:27:21 +0200 Subject: [PATCH] Reduce registry tool image information retrieval to modify, create and list-tools commands. --- dem/cli/command/create_cmd.py | 1 + dem/cli/command/info_cmd.py | 38 +++++------ dem/cli/command/list_cmd.py | 10 ++- dem/cli/command/list_tools_cmd.py | 10 +-- dem/cli/command/modify_cmd.py | 1 + dem/cli/command/run_cmd.py | 25 ++----- dem/cli/main.py | 2 +- dem/core/dev_env.py | 32 +++------ dem/core/platform.py | 19 ++---- dem/core/tool_images.py | 13 ++-- tests/cli/test_create_cmd.py | 20 +----- tests/cli/test_info_cmd.py | 109 ++++++++++++++---------------- tests/cli/test_list_cmd.py | 29 ++------ tests/cli/test_list_tools_cmd.py | 3 +- tests/cli/test_modify_cmd.py | 12 +++- tests/cli/test_run_cmd.py | 46 ++----------- tests/core/test_dev_env.py | 24 ++++--- tests/core/test_platform.py | 33 +-------- tests/core/test_tool_images.py | 6 +- 19 files changed, 149 insertions(+), 284 deletions(-) diff --git a/dem/cli/command/create_cmd.py b/dem/cli/command/create_cmd.py index ca7ec55..a928169 100644 --- a/dem/cli/command/create_cmd.py +++ b/dem/cli/command/create_cmd.py @@ -116,6 +116,7 @@ def execute(platform: Platform, dev_env_name: str) -> None: Exceptions: Abort -- if the name of the Development Environment contains whitespace characters """ + platform.get_tool_image_info_from_registries = True platform.assign_tool_image_instances_to_all_dev_envs() create_dev_env(platform, dev_env_name) diff --git a/dem/cli/command/info_cmd.py b/dem/cli/command/info_cmd.py index 94f2d16..8406573 100644 --- a/dem/cli/command/info_cmd.py +++ b/dem/cli/command/info_cmd.py @@ -2,19 +2,12 @@ # dem/cli/command/info_cmd.py from dem.core.tool_images import ToolImage -from dem.core.dev_env import DevEnv, DevEnv -from dem.cli.console import stdout, stderr +from dem.core.dev_env import DevEnv from dem.core.platform import Platform +from dem.cli.console import stdout, stderr from rich.table import Table import typer -image_status_messages = { - ToolImage.NOT_AVAILABLE: "[red]Error: not available![/]", - ToolImage.LOCAL_ONLY: "Local", - ToolImage.REGISTRY_ONLY: "Registry", - ToolImage.LOCAL_AND_REGISTRY: "Local and Registry", -} - def print_status(platform: Platform, dev_env: DevEnv) -> None: """ Print the status of the Development Environment. @@ -41,13 +34,24 @@ def print_tools_info_table(dev_env: DevEnv, is_local: bool, platform: Platform = """ tool_info_table = Table(title="Tools") tool_info_table.add_column("Image") - tool_info_table.add_column("Availability") + + if is_local: + tool_info_table.add_column("Available Locally") for tool_image in sorted(dev_env.tool_images, key=lambda x: x.name): - tool_info_table.add_row(tool_image.name, - image_status_messages[tool_image.availability]) + if is_local: + if tool_image.availability == ToolImage.LOCAL_ONLY: + available_locally_output = "[green]\u2713[/]" + else: + available_locally_output = "[red]\u2717[/]" + + tool_info_table.add_row(tool_image.name, available_locally_output) + else: + tool_info_table.add_row(tool_image.name) + if is_local: print_status(platform, dev_env) + stdout.print(tool_info_table) def print_tasks_info_table(dev_env: DevEnv) -> None: @@ -77,11 +81,8 @@ def print_local_dev_env_info(platform: Platform, dev_env: DevEnv) -> None: if dev_env.tasks: print_tasks_info_table(dev_env) - if dev_env.is_installed and dev_env.get_tool_image_status() == DevEnv.Status.REINSTALL_NEEDED: - stderr.print("\n[red]Error: Incomplete local install! The Dev Env must be reinstalled![/]") - - if dev_env.get_tool_image_status() == DevEnv.Status.UNAVAILABLE_IMAGE: - stderr.print("\n[red]Error: Required image could not be found either locally or in the registry![/]") + if dev_env.is_installed and not dev_env.is_installation_correct(): + stderr.print("\n[red]Error: Incorrect local install![/]") def local_info(platform: Platform, dev_env_name: str) -> None: """ Gather and print information about the given local Development Environment. @@ -116,9 +117,6 @@ def print_cat_dev_env_info(dev_env: DevEnv, cat_name: str) -> None: if dev_env.tasks: print_tasks_info_table(dev_env) - if dev_env.get_tool_image_status() == DevEnv.Status.UNAVAILABLE_IMAGE: - stderr.print("\n[red]Error: Required image could not be found in the registry![/]") - def cat_dev_env_info(platform: Platform, dev_env_name: str, selected_cats: list[str]) -> None: """ Gather and print information about the given catalog Development Environment. diff --git a/dem/cli/command/list_cmd.py b/dem/cli/command/list_cmd.py index f4b4693..54075c5 100644 --- a/dem/cli/command/list_cmd.py +++ b/dem/cli/command/list_cmd.py @@ -21,13 +21,11 @@ def add_dev_env_info_to_table(platform: Platform, table: Table, dev_env: DevEnv) if dev_env.is_installed: dev_env.assign_tool_image_instances(platform.tool_images) installed_column = "[green]✓[/]" - tool_image_status = dev_env.get_tool_image_status() - if tool_image_status == DevEnv.Status.UNAVAILABLE_IMAGE: - status_column = "[red]Error: Required image is not available![/]" - elif tool_image_status == DevEnv.Status.REINSTALL_NEEDED: - status_column = "[red]Error: Incomplete local install![/]" - else: + + if dev_env.is_installation_correct(): status_column = "[green]Ok[/]" + else: + status_column = "[red]Error: Incorrect installation![/]" if dev_env.name == platform.default_dev_env_name: default_column = "[green]✓[/]" diff --git a/dem/cli/command/list_tools_cmd.py b/dem/cli/command/list_tools_cmd.py index 1400dd3..6b707e4 100644 --- a/dem/cli/command/list_tools_cmd.py +++ b/dem/cli/command/list_tools_cmd.py @@ -16,9 +16,6 @@ def list_local_tools(platform: Platform) -> None: Exceptions: typer.Abort -- if no local tool images are available """ - # by settings this to True, the update method won't try to update the registry tools - platform.local_only = True - if not platform.tool_images.all_tool_images: stdout.print("[yellow]No local tool images are available.[/]") raise typer.Abort() @@ -39,10 +36,6 @@ def update_tools_from_selected_regs(platform: Platform, selected_regs: list[str] Exceptions: typer.Abort -- if an unknown registry is specified """ - # by settings this to True, the update method won't start automatically so we can provide - # the selected registry names - platform.disable_tool_update = True - available_regs = set([reg["name"] for reg in platform.config_file.registries]) selected_regs = set(selected_regs) @@ -51,7 +44,7 @@ def update_tools_from_selected_regs(platform: Platform, selected_regs: list[str] stderr.print(f"[red]Error: Registry {unkown_reg} is not available![/]") raise typer.Abort() - platform.tool_images.update(reg_selection=selected_regs) + platform.tool_images.update(False, True, reg_selection=selected_regs) def list_tools_from_regs(platform: Platform, table: Table) -> None: """ List the available tools from the registries. @@ -105,6 +98,7 @@ def list_tools_from_all_regs(platform: Platform) -> None: Exceptions: typer.Abort -- if no tool images are available in the registries """ + platform.tool_images.update(False, True) if not platform.tool_images.get_registry_ones(): stdout.print("[yellow]No tool images are available in the registries.[/]") raise typer.Abort() diff --git a/dem/cli/command/modify_cmd.py b/dem/cli/command/modify_cmd.py index 6eed69a..2699d36 100644 --- a/dem/cli/command/modify_cmd.py +++ b/dem/cli/command/modify_cmd.py @@ -166,6 +166,7 @@ def execute(platform: Platform, dev_env_name: str) -> None: typer.Abort -- if the user cancels the operation """ + platform.get_tool_image_info_from_registries = True platform.assign_tool_image_instances_to_all_dev_envs() dev_env = platform.get_dev_env_by_name(dev_env_name) diff --git a/dem/cli/command/run_cmd.py b/dem/cli/command/run_cmd.py index 4d1eea6..0cc7bf3 100644 --- a/dem/cli/command/run_cmd.py +++ b/dem/cli/command/run_cmd.py @@ -16,28 +16,13 @@ def dev_env_health_check(platform: Platform, dev_env: DevEnv) -> None: Raises: typer.Abort -- if the Development Environment has missing tool images """ - # Don't load the registry images to save time. - platform.local_only = True - dev_env.assign_tool_image_instances(platform.tool_images) - dev_env_tool_status = dev_env.get_tool_image_status() - if dev_env_tool_status == DevEnv.Status.UNAVAILABLE_IMAGE: - stderr.print("[red]Error: Required tool images are not available![/]") - stdout.print("Trying to locate the missing tool images...") - # Now we need to load the registry images. - platform.tool_images.update() - dev_env.assign_tool_image_instances(platform.tool_images) - # Get the tool status again. - dev_env_tool_status = dev_env.get_tool_image_status() - if dev_env_tool_status == DevEnv.Status.REINSTALL_NEEDED: - stdout.print("The missing images are available from the registries.") - typer.confirm("Should DEM reinstall the missing images?", abort=True) - platform.install_dev_env(dev_env) - stdout.print(f"[green]DEM successfully fixed the {dev_env.name} Development Environment![/]") - else: - stderr.print("[red]Error: The missing tool images could not be found in the registries![/]") - raise typer.Abort() + if not dev_env.is_installation_correct(): + stderr.print("[red]Error: Incorrect installation![/]") + typer.confirm("Should DEM reinstall the DevEnv?", abort=True) + platform.install_dev_env(dev_env) + stdout.print(f"[green]DEM successfully fixed the {dev_env.name} Development Environment![/]") def execute(platform: Platform, dev_env_name: str, task_name: str) -> None: """ Run a task in a Development Environment. diff --git a/dem/cli/main.py b/dem/cli/main.py index 4a42c3e..e9abeab 100644 --- a/dem/cli/main.py +++ b/dem/cli/main.py @@ -339,7 +339,7 @@ def assign(dev_env_name: Annotated[str, typer.Argument(help="Name of the Dev Env @typer_cli.command() def init(project_path: Annotated[str, typer.Argument(help="Path of the project.")] = os.getcwd()) -> None: """ - Initialize a project to use a Development Environment. + Initialize the DevEnv assigned to the project. If the project path is not specified, the current working directory will be used. """ diff --git a/dem/core/dev_env.py b/dem/core/dev_env.py index b52284d..84c59ef 100755 --- a/dem/core/dev_env.py +++ b/dem/core/dev_env.py @@ -8,12 +8,6 @@ class DevEnv(): """ A Development Environment. """ - class Status(Enum): - """ The status of an installed Development Environment. """ - OK = 0 - REINSTALL_NEEDED = 1 - UNAVAILABLE_IMAGE = 2 - def __init__(self, descriptor: dict | None = None, descriptor_path: str | None = None) -> None: """ Init the DevEnv class. @@ -94,23 +88,19 @@ def del_task(self, task_name: str) -> None: else: raise KeyError(f"Task [bold]{task_name}[/] not found.") - def get_tool_image_status(self) -> Status: - """ Get the status of the Tool Images. - - This method checks the availability of the assigned Tool Images. - If at least one of the Tool Images is unkonwn: NOT_AVAILABLE. - If at least one of the Tool Images is only available in the registry: REINSTALL_NEEDED. - If all the Tool Images are available: OK. + def is_installation_correct(self) -> bool: + """ Check if the installation is correct. - Returns: - Status -- the status of the Dev Env + Return True if the Dev Env is in installed state and all the Tool Images are available, + otherwise False. """ - for tool_image in self.tool_images: - if tool_image.availability == ToolImage.NOT_AVAILABLE: - return self.Status.UNAVAILABLE_IMAGE - elif tool_image.availability == ToolImage.REGISTRY_ONLY: - return self.Status.REINSTALL_NEEDED - return self.Status.OK + if self.is_installed: + for tool_image in self.tool_images: + if tool_image.availability == ToolImage.NOT_AVAILABLE: + break + else: + return True + return False def get_deserialized(self, omit_is_installed: bool = False) -> dict[str, str]: """ Create the deserialized json. diff --git a/dem/core/platform.py b/dem/core/platform.py index c29fc87..de1838d 100644 --- a/dem/core/platform.py +++ b/dem/core/platform.py @@ -42,11 +42,8 @@ def __init__(self) -> None: self.local_dev_envs: list[DevEnv] = [] self.are_tool_images_assigned: bool = False - # Set this to true in the platform instance to work with the local tool images only - self.local_only = False - # Set this to true in the platform instance so when first accessing the `tool_images` - # instance variable, do not automatically update the tool images from the registries - self.disable_tool_update = False + # Set this to true in the platform instance to get the tool image info from the registries + self.get_tool_image_info_from_registries = False def load_dev_envs(self) -> None: """ Load the Development Environments from the dev_env.json file. @@ -75,8 +72,7 @@ def tool_images(self) -> ToolImages: """ if self._tool_images is None: self._tool_images = ToolImages(self.container_engine, self.registries) - if not self.disable_tool_update: - self._tool_images.update(local_only=self.local_only) + self._tool_images.update(True, self.get_tool_image_info_from_registries) return self._tool_images @property @@ -157,14 +153,9 @@ def install_dev_env(self, dev_env_to_install: DevEnv) -> None: Args: dev_env_to_install -- the Development Environment to install """ - # First check if the missing images are available in the registries, so DEM won't start to - # pull the images and then fail. for tool_image in dev_env_to_install.tool_images: - if tool_image.availability == ToolImage.NOT_AVAILABLE: - raise PlatformError(f"The {tool_image.name} image is not available.") - - for tool_image in dev_env_to_install.tool_images: - if tool_image.availability == ToolImage.REGISTRY_ONLY: + if tool_image.availability is ToolImage.REGISTRY_ONLY or \ + tool_image.availability is ToolImage.NOT_AVAILABLE: self.user_output.msg(f"\nPulling image {tool_image.name}", is_title=True) try: self.container_engine.pull(tool_image.name) diff --git a/dem/core/tool_images.py b/dem/core/tool_images.py index f6215d9..26fd2b3 100644 --- a/dem/core/tool_images.py +++ b/dem/core/tool_images.py @@ -44,23 +44,22 @@ def __init__(self, container_engine: ContainerEngine, registries: Registries) -> """ self.container_engine = container_engine self.registries = registries - self.all_tool_images = {} + self.all_tool_images: dict[str, ToolImage] = {} - def update(self, local_only: bool = False, registry_only: bool = False, - reg_selection: list[str] = []) -> None: + def update(self, local: bool, registry: bool, reg_selection: list[str] = []) -> None: """ Update the list of available tools. If the tool image already exists, it will be updated. Args: - local_only -- update the local tools only - registry_only -- update the registry tools only + local -- get the local tools + registry -- get the registry tools """ registry_tool_image_names = [] local_tool_image_names = [] - if not registry_only: + if local: local_tool_image_names = self.container_engine.get_local_tool_images() - if not local_only: + if registry: registry_tool_image_names = self.registries.list_repos(reg_selection) for tool_image_name in local_tool_image_names: diff --git a/tests/cli/test_create_cmd.py b/tests/cli/test_create_cmd.py index 2cd3fc0..121b993 100644 --- a/tests/cli/test_create_cmd.py +++ b/tests/cli/test_create_cmd.py @@ -246,7 +246,7 @@ def test_execute(mock_create_dev_env: MagicMock, mock_stdout_print: MagicMock) - mock_platform = MagicMock() main.platform = mock_platform - mock_dev_env = MagicMock() + mock_platform.get_tool_image_info_from_registries = False expected_dev_env_name = "test_dev_env" # Run unit under test @@ -254,7 +254,9 @@ def test_execute(mock_create_dev_env: MagicMock, mock_stdout_print: MagicMock) - # Check expectations assert 0 == runner_result.exit_code + assert mock_platform.get_tool_image_info_from_registries is True + mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_create_dev_env.assert_called_once_with(mock_platform, expected_dev_env_name) mock_platform.flush_dev_env_properties.assert_called_once() mock_stdout_print.assert_has_calls([ @@ -262,22 +264,6 @@ def test_execute(mock_create_dev_env: MagicMock, mock_stdout_print: MagicMock) - call("Run [italic]dem install[/] to install it.") ]) -@patch("dem.cli.command.create_cmd.create_dev_env") -def test_execute_failure(mock_create_dev_env): - # Test setup - mock_platform = MagicMock() - main.platform = mock_platform - - expected_dev_env_name = "test_dev_env" - - # Run unit under test - runner_result = runner.invoke(main.typer_cli, ["create", expected_dev_env_name], color=True) - - # Check expectations - assert 0 == runner_result.exit_code - - mock_create_dev_env.assert_called_once_with(mock_platform, expected_dev_env_name) - @patch("dem.cli.command.create_cmd.stderr.print") def test_create_dev_env_with_whitespace(mock_stderr_print): # Test setup diff --git a/tests/cli/test_info_cmd.py b/tests/cli/test_info_cmd.py index ec853df..b9376ef 100644 --- a/tests/cli/test_info_cmd.py +++ b/tests/cli/test_info_cmd.py @@ -90,14 +90,49 @@ def test_print_tools_info_table(mock_Table: MagicMock, mock_print_status: MagicM # Verify the output mock_Table.assert_called_once_with(title="Tools") - mock_table.add_column.assert_has_calls([call("Image"), call("Availability")]) - mock_table.add_row.assert_has_calls([call("tool1", "Local and Registry"), - call("tool2", "Local"), - call("tool3", "Registry"), - call("tool4", "[red]Error: not available![/]")]) + mock_table.add_column.assert_has_calls([call("Image"), call("Available Locally")]) + mock_table.add_row.assert_has_calls([call("tool1", "[red]\u2717[/]"), + call("tool2", "[green]\u2713[/]"), + call("tool3", "[red]\u2717[/]"), + call("tool4", "[red]\u2717[/]")]) mock_print_status.assert_called_once_with(mock_platform, mock_dev_env) mock_stdout_print.assert_called_once_with(mock_table) +@patch("dem.cli.command.info_cmd.stdout.print") +@patch("dem.cli.command.info_cmd.print_status") +@patch("dem.cli.command.info_cmd.Table") +def test_print_tools_info_table_catalog(mock_Table: MagicMock, mock_print_status: MagicMock, + mock_stdout_print: MagicMock) -> None: + # Setup + mock_dev_env = MagicMock() + mock_tool_image1 = MagicMock() + mock_tool_image1.name = "tool1" + mock_tool_image1.availability = info_cmd.ToolImage.LOCAL_AND_REGISTRY + mock_tool_image2 = MagicMock() + mock_tool_image2.name = "tool2" + mock_tool_image2.availability = info_cmd.ToolImage.LOCAL_ONLY + mock_tool_image3 = MagicMock() + mock_tool_image3.name = "tool3" + mock_tool_image3.availability = info_cmd.ToolImage.REGISTRY_ONLY + mock_tool_image4 = MagicMock() + mock_tool_image4.name = "tool4" + mock_tool_image4.availability = info_cmd.ToolImage.NOT_AVAILABLE + mock_dev_env.tool_images = [mock_tool_image2, mock_tool_image4, mock_tool_image3, mock_tool_image1] + + mock_table = MagicMock() + mock_Table.return_value = mock_table + + mock_platform = MagicMock() + + # Run the test + info_cmd.print_tools_info_table(mock_dev_env, False) + + # Verify the output + mock_Table.assert_called_once_with(title="Tools") + mock_table.add_column.assert_called_once_with("Image") + mock_table.add_row.assert_has_calls([call("tool1"), call("tool2"), call("tool3"), call("tool4")]) + mock_stdout_print.assert_called_once_with(mock_table) + @patch("dem.cli.command.info_cmd.Table") @patch("dem.cli.command.info_cmd.stdout.print") def test_print_tasks_info_table(mock_stdout_print: MagicMock, mock_Table: MagicMock) -> None: @@ -130,7 +165,7 @@ def test_print_local_dev_env_info(mock_stdout_print: MagicMock, mock_dev_env.name = "test_dev_env" mock_dev_env.tasks = MagicMock() mock_dev_env.is_installed = True - mock_dev_env.get_tool_image_status.return_value = info_cmd.DevEnv.Status.OK + mock_dev_env.is_installation_correct.return_value = True mock_platform = MagicMock() @@ -141,21 +176,22 @@ def test_print_local_dev_env_info(mock_stdout_print: MagicMock, mock_stdout_print.assert_called_once_with("\n[bold]Development Environment: test_dev_env[/]\n") mock_print_tools_info_table.assert_called_once_with(mock_dev_env, True, mock_platform) mock_print_tasks_info_table.assert_called_once_with(mock_dev_env) + mock_dev_env.is_installation_correct.assert_called_once() @patch("dem.cli.command.info_cmd.print_tasks_info_table") @patch("dem.cli.command.info_cmd.print_tools_info_table") @patch("dem.cli.command.info_cmd.stdout.print") @patch("dem.cli.command.info_cmd.stderr.print") -def test_print_local_dev_env_info_reinstall_needed(mock_stderr_print: MagicMock, - mock_stdout_print: MagicMock, - mock_print_tools_info_table: MagicMock, - mock_print_tasks_info_table: MagicMock) -> None: +def test_print_local_dev_env_info_incorrect_install(mock_stderr_print: MagicMock, + mock_stdout_print: MagicMock, + mock_print_tools_info_table: MagicMock, + mock_print_tasks_info_table: MagicMock) -> None: # Setup mock_dev_env = MagicMock() mock_dev_env.name = "test_dev_env" mock_dev_env.tasks = MagicMock() mock_dev_env.is_installed = True - mock_dev_env.get_tool_image_status.return_value = info_cmd.DevEnv.Status.REINSTALL_NEEDED + mock_dev_env.is_installation_correct.return_value = False mock_platform = MagicMock() @@ -166,33 +202,8 @@ def test_print_local_dev_env_info_reinstall_needed(mock_stderr_print: MagicMock, mock_stdout_print.assert_called_once_with("\n[bold]Development Environment: test_dev_env[/]\n") mock_print_tools_info_table.assert_called_once_with(mock_dev_env, True, mock_platform) mock_print_tasks_info_table.assert_called_once_with(mock_dev_env) - mock_stderr_print.assert_called_once_with("\n[red]Error: Incomplete local install! The Dev Env must be reinstalled![/]") - -@patch("dem.cli.command.info_cmd.print_tasks_info_table") -@patch("dem.cli.command.info_cmd.print_tools_info_table") -@patch("dem.cli.command.info_cmd.stdout.print") -@patch("dem.cli.command.info_cmd.stderr.print") -def test_print_local_dev_env_info_unavailable_image(mock_stderr_print: MagicMock, - mock_stdout_print: MagicMock, - mock_print_tools_info_table: MagicMock, - mock_print_tasks_info_table: MagicMock) -> None: - # Setup - mock_dev_env = MagicMock() - mock_dev_env.name = "test_dev_env" - mock_dev_env.tasks = MagicMock() - mock_dev_env.is_installed = True - mock_dev_env.get_tool_image_status.return_value = info_cmd.DevEnv.Status.UNAVAILABLE_IMAGE - - mock_platform = MagicMock() - - # Run the test - info_cmd.print_local_dev_env_info(mock_platform, mock_dev_env) - - # Verify the output - mock_stdout_print.assert_called_once_with("\n[bold]Development Environment: test_dev_env[/]\n") - mock_print_tools_info_table.assert_called_once_with(mock_dev_env, True, mock_platform) - mock_print_tasks_info_table.assert_called_once_with(mock_dev_env) - mock_stderr_print.assert_called_once_with("\n[red]Error: Required image could not be found either locally or in the registry![/]") + mock_dev_env.is_installation_correct.assert_called_once() + mock_stderr_print.assert_called_once_with("\n[red]Error: Incorrect local install![/]") @patch("dem.cli.command.info_cmd.print_local_dev_env_info") def test_local_info(mock_print_local_dev_env_info: MagicMock) -> None: @@ -234,7 +245,6 @@ def test_print_cat_dev_env_info(mock_stdout_print: MagicMock, mock_dev_env = MagicMock() mock_dev_env.name = "test_dev_env" mock_dev_env.tasks = MagicMock() - mock_dev_env.get_tool_image_status.return_value = info_cmd.DevEnv.Status.OK # Run the test info_cmd.print_cat_dev_env_info(mock_dev_env, "test_cat") @@ -245,27 +255,6 @@ def test_print_cat_dev_env_info(mock_stdout_print: MagicMock, mock_print_tools_info_table.assert_called_once_with(mock_dev_env, False) mock_print_tasks_info_table.assert_called_once_with(mock_dev_env) -@patch("dem.cli.command.info_cmd.print_tools_info_table") -@patch("dem.cli.command.info_cmd.stderr.print") -@patch("dem.cli.command.info_cmd.stdout.print") -def test_print_cat_dev_env_info_unavailable_image(mock_stdout_print: MagicMock, - mock_stderr_print: MagicMock, - mock_print_tools_info_table: MagicMock) -> None: - # Setup - mock_dev_env = MagicMock() - mock_dev_env.name = "test_dev_env" - mock_dev_env.tasks = {} - mock_dev_env.get_tool_image_status.return_value = info_cmd.DevEnv.Status.UNAVAILABLE_IMAGE - - # Run the test - info_cmd.print_cat_dev_env_info(mock_dev_env, "test_cat") - - # Verify the output - mock_stdout_print.assert_has_calls([call("\n[bold]Development Environment: test_dev_env[/]\n"), - call(f"Catalog: test_cat\n")]) - mock_print_tools_info_table.assert_called_once_with(mock_dev_env, False) - mock_stderr_print.assert_called_once_with("\n[red]Error: Required image could not be found in the registry![/]") - @patch("dem.cli.command.info_cmd.print_cat_dev_env_info") def test_cat_dev_env_info(mock_print_cat_dev_env_info: MagicMock) -> None: # Setup diff --git a/tests/cli/test_list_cmd.py b/tests/cli/test_list_cmd.py index 46e5434..d3b04f3 100644 --- a/tests/cli/test_list_cmd.py +++ b/tests/cli/test_list_cmd.py @@ -25,14 +25,14 @@ def test_add_dev_env_info_to_table_installed_default() -> None: mock_dev_env = MagicMock() mock_dev_env.is_installed = True mock_dev_env.name = "test_dev_env" - mock_dev_env.get_tool_image_status.return_value = list_cmd.DevEnv.Status.OK + mock_dev_env.is_installation_correct.return_value = True # Run the test list_cmd.add_dev_env_info_to_table(mock_platform, mock_table, mock_dev_env) # Check the result mock_dev_env.assign_tool_image_instances.assert_called_once_with(mock_platform.tool_images) - mock_dev_env.get_tool_image_status.assert_called_once() + mock_dev_env.is_installation_correct.assert_called_once() mock_table.add_row.assert_called_once_with("test_dev_env", "[green]✓[/]", "[green]✓[/]", "[green]Ok[/]") @@ -45,34 +45,15 @@ def test_add_dev_env_info_to_table_installed_unavailable_image() -> None: mock_dev_env = MagicMock() mock_dev_env.is_installed = True mock_dev_env.name = "test_dev_env" - mock_dev_env.get_tool_image_status.return_value = list_cmd.DevEnv.Status.UNAVAILABLE_IMAGE + mock_dev_env.is_installation_correct.return_value = False # Run the test list_cmd.add_dev_env_info_to_table(mock_platform, mock_table, mock_dev_env) # Check the result mock_dev_env.assign_tool_image_instances.assert_called_once_with(mock_platform.tool_images) - mock_dev_env.get_tool_image_status.assert_called_once() - mock_table.add_row.assert_called_once_with("test_dev_env", "[green]✓[/]", "", "[red]Error: Required image is not available![/]") - -def test_add_dev_env_info_to_table_installed_reinstall_needed() -> None: - # Setup - mock_platform = MagicMock() - mock_tool_image = MagicMock() - mock_platform.tool_images = mock_tool_image - mock_table = MagicMock() - mock_dev_env = MagicMock() - mock_dev_env.is_installed = True - mock_dev_env.name = "test_dev_env" - mock_dev_env.get_tool_image_status.return_value = list_cmd.DevEnv.Status.REINSTALL_NEEDED - - # Run the test - list_cmd.add_dev_env_info_to_table(mock_platform, mock_table, mock_dev_env) - - # Check the result - mock_dev_env.assign_tool_image_instances.assert_called_once_with(mock_platform.tool_images) - mock_dev_env.get_tool_image_status.assert_called_once() - mock_table.add_row.assert_called_once_with("test_dev_env", "[green]✓[/]", "", "[red]Error: Incomplete local install![/]") + mock_dev_env.is_installation_correct.assert_called_once() + mock_table.add_row.assert_called_once_with("test_dev_env", "[green]✓[/]", "", "[red]Error: Incorrect installation![/]") def test_add_dev_env_info_to_table_not_installed() -> None: # Setup diff --git a/tests/cli/test_list_tools_cmd.py b/tests/cli/test_list_tools_cmd.py index 8c908ba..8a4a0f0 100644 --- a/tests/cli/test_list_tools_cmd.py +++ b/tests/cli/test_list_tools_cmd.py @@ -66,7 +66,7 @@ def test_update_tools_from_seleted_regs() -> None: list_tools_cmd.update_tools_from_selected_regs(mock_platform, ["test_reg"]) # Check the result - mock_platform.tool_images.update.assert_called_once_with(reg_selection={"test_reg"}) + mock_platform.tool_images.update.assert_called_once_with(False, True, reg_selection={"test_reg"}) def test_list_tools_from_regs() -> None: # Setup @@ -168,6 +168,7 @@ def test_list_tools_from_all_regs(mock_Table: MagicMock, mock_list_tools_from_re list_tools_cmd.list_tools_from_all_regs(mock_platform) # Check the result + mock_platform.tool_images.update.assert_called_once_with(False, True) mock_platform.tool_images.get_registry_ones.assert_called_once() mock_Table.assert_called_once() mock_list_tools_from_regs.assert_called_once_with(mock_platform, mock_table) diff --git a/tests/cli/test_modify_cmd.py b/tests/cli/test_modify_cmd.py index b347320..0e5b71a 100644 --- a/tests/cli/test_modify_cmd.py +++ b/tests/cli/test_modify_cmd.py @@ -257,12 +257,15 @@ def test_execute(mock_modify_with_tui: MagicMock, mock_stdout_print: MagicMock) mock_dev_env = MagicMock() mock_dev_env.is_installed = False + mock_platform.get_tool_image_info_from_registries = False mock_platform.get_dev_env_by_name.return_value = mock_dev_env # Run unit under test modify_cmd.execute(mock_platform, test_dev_env_name) # Check expectations + assert mock_platform.get_tool_image_info_from_registries is True + mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_platform.get_dev_env_by_name.assert_called_once_with(test_dev_env_name) mock_modify_with_tui.assert_called_once_with(mock_platform, mock_dev_env) @@ -279,6 +282,7 @@ def test_execute_installed(mock_stdout_print: MagicMock, mock_confirm: MagicMock mock_dev_env = MagicMock() mock_dev_env.is_installed = True + mock_platform.get_tool_image_info_from_registries = False mock_platform.get_dev_env_by_name.return_value = mock_dev_env test_uninstall_dev_env_status = ["test_uninstall_dev_env_status", @@ -289,6 +293,9 @@ def test_execute_installed(mock_stdout_print: MagicMock, mock_confirm: MagicMock modify_cmd.execute(mock_platform, test_dev_env_name) # Check expectations + assert mock_platform.get_tool_image_info_from_registries is True + + mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_platform.get_dev_env_by_name.assert_called_once_with(test_dev_env_name) mock_stdout_print.assert_has_calls([ @@ -310,7 +317,7 @@ def test_execute_installed_PlatformError(mock_stdout_print: MagicMock, mock_conf test_dev_env_name = "test_dev_env_name" mock_dev_env = MagicMock() mock_dev_env.is_installed = True - + mock_platform.get_tool_image_info_from_registries = False mock_platform.get_dev_env_by_name.return_value = mock_dev_env test_exception_text = "test_exception_text" mock_platform.uninstall_dev_env.side_effect = modify_cmd.PlatformError(test_exception_text) @@ -319,6 +326,9 @@ def test_execute_installed_PlatformError(mock_stdout_print: MagicMock, mock_conf modify_cmd.execute(mock_platform, test_dev_env_name) # Check expectations + assert mock_platform.get_tool_image_info_from_registries is True + + mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_platform.assign_tool_image_instances_to_all_dev_envs.assert_called_once() mock_platform.get_dev_env_by_name.assert_called_once_with(test_dev_env_name) mock_stdout_print.assert_called_once_with("[yellow]The Development Environment is installed, so it can't be modified.[/]") diff --git a/tests/cli/test_run_cmd.py b/tests/cli/test_run_cmd.py index cbb9e9d..25ba8d3 100644 --- a/tests/cli/test_run_cmd.py +++ b/tests/cli/test_run_cmd.py @@ -30,54 +30,18 @@ def test_dev_env_health_check(mock_stderr_print: MagicMock, mock_stdout_print: M mock_dev_env = MagicMock() mock_dev_env.name = "my-dev-env" - mock_dev_env.get_tool_image_status.side_effect = [run_cmd.DevEnv.Status.UNAVAILABLE_IMAGE, - run_cmd.DevEnv.Status.REINSTALL_NEEDED] + mock_dev_env.is_installation_correct.return_value = False # Run run_cmd.dev_env_health_check(mock_platform, mock_dev_env) # Check - assert mock_platform.local_only == True - mock_dev_env.assign_tool_image_instances.assert_called_with(mock_platform.tool_images) - mock_dev_env.get_tool_image_status.assert_called() - mock_stderr_print.assert_called_once_with("[red]Error: Required tool images are not available![/]") - mock_stdout_print.assert_has_calls([ - call("Trying to locate the missing tool images..."), - call("The missing images are available from the registries."), - call(f"[green]DEM successfully fixed the {mock_dev_env.name} Development Environment![/]") - ]) - mock_typer_confirm.assert_called_once_with("Should DEM reinstall the missing images?", - abort=True) + mock_dev_env.is_installation_correct.assert_called() + mock_stderr_print.assert_called_once_with("[red]Error: Incorrect installation![/]") + mock_typer_confirm.assert_called_once_with("Should DEM reinstall the DevEnv?", abort=True) mock_platform.install_dev_env.assert_called_once_with(mock_dev_env) - -@patch("dem.cli.command.run_cmd.stdout.print") -@patch("dem.cli.command.run_cmd.stderr.print") -def test_dev_env_health_check_missing_images_not_found(mock_stderr_print: MagicMock, - mock_stdout_print: MagicMock) -> None: - # Setup - mock_platform = MagicMock() - mock_platform.local_only = False - mock_dev_env = MagicMock() - mock_dev_env.name = "my-dev-env" - - mock_dev_env.get_tool_image_status.return_value = run_cmd.DevEnv.Status.UNAVAILABLE_IMAGE - - # Run - with pytest.raises(typer.Abort): - run_cmd.dev_env_health_check(mock_platform, mock_dev_env) - - # Check - assert mock_platform.local_only == True - - mock_dev_env.assign_tool_image_instances.assert_called_with(mock_platform.tool_images) - mock_dev_env.get_tool_image_status.assert_called() - mock_stderr_print.assert_has_calls([ - call("[red]Error: Required tool images are not available![/]"), - call("[red]Error: The missing tool images could not be found in the registries![/]") - ]) - mock_stdout_print.assert_called_once_with("Trying to locate the missing tool images...") - + mock_stdout_print.assert_called_once_with(f"[green]DEM successfully fixed the {mock_dev_env.name} Development Environment![/]") @patch("dem.cli.command.run_cmd.subprocess.run") @patch("dem.cli.command.run_cmd.dev_env_health_check") diff --git a/tests/core/test_dev_env.py b/tests/core/test_dev_env.py index 12e8a5d..f27eef5 100644 --- a/tests/core/test_dev_env.py +++ b/tests/core/test_dev_env.py @@ -214,11 +214,12 @@ def test_DevEnv_del_task_not_existing() -> None: assert str(exc_info.value) == f"\'Task [bold]{test_task_name}[/] not found.\'" @patch.object(dev_env.DevEnv, "__init__") -def test_DevEnv_get_tool_image_status(mock___init__: MagicMock) -> None: +def test_DevEnv_is_installation_correct_true(mock___init__: MagicMock) -> None: # Test setup mock___init__.return_value = None test_dev_env = dev_env.DevEnv(MagicMock()) + mock_tool_image1 = MagicMock() mock_tool_image1.availability = dev_env.ToolImage.LOCAL_AND_REGISTRY mock_tool_image2 = MagicMock() @@ -227,21 +228,23 @@ def test_DevEnv_get_tool_image_status(mock___init__: MagicMock) -> None: mock_tool_image1, mock_tool_image2 ] + test_dev_env.is_installed = True # Run unit under test - actual_status = test_dev_env.get_tool_image_status() + actual_status = test_dev_env.is_installation_correct() # Check expectations - assert actual_status == dev_env.DevEnv.Status.OK + assert actual_status is True mock___init__.assert_called_once() @patch.object(dev_env.DevEnv, "__init__") -def test_DevEnv_get_tool_image_status_unavailable_image(mock___init__: MagicMock) -> None: +def test_DevEnv_is_installation_correct_false(mock___init__: MagicMock) -> None: # Test setup mock___init__.return_value = None test_dev_env = dev_env.DevEnv(MagicMock()) + mock_tool_image1 = MagicMock() mock_tool_image1.availability = dev_env.ToolImage.NOT_AVAILABLE mock_tool_image2 = MagicMock() @@ -250,21 +253,23 @@ def test_DevEnv_get_tool_image_status_unavailable_image(mock___init__: MagicMock mock_tool_image1, mock_tool_image2 ] + test_dev_env.is_installed = True # Run unit under test - actual_status = test_dev_env.get_tool_image_status() + actual_status = test_dev_env.is_installation_correct() # Check expectations - assert actual_status == dev_env.DevEnv.Status.UNAVAILABLE_IMAGE + assert actual_status is False mock___init__.assert_called_once() @patch.object(dev_env.DevEnv, "__init__") -def test_DevEnv_get_tool_image_status_reinstall_needed(mock___init__: MagicMock) -> None: +def test_DevEnv_is_installation_correct_not_istalled(mock___init__: MagicMock) -> None: # Test setup mock___init__.return_value = None test_dev_env = dev_env.DevEnv(MagicMock()) + mock_tool_image1 = MagicMock() mock_tool_image1.availability = dev_env.ToolImage.REGISTRY_ONLY mock_tool_image2 = MagicMock() @@ -273,12 +278,13 @@ def test_DevEnv_get_tool_image_status_reinstall_needed(mock___init__: MagicMock) mock_tool_image1, mock_tool_image2 ] + test_dev_env.is_installed = False # Run unit under test - actual_status = test_dev_env.get_tool_image_status() + actual_status = test_dev_env.is_installation_correct() # Check expectations - assert actual_status == dev_env.DevEnv.Status.REINSTALL_NEEDED + assert actual_status is False mock___init__.assert_called_once() diff --git a/tests/core/test_platform.py b/tests/core/test_platform.py index 0683503..cc20d18 100644 --- a/tests/core/test_platform.py +++ b/tests/core/test_platform.py @@ -96,8 +96,7 @@ def test_Platform_tool_images(mock___init__: MagicMock, mock_ToolImages: MagicMo test_platform._container_engine = mock_container_engine test_platform._registries = mock_registries test_platform._tool_images = None - test_platform.disable_tool_update = False - test_platform.local_only = False + test_platform.get_tool_image_info_from_registries = False mock_tool_images = MagicMock() mock_ToolImages.return_value = mock_tool_images @@ -111,7 +110,7 @@ def test_Platform_tool_images(mock___init__: MagicMock, mock_ToolImages: MagicMo mock___init__.assert_called_once() mock_ToolImages.assert_called_once_with(mock_container_engine, mock_registries) - mock_tool_images.update.assert_called_once_with(local_only=test_platform.local_only) + mock_tool_images.update.assert_called_once_with(True, test_platform.get_tool_image_info_from_registries) @patch("dem.core.platform.ContainerEngine") @patch.object(platform.Platform, "__init__") @@ -364,34 +363,6 @@ def test_Platform_install_dev_env_pull_failure(mock___init__: MagicMock, mock_us is_title=True) mock_container_engine.pull.assert_called_once_with(expected_registry_only_tool_image) -@patch.object(platform.Platform, "tool_images") -@patch.object(platform.Platform, "container_engine") -@patch.object(platform.Platform, "user_output") -@patch.object(platform.Platform, "__init__") -def test_Platform_install_dev_env_with_not_avilable_tool_image(mock___init__: MagicMock, - mock_user_output: MagicMock, - mock_container_engine: MagicMock, - mock_tool_images) -> None: - # Test setup - mock___init__.return_value = None - - mock_dev_env = MagicMock() - mock_tool_image = MagicMock() - mock_tool_image.name = "test_image_name1:test_image_version1" - mock_tool_image.availability = platform.ToolImage.NOT_AVAILABLE - mock_dev_env.tool_images = [mock_tool_image] - - test_platform = platform.Platform() - - # Run unit under test - with pytest.raises(platform.PlatformError) as exported_exception_info: - test_platform.install_dev_env(mock_dev_env) - - # Check expectations - assert str(exported_exception_info.value) == f"Platform error: The test_image_name1:test_image_version1 image is not available." - - mock___init__.assert_called_once() - @patch.object(platform.Platform, "flush_dev_env_properties") @patch.object(platform.Platform, "container_engine") @patch.object(platform.Platform, "assign_tool_image_instances_to_all_dev_envs") diff --git a/tests/core/test_tool_images.py b/tests/core/test_tool_images.py index c3e10c9..972618e 100644 --- a/tests/core/test_tool_images.py +++ b/tests/core/test_tool_images.py @@ -51,7 +51,7 @@ def test_ToolImages_update() -> None: } # Run unit under test - tool_images_instance.update() + tool_images_instance.update(True, True) # Check expectations assert len(tool_images_instance.all_tool_images) == 5 @@ -79,7 +79,7 @@ def test_ToolImages_get_local_ones() -> None: mock_registries.list_repos.return_value = test_registry_tool_images tool_images_instance = tool_images.ToolImages(mock_container_engine, mock_registries) - tool_images_instance.update() + tool_images_instance.update(True, True) # Run unit under test local_tool_images = tool_images_instance.get_local_ones() @@ -108,7 +108,7 @@ def test_ToolImages_get_registry_ones() -> None: mock_registries.list_repos.return_value = test_registry_tool_images tool_images_instance = tool_images.ToolImages(mock_container_engine, mock_registries) - tool_images_instance.update() + tool_images_instance.update(True, True) # Run unit under test registry_tool_images = tool_images_instance.get_registry_ones()