From 439166506a9be87be7ec2aebbea74f34e6855a78 Mon Sep 17 00:00:00 2001 From: Cristian Hotea Date: Mon, 23 Apr 2018 14:05:41 +0300 Subject: [PATCH] Add autoremove, force-removal-of-dependent-packages for opkg.remove Add extra options for opkg remove: - --force-removal-of-dependent-packages - Remove package and all dependencies - --autoremove - Remove packages that were installed automatically to satisfy dependencies Add unit tests for opkg module Signed-off-by: Cristian Hotea --- salt/modules/opkg.py | 14 +++ tests/unit/modules/test_opkg.py | 178 ++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 tests/unit/modules/test_opkg.py diff --git a/salt/modules/opkg.py b/salt/modules/opkg.py index 6ac568614d68..412008f85f90 100644 --- a/salt/modules/opkg.py +++ b/salt/modules/opkg.py @@ -509,6 +509,15 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument A list of packages to delete. Must be passed as a python list. The ``name`` parameter will be ignored if this option is passed. + remove_dependencies + Remove package and all dependencies + + .. versionadded:: Fluorine + + auto_remove_deps + Remove packages that were installed automatically to satisfy dependencies + + .. versionadded:: Fluorine Returns a dict containing the changes. @@ -519,6 +528,7 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument salt '*' pkg.remove salt '*' pkg.remove ,, salt '*' pkg.remove pkgs='["foo", "bar"]' + salt '*' pkg.remove pkgs='["foo", "bar"]' remove_dependencies=True auto_remove_deps=True ''' try: pkg_params = __salt__['pkg_resource.parse_targets'](name, pkgs)[0] @@ -530,6 +540,10 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument if not targets: return {} cmd = ['opkg', 'remove'] + if kwargs.get('remove_dependencies', False): + cmd.append('--force-removal-of-dependent-packages') + if kwargs.get('auto_remove_deps', False): + cmd.append('--autoremove') cmd.extend(targets) out = __salt__['cmd.run_all']( diff --git a/tests/unit/modules/test_opkg.py b/tests/unit/modules/test_opkg.py new file mode 100644 index 000000000000..c52d196ecb48 --- /dev/null +++ b/tests/unit/modules/test_opkg.py @@ -0,0 +1,178 @@ +# -*- coding: utf-8 -*- +''' + :synopsis: Unit Tests for Package Management module 'module.opkg' + :platform: Linux +''' +# pylint: disable=import-error,3rd-party-module-not-gated +# Import Python libs +from __future__ import absolute_import, print_function, unicode_literals +import collections +import copy + +# Import Salt Testing Libs +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.unit import TestCase, skipIf +from tests.support.mock import ( + MagicMock, + patch, + NO_MOCK, + NO_MOCK_REASON +) + +# Import Salt Libs +from salt.ext import six +import salt.modules.opkg as opkg +# pylint: disable=import-error,3rd-party-module-not-gated +OPKG_VIM_INFO = { + 'vim': { + 'Package': 'vim', + 'Version': '7.4.769-r0.31', + 'Status': 'install ok installed' + } +} + +OPKG_VIM_FILES = { + 'errors': [], + 'packages': { + 'vim': [ + '/usr/bin/view', + '/usr/bin/vim.vim', + '/usr/bin/xxd', + '/usr/bin/vimdiff', + '/usr/bin/rview', + '/usr/bin/rvim', + '/usr/bin/ex' + ] + } +} + +INSTALLED = { + 'vim': { + 'new': '7.4', + 'old': six.text_type() + } +} + +REMOVED = { + 'vim': { + 'new': six.text_type(), + 'old': '7.4' + } +} +PACKAGES = { + 'vim': '7.4' +} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class OpkgTestCase(TestCase, LoaderModuleMockMixin): + ''' + Test cases for salt.modules.opkg + ''' + def setup_loader_modules(self): # pylint: disable=no-self-use + ''' + Tested modules + ''' + return {opkg: {}} + + def test_version(self): + ''' + Test - Returns a string representing the package version or an empty string if + not installed. + ''' + version = OPKG_VIM_INFO['vim']['Version'] + mock = MagicMock(return_value=version) + with patch.dict(opkg.__salt__, {'pkg_resource.version': mock}): + self.assertEqual(opkg.version(*['vim']), version) + + def test_upgrade_available(self): + ''' + Test - Check whether or not an upgrade is available for a given package. + ''' + with patch('salt.modules.opkg.latest_version', + MagicMock(return_value='')): + self.assertFalse(opkg.upgrade_available('vim')) + + def test_file_dict(self): + ''' + Test - List the files that belong to a package, grouped by package. + ''' + std_out = '\n'.join(OPKG_VIM_FILES['packages']['vim']) + ret_value = {'stdout': std_out} + mock = MagicMock(return_value=ret_value) + with patch.dict(opkg.__salt__, {'cmd.run_all': mock}): + self.assertEqual(opkg.file_dict('vim'), OPKG_VIM_FILES) + + def test_file_list(self): + ''' + Test - List the files that belong to a package. + ''' + std_out = '\n'.join(OPKG_VIM_FILES['packages']['vim']) + ret_value = {'stdout': std_out} + mock = MagicMock(return_value=ret_value) + files = { + 'errors': OPKG_VIM_FILES['errors'], + 'files': OPKG_VIM_FILES['packages']['vim'], + } + with patch.dict(opkg.__salt__, {'cmd.run_all': mock}): + self.assertEqual(opkg.file_list('vim'), files) + + def test_owner(self): + ''' + Test - Return the name of the package that owns the file. + ''' + paths = ['/usr/bin/vimdiff'] + mock = MagicMock(return_value='vim - version - info') + with patch.dict(opkg.__salt__, {'cmd.run_stdout': mock}): + self.assertEqual(opkg.owner(*paths), 'vim') + + def test_install(self): + ''' + Test - Install packages. + ''' + with patch('salt.modules.opkg.list_pkgs', MagicMock(side_effect=[{}, PACKAGES])): + ret_value = {'retcode': 0} + mock = MagicMock(return_value=ret_value) + patch_kwargs = { + '__salt__': { + 'cmd.run_all': mock, + 'pkg_resource.parse_targets': MagicMock(return_value=({'vim': '7.4'}, 'repository')), + 'restartcheck.restartcheck': MagicMock(return_value='No packages seem to need to be restarted') + } + } + with patch.multiple(opkg, **patch_kwargs): + self.assertEqual(opkg.install('vim:7.4'), INSTALLED) + + def test_remove(self): + ''' + Test - Remove packages. + ''' + with patch('salt.modules.opkg.list_pkgs', MagicMock(side_effect=[PACKAGES, {}])): + ret_value = {'retcode': 0} + mock = MagicMock(return_value=ret_value) + patch_kwargs = { + '__salt__': { + 'cmd.run_all': mock, + 'pkg_resource.parse_targets': MagicMock(return_value=({'vim': '7.4'}, 'repository')), + 'restartcheck.restartcheck': MagicMock(return_value='No packages seem to need to be restarted') + } + } + with patch.multiple(opkg, **patch_kwargs): + self.assertEqual(opkg.remove('vim'), REMOVED) + + def test_info_installed(self): + ''' + Test - Return the information of the named package(s) installed on the system. + ''' + installed = copy.deepcopy(OPKG_VIM_INFO['vim']) + del installed['Package'] + ordered_info = collections.OrderedDict(sorted(installed.items())) + expected_dict = {'vim': {k.lower(): v for k, v in ordered_info.items()}} + std_out = '\n'.join([k + ': ' + v for k, v in OPKG_VIM_INFO['vim'].items()]) + ret_value = { + 'stdout': std_out, + 'retcode': 0 + } + mock = MagicMock(return_value=ret_value) + with patch.dict(opkg.__salt__, {'cmd.run_all': mock}): + self.assertEqual(opkg.info_installed('vim'), expected_dict)