From 075d4d53e8c84c744d2ab15d8ee989aa668f4030 Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Thu, 31 Oct 2019 15:00:10 +0100 Subject: [PATCH 1/4] Adds list_downloaded to aptpkg module This enables us to use the pkg.downloaded state also for Debian and Ubuntu. --- salt/modules/aptpkg.py | 38 ++++++++++++++++++++++++++++++++++++++ salt/states/pkg.py | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py index ead7c6391ec1..f73ae7f1f99b 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py @@ -384,6 +384,7 @@ def install(name=None, pkgs=None, sources=None, reinstall=False, + downloadonly=False, ignore_epoch=False, **kwargs): ''' @@ -730,6 +731,9 @@ def install(name=None, cmd.extend(downgrade) cmds.append(cmd) + if downloadonly: + cmd.append("--download-only") + if to_reinstall: all_pkgs.extend(to_reinstall) cmd = copy.deepcopy(cmd_prefix) @@ -2840,3 +2844,37 @@ def _get_http_proxy_url(): ) return http_proxy_url + + +def list_downloaded(root=None, **kwargs): + ''' + .. versionadded:: 3000? + + List prefetched packages downloaded by apt in the local disk. + + root + operate on a different root directory. + + CLI example: + + .. code-block:: bash + + salt '*' pkg.list_downloaded + ''' + CACHE_DIR = '/var/cache/apt' + if root: + CACHE_DIR = os.path.join(root, os.path.relpath(CACHE_DIR, os.path.sep)) + + ret = {} + for root, dirnames, filenames in salt.utils.path.os_walk(CACHE_DIR): + for filename in fnmatch.filter(filenames, '*.deb'): + package_path = os.path.join(root, filename) + pkg_info = __salt__['lowpkg.bin_pkg_info'](package_path) + pkg_timestamp = int(os.path.getctime(package_path)) + ret.setdefault(pkg_info['name'], {})[pkg_info['version']] = { + 'path': package_path, + 'size': os.path.getsize(package_path), + 'creation_date_time_t': pkg_timestamp, + 'creation_date_time': datetime.datetime.utcfromtimestamp(pkg_timestamp).isoformat(), + } + return ret \ No newline at end of file diff --git a/salt/states/pkg.py b/salt/states/pkg.py index 0aca1e0af88b..12b265981d29 100644 --- a/salt/states/pkg.py +++ b/salt/states/pkg.py @@ -1971,7 +1971,7 @@ def downloaded(name, (if specified). Currently supported for the following pkg providers: - :mod:`yumpkg ` and :mod:`zypper ` + :mod:`yumpkg `, :mod:`zypper ` and :mod:`zypper ` :param str name: The name of the package to be downloaded. This parameter is ignored if From 61b72453df033aaf3c4d48205b9a3437ea902ace Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Thu, 31 Oct 2019 15:35:26 +0100 Subject: [PATCH 2/4] Correction for comment This should be the success message. --- salt/states/pkg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/states/pkg.py b/salt/states/pkg.py index 12b265981d29..96745096d137 100644 --- a/salt/states/pkg.py +++ b/salt/states/pkg.py @@ -2110,7 +2110,7 @@ def downloaded(name, if not ret['changes'] and not ret['comment']: ret['result'] = True - ret['comment'] = 'Packages are already downloaded: ' \ + ret['comment'] = 'Packages downloaded: ' \ '{0}'.format(', '.join(targets)) return ret From aa26a6bbe63eb3f17a3525d8dbf1ef22130c81e0 Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Mon, 4 Nov 2019 13:39:13 +0100 Subject: [PATCH 3/4] Adds missing imports --- salt/modules/aptpkg.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py index f73ae7f1f99b..84493ee6cf6a 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py @@ -18,6 +18,9 @@ import re import logging import time +import fnmatch +import datetime + # Import third party libs # pylint: disable=no-name-in-module,import-error,redefined-builtin @@ -2877,4 +2880,4 @@ def list_downloaded(root=None, **kwargs): 'creation_date_time_t': pkg_timestamp, 'creation_date_time': datetime.datetime.utcfromtimestamp(pkg_timestamp).isoformat(), } - return ret \ No newline at end of file + return ret From c68c4f73eab4a5ce6f83a43e64752a3e659d69b2 Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Mon, 4 Nov 2019 13:39:35 +0100 Subject: [PATCH 4/4] Unittest for list_downloaded --- tests/unit/modules/test_aptpkg.py | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py index 1e963ee5dbd0..9c2090bb8fbc 100644 --- a/tests/unit/modules/test_aptpkg.py +++ b/tests/unit/modules/test_aptpkg.py @@ -470,6 +470,32 @@ def test_show(self): self.assert_called_once(refresh_mock) refresh_mock.reset_mock() + @patch('salt.utils.path.os_walk', MagicMock(return_value=[('test', 'test', 'test')])) + @patch('os.path.getsize', MagicMock(return_value=123456)) + @patch('os.path.getctime', MagicMock(return_value=1234567890.123456)) + @patch('fnmatch.filter', MagicMock(return_value=['/var/cache/apt/archive/test_package.rpm'])) + def test_list_downloaded(self): + ''' + Test downloaded packages listing. + :return: + ''' + DOWNLOADED_RET = { + 'test-package': { + '1.0': { + 'path': '/var/cache/apt/archive/test_package.rpm', + 'size': 123456, + 'creation_date_time_t': 1234567890, + 'creation_date_time': '2009-02-13T23:31:30', + } + } + } + + with patch.dict(aptpkg.__salt__, {'lowpkg.bin_pkg_info': MagicMock(return_value={'name': 'test-package', + 'version': '1.0'})}): + list_downloaded = aptpkg.list_downloaded() + self.assertEqual(len(list_downloaded), 1) + self.assertDictEqual(list_downloaded, DOWNLOADED_RET) + @skipIf(pytest is None, 'PyTest is missing') class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):