SHA256
1
0
forked from pool/salt

Accepting request 949489 from systemsmanagement:saltstack

- Update to version 3004, see release notes: https://docs.saltproject.io/en/master/topics/releases/3004.html
- Don't check for cached pillar errors on state.apply (bsc#1190781)
- Added:
  * state.apply-don-t-check-for-cached-pillar-errors.patch
- Modified:
  * add-migrated-state-and-gpg-key-management-functions-.patch
  * switch-firewalld-state-to-use-change_interface.patch
  * include-aliases-in-the-fqdns-grains.patch
  * debian-info_installed-compatibility-50453.patch
  * info_installed-works-without-status-attr-now.patch
  * fix-traceback.print_exc-calls-for-test_pip_state-432.patch
  * add-custom-suse-capabilities-as-grains.patch
  * add-rpm_vercmp-python-library-for-version-comparison.patch
  * 3003.3-do-not-consider-skipped-targets-as-failed-for.patch
  * support-transactional-systems-microos.patch
  * do-not-crash-when-unexpected-cmd-output-at-listing-p.patch
  * enable-passing-a-unix_socket-for-mysql-returners-bsc.patch
  * update-target-fix-for-salt-ssh-to-process-targets-li.patch
  * fix-exception-in-yumpkg.remove-for-not-installed-pac.patch
  * enhance-openscap-module-add-xccdf_eval-call-386.patch
  * add-environment-variable-to-know-if-yum-is-invoked-f.patch
  * zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch
  * run-salt-master-as-dedicated-salt-user.patch
  * 3003.3-postgresql-json-support-in-pillar-423.patch
  * prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch
  * early-feature-support-config.patch
  * implementation-of-held-unheld-functions-for-state-pk.patch
  * x509-fixes-111.patch
  * fix-issues-with-salt-ssh-s-extra-filerefs.patch
  * mock-ip_addrs-in-utils-minions.py-unit-test-443.patch

OBS-URL: https://build.opensuse.org/request/show/949489
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=123
This commit is contained in:
Dominique Leuenberger 2022-01-29 20:01:15 +00:00 committed by Git OBS Bridge
commit f3f570995e
52 changed files with 1425 additions and 13919 deletions

View File

@ -1,7 +1,6 @@
From b279ec17a06619c97d9fbec215c7dd1ec3af088e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 6 Oct 2021 09:21:42 +0100
From c2dbf6ccdf320f1cce3d42f746f3c65f8633ee55 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 17:28:29 +0100
Subject: [PATCH] 3003.3: Do not consider skipped targets as failed for
ansible.playbooks state (bsc#1190446) (#436)
@ -14,16 +13,16 @@ Subject: [PATCH] 3003.3: Do not consider skipped targets as failed for
* Fix remaining problems in unit tests after backport
---
salt/states/ansiblegate.py | 19 +-
tests/pytests/unit/states/test_ansiblegate.py | 30 +
.../success_example_with_skipped.json | 1320 +++++++++++++++++
tests/unit/states/test_ansiblegate.py | 33 +-
3 files changed, 1356 insertions(+), 16 deletions(-)
3 files changed, 1354 insertions(+), 15 deletions(-)
create mode 100644 tests/unit/files/playbooks/success_example_with_skipped.json
diff --git a/salt/states/ansiblegate.py b/salt/states/ansiblegate.py
index bd00653928..d97a0ebb5b 100644
index af5cb0f0e5..4de7fb096d 100644
--- a/salt/states/ansiblegate.py
+++ b/salt/states/ansiblegate.py
@@ -188,19 +188,13 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
@@ -189,19 +189,13 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
ret["result"] = False
ret["changes"] = {}
elif all(
@ -45,7 +44,7 @@ index bd00653928..d97a0ebb5b 100644
for check in checks["stats"].values()
):
ret["comment"] = "Changes will be made from playbook {}".format(name)
@@ -221,10 +215,7 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
@@ -222,10 +216,7 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
ret["result"] = False
ret["changes"] = {}
elif all(
@ -57,7 +56,7 @@ index bd00653928..d97a0ebb5b 100644
for check in results["stats"].values()
):
ret["comment"] = "No changes to be made from playbook {}".format(name)
@@ -233,9 +224,7 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
@@ -234,9 +225,7 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
else:
ret["changes"] = _changes(results)
ret["result"] = all(
@ -68,6 +67,47 @@ index bd00653928..d97a0ebb5b 100644
for check in results["stats"].values()
)
if ret["result"]:
diff --git a/tests/pytests/unit/states/test_ansiblegate.py b/tests/pytests/unit/states/test_ansiblegate.py
index fa1a1cd264..02157d3420 100644
--- a/tests/pytests/unit/states/test_ansiblegate.py
+++ b/tests/pytests/unit/states/test_ansiblegate.py
@@ -42,6 +42,36 @@ def test_ansible_playbooks_states_success(playbooks_examples_dir):
}
+def test_ansible_playbooks_states_success_with_skipped(playbooks_examples_dir):
+ """
+ Test ansible.playbooks states executions success.
+ """
+
+ success_output = json.loads(
+ playbooks_examples_dir.joinpath("success_example_with_skipped.json").read_text()
+ )
+
+ with patch.dict(
+ ansiblegate.__salt__,
+ {"ansible.playbooks": MagicMock(return_value=success_output)},
+ ), patch("salt.utils.path.which", return_value=True), patch.dict(
+ ansiblegate.__opts__, {"test": False}
+ ):
+ ret = ansiblegate.playbooks("foobar")
+ assert ret["result"] is True
+ assert ret["comment"] == "No changes to be made from playbook foobar"
+ assert ret["changes"] == {
+ "all": {
+ "install git CentOS": {"uyuni-stable-min-sles15sp3.tf.local": {}},
+ "install git SUSE": {"uyuni-stable-min-centos7.tf.local": {}},
+ "install git Ubuntu": {
+ "uyuni-stable-min-centos7.tf.local": {},
+ "uyuni-stable-min-sles15sp3.tf.local": {},
+ },
+ }
+ }
+
+
def test_ansible_playbooks_states_failed(playbooks_examples_dir):
"""
Test ansible.playbooks failed states executions.
diff --git a/tests/unit/files/playbooks/success_example_with_skipped.json b/tests/unit/files/playbooks/success_example_with_skipped.json
new file mode 100644
index 0000000000..21bdb290c1
@ -1394,58 +1434,7 @@ index 0000000000..21bdb290c1
+ },
+ "retcode": 0
+}
diff --git a/tests/unit/states/test_ansiblegate.py b/tests/unit/states/test_ansiblegate.py
index ac677fc5db..6bf4494326 100644
--- a/tests/unit/states/test_ansiblegate.py
+++ b/tests/unit/states/test_ansiblegate.py
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# Import Salt Testing Libs
import json
import os
@@ -73,6 +72,38 @@ class AnsiblegateTestCase(TestCase, LoaderModuleMockMixin):
},
)
+ @patch("salt.utils.path.which", MagicMock(return_value=True))
+ def test_ansible_playbooks_states_success_with_skipped(self):
+ """
+ Test ansible.playbooks states executions success.
+ """
+
+ with salt.utils.files.fopen(
+ os.path.join(self.playbooks_examples_dir, "success_example_with_skipped.json")
+ ) as f:
+ success_output = json.loads(f.read())
+
+ with patch.dict(
+ ansible.__salt__,
+ {"ansible.playbooks": MagicMock(return_value=success_output)},
+ ), patch("salt.utils.path.which", return_value=True), patch.dict(
+ ansible.__opts__, {"test": False}
+ ):
+ ret = ansible.playbooks("foobar")
+ assert ret["result"] is True
+ assert ret["comment"] == "No changes to be made from playbook foobar"
+ assert ret["changes"] == {
+ "all": {
+ "install git CentOS": {"uyuni-stable-min-sles15sp3.tf.local": {}},
+ "install git SUSE": {"uyuni-stable-min-centos7.tf.local": {}},
+ "install git Ubuntu": {
+ "uyuni-stable-min-centos7.tf.local": {},
+ "uyuni-stable-min-sles15sp3.tf.local": {},
+ },
+ }
+ }
+
+ @patch("salt.utils.path.which", MagicMock(return_value=True))
def test_ansible_playbooks_states_failed(self):
"""
Test ansible.playbooks failed states executions.
--
2.33.0
2.34.1

View File

@ -1,6 +1,6 @@
From 6ffe3270d58527576688011e2b3bd826ec3941ee Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cedric.bosdonnat@free.fr>
Date: Fri, 24 Sep 2021 17:01:34 +0200
From 5c2624552e1ac2dbec3b54ff8c147ae50494969e Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 17:25:37 +0100
Subject: [PATCH] 3003.3 - postgresql JSON support in pillar (#423)
* Allow single field returns from SQL pillar
@ -40,10 +40,10 @@ index 0000000000..3fe39286a8
@@ -0,0 +1 @@
+Support querying for JSON data in SQL external pillar
diff --git a/salt/pillar/sql_base.py b/salt/pillar/sql_base.py
index 976ca8c0d8..9d9f0c9c9f 100644
index f7d87105af..8020d5503b 100644
--- a/salt/pillar/sql_base.py
+++ b/salt/pillar/sql_base.py
@@ -137,6 +137,33 @@ These columns define list grouping
@@ -136,6 +136,33 @@ These columns define list grouping
The range for with_lists is 1 to number_of_fields, inclusive.
Numbers outside this range are ignored.
@ -77,15 +77,15 @@ index 976ca8c0d8..9d9f0c9c9f 100644
Finally, if you pass the queries in via a mapping, the key will be the
first level name where as passing them in as a list will place them in the
root. This isolates the query results into their own subtrees.
@@ -179,6 +206,7 @@ from salt.ext import six
from salt.ext.six.moves import range
@@ -171,6 +198,7 @@ More complete example for MySQL (to also show configuration)
import abc # Added in python2.6 so always available
import logging
# Import Salt libs
+from salt.utils.dictupdate import update
from salt.utils.odict import OrderedDict
# Please don't strip redundant parentheses from this file.
@@ -208,6 +236,7 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)):
@@ -200,6 +228,7 @@ class SqlBaseExtPillar(metaclass=abc.ABCMeta):
num_fields = 0
depth = 0
as_list = False
@ -93,7 +93,7 @@ index 976ca8c0d8..9d9f0c9c9f 100644
with_lists = None
ignore_null = False
@@ -267,6 +296,7 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)):
@@ -259,6 +288,7 @@ class SqlBaseExtPillar(metaclass=abc.ABCMeta):
"query": "",
"depth": 0,
"as_list": False,
@ -101,7 +101,7 @@ index 976ca8c0d8..9d9f0c9c9f 100644
"with_lists": None,
"ignore_null": False,
}
@@ -324,6 +354,13 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)):
@@ -314,6 +344,13 @@ class SqlBaseExtPillar(metaclass=abc.ABCMeta):
for ret in rows:
# crd is the Current Return Data level, to make this non-recursive.
crd = self.focus
@ -115,7 +115,7 @@ index 976ca8c0d8..9d9f0c9c9f 100644
# Walk and create dicts above the final layer
for i in range(0, self.depth - 1):
# At the end we'll use listify to find values to make a list of
@@ -443,6 +480,7 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)):
@@ -433,6 +470,7 @@ class SqlBaseExtPillar(metaclass=abc.ABCMeta):
)
self.enter_root(root)
self.as_list = details["as_list"]
@ -173,10 +173,10 @@ index 0000000000..0d44c2d608
+ "f": [{"g": 7, "h": "test"}],
+ }
diff --git a/tests/unit/pillar/test_mysql.py b/tests/unit/pillar/test_mysql.py
index bc81eb4174..9db724329d 100644
index ddfb67d230..de6212b2c8 100644
--- a/tests/unit/pillar/test_mysql.py
+++ b/tests/unit/pillar/test_mysql.py
@@ -26,6 +26,7 @@ class MysqlPillarTestCase(TestCase):
@@ -18,6 +18,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -184,7 +184,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -47,6 +48,7 @@ class MysqlPillarTestCase(TestCase):
@@ -39,6 +40,7 @@ class MysqlPillarTestCase(TestCase):
{"query": "SELECT blah7", "as_list": True},
{"query": "SELECT blah8", "with_lists": "1"},
{"query": "SELECT blah9", "with_lists": "1,2"},
@ -192,7 +192,7 @@ index bc81eb4174..9db724329d 100644
],
{},
)
@@ -59,6 +61,7 @@ class MysqlPillarTestCase(TestCase):
@@ -51,6 +53,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -200,7 +200,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -69,6 +72,7 @@ class MysqlPillarTestCase(TestCase):
@@ -61,6 +64,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -208,7 +208,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -79,6 +83,7 @@ class MysqlPillarTestCase(TestCase):
@@ -71,6 +75,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -216,7 +216,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -89,6 +94,7 @@ class MysqlPillarTestCase(TestCase):
@@ -81,6 +86,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -224,7 +224,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -99,6 +105,7 @@ class MysqlPillarTestCase(TestCase):
@@ -91,6 +97,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -232,7 +232,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -109,6 +116,7 @@ class MysqlPillarTestCase(TestCase):
@@ -101,6 +108,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -240,7 +240,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -119,6 +127,7 @@ class MysqlPillarTestCase(TestCase):
@@ -111,6 +119,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -248,7 +248,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -129,6 +138,7 @@ class MysqlPillarTestCase(TestCase):
@@ -121,6 +130,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": False,
@ -256,7 +256,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": [1],
"ignore_null": False,
},
@@ -139,10 +149,22 @@ class MysqlPillarTestCase(TestCase):
@@ -131,10 +141,22 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah9",
"depth": 0,
"as_list": False,
@ -279,7 +279,7 @@ index bc81eb4174..9db724329d 100644
],
qbuffer,
)
@@ -159,6 +181,7 @@ class MysqlPillarTestCase(TestCase):
@@ -151,6 +173,7 @@ class MysqlPillarTestCase(TestCase):
"5": {"query": "SELECT blah5"},
"6": {"query": "SELECT blah6", "depth": 2},
"7": {"query": "SELECT blah7", "as_list": True},
@ -287,7 +287,7 @@ index bc81eb4174..9db724329d 100644
},
)
qbuffer = return_data.extract_queries(args, kwargs)
@@ -170,6 +193,7 @@ class MysqlPillarTestCase(TestCase):
@@ -162,6 +185,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -295,7 +295,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -180,6 +204,7 @@ class MysqlPillarTestCase(TestCase):
@@ -172,6 +196,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -303,7 +303,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -190,6 +215,7 @@ class MysqlPillarTestCase(TestCase):
@@ -182,6 +207,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -311,7 +311,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -200,6 +226,7 @@ class MysqlPillarTestCase(TestCase):
@@ -192,6 +218,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -319,7 +319,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -210,6 +237,7 @@ class MysqlPillarTestCase(TestCase):
@@ -202,6 +229,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -327,7 +327,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -220,6 +248,7 @@ class MysqlPillarTestCase(TestCase):
@@ -212,6 +240,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -335,7 +335,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -230,6 +259,18 @@ class MysqlPillarTestCase(TestCase):
@@ -222,6 +251,18 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -354,7 +354,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -261,6 +302,7 @@ class MysqlPillarTestCase(TestCase):
@@ -253,6 +294,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -362,7 +362,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -271,6 +313,7 @@ class MysqlPillarTestCase(TestCase):
@@ -263,6 +305,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -370,7 +370,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -281,6 +324,7 @@ class MysqlPillarTestCase(TestCase):
@@ -273,6 +316,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -378,7 +378,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -291,6 +335,7 @@ class MysqlPillarTestCase(TestCase):
@@ -283,6 +327,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -386,7 +386,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -301,6 +346,7 @@ class MysqlPillarTestCase(TestCase):
@@ -293,6 +338,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -394,7 +394,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -311,6 +357,7 @@ class MysqlPillarTestCase(TestCase):
@@ -303,6 +349,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -402,7 +402,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -349,6 +396,7 @@ class MysqlPillarTestCase(TestCase):
@@ -341,6 +388,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -410,7 +410,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -359,6 +407,7 @@ class MysqlPillarTestCase(TestCase):
@@ -351,6 +399,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -418,7 +418,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -369,6 +418,7 @@ class MysqlPillarTestCase(TestCase):
@@ -361,6 +410,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -426,7 +426,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -379,6 +429,7 @@ class MysqlPillarTestCase(TestCase):
@@ -371,6 +421,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -434,7 +434,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -389,6 +440,7 @@ class MysqlPillarTestCase(TestCase):
@@ -381,6 +432,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -442,7 +442,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -399,6 +451,7 @@ class MysqlPillarTestCase(TestCase):
@@ -391,6 +443,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 0,
"as_list": False,
@ -450,7 +450,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -409,6 +462,7 @@ class MysqlPillarTestCase(TestCase):
@@ -401,6 +454,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 2,
"as_list": False,
@ -458,7 +458,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -419,6 +473,7 @@ class MysqlPillarTestCase(TestCase):
@@ -411,6 +465,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": True,
@ -466,7 +466,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -440,6 +495,7 @@ class MysqlPillarTestCase(TestCase):
@@ -432,6 +487,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -474,7 +474,7 @@ index bc81eb4174..9db724329d 100644
"with_lists": None,
"ignore_null": False,
},
@@ -450,6 +506,7 @@ class MysqlPillarTestCase(TestCase):
@@ -442,6 +498,7 @@ class MysqlPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -483,10 +483,10 @@ index bc81eb4174..9db724329d 100644
"ignore_null": False,
},
diff --git a/tests/unit/pillar/test_sqlcipher.py b/tests/unit/pillar/test_sqlcipher.py
index d7e9eed6f6..6f7b21fb3f 100644
index 99edcb094c..1330c3bbfc 100644
--- a/tests/unit/pillar/test_sqlcipher.py
+++ b/tests/unit/pillar/test_sqlcipher.py
@@ -38,6 +38,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -30,6 +30,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -494,7 +494,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -48,6 +49,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -40,6 +41,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -502,7 +502,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -58,6 +60,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -50,6 +52,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -510,7 +510,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -68,6 +71,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -60,6 +63,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -518,7 +518,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -78,6 +82,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -70,6 +74,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -526,7 +526,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -88,6 +93,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -80,6 +85,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -534,7 +534,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -98,6 +104,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -90,6 +96,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -542,7 +542,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -108,6 +115,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -100,6 +107,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": False,
@ -550,7 +550,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": [1],
"ignore_null": False,
},
@@ -118,6 +126,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -110,6 +118,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah9",
"depth": 0,
"as_list": False,
@ -558,7 +558,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": [1, 2],
"ignore_null": False,
},
@@ -149,6 +158,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -141,6 +150,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -566,7 +566,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -159,6 +169,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -151,6 +161,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -574,7 +574,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -169,6 +180,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -161,6 +172,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -582,7 +582,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -179,6 +191,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -171,6 +183,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -590,7 +590,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -189,6 +202,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -181,6 +194,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -598,7 +598,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -199,6 +213,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -191,6 +205,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -606,7 +606,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -209,6 +224,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -201,6 +216,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -614,7 +614,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -240,6 +256,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -232,6 +248,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -622,7 +622,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -250,6 +267,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -242,6 +259,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -630,7 +630,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -260,6 +278,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -252,6 +270,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -638,7 +638,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -270,6 +289,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -262,6 +281,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -646,7 +646,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -280,6 +300,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -272,6 +292,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -654,7 +654,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -290,6 +311,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -282,6 +303,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -662,7 +662,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -328,6 +350,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -320,6 +342,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -670,7 +670,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -338,6 +361,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -330,6 +353,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -678,7 +678,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -348,6 +372,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -340,6 +364,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -686,7 +686,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -358,6 +383,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -350,6 +375,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -694,7 +694,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -368,6 +394,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -360,6 +386,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -702,7 +702,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -378,6 +405,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -370,6 +397,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 0,
"as_list": False,
@ -710,7 +710,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -388,6 +416,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -380,6 +408,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 2,
"as_list": False,
@ -718,7 +718,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -398,6 +427,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -390,6 +419,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": True,
@ -726,7 +726,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -419,6 +449,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -411,6 +441,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -734,7 +734,7 @@ index d7e9eed6f6..6f7b21fb3f 100644
"with_lists": None,
"ignore_null": False,
},
@@ -429,6 +460,7 @@ class SQLCipherPillarTestCase(TestCase):
@@ -421,6 +452,7 @@ class SQLCipherPillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -743,10 +743,10 @@ index d7e9eed6f6..6f7b21fb3f 100644
"ignore_null": False,
},
diff --git a/tests/unit/pillar/test_sqlite3.py b/tests/unit/pillar/test_sqlite3.py
index da780682e7..69efd0a3e8 100644
index 1d0b187729..fee651db32 100644
--- a/tests/unit/pillar/test_sqlite3.py
+++ b/tests/unit/pillar/test_sqlite3.py
@@ -38,6 +38,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -30,6 +30,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -754,7 +754,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -48,6 +49,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -40,6 +41,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -762,7 +762,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -58,6 +60,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -50,6 +52,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -770,7 +770,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -68,6 +71,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -60,6 +63,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -778,7 +778,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -78,6 +82,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -70,6 +74,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -786,7 +786,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -88,6 +93,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -80,6 +85,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -794,7 +794,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -98,6 +104,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -90,6 +96,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -802,7 +802,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -108,6 +115,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -100,6 +107,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": False,
@ -810,7 +810,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": [1],
"ignore_null": False,
},
@@ -118,6 +126,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -110,6 +118,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah9",
"depth": 0,
"as_list": False,
@ -818,7 +818,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": [1, 2],
"ignore_null": False,
},
@@ -149,6 +158,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -141,6 +150,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -826,7 +826,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -159,6 +169,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -151,6 +161,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -834,7 +834,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -169,6 +180,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -161,6 +172,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -842,7 +842,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -179,6 +191,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -171,6 +183,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -850,7 +850,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -189,6 +202,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -181,6 +194,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -858,7 +858,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -199,6 +213,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -191,6 +205,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 2,
"as_list": False,
@ -866,7 +866,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -209,6 +224,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -201,6 +216,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 0,
"as_list": True,
@ -874,7 +874,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -240,6 +256,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -232,6 +248,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -882,7 +882,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -250,6 +267,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -242,6 +259,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -890,7 +890,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -260,6 +278,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -252,6 +270,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -898,7 +898,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -270,6 +289,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -262,6 +281,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah1",
"depth": 0,
"as_list": False,
@ -906,7 +906,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -280,6 +300,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -272,6 +292,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 2,
"as_list": False,
@ -914,7 +914,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -290,6 +311,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -282,6 +303,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": True,
@ -922,7 +922,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -328,6 +350,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -320,6 +342,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -930,7 +930,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -338,6 +361,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -330,6 +353,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -938,7 +938,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -348,6 +372,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -340,6 +364,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah3",
"depth": 0,
"as_list": False,
@ -946,7 +946,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -358,6 +383,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -350,6 +375,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah4",
"depth": 2,
"as_list": False,
@ -954,7 +954,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -368,6 +394,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -360,6 +386,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah5",
"depth": 0,
"as_list": False,
@ -962,7 +962,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -378,6 +405,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -370,6 +397,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah6",
"depth": 0,
"as_list": False,
@ -970,7 +970,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -388,6 +416,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -380,6 +408,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah7",
"depth": 2,
"as_list": False,
@ -978,7 +978,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -398,6 +427,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -390,6 +419,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah8",
"depth": 0,
"as_list": True,
@ -986,7 +986,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -419,6 +449,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -411,6 +441,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah",
"depth": 0,
"as_list": False,
@ -994,7 +994,7 @@ index da780682e7..69efd0a3e8 100644
"with_lists": None,
"ignore_null": False,
},
@@ -429,6 +460,7 @@ class SQLite3PillarTestCase(TestCase):
@@ -421,6 +452,7 @@ class SQLite3PillarTestCase(TestCase):
"query": "SELECT blah2",
"depth": 0,
"as_list": False,
@ -1003,6 +1003,6 @@ index da780682e7..69efd0a3e8 100644
"ignore_null": False,
},
--
2.33.0
2.34.1

View File

@ -1 +1 @@
21e5e5ac757d79b2899ba18b18ae369d713013dd
4dd4ea97489b05983b3cd9277bca1edc25c50985

View File

@ -3,7 +3,7 @@
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
<param name="subdir">salt</param>
<param name="filename">package</param>
<param name="revision">3003.3</param>
<param name="revision">3004</param>
<param name="scm">git</param>
</service>
<service name="extract_file" mode="disabled">
@ -12,8 +12,8 @@
</service>
<service name="download_url" mode="disabled">
<param name="host">codeload.github.com</param>
<param name="path">openSUSE/salt/tar.gz/v3003.3-suse</param>
<param name="filename">v3003.3.tar.gz</param>
<param name="path">openSUSE/salt/tar.gz/v3004-suse</param>
<param name="filename">v3004.tar.gz</param>
</service>
<service name="update_changelog" mode="disabled"></service>
</services>

View File

