From 2a9ade62d6766a69abc498874fd176bde35d6c11 Mon Sep 17 00:00:00 2001 From: Stepan Blyschak Date: Mon, 20 Mar 2023 18:47:56 +0200 Subject: [PATCH] [sonic-package-manager] add support for multiple CLI plugin files Signed-off-by: Stepan Blyschak --- sonic_package_manager/manager.py | 25 ++++++++++++--------- tests/sonic_package_manager/test_manager.py | 25 +++++++++++++++++---- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/sonic_package_manager/manager.py b/sonic_package_manager/manager.py index 54636c7e5f..770641a27a 100644 --- a/sonic_package_manager/manager.py +++ b/sonic_package_manager/manager.py @@ -160,17 +160,18 @@ def get_cli_plugin_directory(command: str) -> str: return plugins_pkg_path -def get_cli_plugin_path(package: Package, command: str) -> str: +def get_cli_plugin_path(package: Package, index: int, command: str) -> str: """ Returns a path where to put CLI plugin code. Args: package: Package to generate this path for. + index: Index of a cli plugin command: SONiC command: "show"/"config"/"clear". Returns: Path generated for this package. """ - plugin_module_file = package.name + '.py' + plugin_module_file = f'{package.name}_{index}.py' return os.path.join(get_cli_plugin_directory(command), plugin_module_file) @@ -978,19 +979,21 @@ def _uninstall_cli_plugins(self, package: Package): self._uninstall_cli_plugin(package, command) def _install_cli_plugin(self, package: Package, command: str): - image_plugin_path = package.manifest['cli'][command] - if not image_plugin_path: + image_plugins = package.manifest['cli'][command] + if not image_plugins: return - host_plugin_path = get_cli_plugin_path(package, command) - self.docker.extract(package.entry.image_id, image_plugin_path, host_plugin_path) + for index, image_plugin_path in enumerate(image_plugins): + host_plugin_path = get_cli_plugin_path(package, index, command) + self.docker.extract(package.entry.image_id, image_plugin_path, host_plugin_path) def _uninstall_cli_plugin(self, package: Package, command: str): - image_plugin_path = package.manifest['cli'][command] - if not image_plugin_path: + image_plugins = package.manifest['cli'][command] + if not image_plugins: return - host_plugin_path = get_cli_plugin_path(package, command) - if os.path.exists(host_plugin_path): - os.remove(host_plugin_path) + for index, _ in enumerate(image_plugins): + host_plugin_path = get_cli_plugin_path(package, index, command) + if os.path.exists(host_plugin_path): + os.remove(host_plugin_path) @staticmethod def get_manager() -> 'PackageManager': diff --git a/tests/sonic_package_manager/test_manager.py b/tests/sonic_package_manager/test_manager.py index a1348514be..bf2594a592 100644 --- a/tests/sonic_package_manager/test_manager.py +++ b/tests/sonic_package_manager/test_manager.py @@ -1,10 +1,11 @@ #!/usr/bin/env python import re -from unittest.mock import Mock, call +from unittest.mock import Mock, call, patch import pytest +import sonic_package_manager from sonic_package_manager.errors import * from sonic_package_manager.version import Version @@ -161,9 +162,25 @@ def test_installation_base_os_constraint_satisfied(package_manager, fake_metadat def test_installation_cli_plugin(package_manager, fake_metadata_resolver, anything): manifest = fake_metadata_resolver.metadata_store['Azure/docker-test']['1.6.0']['manifest'] manifest['cli']= {'show': '/cli/plugin.py'} - package_manager._install_cli_plugins = Mock() - package_manager.install('test-package') - package_manager._install_cli_plugins.assert_called_once_with(anything) + with patch('sonic_package_manager.manager.get_cli_plugin_directory') as get_dir_mock: + get_dir_mock.return_value = '/' + package_manager.install('test-package') + package_manager.docker.extract.assert_called_once_with(anything, '/cli/plugin.py', '/test-package_0.py') + + +def test_installation_multiple_cli_plugin(package_manager, fake_metadata_resolver, anything): + manifest = fake_metadata_resolver.metadata_store['Azure/docker-test']['1.6.0']['manifest'] + manifest['cli']= {'show': ['/cli/plugin.py', '/cli/plugin2.py']} + with patch('sonic_package_manager.manager.get_cli_plugin_directory') as get_dir_mock: + get_dir_mock.return_value = '/' + package_manager.install('test-package') + package_manager.docker.extract.assert_has_calls( + [ + call(anything, '/cli/plugin.py', '/test-package_0.py'), + call(anything, '/cli/plugin2.py', '/test-package_1.py'), + ], + any_order=True, + ) def test_installation_cli_plugin_skipped(package_manager, fake_metadata_resolver, anything):