Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package salt for openSUSE:Factory checked in 
at 2021-04-22 18:03:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/salt (Old)
 and      /work/SRC/openSUSE:Factory/.salt.new.12324 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "salt"

Thu Apr 22 18:03:26 2021 rev:117 rq:887060 version:3002.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/salt/salt.changes        2021-03-12 
13:30:24.906081393 +0100
+++ /work/SRC/openSUSE:Factory/.salt.new.12324/salt.changes     2021-04-22 
18:03:37.474475050 +0200
@@ -1,0 +2,52 @@
+Tue Apr 20 12:18:06 UTC 2021 - Pablo Su??rez Hern??ndez 
<[email protected]>
+
+- 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 
<[email protected]>
+
+- 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 
<[email protected]>
+
+- 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 <[email protected]>
+
+- 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 <[email protected]>
+
+- 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 <[email protected]>
+
+- Allow vendor change option with zypper
+
+- Added:
+  * allow-vendor-change-option-with-zypper-313.patch
+
+-------------------------------------------------------------------

New:
----
  add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch
  add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch
  allow-vendor-change-option-with-zypper-313.patch
  improvements-on-ansiblegate-module-354.patch
  notify-beacon-for-debian-ubuntu-systems-347.patch
  regression-fix-of-salt-ssh-on-processing-targets-353.patch
  update-target-fix-for-salt-ssh-to-process-targets-li.patch

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ salt.spec ++++++
--- /var/tmp/diff_new_pack.YiWDsB/_old  2021-04-22 18:03:39.486478161 +0200
+++ /var/tmp/diff_new_pack.YiWDsB/_new  2021-04-22 18:03:39.490478167 +0200
@@ -381,6 +381,21 @@
 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
+# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/60056
+Patch168:     improvements-on-ansiblegate-module-354.patch
 
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildRequires:  logrotate
@@ -937,6 +952,13 @@
 %patch159 -p1
 %patch160 -p1
 %patch161 -p1
+%patch162 -p1
+%patch163 -p1
+%patch164 -p1
+%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

++++++ _lastrevision ++++++
--- /var/tmp/diff_new_pack.YiWDsB/_old  2021-04-22 18:03:39.558478272 +0200
+++ /var/tmp/diff_new_pack.YiWDsB/_new  2021-04-22 18:03:39.558478272 +0200
@@ -1 +1 @@
-68bd2c45e40cf64ac426a7e5833daa076ab10cfe
\ No newline at end of file
+a94708ad2eba9aa15413d989ab3361b2c980589e
\ No newline at end of file

++++++ add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch ++++++
>From ec0d11ed66e8541a9ccaebc85aab4724013fb71f Mon Sep 17 00:00:00 2001
From: Pau Garcia Quiles <[email protected]>
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


++++++ add-almalinux-and-alibaba-cloud-linux-to-the-os-fami.patch ++++++
>From beec6f3945bda722bfe9c0aa606065f04c89bc62 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?=
 <[email protected]>
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


++++++ allow-vendor-change-option-with-zypper-313.patch ++++++
>From 33ad6876a04e800afc08748133dc568a5e362903 Mon Sep 17 00:00:00 2001
From: Martin Seidl <[email protected]>
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 <[email protected]>

* Fix unit test for allow vendor change on upgrade

* Add unit test with unsupported zypper version

Co-authored-by: Pablo Su??rez Hern??ndez <[email protected]>
---
 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


++++++ improvements-on-ansiblegate-module-354.patch ++++++
>From aa0f845e2bbc37332db04c583f475cfe25304db6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
 <[email protected]>
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


++++++ notify-beacon-for-debian-ubuntu-systems-347.patch ++++++
>From e0f8087409bdff4c3036e38ed4f22f5f031306e8 Mon Sep 17 00:00:00 2001
From: Ricardo Mateus <[email protected]>
Date: Fri, 9 Apr 2021 10:57:27 +0100
Subject: [PATCH] Notify beacon for Debian/Ubuntu systems (#347)

Signed-off-by: Ricardo Mateus <[email protected]>
(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


++++++ regression-fix-of-salt-ssh-on-processing-targets-353.patch ++++++
>From 543969c927df2f73662ac6ac19467d66d33e0577 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <[email protected]>
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


++++++ update-target-fix-for-salt-ssh-to-process-targets-li.patch ++++++
>From a603d31c4d3ace3590952ef848f4244c41abe7c8 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <[email protected]>
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

Reply via email to