@ -1,74 +0,0 @@
From 2e810cc876f7b7110326231de51d78ff5d12eae6 Mon Sep 17 00:00:00 2001
From: Pau Garcia Quiles <pau.garcia@suse.com>
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 | 2 ++
tests/unit/grains/test_core.py | 28 ++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 19937f008e..bce8c95179 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1560,6 +1560,7 @@ _OS_NAME_MAP = {
"linuxmint": "Mint",
"neon": "KDE neon",
"pop": "Pop",
+ "alibabaclo": "Alinux",
}
# Map the 'os' grain to the 'os_family' grain
@@ -1637,6 +1638,7 @@ _OS_FAMILY_MAP = {
"TurnKey": "Debian",
"Pop": "Debian",
"AstraLinuxCE": "Debian",
+ "Alinux": "RedHat",
}
# Matches any possible format:
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index ac2d515bcd..fa06bb27ab 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -846,6 +846,34 @@ 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 = {
+ "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": "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)
+
@skipIf(not salt.utils.platform.is_windows(), "System is not Windows")
def test_windows_platform_data(self):
"""
--
2.33.0

View File

@ -1,59 +0,0 @@
From 30366101c20eefd2411482138edfa0ca0c8a3b06 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?=
<juliogonzalez@users.noreply.github.com>
Date: Wed, 12 Feb 2020 10:05:45 +0100
Subject: [PATCH] Add Astra Linux Common Edition to the OS Family list
(#209)
---
salt/grains/core.py | 1 +
tests/unit/grains/test_core.py | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index e007f40c92..19937f008e 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1636,6 +1636,7 @@ _OS_FAMILY_MAP = {
"AIX": "AIX",
"TurnKey": "Debian",
"Pop": "Debian",
+ "AstraLinuxCE": "Debian",
}
# Matches any possible format:
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 7173f04979..e8845e2dfa 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -826,6 +826,26 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
}
self._run_os_grains_tests("pop-20.10", _os_release_map, expectation)
+ @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
+ def test_astralinuxce_2_os_grains(self):
+ """
+ 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"),
+ }
+ expectation = {
+ "os": "AstraLinuxCE",
+ "os_family": "Debian",
+ "oscodename": "orel",
+ "osfullname": "AstraLinuxCE",
+ "osrelease": "2.12.22",
+ "osrelease_info": (2, 12, 22),
+ "osmajorrelease": 2,
+ "osfinger": "AstraLinuxCE-2",
+ }
+ self._run_os_grains_tests("astralinuxce-2.12.22", _os_release_map, expectation)
+
@skipIf(not salt.utils.platform.is_windows(), "System is not Windows")
def test_windows_platform_data(self):
"""
--
2.33.0

View File

@ -1,7 +1,6 @@
From bdb48ed82c755407bc413fa445e057a6da5f1e87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 21 Jun 2018 11:57:57 +0100
From 1c20e6e1acf21d301d6e53432afaa7cc42db2380 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 12:59:43 +0100
Subject: [PATCH] Add custom SUSE capabilities as Grains
Add new custom SUSE capability for saltutil state module
@ -10,13 +9,13 @@ Add new custom SUSE capability for saltutil state module
1 file changed, 8 insertions(+)
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
index 2fdbe6526a..0eec27e628 100644
index 300052f1ee..f2504dbf19 100644
--- a/salt/grains/extra.py
+++ b/salt/grains/extra.py
@@ -66,3 +66,11 @@ def config():
log.warning("Bad syntax in grains file! Skipping.")
return {}
return {}
@@ -96,3 +96,11 @@ def uefi():
def transactional():
"""Determine if the system is transactional."""
return {"transactional": bool(salt.utils.path.which("transactional-update"))}
+
+
+def suse_backported_capabilities():
@ -26,6 +25,6 @@ index 2fdbe6526a..0eec27e628 100644
+ '__suse_reserved_saltutil_states_support': True
+ }
--
2.33.0
2.34.1

View File

@ -1,18 +1,18 @@
From 7b2b5fc53d30397b8f7a11e59f5c7a57bcb63058 Mon Sep 17 00:00:00 2001
From: Marcelo Chiaradia <mchiaradia@suse.com>
Date: Thu, 7 Jun 2018 10:29:41 +0200
Subject: [PATCH] Add environment variable to know if yum is invoked
from Salt(bsc#1057635)
From 6ba30d3900bc328efd3480c0ff3d9e9b126fc5cb Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 12:57:21 +0100
Subject: [PATCH] Add environment variable to know if yum is invoked from
Salt(bsc#1057635)
---
salt/modules/yumpkg.py | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index b547fe6be7..c58b3e4c70 100644
index cf684e20f7..8d089c6aa4 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -917,7 +917,9 @@ def list_repo_pkgs(*args, **kwargs):
@@ -965,7 +965,9 @@ def list_repo_pkgs(*args, **kwargs):
None
if _yum() != "yum"
else _LooseVersion(
@ -23,7 +23,7 @@ index b547fe6be7..c58b3e4c70 100644
.splitlines()[0]
.strip()
)
@@ -2347,7 +2349,9 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
@@ -2422,7 +2424,9 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
"""
_check_versionlock()
@ -34,7 +34,7 @@ index b547fe6be7..c58b3e4c70 100644
ret = []
for line in salt.utils.itertools.split(out, "\n"):
match = _get_hold(line, pattern=pattern, full=full)
@@ -2415,7 +2419,10 @@ def group_list():
@@ -2490,7 +2494,10 @@ def group_list():
}
out = __salt__["cmd.run_stdout"](
@ -46,7 +46,7 @@ index b547fe6be7..c58b3e4c70 100644
)
key = None
for line in salt.utils.itertools.split(out, "\n"):
@@ -2486,7 +2493,9 @@ def group_info(name, expand=False, ignore_groups=None):
@@ -2561,7 +2568,9 @@ def group_info(name, expand=False, ignore_groups=None):
ret[pkgtype] = set()
cmd = [_yum(), "--quiet", "groupinfo", name]
@ -57,7 +57,7 @@ index b547fe6be7..c58b3e4c70 100644
g_info = {}
for line in salt.utils.itertools.split(out, "\n"):
@@ -3203,7 +3212,9 @@ def download(*packages, **kwargs):
@@ -3278,7 +3287,9 @@ def download(*packages, **kwargs):
cmd = ["yumdownloader", "-q", "--destdir={}".format(CACHE_DIR)]
cmd.extend(packages)
@ -68,16 +68,16 @@ index b547fe6be7..c58b3e4c70 100644
ret = {}
for dld_result in os.listdir(CACHE_DIR):
if not dld_result.endswith(".rpm"):
@@ -3279,7 +3290,7 @@ def _get_patches(installed_only=False):
@@ -3354,7 +3365,7 @@ def _get_patches(installed_only=False):
patches = {}
cmd = [_yum(), "--quiet", "updateinfo", "list", "all"]
- ret = __salt__["cmd.run_stdout"](cmd, python_shell=False)
+ ret = __salt__["cmd.run_stdout"](cmd, python_shell=False, env={"SALT_RUNNING": "1"})
parsing_errors = False
for line in salt.utils.itertools.split(ret, os.linesep):
inst, advisory_id, sev, pkg = re.match(
r"([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)", line
--
2.29.2
2.34.1

File diff suppressed because it is too large Load Diff

View File

@ -1,71 +0,0 @@
From 03b40485102e88e217814ea4e08fb857ad16cbff Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Wed, 18 Aug 2021 15:05:42 +0300
Subject: [PATCH] Add missing aarch64 to rpm package architectures (#405)
Required to prevent false negative results on using pkg.installed
with architecture specification in package name (ex. `bash.aarch64`)
---
salt/utils/pkg/rpm.py | 2 +-
tests/unit/modules/test_zypperpkg.py | 34 ++++++++++++++++++++++++++++
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/salt/utils/pkg/rpm.py b/salt/utils/pkg/rpm.py
index 3e990cc05d..8203d2f989 100644
--- a/salt/utils/pkg/rpm.py
+++ b/salt/utils/pkg/rpm.py
@@ -30,7 +30,7 @@ ARCHES_ALPHA = (
"alphaev68",
"alphaev7",
)
-ARCHES_ARM = ("armv5tel", "armv5tejl", "armv6l", "armv7l")
+ARCHES_ARM = ("armv5tel", "armv5tejl", "armv6l", "armv7l", "aarch64")
ARCHES_SH = ("sh3", "sh4", "sh4a")
ARCHES = (
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index 2d7e5f0858..20bf5eaaad 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -2475,3 +2475,37 @@ pattern() = package-c"""
with patch.dict(zypper.__salt__, salt_mock):
self.assertTrue(zypper.del_repo_key(keyid="keyid", root="/mnt"))
salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
+
+ def test_services_need_restart(self):
+ """
+ Test that zypper ps is used correctly to list services that need to
+ be restarted.
+ """
+ expected = ["salt-minion", "firewalld"]
+ zypper_output = "salt-minion\nfirewalld"
+ zypper_mock = Mock()
+ zypper_mock(root=None).nolock.call = Mock(return_value=zypper_output)
+
+ with patch("salt.modules.zypperpkg.__zypper__", zypper_mock):
+ assert zypper.services_need_restart() == expected
+ zypper_mock(root=None).nolock.call.assert_called_with("ps", "-sss")
+
+ def test_normalize_name(self):
+ """
+ Test that package is normalized only when it should be
+ """
+ with patch.dict(zypper.__grains__, {"osarch": "x86_64"}):
+ result = zypper.normalize_name("foo")
+ assert result == "foo", result
+ result = zypper.normalize_name("foo.x86_64")
+ assert result == "foo", result
+ result = zypper.normalize_name("foo.noarch")
+ assert result == "foo", result
+
+ with patch.dict(zypper.__grains__, {"osarch": "aarch64"}):
+ result = zypper.normalize_name("foo")
+ assert result == "foo", result
+ result = zypper.normalize_name("foo.aarch64")
+ assert result == "foo", result
+ result = zypper.normalize_name("foo.noarch")
+ assert result == "foo", result
--
2.33.0

View File

@ -1,6 +1,6 @@
From 0ccc9aa260032ba86481f121132a10f439a20700 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Mon, 15 Nov 2021 17:22:35 +0300
From a15321796586b033d8fa8366074087ceddaa4d23 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 17:41:11 +0100
Subject: [PATCH] Add rpm_vercmp python library for version comparison -
3003.3 (#448)
@ -13,13 +13,9 @@ Subject: [PATCH] Add rpm_vercmp python library for version comparison -
Co-authored-by: Megan Wilhite <mwilhite@vmware.com>
---
changelog/60814.added | 1 +
salt/modules/rpm_lowpkg.py | 21 +-
tests/pytests/unit/modules/test_rpm_lowpkg.py | 545 ++++++++++++++++++
tests/unit/modules/test_rpm_lowpkg.py | 478 ---------------
4 files changed, 566 insertions(+), 479 deletions(-)
tests/pytests/unit/modules/test_rpm_lowpkg.py | 326 ++++++++++++++----
2 files changed, 263 insertions(+), 64 deletions(-)
create mode 100644 changelog/60814.added
create mode 100644 tests/pytests/unit/modules/test_rpm_lowpkg.py
delete mode 100644 tests/unit/modules/test_rpm_lowpkg.py
diff --git a/changelog/60814.added b/changelog/60814.added
new file mode 100644
@ -28,338 +24,72 @@ index 0000000000..7a9ffe1b25
+++ b/changelog/60814.added
@@ -0,0 +1 @@
+Add the python rpm-vercmp library in the rpm_lowpkg.py module.
diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py
index 370bd5b728..aba5b939b6 100644
--- a/salt/modules/rpm_lowpkg.py
+++ b/salt/modules/rpm_lowpkg.py
@@ -29,6 +29,13 @@ try:
except ImportError:
HAS_RPMUTILS = False
+try:
+ import rpm_vercmp
+
+ HAS_PY_RPM = True
+except ImportError:
+ HAS_PY_RPM = False
+
log = logging.getLogger(__name__)
@@ -710,6 +717,8 @@ def version_cmp(ver1, ver2, ignore_epoch=False):
"labelCompare function. Not using rpm.labelCompare for "
"version comparison."
)
+ elif HAS_PY_RPM:
+ cmp_func = rpm_vercmp.vercmp
else:
log.warning(
"Please install a package that provides rpm.labelCompare for "
@@ -778,7 +787,17 @@ def version_cmp(ver1, ver2, ignore_epoch=False):
if not ver1_r or not ver2_r:
ver1_r = ver2_r = ""
- cmp_result = cmp_func((ver1_e, ver1_v, ver1_r), (ver2_e, ver2_v, ver2_r))
+ if HAS_PY_RPM:
+ # handle epoch version comparison first
+ # rpm_vercmp.vercmp does not handle epoch version comparison
+ ret = salt.utils.versions.version_cmp(ver1_e, ver2_e)
+ if ret in (1, -1):
+ return ret
+ cmp_result = cmp_func(ver1, ver2)
+ else:
+ cmp_result = cmp_func(
+ (ver1_e, ver1_v, ver1_r), (ver2_e, ver2_v, ver2_r)
+ )
if cmp_result not in (-1, 0, 1):
raise CommandExecutionError(
"Comparison result '{}' is invalid".format(cmp_result)
diff --git a/tests/pytests/unit/modules/test_rpm_lowpkg.py b/tests/pytests/unit/modules/test_rpm_lowpkg.py
new file mode 100644
index 0000000000..c9d1ac2b1c
--- /dev/null
index f19afa854e..c9d1ac2b1c 100644
--- a/tests/pytests/unit/modules/test_rpm_lowpkg.py
+++ b/tests/pytests/unit/modules/test_rpm_lowpkg.py
@@ -0,0 +1,545 @@
+"""
+ :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
+"""
+
+
@@ -3,6 +3,7 @@
"""
+import datetime
+import pytest
+import salt.modules.cmdmod
+import salt.modules.rpm_lowpkg as rpm
+import salt.utils.path
+from tests.support.mock import MagicMock, patch
+
+# pylint: disable=unused-import
+try:
+ import rpm as rpm_lib
+
+ HAS_RPM = True
+except ImportError:
+ HAS_RPM = False
+
+try:
+ import rpm_vercmp
+
+ HAS_PY_RPM = True
+except ImportError:
+ HAS_PY_RPM = False
+# pylint: enable=unused-import
+
+
+def _called_with_root(mock):
+ cmd = " ".join(mock.call_args[0][0])
+ return cmd.startswith("rpm --root /")
+
+
+@pytest.fixture
+def configure_loader_modules():
+ return {rpm: {"rpm": MagicMock(return_value=MagicMock)}}
+
+
+# 'list_pkgs' function tests: 2
+
+
+def test_list_pkgs():
+ """
+ Test if it list the packages currently installed in a dict
+ """
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ assert rpm.list_pkgs() == {}
+ assert not _called_with_root(mock)
+
+
+def test_list_pkgs_root():
+ """
+ Test if it list the packages currently installed in a dict,
+ called with root parameter
+ """
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ rpm.list_pkgs(root="/")
+ assert _called_with_root(mock)
+
+
+# 'verify' function tests: 2
+
+
+def test_verify():
+ """
+ Test if it runs an rpm -Va on a system, and returns the
+ results in a dict
+ """
+ mock = MagicMock(
+ return_value={"stdout": "", "stderr": "", "retcode": 0, "pid": 12345}
+ )
+ with patch.dict(rpm.__salt__, {"cmd.run_all": mock}):
+ assert rpm.verify("httpd") == {}
+ assert not _called_with_root(mock)
+
+
+def test_verify_root():
+ """
+ Test if it runs an rpm -Va on a system, and returns the
+ results in a dict, called with root parameter
+ """
+ mock = MagicMock(
+ return_value={"stdout": "", "stderr": "", "retcode": 0, "pid": 12345}
+ )
+ with patch.dict(rpm.__salt__, {"cmd.run_all": mock}):
+ rpm.verify("httpd", root="/")
+ assert _called_with_root(mock)
+
+
+# 'file_list' function tests: 2
+
+
+def test_file_list():
+ """
+ Test if it list the files that belong to a package.
+ """
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ assert rpm.file_list("httpd") == {"errors": [], "files": []}
+ assert not _called_with_root(mock)
+
+
+def test_file_list_root():
+ """
+ Test if it list the files that belong to a package, using the
+ root parameter.
+ """
+
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ rpm.file_list("httpd", root="/")
+ assert _called_with_root(mock)
+
+
+# 'file_dict' function tests: 2
+
+
+def test_file_dict():
+ """
+ Test if it list the files that belong to a package
+ """
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ assert rpm.file_dict("httpd") == {"errors": [], "packages": {}}
+ assert not _called_with_root(mock)
+
+
+def test_file_dict_root():
+ """
+ Test if it list the files that belong to a package
+ """
+ mock = MagicMock(return_value="")
+ with patch.dict(rpm.__salt__, {"cmd.run": mock}):
+ rpm.file_dict("httpd", root="/")
+ assert _called_with_root(mock)
+
+
+# 'owner' function tests: 1
+
+
+def test_owner():
+ """
+ Test if it return the name of the package that owns the file.
+ """
+ assert rpm.owner() == ""
+
+ ret = "file /usr/bin/salt-jenkins-build is not owned by any package"
+ mock = MagicMock(return_value=ret)
+ with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
+ assert rpm.owner("/usr/bin/salt-jenkins-build") == ""
+ assert not _called_with_root(mock)
+
+ ret = {
+ "/usr/bin/vim": "vim-enhanced-7.4.160-1.e17.x86_64",
+ "/usr/bin/python": "python-2.7.5-16.e17.x86_64",
+ }
+ mock = MagicMock(
+ side_effect=[
+ "python-2.7.5-16.e17.x86_64",
+ "vim-enhanced-7.4.160-1.e17.x86_64",
+ ]
+ )
+ with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
+ assert rpm.owner("/usr/bin/python", "/usr/bin/vim") == ret
+ assert not _called_with_root(mock)
+
+
+def test_owner_root():
+ """
+ Test if it return the name of the package that owns the file,
+ using the parameter root.
+ """
+ assert rpm.owner() == ""
+
+ ret = "file /usr/bin/salt-jenkins-build is not owned by any package"
+ mock = MagicMock(return_value=ret)
+ with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
+ rpm.owner("/usr/bin/salt-jenkins-build", root="/")
+ assert _called_with_root(mock)
+
+
+# 'checksum' function tests: 2
+
+
+def test_checksum():
+ """
+ Test if checksum validate as expected
+ """
+ ret = {
+ "file1.rpm": True,
+ "file2.rpm": False,
+ "file3.rpm": False,
+ }
+
+ mock = MagicMock(side_effect=[True, 0, True, 1, False, 0])
+ with patch.dict(rpm.__salt__, {"file.file_exists": mock, "cmd.retcode": mock}):
+ assert rpm.checksum("file1.rpm", "file2.rpm", "file3.rpm") == ret
+ assert not _called_with_root(mock)
+
+
+def test_checksum_root():
+ """
+ Test if checksum validate as expected, using the parameter
+ root
+ """
+ mock = MagicMock(side_effect=[True, 0])
+ with patch.dict(rpm.__salt__, {"file.file_exists": mock, "cmd.retcode": mock}):
+ rpm.checksum("file1.rpm", root="/")
+ assert _called_with_root(mock)
+
+
+@pytest.mark.parametrize("rpm_lib", ["HAS_RPM", "HAS_PY_RPM", "rpmdev-vercmp"])
+def test_version_cmp_rpm_all_libraries(rpm_lib):
+ """
+ Test package version when each library is installed
+ """
+ rpmdev = salt.utils.path.which("rpmdev-vercmp")
+ patch_cmd = patch.dict(rpm.__salt__, {"cmd.run_all": salt.modules.cmdmod.run_all})
+ if rpm_lib == "rpmdev-vercmp":
+ if rpmdev:
+ patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
+ patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
+ else:
+ pytest.skip("The rpmdev-vercmp binary is not installed")
+ elif rpm_lib == "HAS_RPM":
+ if HAS_RPM:
+ patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", True)
+ patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
+ else:
+ pytest.skip("The RPM lib is not installed, skipping")
+ elif rpm_lib == "HAS_PY_RPM":
+ if HAS_PY_RPM:
+ patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
+ patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", True)
+ else:
+ pytest.skip("The Python RPM lib is not installed, skipping")
+
+ with patch_rpm, patch_py_rpm, patch_cmd:
+ assert -1 == rpm.version_cmp("1", "2")
+ assert -1 == rpm.version_cmp("2.9.1-6.el7_2.3", "2.9.1-6.el7.4")
+ assert 1 == rpm.version_cmp("3.2", "3.0")
+ assert 0 == rpm.version_cmp("3.0", "3.0")
+ assert 1 == rpm.version_cmp("1:2.9.1-6.el7_2.3", "2.9.1-6.el7.4")
+ assert -1 == rpm.version_cmp("1:2.9.1-6.el7_2.3", "1:2.9.1-6.el7.4")
+ assert 1 == rpm.version_cmp("2:2.9.1-6.el7_2.3", "1:2.9.1-6.el7.4")
+ assert 0 == rpm.version_cmp("3:2.9.1-6.el7.4", "3:2.9.1-6.el7.4")
+ assert -1 == rpm.version_cmp("3:2.9.1-6.el7.4", "3:2.9.1-7.el7.4")
+ assert 1 == rpm.version_cmp("3:2.9.1-8.el7.4", "3:2.9.1-7.el7.4")
+
+
import pytest
import salt.modules.cmdmod
import salt.modules.rpm_lowpkg as rpm
@@ -250,92 +251,57 @@ def test_version_cmp_rpm_all_libraries(rpm_lib):
assert 1 == rpm.version_cmp("3:2.9.1-8.el7.4", "3:2.9.1-7.el7.4")
-def test_version_cmp_rpm():
+@patch("salt.modules.rpm_lowpkg.HAS_RPM", True)
+@patch("salt.modules.rpm_lowpkg.rpm.labelCompare", return_value=-1)
+@patch("salt.modules.rpm_lowpkg.log")
+def test_version_cmp_rpm(mock_log, mock_labelCompare):
+ """
+ Test package version if RPM-Python is installed
+
+ :return:
+ """
"""
Test package version if RPM-Python is installed
:return:
"""
- mock_label = MagicMock(return_value=-1)
- mock_log = MagicMock()
- patch_label = patch("salt.modules.rpm_lowpkg.rpm.labelCompare", mock_label)
- patch_log = patch("salt.modules.rpm_lowpkg.log", mock_log)
- patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", True)
- with patch_label, patch_rpm, patch_log:
- assert -1 == rpm.version_cmp("1", "2")
- assert not mock_log.warning.called
- assert mock_label.called
+ assert -1 == rpm.version_cmp("1", "2")
+ assert not mock_log.warning.called
+ assert mock_labelCompare.called
+
+
-def test_version_cmp_rpmutils():
+@patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
+@patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", True)
+@patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
+@patch("salt.modules.rpm_lowpkg.rpmUtils", create=True)
+@patch("salt.modules.rpm_lowpkg.log")
+def test_version_cmp_rpmutils(mock_log, mock_rpmUtils):
+ """
+ Test package version if rpmUtils.miscutils called
+
+ :return:
+ """
+ mock_rpmUtils.miscutils = MagicMock()
+ mock_rpmUtils.miscutils.compareEVR = MagicMock(return_value=-1)
"""
Test package version if rpmUtils.miscutils called
:return:
"""
- mock_log = MagicMock()
- mock_rpmUtils = MagicMock()
mock_rpmUtils.miscutils = MagicMock()
mock_rpmUtils.miscutils.compareEVR = MagicMock(return_value=-1)
- patch_utils = patch("salt.modules.rpm_lowpkg.rpmUtils", mock_rpmUtils, create=True)
- patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- patch_utils_lib = patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", True)
- patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
- patch_log = patch("salt.modules.rpm_lowpkg.log", mock_log)
-
- with patch_utils, patch_rpm, patch_py_rpm, patch_utils_lib, patch_log:
- assert -1 == rpm.version_cmp("1", "2")
- assert mock_log.warning.called
- assert mock_rpmUtils.miscutils.compareEVR.called
+ assert -1 == rpm.version_cmp("1", "2")
+ assert mock_log.warning.called
+ assert mock_rpmUtils.miscutils.compareEVR.called
@ -367,32 +97,73 @@ index 0000000000..c9d1ac2b1c
+ mock_log.warning.mock_calls[0][1][0]
+ == "Please install a package that provides rpm.labelCompare for more accurate version comparisons."
+ )
+
+
-def test_version_cmp_rpmdev_vercmp():
+@patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
+@patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", False)
+@patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
+@patch("salt.utils.path.which", return_value=True)
+@patch("salt.modules.rpm_lowpkg.log")
+def test_version_cmp_rpmdev_vercmp(mock_log, mock_which):
+ """
+ Test package version if rpmdev-vercmp is installed
+
+ :return:
+ """
+ mock__salt__ = MagicMock(return_value={"retcode": 12})
"""
Test package version if rpmdev-vercmp is installed
:return:
"""
mock__salt__ = MagicMock(return_value={"retcode": 12})
- mock_log = MagicMock()
- patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- patch_rpmutils = patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", False)
- patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
- patch_which = patch("salt.utils.path.which", return_value=True)
- patch_log = patch("salt.modules.rpm_lowpkg.log", mock_log)
-
- with patch_rpm, patch_rpmutils, patch_py_rpm, patch_which, patch_log:
- with patch.dict(rpm.__salt__, {"cmd.run_all": mock__salt__}):
- assert -1 == rpm.version_cmp("1", "2")
- assert mock__salt__.called
- assert mock_log.warning.called
- assert (
- mock_log.warning.mock_calls[0][1][0]
- == "Please install a package that provides rpm.labelCompare for more accurate version comparisons."
- )
- assert (
- mock_log.warning.mock_calls[1][1][0]
- == "Installing the rpmdevtools package may surface dev tools in production."
- )
-
-
-def test_version_cmp_python():
- """
- Test package version if falling back to python
-
- :return:
- """
- mock_log = MagicMock()
- patch_rpm = patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- patch_rpmutils = patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", False)
- mock_version_cmp = MagicMock(return_value=-1)
- patch_py_rpm = patch("salt.modules.rpm_lowpkg.HAS_PY_RPM", False)
- patch_cmp = patch("salt.utils.versions.version_cmp", mock_version_cmp)
- patch_which = patch("salt.utils.path.which", return_value=False)
- patch_log = patch("salt.modules.rpm_lowpkg.log", mock_log)
-
- with patch_rpm, patch_rpmutils, patch_py_rpm, patch_cmp, patch_which, patch_log:
+ with patch.dict(rpm.__salt__, {"cmd.run_all": mock__salt__}):
+ assert -1 == rpm.version_cmp("1", "2")
assert -1 == rpm.version_cmp("1", "2")
- assert mock_version_cmp.called
+ assert mock__salt__.called
+ assert mock_log.warning.called
+ assert (
+ mock_log.warning.mock_calls[0][1][0]
+ == "Please install a package that provides rpm.labelCompare for more accurate version comparisons."
+ )
+ assert (
+ mock_log.warning.mock_calls[1][1][0]
assert mock_log.warning.called
assert (
mock_log.warning.mock_calls[0][1][0]
@@ -343,5 +309,237 @@ def test_version_cmp_python():
)
assert (
mock_log.warning.mock_calls[1][1][0]
- == "Falling back on salt.utils.versions.version_cmp() for version comparisons"
+ == "Installing the rpmdevtools package may surface dev tools in production."
+ )
)
+
+
+@patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
@ -625,491 +396,7 @@ index 0000000000..c9d1ac2b1c
+ with patch.dict(rpm.__salt__, {"cmd.retcode": mock}):
+ assert rpm.remove_gpg_key("gpg-pubkey-1")
+ assert not _called_with_root(mock)
diff --git a/tests/unit/modules/test_rpm_lowpkg.py b/tests/unit/modules/test_rpm_lowpkg.py
deleted file mode 100644
index 280a19b911..0000000000
--- a/tests/unit/modules/test_rpm_lowpkg.py
+++ /dev/null
@@ -1,478 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
- :codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
-"""
-
-# Import Python Libs
-from __future__ import absolute_import
-import datetime
-
-# Import Salt Libs
-import salt.modules.rpm_lowpkg as rpm
-
-# Import Salt Testing Libs
-from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import MagicMock, patch
-from tests.support.unit import TestCase
-
-
-def _called_with_root(mock):
- cmd = " ".join(mock.call_args[0][0])
- return cmd.startswith("rpm --root /")
-
-
-class RpmTestCase(TestCase, LoaderModuleMockMixin):
- """
- Test cases for salt.modules.rpm
- """
-
- def setup_loader_modules(self):
- return {rpm: {"rpm": MagicMock(return_value=MagicMock)}}
-
- # 'list_pkgs' function tests: 2
-
- def test_list_pkgs(self):
- """
- Test if it list the packages currently installed in a dict
- """
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- self.assertDictEqual(rpm.list_pkgs(), {})
- self.assertFalse(_called_with_root(mock))
-
- def test_list_pkgs_root(self):
- """
- Test if it list the packages currently installed in a dict,
- called with root parameter
- """
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- rpm.list_pkgs(root="/")
- self.assertTrue(_called_with_root(mock))
-
- # 'verify' function tests: 2
-
- def test_verify(self):
- """
- Test if it runs an rpm -Va on a system, and returns the
- results in a dict
- """
- mock = MagicMock(
- return_value={"stdout": "", "stderr": "", "retcode": 0, "pid": 12345}
- )
- with patch.dict(rpm.__salt__, {"cmd.run_all": mock}):
- self.assertDictEqual(rpm.verify("httpd"), {})
- self.assertFalse(_called_with_root(mock))
-
- def test_verify_root(self):
- """
- Test if it runs an rpm -Va on a system, and returns the
- results in a dict, called with root parameter
- """
- mock = MagicMock(
- return_value={"stdout": "", "stderr": "", "retcode": 0, "pid": 12345}
- )
- with patch.dict(rpm.__salt__, {"cmd.run_all": mock}):
- rpm.verify("httpd", root="/")
- self.assertTrue(_called_with_root(mock))
-
- # 'file_list' function tests: 2
-
- def test_file_list(self):
- """
- Test if it list the files that belong to a package.
- """
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- self.assertDictEqual(rpm.file_list("httpd"), {"errors": [], "files": []})
- self.assertFalse(_called_with_root(mock))
-
- def test_file_list_root(self):
- """
- Test if it list the files that belong to a package, using the
- root parameter.
- """
-
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- rpm.file_list("httpd", root="/")
- self.assertTrue(_called_with_root(mock))
-
- # 'file_dict' function tests: 2
-
- def test_file_dict(self):
- """
- Test if it list the files that belong to a package
- """
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- self.assertDictEqual(rpm.file_dict("httpd"), {"errors": [], "packages": {}})
- self.assertFalse(_called_with_root(mock))
-
- def test_file_dict_root(self):
- """
- Test if it list the files that belong to a package
- """
- mock = MagicMock(return_value="")
- with patch.dict(rpm.__salt__, {"cmd.run": mock}):
- rpm.file_dict("httpd", root="/")
- self.assertTrue(_called_with_root(mock))
-
- # 'owner' function tests: 1
-
- def test_owner(self):
- """
- Test if it return the name of the package that owns the file.
- """
- self.assertEqual(rpm.owner(), "")
-
- ret = "file /usr/bin/salt-jenkins-build is not owned by any package"
- mock = MagicMock(return_value=ret)
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(rpm.owner("/usr/bin/salt-jenkins-build"), "")
- self.assertFalse(_called_with_root(mock))
-
- ret = {
- "/usr/bin/vim": "vim-enhanced-7.4.160-1.e17.x86_64",
- "/usr/bin/python": "python-2.7.5-16.e17.x86_64",
- }
- mock = MagicMock(
- side_effect=[
- "python-2.7.5-16.e17.x86_64",
- "vim-enhanced-7.4.160-1.e17.x86_64",
- ]
- )
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertDictEqual(rpm.owner("/usr/bin/python", "/usr/bin/vim"), ret)
- self.assertFalse(_called_with_root(mock))
-
- def test_owner_root(self):
- """
- Test if it return the name of the package that owns the file,
- using the parameter root.
- """
- self.assertEqual(rpm.owner(), "")
-
- ret = "file /usr/bin/salt-jenkins-build is not owned by any package"
- mock = MagicMock(return_value=ret)
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- rpm.owner("/usr/bin/salt-jenkins-build", root="/")
- self.assertTrue(_called_with_root(mock))
-
- # 'checksum' function tests: 2
-
- def test_checksum(self):
- """
- Test if checksum validate as expected
- """
- ret = {
- "file1.rpm": True,
- "file2.rpm": False,
- "file3.rpm": False,
- }
-
- mock = MagicMock(side_effect=[True, 0, True, 1, False, 0])
- with patch.dict(rpm.__salt__, {"file.file_exists": mock, "cmd.retcode": mock}):
- self.assertDictEqual(
- rpm.checksum("file1.rpm", "file2.rpm", "file3.rpm"), ret
- )
- self.assertFalse(_called_with_root(mock))
-
- def test_checksum_root(self):
- """
- Test if checksum validate as expected, using the parameter
- root
- """
- mock = MagicMock(side_effect=[True, 0])
- with patch.dict(rpm.__salt__, {"file.file_exists": mock, "cmd.retcode": mock}):
- rpm.checksum("file1.rpm", root="/")
- self.assertTrue(_called_with_root(mock))
-
- @patch("salt.modules.rpm_lowpkg.HAS_RPM", True)
- @patch("salt.modules.rpm_lowpkg.rpm.labelCompare", return_value=-1)
- @patch("salt.modules.rpm_lowpkg.log")
- def test_version_cmp_rpm(self, mock_log, mock_labelCompare):
- """
- Test package version if RPM-Python is installed
-
- :return:
- """
- self.assertEqual(-1, rpm.version_cmp("1", "2"))
- self.assertEqual(mock_log.warning.called, False)
- self.assertEqual(mock_labelCompare.called, True)
-
- @patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- @patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", True)
- @patch("salt.modules.rpm_lowpkg.rpmUtils", create=True)
- @patch("salt.modules.rpm_lowpkg.log")
- def test_version_cmp_rpmutils(self, mock_log, mock_rpmUtils):
- """
- Test package version if rpmUtils.miscutils called
-
- :return:
- """
- mock_rpmUtils.miscutils = MagicMock()
- mock_rpmUtils.miscutils.compareEVR = MagicMock(return_value=-1)
- self.assertEqual(-1, rpm.version_cmp("1", "2"))
- self.assertEqual(mock_log.warning.called, True)
- self.assertEqual(mock_rpmUtils.miscutils.compareEVR.called, True)
- self.assertEqual(
- mock_log.warning.mock_calls[0][1][0],
- "Please install a package that provides rpm.labelCompare for more accurate version comparisons.",
- )
-
- @patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- @patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", False)
- @patch("salt.utils.path.which", return_value=True)
- @patch("salt.modules.rpm_lowpkg.log")
- def test_version_cmp_rpmdev_vercmp(self, mock_log, mock_which):
- """
- Test package version if rpmdev-vercmp is installed
-
- :return:
- """
- mock__salt__ = MagicMock(return_value={"retcode": 12})
- with patch.dict(rpm.__salt__, {"cmd.run_all": mock__salt__}):
- self.assertEqual(-1, rpm.version_cmp("1", "2"))
- self.assertEqual(mock__salt__.called, True)
- self.assertEqual(mock_log.warning.called, True)
- self.assertEqual(
- mock_log.warning.mock_calls[0][1][0],
- "Please install a package that provides rpm.labelCompare for more accurate version comparisons.",
- )
- self.assertEqual(
- mock_log.warning.mock_calls[1][1][0],
- "Installing the rpmdevtools package may surface dev tools in production.",
- )
-
- @patch("salt.modules.rpm_lowpkg.HAS_RPM", False)
- @patch("salt.modules.rpm_lowpkg.HAS_RPMUTILS", False)
- @patch("salt.utils.versions.version_cmp", return_value=-1)
- @patch("salt.utils.path.which", return_value=False)
- @patch("salt.modules.rpm_lowpkg.log")
- def test_version_cmp_python(self, mock_log, mock_which, mock_version_cmp):
- """
- Test package version if falling back to python
-
- :return:
- """
- with patch(
- "salt.modules.rpm_lowpkg.rpm.labelCompare", MagicMock(return_value=0)
- ), patch("salt.modules.rpm_lowpkg.HAS_RPM", False):
- self.assertEqual(
- -1, rpm.version_cmp("1", "2")
- ) # mock returns -1, a python implementation was called
-
- def test_list_gpg_keys_no_info(self):
- """
- Test list_gpg_keys with no extra information
- """
- mock = MagicMock(return_value="\n".join(["gpg-pubkey-1", "gpg-pubkey-2"]))
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(rpm.list_gpg_keys(), ["gpg-pubkey-1", "gpg-pubkey-2"])
- self.assertFalse(_called_with_root(mock))
-
- def test_list_gpg_keys_no_info_root(self):
- """
- Test list_gpg_keys with no extra information and root
- """
- mock = MagicMock(return_value="\n".join(["gpg-pubkey-1", "gpg-pubkey-2"]))
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(
- rpm.list_gpg_keys(root="/mnt"), ["gpg-pubkey-1", "gpg-pubkey-2"]
- )
- self.assertTrue(_called_with_root(mock))
-
- @patch("salt.modules.rpm_lowpkg.info_gpg_key")
- def test_list_gpg_keys_info(self, info_gpg_key):
- """
- Test list_gpg_keys with extra information
- """
- info_gpg_key.side_effect = lambda x, root: {
- "Description": "key for {}".format(x)
- }
- mock = MagicMock(return_value="\n".join(["gpg-pubkey-1", "gpg-pubkey-2"]))
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(
- rpm.list_gpg_keys(info=True),
- {
- "gpg-pubkey-1": {"Description": "key for gpg-pubkey-1"},
- "gpg-pubkey-2": {"Description": "key for gpg-pubkey-2"},
- },
- )
- self.assertFalse(_called_with_root(mock))
-
- def test_info_gpg_key(self):
- """
- Test info_gpg_keys from a normal output
- """
- info = """Name : gpg-pubkey
-Version : 3dbdc284
-Release : 53674dd4
-Architecture: (none)
-Install Date: Fri 08 Mar 2019 11:57:44 AM UTC
-Group : Public Keys
-Size : 0
-License : pubkey
-Signature : (none)
-Source RPM : (none)
-Build Date : Mon 05 May 2014 10:37:40 AM UTC
-Build Host : localhost
-Packager : openSUSE Project Signing Key <opensuse@opensuse.org>
-Summary : gpg(openSUSE Project Signing Key <opensuse@opensuse.org>)
-Description :
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: rpm-4.14.2.1 (NSS-3)
-
-mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G
-3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ
-93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO
-mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig
-oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD
-VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl
-Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC
-GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C
-hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI
-CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha
-Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr
-hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk
-4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a
-5v4gbqOcigKaFs9Lc3Bj8b/lE10Y
-=i2TA
------END PGP PUBLIC KEY BLOCK-----
-
-"""
- mock = MagicMock(return_value=info)
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(
- rpm.info_gpg_key("key"),
- {
- "Name": "gpg-pubkey",
- "Version": "3dbdc284",
- "Release": "53674dd4",
- "Architecture": None,
- "Install Date": datetime.datetime(2019, 3, 8, 11, 57, 44),
- "Group": "Public Keys",
- "Size": 0,
- "License": "pubkey",
- "Signature": None,
- "Source RPM": None,
- "Build Date": datetime.datetime(2014, 5, 5, 10, 37, 40),
- "Build Host": "localhost",
- "Packager": "openSUSE Project Signing Key <opensuse@opensuse.org>",
- "Summary": "gpg(openSUSE Project Signing Key <opensuse@opensuse.org>)",
- "Description": """-----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: rpm-4.14.2.1 (NSS-3)
-
-mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G
-3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ
-93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO
-mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig
-oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD
-VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl
-Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC
-GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C
-hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI
-CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha
-Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr
-hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk
-4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a
-5v4gbqOcigKaFs9Lc3Bj8b/lE10Y
-=i2TA
------END PGP PUBLIC KEY BLOCK-----""",
- },
- )
- self.assertFalse(_called_with_root(mock))
-
- def test_info_gpg_key_extended(self):
- """
- Test info_gpg_keys from an extended output
- """
- info = """Name : gpg-pubkey
-Version : 3dbdc284
-Release : 53674dd4
-Architecture: (none)
-Install Date: Fri 08 Mar 2019 11:57:44 AM UTC
-Group : Public Keys
-Size : 0
-License : pubkey
-Signature : (none)
-Source RPM : (none)
-Build Date : Mon 05 May 2014 10:37:40 AM UTC
-Build Host : localhost
-Packager : openSUSE Project Signing Key <opensuse@opensuse.org>
-Summary : gpg(openSUSE Project Signing Key <opensuse@opensuse.org>)
-Description :
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: rpm-4.14.2.1 (NSS-3)
-
-mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G
-3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ
-93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO
-mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig
-oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD
-VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl
-Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC
-GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C
-hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI
-CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha
-Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr
-hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk
-4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a
-5v4gbqOcigKaFs9Lc3Bj8b/lE10Y
-=i2TA
------END PGP PUBLIC KEY BLOCK-----
-
-Distribution: (none)
-"""
- mock = MagicMock(return_value=info)
- with patch.dict(rpm.__salt__, {"cmd.run_stdout": mock}):
- self.assertEqual(
- rpm.info_gpg_key("key"),
- {
- "Name": "gpg-pubkey",
- "Version": "3dbdc284",
- "Release": "53674dd4",
- "Architecture": None,
- "Install Date": datetime.datetime(2019, 3, 8, 11, 57, 44),
- "Group": "Public Keys",
- "Size": 0,
- "License": "pubkey",
- "Signature": None,
- "Source RPM": None,
- "Build Date": datetime.datetime(2014, 5, 5, 10, 37, 40),
- "Build Host": "localhost",
- "Packager": "openSUSE Project Signing Key <opensuse@opensuse.org>",
- "Summary": "gpg(openSUSE Project Signing Key <opensuse@opensuse.org>)",
- "Description": """-----BEGIN PGP PUBLIC KEY BLOCK-----
-Version: rpm-4.14.2.1 (NSS-3)
-
-mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G
-3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ
-93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO
-mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig
-oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD
-VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl
-Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC
-GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C
-hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI
-CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha
-Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr
-hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk
-4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a
-5v4gbqOcigKaFs9Lc3Bj8b/lE10Y
-=i2TA
------END PGP PUBLIC KEY BLOCK-----""",
- "Distribution": None,
- },
- )
- self.assertFalse(_called_with_root(mock))
-
- def test_remove_gpg_key(self):
- """
- Test remove_gpg_key
- """
- mock = MagicMock(return_value=0)
- with patch.dict(rpm.__salt__, {"cmd.retcode": mock}):
- self.assertTrue(rpm.remove_gpg_key("gpg-pubkey-1"))
- self.assertFalse(_called_with_root(mock))
--
2.33.1
2.34.1

View File

@ -1,97 +0,0 @@
From e3e55336b0d457cb55cd83236e9ac8e0dc671d2e Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Mon, 5 Jul 2021 18:57:26 +0300
Subject: [PATCH] Adding preliminary support for Rocky. (#59682) (#391)
* Adding preliminary support for Rocky.
* Adding changelog and test per MR guidence.
* Update test_core.py
Fix a clean up issue
Co-authored-by: Megan Wilhite <megan.wilhite@gmail.com>
Co-authored-by: Gareth J. Greenaway <gareth@wiked.org>
Co-authored-by: StackKorora <42156355+StackKorora@users.noreply.github.com>
Co-authored-by: Megan Wilhite <megan.wilhite@gmail.com>
Co-authored-by: Gareth J. Greenaway <gareth@wiked.org>
---
changelog/59682.added | 1 +
salt/grains/core.py | 2 ++
tests/unit/grains/test_core.py | 29 +++++++++++++++++++++++++++++
3 files changed, 32 insertions(+)
create mode 100644 changelog/59682.added
diff --git a/changelog/59682.added b/changelog/59682.added
new file mode 100644
index 0000000000..93b4a3d1fc
--- /dev/null
+++ b/changelog/59682.added
@@ -0,0 +1 @@
+Rocky Linux has been added to the RedHat os_family.
diff --git a/salt/grains/core.py b/salt/grains/core.py
index bce8c95179..f79110124f 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1560,6 +1560,7 @@ _OS_NAME_MAP = {
"linuxmint": "Mint",
"neon": "KDE neon",
"pop": "Pop",
+ "rocky": "Rocky",
"alibabaclo": "Alinux",
}
@@ -1637,6 +1638,7 @@ _OS_FAMILY_MAP = {
"AIX": "AIX",
"TurnKey": "Debian",
"Pop": "Debian",
+ "Rocky": "RedHat",
"AstraLinuxCE": "Debian",
"Alinux": "RedHat",
}
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index fa06bb27ab..fcc7586775 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -708,6 +708,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_rocky_8_os_grains(self):
+ """
+ Test if OS grains are parsed correctly in Rocky 8
+ """
+ _os_release_map = {
+ "os_release_file": {
+ "NAME": "Rocky",
+ "VERSION_ID": "8.3",
+ "PRETTY_NAME": "Rocky 8",
+ "ID": "Rocky",
+ "ANSI_COLOR": "0;31",
+ "CPE_NAME": "cpe:/o:rocky:rocky:8.3",
+ },
+ "_linux_distribution": ("rocky", "8.3", ""),
+ }
+
+ expectation = {
+ "os": "Rocky",
+ "os_family": "RedHat",
+ "oscodename": "Rocky 8",
+ "osfullname": "Rocky",
+ "osrelease": "8.3",
+ "osrelease_info": (8, 3,),
+ "osmajorrelease": 8,
+ "osfinger": "Rocky-8",
+ }
+ 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):
"""
--
2.33.0

View File

@ -1,218 +0,0 @@
From f0025c6d00f174db587726bb15b78713cbbcf996 Mon Sep 17 00:00:00 2001
From: "Daniel A. Wozniak" <dwozniak@saltstack.com>
Date: Mon, 2 Aug 2021 13:50:37 -0700
Subject: [PATCH] Better handling of bad public keys from minions
(bsc#1189040)
Add changelog for #57733
Fix pre-commit check
Add missing test
Fix test on older pythons
---
changelog/57733.fixed | 1 +
salt/crypt.py | 11 ++++++--
salt/exceptions.py | 6 ++++
salt/key.py | 15 ++++++++--
salt/transport/mixins/auth.py | 12 ++++----
.../pytests/integration/cli/test_salt_key.py | 28 +++++++++++++++++++
tests/pytests/unit/test_crypt.py | 20 +++++++++++++
7 files changed, 83 insertions(+), 10 deletions(-)
create mode 100644 changelog/57733.fixed
create mode 100644 tests/pytests/unit/test_crypt.py
diff --git a/changelog/57733.fixed b/changelog/57733.fixed
new file mode 100644
index 0000000000..0cd55b19a6
--- /dev/null
+++ b/changelog/57733.fixed
@@ -0,0 +1 @@
+Better handling of bad RSA public keys from minions
diff --git a/salt/crypt.py b/salt/crypt.py
index f3da78f9ba..789c562e25 100644
--- a/salt/crypt.py
+++ b/salt/crypt.py
@@ -36,6 +36,7 @@ import salt.utils.verify
import salt.version
from salt.exceptions import (
AuthenticationError,
+ InvalidKeyError,
MasterExit,
SaltClientError,
SaltReqTimeoutError,
@@ -220,10 +221,16 @@ def get_rsa_pub_key(path):
with salt.utils.files.fopen(path, "rb") as f:
data = f.read().replace(b"RSA ", b"")
bio = BIO.MemoryBuffer(data)
- key = RSA.load_pub_key_bio(bio)
+ try:
+ key = RSA.load_pub_key_bio(bio)
+ except RSA.RSAError:
+ raise InvalidKeyError("Encountered bad RSA public key")
else:
with salt.utils.files.fopen(path) as f:
- key = RSA.importKey(f.read())
+ try:
+ key = RSA.importKey(f.read())
+ except (ValueError, IndexError, TypeError):
+ raise InvalidKeyError("Encountered bad RSA public key")
return key
diff --git a/salt/exceptions.py b/salt/exceptions.py
index 033a19cc54..1da15f9e69 100644
--- a/salt/exceptions.py
+++ b/salt/exceptions.py
@@ -111,6 +111,12 @@ class AuthenticationError(SaltException):
"""
+class InvalidKeyError(SaltException):
+ """
+ Raised when we encounter an invalid RSA key.
+ """
+
+
class CommandNotFoundError(SaltException):
"""
Used in modules or grains when a required binary is not available
diff --git a/salt/key.py b/salt/key.py
index 16d20b1303..3b931152cc 100644
--- a/salt/key.py
+++ b/salt/key.py
@@ -9,6 +9,7 @@ import itertools
import logging
import os
import shutil
+import sys
import salt.cache
import salt.client
@@ -643,17 +644,27 @@ class Key:
keydirs.append(self.REJ)
if include_denied:
keydirs.append(self.DEN)
+ invalid_keys = []
for keydir in keydirs:
for key in matches.get(keydir, []):
+ key_path = os.path.join(self.opts["pki_dir"], keydir, key)
+ try:
+ salt.crypt.get_rsa_pub_key(key_path)
+ except salt.exceptions.InvalidKeyError:
+ log.error("Invalid RSA public key: %s", key)
+ invalid_keys.append((keydir, key))
+ continue
try:
shutil.move(
- os.path.join(self.opts["pki_dir"], keydir, key),
- os.path.join(self.opts["pki_dir"], self.ACC, key),
+ key_path, os.path.join(self.opts["pki_dir"], self.ACC, key),
)
eload = {"result": True, "act": "accept", "id": key}
self.event.fire_event(eload, salt.utils.event.tagify(prefix="key"))
except OSError:
pass
+ for keydir, key in invalid_keys:
+ matches[keydir].remove(key)
+ sys.stderr.write("Unable to accept invalid key for {}.\n".format(key))
return self.name_match(match) if match is not None else self.dict_match(matches)
def accept_all(self):
diff --git a/salt/transport/mixins/auth.py b/salt/transport/mixins/auth.py
index 102af568f3..29b38d3027 100644
--- a/salt/transport/mixins/auth.py
+++ b/salt/transport/mixins/auth.py
@@ -174,11 +174,11 @@ class AESReqServerMixin:
tagged "auth" and returns a dict with information about the auth
event
- # Verify that the key we are receiving matches the stored key
- # Store the key if it is not there
- # Make an RSA key with the pub key
- # Encrypt the AES key as an encrypted salt.payload
- # Package the return and return it
+ - Verify that the key we are receiving matches the stored key
+ - Store the key if it is not there
+ - Make an RSA key with the pub key
+ - Encrypt the AES key as an encrypted salt.payload
+ - Package the return and return it
"""
if not salt.utils.verify.valid_id(self.opts, load["id"]):
@@ -450,7 +450,7 @@ class AESReqServerMixin:
# and an empty request comes in
try:
pub = salt.crypt.get_rsa_pub_key(pubfn)
- except (ValueError, IndexError, TypeError) as err:
+ except salt.crypt.InvalidKeyError as err:
log.error('Corrupt public key "%s": %s', pubfn, err)
return {"enc": "clear", "load": {"ret": False}}
diff --git a/tests/pytests/integration/cli/test_salt_key.py b/tests/pytests/integration/cli/test_salt_key.py
index 3ec87fe580..8f29929747 100644
--- a/tests/pytests/integration/cli/test_salt_key.py
+++ b/tests/pytests/integration/cli/test_salt_key.py
@@ -316,3 +316,31 @@ def test_keys_generation_keysize_max(salt_key_cli):
)
assert ret.exitcode != 0
assert "error: The maximum value for keysize is 32768" in ret.stderr
+
+def test_keys_generation_keysize_max(salt_key_cli, tmp_path):
+ ret = salt_key_cli.run(
+ "--gen-keys", "minibar", "--gen-keys-dir", str(tmp_path), "--keysize", "32769"
+ )
+ assert ret.exitcode != 0
+ assert "error: The maximum value for keysize is 32768" in ret.stderr
+
+
+def test_accept_bad_key(salt_master, salt_key_cli):
+ """
+ test salt-key -d usage
+ """
+ min_name = random_string("minibar-")
+ pki_dir = salt_master.config["pki_dir"]
+ key = os.path.join(pki_dir, "minions_pre", min_name)
+
+ with salt.utils.files.fopen(key, "w") as fp:
+ fp.write("")
+
+ try:
+ # Check Key
+ ret = salt_key_cli.run("-y", "-a", min_name)
+ assert ret.exitcode == 0
+ assert "invalid key for {}".format(min_name) in ret.stderr
+ finally:
+ if os.path.exists(key):
+ os.remove(key)
diff --git a/tests/pytests/unit/test_crypt.py b/tests/pytests/unit/test_crypt.py
new file mode 100644
index 0000000000..aa8f439b8c
--- /dev/null
+++ b/tests/pytests/unit/test_crypt.py
@@ -0,0 +1,20 @@
+"""
+tests.pytests.unit.test_crypt
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Unit tests for salt's crypt module
+"""
+import pytest
+import salt.crypt
+import salt.utils.files
+
+
+def test_get_rsa_pub_key_bad_key(tmp_path):
+ """
+ get_rsa_pub_key raises InvalidKeyError when encoutering a bad key
+ """
+ key_path = str(tmp_path / "key")
+ with salt.utils.files.fopen(key_path, "w") as fp:
+ fp.write("")
+ with pytest.raises(salt.crypt.InvalidKeyError):
+ salt.crypt.get_rsa_pub_key(key_path)
--
2.33.0

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +0,0 @@
From a4412799453bf967aa14b93660bfc70f94e11a85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 30 Sep 2021 11:06:09 +0100
Subject: [PATCH] Do not break master_tops for minion with version lower
to 3003
---
salt/master.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/salt/master.py b/salt/master.py
index 1bfd278b31..2c5739cc90 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -1234,6 +1234,7 @@ class AESFuncs(TransportMethods):
"_dir_list",
"_symlink_list",
"_file_envs",
+ "_ext_nodes",
)
def __init__(self, opts):
@@ -1433,6 +1434,9 @@ class AESFuncs(TransportMethods):
return {}
return self.masterapi._master_tops(load, skip_verify=True)
+ # Needed so older minions can request master_tops
+ _ext_nodes = _master_tops
+
def _master_opts(self, load):
"""
Return the master options to the minion
--
2.33.0

View File

@ -1,60 +1,19 @@
From f9a66dbf39345b2b371b18e8bf9d89835d6381b7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 25 Jan 2021 12:15:59 +0000
From b151f2c1c6b6599b6387ec6e2d32a56e031e3d48 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 19:12:25 +0100
Subject: [PATCH] Do not crash when unexpected cmd output at listing
patches (bsc#1181290)
Add unit tests to cover unexpected output when listing patches
---
salt/modules/yumpkg.py | 20 +++++++--
tests/pytests/unit/modules/test_yumpkg.py | 53 +++++++++++++++++++++++
2 files changed, 70 insertions(+), 3 deletions(-)
1 file changed, 53 insertions(+)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index fd79109e40..c800dafa82 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -3325,10 +3325,17 @@ def _get_patches(installed_only=False):
cmd = [_yum(), "--quiet", "updateinfo", "list", "all"]
ret = __salt__["cmd.run_stdout"](cmd, python_shell=False, env={"SALT_RUNNING": "1"})
+ parsing_errors = False
+
for line in salt.utils.itertools.split(ret, os.linesep):
- inst, advisory_id, sev, pkg = re.match(
- r"([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)", line
- ).groups()
+ try:
+ inst, advisory_id, sev, pkg = re.match(
+ r"([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)", line
+ ).groups()
+ except Exception: # pylint: disable=broad-except
+ parsing_errors = True
+ continue
+
if advisory_id not in patches:
patches[advisory_id] = {
"installed": True if inst == "i" else False,
@@ -3339,6 +3346,13 @@ def _get_patches(installed_only=False):
if inst != "i":
patches[advisory_id]["installed"] = False
+ if parsing_errors:
+ log.warning(
+ "Skipped some unexpected output while running '{}' to list patches. Please check output".format(
+ " ".join(cmd)
+ )
+ )
+
if installed_only:
patches = {k: v for k, v in patches.items() if v["installed"]}
return patches
diff --git a/tests/pytests/unit/modules/test_yumpkg.py b/tests/pytests/unit/modules/test_yumpkg.py
index ef7100fe9d..df01853927 100644
index 475e1d6094..3b35272550 100644
--- a/tests/pytests/unit/modules/test_yumpkg.py
+++ b/tests/pytests/unit/modules/test_yumpkg.py
@@ -420,6 +420,59 @@ def test_list_patches():
@@ -433,6 +433,59 @@ def test_list_patches():
assert _patch in patches["my-fake-patch-installed-1234"]["summary"]
@ -115,6 +74,6 @@ index ef7100fe9d..df01853927 100644
with patch.object(yumpkg, "list_pkgs", MagicMock(return_value={})):
--
2.33.0
2.34.1

View File

@ -1,153 +0,0 @@
From e82c8832aed9ef46f5021558758ef9d944d89214 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 8 Mar 2021 12:35:14 +0000
Subject: [PATCH] Do not monkey patch yaml (bsc#1177474)
Add changelog file
Add suggestions by pre-commit
Add unit test to check for monkey patching
---
changelog/57995.fixed | 1 +
salt/utils/yamlloader.py | 28 ++++++++++------------------
tests/unit/utils/test_yamlloader.py | 6 +++++-
3 files changed, 16 insertions(+), 19 deletions(-)
create mode 100644 changelog/57995.fixed
diff --git a/changelog/57995.fixed b/changelog/57995.fixed
new file mode 100644
index 0000000000..78f2cd1fa4
--- /dev/null
+++ b/changelog/57995.fixed
@@ -0,0 +1 @@
+Do not monkey patch yaml loaders: Prevent breaking Ansible filter modules
diff --git a/salt/utils/yamlloader.py b/salt/utils/yamlloader.py
index e9d80fc4ad..f98fdcb0e9 100644
--- a/salt/utils/yamlloader.py
+++ b/salt/utils/yamlloader.py
@@ -1,10 +1,7 @@
-# -*- coding: utf-8 -*-
"""
Custom YAML loading in Salt
"""
-# Import python libs
-from __future__ import absolute_import, print_function, unicode_literals
import warnings
@@ -13,13 +10,8 @@ import yaml # pylint: disable=blacklisted-import
from yaml.constructor import ConstructorError
from yaml.nodes import MappingNode, SequenceNode
-try:
- yaml.Loader = yaml.CLoader
- yaml.Dumper = yaml.CDumper
- yaml.SafeLoader = yaml.CSafeLoader
- yaml.SafeDumper = yaml.CSafeDumper
-except Exception: # pylint: disable=broad-except
- pass
+# prefer C bindings over python when available
+BaseLoader = getattr(yaml, "CSafeLoader", yaml.SafeLoader)
__all__ = ["SaltYamlSafeLoader", "load", "safe_load"]
@@ -35,7 +27,7 @@ warnings.simplefilter("always", category=DuplicateKeyWarning)
# with code integrated from https://gist.github.com/844388
-class SaltYamlSafeLoader(yaml.SafeLoader):
+class SaltYamlSafeLoader(BaseLoader):
"""
Create a custom YAML loader that uses the custom constructor. This allows
for the YAML loading defaults to be manipulated based on needs within salt
@@ -43,7 +35,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
"""
def __init__(self, stream, dictclass=dict):
- super(SaltYamlSafeLoader, self).__init__(stream)
+ super().__init__(stream)
if dictclass is not dict:
# then assume ordered dict and use it for both !map and !omap
self.add_constructor("tag:yaml.org,2002:map", type(self).construct_yaml_map)
@@ -74,7 +66,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
raise ConstructorError(
None,
None,
- "expected a mapping node, but found {0}".format(node.id),
+ "expected a mapping node, but found {}".format(node.id),
node.start_mark,
)
@@ -90,7 +82,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
raise ConstructorError(
context,
node.start_mark,
- "found unacceptable key {0}".format(key_node.value),
+ "found unacceptable key {}".format(key_node.value),
key_node.start_mark,
)
value = self.construct_object(value_node, deep=deep)
@@ -98,7 +90,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
raise ConstructorError(
context,
node.start_mark,
- "found conflicting ID '{0}'".format(key),
+ "found conflicting ID '{}'".format(key),
key_node.start_mark,
)
mapping[key] = value
@@ -118,7 +110,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
# an empty string. Change it to '0'.
if node.value == "":
node.value = "0"
- return super(SaltYamlSafeLoader, self).construct_scalar(node)
+ return super().construct_scalar(node)
def construct_yaml_str(self, node):
value = self.construct_scalar(node)
@@ -142,7 +134,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
raise ConstructorError(
"while constructing a mapping",
node.start_mark,
- "expected a mapping for merging, but found {0}".format(
+ "expected a mapping for merging, but found {}".format(
subnode.id
),
subnode.start_mark,
@@ -156,7 +148,7 @@ class SaltYamlSafeLoader(yaml.SafeLoader):
raise ConstructorError(
"while constructing a mapping",
node.start_mark,
- "expected a mapping or list of mappings for merging, but found {0}".format(
+ "expected a mapping or list of mappings for merging, but found {}".format(
value_node.id
),
value_node.start_mark,
diff --git a/tests/unit/utils/test_yamlloader.py b/tests/unit/utils/test_yamlloader.py
index e1d60aeed0..a5de963817 100644
--- a/tests/unit/utils/test_yamlloader.py
+++ b/tests/unit/utils/test_yamlloader.py
@@ -5,7 +5,7 @@
import textwrap
import salt.utils.files
-from salt.utils.yamlloader import SaltYamlSafeLoader
+from salt.utils.yamlloader import SaltYamlSafeLoader, yaml
from tests.support.mock import mock_open, patch
from tests.support.unit import TestCase
from yaml.constructor import ConstructorError
@@ -133,3 +133,7 @@ class YamlLoaderTestCase(TestCase):
),
{"foo": {"b": {"foo": "bar", "one": 1, "list": [1, "two", 3]}}},
)
+
+ def test_not_yaml_monkey_patching(self):
+ if hasattr(yaml, "CSafeLoader"):
+ assert yaml.SafeLoader != yaml.CSafeLoader
--
2.33.0

View File

@ -1,42 +0,0 @@
From 421988aea296ced1f8c63cfa4b517b25eedfb00c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Tue, 29 Jan 2019 09:44:03 +0100
Subject: [PATCH] Don't call zypper with more than one --no-refresh
Now zypper started being picky and errors out when --no-refresh is
passed twice. Make sure we won't hit this.
---
salt/modules/zypperpkg.py | 2 +-
tests/unit/modules/test_zypperpkg.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 6fa6e3e0a1..dfaaf420a1 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -300,7 +300,7 @@ class _Zypper:
self.__called = True
if self.__xml:
self.__cmd.append("--xmlout")
- if not self.__refresh:
+ if not self.__refresh and "--no-refresh" not in args:
self.__cmd.append("--no-refresh")
if self.__root:
self.__cmd.extend(["--root", self.__root])
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index 7bff7065c6..b07f9a3af7 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -136,7 +136,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(zypper.__zypper__.call("foo"), stdout_xml_snippet)
self.assertEqual(len(sniffer.calls), 1)
- zypper.__zypper__.call("bar")
+ zypper.__zypper__.call("--no-refresh", "bar")
self.assertEqual(len(sniffer.calls), 2)
self.assertEqual(
sniffer.calls[0]["args"][0],
--
2.29.2

View File

@ -1,6 +1,6 @@
From a20d99db6de68bd4e7a4d2eda4c1c590aea449e7 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 10 Jul 2018 12:06:33 +0200
From f24c61d3c1ede64c0ef5c11efeb7d2293e714550 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 16:40:45 +0100
Subject: [PATCH] early feature: support-config
Add support script function
@ -527,19 +527,19 @@ Check last function by full name
salt/cli/support/profiles/postgres.yml | 11 +
salt/cli/support/profiles/salt.yml | 9 +
salt/cli/support/profiles/users.yml | 22 +
salt/loader.py | 6 +-
salt/loader/lazy.py | 6 +-
salt/modules/saltsupport.py | 405 ++++++++++++++++
salt/scripts.py | 15 +
salt/state.py | 38 +-
salt/states/saltsupport.py | 225 +++++++++
salt/utils/args.py | 3 +-
salt/utils/decorators/__init__.py | 68 +--
salt/utils/decorators/__init__.py | 24 +
salt/utils/parsers.py | 114 +++++
scripts/salt-support | 11 +
setup.py | 2 +
tests/unit/cli/test_support.py | 553 +++++++++++++++++++++
tests/unit/modules/test_saltsupport.py | 496 +++++++++++++++++++
28 files changed, 2973 insertions(+), 36 deletions(-)
28 files changed, 2958 insertions(+), 7 deletions(-)
create mode 100644 salt/cli/support/__init__.py
create mode 100644 salt/cli/support/collector.py
create mode 100644 salt/cli/support/console.py
@ -561,10 +561,10 @@ Check last function by full name
create mode 100644 tests/unit/modules/test_saltsupport.py
diff --git a/doc/ref/modules/all/index.rst b/doc/ref/modules/all/index.rst
index d9501ae4d9..3fff7ad636 100644
index 43dfb700f9..73958181dd 100644
--- a/doc/ref/modules/all/index.rst
+++ b/doc/ref/modules/all/index.rst
@@ -414,6 +414,7 @@ execution modules
@@ -415,6 +415,7 @@ execution modules
salt_version
saltcheck
saltcloudmod
@ -1739,12 +1739,12 @@ index 0000000000..391acdb606
+ - group.getent:
+ info: List of all available groups
+ output: table
diff --git a/salt/loader.py b/salt/loader.py
index 7a32f4c90d..491768a028 100644
--- a/salt/loader.py
+++ b/salt/loader.py
@@ -2019,8 +2019,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
}
diff --git a/salt/loader/lazy.py b/salt/loader/lazy.py
index 48c70d01c0..220641059c 100644
--- a/salt/loader/lazy.py
+++ b/salt/loader/lazy.py
@@ -950,8 +950,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
mod_names = [module_name] + list(virtual_aliases)
for attr in getattr(mod, "__load__", dir(mod)):
- if attr.startswith("_"):
@ -2168,10 +2168,10 @@ index 0000000000..e800e3bf1f
+
+ return __virtualname__
diff --git a/salt/scripts.py b/salt/scripts.py
index 8f3cde8477..e5c248f011 100644
index 93eab0f702..b1fea566a9 100644
--- a/salt/scripts.py
+++ b/salt/scripts.py
@@ -592,3 +592,18 @@ def salt_unity():
@@ -574,3 +574,18 @@ def salt_unity():
sys.argv.pop(1)
s_fun = getattr(sys.modules[__name__], "salt_{}".format(cmd))
s_fun()
@ -2191,10 +2191,10 @@ index 8f3cde8477..e5c248f011 100644
+ _install_signal_handlers(client)
+ client.run()
diff --git a/salt/state.py b/salt/state.py
index f999191e6d..f5ac3199c7 100644
index 91927d9ec6..fa5a578dc6 100644
--- a/salt/state.py
+++ b/salt/state.py
@@ -1565,7 +1565,9 @@ class State:
@@ -1577,7 +1577,9 @@ class State:
names = []
if state.startswith("__"):
continue
@ -2205,7 +2205,7 @@ index f999191e6d..f5ac3199c7 100644
if orchestration_jid is not None:
chunk["__orchestration_jid__"] = orchestration_jid
if "__sls__" in body:
@@ -2168,9 +2170,16 @@ class State:
@@ -2176,9 +2178,16 @@ class State:
ret = self.call_parallel(cdata, low)
else:
self.format_slots(cdata)
@ -2225,7 +2225,7 @@ index f999191e6d..f5ac3199c7 100644
self.states.inject_globals = {}
if (
"check_cmd" in low
@@ -3242,10 +3251,31 @@ class State:
@@ -3252,10 +3261,31 @@ class State:
running.update(errors)
return running
@ -2510,153 +2510,11 @@ index ba50aff126..4e5ca0eedf 100644
aspec = get_function_argspec(fun, is_class_method=is_class_method)
diff --git a/salt/utils/decorators/__init__.py b/salt/utils/decorators/__init__.py
index 940d0a90f2..b06cf0abc8 100644
index 20803771ed..0aba77e194 100644
--- a/salt/utils/decorators/__init__.py
+++ b/salt/utils/decorators/__init__.py
@@ -1,10 +1,7 @@
-# -*- coding: utf-8 -*-
"""
Helpful decorators for module writing
"""
-# Import python libs
-from __future__ import absolute_import, print_function, unicode_literals
import errno
import inspect
@@ -15,13 +12,10 @@ import time
from collections import defaultdict
from functools import wraps
-# Import salt libs
import salt.utils.args
import salt.utils.data
import salt.utils.versions
from salt.exceptions import CommandExecutionError, SaltConfigurationError
-
-# Import 3rd-party libs
from salt.ext import six
from salt.log import LOG_LEVELS
@@ -32,7 +26,7 @@ if getattr(sys, "getwindowsversion", False):
log = logging.getLogger(__name__)
-class Depends(object):
+class Depends:
"""
This decorator will check the module when it is loaded and check that the
dependencies passed in are in the globals of the module. If not, it will
@@ -121,7 +115,7 @@ class Depends(object):
@staticmethod
def run_command(dependency, mod_name, func_name):
- full_name = "{0}.{1}".format(mod_name, func_name)
+ full_name = "{}.{}".format(mod_name, func_name)
log.trace("Running '%s' for '%s'", dependency, full_name)
if IS_WINDOWS:
args = salt.utils.args.shlex_split(dependency, posix=False)
@@ -145,8 +139,8 @@ class Depends(object):
It will modify the "functions" dict and remove/replace modules that
are missing dependencies.
"""
- for dependency, dependent_dict in six.iteritems(cls.dependency_dict[kind]):
- for (mod_name, func_name), (frame, params) in six.iteritems(dependent_dict):
+ for dependency, dependent_dict in cls.dependency_dict[kind].items():
+ for (mod_name, func_name), (frame, params) in dependent_dict.items():
if mod_name != tgt_mod:
continue
# Imports from local context take presedence over those from the global context.
@@ -232,7 +226,7 @@ class Depends(object):
except (AttributeError, KeyError):
pass
- mod_key = "{0}.{1}".format(mod_name, func_name)
+ mod_key = "{}.{}".format(mod_name, func_name)
# if we don't have this module loaded, skip it!
if mod_key not in functions:
@@ -267,9 +261,7 @@ def timing(function):
mod_name = function.__module__[16:]
else:
mod_name = function.__module__
- fstr = "Function %s.%s took %.{0}f seconds to execute".format(
- sys.float_info.dig
- )
+ fstr = "Function %s.%s took %.{}f seconds to execute".format(sys.float_info.dig)
log.profile(fstr, mod_name, function.__name__, end_time - start_time)
return ret
@@ -291,13 +283,13 @@ def memoize(func):
def _memoize(*args, **kwargs):
str_args = []
for arg in args:
- if not isinstance(arg, six.string_types):
- str_args.append(six.text_type(arg))
+ if not isinstance(arg, str):
+ str_args.append(str(arg))
else:
str_args.append(arg)
args_ = ",".join(
- list(str_args) + ["{0}={1}".format(k, kwargs[k]) for k in sorted(kwargs)]
+ list(str_args) + ["{}={}".format(k, kwargs[k]) for k in sorted(kwargs)]
)
if args_ not in cache:
cache[args_] = func(*args, **kwargs)
@@ -306,7 +298,7 @@ def memoize(func):
return _memoize
-class _DeprecationDecorator(object):
+class _DeprecationDecorator:
"""
Base mix-in class for the deprecation decorator.
Takes care of a common functionality, used in its derivatives.
@@ -359,7 +351,7 @@ class _DeprecationDecorator(object):
try:
return self._function(*args, **kwargs)
except TypeError as error:
- error = six.text_type(error).replace(
+ error = str(error).replace(
self._function, self._orig_f_name
) # Hide hidden functions
log.error(
@@ -374,7 +366,7 @@ class _DeprecationDecorator(object):
self._function.__name__,
error,
)
- six.reraise(*sys.exc_info())
+ raise
else:
raise CommandExecutionError(
"Function is deprecated, but the successor function was not found."
@@ -626,11 +618,11 @@ class _WithDeprecated(_DeprecationDecorator):
if use_deprecated and use_superseded:
raise SaltConfigurationError(
- "Function '{0}' is mentioned both in deprecated "
+ "Function '{}' is mentioned both in deprecated "
"and superseded sections. Please remove any of that.".format(full_name)
)
old_function = self._globals.get(
- self._with_name or "_{0}".format(function.__name__)
+ self._with_name or "_{}".format(function.__name__)
)
if self._policy == self.OPT_IN:
self._function = function if use_superseded else old_function
@@ -782,12 +774,30 @@ def ensure_unicode_args(function):
@wraps(function)
def wrapped(*args, **kwargs):
- if six.PY2:
- return function(
- *salt.utils.data.decode_list(args),
- **salt.utils.data.decode_dict(kwargs)
- )
- else:
- return function(*args, **kwargs)
+ return function(*args, **kwargs)
@@ -867,3 +867,27 @@ def ensure_unicode_args(function):
return function(*args, **kwargs)
return wrapped
+
@ -2684,7 +2542,7 @@ index 940d0a90f2..b06cf0abc8 100644
+
+ return f
diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py
index 2a5abb25d5..31a2bf0b64 100644
index 28660397d4..c0820e5df0 100644
--- a/salt/utils/parsers.py
+++ b/salt/utils/parsers.py
@@ -17,6 +17,7 @@ import optparse
@ -2703,7 +2561,7 @@ index 2a5abb25d5..31a2bf0b64 100644
import salt.utils.platform
import salt.utils.process
import salt.utils.stringutils
@@ -2066,6 +2068,118 @@ class SyndicOptionParser(
@@ -2088,6 +2090,118 @@ class SyndicOptionParser(
return opts
@ -2840,10 +2698,10 @@ index 0000000000..4e0e79f3ea
+if __name__ == "__main__":
+ salt_support()
diff --git a/setup.py b/setup.py
index 031f2bc492..6f3c1abd76 100755
index af8e448007..2f6dfd6064 100755
--- a/setup.py
+++ b/setup.py
@@ -1251,6 +1251,7 @@ class SaltDistribution(distutils.dist.Distribution):
@@ -1253,6 +1253,7 @@ class SaltDistribution(distutils.dist.Distribution):
"scripts/salt-master",
"scripts/salt-minion",
"scripts/salt-proxy",
@ -2851,7 +2709,7 @@ index 031f2bc492..6f3c1abd76 100755
"scripts/salt-ssh",
"scripts/salt-syndic",
"scripts/salt-unity",
@@ -1297,6 +1298,7 @@ class SaltDistribution(distutils.dist.Distribution):
@@ -1299,6 +1300,7 @@ class SaltDistribution(distutils.dist.Distribution):
"salt-key = salt.scripts:salt_key",
"salt-master = salt.scripts:salt_master",
"salt-minion = salt.scripts:salt_minion",
@ -3921,6 +3779,6 @@ index 0000000000..f9ce7be29a
+ "00:00:00.000 - The real TTYs became " "pseudo TTYs and vice versa"
+ ]
--
2.33.0
2.34.1

View File

@ -1,4 +1,4 @@
From fec7f65b4debede8cf0eef335182fce2206e200d Mon Sep 17 00:00:00 2001
From c8f4092f117bd93293e0957422555d3ae7bae999 Mon Sep 17 00:00:00 2001
From: Maximilian Meister <mmeister@suse.de>
Date: Thu, 3 May 2018 15:52:23 +0200
Subject: [PATCH] enable passing a unix_socket for mysql returners
@ -15,19 +15,14 @@ the refactor is done upstream
Signed-off-by: Maximilian Meister <mmeister@suse.de>
---
salt/returners/mysql.py | 63 ++++++++++++++++++++---------------------
1 file changed, 30 insertions(+), 33 deletions(-)
salt/returners/mysql.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py
index b7bb05164f..4aa8aeddfa 100644
index 6fd4fdef2c..7a7e9a3284 100644
--- a/salt/returners/mysql.py
+++ b/salt/returners/mysql.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Return data to a mysql server
@@ -18,6 +17,7 @@ config. These are the defaults:
@@ -17,6 +17,7 @@ config. These are the defaults:
mysql.pass: 'salt'
mysql.db: 'salt'
mysql.port: 3306
@ -35,7 +30,7 @@ index b7bb05164f..4aa8aeddfa 100644
SSL is optional. The defaults are set to None. If you do not want to use SSL,
either exclude these options or set them to None.
@@ -43,6 +43,7 @@ optional. The following ssl options are simply for illustration purposes:
@@ -42,6 +43,7 @@ optional. The following ssl options are simply for illustration purposes:
alternative.mysql.ssl_ca: '/etc/pki/mysql/certs/localhost.pem'
alternative.mysql.ssl_cert: '/etc/pki/mysql/certs/localhost.crt'
alternative.mysql.ssl_key: '/etc/pki/mysql/certs/localhost.key'
@ -43,30 +38,7 @@ index b7bb05164f..4aa8aeddfa 100644
Should you wish the returner data to be cleaned out every so often, set
`keep_jobs` to the number of hours for the jobs to live in the tables.
@@ -138,22 +139,15 @@ To override individual configuration items, append --return_kwargs '{"key:": "va
salt '*' test.ping --return mysql --return_kwargs '{"db": "another-salt"}'
"""
-from __future__ import absolute_import, print_function, unicode_literals
import logging
import sys
-
-# Import python libs
from contextlib import contextmanager
import salt.exceptions
-
-# Import salt libs
import salt.returners
import salt.utils.jid
import salt.utils.json
-
-# Import 3rd-party libs
from salt.ext import six
# Let's not allow PyLint complain about string substitution
@@ -205,6 +199,7 @@ def _get_options(ret=None):
@@ -196,6 +198,7 @@ def _get_options(ret=None):
"ssl_ca": None,
"ssl_cert": None,
"ssl_key": None,
@ -74,7 +46,7 @@ index b7bb05164f..4aa8aeddfa 100644
}
attrs = {
@@ -216,6 +211,7 @@ def _get_options(ret=None):
@@ -207,6 +210,7 @@ def _get_options(ret=None):
"ssl_ca": "ssl_ca",
"ssl_cert": "ssl_cert",
"ssl_key": "ssl_key",
@ -82,18 +54,7 @@ index b7bb05164f..4aa8aeddfa 100644
}
_options = salt.returners.get_returner_options(
@@ -227,8 +223,8 @@ def _get_options(ret=None):
defaults=defaults,
)
# post processing
- for k, v in six.iteritems(_options):
- if isinstance(v, six.string_types) and v.lower() == "none":
+ for k, v in _options.items():
+ if isinstance(v, str) and v.lower() == "none":
# Ensure 'None' is rendered as None
_options[k] = None
if k == "port":
@@ -274,6 +270,7 @@ def _get_serv(ret=None, commit=False):
@@ -265,6 +269,7 @@ def _get_serv(ret=None, commit=False):
db=_options.get("db"),
port=_options.get("port"),
ssl=ssl_options,
@ -101,137 +62,7 @@ index b7bb05164f..4aa8aeddfa 100644
)
try:
@@ -291,9 +288,9 @@ def _get_serv(ret=None, commit=False):
yield cursor
except MySQLdb.DatabaseError as err:
error = err.args
- sys.stderr.write(six.text_type(error))
+ sys.stderr.write(str(error))
cursor.execute("ROLLBACK")
- six.reraise(*sys.exc_info())
+ raise
else:
if commit:
cursor.execute("COMMIT")
@@ -515,8 +512,8 @@ def _purge_jobs(timestamp):
log.error(
"mysql returner archiver was unable to delete contents of table 'jids'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
try:
sql = "delete from `salt_returns` where alter_time < %s"
@@ -526,8 +523,8 @@ def _purge_jobs(timestamp):
log.error(
"mysql returner archiver was unable to delete contents of table 'salt_returns'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
try:
sql = "delete from `salt_events` where alter_time < %s"
@@ -537,8 +534,8 @@ def _purge_jobs(timestamp):
log.error(
"mysql returner archiver was unable to delete contents of table 'salt_events'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
return True
@@ -556,7 +553,7 @@ def _archive_jobs(timestamp):
for table_name in source_tables:
try:
tmp_table_name = table_name + "_archive"
- sql = "create table if not exists {0} like {1}".format(
+ sql = "create table if not exists {} like {}".format(
tmp_table_name, table_name
)
cur.execute(sql)
@@ -566,11 +563,11 @@ def _archive_jobs(timestamp):
log.error(
"mysql returner archiver was unable to create the archive tables."
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
try:
- sql = "insert into `{0}` select * from `{1}` where jid in (select distinct jid from salt_returns where alter_time < %s)".format(
+ sql = "insert into `{}` select * from `{}` where jid in (select distinct jid from salt_returns where alter_time < %s)".format(
target_tables["jids"], "jids"
)
cur.execute(sql, (timestamp,))
@@ -579,14 +576,14 @@ def _archive_jobs(timestamp):
log.error(
"mysql returner archiver was unable to copy contents of table 'jids'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
except Exception as e: # pylint: disable=broad-except
log.error(e)
raise
try:
- sql = "insert into `{0}` select * from `{1}` where alter_time < %s".format(
+ sql = "insert into `{}` select * from `{}` where alter_time < %s".format(
target_tables["salt_returns"], "salt_returns"
)
cur.execute(sql, (timestamp,))
@@ -595,11 +592,11 @@ def _archive_jobs(timestamp):
log.error(
"mysql returner archiver was unable to copy contents of table 'salt_returns'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
try:
- sql = "insert into `{0}` select * from `{1}` where alter_time < %s".format(
+ sql = "insert into `{}` select * from `{}` where alter_time < %s".format(
target_tables["salt_events"], "salt_events"
)
cur.execute(sql, (timestamp,))
@@ -608,8 +605,8 @@ def _archive_jobs(timestamp):
log.error(
"mysql returner archiver was unable to copy contents of table 'salt_events'"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
return _purge_jobs(timestamp)
@@ -623,7 +620,7 @@ def clean_old_jobs():
if __opts__.get("keep_jobs", False) and int(__opts__.get("keep_jobs", 0)) > 0:
try:
with _get_serv() as cur:
- sql = "select date_sub(now(), interval {0} hour) as stamp;".format(
+ sql = "select date_sub(now(), interval {} hour) as stamp;".format(
__opts__["keep_jobs"]
)
cur.execute(sql)
@@ -638,5 +635,5 @@ def clean_old_jobs():
log.error(
"Mysql returner was unable to get timestamp for purge/archive of jobs"
)
- log.error(six.text_type(e))
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
+ log.error(str(e))
+ raise salt.exceptions.SaltRunnerError(str(e))
--
2.29.2
2.34.1

View File

@ -1,4 +1,4 @@
From 9071189b7395284f0328b59c999c18919e12ae32 Mon Sep 17 00:00:00 2001
From 933345d049a0207e730ca518dc5f016b0c05d761 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 7 Jul 2021 15:41:48 +0100
@ -17,9 +17,9 @@ Co-authored-by: Michael Calmer <mc@suse.de>
Fix error handling in openscap module (bsc#1188647) (#409)
---
changelog/59756.added | 1 +
salt/modules/openscap.py | 126 +++++++++++++--
salt/modules/openscap.py | 116 +++++++++++++-
tests/unit/modules/test_openscap.py | 234 ++++++++++++++++++++++++++++
3 files changed, 352 insertions(+), 9 deletions(-)
3 files changed, 350 insertions(+), 1 deletion(-)
create mode 100644 changelog/59756.added
diff --git a/changelog/59756.added b/changelog/59756.added
@ -30,41 +30,18 @@ index 0000000000..a59fb21eef
@@ -0,0 +1 @@
+adding new call for openscap xccdf eval supporting new parameters
diff --git a/salt/modules/openscap.py b/salt/modules/openscap.py
index 6f8ff4a76d..216fd89eef 100644
index 770c8e7c04..216fd89eef 100644
--- a/salt/modules/openscap.py
+++ b/salt/modules/openscap.py
@@ -1,20 +1,15 @@
-# -*- coding: utf-8 -*-
"""
Module for OpenSCAP Management
@@ -4,6 +4,7 @@ Module for OpenSCAP Management
"""
-# Import Python libs
-from __future__ import absolute_import, print_function, unicode_literals
+import os.path
import shlex
import shutil
import tempfile
from subprocess import PIPE, Popen
-# Import Salt libs
-from salt.ext import six
-
ArgumentParser = object
try:
@@ -44,7 +39,7 @@ def __virtual__():
class _ArgumentParser(ArgumentParser):
def __init__(self, action=None, *args, **kwargs):
- super(_ArgumentParser, self).__init__(*args, prog="oscap", **kwargs)
+ super().__init__(*args, prog="oscap", **kwargs)
self.add_argument("action", choices=["eval"])
add_arg = None
for params, kwparams in _XCCDF_MAP["eval"]["parser_arguments"]:
@@ -61,6 +56,117 @@ _OSCAP_EXIT_CODES_MAP = {
@@ -55,6 +56,117 @@ _OSCAP_EXIT_CODES_MAP = {
}
@ -182,15 +159,7 @@ index 6f8ff4a76d..216fd89eef 100644
def xccdf(params):
"""
Run ``oscap xccdf`` commands on minions.
@@ -91,14 +197,16 @@ def xccdf(params):
args, argv = _ArgumentParser(action=action).parse_known_args(args=params)
except Exception as err: # pylint: disable=broad-except
success = False
- error = six.text_type(err)
+ error = str(err)
if success:
cmd = _XCCDF_MAP[action]["cmd_pattern"].format(args.profile, policy)
@@ -92,7 +204,9 @@ def xccdf(params):
tempdir = tempfile.mkdtemp()
proc = Popen(shlex.split(cmd), stdout=PIPE, stderr=PIPE, cwd=tempdir)
(stdoutdata, error) = proc.communicate()
@ -451,6 +420,6 @@ index 045c37f7c9..301c1869ec 100644
+ },
+ )
--
2.33.0
2.34.1

View File

@ -1,125 +0,0 @@
From 1b54843abe5fad0bac844d6d5d9707df3e501aae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 19 May 2021 16:24:27 +0100
Subject: [PATCH] Figure out Python interpreter to use inside containers
Fix unit test for dockermod.call function
---
salt/modules/dockermod.py | 28 +++++++++++++++++++++++---
tests/unit/modules/test_dockermod.py | 30 +++++++++++++++-------------
2 files changed, 41 insertions(+), 17 deletions(-)
diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py
index ab2296a945..6d60a9a5aa 100644
--- a/salt/modules/dockermod.py
+++ b/salt/modules/dockermod.py
@@ -209,7 +209,6 @@ import re
import shutil
import string
import subprocess
-import sys
import time
import uuid
@@ -6728,9 +6727,32 @@ def call(name, function, *args, **kwargs):
name, thin_path, os.path.join(thin_dest_path, os.path.basename(thin_path))
)
+ # figure out available python interpreter inside the container
+ pycmds = (
+ "python3",
+ "/usr/libexec/platform-python",
+ "python27",
+ "python2.7",
+ "python26",
+ "python2.6",
+ "python2",
+ "python",
+ )
+ container_python_bin = None
+ for py_cmd in pycmds:
+ cmd = [py_cmd] + ["--version"]
+ ret = run_all(name, subprocess.list2cmdline(cmd))
+ if ret["retcode"] == 0:
+ container_python_bin = py_cmd
+ break
+ if not container_python_bin:
+ raise CommandExecutionError(
+ "Python interpreter cannot be found inside the container. Make sure Python is installed in the container"
+ )
+
# untar archive
untar_cmd = [
- "python",
+ container_python_bin,
"-c",
"import tarfile; "
'tarfile.open("{0}/{1}").extractall(path="{0}")'.format(
@@ -6744,7 +6766,7 @@ def call(name, function, *args, **kwargs):
try:
salt_argv = (
[
- "python{}".format(sys.version_info[0]),
+ container_python_bin,
os.path.join(thin_dest_path, "salt-call"),
"--metadata",
"--local",
diff --git a/tests/unit/modules/test_dockermod.py b/tests/unit/modules/test_dockermod.py
index 2c3665de85..fcedaf9272 100644
--- a/tests/unit/modules/test_dockermod.py
+++ b/tests/unit/modules/test_dockermod.py
@@ -987,33 +987,35 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
# [ call(name, [args]), ...
self.maxDiff = None
self.assertIn("mkdir", docker_run_all_mock.mock_calls[0][1][1])
- self.assertIn("mkdir", docker_run_all_mock.mock_calls[4][1][1])
+ self.assertIn("mkdir", docker_run_all_mock.mock_calls[5][1][1])
self.assertNotEqual(
docker_run_all_mock.mock_calls[0][1][1],
- docker_run_all_mock.mock_calls[4][1][1],
+ docker_run_all_mock.mock_calls[5][1][1],
)
- self.assertIn("salt-call", docker_run_all_mock.mock_calls[2][1][1])
- self.assertIn("salt-call", docker_run_all_mock.mock_calls[6][1][1])
+ self.assertEqual("python3 --version", docker_run_all_mock.mock_calls[1][1][1])
+
+ self.assertIn("salt-call", docker_run_all_mock.mock_calls[3][1][1])
+ self.assertIn("salt-call", docker_run_all_mock.mock_calls[8][1][1])
self.assertNotEqual(
- docker_run_all_mock.mock_calls[2][1][1],
- docker_run_all_mock.mock_calls[6][1][1],
+ docker_run_all_mock.mock_calls[3][1][1],
+ docker_run_all_mock.mock_calls[8][1][1],
)
# check thin untar
- self.assertIn("tarfile", docker_run_all_mock.mock_calls[1][1][1])
- self.assertIn("tarfile", docker_run_all_mock.mock_calls[5][1][1])
+ self.assertIn("tarfile", docker_run_all_mock.mock_calls[2][1][1])
+ self.assertIn("tarfile", docker_run_all_mock.mock_calls[7][1][1])
self.assertNotEqual(
- docker_run_all_mock.mock_calls[1][1][1],
- docker_run_all_mock.mock_calls[5][1][1],
+ docker_run_all_mock.mock_calls[2][1][1],
+ docker_run_all_mock.mock_calls[7][1][1],
)
# check directory cleanup
- self.assertIn("rm -rf", docker_run_all_mock.mock_calls[3][1][1])
- self.assertIn("rm -rf", docker_run_all_mock.mock_calls[7][1][1])
+ self.assertIn("rm -rf", docker_run_all_mock.mock_calls[4][1][1])
+ self.assertIn("rm -rf", docker_run_all_mock.mock_calls[9][1][1])
self.assertNotEqual(
- docker_run_all_mock.mock_calls[3][1][1],
- docker_run_all_mock.mock_calls[7][1][1],
+ docker_run_all_mock.mock_calls[4][1][1],
+ docker_run_all_mock.mock_calls[9][1][1],
)
self.assertEqual({"retcode": 0, "comment": "container cmd"}, ret)
--
2.33.0

View File

@ -1,29 +0,0 @@
From daf29460408a5e0eb042b3c234c7e21a6b994cf1 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Tue, 12 May 2020 14:16:23 +0200
Subject: [PATCH] Fix a test and some variable names (#229)
* loop: fix variable names for until_no_eval
* Fix test_core tests for fqdns errors
---
tests/unit/grains/test_core.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 196dbcf83d..918a9155cb 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -1416,7 +1416,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
with patch("salt.modules.network.log", mock_log):
self.assertEqual(core.fqdns(), {"fqdns": []})
mock_log.debug.assert_called_once()
- mock_log.error.assert_called()
+ mock_log.error.assert_called_once()
@patch.object(salt.utils.platform, "is_windows", MagicMock(return_value=False))
@patch(
--
2.29.2

View File

@ -1,42 +0,0 @@
From 763d63b72b9a20f22555b665033899e10f091b60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 11 Jan 2021 15:45:28 +0000
Subject: [PATCH] Fix aptpkg.normalize_name when package arch is 'all'
Add test case of DEB package where arch is 'all'
---
salt/modules/aptpkg.py | 2 +-
tests/unit/modules/test_aptpkg.py | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index e001d2f11c..03e99af733 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -208,7 +208,7 @@ def normalize_name(name):
pkgname = name
pkgarch = __grains__["osarch"]
- return pkgname if pkgarch in (__grains__["osarch"], "any") else name
+ return pkgname if pkgarch in (__grains__["osarch"], "all", "any") else name
def parse_arch(name):
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index 51dfce29eb..eb3f9e2da7 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -808,6 +808,8 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
assert result == "foo", result
result = aptpkg.normalize_name("foo:any")
assert result == "foo", result
+ result = aptpkg.normalize_name("foo:all")
+ assert result == "foo", result
result = aptpkg.normalize_name("foo:i386")
assert result == "foo:i386", result
--
2.29.2

View File

@ -1,4 +1,4 @@
From 9413059223107924c6594e6c72e50fcbcc441e60 Mon Sep 17 00:00:00 2001
From 40d9cde9b90965e60520f36dbe189fb64d15559d Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Thu, 24 Jun 2021 13:17:13 +0300
Subject: [PATCH] Fix exception in yumpkg.remove for not installed
@ -10,23 +10,23 @@ Subject: [PATCH] Fix exception in yumpkg.remove for not installed
2 files changed, 39 insertions(+)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index dd81c6f1e9..273f0fb370 100644
index 9737508377..9f8f548e5f 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -2087,6 +2087,8 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
old = list_pkgs()
targets = []
@@ -2123,6 +2123,8 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
pkg_params.update(pkg_matches)
for target in pkg_params:
+ if target not in old:
+ continue
version_to_remove = pkg_params[target]
installed_versions = old[target].split(",")
# Check if package version set to be removed is actually installed:
diff --git a/tests/pytests/unit/modules/test_yumpkg.py b/tests/pytests/unit/modules/test_yumpkg.py
index 7e3ed517ea..b5572db123 100644
index 3b35272550..c3456f7e29 100644
--- a/tests/pytests/unit/modules/test_yumpkg.py
+++ b/tests/pytests/unit/modules/test_yumpkg.py
@@ -1219,6 +1219,43 @@ def test_install_error_reporting():
@@ -1284,6 +1284,43 @@ def test_install_error_reporting():
assert exc_info.value.info == expected, exc_info.value.info
@ -71,6 +71,6 @@ index 7e3ed517ea..b5572db123 100644
with patch.object(yumpkg, "list_pkgs", MagicMock(return_value={})), patch(
"salt.utils.systemd.has_scope", MagicMock(return_value=False)
--
2.33.0
2.34.1

View File

@ -1,4 +1,4 @@
From ef433d6f02af87d45363ae07fe438a1d7747df13 Mon Sep 17 00:00:00 2001
From a268bfee70fabffc6d8fb6c297cd255fb3483ae1 Mon Sep 17 00:00:00 2001
From: "Daniel A. Wozniak" <dwozniak@saltstack.com>
Date: Thu, 7 Oct 2021 17:22:37 -0700
Subject: [PATCH] Fix issues with salt-ssh's extra-filerefs
@ -7,12 +7,9 @@ Verify salt-ssh can import from map files in states
Add changelog for 60003.fixed
---
changelog/60003.fixed | 1 +
salt/client/ssh/__init__.py | 1 +
tests/pytests/integration/ssh/test_state.py | 94 +++++++++++++++++++++
3 files changed, 96 insertions(+)
changelog/60003.fixed | 1 +
1 file changed, 1 insertion(+)
create mode 100644 changelog/60003.fixed
create mode 100644 tests/pytests/integration/ssh/test_state.py
diff --git a/changelog/60003.fixed b/changelog/60003.fixed
new file mode 100644
@ -21,119 +18,7 @@ index 0000000000..6fafbf5108
+++ b/changelog/60003.fixed
@@ -0,0 +1 @@
+Validate we can import map files in states
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 409d6e740e..76c57996d9 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -1161,6 +1161,7 @@ class Single:
opts_pkg["_ssh_version"] = self.opts["_ssh_version"]
opts_pkg["thin_dir"] = self.opts["thin_dir"]
opts_pkg["master_tops"] = self.opts["master_tops"]
+ opts_pkg["extra_filerefs"] = self.opts.get("extra_filerefs", "")
opts_pkg["__master_opts__"] = self.context["master_opts"]
if "known_hosts_file" in self.opts:
opts_pkg["known_hosts_file"] = self.opts["known_hosts_file"]
diff --git a/tests/pytests/integration/ssh/test_state.py b/tests/pytests/integration/ssh/test_state.py
new file mode 100644
index 0000000000..58330a5dd8
--- /dev/null
+++ b/tests/pytests/integration/ssh/test_state.py
@@ -0,0 +1,94 @@
+import pytest
+
+pytestmark = [
+ pytest.mark.skip_on_windows(reason="salt-ssh not available on Windows"),
+]
+
+
+@pytest.fixture(scope="module")
+def state_tree(base_env_state_tree_root_dir):
+ top_file = """
+ base:
+ 'localhost':
+ - basic
+ '127.0.0.1':
+ - basic
+ """
+ map_file = """
+ {%- set abc = "def" %}
+ """
+ state_file = """
+ {%- from "map.jinja" import abc with context %}
+
+ Ok with {{ abc }}:
+ test.succeed_without_changes
+ """
+ top_tempfile = pytest.helpers.temp_file(
+ "top.sls", top_file, base_env_state_tree_root_dir
+ )
+ map_tempfile = pytest.helpers.temp_file(
+ "map.jinja", map_file, base_env_state_tree_root_dir
+ )
+ state_tempfile = pytest.helpers.temp_file(
+ "test.sls", state_file, base_env_state_tree_root_dir
+ )
+
+ with top_tempfile, map_tempfile, state_tempfile:
+ yield
+
+
+@pytest.mark.slow_test
+def test_state_with_import(salt_ssh_cli, state_tree):
+ """
+ verify salt-ssh can use imported map files in states
+ """
+ ret = salt_ssh_cli.run("state.sls", "test")
+ assert ret.exitcode == 0
+ assert ret.json
+
+
+@pytest.fixture
+def nested_state_tree(base_env_state_tree_root_dir, tmpdir):
+ top_file = """
+ base:
+ 'localhost':
+ - basic
+ '127.0.0.1':
+ - basic
+ """
+ state_file = """
+ /{}/file.txt:
+ file.managed:
+ - source: salt://foo/file.jinja
+ - template: jinja
+ """.format(
+ tmpdir
+ )
+ file_jinja = """
+ {% from 'foo/map.jinja' import comment %}{{ comment }}
+ """
+ map_file = """
+ {% set comment = "blah blah" %}
+ """
+ statedir = base_env_state_tree_root_dir / "foo"
+ top_tempfile = pytest.helpers.temp_file(
+ "top.sls", top_file, base_env_state_tree_root_dir
+ )
+ map_tempfile = pytest.helpers.temp_file("map.jinja", map_file, statedir)
+ file_tempfile = pytest.helpers.temp_file("file.jinja", file_jinja, statedir)
+ state_tempfile = pytest.helpers.temp_file("init.sls", state_file, statedir)
+
+ with top_tempfile, map_tempfile, state_tempfile, file_tempfile:
+ yield
+
+
+@pytest.mark.slow_test
+def test_state_with_import_from_dir(salt_ssh_cli, nested_state_tree):
+ """
+ verify salt-ssh can use imported map files in states
+ """
+ ret = salt_ssh_cli.run(
+ "--extra-filerefs=salt://foo/map.jinja", "state.apply", "foo"
+ )
+ assert ret.exitcode == 0
+ assert ret.json
--
2.33.0
2.34.1

View File

@ -1,433 +0,0 @@
From 944f2a8e4db522ad32f547cf350a1268caa6de5a Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Thu, 24 Jun 2021 13:18:51 +0300
Subject: [PATCH] Fix save for iptables state module (bsc#1185131)
(#372)
---
salt/states/iptables.py | 86 ++++++++------
tests/unit/states/test_iptables.py | 184 ++++++++++++++++++++++++++++-
2 files changed, 227 insertions(+), 43 deletions(-)
diff --git a/salt/states/iptables.py b/salt/states/iptables.py
index 61dfc7e665..2e81477f18 100644
--- a/salt/states/iptables.py
+++ b/salt/states/iptables.py
@@ -401,7 +401,7 @@ def append(name, table="filter", family="ipv4", **kwargs):
if save:
if save_file is True:
save_file = None
- __salt__["iptables.save"](save_file, family=family)
+ __salt__["iptables.save"](filename=save_file, family=family)
if not ret["changes"]["locale"]:
del ret["changes"]["locale"]
ret["comment"] = "\n".join(comments)
@@ -426,7 +426,9 @@ def append(name, table="filter", family="ipv4", **kwargs):
filename = kwargs["save"]
else:
filename = None
- saved_rules = __salt__["iptables.get_saved_rules"](family=family)
+ saved_rules = __salt__["iptables.get_saved_rules"](
+ conf_file=filename, family=family
+ )
_rules = __salt__["iptables.get_rules"](family=family)
__rules = []
for table in _rules:
@@ -438,7 +440,7 @@ def append(name, table="filter", family="ipv4", **kwargs):
__saved_rules.append(saved_rules[table][chain].get("rules"))
# Only save if rules in memory are different than saved rules
if __rules != __saved_rules:
- out = __salt__["iptables.save"](filename, family=family)
+ out = __salt__["iptables.save"](filename=filename, family=family)
ret["comment"] += ("\nSaved iptables rule {} for {}\n" "{}\n{}").format(
name, family, command.strip(), out
)
@@ -454,16 +456,15 @@ def append(name, table="filter", family="ipv4", **kwargs):
ret["comment"] = "Set iptables rule for {} to: {} for {}".format(
name, command.strip(), family
)
- if "save" in kwargs:
- if kwargs["save"]:
- if kwargs["save"] is not True:
- filename = kwargs["save"]
- else:
- filename = None
- out = __salt__["iptables.save"](filename, family=family)
- ret["comment"] = (
- "Set and saved iptables rule {} for {}\n" "{}\n{}"
- ).format(name, family, command.strip(), out)
+ if "save" in kwargs and kwargs["save"]:
+ if kwargs["save"] is not True:
+ filename = kwargs["save"]
+ else:
+ filename = None
+ out = __salt__["iptables.save"](filename=filename, family=family)
+ ret["comment"] = (
+ "Set and saved iptables rule {} for {}\n" "{}\n{}"
+ ).format(name, family, command.strip(), out)
return ret
else:
ret["result"] = False
@@ -527,7 +528,7 @@ def insert(name, table="filter", family="ipv4", **kwargs):
if save:
if save_file is True:
save_file = None
- __salt__["iptables.save"](save_file, family=family)
+ __salt__["iptables.save"](filename=save_file, family=family)
if not ret["changes"]["locale"]:
del ret["changes"]["locale"]
ret["comment"] = "\n".join(comments)
@@ -552,7 +553,9 @@ def insert(name, table="filter", family="ipv4", **kwargs):
filename = kwargs["save"]
else:
filename = None
- saved_rules = __salt__["iptables.get_saved_rules"](family=family)
+ saved_rules = __salt__["iptables.get_saved_rules"](
+ conf_file=filename, family=family
+ )
_rules = __salt__["iptables.get_rules"](family=family)
__rules = []
for table in _rules:
@@ -564,7 +567,7 @@ def insert(name, table="filter", family="ipv4", **kwargs):
__saved_rules.append(saved_rules[table][chain].get("rules"))
# Only save if rules in memory are different than saved rules
if __rules != __saved_rules:
- out = __salt__["iptables.save"](filename, family=family)
+ out = __salt__["iptables.save"](filename=filename, family=family)
ret["comment"] += ("\nSaved iptables rule {} for {}\n" "{}\n{}").format(
name, family, command.strip(), out
)
@@ -582,12 +585,15 @@ def insert(name, table="filter", family="ipv4", **kwargs):
ret["comment"] = "Set iptables rule for {} to: {} for {}".format(
name, command.strip(), family
)
- if "save" in kwargs:
- if kwargs["save"]:
- out = __salt__["iptables.save"](filename=None, family=family)
- ret["comment"] = (
- "Set and saved iptables rule {} for {}\n" "{}\n{}"
- ).format(name, family, command.strip(), out)
+ if "save" in kwargs and kwargs["save"]:
+ if kwargs["save"] is not True:
+ filename = kwargs["save"]
+ else:
+ filename = None
+ out = __salt__["iptables.save"](filename=filename, family=family)
+ ret["comment"] = (
+ "Set and saved iptables rule {} for {}\n" "{}\n{}"
+ ).format(name, family, command.strip(), out)
return ret
else:
ret["result"] = False
@@ -646,7 +652,7 @@ def delete(name, table="filter", family="ipv4", **kwargs):
if save:
if save_file is True:
save_file = None
- __salt__["iptables.save"](save_file, family=family)
+ __salt__["iptables.save"](filename=save_file, family=family)
if not ret["changes"]["locale"]:
del ret["changes"]["locale"]
ret["comment"] = "\n".join(comments)
@@ -688,12 +694,15 @@ def delete(name, table="filter", family="ipv4", **kwargs):
ret["changes"] = {"locale": name}
ret["result"] = True
ret["comment"] = "Delete iptables rule for {} {}".format(name, command.strip())
- if "save" in kwargs:
- if kwargs["save"]:
- out = __salt__["iptables.save"](filename=None, family=family)
- ret["comment"] = (
- "Deleted and saved iptables rule {} for {}\n" "{}\n{}"
- ).format(name, family, command.strip(), out)
+ if "save" in kwargs and kwargs["save"]:
+ if kwargs["save"] is not True:
+ filename = kwargs["save"]
+ else:
+ filename = None
+ out = __salt__["iptables.save"](filename=filename, family=family)
+ ret["comment"] = (
+ "Deleted and saved iptables rule {} for {}\n" "{}\n{}"
+ ).format(name, family, command.strip(), out)
return ret
else:
ret["result"] = False
@@ -751,14 +760,17 @@ def set_policy(name, table="filter", family="ipv4", **kwargs):
ret["comment"] = "Set default policy for {} to {} family {}".format(
kwargs["chain"], kwargs["policy"], family
)
- if "save" in kwargs:
- if kwargs["save"]:
- __salt__["iptables.save"](filename=None, family=family)
- ret[
- "comment"
- ] = "Set and saved default policy for {} to {} family {}".format(
- kwargs["chain"], kwargs["policy"], family
- )
+ if "save" in kwargs and kwargs["save"]:
+ if kwargs["save"] is not True:
+ filename = kwargs["save"]
+ else:
+ filename = None
+ __salt__["iptables.save"](filename=filename, family=family)
+ ret[
+ "comment"
+ ] = "Set and saved default policy for {} to {} family {}".format(
+ kwargs["chain"], kwargs["policy"], family
+ )
return ret
else:
ret["result"] = False
diff --git a/tests/unit/states/test_iptables.py b/tests/unit/states/test_iptables.py
index c49022c962..975ae49c3e 100644
--- a/tests/unit/states/test_iptables.py
+++ b/tests/unit/states/test_iptables.py
@@ -135,7 +135,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
with patch.object(iptables, "_STATE_INTERNAL_KEYWORDS", mock):
mock = MagicMock(return_value="a")
with patch.dict(iptables.__salt__, {"iptables.build_rule": mock}):
- mock = MagicMock(side_effect=[True, False, False, False])
+ mock = MagicMock(side_effect=[True, False, False, False, False, True])
with patch.dict(iptables.__salt__, {"iptables.check": mock}):
ret.update(
{
@@ -161,7 +161,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
)
with patch.dict(iptables.__opts__, {"test": False}):
- mock = MagicMock(side_effect=[True, False])
+ mock = MagicMock(side_effect=[True, False, True, True])
with patch.dict(iptables.__salt__, {"iptables.append": mock}):
ret.update(
{
@@ -188,6 +188,65 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
iptables.append("salt", table="", chain=""), ret
)
+ mock_save = MagicMock(
+ side_effect=['Wrote 1 lines to "/tmp/iptables"', ""]
+ )
+ with patch.dict(
+ iptables.__salt__, {"iptables.save": mock_save}
+ ):
+ mock_get_saved_rules = MagicMock(side_effect=[""])
+ with patch.dict(
+ iptables.__salt__,
+ {"iptables.get_saved_rules": mock_get_saved_rules},
+ ):
+ mock = MagicMock(side_effect=[""])
+ with patch.dict(
+ iptables.__salt__, {"iptables.get_rules": mock}
+ ):
+ ret.update(
+ {
+ "changes": {"locale": "salt"},
+ "result": True,
+ "comment": "Set and saved iptables rule"
+ ' salt for ipv4\na\nWrote 1 lines to "/tmp/iptables"',
+ }
+ )
+ self.assertDictEqual(
+ iptables.append(
+ "salt",
+ table="",
+ chain="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ ret.update(
+ {
+ "changes": {},
+ "result": True,
+ "comment": "iptables rule for salt already set (a) for ipv4",
+ }
+ )
+ self.assertDictEqual(
+ iptables.append(
+ "salt",
+ table="",
+ chain="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ self.assertEqual(
+ mock_get_saved_rules.mock_calls[0][2][
+ "conf_file"
+ ],
+ "/tmp/iptables",
+ )
+ self.assertEqual(
+ mock_save.mock_calls[0][2]["filename"],
+ "/tmp/iptables",
+ )
+
def test_insert(self):
"""
Test to insert a rule into a chain
@@ -200,7 +259,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
with patch.object(iptables, "_STATE_INTERNAL_KEYWORDS", mock):
mock = MagicMock(return_value="a")
with patch.dict(iptables.__salt__, {"iptables.build_rule": mock}):
- mock = MagicMock(side_effect=[True, False, False, False])
+ mock = MagicMock(side_effect=[True, False, False, False, False, True])
with patch.dict(iptables.__salt__, {"iptables.check": mock}):
ret.update(
{
@@ -226,7 +285,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
)
with patch.dict(iptables.__opts__, {"test": False}):
- mock = MagicMock(side_effect=[False, True])
+ mock = MagicMock(side_effect=[False, True, False, True])
with patch.dict(iptables.__salt__, {"iptables.insert": mock}):
ret.update(
{
@@ -258,6 +317,67 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
ret,
)
+ mock_save = MagicMock(
+ side_effect=['Wrote 1 lines to "/tmp/iptables"', ""]
+ )
+ with patch.dict(
+ iptables.__salt__, {"iptables.save": mock_save}
+ ):
+ mock_get_saved_rules = MagicMock(side_effect=[""])
+ with patch.dict(
+ iptables.__salt__,
+ {"iptables.get_saved_rules": mock_get_saved_rules},
+ ):
+ mock = MagicMock(side_effect=[""])
+ with patch.dict(
+ iptables.__salt__, {"iptables.get_rules": mock}
+ ):
+ ret.update(
+ {
+ "changes": {"locale": "salt"},
+ "result": True,
+ "comment": "Set and saved iptables rule"
+ ' salt for ipv4\na\nWrote 1 lines to "/tmp/iptables"',
+ }
+ )
+ self.assertDictEqual(
+ iptables.insert(
+ "salt",
+ table="",
+ chain="",
+ position="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ ret.update(
+ {
+ "changes": {},
+ "result": True,
+ "comment": "iptables rule for salt already set for ipv4 (a)",
+ }
+ )
+ self.assertDictEqual(
+ iptables.insert(
+ "salt",
+ table="",
+ chain="",
+ position="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ self.assertEqual(
+ mock_get_saved_rules.mock_calls[0][2][
+ "conf_file"
+ ],
+ "/tmp/iptables",
+ )
+ self.assertEqual(
+ mock_save.mock_calls[0][2]["filename"],
+ "/tmp/iptables",
+ )
+
def test_delete(self):
"""
Test to delete a rule to a chain
@@ -270,7 +390,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
with patch.object(iptables, "_STATE_INTERNAL_KEYWORDS", mock):
mock = MagicMock(return_value="a")
with patch.dict(iptables.__salt__, {"iptables.build_rule": mock}):
- mock = MagicMock(side_effect=[False, True, True, True])
+ mock = MagicMock(side_effect=[False, True, True, True, True, False])
with patch.dict(iptables.__salt__, {"iptables.check": mock}):
ret.update(
{
@@ -296,7 +416,7 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
)
with patch.dict(iptables.__opts__, {"test": False}):
- mock = MagicMock(side_effect=[False, True])
+ mock = MagicMock(side_effect=[False, True, False, False])
with patch.dict(iptables.__salt__, {"iptables.delete": mock}):
ret.update(
{
@@ -327,6 +447,58 @@ class IptablesTestCase(TestCase, LoaderModuleMockMixin):
ret,
)
+ mock_save = MagicMock(
+ side_effect=['Wrote 1 lines to "/tmp/iptables"', ""]
+ )
+ with patch.dict(
+ iptables.__salt__, {"iptables.save": mock_save}
+ ):
+ mock = MagicMock(side_effect=[True, False])
+ with patch.dict(
+ iptables.__salt__, {"iptables.check": mock}
+ ):
+ mock = MagicMock(side_effect=[""])
+ with patch.dict(
+ iptables.__salt__, {"iptables.get_rules": mock}
+ ):
+ ret.update(
+ {
+ "changes": {"locale": "salt"},
+ "result": True,
+ "comment": "Deleted and saved iptables rule"
+ ' salt for ipv4\na\nWrote 1 lines to "/tmp/iptables"',
+ }
+ )
+ self.assertDictEqual(
+ iptables.delete(
+ "salt",
+ table="",
+ chain="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ ret.update(
+ {
+ "changes": {},
+ "result": True,
+ "comment": "iptables rule for salt already absent for ipv4 (a)",
+ }
+ )
+ self.assertDictEqual(
+ iptables.delete(
+ "salt",
+ table="",
+ chain="",
+ save="/tmp/iptables",
+ ),
+ ret,
+ )
+ self.assertEqual(
+ mock_save.mock_calls[0][2]["filename"],
+ "/tmp/iptables",
+ )
+
def test_set_policy(self):
"""
Test to sets the default policy for iptables firewall tables
--
2.32.0

View File

@ -1,27 +1,17 @@
From fba844fbaeb6203350944241a4ad0d7127a79bd5 Mon Sep 17 00:00:00 2001
From 929942b15f377df21ae076ef9e25cf83639b1850 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Mon, 8 Nov 2021 17:43:02 +0300
Subject: [PATCH] Fix traceback.print_exc calls for test_pip_state (#432)
---
tests/unit/states/test_pip_state.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
tests/unit/states/test_pip_state.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/unit/states/test_pip_state.py b/tests/unit/states/test_pip_state.py
index 914f62ff23..9e827dbf8a 100644
index 9f5be295be..1074a1989f 100644
--- a/tests/unit/states/test_pip_state.py
+++ b/tests/unit/states/test_pip_state.py
@@ -439,15 +439,15 @@ class PipStateInstallationErrorTest(TestCase):
import salt.states.pip_state
salt.states.pip_state.InstallationError
except ImportError as exc:
- traceback.print_exc(exc, file=sys.stdout)
+ traceback.print_exc(file=sys.stdout)
sys.stdout.flush()
sys.exit(1)
except AttributeError as exc:
- traceback.print_exc(exc, file=sys.stdout)
+ traceback.print_exc(file=sys.stdout)
@@ -445,7 +445,7 @@ class PipStateInstallationErrorTest(TestCase):
sys.stdout.flush()
sys.exit(2)
except Exception as exc:
@ -31,6 +21,6 @@ index 914f62ff23..9e827dbf8a 100644
sys.exit(3)
sys.exit(0)
--
2.33.1
2.34.1

View File

@ -1,22 +1,22 @@
From f6e5a6bd16fa49cceadde9a9f46fefd12d92316b Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Mon, 5 Jul 2021 18:39:26 +0300
From 8e5295ef9047a9afdd2323508c633ab0356ef603 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 15:34:24 +0100
Subject: [PATCH] Implementation of held/unheld functions for state pkg
(#387)
* Implementation of held/unheld functions for state pkg
---
salt/modules/zypperpkg.py | 117 ++++++-
salt/modules/zypperpkg.py | 119 ++++++-
salt/states/pkg.py | 310 +++++++++++++++++++
tests/pytests/unit/modules/test_zypperpkg.py | 133 ++++++++
tests/pytests/unit/states/test_pkg.py | 137 ++++++++
4 files changed, 684 insertions(+), 13 deletions(-)
4 files changed, 686 insertions(+), 13 deletions(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 863be3c894..9c7ffcf5da 100644
index 4fc045c313..ac6c36a09f 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -2092,6 +2092,76 @@ def purge(
@@ -2103,6 +2103,76 @@ def purge(
return _uninstall(inclusion_detection, name=name, pkgs=pkgs, root=root)
@ -93,7 +93,7 @@ index 863be3c894..9c7ffcf5da 100644
def list_locks(root=None):
"""
List current package locks.
@@ -2162,7 +2232,7 @@ def clean_locks(root=None):
@@ -2173,7 +2243,7 @@ def clean_locks(root=None):
return out
@ -102,16 +102,17 @@ index 863be3c894..9c7ffcf5da 100644
"""
.. versionadded:: 3003
@@ -2176,6 +2246,8 @@ def unhold(name=None, pkgs=None, **kwargs):
@@ -2187,6 +2257,9 @@ def unhold(name=None, pkgs=None, **kwargs):
A list of packages to unhold. The ``name`` parameter will be ignored if
this option is passed.
+ root
+ Operate on a different root directory.
+
CLI Example:
@@ -2191,24 +2263,38 @@ def unhold(name=None, pkgs=None, **kwargs):
.. code-block:: bash
@@ -2201,24 +2274,38 @@ def unhold(name=None, pkgs=None, **kwargs):
targets = []
if pkgs:
@ -158,7 +159,7 @@ index 863be3c894..9c7ffcf5da 100644
ret[target]["comment"] = "Package {} was already unheld.".format(target)
if removed:
@@ -2261,7 +2347,7 @@ def remove_lock(name, root=None, **kwargs):
@@ -2271,7 +2358,7 @@ def remove_lock(name, root=None, **kwargs):
return {"removed": len(removed), "not_found": missing}
@ -167,17 +168,18 @@ index 863be3c894..9c7ffcf5da 100644
"""
.. versionadded:: 3003
@@ -2275,6 +2361,9 @@ def hold(name=None, pkgs=None, **kwargs):
@@ -2285,6 +2372,10 @@ def hold(name=None, pkgs=None, **kwargs):
A list of packages to hold. The ``name`` parameter will be ignored if
this option is passed.
+ root
+ Operate on a different root directory.
+
+
CLI Example:
@@ -2290,8 +2379,7 @@ def hold(name=None, pkgs=None, **kwargs):
.. code-block:: bash
@@ -2299,8 +2390,7 @@ def hold(name=None, pkgs=None, **kwargs):
targets = []
if pkgs:
@ -187,7 +189,7 @@ index 863be3c894..9c7ffcf5da 100644
else:
targets.append(name)
@@ -2299,9 +2387,12 @@ def hold(name=None, pkgs=None, **kwargs):
@@ -2308,9 +2398,12 @@ def hold(name=None, pkgs=None, **kwargs):
added = []
for target in targets:
@ -202,10 +204,10 @@ index 863be3c894..9c7ffcf5da 100644
ret[target]["changes"]["old"] = ""
ret[target]["comment"] = "Package {} is now being held.".format(target)
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index fd6808a2dc..a8ffe25a77 100644
index f71f61e720..0d601e1aaf 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -3607,3 +3607,313 @@ def mod_beacon(name, **kwargs):
@@ -3644,3 +3644,313 @@ def mod_beacon(name, **kwargs):
),
"result": False,
}
@ -520,10 +522,10 @@ index fd6808a2dc..a8ffe25a77 100644
+
+ return ret
diff --git a/tests/pytests/unit/modules/test_zypperpkg.py b/tests/pytests/unit/modules/test_zypperpkg.py
index 37bbef87b7..dbe09976b2 100644
index eb1e63f6d7..bfc1558c9a 100644
--- a/tests/pytests/unit/modules/test_zypperpkg.py
+++ b/tests/pytests/unit/modules/test_zypperpkg.py
@@ -119,3 +119,136 @@ def test_del_repo_key():
@@ -121,3 +121,136 @@ def test_del_repo_key():
with patch.dict(zypper.__salt__, salt_mock):
assert zypper.del_repo_key(keyid="keyid", root="/mnt")
salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
@ -661,13 +663,13 @@ index 37bbef87b7..dbe09976b2 100644
+ assert len(ret) == 1
+ assert "bar-2:2.3.4-2.1.*" in ret
diff --git a/tests/pytests/unit/states/test_pkg.py b/tests/pytests/unit/states/test_pkg.py
index 8e5ae42ed8..a2e63d5157 100644
index 7e667d36fd..17b91bcb39 100644
--- a/tests/pytests/unit/states/test_pkg.py
+++ b/tests/pytests/unit/states/test_pkg.py
@@ -352,3 +352,140 @@ def test_mod_beacon():
}
assert ret == expected
@@ -578,3 +578,140 @@ def test_removed_purged_with_changes_test_true(list_pkgs, action):
ret = pkg_actions[action]("pkga", test=True)
assert ret["result"] is None
assert ret["changes"] == expected
+
+
+@pytest.mark.parametrize(
@ -806,6 +808,6 @@ index 8e5ae42ed8..a2e63d5157 100644
+ unhold_mock.assert_any_call(name="held-test", pkgs=["baz"])
+ unhold_mock.assert_any_call(name="held-test", pkgs=["bar"])
--
2.33.0
2.34.1

View File

@ -1,7 +1,6 @@
From 90cc5349ed085729db43966bf290c76db5c7f6b9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Tue, 20 Apr 2021 11:01:26 +0100
From b58056da2f5a12e3d614650904039c0655ce1221 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 19:41:03 +0100
Subject: [PATCH] Improvements on "ansiblegate" module (#354)
* Allow collecting Ansible Inventory from a minion
@ -36,26 +35,34 @@ Subject: [PATCH] Improvements on "ansiblegate" module (#354)
Fix issue parsing errors in ansiblegate state module
---
salt/modules/ansiblegate.py | 166 +++++++++++++++++-
salt/roster/ansible.py | 18 +-
salt/modules/ansiblegate.py | 167 +++++++++++++++++-
salt/roster/ansible.py | 17 +-
salt/states/ansiblegate.py | 12 +-
salt/utils/ansible.py | 44 +++++
.../pytests/unit/modules/test_ansiblegate.py | 94 +++++++++-
salt/utils/ansible.py | 41 +++++
.../pytests/unit/modules/test_ansiblegate.py | 99 ++++++++++-
.../example_playbooks/example-playbook2/hosts | 7 +
.../example-playbook2/site.yml | 28 +++
.../playbooks/example_playbooks/playbook1.yml | 5 +
tests/unit/roster/test_ansible.py | 2 +-
9 files changed, 364 insertions(+), 12 deletions(-)
9 files changed, 367 insertions(+), 11 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 0279a26017..2b4d4b0bdf 100644
index 328d9b7b0a..f33be6a00e 100644
--- a/salt/modules/ansiblegate.py
+++ b/salt/modules/ansiblegate.py
@@ -425,7 +425,171 @@ def playbooks(
@@ -17,6 +17,7 @@ any Ansible module to respond.
import fnmatch
import json
import logging
+import os
import subprocess
import sys
from tempfile import NamedTemporaryFile
@@ -365,7 +366,171 @@ def playbooks(
}
ret = __salt__["cmd.run_all"](**cmd_kwargs)
log.debug("Ansible Playbook Return: %s", ret)
@ -229,23 +236,15 @@ index 0279a26017..2b4d4b0bdf 100644
+ 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
index 7beaaf2075..d3b352de27 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):
@@ -117,27 +117,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__))
- "cmd.run", "ansible-inventory -i {} --list".format(get_roster_file(__opts__))
- )
- __context__["inventory"] = __utils__["json.loads"](
- __utils__["stringutils.to_str"](inventory)
@ -280,10 +279,10 @@ index f17316bdd7..cc61f6fb7d 100644
return hosts
diff --git a/salt/states/ansiblegate.py b/salt/states/ansiblegate.py
index 5daba0f37f..bd00653928 100644
index 4afe6a020d..af5cb0f0e5 100644
--- a/salt/states/ansiblegate.py
+++ b/salt/states/ansiblegate.py
@@ -183,7 +183,11 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
@@ -184,7 +184,11 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
checks = __salt__["ansible.playbooks"](
name, rundir=rundir, check=True, diff=True, **ansible_kwargs
)
@ -296,7 +295,7 @@ index 5daba0f37f..bd00653928 100644
not check["changed"]
and not check["failures"]
and not check["unreachable"]
@@ -212,7 +216,11 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
@@ -213,7 +217,11 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs=
results = __salt__["ansible.playbooks"](
name, rundir=rundir, diff=True, **ansible_kwargs
)
@ -311,13 +310,10 @@ index 5daba0f37f..bd00653928 100644
and not check["unreachable"]
diff --git a/salt/utils/ansible.py b/salt/utils/ansible.py
new file mode 100644
index 0000000000..ee85cb656c
index 0000000000..1e14037fd3
--- /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
@@ -0,0 +1,41 @@
+import logging
+import os
+
@ -360,33 +356,37 @@ index 0000000000..ee85cb656c
+ 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
index 44c9b12acb..f357133000 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
@@ -1,9 +1,15 @@
# Author: Bo Maryniuk <bo@suse.de>
+import os
import pytest
+
+import salt.config
+import salt.loader
from salt.exceptions import LoaderError
from tests.support.mock import MagicMock, MockTimedProc, patch
import salt.modules.ansiblegate as ansiblegate
import salt.utils.json
+import salt.utils.path
from tests.support.mock import ANY, MagicMock, 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(
pytestmark = [
pytest.mark.skip_on_windows(reason="Not supported on Windows"),
@@ -12,7 +18,7 @@ pytestmark = [
@pytest.fixture
def configure_loader_modules():
- return {ansible: {}}
+ return {ansible: {"__utils__": {}}}
- return {ansiblegate: {}}
+ return {ansiblegate: {"__utils__": {}}}
@pytest.fixture
@@ -201,3 +204,92 @@ def test_ansible_playbooks_return_retcode(resolver):
def test_ansible_module_help():
@@ -133,3 +139,94 @@ def test_ansible_playbooks_return_retcode():
):
ret = ansible.playbooks("fake-playbook.yml")
ret = ansiblegate.playbooks("fake-playbook.yml")
assert "retcode" in ret
+
+
@ -425,14 +425,16 @@ index 42c0968a6e..24c7e5e6b3 100644
+ 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()
+ ansiblegate.__utils__, utils
+ ), patch("os.path.isfile", MagicMock(return_value=True)):
+ ret = ansiblegate.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 (
+ "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
+
@ -441,7 +443,7 @@ index 42c0968a6e..24c7e5e6b3 100644
+ playbooks_dir = os.path.join(
+ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/"
+ )
+ ret = ansible.discover_playbooks(playbooks_dir)
+ ret = ansiblegate.discover_playbooks(playbooks_dir)
+ assert playbooks_dir in ret
+ assert ret[playbooks_dir]["playbook1.yml"] == {
+ "fullpath": os.path.join(playbooks_dir, "playbook1.yml")
@ -456,7 +458,7 @@ index 42c0968a6e..24c7e5e6b3 100644
+ playbooks_dir = os.path.join(
+ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/"
+ )
+ ret = ansible.discover_playbooks(
+ ret = ansiblegate.discover_playbooks(
+ playbooks_dir, playbook_extension="foobar", hosts_filename="deadbeaf"
+ )
+ assert playbooks_dir in ret
@ -467,7 +469,7 @@ index 42c0968a6e..24c7e5e6b3 100644
+ playbooks_dir = os.path.join(
+ RUNTIME_VARS.TESTS_DIR, "unit/files/playbooks/example_playbooks/"
+ )
+ ret = ansible.discover_playbooks(locations=[playbooks_dir, "/tmp/foobar"])
+ ret = ansiblegate.discover_playbooks(locations=[playbooks_dir, "/tmp/foobar"])
+ assert playbooks_dir in ret
+ assert "/tmp/foobar" in ret
+ assert ret[playbooks_dir]["playbook1.yml"] == {
@ -536,10 +538,10 @@ index 0000000000..e258a101e1
+ tasks:
+ - ping:
diff --git a/tests/unit/roster/test_ansible.py b/tests/unit/roster/test_ansible.py
index a5cdcbbdbc..8bc9c1c6f7 100644
index 7f1144454b..c4ab8b7639 100644
--- a/tests/unit/roster/test_ansible.py
+++ b/tests/unit/roster/test_ansible.py
@@ -71,7 +71,7 @@ class AnsibleRosterTestCase(TestCase, mixins.LoaderModuleMockMixin):
@@ -63,7 +63,7 @@ class AnsibleRosterTestCase(TestCase, mixins.LoaderModuleMockMixin):
opts = salt.config.master_config(
os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master")
)
@ -549,6 +551,6 @@ index a5cdcbbdbc..8bc9c1c6f7 100644
return {ansible: {"__utils__": utils, "__opts__": {}, "__runner__": runner}}
--
2.33.0
2.34.1

View File

@ -1,6 +1,6 @@
From 0c0f470f0bc082316cf854c8c4f6f6500f80f3f0 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 29 Jan 2019 11:11:38 +0100
From 834defc8e38c4495ed51bb549d86727dd8b812b3 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 17:10:37 +0100
Subject: [PATCH] Include aliases in the fqdns grains
Add UT for "is_fqdn"
@ -24,17 +24,16 @@ Implement network.fqdns module function (bsc#1134860) (#172)
Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de>
---
salt/modules/network.py | 5 ++-
salt/utils/network.py | 16 +++++++++
tests/unit/grains/test_core.py | 60 +++++++++++++++++++++-----------
tests/unit/utils/test_network.py | 37 ++++++++++++++++++++
4 files changed, 97 insertions(+), 21 deletions(-)
salt/modules/network.py | 5 ++++-
salt/utils/network.py | 16 ++++++++++++++
tests/unit/utils/test_network.py | 37 ++++++++++++++++++++++++++++++++
3 files changed, 57 insertions(+), 1 deletion(-)
diff --git a/salt/modules/network.py b/salt/modules/network.py
index 9280a0f854..d8ff251271 100644
index 08c20b99f9..53ebfe4bc7 100644
--- a/salt/modules/network.py
+++ b/salt/modules/network.py
@@ -2073,7 +2073,10 @@ def fqdns():
@@ -2089,7 +2089,10 @@ def fqdns():
def _lookup_fqdn(ip):
try:
@ -47,10 +46,10 @@ index 9280a0f854..d8ff251271 100644
if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
# No FQDN for this IP address, so we don't need to know this all the time.
diff --git a/salt/utils/network.py b/salt/utils/network.py
index 144f9dc850..5fc9a34ca4 100644
index 22075066fd..8867041e0e 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -2286,3 +2286,19 @@ def filter_by_networks(values, networks):
@@ -2302,3 +2302,19 @@ def filter_by_networks(values, networks):
raise ValueError("Do not know how to filter a {}".format(type(values)))
else:
return values
@ -70,111 +69,6 @@ index 144f9dc850..5fc9a34ca4 100644
+ and len(hostname) < 0xFF
+ and all(compliant.match(x) for x in hostname.rstrip(".").split("."))
+ )
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 914be531ed..7173f04979 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -18,6 +18,7 @@ import salt.utils.network
import salt.utils.path
import salt.utils.platform
from salt._compat import ipaddress
+from salt.ext import six
from tests.support.mixins import LoaderModuleMockMixin
from tests.support.mock import MagicMock, Mock, mock_open, patch
from tests.support.unit import TestCase, skipIf
@@ -1428,7 +1429,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": False}):
assert core.fqdns() == {"fqdns": []}
- def test_enable_fqdns_true(self):
+ def test_enablefqdnsTrue(self):
"""
testing that grains uses network.fqdns module
"""
@@ -1439,14 +1440,14 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": True}):
assert core.fqdns() == "my.fake.domain"
- def test_enable_fqdns_none(self):
+ def test_enablefqdnsNone(self):
"""
testing default fqdns grains is returned when enable_fqdns_grains is None
"""
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": None}):
assert core.fqdns() == {"fqdns": []}
- def test_enable_fqdns_without_patching(self):
+ def test_enablefqdnswithoutpaching(self):
"""
testing fqdns grains is enabled by default
"""
@@ -1454,23 +1455,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
"salt.grains.core.__salt__",
{"network.fqdns": MagicMock(return_value="my.fake.domain")},
):
- # fqdns is disabled by default on Windows
- if salt.utils.platform.is_windows():
- assert core.fqdns() == {"fqdns": []}
- else:
- assert core.fqdns() == "my.fake.domain"
-
- def test_enable_fqdns_false_is_proxy(self):
- """
- testing fqdns grains is disabled by default for proxy minions
- """
- with patch("salt.utils.platform.is_proxy", return_value=True, autospec=True):
- with patch.dict(
- "salt.grains.core.__salt__",
- {"network.fqdns": MagicMock(return_value="my.fake.domain")},
- ):
- # fqdns is disabled by default on proxy minions
- assert core.fqdns() == {"fqdns": []}
+ assert core.fqdns() == "my.fake.domain"
def test_enable_fqdns_false_is_aix(self):
"""
@@ -1577,6 +1562,41 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
mock_log.debug.assert_called_once()
mock_log.error.assert_called()
+ @patch.object(salt.utils.platform, "is_windows", MagicMock(return_value=False))
+ @patch(
+ "salt.utils.network.ip_addrs", MagicMock(return_value=["1.2.3.4", "5.6.7.8"])
+ )
+ @patch(
+ "salt.utils.network.ip_addrs6",
+ MagicMock(return_value=["fe80::a8b2:93ff:fe00:0", "fe80::a8b2:93ff:dead:beef"]),
+ )
+ @patch(
+ "salt.utils.network.socket.getfqdn", MagicMock(side_effect=lambda v: v)
+ ) # Just pass-through
+ def test_fqdns_aliases(self):
+ """
+ FQDNs aliases
+ """
+ reverse_resolv_mock = [
+ ("foo.bar.baz", ["throwmeaway", "this.is.valid.alias"], ["1.2.3.4"]),
+ ("rinzler.evil-corp.com", ["false-hostname", "badaliass"], ["5.6.7.8"]),
+ ("foo.bar.baz", [], ["fe80::a8b2:93ff:fe00:0"]),
+ (
+ "bluesniff.foo.bar",
+ ["alias.bluesniff.foo.bar"],
+ ["fe80::a8b2:93ff:dead:beef"],
+ ),
+ ]
+ with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
+ with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
+ fqdns = core.fqdns()
+ assert "fqdns" in fqdns
+ for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
+ assert alias in fqdns["fqdns"]
+
+ for alias in ["throwmeaway", "false-hostname", "badaliass"]:
+ assert alias not in fqdns["fqdns"]
+
def test_core_virtual(self):
"""
test virtual grain with cmd virt-what
diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py
index 6863ccd0c9..637d5e9811 100644
--- a/tests/unit/utils/test_network.py
@ -221,6 +115,6 @@ index 6863ccd0c9..637d5e9811 100644
+ ]:
+ assert not network.is_fqdn(fqdn)
--
2.33.0
2.34.1

View File

@ -1,21 +1,21 @@
From 0ef6eed4f5e120a584843c33272066ba477feb3f Mon Sep 17 00:00:00 2001
From: Jochen Breuer <brejoc@gmail.com>
Date: Tue, 19 May 2020 10:34:35 +0200
From 3f8e937d938f19dd40fde527497f7775bbffe353 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 25 Jan 2022 17:12:47 +0100
Subject: [PATCH] info_installed works without status attr now
If 'status' was excluded via attr, info_installed was no longer able to
detect if a package was installed or not. Now info_installed adds the
'status' for the 'lowpkg.info' request again.
---
salt/modules/aptpkg.py | 9 +++++++++
tests/unit/modules/test_aptpkg.py | 20 ++++++++++++++++++++
2 files changed, 29 insertions(+)
salt/modules/aptpkg.py | 9 +++++++++
tests/pytests/unit/modules/test_aptpkg.py | 18 ++++++++++++++++++
2 files changed, 27 insertions(+)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index db0480b45d..e4a9872aad 100644
index 3c3fbf4970..0d378355ab 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -2923,6 +2923,15 @@ def info_installed(*names, **kwargs):
@@ -3056,6 +3056,15 @@ def info_installed(*names, **kwargs):
failhard = kwargs.pop("failhard", True)
kwargs.pop("errors", None) # Only for compatibility with RPM
attr = kwargs.pop("attr", None) # Package attributes to return
@ -31,38 +31,36 @@ index db0480b45d..e4a9872aad 100644
all_versions = kwargs.pop(
"all_versions", False
) # This is for backward compatible structure only
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index 3c9744e224..51dfce29eb 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -297,6 +297,26 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(aptpkg.info_installed("wget"), installed)
self.assertEqual(len(aptpkg.info_installed()), 1)
diff --git a/tests/pytests/unit/modules/test_aptpkg.py b/tests/pytests/unit/modules/test_aptpkg.py
index 51b7ffbe4d..8c64c8c9c1 100644
--- a/tests/pytests/unit/modules/test_aptpkg.py
+++ b/tests/pytests/unit/modules/test_aptpkg.py
@@ -361,6 +361,24 @@ def test_info_installed_attr(lowpkg_info_var):
assert ret["wget"] == expected_pkg
+ def test_info_installed_attr_without_status(self):
+ """
+ Test info_installed 'attr' for inclusion of 'status' attribute.
+def test_info_installed_attr_without_status(lowpkg_info_var):
+ """
+ Test info_installed 'attr' for inclusion of 'status' attribute.
+
+ Since info_installed should only return installed packages, we need to
+ call __salt__['lowpkg.info'] with the 'status' attribute even if the user
+ is not asking for it in 'attr'. Otherwise info_installed would not be able
+ to check if the package is installed and would return everything.
+ Since info_installed should only return installed packages, we need to
+ call __salt__['lowpkg.info'] with the 'status' attribute even if the user
+ is not asking for it in 'attr'. Otherwise info_installed would not be able
+ to check if the package is installed and would return everything.
+
+ :return:
+ """
+ with patch(
+ "salt.modules.aptpkg.__salt__",
+ {"lowpkg.info": MagicMock(return_value=LOWPKG_INFO)},
+ ) as wget_lowpkg:
+ ret = aptpkg.info_installed("wget", attr="version")
+ calls = wget_lowpkg["lowpkg.info"].call_args_list.pop()
+ self.assertIn("status", calls.kwargs["attr"])
+ self.assertIn("version", calls.kwargs["attr"])
+ :return:
+ """
+ mock = MagicMock(return_value=lowpkg_info_var)
+ with patch.dict(aptpkg.__salt__, {"lowpkg.info": mock}):
+ aptpkg.info_installed("wget", attr="version")
+ assert "status" in mock.call_args.kwargs["attr"]
+ assert "version" in mock.call_args.kwargs["attr"]
+
@patch(
"salt.modules.aptpkg.__salt__",
{"lowpkg.info": MagicMock(return_value=LOWPKG_INFO)},
+
def test_info_installed_all_versions(lowpkg_info_var):
"""
Test info_installed 'all_versions'.
--
2.29.2
2.34.1

View File

@ -1,6 +1,6 @@
From 2ea56dd17378fe2f41de04a9c1786d27fec9a266 Mon Sep 17 00:00:00 2001
From: Alexander Graul <mail@agraul.de>
Date: Mon, 25 Oct 2021 10:31:10 +0200
From a363596e5e02307680859432da9935905b749846 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 17:33:01 +0100
Subject: [PATCH] Mock ip_addrs() in utils/minions.py unit test (#443)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
@ -14,23 +14,25 @@ Since this is a unit test, it should not depend on the environment,
it should just work™, even if there are no real IP addresses assigned to
the system (or container) that runs the test.
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
---
tests/pytests/unit/utils/test_minions.py | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
tests/pytests/unit/utils/test_minions.py | 36 +++++++++++++-----------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/tests/pytests/unit/utils/test_minions.py b/tests/pytests/unit/utils/test_minions.py
index 0b7a7d3928..5b0cd77216 100644
index a9eee20ea1..6bc6c80bbd 100644
--- a/tests/pytests/unit/utils/test_minions.py
+++ b/tests/pytests/unit/utils/test_minions.py
@@ -8,15 +8,16 @@ def test_connected_ids():
@@ -8,18 +8,22 @@ def test_connected_ids():
test ckminion connected_ids when
local_port_tcp returns 127.0.0.1
"""
- opts = {"publish_port": 4505}
+ opts = {"publish_port": 4505, "minion_data_cache": True}
- opts = {"publish_port": 4505, "detect_remote_minions": False}
+ opts = {
+ "publish_port": 4505,
+ "detect_remote_minions": False,
+ "minion_data_cache": True,
+ }
minion = "minion"
- ip = salt.utils.network.ip_addrs()
- mdata = {"grains": {"ipv4": ip, "ipv6": []}}
@ -45,12 +47,44 @@ index 0b7a7d3928..5b0cd77216 100644
- with patch_net, patch_list, patch_fetch:
- ret = ckminions.connected_ids()
- assert ret == {minion}
+
+ ckminions = salt.utils.minions.CkMinions(opts)
+ with patch_net, patch_ip_addrs, patch_list, patch_fetch:
+ ret = ckminions.connected_ids()
+ assert ret == {minion}
def test_connected_ids_remote_minions():
@@ -31,21 +35,21 @@ def test_connected_ids_remote_minions():
"publish_port": 4505,
"detect_remote_minions": True,
"remote_minions_port": 22,
+ "minion_data_cache": True,
}
minion = "minion"
minion2 = "minion2"
minion2_ip = "192.168.2.10"
- ip = salt.utils.network.ip_addrs()
- mdata = {"grains": {"ipv4": ip, "ipv6": []}}
+ minion_ips = {"203.0.113.1", "203.0.113.2", "127.0.0.1"}
+ mdata = {"grains": {"ipv4": minion_ips, "ipv6": []}}
mdata2 = {"grains": {"ipv4": [minion2_ip], "ipv6": []}}
- ckminions = salt.utils.minions.CkMinions({"minion_data_cache": True})
- patch_net = patch("salt.utils.network.local_port_tcp", return_value={"127.0.0.1"})
+ patch_net = patch("salt.utils.network.local_port_tcp", return_value=minion_ips)
patch_remote_net = patch(
"salt.utils.network.remote_port_tcp", return_value={minion2_ip}
)
patch_list = patch("salt.cache.Cache.list", return_value=[minion, minion2])
patch_fetch = patch("salt.cache.Cache.fetch", side_effect=[mdata, mdata2])
- with patch.dict(ckminions.opts, opts):
- with patch_net, patch_list, patch_fetch, patch_remote_net:
- ret = ckminions.connected_ids()
- assert ret == {minion2, minion}
+ ckminions = salt.utils.minions.CkMinions(opts)
+ with patch_net, patch_list, patch_fetch, patch_remote_net:
+ ret = ckminions.connected_ids()
+ assert ret == {minion2, minion}
--
2.33.1
2.34.1

View File

@ -1,159 +0,0 @@
From 3973f51a948c0d4a81ca5992c9b06e71ebae443c Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Mon, 3 May 2021 17:20:54 +0200
Subject: [PATCH] Parsing Epoch out of version provided during pkg remove
(bsc#1173692)
yum doesn't seem to like the epoch information provided within the
version. Therefore it's removed before passing it to yum.
* Introducing `ignore_epoch` to pkg.remove
Just like pkg.install pkg.remove now also has ignore_epoch. With
this it is possible to ignore the epoch information completely
during version comparison.
* No epoch regardless of arch
* Added tests for cases with and without arch.
* Epoch information is now skipped in all cases.
* Removes ignore_epoch from pkg state
---
changelog/57881.changed | 1 +
salt/modules/yumpkg.py | 14 ++--
tests/pytests/unit/modules/test_yumpkg.py | 79 +++++++++++++++++++++++
3 files changed, 90 insertions(+), 4 deletions(-)
create mode 100644 changelog/57881.changed
diff --git a/changelog/57881.changed b/changelog/57881.changed
new file mode 100644
index 0000000000..e2ae2f4653
--- /dev/null
+++ b/changelog/57881.changed
@@ -0,0 +1 @@
+Parsing Epoch out of version during pkg remove, since yum can't handle that in all of the cases.
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index c800dafa82..dd81c6f1e9 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -2087,11 +2087,13 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
old = list_pkgs()
targets = []
for target in pkg_params:
+ version_to_remove = pkg_params[target]
+ installed_versions = old[target].split(",")
+
# Check if package version set to be removed is actually installed:
- # old[target] contains a comma-separated list of installed versions
- if target in old and not pkg_params[target]:
+ if target in old and not version_to_remove:
targets.append(target)
- elif target in old and pkg_params[target] in old[target].split(","):
+ elif target in old and version_to_remove in installed_versions:
arch = ""
pkgname = target
try:
@@ -2102,7 +2104,11 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
if archpart in salt.utils.pkg.rpm.ARCHES:
arch = "." + archpart
pkgname = namepart
- targets.append("{}-{}{}".format(pkgname, pkg_params[target], arch))
+ # Since we don't always have the arch info, epoch information has to parsed out. But
+ # a version check was already performed, so we are removing the right version.
+ targets.append(
+ "{}-{}{}".format(pkgname, version_to_remove.split(":", 1)[-1], arch)
+ )
if not targets:
return {}
diff --git a/tests/pytests/unit/modules/test_yumpkg.py b/tests/pytests/unit/modules/test_yumpkg.py
index cae47788ff..7e3ed517ea 100644
--- a/tests/pytests/unit/modules/test_yumpkg.py
+++ b/tests/pytests/unit/modules/test_yumpkg.py
@@ -1046,6 +1046,85 @@ def test_install_with_options():
)
+def test_remove_with_epoch():
+ """
+ Tests that we properly identify a version containing an epoch for
+ deinstallation.
+ You can deinstall pkgs only without the epoch if no arch is provided:
+ .. code-block:: bash
+ yum remove PackageKit-yum-1.1.10-2.el7.centos
+ """
+ name = "foo"
+ installed = "8:3.8.12-4.n.el7"
+ list_pkgs_mock = MagicMock(
+ side_effect=lambda **kwargs: {
+ name: [installed] if kwargs.get("versions_as_list", False) else installed
+ }
+ )
+ cmd_mock = MagicMock(
+ return_value={"pid": 12345, "retcode": 0, "stdout": "", "stderr": ""}
+ )
+ salt_mock = {
+ "cmd.run_all": cmd_mock,
+ "lowpkg.version_cmp": rpm.version_cmp,
+ "pkg_resource.parse_targets": MagicMock(
+ return_value=({name: installed}, "repository")
+ ),
+ }
+ full_pkg_string = "-".join((name, installed[2:]))
+ with patch.object(yumpkg, "list_pkgs", list_pkgs_mock), patch(
+ "salt.utils.systemd.has_scope", MagicMock(return_value=False)
+ ), patch.dict(yumpkg.__salt__, salt_mock):
+
+ with patch.dict(yumpkg.__grains__, {"os": "CentOS", "osrelease": 7}):
+ expected = ["yum", "-y", "remove", full_pkg_string]
+ yumpkg.remove(name)
+ call = cmd_mock.mock_calls[0][1][0]
+ assert call == expected, call
+
+
+def test_remove_with_epoch_and_arch_info():
+ """
+ Tests that we properly identify a version containing an epoch and arch
+ deinstallation.
+ You can deinstall pkgs with or without epoch in combination with the arch.
+ Here we test for the absence of the epoch, but the presence for the arch:
+ .. code-block:: bash
+ yum remove PackageKit-yum-1.1.10-2.el7.centos.x86_64
+ """
+ arch = "x86_64"
+ name = "foo"
+ name_and_arch = name + "." + arch
+ installed = "8:3.8.12-4.n.el7"
+ list_pkgs_mock = MagicMock(
+ side_effect=lambda **kwargs: {
+ name_and_arch: [installed]
+ if kwargs.get("versions_as_list", False)
+ else installed
+ }
+ )
+ cmd_mock = MagicMock(
+ return_value={"pid": 12345, "retcode": 0, "stdout": "", "stderr": ""}
+ )
+ salt_mock = {
+ "cmd.run_all": cmd_mock,
+ "lowpkg.version_cmp": rpm.version_cmp,
+ "pkg_resource.parse_targets": MagicMock(
+ return_value=({name_and_arch: installed}, "repository")
+ ),
+ }
+ full_pkg_string = "-".join((name, installed[2:]))
+ with patch.object(yumpkg, "list_pkgs", list_pkgs_mock), patch(
+ "salt.utils.systemd.has_scope", MagicMock(return_value=False)
+ ), patch.dict(yumpkg.__salt__, salt_mock):
+
+ with patch.dict(yumpkg.__grains__, {"os": "CentOS", "osrelease": 7}):
+ expected = ["yum", "-y", "remove", full_pkg_string + "." + arch]
+ yumpkg.remove(name)
+ call = cmd_mock.mock_calls[0][1][0]
+ assert call == expected, call
+
+
def test_install_with_epoch():
"""
Tests that we properly identify a version containing an epoch as an
--
2.33.0

View File

@ -1,318 +0,0 @@
From eb15f772aa7aa6c9553bb4f24c709e941e6f3413 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 22 Jan 2020 08:19:55 +0000
Subject: [PATCH] Prevent logging deadlock on salt-api subprocesses
(bsc#1159284)
---
salt/_logging/impl.py | 80 +++++++++++++++++++----------------
salt/client/ssh/__init__.py | 12 +++++-
salt/client/ssh/client.py | 9 +++-
salt/client/ssh/wrapper/cp.py | 2 +-
salt/loader.py | 6 +--
salt/utils/lazy.py | 10 ++---
6 files changed, 71 insertions(+), 48 deletions(-)
diff --git a/salt/_logging/impl.py b/salt/_logging/impl.py
index afb0027eeb..ad46c10e01 100644
--- a/salt/_logging/impl.py
+++ b/salt/_logging/impl.py
@@ -15,6 +15,7 @@ PROFILE = logging.PROFILE = 15
TRACE = logging.TRACE = 5
GARBAGE = logging.GARBAGE = 1
QUIET = logging.QUIET = 1000
+DEBUG = logging.DEBUG = 10
from salt._logging.handlers import StreamHandler # isort:skip
@@ -182,11 +183,9 @@ class SaltLoggingClass(
"""
instance = super().__new__(cls)
- try:
- max_logger_length = len(
- max(list(logging.Logger.manager.loggerDict), key=len)
- )
- for handler in logging.root.handlers:
+ max_logger_length = len(max(list(logging.Logger.manager.loggerDict), key=len))
+ for handler in logging.root.handlers:
+ try:
if handler in (
LOGGING_NULL_HANDLER,
LOGGING_STORE_HANDLER,
@@ -207,18 +206,15 @@ class SaltLoggingClass(
match = MODNAME_PATTERN.search(fmt)
if not match:
# Not matched. Release handler and return.
- handler.release()
return instance
if "digits" not in match.groupdict():
# No digits group. Release handler and return.
- handler.release()
return instance
digits = match.group("digits")
if not digits or not (digits and digits.isdigit()):
# No valid digits. Release handler and return.
- handler.release()
return instance
if int(digits) < max_logger_length:
@@ -229,9 +225,14 @@ class SaltLoggingClass(
)
handler.setFormatter(formatter)
handler.release()
- except ValueError:
- # There are no registered loggers yet
- pass
+ except ValueError:
+ # There are no registered loggers yet
+ pass
+ finally:
+ try:
+ handler.release()
+ except:
+ pass
return instance
def _log(
@@ -281,31 +282,37 @@ class SaltLoggingClass(
else:
extra["exc_info_on_loglevel"] = exc_info_on_loglevel
- if sys.version_info < (3,):
- LOGGING_LOGGER_CLASS._log(
- self, level, msg, args, exc_info=exc_info, extra=extra
- )
- elif sys.version_info < (3, 8):
- LOGGING_LOGGER_CLASS._log(
- self,
- level,
- msg,
- args,
- exc_info=exc_info,
- extra=extra,
- stack_info=stack_info,
- )
- else:
- LOGGING_LOGGER_CLASS._log(
- self,
- level,
- msg,
- args,
- exc_info=exc_info,
- extra=extra,
- stack_info=stack_info,
- stacklevel=stacklevel,
- )
+ try:
+ logging._acquireLock()
+ if sys.version_info < (3,):
+ LOGGING_LOGGER_CLASS._log(
+ self, level, msg, args, exc_info=exc_info, extra=extra
+ )
+ elif sys.version_info < (3, 8):
+ LOGGING_LOGGER_CLASS._log(
+ self,
+ level,
+ msg,
+ args,
+ exc_info=exc_info,
+ extra=extra,
+ stack_info=stack_info,
+ )
+ else:
+ LOGGING_LOGGER_CLASS._log(
+ self,
+ level,
+ msg,
+ args,
+ exc_info=exc_info,
+ extra=extra,
+ stack_info=stack_info,
+ stacklevel=stacklevel,
+ )
+ except:
+ pass
+ finally:
+ logging._releaseLock()
def makeRecord(
self,
@@ -395,6 +402,7 @@ if logging.getLoggerClass() is not SaltLoggingClass:
logging.addLevelName(PROFILE, "PROFILE")
logging.addLevelName(TRACE, "TRACE")
logging.addLevelName(GARBAGE, "GARBAGE")
+ logging.addLevelName(DEBUG, "DEBUG")
if pip_log_module is not None:
# Let's make newer versions of pip work by patching SaltLoggingClass to
# add a verbose method which is what pip expects
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 01fb5e9a30..a4a74aa2c2 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -532,7 +532,9 @@ class SSH:
**target
)
ret = {"id": single.id}
+ logging._acquireLock()
stdout, stderr, retcode = single.run()
+ logging._releaseLock()
# This job is done, yield
try:
data = salt.utils.json.find_json(stdout)
@@ -600,8 +602,14 @@ class SSH:
self.targets[host],
mine,
)
- routine = Process(target=self.handle_routine, args=args)
- routine.start()
+ try:
+ logging._acquireLock()
+ routine = Process(target=self.handle_routine, args=args)
+ routine.start()
+ except:
+ pass
+ finally:
+ logging._releaseLock()
running[host] = {"thread": routine}
continue
ret = {}
diff --git a/salt/client/ssh/client.py b/salt/client/ssh/client.py
index ef4287463b..037aea779c 100644
--- a/salt/client/ssh/client.py
+++ b/salt/client/ssh/client.py
@@ -1,7 +1,9 @@
import copy
import logging
+import multiprocessing
import os
import random
+import time
import salt.config
import salt.syspaths
@@ -10,6 +12,7 @@ from salt.exceptions import SaltClientError
log = logging.getLogger(__name__)
+_LOCK = multiprocessing.Lock()
class SSHClient:
"""
@@ -124,7 +127,11 @@ class SSHClient:
opts["selected_target_option"] = tgt_type
opts["tgt"] = tgt
opts["arg"] = arg
- return salt.client.ssh.SSH(opts)
+ _LOCK.acquire()
+ ret = salt.client.ssh.SSH(opts)
+ time.sleep(0.01)
+ _LOCK.release()
+ return ret
def cmd_iter(
self,
diff --git a/salt/client/ssh/wrapper/cp.py b/salt/client/ssh/wrapper/cp.py
index 020dadfa35..af7d4f73f4 100644
--- a/salt/client/ssh/wrapper/cp.py
+++ b/salt/client/ssh/wrapper/cp.py
@@ -2,10 +2,10 @@
Wrap the cp module allowing for managed ssh file transfers
"""
-import logging
import os
import salt.client.ssh
+import salt.log.setup as logging
import salt.utils.files
import salt.utils.stringutils
import salt.utils.templates
diff --git a/salt/loader.py b/salt/loader.py
index 491768a028..cdcec70262 100644
--- a/salt/loader.py
+++ b/salt/loader.py
@@ -10,7 +10,6 @@ import importlib
import importlib.machinery # pylint: disable=no-name-in-module,import-error
import importlib.util # pylint: disable=no-name-in-module,import-error
import inspect
-import logging
import os
import re
import sys
@@ -27,6 +26,7 @@ import salt.config
import salt.defaults.events
import salt.defaults.exitcodes
import salt.loader_context
+import salt.log.setup as logging
import salt.syspaths
import salt.utils.args
import salt.utils.context
@@ -2195,7 +2195,7 @@ class LazyLoader(salt.utils.lazy.LazyDict):
mod.__name__, exc
)
)
- log.error(error_reason, exc_info_on_loglevel=logging.DEBUG)
+ log.error(error_reason, exc_info_on_loglevel=logging.logging.DEBUG)
virtual = None
# Get the module's virtual name
virtualname = getattr(mod, "__virtualname__", virtual)
@@ -2341,5 +2341,5 @@ def catch_entry_points_exception(entry_point):
entry_point_details.name,
entry_point_details.version,
exc,
- exc_info_on_loglevel=logging.DEBUG,
+ exc_info_on_loglevel=logging.logging.DEBUG,
)
diff --git a/salt/utils/lazy.py b/salt/utils/lazy.py
index 8fc538164a..c828dd2c32 100644
--- a/salt/utils/lazy.py
+++ b/salt/utils/lazy.py
@@ -1,15 +1,13 @@
-# -*- coding: utf-8 -*-
"""
Lazily-evaluated data structures, primarily used by Salt's loader
"""
-# Import Python Libs
-from __future__ import absolute_import, unicode_literals
-import logging
+import time
from collections.abc import MutableMapping
import salt.exceptions
+import salt.log.setup as logging
log = logging.getLogger(__name__)
@@ -81,7 +79,7 @@ class LazyDict(MutableMapping):
Override this to return a more meaningfull error message if possible
"""
- return "'{0}' is not available.".format(function_name)
+ return "'{}' is not available.".format(function_name)
def __setitem__(self, key, val):
self._dict[key] = val
@@ -100,11 +98,13 @@ class LazyDict(MutableMapping):
# load the item
if self._load(key):
log.debug("LazyLoaded %s", key)
+ time.sleep(0.0001)
return self._dict[key]
else:
log.debug(
"Could not LazyLoad %s: %s", key, self.missing_fun_string(key)
)
+ time.sleep(0.0001)
raise KeyError(key)
else:
return self._dict[key]
--
2.33.0

View File

@ -1,4 +1,4 @@
From ad5baab333cb80ce47e65605c47c8ca6fc6d4514 Mon Sep 17 00:00:00 2001
From 27db7d49c4b3348d5dcfe229f0d5823c0e770179 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
Date: Mon, 8 Nov 2021 17:42:36 +0300
Subject: [PATCH] Prevent pkg plugins errors on missing cookie path
@ -12,11 +12,11 @@ Subject: [PATCH] Prevent pkg plugins errors on missing cookie path
* Fix yumnotify
---
scripts/suse/dpkg/dpkgnotify | 18 ++++++++++++++---
scripts/suse/dpkg/dpkgnotify | 18 +++++++++++++++---
scripts/suse/yum/plugins/README.md | 2 +-
scripts/suse/yum/plugins/yumnotify.py | 17 ++++++++++++----
scripts/suse/zypper/plugins/commit/zyppnotify | 20 ++++++++++++-------
4 files changed, 42 insertions(+), 15 deletions(-)
scripts/suse/yum/plugins/yumnotify.py | 17 +++++++++++++----
scripts/suse/zypper/plugins/commit/zyppnotify | 18 ++++++++++++------
4 files changed, 41 insertions(+), 14 deletions(-)
diff --git a/scripts/suse/dpkg/dpkgnotify b/scripts/suse/dpkg/dpkgnotify
index d3ad3d2ba9..3d6d038a98 100644
@ -104,7 +104,7 @@ index 4e137191a0..0d117e8946 100644
+ except OSError as e:
+ print("Unable to save the cookie file: %s" % (e), file=sys.stderr)
diff --git a/scripts/suse/zypper/plugins/commit/zyppnotify b/scripts/suse/zypper/plugins/commit/zyppnotify
index d6a1bef42b..e3528e87a9 100755
index bacbc8b97e..e3528e87a9 100755
--- a/scripts/suse/zypper/plugins/commit/zyppnotify
+++ b/scripts/suse/zypper/plugins/commit/zyppnotify
@@ -1,4 +1,4 @@
@ -113,12 +113,8 @@ index d6a1bef42b..e3528e87a9 100755
#
# Copyright (c) 2016 SUSE Linux LLC
# All Rights Reserved.
@@ -52,15 +52,21 @@ class DriftDetector(Plugin):
def PLUGINEND(self, headers, body):
"""
- Hook when plugin closes Zypper's transaction.
+ Hook when plugin closes Zypper's transaction.
@@ -55,12 +55,18 @@ class DriftDetector(Plugin):
Hook when plugin closes Zypper's transaction.
"""
if "SALT_RUNNING" not in os.environ:
- with open(self.ck_path, "w") as ck_fh:
@ -142,6 +138,6 @@ index d6a1bef42b..e3528e87a9 100755
self.ack()
--
2.33.1
2.34.1

View File

@ -1,7 +1,6 @@
From b458f53eaa4930abab230ca734f5930b95b8def0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 4 Nov 2021 16:07:01 +0000
From e28a67ec69b4781fc9c667a9cdec66192e4cca45 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Wed, 19 Jan 2022 17:45:01 +0100
Subject: [PATCH] Refactor and improvements for "transactional-updates"
module
@ -26,8 +25,8 @@ Remove hack about tukit issue that has been already fixed
salt/modules/state.py | 12 +-
salt/modules/transactional_update.py | 235 ++---------
salt/utils/parsers.py | 6 +
.../pytests/unit/modules/state/test_state.py | 2 +-
.../unit/modules/test_transactional_update.py | 389 ++----------------
tests/unit/modules/test_state.py | 2 +-
7 files changed, 81 insertions(+), 568 deletions(-)
create mode 100644 changelog/61188.fixed
@ -41,10 +40,10 @@ index 0000000000..102a8982a6
+Make "state.highstate" to acts on concurrent flag.
+Simplify "transactional_update" module to not use SSH wrapper and allow more flexible execution
diff --git a/salt/cli/caller.py b/salt/cli/caller.py
index 0e1fa9f90b..af8cc84a29 100644
index 795d32e4c9..10eb5e397a 100644
--- a/salt/cli/caller.py
+++ b/salt/cli/caller.py
@@ -294,7 +294,7 @@ class BaseCaller:
@@ -293,7 +293,7 @@ class BaseCaller:
pass
# return the job infos back up to the respective minion's master
@ -54,10 +53,10 @@ index 0e1fa9f90b..af8cc84a29 100644
mret = ret.copy()
mret["jid"] = "req"
diff --git a/salt/modules/state.py b/salt/modules/state.py
index ff6998a0e3..0636b7d894 100644
index c78072131b..0c3dfc3317 100644
--- a/salt/modules/state.py
+++ b/salt/modules/state.py
@@ -1052,9 +1052,15 @@ def highstate(test=None, queue=False, **kwargs):
@@ -1053,9 +1053,15 @@ def highstate(test=None, queue=False, **kwargs):
}
return ret
@ -394,12 +393,12 @@ index 799fe08e4d..28b02f8fec 100644
+ **kwargs
)
diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py
index 31a2bf0b64..6cfb34a550 100644
index c0820e5df0..5ff3c964be 100644
--- a/salt/utils/parsers.py
+++ b/salt/utils/parsers.py
@@ -3079,6 +3079,12 @@ class SaltCallOptionParser(
@@ -3108,6 +3108,12 @@ class SaltCallOptionParser(
action="store_true",
help=("Force a refresh of the grains cache."),
help="Force a refresh of the grains cache.",
)
+ self.add_option(
+ "--no-return-event",
@ -410,15 +409,28 @@ index 31a2bf0b64..6cfb34a550 100644
self.add_option(
"-t",
"--timeout",
diff --git a/tests/pytests/unit/modules/state/test_state.py b/tests/pytests/unit/modules/state/test_state.py
index 3fa663edeb..02fd2dd307 100644
--- a/tests/pytests/unit/modules/state/test_state.py
+++ b/tests/pytests/unit/modules/state/test_state.py
@@ -777,7 +777,7 @@ def test_highstate():
}
mock = MagicMock(side_effect=["A", None, None])
- with patch.object(state, "_check_queue", mock):
+ with patch.object(state, "running", mock):
assert state.highstate("whitelist=sls1.sls") == "A"
with patch.dict(state.__opts__, {"test": "A"}):
diff --git a/tests/pytests/unit/modules/test_transactional_update.py b/tests/pytests/unit/modules/test_transactional_update.py
index e7293cf3e2..64c06c1693 100644
index 032ca0c9e8..40dab0e2f6 100644
--- a/tests/pytests/unit/modules/test_transactional_update.py
+++ b/tests/pytests/unit/modules/test_transactional_update.py
@@ -1,5 +1,3 @@
-import sys
-
import pytest
import salt.loader_context
import salt.loader.context
import salt.modules.state as statemod
@@ -353,114 +351,23 @@ def test_call_fails_input_validation():
tu.call("")
@ -1045,20 +1057,7 @@ index e7293cf3e2..64c06c1693 100644
):
assert tu.single("pkg.installed", name="emacs", queue=True) == "result"
- _create_and_execute_salt_state_mock.assert_called_once()
diff --git a/tests/unit/modules/test_state.py b/tests/unit/modules/test_state.py
index ffa5428873..03f434dbcc 100644
--- a/tests/unit/modules/test_state.py
+++ b/tests/unit/modules/test_state.py
@@ -801,7 +801,7 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
)
mock = MagicMock(side_effect=["A", None, None])
- with patch.object(state, "_check_queue", mock):
+ with patch.object(state, "running", mock):
self.assertEqual(state.highstate("whitelist=sls1.sls"), "A")
with patch.dict(state.__opts__, {"test": "A"}):
--
2.33.1
2.34.1

View File

@ -1,7 +1,6 @@
From 93a38f70953f48d10e21ba8601e1a562a4b739fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Tue, 5 Jan 2021 12:31:26 +0000
From a82b6316d8a780a7a8cbfbabeb52fa50b3fb1032 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 19:07:34 +0100
Subject: [PATCH] Revert "Fixing a use case when multiple inotify beacons
are defined but when notifications are fired the configuration fron the first
beacon are used." Revert "Adding a util function to remove hidden (options
@ -12,20 +11,20 @@ Subject: [PATCH] Revert "Fixing a use case when multiple inotify beacons
This reverts commit 68a891ab2fe53ebf329b9c83b875f3575e87e266.
This reverts commit 66c58dedf8c364eaeb35c5adce8bcc8fe5c1219a.
---
salt/beacons/__init__.py | 1 -
salt/beacons/diskusage.py | 3 ---
salt/beacons/inotify.py | 25 +++++++------------
salt/beacons/napalm_beacon.py | 6 ++---
salt/beacons/status.py | 4 ---
tests/unit/beacons/test_inotify.py | 39 ------------------------------
tests/unit/test_beacons.py | 25 +++----------------
7 files changed, 15 insertions(+), 88 deletions(-)
salt/beacons/__init__.py | 1 -
salt/beacons/diskusage.py | 3 ---
salt/beacons/inotify.py | 24 ++++++++--------------
salt/beacons/napalm_beacon.py | 6 ++----
salt/beacons/status.py | 4 ----
tests/pytests/unit/beacons/test_inotify.py | 5 +----
tests/pytests/unit/test_beacons.py | 16 ---------------
7 files changed, 11 insertions(+), 48 deletions(-)
diff --git a/salt/beacons/__init__.py b/salt/beacons/__init__.py
index cd00b15275..967f9ff64b 100644
index 414142c262..13e2ae78db 100644
--- a/salt/beacons/__init__.py
+++ b/salt/beacons/__init__.py
@@ -70,7 +70,6 @@ class Beacon:
@@ -71,7 +71,6 @@ class Beacon:
beacon_name = current_beacon_config["beacon_module"]
else:
beacon_name = mod
@ -34,7 +33,7 @@ index cd00b15275..967f9ff64b 100644
validate_str = "{}.validate".format(beacon_name)
if fun_str in self.beacons:
diff --git a/salt/beacons/diskusage.py b/salt/beacons/diskusage.py
index 5624ebaffd..a015eebdc7 100644
index 1216abf79b..897bc90a6a 100644
--- a/salt/beacons/diskusage.py
+++ b/salt/beacons/diskusage.py
@@ -8,7 +8,6 @@ Beacon to monitor disk usage.
@ -55,18 +54,10 @@ index 5624ebaffd..a015eebdc7 100644
ret = []
for mounts in config:
diff --git a/salt/beacons/inotify.py b/salt/beacons/inotify.py
index 4d9ffbeb87..031da181f0 100644
index b6e7334eee..c44bd49fb0 100644
--- a/salt/beacons/inotify.py
+++ b/salt/beacons/inotify.py
@@ -21,6 +21,7 @@ import os
import re
import salt.utils.beacons
+import salt.ext.six
try:
import pyinotify
@@ -65,19 +66,17 @@ def _get_notifier(config):
@@ -65,19 +65,17 @@ def _get_notifier(config):
"""
Check the context for the notifier and construct it if not present
"""
@ -90,30 +81,30 @@ index 4d9ffbeb87..031da181f0 100644
def validate(config):
@@ -253,10 +252,6 @@ def beacon(config):
affects all paths that are being watched. This is due to this option
@@ -237,9 +235,6 @@ def beacon(config):
being at the Notifier level in pyinotify.
"""
-
- whitelist = ["_beacon_name"]
- config = salt.utils.beacons.remove_hidden_options(config, whitelist)
-
_config = {}
list(map(_config.update, config))
config = salt.utils.beacons.list_to_dict(config)
@@ -280,7 +275,7 @@ def beacon(config):
ret = []
@@ -262,7 +257,7 @@ def beacon(config):
break
path = os.path.dirname(path)
- excludes = _config["files"].get(path, {}).get("exclude", "")
+ excludes = _config["files"][path].get("exclude", "")
- excludes = config["files"].get(path, {}).get("exclude", "")
+ excludes = config["files"][path].get("exclude", "")
if excludes and isinstance(excludes, list):
for exclude in excludes:
@@ -367,8 +362,6 @@ def beacon(config):
@@ -349,9 +344,6 @@ def beacon(config):
def close(config):
- config = salt.utils.beacons.list_to_dict(config)
- beacon_name = config.get("_beacon_name", "inotify")
- notifier = "{}.notifier".format(beacon_name)
- if notifier in __context__:
@ -123,7 +114,7 @@ index 4d9ffbeb87..031da181f0 100644
+ __context__["inotify.notifier"].stop()
+ del __context__["inotify.notifier"]
diff --git a/salt/beacons/napalm_beacon.py b/salt/beacons/napalm_beacon.py
index 3ca4d10512..d1bddccb8e 100644
index ec8cf63fca..164b29cdf8 100644
--- a/salt/beacons/napalm_beacon.py
+++ b/salt/beacons/napalm_beacon.py
@@ -168,9 +168,10 @@ with a NTP server at a stratum level greater than 5.
@ -138,7 +129,7 @@ index 3ca4d10512..d1bddccb8e 100644
import salt.utils.napalm
log = logging.getLogger(__name__)
@@ -302,9 +303,6 @@ def beacon(config):
@@ -301,9 +302,6 @@ def beacon(config):
"""
Watch napalm function and fire events.
"""
@ -149,7 +140,7 @@ index 3ca4d10512..d1bddccb8e 100644
log.debug(config)
ret = []
diff --git a/salt/beacons/status.py b/salt/beacons/status.py
index bd7046aaa1..a30bf5f4e6 100644
index aa5aa13b47..e2c3177ea8 100644
--- a/salt/beacons/status.py
+++ b/salt/beacons/status.py
@@ -91,7 +91,6 @@ import datetime
@ -170,101 +161,55 @@ index bd7046aaa1..a30bf5f4e6 100644
if not config:
config = [
{
diff --git a/tests/unit/beacons/test_inotify.py b/tests/unit/beacons/test_inotify.py
index 665e334fbc..d91a2daebf 100644
--- a/tests/unit/beacons/test_inotify.py
+++ b/tests/unit/beacons/test_inotify.py
@@ -273,42 +273,3 @@ class INotifyBeaconTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(len(ret), 1)
self.assertEqual(ret[0]["path"], fp)
self.assertEqual(ret[0]["change"], "IN_DELETE")
-
- # Check __get_notifier and ensure that the right bits are in __context__
- # including a beacon_name specific notifier is found.
- def test__get_notifier(self):
- config = {
- "files": {
- "/tmp/httpd/vhost.d": {
- "mask": ["delete", "modify"],
- "recurse": True,
- "auto_add": True,
- "exclude": [
- {"/tmp/httpd/vhost.d/.+?\\.sw[px]*$|4913|~$": {"regex": True}}
- ],
- },
- "/tmp/httpd/conf.d": {
- "mask": ["delete", "modify"],
- "recurse": True,
- "auto_add": True,
- "exclude": [
- {"/tmp/httpd/vhost.d/.+?\\.sw[px]*$|4913|~$": {"regex": True}}
- ],
- },
- "/tmp/httpd/conf": {
- "mask": ["delete", "modify"],
- "recurse": True,
- "auto_add": True,
- "exclude": [
- {"/tmp/httpd/vhost.d/.+?\\.sw[px]*$|4913|~$": {"regex": True}}
- ],
- },
- },
- "coalesce": True,
- "beacon_module": "inotify",
- "_beacon_name": "httpd.inotify",
- }
-
- ret = inotify._get_notifier(config)
- self.assertIn("inotify.queue", inotify.__context__)
- self.assertIn("httpd.inotify.notifier", inotify.__context__)
diff --git a/tests/unit/test_beacons.py b/tests/unit/test_beacons.py
index b7a5127179..be629f49d4 100644
--- a/tests/unit/test_beacons.py
+++ b/tests/unit/test_beacons.py
@@ -7,7 +7,7 @@ import logging
import salt.beacons as beacons
import salt.config
from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import MagicMock, call, patch
+from tests.support.mock import patch
from tests.support.unit import TestCase
diff --git a/tests/pytests/unit/beacons/test_inotify.py b/tests/pytests/unit/beacons/test_inotify.py
index f5befb2756..dfaf1d499a 100644
--- a/tests/pytests/unit/beacons/test_inotify.py
+++ b/tests/pytests/unit/beacons/test_inotify.py
@@ -273,7 +273,6 @@ def test_multi_files_exclude(tmp_path):
log = logging.getLogger(__name__)
@@ -35,9 +35,9 @@ class BeaconsTestCase(TestCase, LoaderModuleMockMixin):
]
}
with patch.dict(beacons.__opts__, mock_opts):
- beacon = salt.beacons.Beacon(mock_opts, [])
- ret = beacon.process(mock_opts["beacons"], mock_opts["grains"])
-
+ ret = salt.beacons.Beacon(mock_opts, []).process(
+ mock_opts["beacons"], mock_opts["grains"]
+ )
_expected = [
{
"tag": "salt/beacon/minion/watch_apache/",
@@ -46,20 +46,3 @@ class BeaconsTestCase(TestCase, LoaderModuleMockMixin):
}
]
self.assertEqual(ret, _expected)
-
- # Ensure that "beacon_name" is available in the call to the beacon function
- name = "ps.beacon"
- mocked = {name: MagicMock(return_value=_expected)}
- mocked[name].__globals__ = {}
- calls = [
- call(
- [
- {"processes": {"apache2": "stopped"}},
- {"beacon_module": "ps"},
- {"_beacon_name": "watch_apache"},
- ]
- )
# Check __get_notifier and ensure that the right bits are in __context__
-# including a beacon_name specific notifier is found.
def test__get_notifier():
config = {
"files": {
@@ -303,10 +302,8 @@ def test__get_notifier():
},
},
"coalesce": True,
- "beacon_module": "inotify",
- "_beacon_name": "httpd.inotify",
}
ret = inotify._get_notifier(config)
assert "inotify.queue" in inotify.__context__
- assert "httpd.inotify.notifier" in inotify.__context__
+ assert "inotify.notifier" in inotify.__context__
diff --git a/tests/pytests/unit/test_beacons.py b/tests/pytests/unit/test_beacons.py
index 27940c6f65..a347f3f27f 100644
--- a/tests/pytests/unit/test_beacons.py
+++ b/tests/pytests/unit/test_beacons.py
@@ -70,19 +70,3 @@ def test_beacon_module():
]
assert ret == _expected
- # Ensure that "beacon_name" is available in the call to the beacon function
- name = "ps.beacon"
- mocked = {name: MagicMock(return_value=_expected)}
- mocked[name].__globals__ = {}
- calls = [
- call(
- [
- {"processes": {"apache2": "stopped"}},
- {"beacon_module": "ps"},
- {"_beacon_name": "watch_apache"},
- ]
- with patch.object(beacon, "beacons", mocked) as patched:
- beacon.process(mock_opts["beacons"], mock_opts["grains"])
- patched[name].assert_has_calls(calls)
- )
- ]
- with patch.object(beacon, "beacons", mocked) as patched:
- beacon.process(mock_opts["beacons"], mock_opts["grains"])
- patched[name].assert_has_calls(calls)
--
2.33.0
2.34.1

View File

@ -1,4 +1,4 @@
From 88f40fff3b81edaa55f37949f56c67112ca2dcad Mon Sep 17 00:00:00 2001
From 3d75826c24a6a1533623982cc4d92325c739d908 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <kkaempf@suse.de>
Date: Wed, 20 Jan 2016 11:01:06 +0100
Subject: [PATCH] Run salt master as dedicated salt user
@ -10,7 +10,7 @@ Subject: [PATCH] Run salt master as dedicated salt user
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/conf/master b/conf/master
index 41a62f2f34..943c5b5846 100644
index 07bf2e9591..6415a536e7 100644
--- a/conf/master
+++ b/conf/master
@@ -25,7 +25,8 @@
@ -42,6 +42,6 @@ index a0306ff370..97d158db18 100644
missingok
rotate 7
--
2.29.2
2.34.1

View File

@ -1,3 +1,61 @@
-------------------------------------------------------------------
Wed Jan 26 17:04:36 UTC 2022 - Alexander Graul <alexander.graul@suse.com>
- Update to version 3004, see release notes: https://docs.saltproject.io/en/master/topics/releases/3004.html
- Don't check for cached pillar errors on state.apply (bsc#1190781)
- Added:
* state.apply-don-t-check-for-cached-pillar-errors.patch
- Modified:
* add-migrated-state-and-gpg-key-management-functions-.patch
* switch-firewalld-state-to-use-change_interface.patch
* include-aliases-in-the-fqdns-grains.patch
* debian-info_installed-compatibility-50453.patch
* info_installed-works-without-status-attr-now.patch
* fix-traceback.print_exc-calls-for-test_pip_state-432.patch
* add-custom-suse-capabilities-as-grains.patch
* add-rpm_vercmp-python-library-for-version-comparison.patch
* 3003.3-do-not-consider-skipped-targets-as-failed-for.patch
* support-transactional-systems-microos.patch
* do-not-crash-when-unexpected-cmd-output-at-listing-p.patch
* enable-passing-a-unix_socket-for-mysql-returners-bsc.patch
* update-target-fix-for-salt-ssh-to-process-targets-li.patch
* fix-exception-in-yumpkg.remove-for-not-installed-pac.patch
* enhance-openscap-module-add-xccdf_eval-call-386.patch
* add-environment-variable-to-know-if-yum-is-invoked-f.patch
* zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch
* run-salt-master-as-dedicated-salt-user.patch
* 3003.3-postgresql-json-support-in-pillar-423.patch
* prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch
* early-feature-support-config.patch
* implementation-of-held-unheld-functions-for-state-pk.patch
* x509-fixes-111.patch
* fix-issues-with-salt-ssh-s-extra-filerefs.patch
* mock-ip_addrs-in-utils-minions.py-unit-test-443.patch
* use-adler32-algorithm-to-compute-string-checksums.patch
* refactor-and-improvements-for-transactional-updates-.patch
* improvements-on-ansiblegate-module-354.patch
* revert-fixing-a-use-case-when-multiple-inotify-beaco.patch
- Removed:
* add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch
* prevent-logging-deadlock-on-salt-api-subprocesses-bs.patch
* do-not-break-master_tops-for-minion-with-version-low.patch
* don-t-call-zypper-with-more-than-one-no-refresh.patch
* do-not-monkey-patch-yaml-bsc-1177474.patch
* add-missing-aarch64-to-rpm-package-architectures-405.patch
* figure-out-python-interpreter-to-use-inside-containe.patch
* parsing-epoch-out-of-version-provided-during-pkg-rem.patch
* fix-a-test-and-some-variable-names-229.patch
* add-astra-linux-common-edition-to-the-os-family-list.patch
* better-handling-of-bad-public-keys-from-minions-bsc-.patch
* templates-move-the-globals-up-to-the-environment-jin.patch
* virt-enhancements.patch
* fix-aptpkg.normalize_name-when-package-arch-is-all.patch
* adding-preliminary-support-for-rocky.-59682-391.patch
* fix-save-for-iptables-state-module-bsc-1185131-372.patch
-------------------------------------------------------------------
Mon Nov 15 15:14:54 UTC 2021 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>

224
salt.spec
View File

@ -36,7 +36,7 @@
%bcond_with builddocs
Name: salt
Version: 3003.3
Version: 3004
Release: 0
Summary: A parallel remote execution system
License: Apache-2.0
@ -115,12 +115,10 @@ Patch16: return-the-expected-powerpc-os-arch-bsc-1117995.patch
Patch17: fix-issue-2068-test.patch
# PATCH_FIX_OPENSUSE Temporary fix allowing "id_" and "force" params while upstrem figures it out
Patch18: temporary-fix-extend-the-whitelist-of-allowed-comman.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/58086 (merged but not in 3003)
Patch19: don-t-call-zypper-with-more-than-one-no-refresh.patch
### FQDNS ####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/51384 (master PR not yet created)
Patch20: include-aliases-in-the-fqdns-grains.patch
Patch19: include-aliases-in-the-fqdns-grains.patch
###########
#### BATCH ASYNC - unified #####
@ -143,172 +141,134 @@ Patch20: include-aliases-in-the-fqdns-grains.patch
# PATCH_FIX_OPENSUSE https://github.com/openSUSE/salt/commit/b4c401cfe6031b61e27f7795bfa1aca6e8341e52
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/320
# PATCH_FIX_OPENSUSE https://github.com/openSUSE/salt/commit/25b4e3ea983b2606b2fb3d3c0e42f9840208bf84 (cleanup local code)
Patch21: async-batch-implementation.patch
Patch20: async-batch-implementation.patch
###########
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/52743
Patch22: switch-firewalld-state-to-use-change_interface.patch
Patch21: switch-firewalld-state-to-use-change_interface.patch
### STANDALONE FORMULA CONFIGURATION ###
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/commit/8ad65d6fa39edc7fc1967e2df1f3db0aa7df4d11
Patch23: add-standalone-configuration-file-for-enabling-packa.patch
Patch22: add-standalone-configuration-file-for-enabling-packa.patch
#############
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/53159 (missing PR to master)
Patch24: batch.py-avoid-exception-when-minion-does-not-respon.patch
Patch23: batch.py-avoid-exception-when-minion-does-not-respon.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/177
# (deviation from upstream - we should probably port this)
Patch25: restore-default-behaviour-of-pkg-list-return.patch
Patch24: restore-default-behaviour-of-pkg-list-return.patch
# PATCH_FIX_OPENSUSE https://github.com/openSUSE/salt/pull/186 (missing upstream PR to master)
Patch26: read-repo-info-without-using-interpolation-bsc-11356.patch
Patch25: read-repo-info-without-using-interpolation-bsc-11356.patch
# PATCH_FIX_OPENSUSE https://github.com/openSUSE/salt/pull/191 (missing upstream PR to master)
Patch27: let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/56125 (merged but not in 3003: https://github.com/saltstack/salt/pull/59353)
Patch28: add-astra-linux-common-edition-to-the-os-family-list.patch
Patch26: let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch
# PATCH_FIX_OPENSUSE https://github.com/openSUSE/salt/commit/a8f0a15e4067ec278c8a2d690e3bf815523286ca (missing upstream PR)
Patch29: fix-wrong-test_mod_del_repo_multiline_values-test-af.patch
Patch27: fix-wrong-test_mod_del_repo_multiline_values-test-af.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/commit/a18ac47b75550bd55f4ca91dc221ed408881984c
Patch30: make-setup.py-script-to-not-require-setuptools-9.1.patch
Patch28: make-setup.py-script-to-not-require-setuptools-9.1.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/228 (missing upstream PR)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/61017
Patch31: adds-explicit-type-cast-for-port.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/57123
Patch32: prevent-logging-deadlock-on-salt-api-subprocesses-bs.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/229
# (no upstream PR, fixes tests locally)
Patch33: fix-a-test-and-some-variable-names-229.patch
Patch29: adds-explicit-type-cast-for-port.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/commit/da936daeebd701e147707ad814c07bfc259d4be (not yet upstream PR)
Patch34: add-publish_batch-to-clearfuncs-exposed-methods.patch
Patch30: add-publish_batch-to-clearfuncs-exposed-methods.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/57779
Patch35: info_installed-works-without-status-attr-now.patch
Patch31: info_installed-works-without-status-attr-now.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/58552
Patch36: zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch
Patch32: zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch
#### MICROOS - TRANSACTIONAL UPDATES ####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/58520 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60903
Patch37: support-transactional-systems-microos.patch
Patch33: support-transactional-systems-microos.patch
###########
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/275 (missing upstream PR)
Patch38: bsc-1176024-fix-file-directory-user-and-group-owners.patch
Patch34: bsc-1176024-fix-file-directory-user-and-group-owners.patch
#### NO VENDOR CHANGE ####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60421
Patch39: allow-vendor-change-option-with-zypper.patch
Patch35: allow-vendor-change-option-with-zypper.patch
###########
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/58784
Patch40: add-migrated-state-and-gpg-key-management-functions-.patch
Patch36: add-migrated-state-and-gpg-key-management-functions-.patch
### BEACON CONFIG ###
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/commit/5ea2f10b15684dd417bad858642faafc92cd382
# (revert https://github.com/saltstack/salt/pull/58655)
Patch41: revert-fixing-a-use-case-when-multiple-inotify-beaco.patch
Patch37: revert-fixing-a-use-case-when-multiple-inotify-beaco.patch
###########
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59269 (master PR merged but not included in 3003)
Patch42: fix-aptpkg.normalize_name-when-package-arch-is-all.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/298 (missing upstream PR)
Patch43: fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch
Patch38: fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/304 (missing uptstream PR)
Patch44: force-zyppnotify-to-prefer-packages.db-than-packages.patch
Patch39: force-zyppnotify-to-prefer-packages.db-than-packages.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59354 (master PR merged but not included in 3003)
Patch45: do-not-crash-when-unexpected-cmd-output-at-listing-p.patch
#### VIRT ENHANCEMENTS #####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59417 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59693 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60133 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60420 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60492 (master PR merged but not included in 3003)
Patch46: virt-enhancements.patch
##################
Patch40: do-not-crash-when-unexpected-cmd-output-at-listing-p.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/56173
Patch47: fixes-56144-to-enable-hotadd-profile-support.patch
Patch41: fixes-56144-to-enable-hotadd-profile-support.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/307 (missing upstream PR)
Patch48: add-sleep-on-exception-handling-on-minion-connection.patch
Patch42: add-sleep-on-exception-handling-on-minion-connection.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/323 (missing upstream PR)
Patch49: implementation-of-suse_ip-execution-module-bsc-10999.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59746 (master PR merged but not included in 3003)
Patch50: do-not-monkey-patch-yaml-bsc-1177474.patch
Patch43: implementation-of-suse_ip-execution-module-bsc-10999.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/347 (missing upstream PR)
Patch51: notify-beacon-for-debian-ubuntu-systems-347.patch
Patch44: notify-beacon-for-debian-ubuntu-systems-347.patch
### SALT-SSH PROCESSING TARGETS ###
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/336 (missing upstream PR)
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/353 (missing upstream PR)
Patch52: update-target-fix-for-salt-ssh-to-process-targets-li.patch
Patch45: update-target-fix-for-salt-ssh-to-process-targets-li.patch
############
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59687 (master PR merged but not included in 3003)
Patch53: add-alibaba-cloud-linux-2-by-backporting-upstream-s-.patch
#### ANSIBLE GATE IMPROVEMENTS ####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60056
Patch54: improvements-on-ansiblegate-module-354.patch
Patch46: improvements-on-ansiblegate-module-354.patch
##########
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/376 (missing upstream PR)
Patch55: check-if-dpkgnotify-is-executable-bsc-1186674-376.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/57881 (master PR merged but not included in 3003)
Patch56: parsing-epoch-out-of-version-provided-during-pkg-rem.patch
Patch47: check-if-dpkgnotify-is-executable-bsc-1186674-376.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/58503
Patch57: fix-missing-minion-returns-in-batch-mode-360.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60229 (master PR merged but not included in 3003)
Patch58: figure-out-python-interpreter-to-use-inside-containe.patch
Patch48: fix-missing-minion-returns-in-batch-mode-360.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60402
Patch59: enhance-logging-when-inotify-beacon-is-missing-pyino.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60358 (master PR merged but not included in 3003)
Patch60: fix-save-for-iptables-state-module-bsc-1185131-372.patch
Patch49: enhance-logging-when-inotify-beacon-is-missing-pyino.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60356
Patch61: fix-exception-in-yumpkg.remove-for-not-installed-pac.patch
Patch50: fix-exception-in-yumpkg.remove-for-not-installed-pac.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60432 (merged on master but not included in 3003)
Patch62: implementation-of-held-unheld-functions-for-state-pk.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59682 (master PR merged but not included in 3003)
Patch63: adding-preliminary-support-for-rocky.-59682-391.patch
Patch51: implementation-of-held-unheld-functions-for-state-pk.patch
#### OPENSCAP ENHANCE ####
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59756
Patch64: enhance-openscap-module-add-xccdf_eval-call-386.patch
Patch52: enhance-openscap-module-add-xccdf_eval-call-386.patch
###############
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60662 (master PR merged but not included in 3003)
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60688 (master PR merged but not included in 3003)
Patch65: better-handling-of-bad-public-keys-from-minions-bsc-.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60650 (master PR merged but not included in 3003)
Patch66: add-missing-aarch64-to-rpm-package-architectures-405.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/413 (missing upstream PR)
Patch67: don-t-use-shell-sbin-nologin-in-requisites.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60811 (master PR merged but not included in 3003)
Patch68: templates-move-the-globals-up-to-the-environment-jin.patch
Patch53: don-t-use-shell-sbin-nologin-in-requisites.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/59777
Patch69: 3003.3-postgresql-json-support-in-pillar-423.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60980
Patch70: do-not-break-master_tops-for-minion-with-version-low.patch
Patch54: 3003.3-postgresql-json-support-in-pillar-423.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/60983
Patch71: 3003.3-do-not-consider-skipped-targets-as-failed-for.patch
Patch55: 3003.3-do-not-consider-skipped-targets-as-failed-for.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/61017
Patch72: fix-crash-when-calling-manage.not_alive-runners.patch
Patch56: fix-crash-when-calling-manage.not_alive-runners.patch
# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/61014
Patch73: fix-issues-with-salt-ssh-s-extra-filerefs.patch
Patch57: fix-issues-with-salt-ssh-s-extra-filerefs.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61061
Patch74: fix-ip6_interface-grain-to-not-leak-secondary-ipv4-a.patch
Patch58: fix-ip6_interface-grain-to-not-leak-secondary-ipv4-a.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/432 (missing upstream PR)
Patch75: fix-traceback.print_exc-calls-for-test_pip_state-432.patch
Patch59: fix-traceback.print_exc-calls-for-test_pip_state-432.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/415 (missing upstream PR)
Patch76: prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch
Patch60: prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/60815
Patch77: add-rpm_vercmp-python-library-for-version-comparison.patch
Patch61: add-rpm_vercmp-python-library-for-version-comparison.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61180
Patch78: dnfnotify-pkgset-plugin-implementation-3002.2-450.patch
Patch62: dnfnotify-pkgset-plugin-implementation-3002.2-450.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/60324
Patch79: mock-ip_addrs-in-utils-minions.py-unit-test-443.patch
Patch63: mock-ip_addrs-in-utils-minions.py-unit-test-443.patch
# PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/456 (missing upstream PR)
Patch80: fix-the-regression-for-yumnotify-plugin-456.patch
Patch64: fix-the-regression-for-yumnotify-plugin-456.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61188
Patch81: refactor-and-improvements-for-transactional-updates-.patch
Patch65: refactor-and-improvements-for-transactional-updates-.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61189
Patch66: state.apply-don-t-check-for-cached-pillar-errors.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@ -729,87 +689,7 @@ list of active executors. This package add the configuration file.
cp %{S:1} .
cp %{S:5} ./.travis.yml
cp %{S:6} .
%patch1 -p1
%patch2 -p1
%patch3 -p1
%patch4 -p1
%patch5 -p1
%patch6 -p1
%patch7 -p1
%patch8 -p1
%patch9 -p1
%patch10 -p1
%patch11 -p1
%patch12 -p1
%patch13 -p1
%patch14 -p1
%patch15 -p1
%patch16 -p1
%patch17 -p1
%patch18 -p1
%patch19 -p1
%patch20 -p1
%patch21 -p1
%patch22 -p1
%patch23 -p1
%patch24 -p1
%patch25 -p1
%patch26 -p1
%patch27 -p1
%patch28 -p1
%patch29 -p1
%patch30 -p1
%patch31 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch52 -p1
%patch53 -p1
%patch54 -p1
%patch55 -p1
%patch56 -p1
%patch57 -p1
%patch58 -p1
%patch59 -p1
%patch60 -p1
%patch61 -p1
%patch62 -p1
%patch63 -p1
%patch64 -p1
%patch65 -p1
%patch66 -p1
%patch67 -p1
%patch68 -p1
%patch69 -p1
%patch70 -p1
%patch71 -p1
%patch72 -p1
%patch73 -p1
%patch74 -p1
%patch75 -p1
%patch76 -p1
%patch77 -p1
%patch78 -p1
%patch79 -p1
%patch80 -p1
%patch81 -p1
%autopatch -p1
%build
# Putting /usr/bin at the front of $PATH is needed for RHEL/RES 7. Without this
@ -973,7 +853,7 @@ install -Dpm 0644 pkg/suse/salt.SuSEfirewall2 %{buildroot}%{_sysconfdir}/syscon
install -Dpm 0644 pkg/salt.bash %{buildroot}%{_sysconfdir}/bash_completion.d/salt
%endif
%if %{with zsh_completion}
install -Dpm 0644 pkg/zsh_completion.zsh %{buildroot}%{_sysconfdir}/zsh_completion.d/salt
install -Dpm 0644 pkg/salt.zsh %{buildroot}%{_sysconfdir}/zsh_completion.d/salt
%endif
%if %{with fish_completion}

View File

@ -0,0 +1,362 @@
From 5880703551d82a68a0e2f3108878124d8ae98bf0 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 25 Jan 2022 17:20:55 +0100
Subject: [PATCH] state.apply: don't check for cached pillar errors
state.apply request new pillar data from the server. This done to always
have the most up-to-date pillar to work with. Previously, checking for
pillar errors looked at both the new pillar and the in-memory pillar.
The latter might contain pillar rendering errors even if the former does
not.
For this reason, only the new pillar should be checked, not both.
---
changelog/52354.fixed | 1 +
changelog/57180.fixed | 1 +
changelog/59339.fixed | 1 +
salt/modules/state.py | 17 ++-
.../modules/state/test_state_pillar_errors.py | 131 ++++++++++++++++++
.../pytests/unit/modules/state/test_state.py | 115 +++++----------
6 files changed, 177 insertions(+), 89 deletions(-)
create mode 100644 changelog/52354.fixed
create mode 100644 changelog/57180.fixed
create mode 100644 changelog/59339.fixed
create mode 100644 tests/pytests/integration/modules/state/test_state_pillar_errors.py
diff --git a/changelog/52354.fixed b/changelog/52354.fixed
new file mode 100644
index 0000000000..af885d77fa
--- /dev/null
+++ b/changelog/52354.fixed
@@ -0,0 +1 @@
+Don't check for cached pillar errors on state.apply
diff --git a/changelog/57180.fixed b/changelog/57180.fixed
new file mode 100644
index 0000000000..af885d77fa
--- /dev/null
+++ b/changelog/57180.fixed
@@ -0,0 +1 @@
+Don't check for cached pillar errors on state.apply
diff --git a/changelog/59339.fixed b/changelog/59339.fixed
new file mode 100644
index 0000000000..af885d77fa
--- /dev/null
+++ b/changelog/59339.fixed
@@ -0,0 +1 @@
+Don't check for cached pillar errors on state.apply
diff --git a/salt/modules/state.py b/salt/modules/state.py
index 0c3dfc3317..0027744229 100644
--- a/salt/modules/state.py
+++ b/salt/modules/state.py
@@ -106,18 +106,17 @@ def _set_retcode(ret, highstate=None):
def _get_pillar_errors(kwargs, pillar=None):
"""
- Checks all pillars (external and internal) for errors.
- Return an error message, if anywhere or None.
+ Check pillar for errors.
+
+ If a pillar is passed, it will be checked. Otherwise, the in-memory pillar
+ will checked instead. Passing kwargs['force'] = True short cuts the check
+ and always returns None, indicating no errors.
:param kwargs: dictionary of options
- :param pillar: external pillar
- :return: None or an error message
+ :param pillar: pillar
+ :return: None or a list of error messages
"""
- return (
- None
- if kwargs.get("force")
- else (pillar or {}).get("_errors", __pillar__.get("_errors")) or None
- )
+ return None if kwargs.get("force") else (pillar or __pillar__).get("_errors")
def _wait(jid):
diff --git a/tests/pytests/integration/modules/state/test_state_pillar_errors.py b/tests/pytests/integration/modules/state/test_state_pillar_errors.py
new file mode 100644
index 0000000000..af65a05945
--- /dev/null
+++ b/tests/pytests/integration/modules/state/test_state_pillar_errors.py
@@ -0,0 +1,131 @@
+#!/usr/bin/python3
+
+import textwrap
+
+import pytest
+from saltfactories.utils.functional import StateResult
+
+pytestmark = [
+ pytest.mark.slow_test,
+]
+
+
+@pytest.fixture(scope="module")
+def reset_pillar(salt_call_cli):
+ try:
+ # Run tests
+ yield
+ finally:
+ # Refresh pillar once all tests are done.
+ ret = salt_call_cli.run("saltutil.refresh_pillar", wait=True)
+ assert ret.exitcode == 0
+ assert ret.json is True
+
+
+@pytest.fixture
+def testfile_path(tmp_path, base_env_state_tree_root_dir):
+ testfile = tmp_path / "testfile"
+ sls_contents = textwrap.dedent(
+ """
+ {}:
+ file:
+ - managed
+ - source: salt://testfile
+ - makedirs: true
+ """.format(testfile)
+ )
+ with pytest.helpers.temp_file(
+ "sls-id-test.sls", sls_contents, base_env_state_tree_root_dir
+ ):
+ yield testfile
+
+
+@pytest.mark.usefixtures("testfile_path", "reset_pillar")
+def test_state_apply_aborts_on_pillar_error(
+ salt_cli,
+ salt_minion,
+ base_env_pillar_tree_root_dir,
+):
+ """
+ Test state.apply with error in pillar.
+ """
+ pillar_top_file = textwrap.dedent(
+ """
+ base:
+ '{}':
+ - basic
+ """
+ ).format(salt_minion.id)
+ basic_pillar_file = textwrap.dedent(
+ """
+ syntax_error
+ """
+ )
+
+ with pytest.helpers.temp_file(
+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir
+ ), pytest.helpers.temp_file(
+ "basic.sls", basic_pillar_file, base_env_pillar_tree_root_dir
+ ):
+ expected_comment = [
+ "Pillar failed to render with the following messages:",
+ "SLS 'basic' does not render to a dictionary",
+ ]
+ shell_result = salt_cli.run(
+ "state.apply", "sls-id-test", minion_tgt=salt_minion.id
+ )
+ assert shell_result.exitcode == 1
+ assert shell_result.json == expected_comment
+
+
+@pytest.mark.usefixtures("testfile_path", "reset_pillar")
+def test_state_apply_continues_after_pillar_error_is_fixed(
+ salt_cli,
+ salt_minion,
+ base_env_pillar_tree_root_dir,
+):
+ """
+ Test state.apply with error in pillar.
+ """
+ pillar_top_file = textwrap.dedent(
+ """
+ base:
+ '{}':
+ - basic
+ """.format(salt_minion.id)
+ )
+ basic_pillar_file_error = textwrap.dedent(
+ """
+ syntax_error
+ """
+ )
+ basic_pillar_file = textwrap.dedent(
+ """
+ syntax_error: Fixed!
+ """
+ )
+
+ # save pillar render error in minion's in-memory pillar
+ with pytest.helpers.temp_file(
+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir
+ ), pytest.helpers.temp_file(
+ "basic.sls", basic_pillar_file_error, base_env_pillar_tree_root_dir
+ ):
+ shell_result = salt_cli.run(
+ "saltutil.refresh_pillar", minion_tgt=salt_minion.id
+ )
+ assert shell_result.exitcode == 0
+
+ # run state.apply with fixed pillar render error
+ with pytest.helpers.temp_file(
+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir
+ ), pytest.helpers.temp_file(
+ "basic.sls", basic_pillar_file, base_env_pillar_tree_root_dir
+ ):
+ shell_result = salt_cli.run(
+ "state.apply", "sls-id-test", minion_tgt=salt_minion.id
+ )
+ assert shell_result.exitcode == 0
+ state_result = StateResult(shell_result.json)
+ assert state_result.result is True
+ assert state_result.changes == {"diff": "New file", "mode": "0644"}
diff --git a/tests/pytests/unit/modules/state/test_state.py b/tests/pytests/unit/modules/state/test_state.py
index 02fd2dd307..30cda303cc 100644
--- a/tests/pytests/unit/modules/state/test_state.py
+++ b/tests/pytests/unit/modules/state/test_state.py
@@ -1,14 +1,16 @@
"""
:codeauthor: Rahul Handay <rahulha@saltstack.com>
"""
-
import datetime
import logging
import os
+from collections import namedtuple
import pytest
+
import salt.config
import salt.loader
+import salt.loader.context
import salt.modules.config as config
import salt.modules.state as state
import salt.state
@@ -1200,85 +1202,6 @@ def test_lock_saltenv():
)
-def test_get_pillar_errors_CC():
- """
- Test _get_pillar_errors function.
- CC: External clean, Internal clean
- :return:
- """
- for int_pillar, ext_pillar in [
- ({"foo": "bar"}, {"fred": "baz"}),
- ({"foo": "bar"}, None),
- ({}, {"fred": "baz"}),
- ]:
- with patch("salt.modules.state.__pillar__", int_pillar):
- for opts, res in [
- ({"force": True}, None),
- ({"force": False}, None),
- ({}, None),
- ]:
- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar)
-
-
-def test_get_pillar_errors_EC():
- """
- Test _get_pillar_errors function.
- EC: External erroneous, Internal clean
- :return:
- """
- errors = ["failure", "everywhere"]
- for int_pillar, ext_pillar in [
- ({"foo": "bar"}, {"fred": "baz", "_errors": errors}),
- ({}, {"fred": "baz", "_errors": errors}),
- ]:
- with patch("salt.modules.state.__pillar__", int_pillar):
- for opts, res in [
- ({"force": True}, None),
- ({"force": False}, errors),
- ({}, errors),
- ]:
- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar)
-
-
-def test_get_pillar_errors_EE():
- """
- Test _get_pillar_errors function.
- CC: External erroneous, Internal erroneous
- :return:
- """
- errors = ["failure", "everywhere"]
- for int_pillar, ext_pillar in [
- ({"foo": "bar", "_errors": errors}, {"fred": "baz", "_errors": errors})
- ]:
- with patch("salt.modules.state.__pillar__", int_pillar):
- for opts, res in [
- ({"force": True}, None),
- ({"force": False}, errors),
- ({}, errors),
- ]:
- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar)
-
-
-def test_get_pillar_errors_CE():
- """
- Test _get_pillar_errors function.
- CC: External clean, Internal erroneous
- :return:
- """
- errors = ["failure", "everywhere"]
- for int_pillar, ext_pillar in [
- ({"foo": "bar", "_errors": errors}, {"fred": "baz"}),
- ({"foo": "bar", "_errors": errors}, None),
- ]:
- with patch("salt.modules.state.__pillar__", int_pillar):
- for opts, res in [
- ({"force": True}, None),
- ({"force": False}, errors),
- ({}, errors),
- ]:
- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar)
-
-
def test_event():
"""
test state.event runner
@@ -1318,3 +1241,35 @@ def test_event():
if _expected in x.args[0]:
found = True
assert found is True
+
+
+PillarPair = namedtuple("PillarPair", ["in_memory", "fresh"])
+pillar_combinations = [
+ (PillarPair({"foo": "bar"}, {"fred": "baz"}), None),
+ (PillarPair({"foo": "bar"}, {"fred": "baz", "_errors": ["Failure"]}), ["Failure"]),
+ (PillarPair({"foo": "bar"}, None), None),
+ (PillarPair({"foo": "bar", "_errors": ["Failure"]}, None), ["Failure"]),
+ (PillarPair({"foo": "bar", "_errors": ["Failure"]}, {"fred": "baz"}), None),
+]
+
+
+@pytest.mark.parametrize("pillar,expected_errors", pillar_combinations)
+def test_get_pillar_errors(pillar: PillarPair, expected_errors):
+ """
+ test _get_pillar_errors function
+
+ There are three cases to consider:
+ 1. kwargs['force'] is True -> None, no matter what's in pillar/__pillar__
+ 2. pillar kwarg is available -> only check pillar, no matter what's in __pillar__
+ 3. pillar kwarg is not available -> check __pillar__
+ """
+ ctx = salt.loader.context.LoaderContext()
+ named_ctx = ctx.named_context("__pillar__", pillar.in_memory)
+ with patch("salt.modules.state.__pillar__", named_ctx, create=True):
+ assert (
+ state._get_pillar_errors(kwargs={"force": True}, pillar=pillar.fresh)
+ is None
+ )
+ assert (
+ state._get_pillar_errors(kwargs={}, pillar=pillar.fresh) == expected_errors
+ )
--
2.34.1

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
From 74d5d84ada50609c60008d3160492c1f4a29d72d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 20 May 2019 11:59:39 +0100
From c3e73e4a9e0c81b5dca198fac5c49a1ae91c7111 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 17:12:04 +0100
Subject: [PATCH] Switch firewalld state to use change_interface
firewalld.present state allows to bind interface to given zone.
@ -14,296 +13,18 @@ zone to another.
This PR adds `firewalld.change_interface` call to firewalld module
and updates `firewalld.present` state to use this call.
---
salt/modules/firewalld.py | 100 ++++++++++++++++++++++----------------
salt/states/firewalld.py | 93 +++++++++++++++++------------------
2 files changed, 104 insertions(+), 89 deletions(-)
salt/modules/firewalld.py | 23 +++++++++++++++++++++++
salt/states/firewalld.py | 4 +++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/salt/modules/firewalld.py b/salt/modules/firewalld.py
index ca35568c3f..12808cb038 100644
index 135713d851..70bc738240 100644
--- a/salt/modules/firewalld.py
+++ b/salt/modules/firewalld.py
@@ -1,19 +1,14 @@
-# -*- coding: utf-8 -*-
"""
Support for firewalld.
.. versionadded:: 2015.2.0
"""
-# Import Python Libs
-from __future__ import absolute_import, print_function, unicode_literals
import logging
import re
import salt.utils.path
-
-# Import Salt Libs
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
@@ -36,7 +31,7 @@ def __firewall_cmd(cmd):
"""
Return the firewall-cmd location
"""
- firewall_cmd = "{0} {1}".format(salt.utils.path.which("firewall-cmd"), cmd)
+ firewall_cmd = "{} {}".format(salt.utils.path.which("firewall-cmd"), cmd)
out = __salt__["cmd.run_all"](firewall_cmd)
if out["retcode"] != 0:
@@ -44,7 +39,7 @@ def __firewall_cmd(cmd):
msg = out["stdout"]
else:
msg = out["stderr"]
- raise CommandExecutionError("firewall-cmd failed: {0}".format(msg))
+ raise CommandExecutionError("firewall-cmd failed: {}".format(msg))
return out["stdout"]
@@ -53,7 +48,7 @@ def __mgmt(name, _type, action):
Perform zone management
"""
# It's permanent because the 4 concerned functions need the permanent option, it's wrong without
- cmd = "--{0}-{1}={2} --permanent".format(action, _type, name)
+ cmd = "--{}-{}={} --permanent".format(action, _type, name)
return __firewall_cmd(cmd)
@@ -250,7 +245,7 @@ def set_default_zone(zone):
salt '*' firewalld.set_default_zone damian
"""
- return __firewall_cmd("--set-default-zone={0}".format(zone))
+ return __firewall_cmd("--set-default-zone={}".format(zone))
def new_service(name, restart=True):
@@ -327,7 +322,7 @@ def list_all(zone=None, permanent=True):
id_ = ""
if zone:
- cmd = "--zone={0} --list-all".format(zone)
+ cmd = "--zone={} --list-all".format(zone)
else:
cmd = "--list-all"
@@ -372,7 +367,7 @@ def list_services(zone=None, permanent=True):
salt '*' firewalld.list_services my_zone
"""
if zone:
- cmd = "--zone={0} --list-services".format(zone)
+ cmd = "--zone={} --list-services".format(zone)
else:
cmd = "--list-services"
@@ -399,9 +394,9 @@ def add_service(service, zone=None, permanent=True):
salt '*' firewalld.add_service ssh my_zone
"""
if zone:
- cmd = "--zone={0} --add-service={1}".format(zone, service)
+ cmd = "--zone={} --add-service={}".format(zone, service)
else:
- cmd = "--add-service={0}".format(service)
+ cmd = "--add-service={}".format(service)
if permanent:
cmd += " --permanent"
@@ -427,9 +422,9 @@ def remove_service(service, zone=None, permanent=True):
salt '*' firewalld.remove_service ssh dmz
"""
if zone:
- cmd = "--zone={0} --remove-service={1}".format(zone, service)
+ cmd = "--zone={} --remove-service={}".format(zone, service)
else:
- cmd = "--remove-service={0}".format(service)
+ cmd = "--remove-service={}".format(service)
if permanent:
cmd += " --permanent"
@@ -452,7 +447,7 @@ def add_service_port(service, port):
if service not in get_services(permanent=True):
raise CommandExecutionError("The service does not exist.")
- cmd = "--permanent --service={0} --add-port={1}".format(service, port)
+ cmd = "--permanent --service={} --add-port={}".format(service, port)
@@ -918,6 +918,29 @@ def remove_interface(zone, interface, permanent=True):
return __firewall_cmd(cmd)
@@ -471,7 +466,7 @@ def remove_service_port(service, port):
if service not in get_services(permanent=True):
raise CommandExecutionError("The service does not exist.")
- cmd = "--permanent --service={0} --remove-port={1}".format(service, port)
+ cmd = "--permanent --service={} --remove-port={}".format(service, port)
return __firewall_cmd(cmd)
@@ -487,7 +482,7 @@ def get_service_ports(service):
salt '*' firewalld.get_service_ports zone
"""
- cmd = "--permanent --service={0} --get-ports".format(service)
+ cmd = "--permanent --service={} --get-ports".format(service)
return __firewall_cmd(cmd).split()
@@ -503,7 +498,7 @@ def add_service_protocol(service, protocol):
salt '*' firewalld.add_service_protocol zone ssh
"""
- cmd = "--permanent --service={0} --add-protocol={1}".format(service, protocol)
+ cmd = "--permanent --service={} --add-protocol={}".format(service, protocol)
return __firewall_cmd(cmd)
@@ -519,7 +514,7 @@ def remove_service_protocol(service, protocol):
salt '*' firewalld.remove_service_protocol zone ssh
"""
- cmd = "--permanent --service={0} --remove-protocol={1}".format(service, protocol)
+ cmd = "--permanent --service={} --remove-protocol={}".format(service, protocol)
return __firewall_cmd(cmd)
@@ -535,7 +530,7 @@ def get_service_protocols(service):
salt '*' firewalld.get_service_protocols zone
"""
- cmd = "--permanent --service={0} --get-protocols".format(service)
+ cmd = "--permanent --service={} --get-protocols".format(service)
return __firewall_cmd(cmd).split()
@@ -578,7 +573,7 @@ def add_masquerade(zone=None, permanent=True):
salt '*' firewalld.add_masquerade dmz
"""
if zone:
- cmd = "--zone={0} --add-masquerade".format(zone)
+ cmd = "--zone={} --add-masquerade".format(zone)
else:
cmd = "--add-masquerade"
@@ -608,7 +603,7 @@ def remove_masquerade(zone=None, permanent=True):
salt '*' firewalld.remove_masquerade dmz
"""
if zone:
- cmd = "--zone={0} --remove-masquerade".format(zone)
+ cmd = "--zone={} --remove-masquerade".format(zone)
else:
cmd = "--remove-masquerade"
@@ -637,7 +632,7 @@ def add_port(zone, port, permanent=True, force_masquerade=False):
if force_masquerade and not get_masquerade(zone):
add_masquerade(zone)
- cmd = "--zone={0} --add-port={1}".format(zone, port)
+ cmd = "--zone={} --add-port={}".format(zone, port)
if permanent:
cmd += " --permanent"
@@ -657,7 +652,7 @@ def remove_port(zone, port, permanent=True):
salt '*' firewalld.remove_port internal 443/tcp
"""
- cmd = "--zone={0} --remove-port={1}".format(zone, port)
+ cmd = "--zone={} --remove-port={}".format(zone, port)
if permanent:
cmd += " --permanent"
@@ -677,7 +672,7 @@ def list_ports(zone, permanent=True):
salt '*' firewalld.list_ports
"""
- cmd = "--zone={0} --list-ports".format(zone)
+ cmd = "--zone={} --list-ports".format(zone)
if permanent:
cmd += " --permanent"
@@ -706,7 +701,7 @@ def add_port_fwd(
if force_masquerade and not get_masquerade(zone):
add_masquerade(zone)
- cmd = "--zone={0} --add-forward-port=port={1}:proto={2}:toport={3}:toaddr={4}".format(
+ cmd = "--zone={} --add-forward-port=port={}:proto={}:toport={}:toaddr={}".format(
zone, src, proto, dest, dstaddr
)
@@ -728,7 +723,7 @@ def remove_port_fwd(zone, src, dest, proto="tcp", dstaddr="", permanent=True):
salt '*' firewalld.remove_port_fwd public 80 443 tcp
"""
- cmd = "--zone={0} --remove-forward-port=port={1}:proto={2}:toport={3}:toaddr={4}".format(
+ cmd = "--zone={} --remove-forward-port=port={}:proto={}:toport={}:toaddr={}".format(
zone, src, proto, dest, dstaddr
)
@@ -752,7 +747,7 @@ def list_port_fwd(zone, permanent=True):
"""
ret = []
- cmd = "--zone={0} --list-forward-ports".format(zone)
+ cmd = "--zone={} --list-forward-ports".format(zone)
if permanent:
cmd += " --permanent"
@@ -792,7 +787,7 @@ def block_icmp(zone, icmp, permanent=True):
log.info("ICMP block already exists")
return "success"
- cmd = "--zone={0} --add-icmp-block={1}".format(zone, icmp)
+ cmd = "--zone={} --add-icmp-block={}".format(zone, icmp)
if permanent:
cmd += " --permanent"
@@ -820,7 +815,7 @@ def allow_icmp(zone, icmp, permanent=True):
log.info("ICMP Type is already permitted")
return "success"
- cmd = "--zone={0} --remove-icmp-block={1}".format(zone, icmp)
+ cmd = "--zone={} --remove-icmp-block={}".format(zone, icmp)
if permanent:
cmd += " --permanent"
@@ -840,7 +835,7 @@ def list_icmp_block(zone, permanent=True):
salt '*' firewlld.list_icmp_block zone
"""
- cmd = "--zone={0} --list-icmp-blocks".format(zone)
+ cmd = "--zone={} --list-icmp-blocks".format(zone)
if permanent:
cmd += " --permanent"
@@ -875,7 +870,7 @@ def get_interfaces(zone, permanent=True):
salt '*' firewalld.get_interfaces zone
"""
- cmd = "--zone={0} --list-interfaces".format(zone)
+ cmd = "--zone={} --list-interfaces".format(zone)
if permanent:
cmd += " --permanent"
@@ -898,7 +893,7 @@ def add_interface(zone, interface, permanent=True):
if interface in get_interfaces(zone, permanent):
log.info("Interface is already bound to zone.")
- cmd = "--zone={0} --add-interface={1}".format(zone, interface)
+ cmd = "--zone={} --add-interface={}".format(zone, interface)
if permanent:
cmd += " --permanent"
@@ -921,7 +916,30 @@ def remove_interface(zone, interface, permanent=True):
if interface not in get_interfaces(zone, permanent):
log.info("Interface is not bound to zone.")
- cmd = "--zone={0} --remove-interface={1}".format(zone, interface)
+ cmd = "--zone={} --remove-interface={}".format(zone, interface)
+
+ if permanent:
+ cmd += " --permanent"
+
+ return __firewall_cmd(cmd)
+
+
+def change_interface(zone, interface, permanent=True):
+ """
+ Change zone the interface bound to
@ -320,355 +41,21 @@ index ca35568c3f..12808cb038 100644
+ log.info("Interface is already bound to zone.")
+
+ cmd = "--zone={} --change-interface={}".format(zone, interface)
if permanent:
cmd += " --permanent"
@@ -941,7 +959,7 @@ def get_sources(zone, permanent=True):
salt '*' firewalld.get_sources zone
+
+ if permanent:
+ cmd += " --permanent"
+
+ return __firewall_cmd(cmd)
+
+
def get_sources(zone, permanent=True):
"""
- cmd = "--zone={0} --list-sources".format(zone)
+ cmd = "--zone={} --list-sources".format(zone)
if permanent:
cmd += " --permanent"
@@ -964,7 +982,7 @@ def add_source(zone, source, permanent=True):
if source in get_sources(zone, permanent):
log.info("Source is already bound to zone.")
- cmd = "--zone={0} --add-source={1}".format(zone, source)
+ cmd = "--zone={} --add-source={}".format(zone, source)
if permanent:
cmd += " --permanent"
@@ -987,7 +1005,7 @@ def remove_source(zone, source, permanent=True):
if source not in get_sources(zone, permanent):
log.info("Source is not bound to zone.")
- cmd = "--zone={0} --remove-source={1}".format(zone, source)
+ cmd = "--zone={} --remove-source={}".format(zone, source)
if permanent:
cmd += " --permanent"
@@ -1007,7 +1025,7 @@ def get_rich_rules(zone, permanent=True):
salt '*' firewalld.get_rich_rules zone
"""
- cmd = "--zone={0} --list-rich-rules".format(zone)
+ cmd = "--zone={} --list-rich-rules".format(zone)
if permanent:
cmd += " --permanent"
@@ -1027,7 +1045,7 @@ def add_rich_rule(zone, rule, permanent=True):
salt '*' firewalld.add_rich_rule zone 'rule'
"""
- cmd = "--zone={0} --add-rich-rule='{1}'".format(zone, rule)
+ cmd = "--zone={} --add-rich-rule='{}'".format(zone, rule)
if permanent:
cmd += " --permanent"
@@ -1047,7 +1065,7 @@ def remove_rich_rule(zone, rule, permanent=True):
salt '*' firewalld.remove_rich_rule zone 'rule'
"""
- cmd = "--zone={0} --remove-rich-rule='{1}'".format(zone, rule)
+ cmd = "--zone={} --remove-rich-rule='{}'".format(zone, rule)
if permanent:
cmd += " --permanent"
List sources bound to a zone
diff --git a/salt/states/firewalld.py b/salt/states/firewalld.py
index 4114e99f43..425defcfb1 100644
index cc6eaba5c3..534b9dd62d 100644
--- a/salt/states/firewalld.py
+++ b/salt/states/firewalld.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
Management of firewalld
@@ -76,21 +75,17 @@ would allow access to the salt master from the 10.0.0.0/8 subnet:
- 10.0.0.0/8
"""
-# Import Python Libs
-from __future__ import absolute_import, print_function, unicode_literals
import logging
import salt.utils.path
-
-# Import Salt Libs
from salt.exceptions import CommandExecutionError
from salt.output import nested
log = logging.getLogger(__name__)
-class ForwardingMapping(object):
+class ForwardingMapping:
"""
Represents a port forwarding statement mapping a local port to a remote
port for a specific protocol (TCP or UDP)
@@ -282,7 +277,7 @@ def service(name, ports=None, protocols=None):
try:
_current_ports = __salt__["firewalld.get_service_ports"](name)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_ports = set(ports) - set(_current_ports)
@@ -293,7 +288,7 @@ def service(name, ports=None, protocols=None):
try:
__salt__["firewalld.add_service_port"](name, port)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
for port in old_ports:
@@ -301,7 +296,7 @@ def service(name, ports=None, protocols=None):
try:
__salt__["firewalld.remove_service_port"](name, port)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_ports or old_ports:
@@ -312,7 +307,7 @@ def service(name, ports=None, protocols=None):
try:
_current_protocols = __salt__["firewalld.get_service_protocols"](name)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_protocols = set(protocols) - set(_current_protocols)
@@ -323,7 +318,7 @@ def service(name, ports=None, protocols=None):
try:
__salt__["firewalld.add_service_protocol"](name, protocol)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
for protocol in old_protocols:
@@ -331,7 +326,7 @@ def service(name, ports=None, protocols=None):
try:
__salt__["firewalld.remove_service_protocol"](name, protocol)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_protocols or old_protocols:
@@ -344,15 +339,15 @@ def service(name, ports=None, protocols=None):
ret["result"] = True
if ret["changes"] == {}:
- ret["comment"] = "'{0}' is already in the desired state.".format(name)
+ ret["comment"] = "'{}' is already in the desired state.".format(name)
return ret
if __opts__["test"]:
ret["result"] = None
- ret["comment"] = "Configuration for '{0}' will change.".format(name)
+ ret["comment"] = "Configuration for '{}' will change.".format(name)
return ret
- ret["comment"] = "'{0}' was configured.".format(name)
+ ret["comment"] = "'{}' was configured.".format(name)
return ret
@@ -385,7 +380,7 @@ def _present(
try:
zones = __salt__["firewalld.get_zones"](permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if name not in zones:
@@ -393,7 +388,7 @@ def _present(
try:
__salt__["firewalld.new_zone"](name)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
ret["changes"].update({name: {"old": zones, "new": name}})
@@ -408,14 +403,14 @@ def _present(
name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if block_icmp:
try:
_valid_icmp_types = __salt__["firewalld.get_icmp_types"](permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
# log errors for invalid ICMP types in block_icmp input
@@ -431,7 +426,7 @@ def _present(
name, icmp_type, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_block_icmp:
@@ -446,7 +441,7 @@ def _present(
name, icmp_type, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_icmp_types or old_icmp_types:
@@ -464,21 +459,21 @@ def _present(
try:
default_zone = __salt__["firewalld.default_zone"]()
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if name != default_zone:
if not __opts__["test"]:
try:
__salt__["firewalld.set_default_zone"](name)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
ret["changes"].update({"default": {"old": default_zone, "new": name}})
try:
masquerade_ret = __salt__["firewalld.get_masquerade"](name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if masquerade and not masquerade_ret:
@@ -486,7 +481,7 @@ def _present(
try:
__salt__["firewalld.add_masquerade"](name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
ret["changes"].update(
{"masquerade": {"old": "", "new": "Masquerading successfully set."}}
@@ -496,7 +491,7 @@ def _present(
try:
__salt__["firewalld.remove_masquerade"](name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
ret["changes"].update(
{"masquerade": {"old": "", "new": "Masquerading successfully " "disabled."}}
@@ -507,7 +502,7 @@ def _present(
try:
_current_ports = __salt__["firewalld.list_ports"](name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_ports = set(ports) - set(_current_ports)
@@ -520,7 +515,7 @@ def _present(
name, port, permanent=True, force_masquerade=False
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_ports:
@@ -530,7 +525,7 @@ def _present(
try:
__salt__["firewalld.remove_port"](name, port, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_ports or old_ports:
@@ -547,7 +542,7 @@ def _present(
name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
port_fwd = [_parse_forward(fwd) for fwd in port_fwd]
@@ -577,7 +572,7 @@ def _present(
force_masquerade=False,
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_port_fwd:
@@ -594,7 +589,7 @@ def _present(
permanent=True,
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_port_fwd or old_port_fwd:
@@ -618,7 +613,7 @@ def _present(
name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_services = set(services) - set(_current_services)
@@ -629,7 +624,7 @@ def _present(
try:
__salt__["firewalld.add_service"](new_service, name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_services:
@@ -641,7 +636,7 @@ def _present(
old_service, name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_services or old_services:
@@ -660,7 +655,7 @@ def _present(
name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_interfaces = set(interfaces) - set(_current_interfaces)
@@ -669,9 +664,11 @@ def _present(
@@ -691,7 +691,9 @@ def _present(
for interface in new_interfaces:
if not __opts__["test"]:
try:
@ -677,100 +64,9 @@ index 4114e99f43..425defcfb1 100644
+ name, interface, permanent=True
+ )
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
ret["comment"] = "Error: {}".format(err)
return ret
if prune_interfaces:
@@ -683,7 +680,7 @@ def _present(
name, interface, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_interfaces or old_interfaces:
@@ -700,7 +697,7 @@ def _present(
try:
_current_sources = __salt__["firewalld.get_sources"](name, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_sources = set(sources) - set(_current_sources)
@@ -711,7 +708,7 @@ def _present(
try:
__salt__["firewalld.add_source"](name, source, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_sources:
@@ -723,7 +720,7 @@ def _present(
name, source, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_sources or old_sources:
@@ -742,7 +739,7 @@ def _present(
name, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
new_rich_rules = set(rich_rules) - set(_current_rich_rules)
@@ -753,7 +750,7 @@ def _present(
try:
__salt__["firewalld.add_rich_rule"](name, rich_rule, permanent=True)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if prune_rich_rules:
@@ -765,7 +762,7 @@ def _present(
name, rich_rule, permanent=True
)
except CommandExecutionError as err:
- ret["comment"] = "Error: {0}".format(err)
+ ret["comment"] = "Error: {}".format(err)
return ret
if new_rich_rules or old_rich_rules:
@@ -780,7 +777,7 @@ def _present(
# No changes
if ret["changes"] == {}:
ret["result"] = True
- ret["comment"] = "'{0}' is already in the desired state.".format(name)
+ ret["comment"] = "'{}' is already in the desired state.".format(name)
return ret
# test=True and changes predicted
@@ -789,7 +786,7 @@ def _present(
# build comment string
nested.__opts__ = __opts__
comment = []
- comment.append("Configuration for '{0}' will change:".format(name))
+ comment.append("Configuration for '{}' will change:".format(name))
comment.append(nested.output(ret["changes"]).rstrip())
ret["comment"] = "\n".join(comment)
ret["changes"] = {}
@@ -797,5 +794,5 @@ def _present(
# Changes were made successfully
ret["result"] = True
- ret["comment"] = "'{0}' was configured.".format(name)
+ ret["comment"] = "'{}' was configured.".format(name)
return ret
--
2.29.2
2.34.1

View File

@ -1,113 +0,0 @@
From 4664c4b31fdef9ef5b3987b9d993ccba2675d18f Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Tue, 31 Aug 2021 11:20:49 +0200
Subject: [PATCH] templates: move the globals up to the Environment
(Jinja2 3.0.0) (#418)
* jinja: fix TemplateNotFound missing name
The TemplateNotFound exception requires a parameter, name, that is
missing in one of the calls.
File "/usr/lib/python3.8/site-packages/salt/utils/jinja.py", line 158, in get_source
raise TemplateNotFound
TypeError: __init__() missing 1 required positional argument: 'name'
This patch add the missing parameter in the raise call.
Signed-off-by: Alberto Planas <aplanas@suse.com>
* templates: move the globals up to the Environment
When creating a Jinja2 environment, we populate the globals in the
Template object that we generate from the environment. This cause a
problem when there is a {% include "./file.sls" %} in the template, as
cannot find in the environment globals information like the "tpldir",
for example, making the relative path to be unresolved.
Seems that in Jinja2 2.X this behaviour is not present, so attaching the
globals to the Template will make the include to work, but since Jinja2
3.0.0 this is not the case. Maybe related with the re-architecture from
https://github.com/pallets/jinja/issues/295
This patch populate the globals in the Environment level, making this
and other variables reachable by the Jinja templates.
Fix #55159
Signed-off-by: Alberto Planas <aplanas@suse.com>
---
changelog/55159.fixed | 1 +
salt/utils/jinja.py | 2 +-
salt/utils/templates.py | 3 ++-
tests/unit/utils/test_jinja.py | 16 ++++++++++++++++
4 files changed, 20 insertions(+), 2 deletions(-)
create mode 100644 changelog/55159.fixed
diff --git a/changelog/55159.fixed b/changelog/55159.fixed
new file mode 100644
index 0000000000..6ee1a78366
--- /dev/null
+++ b/changelog/55159.fixed
@@ -0,0 +1 @@
+Jinja renderer resolves wrong relative paths when importing subdirectories
diff --git a/salt/utils/jinja.py b/salt/utils/jinja.py
index 68a8646474..3f27c2c7e1 100644
--- a/salt/utils/jinja.py
+++ b/salt/utils/jinja.py
@@ -148,7 +148,7 @@ class SaltCacheLoader(BaseLoader):
'Relative path "%s" cannot be resolved without an environment',
template,
)
- raise TemplateNotFound
+ raise TemplateNotFound(template)
base_path = environment.globals["tpldir"]
_template = os.path.normpath("/".join((base_path, _template)))
if _template.split("/", 1)[0] == "..":
diff --git a/salt/utils/templates.py b/salt/utils/templates.py
index 0f705cfa37..4c59553bc8 100644
--- a/salt/utils/templates.py
+++ b/salt/utils/templates.py
@@ -494,9 +494,10 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None):
SLS_ENCODING,
)
decoded_context[key] = salt.utils.data.decode(value)
+
+ jinja_env.globals.update(decoded_context)
try:
template = jinja_env.from_string(tmplstr)
- template.globals.update(decoded_context)
output = template.render(**decoded_context)
except jinja2.exceptions.UndefinedError as exc:
trace = traceback.extract_tb(sys.exc_info()[2])
diff --git a/tests/unit/utils/test_jinja.py b/tests/unit/utils/test_jinja.py
index fb67e17fa2..e23caf11ae 100644
--- a/tests/unit/utils/test_jinja.py
+++ b/tests/unit/utils/test_jinja.py
@@ -619,6 +619,22 @@ class TestGetTemplate(TestCase):
dict(opts=self.local_opts, saltenv="test", salt=self.local_salt),
)
+ def test_relative_include(self):
+ template = "{% include './hello_import' %}"
+ expected = "Hey world !a b !"
+ filename = os.path.join(self.template_dir, "hello_import")
+ with salt.utils.files.fopen(filename) as fp_:
+ out = render_jinja_tmpl(
+ template,
+ dict(
+ opts=self.local_opts,
+ saltenv="test",
+ salt=self.local_salt,
+ tpldir=self.template_dir,
+ ),
+ )
+ self.assertEqual(out, expected)
+
class TestJinjaDefaultOptions(TestCase):
@classmethod
--
2.33.0

View File

@ -1,4 +1,4 @@
From eb51c650e39359851588b611a0802d06eedeb5b5 Mon Sep 17 00:00:00 2001
From 74d3d43d09c692ba41138278f34d2a2e2ef83dd8 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
@ -14,10 +14,10 @@ Regression fix of salt-ssh on processing targets (#353)
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index a4a74aa2c2..409d6e740e 100644
index 564d622ab5..37faa869bc 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -325,7 +325,7 @@ class SSH:
@@ -327,7 +327,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", "")
@ -26,7 +26,7 @@ index a4a74aa2c2..409d6e740e 100644
user, hostname = hostname.split("@", 1)
else:
user = self.opts.get("ssh_user")
@@ -376,7 +376,7 @@ class SSH:
@@ -378,7 +378,7 @@ class SSH:
self.__parsed_rosters[self.ROSTER_UPDATE_FLAG] = False
return
@ -35,8 +35,8 @@ index a4a74aa2c2..409d6e740e 100644
"""
Update default flat roster with the passed in information.
:return:
@@ -391,8 +391,8 @@ class SSH:
"\n passwd: {passwd}\n".format(
@@ -392,8 +392,8 @@ class SSH:
" host: {hostname}\n user: {user}\n passwd: {passwd}\n".format(
s_user=getpass.getuser(),
s_time=datetime.datetime.utcnow().isoformat(),
- hostname=self.opts.get("tgt", ""),
@ -46,7 +46,7 @@ index a4a74aa2c2..409d6e740e 100644
passwd=self.opts.get("ssh_passwd", ""),
)
)
@@ -409,20 +409,32 @@ class SSH:
@@ -410,20 +410,32 @@ class SSH:
Uptade targets in case hostname was directly passed without the roster.
:return:
"""
@ -93,6 +93,6 @@ index a4a74aa2c2..409d6e740e 100644
def get_pubkey(self):
"""
--
2.33.0
2.34.1

View File

@ -1,6 +1,6 @@
From db2573bebc90f6e1b445c34ddd707ad547c4325a Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Sat, 28 Jul 2018 22:59:04 +0200
From 466b188b52b064cbdda6cf3efa73da3861be8307 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 16:36:57 +0100
Subject: [PATCH] Use Adler32 algorithm to compute string checksums
Generate the same numeric value across all Python versions and platforms
@ -20,24 +20,24 @@ Move server_id deprecation warning to reduce log spamming (bsc#1135567) (bsc#113
Remove deprecated warning that breaks miniion execution when "server_id_use_crc" opts are missing
---
salt/config/__init__.py | 4 ++++
salt/grains/core.py | 49 +++++++++++++++++++++++++++++++++++++----
2 files changed, 49 insertions(+), 4 deletions(-)
salt/grains/core.py | 48 +++++++++++++++++++++++++++++++++++++----
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/salt/config/__init__.py b/salt/config/__init__.py
index e63489cbce..e05cdfafda 100644
index 97a7fce2f0..2c42290598 100644
--- a/salt/config/__init__.py
+++ b/salt/config/__init__.py
@@ -953,6 +953,9 @@ VALID_OPTS = immutabletypes.freeze(
# Feature flag config
"features": dict,
"fips_mode": bool,
@@ -957,6 +957,9 @@ VALID_OPTS = immutabletypes.freeze(
# The port to be used when checking if a master is connected to a
# minion
"remote_minions_port": int,
+ # Use Adler32 hashing algorithm for server_id (default False until Sodium, "adler32" after)
+ # Possible values are: False, adler32, crc32
+ "server_id_use_crc": (bool, str),
}
)
@@ -1256,6 +1259,7 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze(
@@ -1260,6 +1263,7 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze(
"disabled_requisites": [],
"reactor_niceness": None,
"fips_mode": False,
@ -46,7 +46,7 @@ index e63489cbce..e05cdfafda 100644
)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index fdf0a6f0d8..e007f40c92 100644
index 1077e64a11..dd0bd346b2 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -21,6 +21,7 @@ import subprocess
@ -57,15 +57,7 @@ index fdf0a6f0d8..e007f40c92 100644
from errno import EACCES, EPERM
import distro
@@ -40,6 +41,7 @@ import salt.utils.path
import salt.utils.pkg.rpm
import salt.utils.platform
import salt.utils.stringutils
+import salt.utils.versions
from salt.ext.six.moves import range
from salt.utils.network import _get_interfaces
@@ -2981,6 +2983,36 @@ def _hw_data(osdata):
@@ -3017,6 +3018,36 @@ def _hw_data(osdata):
return grains
@ -102,7 +94,7 @@ index fdf0a6f0d8..e007f40c92 100644
def get_server_id():
"""
Provides an integer based on the FQDN of a machine.
@@ -2991,10 +3023,19 @@ def get_server_id():
@@ -3027,10 +3058,19 @@ def get_server_id():
# server_id
if salt.utils.platform.is_proxy():
@ -127,6 +119,6 @@ index fdf0a6f0d8..e007f40c92 100644
def get_master():
--
2.33.0
2.34.1

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0cbc8ae5ac9f075d430df256be438ab3a3f34082f1afab41df12fc34f04be413
size 16093920

3
v3004.tar.gz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fad2322cfef1a28351ef2cb645fcf7441502864326b63bb20d54d9bde97cf565
size 17761294

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
From e16881c36b535c4798d0bfda089efd9323957fec Mon Sep 17 00:00:00 2001
From: Florian Bergmann <bergmannf@users.noreply.github.com>
Date: Fri, 14 Sep 2018 10:30:39 +0200
From da47028898edb69290f989d9f99973969d6a8652 Mon Sep 17 00:00:00 2001
From: Alexander Graul <agraul@suse.com>
Date: Tue, 18 Jan 2022 16:38:17 +0100
Subject: [PATCH] X509 fixes (#111)
* Return proper content type for the x509 certificate
@ -37,59 +37,17 @@ Fix for log checking in x509 test
We are logging in debug and not in trace mode here.
---
salt/modules/publish.py | 17 +++---
salt/modules/x509.py | 100 ++++++++++++++++----------------
salt/states/x509.py | 74 +++++++++++++++++++++--
tests/unit/modules/test_x509.py | 6 +-
4 files changed, 131 insertions(+), 66 deletions(-)
salt/modules/publish.py | 2 +
salt/modules/x509.py | 93 ++++++++++++++++-----------------
salt/states/x509.py | 74 ++++++++++++++++++++++++--
tests/unit/modules/test_x509.py | 6 +--
4 files changed, 121 insertions(+), 54 deletions(-)
diff --git a/salt/modules/publish.py b/salt/modules/publish.py
index 0926f3fa13..6d56c4d08e 100644
index f9b7e8b168..651119906e 100644
--- a/salt/modules/publish.py
+++ b/salt/modules/publish.py
@@ -1,15 +1,10 @@
-# -*- coding: utf-8 -*-
"""
Publish a command from a minion to a target
"""
-from __future__ import absolute_import, print_function, unicode_literals
import logging
-
-# Import python libs
import time
-# Import salt libs
import salt.crypt
import salt.payload
import salt.transport.client
@@ -93,13 +88,13 @@ def _publish(
matching_master_uris = [
master
for master in __opts__["master_uri_list"]
- if "//{0}:".format(via_master) in master
+ if "//{}:".format(via_master) in master
]
if not matching_master_uris:
raise SaltInvocationError(
- "Could not find match for {0} in \
- list of configured masters {1} when using `via_master` option".format(
+ "Could not find match for {} in \
+ list of configured masters {} when using `via_master` option".format(
via_master, __opts__["master_uri_list"]
)
)
@@ -143,7 +138,7 @@ def _publish(
try:
peer_data = channel.send(load)
except SaltReqTimeoutError:
- return "'{0}' publish timed out".format(fun)
+ return "'{}' publish timed out".format(fun)
if not peer_data:
return {}
# CLI args are passed as strings, re-cast to keep time.sleep happy
@@ -198,6 +193,8 @@ def _publish(
@@ -196,6 +196,8 @@ def _publish(
else:
return ret
@ -98,14 +56,8 @@ index 0926f3fa13..6d56c4d08e 100644
def publish(
tgt, fun, arg=None, tgt_type="glob", returner="", timeout=5, via_master=None
@@ -347,4 +344,4 @@ def runner(fun, arg=None, timeout=5):
try:
return channel.send(load)
except SaltReqTimeoutError:
- return "'{0}' runner publish timed out".format(fun)
+ return "'{}' runner publish timed out".format(fun)
diff --git a/salt/modules/x509.py b/salt/modules/x509.py
index 43a134625f..d8e6ae3baa 100644
index 0909bace48..261b794295 100644
--- a/salt/modules/x509.py
+++ b/salt/modules/x509.py
@@ -30,16 +30,13 @@ from salt.utils.odict import OrderedDict
@ -186,7 +138,7 @@ index 43a134625f..d8e6ae3baa 100644
for nid_num, nid_name, val in sorted(ret_list):
ret[nid_name] = val
return ret
@@ -536,8 +535,8 @@ def get_pem_entries(glob_path):
@@ -537,8 +536,8 @@ def get_pem_entries(glob_path):
if os.path.isfile(path):
try:
ret[path] = get_pem_entry(text=path)
@ -197,7 +149,7 @@ index 43a134625f..d8e6ae3baa 100644
return ret
@@ -615,8 +614,8 @@ def read_certificates(glob_path):
@@ -616,8 +615,8 @@ def read_certificates(glob_path):
if os.path.isfile(path):
try:
ret[path] = read_certificate(certificate=path)
@ -208,7 +160,7 @@ index 43a134625f..d8e6ae3baa 100644
return ret
@@ -646,10 +645,9 @@ def read_csr(csr):
@@ -647,10 +646,9 @@ def read_csr(csr):
"Subject": _parse_subject(csr.get_subject()),
"Subject Hash": _dec2hex(csr.get_subject().as_hash()),
"Public Key Hash": hashlib.sha1(csr.get_pubkey().get_modulus()).hexdigest(),
@ -220,7 +172,7 @@ index 43a134625f..d8e6ae3baa 100644
return ret
@@ -959,7 +957,7 @@ def create_crl(
@@ -960,7 +958,7 @@ def create_crl(
# pyOpenSSL Note due to current limitations in pyOpenSSL it is impossible
# to specify a digest For signing the CRL. This will hopefully be fixed
# soon: https://github.com/pyca/pyopenssl/pull/161
@ -229,18 +181,7 @@ index 43a134625f..d8e6ae3baa 100644
raise salt.exceptions.SaltInvocationError(
"Could not load OpenSSL module, OpenSSL unavailable"
)
@@ -1033,7 +1031,9 @@ def create_crl(
crltext = crl.export(**export_kwargs)
except (TypeError, ValueError):
log.warning(
- "Error signing crl with specified digest. Are you using pyopenssl 0.15 or newer? The default md5 digest will be used."
+ "Error signing crl with specified digest. "
+ "Are you using pyopenssl 0.15 or newer? "
+ "The default md5 digest will be used."
)
export_kwargs.pop("digest", None)
crltext = crl.export(**export_kwargs)
@@ -1109,6 +1109,7 @@ def get_signing_policy(signing_policy_name):
@@ -1111,6 +1109,7 @@ def get_signing_policy(signing_policy_name):
signing_policy = _get_signing_policy(signing_policy_name)
if not signing_policy:
return "Signing policy {} does not exist.".format(signing_policy_name)
@ -248,7 +189,7 @@ index 43a134625f..d8e6ae3baa 100644
if isinstance(signing_policy, list):
dict_ = {}
for item in signing_policy:
@@ -1125,7 +1126,7 @@ def get_signing_policy(signing_policy_name):
@@ -1127,7 +1126,7 @@ def get_signing_policy(signing_policy_name):
signing_policy["signing_cert"], "CERTIFICATE"
)
except KeyError:
@ -257,17 +198,7 @@ index 43a134625f..d8e6ae3baa 100644
return signing_policy
@@ -1734,7 +1735,8 @@ def create_csr(path=None, text=False, **kwargs):
if "private_key" not in kwargs and "public_key" in kwargs:
kwargs["private_key"] = kwargs["public_key"]
log.warning(
- "OpenSSL no longer allows working with non-signed CSRs. A private_key must be specified. Attempting to use public_key as private_key"
+ "OpenSSL no longer allows working with non-signed CSRs. "
+ "A private_key must be specified. Attempting to use public_key as private_key"
)
if "private_key" not in kwargs:
@@ -1758,7 +1760,8 @@ def create_csr(path=None, text=False, **kwargs):
@@ -1761,7 +1760,8 @@ def create_csr(path=None, text=False, **kwargs):
)
)
@ -277,7 +208,7 @@ index 43a134625f..d8e6ae3baa 100644
if entry in kwargs:
setattr(subject, entry, kwargs[entry])
@@ -1794,7 +1797,6 @@ def create_csr(path=None, text=False, **kwargs):
@@ -1797,7 +1797,6 @@ def create_csr(path=None, text=False, **kwargs):
extstack.push(ext)
csr.add_extensions(extstack)
@ -285,7 +216,7 @@ index 43a134625f..d8e6ae3baa 100644
csr.sign(
_get_private_key_obj(
kwargs["private_key"], passphrase=kwargs["private_key_passphrase"]
@@ -1802,10 +1804,11 @@ def create_csr(path=None, text=False, **kwargs):
@@ -1805,10 +1804,11 @@ def create_csr(path=None, text=False, **kwargs):
kwargs["algorithm"],
)
@ -301,7 +232,7 @@ index 43a134625f..d8e6ae3baa 100644
def verify_private_key(private_key, public_key, passphrase=None):
@@ -1830,7 +1833,7 @@ def verify_private_key(private_key, public_key, passphrase=None):
@@ -1833,7 +1833,7 @@ def verify_private_key(private_key, public_key, passphrase=None):
salt '*' x509.verify_private_key private_key=/etc/pki/myca.key \\
public_key=/etc/pki/myca.crt
"""
@ -310,7 +241,7 @@ index 43a134625f..d8e6ae3baa 100644
def verify_signature(
@@ -1886,7 +1889,10 @@ def verify_crl(crl, cert):
@@ -1889,7 +1889,10 @@ def verify_crl(crl, cert):
salt '*' x509.verify_crl crl=/etc/pki/myca.crl cert=/etc/pki/myca.crt
"""
if not salt.utils.path.which("openssl"):
@ -322,7 +253,7 @@ index 43a134625f..d8e6ae3baa 100644
crltext = _text_or_file(crl)
crltext = get_pem_entry(crltext, pem_type="X509 CRL")
crltempfile = tempfile.NamedTemporaryFile(delete=True)
@@ -1908,10 +1914,7 @@ def verify_crl(crl, cert):
@@ -1911,10 +1914,7 @@ def verify_crl(crl, cert):
crltempfile.close()
certtempfile.close()
@ -334,7 +265,7 @@ index 43a134625f..d8e6ae3baa 100644
def expired(certificate):
@@ -1949,8 +1952,9 @@ def expired(certificate):
@@ -1952,8 +1952,9 @@ def expired(certificate):
ret["expired"] = True
else:
ret["expired"] = False
@ -346,7 +277,7 @@ index 43a134625f..d8e6ae3baa 100644
return ret
@@ -1973,6 +1977,7 @@ def will_expire(certificate, days):
@@ -1976,6 +1977,7 @@ def will_expire(certificate, days):
salt '*' x509.will_expire "/etc/pki/mycert.crt" days=30
"""
@ -354,7 +285,7 @@ index 43a134625f..d8e6ae3baa 100644
ret = {}
if os.path.isfile(certificate):
@@ -1986,14 +1991,11 @@ def will_expire(certificate, days):
@@ -1989,14 +1991,11 @@ def will_expire(certificate, days):
_expiration_date = cert.get_not_after().get_datetime()
ret["cn"] = _parse_subject(cert.get_subject())["CN"]
@ -376,7 +307,7 @@ index 43a134625f..d8e6ae3baa 100644
return ret
diff --git a/salt/states/x509.py b/salt/states/x509.py
index 80e1ecdd6d..3a54ad3ba3 100644
index b3d2f978bd..16811bcfb8 100644
--- a/salt/states/x509.py
+++ b/salt/states/x509.py
@@ -177,11 +177,12 @@ import os
@ -402,7 +333,7 @@ index 80e1ecdd6d..3a54ad3ba3 100644
def _revoked_to_list(revs):
@@ -683,7 +684,70 @@ def certificate_managed(name, days_remaining=90, append_certs=None, **kwargs):
@@ -682,7 +683,70 @@ def certificate_managed(name, days_remaining=90, append_certs=None, **kwargs):
"Old": invalid_reason,
"New": "Certificate will be valid and up to date",
}
@ -474,7 +405,7 @@ index 80e1ecdd6d..3a54ad3ba3 100644
contents = __salt__["x509.create_certificate"](text=True, **kwargs)
# Check the module actually returned a cert and not an error message as a string
@@ -879,6 +943,8 @@ def pem_managed(name, text, backup=False, **kwargs):
@@ -878,6 +942,8 @@ def pem_managed(name, text, backup=False, **kwargs):
Any arguments supported by :py:func:`file.managed <salt.states.file.managed>` are supported.
"""
file_args, kwargs = _get_file_args(name, **kwargs)
@ -485,7 +416,7 @@ index 80e1ecdd6d..3a54ad3ba3 100644
return __states__["file.managed"](**file_args)
diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py
index 20ca0d679a..8fa799437d 100644
index 8f4c433b1a..3105290a2c 100644
--- a/tests/unit/modules/test_x509.py
+++ b/tests/unit/modules/test_x509.py
@@ -118,9 +118,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
@ -502,6 +433,6 @@ index 20ca0d679a..8fa799437d 100644
@skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable")
def test_get_pem_entry(self):
--
2.33.0
2.34.1

View File

@ -1,4 +1,4 @@
From 071139f7f1456ac6de6543418d848a01bce62c29 Mon Sep 17 00:00:00 2001
From 48306a830d37e64b5275f48e25c315e658ee37e6 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Mon, 5 Oct 2020 16:24:16 +0200
Subject: [PATCH] zypperpkg: ignore retcode 104 for search()
@ -6,14 +6,14 @@ Subject: [PATCH] zypperpkg: ignore retcode 104 for search()
---
salt/modules/zypperpkg.py | 28 ++++++---
tests/unit/modules/test_zypperpkg.py | 93 +++++++++++++++++++++-------
2 files changed, 93 insertions(+), 28 deletions(-)
tests/unit/modules/test_zypperpkg.py | 89 +++++++++++++++++++++-------
2 files changed, 90 insertions(+), 27 deletions(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 3ee21ddbe5..1777bec031 100644
index c7228bf712..4af29652d9 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -92,6 +92,8 @@ class _Zypper:
@@ -99,6 +99,8 @@ class _Zypper:
}
LOCK_EXIT_CODE = 7
@ -22,7 +22,7 @@ index 3ee21ddbe5..1777bec031 100644
XML_DIRECTIVES = ["-x", "--xmlout"]
# ZYPPER_LOCK is not affected by --root
ZYPPER_LOCK = "/var/run/zypp.pid"
@@ -122,6 +124,7 @@ class _Zypper:
@@ -129,6 +131,7 @@ class _Zypper:
self.__no_raise = False
self.__refresh = False
self.__ignore_repo_failure = False
@ -30,7 +30,7 @@ index 3ee21ddbe5..1777bec031 100644
self.__systemd_scope = False
self.__root = None
@@ -141,6 +144,9 @@ class _Zypper:
@@ -148,6 +151,9 @@ class _Zypper:
# Ignore exit code for 106 (repo is not available)
if "no_repo_failure" in kwargs:
self.__ignore_repo_failure = kwargs["no_repo_failure"]
@ -40,7 +40,7 @@ index 3ee21ddbe5..1777bec031 100644
if "systemd_scope" in kwargs:
self.__systemd_scope = kwargs["systemd_scope"]
if "root" in kwargs:
@@ -299,6 +305,10 @@ class _Zypper:
@@ -306,6 +312,10 @@ class _Zypper:
if self.__root:
self.__cmd.extend(["--root", self.__root])
@ -51,7 +51,7 @@ index 3ee21ddbe5..1777bec031 100644
self.__cmd.extend(args)
kwargs["output_loglevel"] = "trace"
kwargs["python_shell"] = False
@@ -436,9 +446,11 @@ class Wildcard:
@@ -447,9 +457,11 @@ class Wildcard:
Get available versions of the package.
:return:
"""
@ -66,7 +66,7 @@ index 3ee21ddbe5..1777bec031 100644
if not solvables:
raise CommandExecutionError(
"No packages found matching '{}'".format(self.name)
@@ -1043,7 +1055,7 @@ def list_repo_pkgs(*args, **kwargs):
@@ -1054,7 +1066,7 @@ def list_repo_pkgs(*args, **kwargs):
root = kwargs.get("root") or None
for node in (
@ -75,7 +75,7 @@ index 3ee21ddbe5..1777bec031 100644
.xml.call("se", "-s", *targets)
.getElementsByTagName("solvable")
):
@@ -2422,7 +2434,9 @@ def owner(*paths, **kwargs):
@@ -2431,7 +2443,9 @@ def owner(*paths, **kwargs):
def _get_visible_patterns(root=None):
"""Get all available patterns in the repo that are visible."""
patterns = {}
@ -86,7 +86,7 @@ index 3ee21ddbe5..1777bec031 100644
for element in search_patterns.getElementsByTagName("solvable"):
installed = element.getAttribute("status") == "installed"
patterns[element.getAttribute("name")] = {
@@ -2619,7 +2633,7 @@ def search(criteria, refresh=False, **kwargs):
@@ -2628,7 +2642,7 @@ def search(criteria, refresh=False, **kwargs):
cmd.append(criteria)
solvables = (
@ -95,7 +95,7 @@ index 3ee21ddbe5..1777bec031 100644
.nolock.noraise.xml.call(*cmd)
.getElementsByTagName("solvable")
)
@@ -2871,7 +2885,7 @@ def _get_patches(installed_only=False, root=None):
@@ -2880,7 +2894,7 @@ def _get_patches(installed_only=False, root=None):
"""
patches = {}
for element in (
@ -105,28 +105,19 @@ index 3ee21ddbe5..1777bec031 100644
.getElementsByTagName("solvable")
):
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index 919dbb9737..0ba5595d65 100644
index 47fca906a7..671adc2779 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -3,6 +3,8 @@
"""
+import configparser
+import io
import os
from xml.dom import minidom
@@ -14,7 +16,7 @@ from salt.exceptions import CommandExecutionError
from salt.ext import six
from salt.ext.six.moves import configparser
@@ -14,7 +14,7 @@ import salt.utils.files
import salt.utils.pkg
from salt.exceptions import CommandExecutionError
from tests.support.mixins import LoaderModuleMockMixin
-from tests.support.mock import MagicMock, Mock, call, patch
+from tests.support.mock import MagicMock, Mock, call, mock_open, patch
from tests.support.unit import TestCase
@@ -27,7 +29,10 @@ class ZyppCallMock:
@@ -27,7 +27,10 @@ class ZyppCallMock:
def __call__(self, *args, **kwargs):
# If the call is for a configuration modifier, we return self
@ -138,16 +129,7 @@ index 919dbb9737..0ba5595d65 100644
return self
return MagicMock(return_value=self.__return_value)()
@@ -1516,7 +1521,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
"""
repos_cfg = configparser.ConfigParser()
for cfg in ["zypper-repo-1.cfg", "zypper-repo-2.cfg"]:
- repos_cfg.readfp(six.moves.StringIO(get_test_data(cfg)))
+ repos_cfg.readfp(io.StringIO(get_test_data(cfg)))
for alias in repos_cfg.sections():
r_info = zypper._get_repo_info(alias, repos_cfg=repos_cfg)
@@ -1782,8 +1787,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1801,8 +1804,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="installed" name="libzypp" kind="package" edition="16.2.4-19.5" arch="x86_64" repository="(System Packages)"/>
</solvable-list></search-result></stream>
"""
@ -159,7 +141,7 @@ index 919dbb9737..0ba5595d65 100644
wcard = zypper.Wildcard(_zpr)
wcard.name, wcard.version = "libzypp", "*"
assert wcard._get_scope_versions(wcard._get_available_versions()) == [
@@ -1805,8 +1811,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1824,8 +1828,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
</solvable-list></search-result></stream>
"""
@ -171,7 +153,7 @@ index 919dbb9737..0ba5595d65 100644
wcard = zypper.Wildcard(_zpr)
wcard.name, wcard.version = "libzypp", "16.2.*-2*"
assert wcard._get_scope_versions(wcard._get_available_versions()) == [
@@ -1827,8 +1834,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1846,8 +1851,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
</solvable-list></search-result></stream>
"""
@ -183,7 +165,7 @@ index 919dbb9737..0ba5595d65 100644
wcard = zypper.Wildcard(_zpr)
wcard.name, wcard.version = "libzypp", "16.2.5*"
assert wcard._get_scope_versions(wcard._get_available_versions()) == [
@@ -1848,8 +1856,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1867,8 +1873,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
</solvable-list></search-result></stream>
"""
@ -195,7 +177,7 @@ index 919dbb9737..0ba5595d65 100644
wcard = zypper.Wildcard(_zpr)
wcard.name, wcard.version = "libzypp", "*.1"
assert wcard._get_scope_versions(wcard._get_available_versions()) == [
@@ -1870,8 +1879,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1889,8 +1896,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
</solvable-list></search-result></stream>
"""
@ -207,7 +189,7 @@ index 919dbb9737..0ba5595d65 100644
assert zypper.Wildcard(_zpr)("libzypp", "16.2.4*") == "16.2.4-19.5"
assert zypper.Wildcard(_zpr)("libzypp", "16.2*") == "16.2.5-25.1"
assert zypper.Wildcard(_zpr)("libzypp", "*6-*") == "17.2.6-27.9.1"
@@ -1890,8 +1900,10 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1909,8 +1917,10 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
</solvable-list></search-result></stream>
"""
@ -220,7 +202,7 @@ index 919dbb9737..0ba5595d65 100644
assert zypper.Wildcard(_zpr)("libzypp", None) is None
def test_wildcard_to_query_typecheck(self):
@@ -1907,8 +1919,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1926,8 +1936,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
</solvable-list></search-result></stream>
"""
@ -232,7 +214,7 @@ index 919dbb9737..0ba5595d65 100644
assert isinstance(zypper.Wildcard(_zpr)("libzypp", "*.1"), str)
def test_wildcard_to_query_condition_preservation(self):
@@ -1924,8 +1937,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1943,8 +1954,9 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
</solvable-list></search-result></stream>
"""
@ -244,7 +226,7 @@ index 919dbb9737..0ba5595d65 100644
for op in zypper.Wildcard.Z_OP:
assert zypper.Wildcard(_zpr)(
@@ -1951,8 +1965,10 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -1970,8 +1982,10 @@ Repository 'DUMMY' not found by its alias, number, or URI.
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
</solvable-list></search-result></stream>
"""
@ -257,7 +239,7 @@ index 919dbb9737..0ba5595d65 100644
with self.assertRaises(CommandExecutionError):
for op in [">>", "==", "<<", "+"]:
zypper.Wildcard(_zpr)("libzypp", "{}*.1".format(op))
@@ -2044,3 +2060,38 @@ pattern() = package-c"""
@@ -2063,3 +2077,38 @@ pattern() = package-c"""
with patch("salt.modules.zypperpkg.__zypper__", zypper_mock):
assert zypper.services_need_restart() == expected
zypper_mock(root=None).nolock.call.assert_called_with("ps", "-sss")
@ -297,6 +279,6 @@ index 919dbb9737..0ba5595d65 100644
+ env={"ZYPP_READONLY_HACK": "1"},
+ )
--
2.33.0
2.34.1