From 9608a343ff54d057c6dad06236d0216cd7f7bc5da3aa32d9968722f171160a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 13 Apr 2021 15:36:55 +0000 Subject: [PATCH 1/2] osc copypac from project:systemsmanagement:saltstack:testing package:salt revision:393 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=187 --- _lastrevision | 2 +- ...d-linux-2-by-backporting-upstream-s-.patch | 76 +++++ ...d-alibaba-cloud-linux-to-the-os-fami.patch | 131 ++++++++ ...vendor-change-option-with-zypper-313.patch | 292 ++++++++++++++++++ ...beacon-for-debian-ubuntu-systems-347.patch | 92 ++++++ ...f-salt-ssh-on-processing-targets-353.patch | 27 ++ salt.changes | 42 +++ salt.spec | 19 ++ ...x-for-salt-ssh-to-process-targets-li.patch | 98 ++++++ 9 files changed, 778 insertions(+), 1 deletion(-) create mode 100644 add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch create mode 100644 add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch create mode 100644 allow-vendor-change-option-with-zypper-313.patch create mode 100644 notify-beacon-for-debian-ubuntu-systems-347.patch create mode 100644 regression-fix-of-salt-ssh-on-processing-targets-353.patch create mode 100644 update-target-fix-for-salt-ssh-to-process-targets-li.patch diff --git a/_lastrevision b/_lastrevision index 922d560..e5f7c2a 100644 --- a/_lastrevision +++ b/_lastrevision @@ -1 +1 @@ -68bd2c45e40cf64ac426a7e5833daa076ab10cfe \ No newline at end of file +4d10df19ca9defdab8bacf1371c6d36037601a7f \ No newline at end of file diff --git a/add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch b/add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch new file mode 100644 index 0000000..c9cc62b --- /dev/null +++ b/add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch @@ -0,0 +1,76 @@ +From ec0d11ed66e8541a9ccaebc85aab4724013fb71f Mon Sep 17 00:00:00 2001 +From: Pau Garcia Quiles +Date: Tue, 13 Apr 2021 10:31:09 +0200 +Subject: [PATCH] Add Alibaba Cloud Linux 2 by backporting upstream's + grain and discarding my own (#352) + +--- + salt/grains/core.py | 4 ++-- + tests/unit/grains/test_core.py | 26 +++++++++++++++++--------- + 2 files changed, 19 insertions(+), 11 deletions(-) + +diff --git a/salt/grains/core.py b/salt/grains/core.py +index 09f9d29788..2b965a2a8a 100644 +--- a/salt/grains/core.py ++++ b/salt/grains/core.py +@@ -1547,7 +1547,7 @@ _OS_NAME_MAP = { + "slesexpand": "RES", + "linuxmint": "Mint", + "neon": "KDE neon", +- "alibaba": "Alibaba Cloud (Aliyun)", ++ "alibabaclo": "Alinux", + } + + # Map the 'os' grain to the 'os_family' grain +@@ -1622,7 +1622,7 @@ _OS_FAMILY_MAP = { + "AIX": "AIX", + "TurnKey": "Debian", + "AstraLinuxCE": "Debian", +- "Alibaba Cloud (Aliyun)": "RedHat", ++ "Alinux": "RedHat", + } + + # Matches any possible format: +diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py +index 6aa05abe40..8280d6de47 100644 +--- a/tests/unit/grains/test_core.py ++++ b/tests/unit/grains/test_core.py +@@ -782,17 +782,25 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): + Test if OS grains are parsed correctly in Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS + ''' + _os_release_map = { +- '_linux_distribution': ('Alibaba Cloud Linux (Aliyun Linux)', '2.1903', 'Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)'), ++ "os_release_file": { ++ "NAME": "Alibaba Cloud Linux (Aliyun Linux)", ++ "VERSION": "2.1903 LTS (Hunting Beagle)", ++ "VERSION_ID": "2.1903", ++ "PRETTY_NAME": "Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)", ++ "ID": "alinux", ++ "ANSI_COLOR": "0;31", ++ }, ++ "_linux_distribution": ("alinux", "2.1903", "LTS"), + } + expectation = { +- 'os': 'Alibaba Cloud (Aliyun)', +- 'os_family': 'RedHat', +- 'oscodename': 'Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)', +- 'osfullname': 'Alibaba Cloud Linux (Aliyun Linux)', +- 'osrelease': '2.1903', +- 'osrelease_info': (2, 1903), +- 'osmajorrelease': 2, +- 'osfinger': 'Alibaba Cloud Linux (Aliyun Linux)-2', ++ "os": "Alinux", ++ "os_family": "RedHat", ++ "oscodename": "Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)", ++ "osfullname": "Alibaba Cloud Linux (Aliyun Linux)", ++ "osrelease": "2.1903", ++ "osrelease_info": (2, 1903), ++ "osmajorrelease": 2, ++ "osfinger": "Alibaba Cloud Linux (Aliyun Linux)-2", + } + self._run_os_grains_tests(None, _os_release_map, expectation) + +-- +2.30.2 + + diff --git a/add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch b/add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch new file mode 100644 index 0000000..23e27bf --- /dev/null +++ b/add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch @@ -0,0 +1,131 @@ +From beec6f3945bda722bfe9c0aa606065f04c89bc62 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?= + +Date: Wed, 24 Mar 2021 14:12:34 +0100 +Subject: [PATCH] Add AlmaLinux and Alibaba Cloud Linux to the OS + Family list (#341) + +* Add AlmaLinux and Alibaba Cloud Linux to the OS Family list + +* Fix some grains tests +--- + salt/grains/core.py | 4 +++ + tests/unit/grains/test_core.py | 51 +++++++++++++++++++++++++++++++++- + 2 files changed, 54 insertions(+), 1 deletion(-) + +diff --git a/salt/grains/core.py b/salt/grains/core.py +index 5634327623..09f9d29788 100644 +--- a/salt/grains/core.py ++++ b/salt/grains/core.py +@@ -1532,6 +1532,7 @@ _OS_NAME_MAP = { + "oracleserv": "OEL", + "cloudserve": "CloudLinux", + "cloudlinux": "CloudLinux", ++ "almalinux": "AlmaLinux", + "pidora": "Fedora", + "scientific": "ScientificLinux", + "synology": "Synology", +@@ -1546,6 +1547,7 @@ _OS_NAME_MAP = { + "slesexpand": "RES", + "linuxmint": "Mint", + "neon": "KDE neon", ++ "alibaba": "Alibaba Cloud (Aliyun)", + } + + # Map the 'os' grain to the 'os_family' grain +@@ -1563,6 +1565,7 @@ _OS_FAMILY_MAP = { + "Scientific": "RedHat", + "Amazon": "RedHat", + "CloudLinux": "RedHat", ++ "AlmaLinux": "RedHat", + "OVS": "RedHat", + "OEL": "RedHat", + "XCP": "RedHat", +@@ -1619,6 +1622,7 @@ _OS_FAMILY_MAP = { + "AIX": "AIX", + "TurnKey": "Debian", + "AstraLinuxCE": "Debian", ++ "Alibaba Cloud (Aliyun)": "RedHat", + } + + # Matches any possible format: +diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py +index 15de4e363e..6aa05abe40 100644 +--- a/tests/unit/grains/test_core.py ++++ b/tests/unit/grains/test_core.py +@@ -678,6 +678,35 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): + } + self._run_os_grains_tests(None, _os_release_map, expectation) + ++ @skipIf(not salt.utils.platform.is_linux(), "System is not Linux") ++ def test_almalinux_8_os_grains(self): ++ """ ++ Test if OS grains are parsed correctly in AlmaLinux 8 ++ """ ++ _os_release_map = { ++ "os_release_file": { ++ "NAME": "AlmaLinux", ++ "VERSION_ID": "8.3", ++ "PRETTY_NAME": "AlmaLinux 8", ++ "ID": "almalinux", ++ "ANSI_COLOR": "0;31", ++ "CPE_NAME": "cpe:/o:almalinux:almalinux:8.3", ++ }, ++ "_linux_distribution": ("almaLinux", "8.3", ""), ++ } ++ ++ expectation = { ++ "os": "AlmaLinux", ++ "os_family": "RedHat", ++ "oscodename": "AlmaLinux 8", ++ "osfullname": "AlmaLinux", ++ "osrelease": "8.3", ++ "osrelease_info": (8, 3,), ++ "osmajorrelease": 8, ++ "osfinger": "AlmaLinux-8", ++ } ++ self._run_os_grains_tests(None, _os_release_map, expectation) ++ + def test_unicode_error(self): + raise_unicode_mock = MagicMock( + name="raise_unicode_error", side_effect=UnicodeError +@@ -733,7 +762,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): + Test if OS grains are parsed correctly in Astra Linux CE 2.12.22 "orel" + """ + _os_release_map = { +- "linux_distribution": ("AstraLinuxCE", "2.12.22", "orel"), ++ "_linux_distribution": ("AstraLinuxCE", "2.12.22", "orel"), + } + expectation = { + "os": "AstraLinuxCE", +@@ -747,6 +776,26 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin): + } + self._run_os_grains_tests("astralinuxce-2.12.22", _os_release_map, expectation) + ++ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux') ++ def test_aliyunlinux2_os_grains(self): ++ ''' ++ Test if OS grains are parsed correctly in Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS ++ ''' ++ _os_release_map = { ++ '_linux_distribution': ('Alibaba Cloud Linux (Aliyun Linux)', '2.1903', 'Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)'), ++ } ++ expectation = { ++ 'os': 'Alibaba Cloud (Aliyun)', ++ 'os_family': 'RedHat', ++ 'oscodename': 'Alibaba Cloud Linux (Aliyun Linux) 2.1903 LTS (Hunting Beagle)', ++ 'osfullname': 'Alibaba Cloud Linux (Aliyun Linux)', ++ 'osrelease': '2.1903', ++ 'osrelease_info': (2, 1903), ++ 'osmajorrelease': 2, ++ 'osfinger': 'Alibaba Cloud Linux (Aliyun Linux)-2', ++ } ++ self._run_os_grains_tests(None, _os_release_map, expectation) ++ + @skipIf(not salt.utils.platform.is_windows(), "System is not Windows") + def test_windows_platform_data(self): + """ +-- +2.30.2 + + diff --git a/allow-vendor-change-option-with-zypper-313.patch b/allow-vendor-change-option-with-zypper-313.patch new file mode 100644 index 0000000..ae57faa --- /dev/null +++ b/allow-vendor-change-option-with-zypper-313.patch @@ -0,0 +1,292 @@ +From 33ad6876a04e800afc08748133dc568a5e362903 Mon Sep 17 00:00:00 2001 +From: Martin Seidl +Date: Wed, 17 Mar 2021 14:05:42 +0100 +Subject: [PATCH] Allow vendor change option with zypper (#313) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +* add patch support for allow vendor change option with zypper + +* adjust unit tests vendor change refactor, dropping cli arg + +* Fix pr issues + +Co-authored-by: Pablo Suárez Hernández + +* Fix unit test for allow vendor change on upgrade + +* Add unit test with unsupported zypper version + +Co-authored-by: Pablo Suárez Hernández +--- + salt/modules/zypperpkg.py | 58 +++++++++++++--- + tests/unit/modules/test_zypperpkg.py | 99 ++++++++++++++++++---------- + 2 files changed, 112 insertions(+), 45 deletions(-) + +diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py +index 6f22994bf0..b35792237c 100644 +--- a/salt/modules/zypperpkg.py ++++ b/salt/modules/zypperpkg.py +@@ -105,6 +105,10 @@ class _Zypper: + ZYPPER_LOCK = "/var/run/zypp.pid" + TAG_RELEASED = "zypper/released" + TAG_BLOCKED = "zypper/blocked" ++ # Dist upgrade vendor change support (SLE12+) ++ dup_avc = False ++ # Install/Patch/Upgrade vendor change support (SLE15+) ++ inst_avc = False + + def __init__(self): + """ +@@ -218,6 +222,21 @@ class _Zypper: + def pid(self): + return self.__call_result.get("pid", "") + ++ def refresh_zypper_flags(self): ++ try: ++ zypp_version = version('zypper') ++ # zypper version 1.11.34 in SLE12 update supports vendor change for only dist upgrade ++ if version_cmp(zypp_version, '1.11.34') >= 0: ++ # zypper version supports vendor change for dist upgrade ++ self.dup_avc = True ++ # zypper version 1.14.8 in SLE15 update supports vendor change in install/patch/upgrading ++ if version_cmp(zypp_version, '1.14.8') >= 0: ++ self.inst_avc = True ++ else: ++ log.error("Failed to compare Zypper version") ++ except Exception as ex: ++ log.error("Unable to get Zypper version: {}".format(ex)) ++ + def _is_error(self): + """ + Is this is an error code? +@@ -1431,6 +1450,7 @@ def install( + no_recommends=False, + root=None, + inclusion_detection=False, ++ novendorchange=True, + **kwargs + ): + """ +@@ -1478,6 +1498,9 @@ def install( + skip_verify + Skip the GPG verification check (e.g., ``--no-gpg-checks``) + ++ novendorchange ++ Disallow vendor change ++ + version + Can be either a version number, or the combination of a comparison + operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4'). +@@ -1638,6 +1661,15 @@ def install( + cmd_install.append( + kwargs.get("resolve_capabilities") and "--capability" or "--name" + ) ++ # Install / patching / upgrade with vendor change support is only in SLE 15+ opensuse Leap 15+ ++ if not novendorchange: ++ __zypper__(root=root).refresh_zypper_flags() ++ if __zypper__(root=root).inst_avc: ++ cmd_install.append("--allow-vendor-change") ++ log.info("Enabling vendor changes") ++ else: ++ log.warning("Enabling/Disabling vendor changes is not supported on this Zypper version") ++ + + if not refresh: + cmd_install.insert(0, "--no-refresh") +@@ -1793,19 +1825,25 @@ def upgrade( + cmd_update.extend(["--from" if dist_upgrade else "--repo", repo]) + log.info("Targeting repos: %s", fromrepo) + +- if dist_upgrade: +- # TODO: Grains validation should be moved to Zypper class +- if __grains__["osrelease_info"][0] > 11: +- if novendorchange: +- cmd_update.append("--no-allow-vendor-change") +- log.info("Disabling vendor changes") +- else: ++ if not novendorchange: ++ __zypper__(root=root).refresh_zypper_flags() ++ if dist_upgrade: ++ if __zypper__(root=root).dup_avc: + cmd_update.append("--allow-vendor-change") + log.info("Enabling vendor changes") ++ else: ++ log.warning( ++ "Enabling/Disabling vendor changes is not supported on this Zypper version" ++ ) + else: +- log.warning( +- "Enabling/Disabling vendor changes is not supported on this Zypper version" +- ) ++ # Install / patching / upgrade with vendor change support is only in SLE 15+ opensuse Leap 15+ ++ if __zypper__(root=root).inst_avc: ++ cmd_update.append("--allow-vendor-change") ++ log.info("Enabling vendor changes") ++ else: ++ log.warning( ++ "Enabling/Disabling vendor changes is not supported on this Zypper version" ++ ) + + if no_recommends: + cmd_update.append("--no-recommends") +diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py +index 9c4a224c55..f32c382d7f 100644 +--- a/tests/unit/modules/test_zypperpkg.py ++++ b/tests/unit/modules/test_zypperpkg.py +@@ -644,7 +644,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + zypper_mock.assert_any_call( + "dist-upgrade", + "--auto-agree-with-licenses", +- "--no-allow-vendor-change", + ) + + with patch( +@@ -691,46 +690,80 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + "dist-upgrade", + "--auto-agree-with-licenses", + "--dry-run", +- "--no-allow-vendor-change", + ) + zypper_mock.assert_any_call( + "dist-upgrade", + "--auto-agree-with-licenses", + "--dry-run", +- "--no-allow-vendor-change", + ) + + with patch( + "salt.modules.zypperpkg.list_pkgs", +- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]) + ): +- ret = zypper.upgrade( +- dist_upgrade=True, +- dryrun=True, +- fromrepo=["Dummy", "Dummy2"], +- novendorchange=False, +- ) +- zypper_mock.assert_any_call( +- "dist-upgrade", +- "--auto-agree-with-licenses", +- "--dry-run", +- "--from", +- "Dummy", +- "--from", +- "Dummy2", +- "--allow-vendor-change", +- ) +- zypper_mock.assert_any_call( +- "dist-upgrade", +- "--auto-agree-with-licenses", +- "--dry-run", +- "--from", +- "Dummy", +- "--from", +- "Dummy2", +- "--allow-vendor-change", +- "--debug-solver", +- ) ++ with patch.dict(zypper.__salt__, ++ {'pkg_resource.version': MagicMock(return_value='1.15'), ++ 'lowpkg.version_cmp': MagicMock(return_value=1)}): ++ ret = zypper.upgrade( ++ dist_upgrade=True, ++ dryrun=True, ++ fromrepo=["Dummy", "Dummy2"], ++ novendorchange=False, ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ "--allow-vendor-change", ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ "--allow-vendor-change", ++ "--debug-solver", ++ ) ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]) ++ ): ++ with patch.dict(zypper.__salt__, ++ {'pkg_resource.version': MagicMock(return_value='1.11'), ++ 'lowpkg.version_cmp': MagicMock(return_value=1)}): ++ ret = zypper.upgrade( ++ dist_upgrade=True, ++ dryrun=True, ++ fromrepo=["Dummy", "Dummy2"], ++ novendorchange=False, ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ "--debug-solver", ++ ) + + with patch( + "salt.modules.zypperpkg.list_pkgs", +@@ -750,7 +783,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + "Dummy", + "--from", + "Dummy2", +- "--no-allow-vendor-change", + ) + zypper_mock.assert_any_call( + "dist-upgrade", +@@ -760,7 +792,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + "Dummy", + "--from", + "Dummy2", +- "--no-allow-vendor-change", + "--debug-solver", + ) + +@@ -797,7 +828,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + "Dummy", + "--from", + "Dummy2", +- "--no-allow-vendor-change", + ) + + with patch( +@@ -911,7 +941,6 @@ Repository 'DUMMY' not found by its alias, number, or URI. + "--auto-agree-with-licenses", + "--from", + "DUMMY", +- "--no-allow-vendor-change", + ) + + def test_upgrade_available(self): +-- +2.30.1 + + diff --git a/notify-beacon-for-debian-ubuntu-systems-347.patch b/notify-beacon-for-debian-ubuntu-systems-347.patch new file mode 100644 index 0000000..ad13002 --- /dev/null +++ b/notify-beacon-for-debian-ubuntu-systems-347.patch @@ -0,0 +1,92 @@ +From e0f8087409bdff4c3036e38ed4f22f5f031306e8 Mon Sep 17 00:00:00 2001 +From: Ricardo Mateus +Date: Fri, 9 Apr 2021 10:57:27 +0100 +Subject: [PATCH] Notify beacon for Debian/Ubuntu systems (#347) + +Signed-off-by: Ricardo Mateus +(cherry picked from commit 33d6baebba94cc7a66d5555de984ca98684157a0) +--- + scripts/suse/dpkg/99dpkgnotify | 1 + + scripts/suse/dpkg/README.md | 9 +++++++ + scripts/suse/dpkg/dpkgnotify | 44 ++++++++++++++++++++++++++++++++++ + 3 files changed, 54 insertions(+) + create mode 100644 scripts/suse/dpkg/99dpkgnotify + create mode 100644 scripts/suse/dpkg/README.md + create mode 100644 scripts/suse/dpkg/dpkgnotify + +diff --git a/scripts/suse/dpkg/99dpkgnotify b/scripts/suse/dpkg/99dpkgnotify +new file mode 100644 +index 0000000000..8013387a57 +--- /dev/null ++++ b/scripts/suse/dpkg/99dpkgnotify +@@ -0,0 +1 @@ ++DPkg::Post-Invoke {"/usr/bin/dpkgnotify";}; +diff --git a/scripts/suse/dpkg/README.md b/scripts/suse/dpkg/README.md +new file mode 100644 +index 0000000000..b7a75c4786 +--- /dev/null ++++ b/scripts/suse/dpkg/README.md +@@ -0,0 +1,9 @@ ++## What it is ++ ++Debian base package to notify installation of new packages outside the control of salt. ++ ++## Installation ++This script depends on python package, so python3 should be installed on the machine ++ ++- The 99dpkgnotify file must be installed in /etc/apt/apt.conf.d/99dpkgnotify ++- The dpkgnotify file must be installed in /usr/bin/dpkgnotify +diff --git a/scripts/suse/dpkg/dpkgnotify b/scripts/suse/dpkg/dpkgnotify +new file mode 100644 +index 0000000000..d3ad3d2ba9 +--- /dev/null ++++ b/scripts/suse/dpkg/dpkgnotify +@@ -0,0 +1,44 @@ ++#!/usr/bin/python3 ++ ++import os ++import hashlib ++ ++CK_PATH = "/var/cache/salt/minion/dpkg.cookie" ++DPKG_PATH = "/var/lib/dpkg/status" ++ ++def _get_mtime(): ++ """ ++ Get the modified time of the Package Database. ++ Returns: ++ Unix ticks ++ """ ++ return os.path.exists(DPKG_PATH) and int(os.path.getmtime(DPKG_PATH)) or 0 ++ ++ ++def _get_checksum(): ++ """ ++ Get the checksum of the Package Database. ++ Returns: ++ hexdigest ++ """ ++ digest = hashlib.sha256() ++ with open(DPKG_PATH, "rb") as pkg_db_fh: ++ while True: ++ buff = pkg_db_fh.read(0x1000) ++ if not buff: ++ break ++ digest.update(buff) ++ return digest.hexdigest() ++ ++ ++def dpkg_post_invoke(): ++ """ ++ Hook after the package installation transaction. ++ """ ++ if 'SALT_RUNNING' not in os.environ: ++ with open(CK_PATH, 'w') as ck_fh: ++ ck_fh.write('{chksum} {mtime}\n'.format(chksum=_get_checksum(), mtime=_get_mtime())) ++ ++ ++if __name__ == "__main__": ++ dpkg_post_invoke() +-- +2.30.2 + + diff --git a/regression-fix-of-salt-ssh-on-processing-targets-353.patch b/regression-fix-of-salt-ssh-on-processing-targets-353.patch new file mode 100644 index 0000000..577241c --- /dev/null +++ b/regression-fix-of-salt-ssh-on-processing-targets-353.patch @@ -0,0 +1,27 @@ +From 543969c927df2f73662ac6ac19467d66d33e0577 Mon Sep 17 00:00:00 2001 +From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> +Date: Tue, 13 Apr 2021 18:00:42 +0300 +Subject: [PATCH] Regression fix of salt-ssh on processing targets + (#353) + +--- + salt/client/ssh/__init__.py | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py +index 1edb7b3b23..0a76627fe3 100644 +--- a/salt/client/ssh/__init__.py ++++ b/salt/client/ssh/__init__.py +@@ -435,8 +435,6 @@ class SSH: + self.opts["tgt"] = _hosts + elif _hosts: + self.opts["tgt"] = _hosts[0] +- else: +- self.opts["tgt"] = "" + + def get_pubkey(self): + """ +-- +2.30.2 + + diff --git a/salt.changes b/salt.changes index e146fbd..16230d4 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,45 @@ +------------------------------------------------------------------- +Tue Apr 13 15:03:48 UTC 2021 - Pablo Suárez Hernández + +- Regression fix of salt-ssh on processing some targets + +- Added: + * regression-fix-of-salt-ssh-on-processing-targets-353.patch + +------------------------------------------------------------------- +Tue Apr 13 08:40:32 UTC 2021 - Pablo Suárez Hernández + +- Add support for Alibaba Cloud Linux 2 (Aliyun Linux) + +- Added: + * add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch + +------------------------------------------------------------------- +Fri Apr 9 14:39:50 UTC 2021 - Victor Zhestkov + +- Update target fix for salt-ssh to process targets list (bsc#1179831) + +- Added: + * update-target-fix-for-salt-ssh-to-process-targets-li.patch + +------------------------------------------------------------------- +Fri Apr 9 10:33:54 UTC 2021 - Alexander Graul + +- Add notify beacon for Debian/Ubuntu systems +- Add core grains support for AlmaLinux and Alibaba Could Linux + +- Added: + * add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch + * notify-beacon-for-debian-ubuntu-systems-347.patch + +------------------------------------------------------------------- +Wed Mar 17 14:17:05 UTC 2021 - Jochen Breuer + +- Allow vendor change option with zypper + +- Added: + * allow-vendor-change-option-with-zypper-313.patch + ------------------------------------------------------------------- Wed Mar 10 08:42:54 UTC 2021 - Pablo Suárez Hernández diff --git a/salt.spec b/salt.spec index 60d08cc..7b1cd54 100644 --- a/salt.spec +++ b/salt.spec @@ -381,6 +381,19 @@ Patch159: do-not-monkey-patch-yaml-bsc-1177474.patch Patch160: 3002-set-distro-requirement-to-oldest-supported-vers.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/59693 Patch161: virt.network_update-handle-missing-ipv4-netmask-attr.patch +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/313 +Patch162: allow-vendor-change-option-with-zypper-313.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/59404 +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/341 +Patch163: add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/347 +Patch164: notify-beacon-for-debian-ubuntu-systems-347.patch +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/336 +Patch165: update-target-fix-for-salt-ssh-to-process-targets-li.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/59687 +Patch166: add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/353 +Patch167: regression-fix-of-salt-ssh-on-processing-targets-353.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate @@ -937,6 +950,12 @@ cp %{S:5} ./.travis.yml %patch159 -p1 %patch160 -p1 %patch161 -p1 +%patch162 -p1 +%patch163 -p1 +%patch164 -p1 +%patch165 -p1 +%patch166 -p1 +%patch167 -p1 %build # Putting /usr/bin at the front of $PATH is needed for RHEL/RES 7. Without this diff --git a/update-target-fix-for-salt-ssh-to-process-targets-li.patch b/update-target-fix-for-salt-ssh-to-process-targets-li.patch new file mode 100644 index 0000000..52b9e69 --- /dev/null +++ b/update-target-fix-for-salt-ssh-to-process-targets-li.patch @@ -0,0 +1,98 @@ +From a603d31c4d3ace3590952ef848f4244c41abe7c8 Mon Sep 17 00:00:00 2001 +From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> +Date: Fri, 9 Apr 2021 16:01:32 +0300 +Subject: [PATCH] Update target fix for salt-ssh to process targets + list (bsc#1179831) (#336) + +* Update target fix for salt-ssh to process targets list (bsc#1179831) + +* Improvement for fixing (bsc#1179831) +--- + salt/client/ssh/__init__.py | 48 ++++++++++++++++++++++++------------- + 1 file changed, 31 insertions(+), 17 deletions(-) + +diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py +index 6570fba5b1..1edb7b3b23 100644 +--- a/salt/client/ssh/__init__.py ++++ b/salt/client/ssh/__init__.py +@@ -325,7 +325,7 @@ class SSH: + if not self.opts.get("ssh_cli_tgt"): + self.opts["ssh_cli_tgt"] = self.opts.get("tgt", "") + hostname = self.opts.get("ssh_cli_tgt", "") +- if "@" in hostname: ++ if isinstance(hostname, str) and "@" in hostname: + user, hostname = hostname.split("@", 1) + else: + user = self.opts.get("ssh_user") +@@ -376,7 +376,7 @@ class SSH: + self.__parsed_rosters[self.ROSTER_UPDATE_FLAG] = False + return + +- def _update_roster(self): ++ def _update_roster(self, hostname=None, user=None): + """ + Update default flat roster with the passed in information. + :return: +@@ -391,8 +391,8 @@ class SSH: + "\n passwd: {passwd}\n".format( + s_user=getpass.getuser(), + s_time=datetime.datetime.utcnow().isoformat(), +- hostname=self.opts.get("tgt", ""), +- user=self.opts.get("ssh_user", ""), ++ hostname=hostname if hostname else self.opts.get("tgt", ""), ++ user=user if user else self.opts.get("ssh_user", ""), + passwd=self.opts.get("ssh_passwd", ""), + ) + ) +@@ -409,20 +409,34 @@ class SSH: + Uptade targets in case hostname was directly passed without the roster. + :return: + """ +- hostname = self.parse_tgt["hostname"] ++ hosts = self.parse_tgt["hostname"] + user = self.parse_tgt["user"] +- if hostname == "*": +- hostname = "" +- +- if salt.utils.network.is_reachable_host(hostname): +- self.opts["tgt"] = hostname +- self.targets[hostname] = { +- "passwd": self.opts.get("ssh_passwd", ""), +- "host": hostname, +- "user": user, +- } +- if self.opts.get("ssh_update_roster"): +- self._update_roster() ++ ++ if not isinstance(hosts, (list, tuple)): ++ hosts = list([hosts]) ++ _hosts = list() ++ for hostname in hosts: ++ _user = user ++ if "@" in hostname: ++ _user, hostname = hostname.split("@", 1) ++ if hostname == "*": ++ continue ++ if salt.utils.network.is_reachable_host(hostname): ++ _hosts.append(hostname) ++ self.targets[hostname] = { ++ "passwd": self.opts.get("ssh_passwd", ""), ++ "host": hostname, ++ "user": _user, ++ } ++ if self.opts.get("ssh_update_roster"): ++ self._update_roster(hostname=hostname, user=_user) ++ ++ if self.tgt_type == "list": ++ self.opts["tgt"] = _hosts ++ elif _hosts: ++ self.opts["tgt"] = _hosts[0] ++ else: ++ self.opts["tgt"] = "" + + def get_pubkey(self): + """ +-- +2.31.1 + + From dbb3d0d524ddcaf8a4e4eb5194ed219f6c77dc0c7cff9efd337b13b0fa289e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Tue, 20 Apr 2021 15:28:29 +0000 Subject: [PATCH 2/2] osc copypac from project:systemsmanagement:saltstack:testing package:salt revision:394 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=188 --- _lastrevision | 2 +- improvements-on-ansiblegate-module-354.patch | 521 +++++++++++++++++++ salt.changes | 10 + salt.spec | 3 + 4 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 improvements-on-ansiblegate-module-354.patch diff --git a/_lastrevision b/_lastrevision index e5f7c2a..463ecd2 100644 --- a/_lastrevision +++ b/_lastrevision @@ -1 +1 @@ -4d10df19ca9defdab8bacf1371c6d36037601a7f \ No newline at end of file +a94708ad2eba9aa15413d989ab3361b2c980589e \ No newline at end of file diff --git a/improvements-on-ansiblegate-module-354.patch b/improvements-on-ansiblegate-module-354.patch new file mode 100644 index 0000000..b56c907 --- /dev/null +++ b/improvements-on-ansiblegate-module-354.patch @@ -0,0 +1,521 @@ +From aa0f845e2bbc37332db04c583f475cfe25304db6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= + +Date: Tue, 20 Apr 2021 11:01:26 +0100 +Subject: [PATCH] Improvements on "ansiblegate" module (#354) + +* Allow collecting Ansible Inventory from a minion + +* Prevent crashing if ansible-playbook doesn't return JSON + +* Add new 'ansible.discover_playbooks' method + +* Include custom inventory when discovering Ansible playbooks + +* Enhance 'ansible.discover_playbooks' to accept a list of locations + +* Remove unused constants from Ansible utils + +* Avoid string concatenation to calculate extra cmd args + +* Add unit test for ansible.targets + +* Improve Ansible roster targetting + +* Add tests for new ansiblegate module functions + +* Fix issue dealing with ungrouped targets on inventory + +* Enable ansible utils for ansible roster tests + +* Remove unnecessary code from Ansible utils + +* Fix pylint issue + +* Fix issue in documentation +--- + salt/modules/ansiblegate.py | 166 +++++++++++++++++- + salt/roster/ansible.py | 18 +- + salt/utils/ansible.py | 44 +++++ + .../pytests/unit/modules/test_ansiblegate.py | 94 +++++++++- + .../example_playbooks/example-playbook2/hosts | 7 + + .../example-playbook2/site.yml | 28 +++ + .../playbooks/example_playbooks/playbook1.yml | 5 + + tests/unit/roster/test_ansible.py | 2 +- + 8 files changed, 354 insertions(+), 10 deletions(-) + create mode 100644 salt/utils/ansible.py + create mode 100644 tests/unit/files/playbooks/example_playbooks/example-playbook2/hosts + create mode 100644 tests/unit/files/playbooks/example_playbooks/example-playbook2/site.yml + create mode 100644 tests/unit/files/playbooks/example_playbooks/playbook1.yml + +diff --git a/salt/modules/ansiblegate.py b/salt/modules/ansiblegate.py +index 5d4b986ec2..4f96607a07 100644 +--- a/salt/modules/ansiblegate.py ++++ b/salt/modules/ansiblegate.py +@@ -426,7 +426,171 @@ def playbooks( + } + ret = __salt__["cmd.run_all"](**cmd_kwargs) + log.debug("Ansible Playbook Return: %s", ret) +- retdata = json.loads(ret["stdout"]) ++ try: ++ retdata = json.loads(ret["stdout"]) ++ except ValueError: ++ retdata = ret + if "retcode" in ret: + __context__["retcode"] = retdata["retcode"] = ret["retcode"] + return retdata ++ ++ ++def targets(**kwargs): ++ """ ++ Return the inventory from an Ansible inventory_file ++ ++ :param inventory: ++ The inventory file to read the inventory from. Default: "/etc/ansible/hosts" ++ ++ :param yaml: ++ Return the inventory as yaml output. Default: False ++ ++ :param export: ++ Return inventory as export format. Default: False ++ ++ CLI Example: ++ ++ .. code-block:: bash ++ ++ salt 'ansiblehost' ansible.targets ++ salt 'ansiblehost' ansible.targets inventory=my_custom_inventory ++ ++ """ ++ return __utils__["ansible.targets"](**kwargs) ++ ++ ++def discover_playbooks(path=None, ++ locations=None, ++ playbook_extension=None, ++ hosts_filename=None, ++ syntax_check=False): ++ """ ++ Discover Ansible playbooks stored under the given path or from multiple paths (locations) ++ ++ This will search for files matching with the playbook file extension under the given ++ root path and will also look for files inside the first level of directories in this path. ++ ++ The return of this function would be a dict like this: ++ ++ .. code-block:: python ++ ++ { ++ "/home/foobar/": { ++ "my_ansible_playbook.yml": { ++ "fullpath": "/home/foobar/playbooks/my_ansible_playbook.yml", ++ "custom_inventory": "/home/foobar/playbooks/hosts" ++ }, ++ "another_playbook.yml": { ++ "fullpath": "/home/foobar/playbooks/another_playbook.yml", ++ "custom_inventory": "/home/foobar/playbooks/hosts" ++ }, ++ "lamp_simple/site.yml": { ++ "fullpath": "/home/foobar/playbooks/lamp_simple/site.yml", ++ "custom_inventory": "/home/foobar/playbooks/lamp_simple/hosts" ++ }, ++ "lamp_proxy/site.yml": { ++ "fullpath": "/home/foobar/playbooks/lamp_proxy/site.yml", ++ "custom_inventory": "/home/foobar/playbooks/lamp_proxy/hosts" ++ } ++ }, ++ "/srv/playbooks/": { ++ "example_playbook/example.yml": { ++ "fullpath": "/srv/playbooks/example_playbook/example.yml", ++ "custom_inventory": "/srv/playbooks/example_playbook/hosts" ++ } ++ } ++ } ++ ++ :param path: ++ Path to discover playbooks from. ++ ++ :param locations: ++ List of paths to discover playbooks from. ++ ++ :param playbook_extension: ++ File extension of playbooks file to search for. Default: "yml" ++ ++ :param hosts_filename: ++ Filename of custom playbook inventory to search for. Default: "hosts" ++ ++ :param syntax_check: ++ Skip playbooks that do not pass "ansible-playbook --syntax-check" validation. Default: False ++ ++ :return: ++ The discovered playbooks under the given paths ++ ++ CLI Example: ++ ++ .. code-block:: bash ++ ++ salt 'ansiblehost' ansible.discover_playbooks path=/srv/playbooks/ ++ salt 'ansiblehost' ansible.discover_playbooks locations='["/srv/playbooks/", "/srv/foobar"]' ++ ++ """ ++ ++ if not path and not locations: ++ raise CommandExecutionError("You have to specify either 'path' or 'locations' arguments") ++ ++ if path and locations: ++ raise CommandExecutionError("You cannot specify 'path' and 'locations' at the same time") ++ ++ if not playbook_extension: ++ playbook_extension = "yml" ++ if not hosts_filename: ++ hosts_filename = "hosts" ++ ++ if path: ++ if not os.path.isabs(path): ++ raise CommandExecutionError("The given path is not an absolute path: {}".format(path)) ++ if not os.path.isdir(path): ++ raise CommandExecutionError("The given path is not a directory: {}".format(path)) ++ return {path: _explore_path(path, playbook_extension, hosts_filename, syntax_check)} ++ ++ if locations: ++ all_ret = {} ++ for location in locations: ++ all_ret[location] = _explore_path(location, playbook_extension, hosts_filename, syntax_check) ++ return all_ret ++ ++ ++def _explore_path(path, playbook_extension, hosts_filename, syntax_check): ++ ret = {} ++ ++ if not os.path.isabs(path): ++ log.error("The given path is not an absolute path: {}".format(path)) ++ return ret ++ if not os.path.isdir(path): ++ log.error("The given path is not a directory: {}".format(path)) ++ return ret ++ ++ try: ++ # Check files in the given path ++ for _f in os.listdir(path): ++ _path = os.path.join(path, _f) ++ if os.path.isfile(_path) and _path.endswith("." + playbook_extension): ++ ret[_f] = {"fullpath": _path} ++ # Check for custom inventory file ++ if os.path.isfile(os.path.join(path, hosts_filename)): ++ ret[_f].update({"custom_inventory": os.path.join(path, hosts_filename)}) ++ elif os.path.isdir(_path): ++ # Check files in the 1st level of subdirectories ++ for _f2 in os.listdir(_path): ++ _path2 = os.path.join(_path, _f2) ++ if os.path.isfile(_path2) and _path2.endswith("." + playbook_extension): ++ ret[os.path.join(_f, _f2)] = {"fullpath": _path2} ++ # Check for custom inventory file ++ if os.path.isfile(os.path.join(_path, hosts_filename)): ++ ret[os.path.join(_f, _f2)].update({"custom_inventory": os.path.join(_path, hosts_filename)}) ++ except Exception as exc: ++ raise CommandExecutionError("There was an exception while discovering playbooks: {}".format(exc)) ++ ++ # Run syntax check validation ++ if syntax_check: ++ check_command = ["ansible-playbook", "--syntax-check"] ++ try: ++ for pb in list(ret): ++ if __salt__["cmd.retcode"](check_command + [ret[pb]]): ++ del ret[pb] ++ except Exception as exc: ++ raise CommandExecutionError("There was an exception while checking syntax of playbooks: {}".format(exc)) ++ return ret +diff --git a/salt/roster/ansible.py b/salt/roster/ansible.py +index f17316bdd7..cc61f6fb7d 100644 +--- a/salt/roster/ansible.py ++++ b/salt/roster/ansible.py +@@ -89,7 +89,6 @@ Any of the [groups] or direct hostnames will return. The 'all' is special, and + """ + # Import Python libs + from __future__ import absolute_import, print_function, unicode_literals +- + import copy + import fnmatch + +@@ -121,27 +120,32 @@ def targets(tgt, tgt_type="glob", **kwargs): + Return the targets from the ansible inventory_file + Default: /etc/salt/roster + """ +- inventory = __runner__["salt.cmd"]( +- "cmd.run", "ansible-inventory -i {0} --list".format(get_roster_file(__opts__)) +- ) +- __context__["inventory"] = __utils__["json.loads"]( +- __utils__["stringutils.to_str"](inventory) ++ __context__["inventory"] = __utils__["ansible.targets"]( ++ inventory=get_roster_file(__opts__), **kwargs + ) + + if tgt_type == "glob": + hosts = [ + host for host in _get_hosts_from_group("all") if fnmatch.fnmatch(host, tgt) + ] ++ elif tgt_type == "list": ++ hosts = [host for host in _get_hosts_from_group("all") if host in tgt] + elif tgt_type == "nodegroup": + hosts = _get_hosts_from_group(tgt) ++ else: ++ hosts = [] ++ + return {host: _get_hostvars(host) for host in hosts} + + + def _get_hosts_from_group(group): + inventory = __context__["inventory"] ++ if group not in inventory: ++ return [] + hosts = [host for host in inventory[group].get("hosts", [])] + for child in inventory[group].get("children", []): +- if child != "ungrouped": ++ child_info = _get_hosts_from_group(child) ++ if child_info not in hosts: + hosts.extend(_get_hosts_from_group(child)) + return hosts + +diff --git a/salt/utils/ansible.py b/salt/utils/ansible.py +new file mode 100644 +index 0000000000..ee85cb656c +--- /dev/null ++++ b/salt/utils/ansible.py +@@ -0,0 +1,44 @@ ++# -*- coding: utf-8 -*- ++# Import Python libs ++from __future__ import absolute_import, print_function, unicode_literals ++import logging ++import os ++ ++# Import Salt libs ++import salt.utils.json ++import salt.utils.path ++import salt.utils.stringutils ++import salt.modules.cmdmod ++from salt.exceptions import CommandExecutionError ++ ++__virtualname__ = "ansible" ++ ++log = logging.getLogger(__name__) ++ ++ ++def __virtual__(): # pylint: disable=expected-2-blank-lines-found-0 ++ if salt.utils.path.which("ansible-inventory"): ++ return __virtualname__ ++ return (False, "Install `ansible` to use inventory") ++ ++ ++def targets(inventory="/etc/ansible/hosts", **kwargs): ++ """ ++ Return the targets from the ansible inventory_file ++ Default: /etc/salt/roster ++ """ ++ if not os.path.isfile(inventory): ++ raise CommandExecutionError("Inventory file not found: {}".format(inventory)) ++ ++ extra_cmd = [] ++ if "export" in kwargs: ++ extra_cmd.append("--export") ++ if "yaml" in kwargs: ++ extra_cmd.append("--yaml") ++ inv = salt.modules.cmdmod.run( ++ "ansible-inventory -i {} --list {}".format(inventory, " ".join(extra_cmd)) ++ ) ++ if kwargs.get("yaml", False): ++ return salt.utils.stringutils.to_str(inv) ++ else: ++ return salt.utils.json.loads(salt.utils.stringutils.to_str(inv)) +diff --git a/tests/pytests/unit/modules/test_ansiblegate.py b/tests/pytests/unit/modules/test_ansiblegate.py +index 42c0968a6e..24c7e5e6b3 100644 +--- a/tests/pytests/unit/modules/test_ansiblegate.py ++++ b/tests/pytests/unit/modules/test_ansiblegate.py +@@ -8,8 +8,11 @@ import pytest + import salt.modules.ansiblegate as ansible + import salt.utils.path + import salt.utils.platform ++import salt.config ++import salt.loader + from salt.exceptions import LoaderError + from tests.support.mock import MagicMock, MockTimedProc, patch ++from tests.support.runtests import RUNTIME_VARS + + pytestmark = pytest.mark.skipif( + salt.utils.platform.is_windows(), reason="Not supported on Windows" +@@ -18,7 +21,7 @@ pytestmark = pytest.mark.skipif( + + @pytest.fixture + def configure_loader_modules(): +- return {ansible: {}} ++ return {ansible: {"__utils__": {}}} + + + @pytest.fixture +@@ -201,3 +204,92 @@ def test_ansible_playbooks_return_retcode(resolver): + ): + ret = ansible.playbooks("fake-playbook.yml") + assert "retcode" in ret ++ ++ ++def test_ansible_targets(): ++ """ ++ Test ansible.targets execution module function. ++ :return: ++ """ ++ ansible_inventory_ret = """ ++{ ++ "_meta": { ++ "hostvars": { ++ "uyuni-stable-ansible-centos7-1.tf.local": { ++ "ansible_ssh_private_key_file": "/etc/ansible/my_ansible_private_key" ++ }, ++ "uyuni-stable-ansible-centos7-2.tf.local": { ++ "ansible_ssh_private_key_file": "/etc/ansible/my_ansible_private_key" ++ } ++ } ++ }, ++ "all": { ++ "children": [ ++ "ungrouped" ++ ] ++ }, ++ "ungrouped": { ++ "hosts": [ ++ "uyuni-stable-ansible-centos7-1.tf.local", ++ "uyuni-stable-ansible-centos7-2.tf.local" ++ ] ++ } ++} ++ """ ++ ansible_inventory_mock = MagicMock(return_value=ansible_inventory_ret) ++ with patch("salt.utils.path.which", MagicMock(return_value=True)): ++ opts = salt.config.DEFAULT_MINION_OPTS.copy() ++ utils = salt.loader.utils(opts, whitelist=["ansible"]) ++ with patch("salt.modules.cmdmod.run", ansible_inventory_mock), patch.dict( ++ ansible.__utils__, utils), patch( ++ "os.path.isfile", MagicMock(return_value=True) ++ ): ++ ret = ansible.targets() ++ assert ansible_inventory_mock.call_args ++ assert "_meta" in ret ++ assert "uyuni-stable-ansible-centos7-1.tf.local" in ret["_meta"]["hostvars"] ++ assert "ansible_ssh_private_key_file" in ret["_meta"]["hostvars"]["uyuni-stable-ansible-centos7-1.tf.local"] ++ assert "all" in ret ++ assert len(ret["ungrouped"]["hosts"]) == 2 ++ ++ ++def test_ansible_discover_playbooks_single_path(): ++ playbooks_dir = os.path.join( ++ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/" ++ ) ++ ret = ansible.discover_playbooks(playbooks_dir) ++ assert playbooks_dir in ret ++ assert ret[playbooks_dir]["playbook1.yml"] == { ++ "fullpath": os.path.join(playbooks_dir, "playbook1.yml") ++ } ++ assert ret[playbooks_dir]["example-playbook2/site.yml"] == { ++ "fullpath": os.path.join(playbooks_dir, "example-playbook2/site.yml"), ++ "custom_inventory": os.path.join(playbooks_dir, "example-playbook2/hosts"), ++ } ++ ++ ++def test_ansible_discover_playbooks_single_path_using_parameters(): ++ playbooks_dir = os.path.join( ++ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/" ++ ) ++ ret = ansible.discover_playbooks( ++ playbooks_dir, playbook_extension="foobar", hosts_filename="deadbeaf" ++ ) ++ assert playbooks_dir in ret ++ assert ret[playbooks_dir] == {} ++ ++ ++def test_ansible_discover_playbooks_multiple_locations(): ++ playbooks_dir = os.path.join( ++ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/" ++ ) ++ ret = ansible.discover_playbooks(locations=[playbooks_dir, "/tmp/foobar"]) ++ assert playbooks_dir in ret ++ assert "/tmp/foobar" in ret ++ assert ret[playbooks_dir]["playbook1.yml"] == { ++ "fullpath": os.path.join(playbooks_dir, "playbook1.yml") ++ } ++ assert ret[playbooks_dir]["example-playbook2/site.yml"] == { ++ "fullpath": os.path.join(playbooks_dir, "example-playbook2/site.yml"), ++ "custom_inventory": os.path.join(playbooks_dir, "example-playbook2/hosts"), ++ } +diff --git a/tests/unit/files/playbooks/example_playbooks/example-playbook2/hosts b/tests/unit/files/playbooks/example_playbooks/example-playbook2/hosts +new file mode 100644 +index 0000000000..75783285f6 +--- /dev/null ++++ b/tests/unit/files/playbooks/example_playbooks/example-playbook2/hosts +@@ -0,0 +1,7 @@ ++[databases] ++host1 ++host2 ++ ++[webservers] ++host3 ++host4 +diff --git a/tests/unit/files/playbooks/example_playbooks/example-playbook2/site.yml b/tests/unit/files/playbooks/example_playbooks/example-playbook2/site.yml +new file mode 100644 +index 0000000000..a64ebd5e18 +--- /dev/null ++++ b/tests/unit/files/playbooks/example_playbooks/example-playbook2/site.yml +@@ -0,0 +1,28 @@ ++--- ++- name: update web servers ++ hosts: webservers ++ remote_user: root ++ ++ tasks: ++ - name: ensure apache is at the latest version ++ yum: ++ name: httpd ++ state: latest ++ - name: write the apache config file ++ template: ++ src: /srv/httpd.j2 ++ dest: /etc/httpd.conf ++ ++- name: update db servers ++ hosts: databases ++ remote_user: root ++ ++ tasks: ++ - name: ensure postgresql is at the latest version ++ yum: ++ name: postgresql ++ state: latest ++ - name: ensure that postgresql is started ++ service: ++ name: postgresql ++ state: started +diff --git a/tests/unit/files/playbooks/example_playbooks/playbook1.yml b/tests/unit/files/playbooks/example_playbooks/playbook1.yml +new file mode 100644 +index 0000000000..e258a101e1 +--- /dev/null ++++ b/tests/unit/files/playbooks/example_playbooks/playbook1.yml +@@ -0,0 +1,5 @@ ++--- ++- hosts: all ++ gather_facts: false ++ tasks: ++ - ping: +diff --git a/tests/unit/roster/test_ansible.py b/tests/unit/roster/test_ansible.py +index a5cdcbbdbc..8bc9c1c6f7 100644 +--- a/tests/unit/roster/test_ansible.py ++++ b/tests/unit/roster/test_ansible.py +@@ -71,7 +71,7 @@ class AnsibleRosterTestCase(TestCase, mixins.LoaderModuleMockMixin): + opts = salt.config.master_config( + os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master") + ) +- utils = salt.loader.utils(opts, whitelist=["json", "stringutils"]) ++ utils = salt.loader.utils(opts, whitelist=["json", "stringutils", "ansible"]) + runner = salt.loader.runner(opts, utils=utils, whitelist=["salt"]) + return {ansible: {"__utils__": utils, "__opts__": {}, "__runner__": runner}} + +-- +2.31.1 + + diff --git a/salt.changes b/salt.changes index 16230d4..a527fb0 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Tue Apr 20 12:18:06 UTC 2021 - Pablo Suárez Hernández + +- Improvements on "ansiblegate" module: + * New methods: ansible.targets / ansible.discover_playbooks + * General bugfixes + +- Added: + * improvements-on-ansiblegate-module-354.patch + ------------------------------------------------------------------- Tue Apr 13 15:03:48 UTC 2021 - Pablo Suárez Hernández diff --git a/salt.spec b/salt.spec index 7b1cd54..7e8d74d 100644 --- a/salt.spec +++ b/salt.spec @@ -394,6 +394,8 @@ Patch165: update-target-fix-for-salt-ssh-to-process-targets-li.patch Patch166: add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/353 Patch167: regression-fix-of-salt-ssh-on-processing-targets-353.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/60056 +Patch168: improvements-on-ansiblegate-module-354.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate @@ -956,6 +958,7 @@ cp %{S:5} ./.travis.yml %patch165 -p1 %patch166 -p1 %patch167 -p1 +%patch168 -p1 %build # Putting /usr/bin at the front of $PATH is needed for RHEL/RES 7. Without this