Accepting request 1103320 from systemsmanagement:saltstack
OBS-URL: https://build.opensuse.org/request/show/1103320 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=138
This commit is contained in:
commit
e5d36cd92f
71
3006.0-prevent-_pygit2.giterror-error-loading-known_.patch
Normal file
71
3006.0-prevent-_pygit2.giterror-error-loading-known_.patch
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
From 40a57afc65e71835127a437248ed655404cff0e8 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Tue, 27 Jun 2023 11:24:39 +0100
|
||||||
|
Subject: [PATCH] 3006.0: Prevent _pygit2.GitError: error loading
|
||||||
|
known_hosts when $HOME is not set (bsc#1210994) (#588)
|
||||||
|
|
||||||
|
* Prevent _pygit2.GitError: error loading known_hosts when $HOME is not set
|
||||||
|
|
||||||
|
* Add unit test to cover case of unset home
|
||||||
|
---
|
||||||
|
salt/utils/gitfs.py | 5 +++++
|
||||||
|
tests/unit/utils/test_gitfs.py | 14 ++++++++++++++
|
||||||
|
2 files changed, 19 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/salt/utils/gitfs.py b/salt/utils/gitfs.py
|
||||||
|
index cc9895d8ab..38e84f38aa 100644
|
||||||
|
--- a/salt/utils/gitfs.py
|
||||||
|
+++ b/salt/utils/gitfs.py
|
||||||
|
@@ -34,6 +34,7 @@ import salt.utils.stringutils
|
||||||
|
import salt.utils.url
|
||||||
|
import salt.utils.user
|
||||||
|
import salt.utils.versions
|
||||||
|
+import salt.syspaths
|
||||||
|
from salt.config import DEFAULT_MASTER_OPTS as _DEFAULT_MASTER_OPTS
|
||||||
|
from salt.exceptions import FileserverConfigError, GitLockError, get_error_message
|
||||||
|
from salt.utils.event import tagify
|
||||||
|
@@ -1867,6 +1868,10 @@ class Pygit2(GitProvider):
|
||||||
|
# pruning only available in pygit2 >= 0.26.2
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
+ # Make sure $HOME env variable is set to prevent
|
||||||
|
+ # _pygit2.GitError: error loading known_hosts in some libgit2 versions.
|
||||||
|
+ if "HOME" not in os.environ:
|
||||||
|
+ os.environ["HOME"] = salt.syspaths.HOME_DIR
|
||||||
|
fetch_results = origin.fetch(**fetch_kwargs)
|
||||||
|
except GitError as exc: # pylint: disable=broad-except
|
||||||
|
exc_str = get_error_message(exc).lower()
|
||||||
|
diff --git a/tests/unit/utils/test_gitfs.py b/tests/unit/utils/test_gitfs.py
|
||||||
|
index b99da3ef91..7c400b69af 100644
|
||||||
|
--- a/tests/unit/utils/test_gitfs.py
|
||||||
|
+++ b/tests/unit/utils/test_gitfs.py
|
||||||
|
@@ -14,6 +14,7 @@ import salt.utils.gitfs
|
||||||
|
import salt.utils.platform
|
||||||
|
import tests.support.paths
|
||||||
|
from salt.exceptions import FileserverConfigError
|
||||||
|
+from tests.support.helpers import patched_environ
|
||||||
|
from tests.support.mixins import AdaptedConfigurationTestCaseMixin
|
||||||
|
from tests.support.mock import MagicMock, patch
|
||||||
|
from tests.support.unit import TestCase
|
||||||
|
@@ -335,3 +336,16 @@ class TestPygit2(TestCase):
|
||||||
|
self.assertIn(provider.cachedir, provider.checkout())
|
||||||
|
provider.branch = "does_not_exist"
|
||||||
|
self.assertIsNone(provider.checkout())
|
||||||
|
+
|
||||||
|
+ def test_checkout_with_home_env_unset(self):
|
||||||
|
+ remote = os.path.join(tests.support.paths.TMP, "pygit2-repo")
|
||||||
|
+ cache = os.path.join(tests.support.paths.TMP, "pygit2-repo-cache")
|
||||||
|
+ self._prepare_remote_repository(remote)
|
||||||
|
+ provider = self._prepare_cache_repository(remote, cache)
|
||||||
|
+ provider.remotecallbacks = None
|
||||||
|
+ provider.credentials = None
|
||||||
|
+ with patched_environ(__cleanup__=["HOME"]):
|
||||||
|
+ self.assertTrue("HOME" not in os.environ)
|
||||||
|
+ provider.init_remote()
|
||||||
|
+ provider.fetch()
|
||||||
|
+ self.assertTrue("HOME" in os.environ)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
@ -1 +1 @@
|
|||||||
2c8ae68c3fb161fd84005ed1b58abf7865ba646f
|
26c7f283aef34794887afd5a4199be1018c5c592
|
47
avoid-conflicts-with-dependencies-versions-bsc-12116.patch
Normal file
47
avoid-conflicts-with-dependencies-versions-bsc-12116.patch
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
From 8e9f2587aea52c1d0a5c07d5f9bb77a23ae4d4a6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Tue, 23 May 2023 10:40:02 +0100
|
||||||
|
Subject: [PATCH] Avoid conflicts with dependencies versions
|
||||||
|
(bsc#1211612) (#581)
|
||||||
|
|
||||||
|
This commit fixes the Salt requirements file that are used to
|
||||||
|
generate the "requires.txt" file that is included in Salt egginfo
|
||||||
|
in order to be consistent with the installed packages
|
||||||
|
of Salt dependencies.
|
||||||
|
|
||||||
|
This prevents issues when resolving and validating Salt dependencies
|
||||||
|
with "pkg_resources" Python module.
|
||||||
|
---
|
||||||
|
requirements/base.txt | 2 +-
|
||||||
|
requirements/zeromq.txt | 2 +-
|
||||||
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/requirements/base.txt b/requirements/base.txt
|
||||||
|
index c19d8804a2..437aa01d31 100644
|
||||||
|
--- a/requirements/base.txt
|
||||||
|
+++ b/requirements/base.txt
|
||||||
|
@@ -6,7 +6,7 @@ MarkupSafe
|
||||||
|
requests>=1.0.0
|
||||||
|
distro>=1.0.1
|
||||||
|
psutil>=5.0.0
|
||||||
|
-packaging>=21.3
|
||||||
|
+packaging>=17.1
|
||||||
|
looseversion
|
||||||
|
# We need contextvars for salt-ssh
|
||||||
|
contextvars
|
||||||
|
diff --git a/requirements/zeromq.txt b/requirements/zeromq.txt
|
||||||
|
index 1e9a815c1b..23d1ef25dc 100644
|
||||||
|
--- a/requirements/zeromq.txt
|
||||||
|
+++ b/requirements/zeromq.txt
|
||||||
|
@@ -1,5 +1,5 @@
|
||||||
|
-r base.txt
|
||||||
|
-r crypto.txt
|
||||||
|
|
||||||
|
-pyzmq>=20.0.0
|
||||||
|
+pyzmq>=17.1.2
|
||||||
|
pyzmq==25.0.2 ; sys_platform == "win32"
|
||||||
|
--
|
||||||
|
2.39.2
|
||||||
|
|
||||||
|
|
39
define-__virtualname__-for-transactional_update-modu.patch
Normal file
39
define-__virtualname__-for-transactional_update-modu.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
From f02e97df14e4927efbb5ddd3a2bbc5a650330b9e Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Fri, 26 May 2023 16:50:51 +0100
|
||||||
|
Subject: [PATCH] Define __virtualname__ for transactional_update module
|
||||||
|
(#582)
|
||||||
|
|
||||||
|
This prevent problems with LazyLoader when importing this module,
|
||||||
|
which was wrongly exposing functions for this module under "state.*"
|
||||||
|
---
|
||||||
|
salt/modules/transactional_update.py | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/transactional_update.py b/salt/modules/transactional_update.py
|
||||||
|
index 6493966782..658ebccc6b 100644
|
||||||
|
--- a/salt/modules/transactional_update.py
|
||||||
|
+++ b/salt/modules/transactional_update.py
|
||||||
|
@@ -285,6 +285,8 @@ from salt.modules.state import _check_queue, _prior_running_states, _wait, runni
|
||||||
|
|
||||||
|
__func_alias__ = {"apply_": "apply"}
|
||||||
|
|
||||||
|
+__virtualname__ = "transactional_update"
|
||||||
|
+
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -300,7 +302,7 @@ def __virtual__():
|
||||||
|
_prior_running_states, globals()
|
||||||
|
)
|
||||||
|
running = salt.utils.functools.namespaced_function(running, globals())
|
||||||
|
- return True
|
||||||
|
+ return __virtualname__
|
||||||
|
else:
|
||||||
|
return (False, "Module transactional_update requires a transactional system")
|
||||||
|
|
||||||
|
--
|
||||||
|
2.39.2
|
||||||
|
|
||||||
|
|
253
fix-regression-multiple-values-for-keyword-argument-.patch
Normal file
253
fix-regression-multiple-values-for-keyword-argument-.patch
Normal file
@ -0,0 +1,253 @@
|
|||||||
|
From c25c8081ded775f3574b0bc999d809ce14701ba5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Thu, 3 Aug 2023 10:07:28 +0100
|
||||||
|
Subject: [PATCH] Fix regression: multiple values for keyword argument
|
||||||
|
'saltenv' (bsc#1212844) (#590)
|
||||||
|
|
||||||
|
* fix passing wrong keyword arguments to cp.cache_file in pkg.installed with sources
|
||||||
|
|
||||||
|
* Drop `**kwargs` usage and be explicit about the supported keyword arguments.
|
||||||
|
|
||||||
|
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
|
||||||
|
|
||||||
|
* Add regression test for https://github.com/saltstack/salt/issues/64118
|
||||||
|
|
||||||
|
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
|
||||||
|
|
||||||
|
* Add changelog file
|
||||||
|
|
||||||
|
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
|
||||||
|
Co-authored-by: Massimiliano Torromeo <massimiliano.torromeo@gmail.com>
|
||||||
|
Co-authored-by: Pedro Algarvio <palgarvio@vmware.com>
|
||||||
|
---
|
||||||
|
changelog/64118.fixed.md | 1 +
|
||||||
|
salt/modules/win_pkg.py | 25 +++++++-----
|
||||||
|
salt/states/pkg.py | 4 +-
|
||||||
|
tests/pytests/unit/modules/test_win_pkg.py | 2 +-
|
||||||
|
tests/pytests/unit/states/test_pkg.py | 46 +++++++++++++++++++---
|
||||||
|
5 files changed, 62 insertions(+), 16 deletions(-)
|
||||||
|
create mode 100644 changelog/64118.fixed.md
|
||||||
|
|
||||||
|
diff --git a/changelog/64118.fixed.md b/changelog/64118.fixed.md
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..e7251827e9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/changelog/64118.fixed.md
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Stop passing `**kwargs` and be explicit about the keyword arguments to pass, namely, to `cp.cache_file` call in `salt.states.pkg`
|
||||||
|
diff --git a/salt/modules/win_pkg.py b/salt/modules/win_pkg.py
|
||||||
|
index 3aa7c7919a..e80dd19322 100644
|
||||||
|
--- a/salt/modules/win_pkg.py
|
||||||
|
+++ b/salt/modules/win_pkg.py
|
||||||
|
@@ -1298,7 +1298,7 @@ def _repo_process_pkg_sls(filename, short_path_name, ret, successful_verbose):
|
||||||
|
successful_verbose[short_path_name] = []
|
||||||
|
|
||||||
|
|
||||||
|
-def _get_source_sum(source_hash, file_path, saltenv, **kwargs):
|
||||||
|
+def _get_source_sum(source_hash, file_path, saltenv, verify_ssl=True):
|
||||||
|
"""
|
||||||
|
Extract the hash sum, whether it is in a remote hash file, or just a string.
|
||||||
|
"""
|
||||||
|
@@ -1315,7 +1315,7 @@ def _get_source_sum(source_hash, file_path, saltenv, **kwargs):
|
||||||
|
# The source_hash is a file on a server
|
||||||
|
try:
|
||||||
|
cached_hash_file = __salt__["cp.cache_file"](
|
||||||
|
- source_hash, saltenv, verify_ssl=kwargs.get("verify_ssl", True)
|
||||||
|
+ source_hash, saltenv=saltenv, verify_ssl=verify_ssl
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
log.exception("Failed to cache %s", source_hash, exc_info=exc)
|
||||||
|
@@ -1671,7 +1671,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
||||||
|
try:
|
||||||
|
cached_file = __salt__["cp.cache_file"](
|
||||||
|
cache_file,
|
||||||
|
- saltenv,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
@@ -1686,7 +1686,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
||||||
|
try:
|
||||||
|
cached_file = __salt__["cp.cache_file"](
|
||||||
|
cache_file,
|
||||||
|
- saltenv,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
@@ -1706,7 +1706,9 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
||||||
|
# It's not cached. Cache it, mate.
|
||||||
|
try:
|
||||||
|
cached_pkg = __salt__["cp.cache_file"](
|
||||||
|
- installer, saltenv, verify_ssl=kwargs.get("verify_ssl", True)
|
||||||
|
+ installer,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
+ verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
msg = "Failed to cache {}".format(installer)
|
||||||
|
@@ -1730,7 +1732,7 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
||||||
|
try:
|
||||||
|
cached_pkg = __salt__["cp.cache_file"](
|
||||||
|
installer,
|
||||||
|
- saltenv,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
@@ -1754,7 +1756,12 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
|
||||||
|
# Compare the hash sums
|
||||||
|
source_hash = pkginfo[version_num].get("source_hash", False)
|
||||||
|
if source_hash:
|
||||||
|
- source_sum = _get_source_sum(source_hash, cached_pkg, saltenv, **kwargs)
|
||||||
|
+ source_sum = _get_source_sum(
|
||||||
|
+ source_hash,
|
||||||
|
+ cached_pkg,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
+ verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
+ )
|
||||||
|
log.debug(
|
||||||
|
"pkg.install: Source %s hash: %s",
|
||||||
|
source_sum["hash_type"],
|
||||||
|
@@ -2126,7 +2133,7 @@ def remove(name=None, pkgs=None, **kwargs):
|
||||||
|
try:
|
||||||
|
cached_pkg = __salt__["cp.cache_file"](
|
||||||
|
uninstaller,
|
||||||
|
- saltenv,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
@@ -2150,7 +2157,7 @@ def remove(name=None, pkgs=None, **kwargs):
|
||||||
|
try:
|
||||||
|
cached_pkg = __salt__["cp.cache_file"](
|
||||||
|
uninstaller,
|
||||||
|
- saltenv,
|
||||||
|
+ saltenv=saltenv,
|
||||||
|
verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except MinionError as exc:
|
||||||
|
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
|
||||||
|
index 12fbc87a1a..a605b23107 100644
|
||||||
|
--- a/salt/states/pkg.py
|
||||||
|
+++ b/salt/states/pkg.py
|
||||||
|
@@ -760,7 +760,9 @@ def _find_install_targets(
|
||||||
|
err = "Unable to cache {0}: {1}"
|
||||||
|
try:
|
||||||
|
cached_path = __salt__["cp.cache_file"](
|
||||||
|
- version_string, saltenv=kwargs["saltenv"], **kwargs
|
||||||
|
+ version_string,
|
||||||
|
+ saltenv=kwargs["saltenv"],
|
||||||
|
+ verify_ssl=kwargs.get("verify_ssl", True),
|
||||||
|
)
|
||||||
|
except CommandExecutionError as exc:
|
||||||
|
problems.append(err.format(version_string, exc))
|
||||||
|
diff --git a/tests/pytests/unit/modules/test_win_pkg.py b/tests/pytests/unit/modules/test_win_pkg.py
|
||||||
|
index 76234fb77e..6d435f00a5 100644
|
||||||
|
--- a/tests/pytests/unit/modules/test_win_pkg.py
|
||||||
|
+++ b/tests/pytests/unit/modules/test_win_pkg.py
|
||||||
|
@@ -262,7 +262,7 @@ def test_pkg_install_verify_ssl_false():
|
||||||
|
result = win_pkg.install(name="nsis", version="3.02", verify_ssl=False)
|
||||||
|
mock_cp.assert_called_once_with(
|
||||||
|
"http://download.sourceforge.net/project/nsis/NSIS%203/3.02/nsis-3.02-setup.exe",
|
||||||
|
- "base",
|
||||||
|
+ saltenv="base",
|
||||||
|
verify_ssl=False,
|
||||||
|
)
|
||||||
|
assert expected == result
|
||||||
|
diff --git a/tests/pytests/unit/states/test_pkg.py b/tests/pytests/unit/states/test_pkg.py
|
||||||
|
index b852f27b00..f58be11011 100644
|
||||||
|
--- a/tests/pytests/unit/states/test_pkg.py
|
||||||
|
+++ b/tests/pytests/unit/states/test_pkg.py
|
||||||
|
@@ -3,6 +3,7 @@ import logging
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import salt.modules.beacons as beaconmod
|
||||||
|
+import salt.modules.cp as cp
|
||||||
|
import salt.modules.pkg_resource as pkg_resource
|
||||||
|
import salt.modules.yumpkg as yumpkg
|
||||||
|
import salt.states.beacon as beaconstate
|
||||||
|
@@ -15,19 +16,28 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
-def configure_loader_modules():
|
||||||
|
+def configure_loader_modules(minion_opts):
|
||||||
|
return {
|
||||||
|
+ cp: {
|
||||||
|
+ "__opts__": minion_opts,
|
||||||
|
+ },
|
||||||
|
pkg: {
|
||||||
|
"__env__": "base",
|
||||||
|
"__salt__": {},
|
||||||
|
"__grains__": {"os": "CentOS", "os_family": "RedHat"},
|
||||||
|
- "__opts__": {"test": False, "cachedir": ""},
|
||||||
|
+ "__opts__": minion_opts,
|
||||||
|
"__instance_id__": "",
|
||||||
|
"__low__": {},
|
||||||
|
"__utils__": {"state.gen_tag": state_utils.gen_tag},
|
||||||
|
},
|
||||||
|
- beaconstate: {"__salt__": {}, "__opts__": {}},
|
||||||
|
- beaconmod: {"__salt__": {}, "__opts__": {}},
|
||||||
|
+ beaconstate: {
|
||||||
|
+ "__salt__": {},
|
||||||
|
+ "__opts__": minion_opts,
|
||||||
|
+ },
|
||||||
|
+ beaconmod: {
|
||||||
|
+ "__salt__": {},
|
||||||
|
+ "__opts__": minion_opts,
|
||||||
|
+ },
|
||||||
|
pkg_resource: {
|
||||||
|
"__salt__": {},
|
||||||
|
"__grains__": {"os": "CentOS", "os_family": "RedHat"},
|
||||||
|
@@ -35,7 +45,7 @@ def configure_loader_modules():
|
||||||
|
yumpkg: {
|
||||||
|
"__salt__": {},
|
||||||
|
"__grains__": {"osarch": "x86_64", "osmajorrelease": 7},
|
||||||
|
- "__opts__": {},
|
||||||
|
+ "__opts__": minion_opts,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -563,6 +573,32 @@ def test_installed_with_changes_test_true(list_pkgs):
|
||||||
|
assert ret["changes"] == expected
|
||||||
|
|
||||||
|
|
||||||
|
+def test_installed_with_sources(list_pkgs, tmp_path):
|
||||||
|
+ """
|
||||||
|
+ Test pkg.installed with passing `sources`
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ list_pkgs = MagicMock(return_value=list_pkgs)
|
||||||
|
+ pkg_source = tmp_path / "pkga-package-0.3.0.deb"
|
||||||
|
+
|
||||||
|
+ with patch.dict(
|
||||||
|
+ pkg.__salt__,
|
||||||
|
+ {
|
||||||
|
+ "cp.cache_file": cp.cache_file,
|
||||||
|
+ "pkg.list_pkgs": list_pkgs,
|
||||||
|
+ "pkg_resource.pack_sources": pkg_resource.pack_sources,
|
||||||
|
+ "lowpkg.bin_pkg_info": MagicMock(),
|
||||||
|
+ },
|
||||||
|
+ ), patch("salt.fileclient.get_file_client", return_value=MagicMock()):
|
||||||
|
+ try:
|
||||||
|
+ ret = pkg.installed("install-pkgd", sources=[{"pkga": str(pkg_source)}])
|
||||||
|
+ assert ret["result"] is False
|
||||||
|
+ except TypeError as exc:
|
||||||
|
+ if "got multiple values for keyword argument 'saltenv'" in str(exc):
|
||||||
|
+ pytest.fail(f"TypeError should have not been raised: {exc}")
|
||||||
|
+ raise exc from None
|
||||||
|
+
|
||||||
|
+
|
||||||
|
@pytest.mark.parametrize("action", ["removed", "purged"])
|
||||||
|
def test_removed_purged_with_changes_test_true(list_pkgs, action):
|
||||||
|
"""
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
118
fix-some-issues-detected-in-salt-support-cli-module-.patch
Normal file
118
fix-some-issues-detected-in-salt-support-cli-module-.patch
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
From 38de9af6bd243d35464713e0ee790255d3b40a7e Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Fri, 23 Jun 2023 13:02:51 +0100
|
||||||
|
Subject: [PATCH] Fix some issues detected in "salt-support" CLI, module
|
||||||
|
and tests (bsc#1211591) (#580)
|
||||||
|
|
||||||
|
* saltsupport: avoid debug traceback due missing import
|
||||||
|
|
||||||
|
* Use yaml and json wrappers provides by Salt utils
|
||||||
|
|
||||||
|
* Remove unnecessary call to deprecated setup_logfile_logger
|
||||||
|
|
||||||
|
* Move unittest saltsupport tests to proper place
|
||||||
|
|
||||||
|
* Fix test assertion error due wrong capturing of message
|
||||||
|
---
|
||||||
|
salt/cli/support/__init__.py | 4 ++--
|
||||||
|
salt/cli/support/collector.py | 6 ++----
|
||||||
|
tests/{pytests => }/unit/cli/test_support.py | 0
|
||||||
|
tests/unit/modules/test_saltsupport.py | 6 +++---
|
||||||
|
4 files changed, 7 insertions(+), 9 deletions(-)
|
||||||
|
rename tests/{pytests => }/unit/cli/test_support.py (100%)
|
||||||
|
|
||||||
|
diff --git a/salt/cli/support/__init__.py b/salt/cli/support/__init__.py
|
||||||
|
index 59c2609e07..0a7da72e93 100644
|
||||||
|
--- a/salt/cli/support/__init__.py
|
||||||
|
+++ b/salt/cli/support/__init__.py
|
||||||
|
@@ -6,7 +6,7 @@ import os
|
||||||
|
|
||||||
|
import jinja2
|
||||||
|
import salt.exceptions
|
||||||
|
-import yaml
|
||||||
|
+import salt.utils.yaml
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@@ -48,7 +48,7 @@ def get_profile(profile, caller, runner):
|
||||||
|
try:
|
||||||
|
rendered_template = _render_profile(profile_path, caller, runner)
|
||||||
|
log.debug("\n{d}\n{t}\n{d}\n".format(d="-" * 80, t=rendered_template))
|
||||||
|
- data.update(yaml.load(rendered_template))
|
||||||
|
+ data.update(salt.utils.yaml.load(rendered_template))
|
||||||
|
except Exception as ex:
|
||||||
|
log.debug(ex, exc_info=True)
|
||||||
|
raise salt.exceptions.SaltException(
|
||||||
|
diff --git a/salt/cli/support/collector.py b/salt/cli/support/collector.py
|
||||||
|
index 1879cc5220..0ba987580c 100644
|
||||||
|
--- a/salt/cli/support/collector.py
|
||||||
|
+++ b/salt/cli/support/collector.py
|
||||||
|
@@ -1,6 +1,5 @@
|
||||||
|
import builtins as exceptions
|
||||||
|
import copy
|
||||||
|
-import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
@@ -16,10 +15,10 @@ import salt.cli.support.intfunc
|
||||||
|
import salt.cli.support.localrunner
|
||||||
|
import salt.defaults.exitcodes
|
||||||
|
import salt.exceptions
|
||||||
|
-import salt.ext.six as six
|
||||||
|
import salt.output.table_out
|
||||||
|
import salt.runner
|
||||||
|
import salt.utils.files
|
||||||
|
+import salt.utils.json
|
||||||
|
import salt.utils.parsers
|
||||||
|
import salt.utils.platform
|
||||||
|
import salt.utils.process
|
||||||
|
@@ -169,7 +168,7 @@ class SupportDataCollector:
|
||||||
|
content = None
|
||||||
|
|
||||||
|
if content is None:
|
||||||
|
- data = json.loads(json.dumps(data))
|
||||||
|
+ data = salt.utils.json.loads(salt.utils.json.dumps(data))
|
||||||
|
if isinstance(data, dict) and data.get("return"):
|
||||||
|
data = data.get("return")
|
||||||
|
content = yaml.safe_dump(data, default_flow_style=False, indent=4)
|
||||||
|
@@ -506,7 +505,6 @@ class SaltSupport(salt.utils.parsers.SaltSupportOptionParser):
|
||||||
|
self.out.error(ex)
|
||||||
|
else:
|
||||||
|
if self.config["log_level"] not in ("quiet",):
|
||||||
|
- self.setup_logfile_logger()
|
||||||
|
salt.utils.verify.verify_log(self.config)
|
||||||
|
salt.cli.support.log = log # Pass update logger so trace is available
|
||||||
|
|
||||||
|
diff --git a/tests/pytests/unit/cli/test_support.py b/tests/unit/cli/test_support.py
|
||||||
|
similarity index 100%
|
||||||
|
rename from tests/pytests/unit/cli/test_support.py
|
||||||
|
rename to tests/unit/cli/test_support.py
|
||||||
|
diff --git a/tests/unit/modules/test_saltsupport.py b/tests/unit/modules/test_saltsupport.py
|
||||||
|
index 4ef04246b9..2afdd69b3e 100644
|
||||||
|
--- a/tests/unit/modules/test_saltsupport.py
|
||||||
|
+++ b/tests/unit/modules/test_saltsupport.py
|
||||||
|
@@ -251,8 +251,8 @@ professor: Farnsworth
|
||||||
|
with pytest.raises(salt.exceptions.SaltInvocationError) as err:
|
||||||
|
support.sync("group-name")
|
||||||
|
assert (
|
||||||
|
- ' Support archive "/mnt/storage/three-support-222-222.bz2" was not found'
|
||||||
|
- in str(err)
|
||||||
|
+ 'Support archive "/mnt/storage/three-support-222-222.bz2" was not found'
|
||||||
|
+ in str(err.value)
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch("tempfile.mkstemp", MagicMock(return_value=(0, "dummy")))
|
||||||
|
@@ -274,7 +274,7 @@ professor: Farnsworth
|
||||||
|
|
||||||
|
with pytest.raises(salt.exceptions.SaltInvocationError) as err:
|
||||||
|
support.sync("group-name", name="lost.bz2")
|
||||||
|
- assert ' Support archive "lost.bz2" was not found' in str(err)
|
||||||
|
+ assert 'Support archive "lost.bz2" was not found' in str(err.value)
|
||||||
|
|
||||||
|
@patch("tempfile.mkstemp", MagicMock(return_value=(0, "dummy")))
|
||||||
|
@patch("os.path.exists", MagicMock(return_value=False))
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
154
fix-the-regression-of-user.present-state-when-group-.patch
Normal file
154
fix-the-regression-of-user.present-state-when-group-.patch
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
From 502354be32fcff9b0607f6e435ca8825a4c2cd56 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Victor Zhestkov <vzhestkov@suse.com>
|
||||||
|
Date: Thu, 3 Aug 2023 11:07:03 +0200
|
||||||
|
Subject: [PATCH] Fix the regression of user.present state when group is
|
||||||
|
unset (#589)
|
||||||
|
|
||||||
|
* Fix user.present state when group is unset
|
||||||
|
|
||||||
|
* Fix user unit test
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Co-authored-by: Megan Wilhite <mwilhite@vmware.com>
|
||||||
|
---
|
||||||
|
changelog/64211.fixed.md | 1 +
|
||||||
|
salt/states/user.py | 2 +-
|
||||||
|
tests/pytests/functional/states/test_user.py | 74 +++++++++++++++++++-
|
||||||
|
tests/pytests/unit/states/test_user.py | 2 +
|
||||||
|
4 files changed, 76 insertions(+), 3 deletions(-)
|
||||||
|
create mode 100644 changelog/64211.fixed.md
|
||||||
|
|
||||||
|
diff --git a/changelog/64211.fixed.md b/changelog/64211.fixed.md
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..26b39acf02
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/changelog/64211.fixed.md
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Fix user.present state when groups is unset to ensure the groups are unchanged, as documented.
|
||||||
|
diff --git a/salt/states/user.py b/salt/states/user.py
|
||||||
|
index ed2d5a05f4..929afb2cd1 100644
|
||||||
|
--- a/salt/states/user.py
|
||||||
|
+++ b/salt/states/user.py
|
||||||
|
@@ -100,7 +100,7 @@ def _changes(
|
||||||
|
|
||||||
|
change = {}
|
||||||
|
wanted_groups = sorted(set((groups or []) + (optional_groups or [])))
|
||||||
|
- if not remove_groups:
|
||||||
|
+ if not remove_groups or groups is None and not optional_groups:
|
||||||
|
wanted_groups = sorted(set(wanted_groups + lusr["groups"]))
|
||||||
|
if uid and lusr["uid"] != uid:
|
||||||
|
change["uid"] = uid
|
||||||
|
diff --git a/tests/pytests/functional/states/test_user.py b/tests/pytests/functional/states/test_user.py
|
||||||
|
index 09d34da168..96b1ec55c8 100644
|
||||||
|
--- a/tests/pytests/functional/states/test_user.py
|
||||||
|
+++ b/tests/pytests/functional/states/test_user.py
|
||||||
|
@@ -117,7 +117,6 @@ def test_user_present_when_home_dir_does_not_18843(states, existing_account):
|
||||||
|
ret = states.user.present(
|
||||||
|
name=existing_account.username,
|
||||||
|
home=existing_account.info.home,
|
||||||
|
- remove_groups=False,
|
||||||
|
)
|
||||||
|
assert ret.result is True
|
||||||
|
assert pathlib.Path(existing_account.info.home).is_dir()
|
||||||
|
@@ -228,7 +227,6 @@ def test_user_present_unicode(states, username, subtests):
|
||||||
|
roomnumber="①②③",
|
||||||
|
workphone="١٢٣٤",
|
||||||
|
homephone="६७८",
|
||||||
|
- remove_groups=False,
|
||||||
|
)
|
||||||
|
assert ret.result is True
|
||||||
|
|
||||||
|
@@ -429,3 +427,75 @@ def test_user_present_change_optional_groups(
|
||||||
|
user_info = modules.user.info(username)
|
||||||
|
assert user_info
|
||||||
|
assert user_info["groups"] == [group_1.name]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skip_unless_on_linux(reason="underlying functionality only runs on Linux")
|
||||||
|
+def test_user_present_no_groups(modules, states, username):
|
||||||
|
+ """
|
||||||
|
+ test user.present when groups arg is not
|
||||||
|
+ included by the group is created in another
|
||||||
|
+ state. Re-run the states to ensure there are
|
||||||
|
+ not changes and it is idempotent.
|
||||||
|
+ """
|
||||||
|
+ groups = ["testgroup1", "testgroup2"]
|
||||||
|
+ try:
|
||||||
|
+ ret = states.group.present(name=username, gid=61121)
|
||||||
|
+ assert ret.result is True
|
||||||
|
+
|
||||||
|
+ ret = states.user.present(
|
||||||
|
+ name=username,
|
||||||
|
+ uid=61121,
|
||||||
|
+ gid=61121,
|
||||||
|
+ )
|
||||||
|
+ assert ret.result is True
|
||||||
|
+ assert ret.changes["groups"] == [username]
|
||||||
|
+ assert ret.changes["name"] == username
|
||||||
|
+
|
||||||
|
+ ret = states.group.present(
|
||||||
|
+ name=groups[0],
|
||||||
|
+ members=[username],
|
||||||
|
+ )
|
||||||
|
+ assert ret.changes["members"] == [username]
|
||||||
|
+
|
||||||
|
+ ret = states.group.present(
|
||||||
|
+ name=groups[1],
|
||||||
|
+ members=[username],
|
||||||
|
+ )
|
||||||
|
+ assert ret.changes["members"] == [username]
|
||||||
|
+
|
||||||
|
+ user_info = modules.user.info(username)
|
||||||
|
+ assert user_info
|
||||||
|
+ assert user_info["groups"] == [username, groups[0], groups[1]]
|
||||||
|
+
|
||||||
|
+ # run again, expecting no changes
|
||||||
|
+ ret = states.group.present(name=username)
|
||||||
|
+ assert ret.result is True
|
||||||
|
+ assert ret.changes == {}
|
||||||
|
+
|
||||||
|
+ ret = states.user.present(
|
||||||
|
+ name=username,
|
||||||
|
+ )
|
||||||
|
+ assert ret.result is True
|
||||||
|
+ assert ret.changes == {}
|
||||||
|
+
|
||||||
|
+ ret = states.group.present(
|
||||||
|
+ name=groups[0],
|
||||||
|
+ members=[username],
|
||||||
|
+ )
|
||||||
|
+ assert ret.result is True
|
||||||
|
+ assert ret.changes == {}
|
||||||
|
+
|
||||||
|
+ ret = states.group.present(
|
||||||
|
+ name=groups[1],
|
||||||
|
+ members=[username],
|
||||||
|
+ )
|
||||||
|
+ assert ret.result is True
|
||||||
|
+ assert ret.changes == {}
|
||||||
|
+
|
||||||
|
+ user_info = modules.user.info(username)
|
||||||
|
+ assert user_info
|
||||||
|
+ assert user_info["groups"] == [username, groups[0], groups[1]]
|
||||||
|
+ finally:
|
||||||
|
+ for group in groups:
|
||||||
|
+ ret = states.group.absent(name=group)
|
||||||
|
+ assert ret.result is True
|
||||||
|
diff --git a/tests/pytests/unit/states/test_user.py b/tests/pytests/unit/states/test_user.py
|
||||||
|
index 94e69d70ed..d50d16e3be 100644
|
||||||
|
--- a/tests/pytests/unit/states/test_user.py
|
||||||
|
+++ b/tests/pytests/unit/states/test_user.py
|
||||||
|
@@ -189,6 +189,8 @@ def test_present_uid_gid_change():
|
||||||
|
"user.chgid": Mock(),
|
||||||
|
"file.group_to_gid": mock_group_to_gid,
|
||||||
|
"file.gid_to_group": mock_gid_to_group,
|
||||||
|
+ "group.info": MagicMock(return_value=after),
|
||||||
|
+ "user.chgroups": MagicMock(return_value=True),
|
||||||
|
}
|
||||||
|
with patch.dict(user.__grains__, {"kernel": "Linux"}), patch.dict(
|
||||||
|
user.__salt__, dunder_salt
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
181
fix-utf8-handling-in-pass-renderer-and-make-it-more-.patch
Normal file
181
fix-utf8-handling-in-pass-renderer-and-make-it-more-.patch
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
From 027cbef223616f5ab6c73e60bcaa9f9e81a6ce67 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daniel Mach <daniel.mach@suse.com>
|
||||||
|
Date: Wed, 28 Jun 2023 16:39:42 +0200
|
||||||
|
Subject: [PATCH] Fix utf8 handling in 'pass' renderer and make it more
|
||||||
|
robust (#579)
|
||||||
|
|
||||||
|
* Migrate string formatting in 'pass' renderer to a f-string
|
||||||
|
|
||||||
|
* Fix utf8 handling in 'pass' renderer and make it more robust
|
||||||
|
---
|
||||||
|
changelog/64300.fixed.md | 1 +
|
||||||
|
salt/renderers/pass.py | 12 +--
|
||||||
|
tests/pytests/unit/renderers/test_pass.py | 99 +++++++++++++++++++++++
|
||||||
|
3 files changed, 103 insertions(+), 9 deletions(-)
|
||||||
|
create mode 100644 changelog/64300.fixed.md
|
||||||
|
|
||||||
|
diff --git a/changelog/64300.fixed.md b/changelog/64300.fixed.md
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..4418db1d04
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/changelog/64300.fixed.md
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Fix utf8 handling in 'pass' renderer
|
||||||
|
diff --git a/salt/renderers/pass.py b/salt/renderers/pass.py
|
||||||
|
index ba0f152c23..ae75bba443 100644
|
||||||
|
--- a/salt/renderers/pass.py
|
||||||
|
+++ b/salt/renderers/pass.py
|
||||||
|
@@ -145,23 +145,17 @@ def _fetch_secret(pass_path):
|
||||||
|
env["GNUPGHOME"] = pass_gnupghome
|
||||||
|
|
||||||
|
try:
|
||||||
|
- proc = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env)
|
||||||
|
+ proc = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env, encoding="utf-8")
|
||||||
|
pass_data, pass_error = proc.communicate()
|
||||||
|
pass_returncode = proc.returncode
|
||||||
|
- except OSError as e:
|
||||||
|
+ except (OSError, UnicodeDecodeError) as e:
|
||||||
|
pass_data, pass_error = "", str(e)
|
||||||
|
pass_returncode = 1
|
||||||
|
|
||||||
|
# The version of pass used during development sent output to
|
||||||
|
# stdout instead of stderr even though its returncode was non zero.
|
||||||
|
if pass_returncode or not pass_data:
|
||||||
|
- try:
|
||||||
|
- pass_error = pass_error.decode("utf-8")
|
||||||
|
- except (AttributeError, ValueError):
|
||||||
|
- pass
|
||||||
|
- msg = "Could not fetch secret '{}' from the password store: {}".format(
|
||||||
|
- pass_path, pass_error
|
||||||
|
- )
|
||||||
|
+ msg = f"Could not fetch secret '{pass_path}' from the password store: {pass_error}"
|
||||||
|
if pass_strict_fetch:
|
||||||
|
raise SaltRenderError(msg)
|
||||||
|
else:
|
||||||
|
diff --git a/tests/pytests/unit/renderers/test_pass.py b/tests/pytests/unit/renderers/test_pass.py
|
||||||
|
index 1e2ebb7ea8..f7c79e1fe1 100644
|
||||||
|
--- a/tests/pytests/unit/renderers/test_pass.py
|
||||||
|
+++ b/tests/pytests/unit/renderers/test_pass.py
|
||||||
|
@@ -1,8 +1,12 @@
|
||||||
|
import importlib
|
||||||
|
+import os
|
||||||
|
+import shutil
|
||||||
|
+import tempfile
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
import salt.exceptions
|
||||||
|
+import salt.utils.files
|
||||||
|
from tests.support.mock import MagicMock, patch
|
||||||
|
|
||||||
|
# "pass" is a reserved keyword, we need to import it differently
|
||||||
|
@@ -19,6 +23,47 @@ def configure_loader_modules(master_opts):
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+@pytest.fixture()
|
||||||
|
+def pass_executable(request):
|
||||||
|
+ tmp_dir = tempfile.mkdtemp(prefix="salt_pass_")
|
||||||
|
+ pass_path = os.path.join(tmp_dir, "pass")
|
||||||
|
+ with salt.utils.files.fopen(pass_path, "w") as f:
|
||||||
|
+ f.write("#!/bin/sh\n")
|
||||||
|
+ # return path path wrapped into unicode characters
|
||||||
|
+ # pass args ($1, $2) are ("show", <pass_path>)
|
||||||
|
+ f.write('echo "α>>> $2 <<<β"\n')
|
||||||
|
+ os.chmod(pass_path, 0o755)
|
||||||
|
+ yield pass_path
|
||||||
|
+ shutil.rmtree(tmp_dir)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.fixture()
|
||||||
|
+def pass_executable_error(request):
|
||||||
|
+ tmp_dir = tempfile.mkdtemp(prefix="salt_pass_")
|
||||||
|
+ pass_path = os.path.join(tmp_dir, "pass")
|
||||||
|
+ with salt.utils.files.fopen(pass_path, "w") as f:
|
||||||
|
+ f.write("#!/bin/sh\n")
|
||||||
|
+ # return error message with unicode characters
|
||||||
|
+ f.write('echo "ERROR: αβγ" >&2\n')
|
||||||
|
+ f.write("exit 1\n")
|
||||||
|
+ os.chmod(pass_path, 0o755)
|
||||||
|
+ yield pass_path
|
||||||
|
+ shutil.rmtree(tmp_dir)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.fixture()
|
||||||
|
+def pass_executable_invalid_utf8(request):
|
||||||
|
+ tmp_dir = tempfile.mkdtemp(prefix="salt_pass_")
|
||||||
|
+ pass_path = os.path.join(tmp_dir, "pass")
|
||||||
|
+ with salt.utils.files.fopen(pass_path, "wb") as f:
|
||||||
|
+ f.write(b"#!/bin/sh\n")
|
||||||
|
+ # return invalid utf-8 sequence
|
||||||
|
+ f.write(b'echo "\x80\x81"\n')
|
||||||
|
+ os.chmod(pass_path, 0o755)
|
||||||
|
+ yield pass_path
|
||||||
|
+ shutil.rmtree(tmp_dir)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
# The default behavior is that if fetching a secret from pass fails,
|
||||||
|
# the value is passed through. Even the trailing newlines are preserved.
|
||||||
|
def test_passthrough():
|
||||||
|
@@ -161,3 +206,57 @@ def test_env():
|
||||||
|
call_args, call_kwargs = popen_mock.call_args_list[0]
|
||||||
|
assert call_kwargs["env"]["GNUPGHOME"] == config["pass_gnupghome"]
|
||||||
|
assert call_kwargs["env"]["PASSWORD_STORE_DIR"] == config["pass_dir"]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skip_on_windows(reason="Not supported on Windows")
|
||||||
|
+def test_utf8(pass_executable):
|
||||||
|
+ config = {
|
||||||
|
+ "pass_variable_prefix": "pass:",
|
||||||
|
+ "pass_strict_fetch": True,
|
||||||
|
+ }
|
||||||
|
+ mocks = {
|
||||||
|
+ "_get_pass_exec": MagicMock(return_value=pass_executable),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pass_path = "pass:secret"
|
||||||
|
+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks):
|
||||||
|
+ result = pass_.render(pass_path)
|
||||||
|
+ assert result == "α>>> secret <<<β"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skip_on_windows(reason="Not supported on Windows")
|
||||||
|
+def test_utf8_error(pass_executable_error):
|
||||||
|
+ config = {
|
||||||
|
+ "pass_variable_prefix": "pass:",
|
||||||
|
+ "pass_strict_fetch": True,
|
||||||
|
+ }
|
||||||
|
+ mocks = {
|
||||||
|
+ "_get_pass_exec": MagicMock(return_value=pass_executable_error),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pass_path = "pass:secret"
|
||||||
|
+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks):
|
||||||
|
+ with pytest.raises(
|
||||||
|
+ salt.exceptions.SaltRenderError,
|
||||||
|
+ match=r"Could not fetch secret 'secret' from the password store: ERROR: αβγ",
|
||||||
|
+ ):
|
||||||
|
+ result = pass_.render(pass_path)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.skip_on_windows(reason="Not supported on Windows")
|
||||||
|
+def test_invalid_utf8(pass_executable_invalid_utf8):
|
||||||
|
+ config = {
|
||||||
|
+ "pass_variable_prefix": "pass:",
|
||||||
|
+ "pass_strict_fetch": True,
|
||||||
|
+ }
|
||||||
|
+ mocks = {
|
||||||
|
+ "_get_pass_exec": MagicMock(return_value=pass_executable_invalid_utf8),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pass_path = "pass:secret"
|
||||||
|
+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks):
|
||||||
|
+ with pytest.raises(
|
||||||
|
+ salt.exceptions.SaltRenderError,
|
||||||
|
+ match=r"Could not fetch secret 'secret' from the password store: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte",
|
||||||
|
+ ):
|
||||||
|
+ result = pass_.render(pass_path)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
37
make-master_tops-compatible-with-salt-3000-and-older.patch
Normal file
37
make-master_tops-compatible-with-salt-3000-and-older.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
From 53a5a62191b81c6838c3041cf95ffeb12fbab5b5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Mon, 19 Jun 2023 15:35:41 +0100
|
||||||
|
Subject: [PATCH] Make master_tops compatible with Salt 3000 and older
|
||||||
|
minions (bsc#1212516) (bsc#1212517) (#587)
|
||||||
|
|
||||||
|
---
|
||||||
|
salt/master.py | 4 ++++
|
||||||
|
1 file changed, 4 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/salt/master.py b/salt/master.py
|
||||||
|
index da1eb8cef5..fc243ef674 100644
|
||||||
|
--- a/salt/master.py
|
||||||
|
+++ b/salt/master.py
|
||||||
|
@@ -1213,6 +1213,7 @@ class AESFuncs(TransportMethods):
|
||||||
|
"_dir_list",
|
||||||
|
"_symlink_list",
|
||||||
|
"_file_envs",
|
||||||
|
+ "_ext_nodes", # To keep compatibility with old Salt minion versions
|
||||||
|
)
|
||||||
|
|
||||||
|
def __init__(self, opts, context=None):
|
||||||
|
@@ -1412,6 +1413,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.41.0
|
||||||
|
|
||||||
|
|
480
mark-salt-3006-as-released-586.patch
Normal file
480
mark-salt-3006-as-released-586.patch
Normal file
@ -0,0 +1,480 @@
|
|||||||
|
From c1408333364ac25ff5d316afa9674f7687217b0c Mon Sep 17 00:00:00 2001
|
||||||
|
From: Dominik Gedon <dgedon@suse.de>
|
||||||
|
Date: Thu, 3 Aug 2023 11:08:21 +0200
|
||||||
|
Subject: [PATCH] Mark Salt 3006 as released (#586)
|
||||||
|
MIME-Version: 1.0
|
||||||
|
Content-Type: text/plain; charset=UTF-8
|
||||||
|
Content-Transfer-Encoding: 8bit
|
||||||
|
|
||||||
|
* Mark Salt 3006 as released
|
||||||
|
|
||||||
|
Without this, commands like
|
||||||
|
|
||||||
|
```
|
||||||
|
salt '*' salt_version.equal 'Sulfur'
|
||||||
|
```
|
||||||
|
|
||||||
|
will not work properly and return False although Salt 3006 is used.
|
||||||
|
|
||||||
|
Signed-off-by: Dominik Gedon <dominik.gedon@suse.com>
|
||||||
|
|
||||||
|
* Fix detection of Salt codename by salt_version module
|
||||||
|
|
||||||
|
* Fix mess with version detection bad version definition
|
||||||
|
|
||||||
|
* Add some new and fix unit tests
|
||||||
|
|
||||||
|
* Fix SaltStackVersion string for new versions format
|
||||||
|
|
||||||
|
* Do not crash when passing numbers to 'salt_version.get_release_number'
|
||||||
|
|
||||||
|
* Fix salt_version execution module documentation
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Signed-off-by: Dominik Gedon <dominik.gedon@suse.com>
|
||||||
|
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
|
||||||
|
---
|
||||||
|
salt/modules/salt_version.py | 8 +-
|
||||||
|
salt/version.py | 218 +++++++++---------
|
||||||
|
.../pytests/unit/modules/test_salt_version.py | 55 ++++-
|
||||||
|
tests/pytests/unit/test_version.py | 10 +-
|
||||||
|
4 files changed, 176 insertions(+), 115 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/salt_version.py b/salt/modules/salt_version.py
|
||||||
|
index 1b5421fee4..99dae5f61a 100644
|
||||||
|
--- a/salt/modules/salt_version.py
|
||||||
|
+++ b/salt/modules/salt_version.py
|
||||||
|
@@ -20,7 +20,7 @@ A simple example might be something like the following:
|
||||||
|
.. code-block:: jinja
|
||||||
|
|
||||||
|
{# a boolean check #}
|
||||||
|
- {% set option_deprecated = salt['salt_version.less_than']("3001") %}
|
||||||
|
+ {% set option_deprecated = salt['salt_version.less_than']("Sodium") %}
|
||||||
|
|
||||||
|
{% if option_deprecated %}
|
||||||
|
<use old syntax>
|
||||||
|
@@ -35,6 +35,7 @@ import logging
|
||||||
|
|
||||||
|
import salt.utils.versions
|
||||||
|
import salt.version
|
||||||
|
+from salt.exceptions import CommandExecutionError
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@@ -51,7 +52,7 @@ def __virtual__():
|
||||||
|
def get_release_number(name):
|
||||||
|
"""
|
||||||
|
Returns the release number of a given release code name in a
|
||||||
|
- ``MAJOR.PATCH`` format.
|
||||||
|
+ ``MAJOR.PATCH`` format (for Salt versions < 3000) or ``MAJOR`` for newer Salt versions.
|
||||||
|
|
||||||
|
If the release name has not been given an assigned release number, the
|
||||||
|
function returns a string. If the release cannot be found, it returns
|
||||||
|
@@ -66,6 +67,9 @@ def get_release_number(name):
|
||||||
|
|
||||||
|
salt '*' salt_version.get_release_number 'Oxygen'
|
||||||
|
"""
|
||||||
|
+ if not isinstance(name, str):
|
||||||
|
+ raise CommandExecutionError("'name' argument must be a string")
|
||||||
|
+
|
||||||
|
name = name.lower()
|
||||||
|
version_map = salt.version.SaltStackVersion.LNAMES
|
||||||
|
version = version_map.get(name)
|
||||||
|
diff --git a/salt/version.py b/salt/version.py
|
||||||
|
index 67719bd020..44372830b2 100644
|
||||||
|
--- a/salt/version.py
|
||||||
|
+++ b/salt/version.py
|
||||||
|
@@ -77,109 +77,109 @@ class SaltVersionsInfo(type):
|
||||||
|
ALUMINIUM = SaltVersion("Aluminium" , info=3003, released=True)
|
||||||
|
SILICON = SaltVersion("Silicon" , info=3004, released=True)
|
||||||
|
PHOSPHORUS = SaltVersion("Phosphorus" , info=3005, released=True)
|
||||||
|
- SULFUR = SaltVersion("Sulfur" , info=(3006, 0))
|
||||||
|
- CHLORINE = SaltVersion("Chlorine" , info=(3007, 0))
|
||||||
|
- ARGON = SaltVersion("Argon" , info=(3008, 0))
|
||||||
|
- POTASSIUM = SaltVersion("Potassium" , info=(3009, 0))
|
||||||
|
- CALCIUM = SaltVersion("Calcium" , info=(3010, 0))
|
||||||
|
- SCANDIUM = SaltVersion("Scandium" , info=(3011, 0))
|
||||||
|
- TITANIUM = SaltVersion("Titanium" , info=(3012, 0))
|
||||||
|
- VANADIUM = SaltVersion("Vanadium" , info=(3013, 0))
|
||||||
|
- CHROMIUM = SaltVersion("Chromium" , info=(3014, 0))
|
||||||
|
- MANGANESE = SaltVersion("Manganese" , info=(3015, 0))
|
||||||
|
- IRON = SaltVersion("Iron" , info=(3016, 0))
|
||||||
|
- COBALT = SaltVersion("Cobalt" , info=(3017, 0))
|
||||||
|
- NICKEL = SaltVersion("Nickel" , info=(3018, 0))
|
||||||
|
- COPPER = SaltVersion("Copper" , info=(3019, 0))
|
||||||
|
- ZINC = SaltVersion("Zinc" , info=(3020, 0))
|
||||||
|
- GALLIUM = SaltVersion("Gallium" , info=(3021, 0))
|
||||||
|
- GERMANIUM = SaltVersion("Germanium" , info=(3022, 0))
|
||||||
|
- ARSENIC = SaltVersion("Arsenic" , info=(3023, 0))
|
||||||
|
- SELENIUM = SaltVersion("Selenium" , info=(3024, 0))
|
||||||
|
- BROMINE = SaltVersion("Bromine" , info=(3025, 0))
|
||||||
|
- KRYPTON = SaltVersion("Krypton" , info=(3026, 0))
|
||||||
|
- RUBIDIUM = SaltVersion("Rubidium" , info=(3027, 0))
|
||||||
|
- STRONTIUM = SaltVersion("Strontium" , info=(3028, 0))
|
||||||
|
- YTTRIUM = SaltVersion("Yttrium" , info=(3029, 0))
|
||||||
|
- ZIRCONIUM = SaltVersion("Zirconium" , info=(3030, 0))
|
||||||
|
- NIOBIUM = SaltVersion("Niobium" , info=(3031, 0))
|
||||||
|
- MOLYBDENUM = SaltVersion("Molybdenum" , info=(3032, 0))
|
||||||
|
- TECHNETIUM = SaltVersion("Technetium" , info=(3033, 0))
|
||||||
|
- RUTHENIUM = SaltVersion("Ruthenium" , info=(3034, 0))
|
||||||
|
- RHODIUM = SaltVersion("Rhodium" , info=(3035, 0))
|
||||||
|
- PALLADIUM = SaltVersion("Palladium" , info=(3036, 0))
|
||||||
|
- SILVER = SaltVersion("Silver" , info=(3037, 0))
|
||||||
|
- CADMIUM = SaltVersion("Cadmium" , info=(3038, 0))
|
||||||
|
- INDIUM = SaltVersion("Indium" , info=(3039, 0))
|
||||||
|
- TIN = SaltVersion("Tin" , info=(3040, 0))
|
||||||
|
- ANTIMONY = SaltVersion("Antimony" , info=(3041, 0))
|
||||||
|
- TELLURIUM = SaltVersion("Tellurium" , info=(3042, 0))
|
||||||
|
- IODINE = SaltVersion("Iodine" , info=(3043, 0))
|
||||||
|
- XENON = SaltVersion("Xenon" , info=(3044, 0))
|
||||||
|
- CESIUM = SaltVersion("Cesium" , info=(3045, 0))
|
||||||
|
- BARIUM = SaltVersion("Barium" , info=(3046, 0))
|
||||||
|
- LANTHANUM = SaltVersion("Lanthanum" , info=(3047, 0))
|
||||||
|
- CERIUM = SaltVersion("Cerium" , info=(3048, 0))
|
||||||
|
- PRASEODYMIUM = SaltVersion("Praseodymium" , info=(3049, 0))
|
||||||
|
- NEODYMIUM = SaltVersion("Neodymium" , info=(3050, 0))
|
||||||
|
- PROMETHIUM = SaltVersion("Promethium" , info=(3051, 0))
|
||||||
|
- SAMARIUM = SaltVersion("Samarium" , info=(3052, 0))
|
||||||
|
- EUROPIUM = SaltVersion("Europium" , info=(3053, 0))
|
||||||
|
- GADOLINIUM = SaltVersion("Gadolinium" , info=(3054, 0))
|
||||||
|
- TERBIUM = SaltVersion("Terbium" , info=(3055, 0))
|
||||||
|
- DYSPROSIUM = SaltVersion("Dysprosium" , info=(3056, 0))
|
||||||
|
- HOLMIUM = SaltVersion("Holmium" , info=(3057, 0))
|
||||||
|
- ERBIUM = SaltVersion("Erbium" , info=(3058, 0))
|
||||||
|
- THULIUM = SaltVersion("Thulium" , info=(3059, 0))
|
||||||
|
- YTTERBIUM = SaltVersion("Ytterbium" , info=(3060, 0))
|
||||||
|
- LUTETIUM = SaltVersion("Lutetium" , info=(3061, 0))
|
||||||
|
- HAFNIUM = SaltVersion("Hafnium" , info=(3062, 0))
|
||||||
|
- TANTALUM = SaltVersion("Tantalum" , info=(3063, 0))
|
||||||
|
- TUNGSTEN = SaltVersion("Tungsten" , info=(3064, 0))
|
||||||
|
- RHENIUM = SaltVersion("Rhenium" , info=(3065, 0))
|
||||||
|
- OSMIUM = SaltVersion("Osmium" , info=(3066, 0))
|
||||||
|
- IRIDIUM = SaltVersion("Iridium" , info=(3067, 0))
|
||||||
|
- PLATINUM = SaltVersion("Platinum" , info=(3068, 0))
|
||||||
|
- GOLD = SaltVersion("Gold" , info=(3069, 0))
|
||||||
|
- MERCURY = SaltVersion("Mercury" , info=(3070, 0))
|
||||||
|
- THALLIUM = SaltVersion("Thallium" , info=(3071, 0))
|
||||||
|
- LEAD = SaltVersion("Lead" , info=(3072, 0))
|
||||||
|
- BISMUTH = SaltVersion("Bismuth" , info=(3073, 0))
|
||||||
|
- POLONIUM = SaltVersion("Polonium" , info=(3074, 0))
|
||||||
|
- ASTATINE = SaltVersion("Astatine" , info=(3075, 0))
|
||||||
|
- RADON = SaltVersion("Radon" , info=(3076, 0))
|
||||||
|
- FRANCIUM = SaltVersion("Francium" , info=(3077, 0))
|
||||||
|
- RADIUM = SaltVersion("Radium" , info=(3078, 0))
|
||||||
|
- ACTINIUM = SaltVersion("Actinium" , info=(3079, 0))
|
||||||
|
- THORIUM = SaltVersion("Thorium" , info=(3080, 0))
|
||||||
|
- PROTACTINIUM = SaltVersion("Protactinium" , info=(3081, 0))
|
||||||
|
- URANIUM = SaltVersion("Uranium" , info=(3082, 0))
|
||||||
|
- NEPTUNIUM = SaltVersion("Neptunium" , info=(3083, 0))
|
||||||
|
- PLUTONIUM = SaltVersion("Plutonium" , info=(3084, 0))
|
||||||
|
- AMERICIUM = SaltVersion("Americium" , info=(3085, 0))
|
||||||
|
- CURIUM = SaltVersion("Curium" , info=(3086, 0))
|
||||||
|
- BERKELIUM = SaltVersion("Berkelium" , info=(3087, 0))
|
||||||
|
- CALIFORNIUM = SaltVersion("Californium" , info=(3088, 0))
|
||||||
|
- EINSTEINIUM = SaltVersion("Einsteinium" , info=(3089, 0))
|
||||||
|
- FERMIUM = SaltVersion("Fermium" , info=(3090, 0))
|
||||||
|
- MENDELEVIUM = SaltVersion("Mendelevium" , info=(3091, 0))
|
||||||
|
- NOBELIUM = SaltVersion("Nobelium" , info=(3092, 0))
|
||||||
|
- LAWRENCIUM = SaltVersion("Lawrencium" , info=(3093, 0))
|
||||||
|
- RUTHERFORDIUM = SaltVersion("Rutherfordium", info=(3094, 0))
|
||||||
|
- DUBNIUM = SaltVersion("Dubnium" , info=(3095, 0))
|
||||||
|
- SEABORGIUM = SaltVersion("Seaborgium" , info=(3096, 0))
|
||||||
|
- BOHRIUM = SaltVersion("Bohrium" , info=(3097, 0))
|
||||||
|
- HASSIUM = SaltVersion("Hassium" , info=(3098, 0))
|
||||||
|
- MEITNERIUM = SaltVersion("Meitnerium" , info=(3099, 0))
|
||||||
|
- DARMSTADTIUM = SaltVersion("Darmstadtium" , info=(3100, 0))
|
||||||
|
- ROENTGENIUM = SaltVersion("Roentgenium" , info=(3101, 0))
|
||||||
|
- COPERNICIUM = SaltVersion("Copernicium" , info=(3102, 0))
|
||||||
|
- NIHONIUM = SaltVersion("Nihonium" , info=(3103, 0))
|
||||||
|
- FLEROVIUM = SaltVersion("Flerovium" , info=(3104, 0))
|
||||||
|
- MOSCOVIUM = SaltVersion("Moscovium" , info=(3105, 0))
|
||||||
|
- LIVERMORIUM = SaltVersion("Livermorium" , info=(3106, 0))
|
||||||
|
- TENNESSINE = SaltVersion("Tennessine" , info=(3107, 0))
|
||||||
|
- OGANESSON = SaltVersion("Oganesson" , info=(3108, 0))
|
||||||
|
+ SULFUR = SaltVersion("Sulfur" , info=3006, released=True)
|
||||||
|
+ CHLORINE = SaltVersion("Chlorine" , info=3007)
|
||||||
|
+ ARGON = SaltVersion("Argon" , info=3008)
|
||||||
|
+ POTASSIUM = SaltVersion("Potassium" , info=3009)
|
||||||
|
+ CALCIUM = SaltVersion("Calcium" , info=3010)
|
||||||
|
+ SCANDIUM = SaltVersion("Scandium" , info=3011)
|
||||||
|
+ TITANIUM = SaltVersion("Titanium" , info=3012)
|
||||||
|
+ VANADIUM = SaltVersion("Vanadium" , info=3013)
|
||||||
|
+ CHROMIUM = SaltVersion("Chromium" , info=3014)
|
||||||
|
+ MANGANESE = SaltVersion("Manganese" , info=3015)
|
||||||
|
+ IRON = SaltVersion("Iron" , info=3016)
|
||||||
|
+ COBALT = SaltVersion("Cobalt" , info=3017)
|
||||||
|
+ NICKEL = SaltVersion("Nickel" , info=3018)
|
||||||
|
+ COPPER = SaltVersion("Copper" , info=3019)
|
||||||
|
+ ZINC = SaltVersion("Zinc" , info=3020)
|
||||||
|
+ GALLIUM = SaltVersion("Gallium" , info=3021)
|
||||||
|
+ GERMANIUM = SaltVersion("Germanium" , info=3022)
|
||||||
|
+ ARSENIC = SaltVersion("Arsenic" , info=3023)
|
||||||
|
+ SELENIUM = SaltVersion("Selenium" , info=3024)
|
||||||
|
+ BROMINE = SaltVersion("Bromine" , info=3025)
|
||||||
|
+ KRYPTON = SaltVersion("Krypton" , info=3026)
|
||||||
|
+ RUBIDIUM = SaltVersion("Rubidium" , info=3027)
|
||||||
|
+ STRONTIUM = SaltVersion("Strontium" , info=3028)
|
||||||
|
+ YTTRIUM = SaltVersion("Yttrium" , info=3029)
|
||||||
|
+ ZIRCONIUM = SaltVersion("Zirconium" , info=3030)
|
||||||
|
+ NIOBIUM = SaltVersion("Niobium" , info=3031)
|
||||||
|
+ MOLYBDENUM = SaltVersion("Molybdenum" , info=3032)
|
||||||
|
+ TECHNETIUM = SaltVersion("Technetium" , info=3033)
|
||||||
|
+ RUTHENIUM = SaltVersion("Ruthenium" , info=3034)
|
||||||
|
+ RHODIUM = SaltVersion("Rhodium" , info=3035)
|
||||||
|
+ PALLADIUM = SaltVersion("Palladium" , info=3036)
|
||||||
|
+ SILVER = SaltVersion("Silver" , info=3037)
|
||||||
|
+ CADMIUM = SaltVersion("Cadmium" , info=3038)
|
||||||
|
+ INDIUM = SaltVersion("Indium" , info=3039)
|
||||||
|
+ TIN = SaltVersion("Tin" , info=3040)
|
||||||
|
+ ANTIMONY = SaltVersion("Antimony" , info=3041)
|
||||||
|
+ TELLURIUM = SaltVersion("Tellurium" , info=3042)
|
||||||
|
+ IODINE = SaltVersion("Iodine" , info=3043)
|
||||||
|
+ XENON = SaltVersion("Xenon" , info=3044)
|
||||||
|
+ CESIUM = SaltVersion("Cesium" , info=3045)
|
||||||
|
+ BARIUM = SaltVersion("Barium" , info=3046)
|
||||||
|
+ LANTHANUM = SaltVersion("Lanthanum" , info=3047)
|
||||||
|
+ CERIUM = SaltVersion("Cerium" , info=3048)
|
||||||
|
+ PRASEODYMIUM = SaltVersion("Praseodymium" , info=3049)
|
||||||
|
+ NEODYMIUM = SaltVersion("Neodymium" , info=3050)
|
||||||
|
+ PROMETHIUM = SaltVersion("Promethium" , info=3051)
|
||||||
|
+ SAMARIUM = SaltVersion("Samarium" , info=3052)
|
||||||
|
+ EUROPIUM = SaltVersion("Europium" , info=3053)
|
||||||
|
+ GADOLINIUM = SaltVersion("Gadolinium" , info=3054)
|
||||||
|
+ TERBIUM = SaltVersion("Terbium" , info=3055)
|
||||||
|
+ DYSPROSIUM = SaltVersion("Dysprosium" , info=3056)
|
||||||
|
+ HOLMIUM = SaltVersion("Holmium" , info=3057)
|
||||||
|
+ ERBIUM = SaltVersion("Erbium" , info=3058)
|
||||||
|
+ THULIUM = SaltVersion("Thulium" , info=3059)
|
||||||
|
+ YTTERBIUM = SaltVersion("Ytterbium" , info=3060)
|
||||||
|
+ LUTETIUM = SaltVersion("Lutetium" , info=3061)
|
||||||
|
+ HAFNIUM = SaltVersion("Hafnium" , info=3062)
|
||||||
|
+ TANTALUM = SaltVersion("Tantalum" , info=3063)
|
||||||
|
+ TUNGSTEN = SaltVersion("Tungsten" , info=3064)
|
||||||
|
+ RHENIUM = SaltVersion("Rhenium" , info=3065)
|
||||||
|
+ OSMIUM = SaltVersion("Osmium" , info=3066)
|
||||||
|
+ IRIDIUM = SaltVersion("Iridium" , info=3067)
|
||||||
|
+ PLATINUM = SaltVersion("Platinum" , info=3068)
|
||||||
|
+ GOLD = SaltVersion("Gold" , info=3069)
|
||||||
|
+ MERCURY = SaltVersion("Mercury" , info=3070)
|
||||||
|
+ THALLIUM = SaltVersion("Thallium" , info=3071)
|
||||||
|
+ LEAD = SaltVersion("Lead" , info=3072)
|
||||||
|
+ BISMUTH = SaltVersion("Bismuth" , info=3073)
|
||||||
|
+ POLONIUM = SaltVersion("Polonium" , info=3074)
|
||||||
|
+ ASTATINE = SaltVersion("Astatine" , info=3075)
|
||||||
|
+ RADON = SaltVersion("Radon" , info=3076)
|
||||||
|
+ FRANCIUM = SaltVersion("Francium" , info=3077)
|
||||||
|
+ RADIUM = SaltVersion("Radium" , info=3078)
|
||||||
|
+ ACTINIUM = SaltVersion("Actinium" , info=3079)
|
||||||
|
+ THORIUM = SaltVersion("Thorium" , info=3080)
|
||||||
|
+ PROTACTINIUM = SaltVersion("Protactinium" , info=3081)
|
||||||
|
+ URANIUM = SaltVersion("Uranium" , info=3082)
|
||||||
|
+ NEPTUNIUM = SaltVersion("Neptunium" , info=3083)
|
||||||
|
+ PLUTONIUM = SaltVersion("Plutonium" , info=3084)
|
||||||
|
+ AMERICIUM = SaltVersion("Americium" , info=3085)
|
||||||
|
+ CURIUM = SaltVersion("Curium" , info=3086)
|
||||||
|
+ BERKELIUM = SaltVersion("Berkelium" , info=3087)
|
||||||
|
+ CALIFORNIUM = SaltVersion("Californium" , info=3088)
|
||||||
|
+ EINSTEINIUM = SaltVersion("Einsteinium" , info=3089)
|
||||||
|
+ FERMIUM = SaltVersion("Fermium" , info=3090)
|
||||||
|
+ MENDELEVIUM = SaltVersion("Mendelevium" , info=3091)
|
||||||
|
+ NOBELIUM = SaltVersion("Nobelium" , info=3092)
|
||||||
|
+ LAWRENCIUM = SaltVersion("Lawrencium" , info=3093)
|
||||||
|
+ RUTHERFORDIUM = SaltVersion("Rutherfordium", info=3094)
|
||||||
|
+ DUBNIUM = SaltVersion("Dubnium" , info=3095)
|
||||||
|
+ SEABORGIUM = SaltVersion("Seaborgium" , info=3096)
|
||||||
|
+ BOHRIUM = SaltVersion("Bohrium" , info=3097)
|
||||||
|
+ HASSIUM = SaltVersion("Hassium" , info=3098)
|
||||||
|
+ MEITNERIUM = SaltVersion("Meitnerium" , info=3099)
|
||||||
|
+ DARMSTADTIUM = SaltVersion("Darmstadtium" , info=3100)
|
||||||
|
+ ROENTGENIUM = SaltVersion("Roentgenium" , info=3101)
|
||||||
|
+ COPERNICIUM = SaltVersion("Copernicium" , info=3102)
|
||||||
|
+ NIHONIUM = SaltVersion("Nihonium" , info=3103)
|
||||||
|
+ FLEROVIUM = SaltVersion("Flerovium" , info=3104)
|
||||||
|
+ MOSCOVIUM = SaltVersion("Moscovium" , info=3105)
|
||||||
|
+ LIVERMORIUM = SaltVersion("Livermorium" , info=3106)
|
||||||
|
+ TENNESSINE = SaltVersion("Tennessine" , info=3107)
|
||||||
|
+ OGANESSON = SaltVersion("Oganesson" , info=3108)
|
||||||
|
# <---- Please refrain from fixing whitespace -----------------------------------
|
||||||
|
# The idea is to keep this readable.
|
||||||
|
# -------------------------------------------------------------------------------
|
||||||
|
@@ -323,9 +323,7 @@ class SaltStackVersion:
|
||||||
|
self.mbugfix = mbugfix
|
||||||
|
self.pre_type = pre_type
|
||||||
|
self.pre_num = pre_num
|
||||||
|
- if self.can_have_dot_zero(major):
|
||||||
|
- vnames_key = (major, 0)
|
||||||
|
- elif self.new_version(major):
|
||||||
|
+ if self.new_version(major):
|
||||||
|
vnames_key = (major,)
|
||||||
|
else:
|
||||||
|
vnames_key = (major, minor)
|
||||||
|
@@ -476,8 +474,12 @@ class SaltStackVersion:
|
||||||
|
version_string = self.string
|
||||||
|
if self.sse:
|
||||||
|
version_string += " Enterprise"
|
||||||
|
- if (self.major, self.minor) in self.RMATCH:
|
||||||
|
- version_string += " ({})".format(self.RMATCH[(self.major, self.minor)])
|
||||||
|
+ if self.new_version(self.major):
|
||||||
|
+ rmatch_key = (self.major,)
|
||||||
|
+ else:
|
||||||
|
+ rmatch_key = (self.major, self.minor)
|
||||||
|
+ if rmatch_key in self.RMATCH:
|
||||||
|
+ version_string += " ({})".format(self.RMATCH[rmatch_key])
|
||||||
|
return version_string
|
||||||
|
|
||||||
|
@property
|
||||||
|
diff --git a/tests/pytests/unit/modules/test_salt_version.py b/tests/pytests/unit/modules/test_salt_version.py
|
||||||
|
index 6d734f6a76..4b7a7cd073 100644
|
||||||
|
--- a/tests/pytests/unit/modules/test_salt_version.py
|
||||||
|
+++ b/tests/pytests/unit/modules/test_salt_version.py
|
||||||
|
@@ -2,8 +2,11 @@
|
||||||
|
Unit tests for salt/modules/salt_version.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
+import pytest
|
||||||
|
+
|
||||||
|
import salt.modules.salt_version as salt_version
|
||||||
|
import salt.version
|
||||||
|
+from salt.exceptions import CommandExecutionError
|
||||||
|
from tests.support.mock import MagicMock, patch
|
||||||
|
|
||||||
|
|
||||||
|
@@ -21,7 +24,7 @@ def test_mocked_objects():
|
||||||
|
for k, v in salt.version.SaltStackVersion.LNAMES.items():
|
||||||
|
assert k == k.lower()
|
||||||
|
assert isinstance(v, tuple)
|
||||||
|
- if sv.new_version(major=v[0]) and not sv.can_have_dot_zero(major=v[0]):
|
||||||
|
+ if sv.new_version(major=v[0]):
|
||||||
|
assert len(v) == 1
|
||||||
|
else:
|
||||||
|
assert len(v) == 2
|
||||||
|
@@ -64,6 +67,13 @@ def test_get_release_number_success_new_version():
|
||||||
|
assert salt_version.get_release_number("Neon") == "3000"
|
||||||
|
|
||||||
|
|
||||||
|
+def test_get_release_number_success_new_version_with_dot():
|
||||||
|
+ """
|
||||||
|
+ Test that a version is returned for new versioning (3006)
|
||||||
|
+ """
|
||||||
|
+ assert salt_version.get_release_number("Sulfur") == "3006"
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_equal_success():
|
||||||
|
"""
|
||||||
|
Test that the current version is equal to the codename
|
||||||
|
@@ -83,6 +93,16 @@ def test_equal_success_new_version():
|
||||||
|
assert salt_version.equal("foo") is True
|
||||||
|
|
||||||
|
|
||||||
|
+def test_equal_success_new_version_with_dot():
|
||||||
|
+ """
|
||||||
|
+ Test that the current version is equal to the codename
|
||||||
|
+ while using the new versioning
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.version.SaltStackVersion", MagicMock(return_value="3006.1")):
|
||||||
|
+ with patch("salt.version.SaltStackVersion.LNAMES", {"foo": (3006,)}):
|
||||||
|
+ assert salt_version.equal("foo") is True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_equal_older_codename():
|
||||||
|
"""
|
||||||
|
Test that when an older codename is passed in, the function returns False.
|
||||||
|
@@ -142,6 +162,17 @@ def test_greater_than_success_new_version():
|
||||||
|
assert salt_version.greater_than("Nitrogen") is True
|
||||||
|
|
||||||
|
|
||||||
|
+def test_greater_than_success_new_version_with_dot():
|
||||||
|
+ """
|
||||||
|
+ Test that the current version is newer than the codename
|
||||||
|
+ """
|
||||||
|
+ with patch(
|
||||||
|
+ "salt.modules.salt_version.get_release_number", MagicMock(return_value="3000")
|
||||||
|
+ ):
|
||||||
|
+ with patch("salt.version.SaltStackVersion", MagicMock(return_value="3006.0")):
|
||||||
|
+ assert salt_version.greater_than("Neon") is True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_greater_than_with_equal_codename():
|
||||||
|
"""
|
||||||
|
Test that when an equal codename is passed in, the function returns False.
|
||||||
|
@@ -200,6 +231,28 @@ def test_less_than_success_new_version():
|
||||||
|
assert salt_version.less_than("Fluorine") is True
|
||||||
|
|
||||||
|
|
||||||
|
+def test_less_than_success_new_version_with_dot():
|
||||||
|
+ """
|
||||||
|
+ Test that when a newer codename is passed in, the function returns True
|
||||||
|
+ using new version
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.version.SaltStackVersion", MagicMock(return_value="2018.3.2")):
|
||||||
|
+ with patch(
|
||||||
|
+ "salt.modules.salt_version.get_release_number",
|
||||||
|
+ MagicMock(return_value="3006"),
|
||||||
|
+ ):
|
||||||
|
+ assert salt_version.less_than("Fluorine") is True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def test_less_than_do_not_crash_when_input_is_a_number():
|
||||||
|
+ """
|
||||||
|
+ Test that less_than do not crash when unexpected inputs
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.version.SaltStackVersion", MagicMock(return_value="2018.3.2")):
|
||||||
|
+ with pytest.raises(CommandExecutionError):
|
||||||
|
+ salt_version.less_than(1234)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_less_than_with_equal_codename():
|
||||||
|
"""
|
||||||
|
Test that when an equal codename is passed in, the function returns False.
|
||||||
|
diff --git a/tests/pytests/unit/test_version.py b/tests/pytests/unit/test_version.py
|
||||||
|
index 73befea4cf..1cb94c619c 100644
|
||||||
|
--- a/tests/pytests/unit/test_version.py
|
||||||
|
+++ b/tests/pytests/unit/test_version.py
|
||||||
|
@@ -187,7 +187,7 @@ def test_string_new_version_minor():
|
||||||
|
ver = SaltStackVersion(major=maj_ver, minor=min_ver)
|
||||||
|
assert ver.minor == min_ver
|
||||||
|
assert not ver.bugfix
|
||||||
|
- assert ver.string == "{}.{}".format(maj_ver, min_ver)
|
||||||
|
+ assert ver.string == f"{maj_ver}.{min_ver}"
|
||||||
|
|
||||||
|
|
||||||
|
def test_string_new_version_minor_as_string():
|
||||||
|
@@ -201,13 +201,13 @@ def test_string_new_version_minor_as_string():
|
||||||
|
ver = SaltStackVersion(major=maj_ver, minor=min_ver)
|
||||||
|
assert ver.minor == int(min_ver)
|
||||||
|
assert not ver.bugfix
|
||||||
|
- assert ver.string == "{}.{}".format(maj_ver, min_ver)
|
||||||
|
+ assert ver.string == f"{maj_ver}.{min_ver}"
|
||||||
|
|
||||||
|
# This only seems to happen on a cloned repo without its tags
|
||||||
|
maj_ver = "3000"
|
||||||
|
min_ver = ""
|
||||||
|
ver = SaltStackVersion(major=maj_ver, minor=min_ver)
|
||||||
|
- assert ver.minor is None, "{!r} is not {!r}".format(ver.minor, min_ver)
|
||||||
|
+ assert ver.minor is None, f"{ver.minor!r} is not {min_ver!r}"
|
||||||
|
assert not ver.bugfix
|
||||||
|
assert ver.string == maj_ver
|
||||||
|
|
||||||
|
@@ -222,7 +222,7 @@ def test_string_old_version():
|
||||||
|
min_ver = "2"
|
||||||
|
ver = SaltStackVersion(major=maj_ver, minor=min_ver)
|
||||||
|
assert ver.bugfix == 0
|
||||||
|
- assert ver.string == "{}.{}.0".format(maj_ver, min_ver)
|
||||||
|
+ assert ver.string == f"{maj_ver}.{min_ver}.0"
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
@@ -537,6 +537,8 @@ def test_versions_report_no_extensions_available():
|
||||||
|
("3000.1", "3000.1", "Neon"),
|
||||||
|
("3005", "3005", "Phosphorus"),
|
||||||
|
("3006", "3006.0", "Sulfur"),
|
||||||
|
+ ("3006.0", "3006.0", "Sulfur"),
|
||||||
|
+ ("3006.1", "3006.1", "Sulfur"),
|
||||||
|
("3015.1", "3015.1", "Manganese"),
|
||||||
|
("3109.3", "3109.3", None),
|
||||||
|
],
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
29
salt.changes
29
salt.changes
@ -1,3 +1,32 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Wed Aug 9 15:13:50 UTC 2023 - Alexander Graul <alexander.graul@suse.com>
|
||||||
|
|
||||||
|
- Create minion_id with reproducible mtime
|
||||||
|
- Fix detection of Salt codename by "salt_version" execution module
|
||||||
|
- Fix regression: multiple values for keyword argument 'saltenv' (bsc#1212844)
|
||||||
|
- Fix the regression of user.present state when group is unset (bsc#1212855)
|
||||||
|
- Fix zypper repositories always being reconfigured
|
||||||
|
- Fix utf8 handling in 'pass' renderer and make it more robust
|
||||||
|
- Prevent _pygit2.GitError: error loading known_hosts when $HOME is not set (bsc#1210994)
|
||||||
|
- Fix ModuleNotFoundError and other issues raised by salt-support module (bsc#1211591)
|
||||||
|
- tornado: Fix an open redirect in StaticFileHandler (CVE-2023-28370, bsc#1211741)
|
||||||
|
- Make master_tops compatible with Salt 3000 and older minions (bsc#1212516) (bsc#1212517)
|
||||||
|
- Avoid failures due transactional_update module not available in Salt 3006.0 (bsc#1211754)
|
||||||
|
- Avoid conflicts with Salt dependencies versions (bsc#1211612)
|
||||||
|
|
||||||
|
- Added:
|
||||||
|
* fix-utf8-handling-in-pass-renderer-and-make-it-more-.patch
|
||||||
|
* fix-the-regression-of-user.present-state-when-group-.patch
|
||||||
|
* make-master_tops-compatible-with-salt-3000-and-older.patch
|
||||||
|
* avoid-conflicts-with-dependencies-versions-bsc-12116.patch
|
||||||
|
* tornado-fix-an-open-redirect-in-staticfilehandler-cv.patch
|
||||||
|
* fix-regression-multiple-values-for-keyword-argument-.patch
|
||||||
|
* zypper-pkgrepo-alreadyconfigured-585.patch
|
||||||
|
* mark-salt-3006-as-released-586.patch
|
||||||
|
* fix-some-issues-detected-in-salt-support-cli-module-.patch
|
||||||
|
* define-__virtualname__-for-transactional_update-modu.patch
|
||||||
|
* 3006.0-prevent-_pygit2.giterror-error-loading-known_.patch
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Fri May 5 08:29:26 UTC 2023 - Alexander Graul <alexander.graul@suse.com>
|
Fri May 5 08:29:26 UTC 2023 - Alexander Graul <alexander.graul@suse.com>
|
||||||
|
|
||||||
|
24
salt.spec
24
salt.spec
@ -267,6 +267,28 @@ Patch60: skip-package-names-without-colon-bsc-1208691-578.patch
|
|||||||
Patch61: fix-version-detection-and-avoid-building-and-testing.patch
|
Patch61: fix-version-detection-and-avoid-building-and-testing.patch
|
||||||
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64113
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64113
|
||||||
Patch62: make-sure-the-file-client-is-destroyed-upon-used.patch
|
Patch62: make-sure-the-file-client-is-destroyed-upon-used.patch
|
||||||
|
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/581
|
||||||
|
Patch63: avoid-conflicts-with-dependencies-versions-bsc-12116.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64369
|
||||||
|
Patch64: define-__virtualname__-for-transactional_update-modu.patch
|
||||||
|
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/587
|
||||||
|
Patch65: make-master_tops-compatible-with-salt-3000-and-older.patch
|
||||||
|
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/583
|
||||||
|
Patch66: tornado-fix-an-open-redirect-in-staticfilehandler-cv.patch
|
||||||
|
# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/580
|
||||||
|
Patch67: fix-some-issues-detected-in-salt-support-cli-module-.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64510
|
||||||
|
Patch68: 3006.0-prevent-_pygit2.giterror-error-loading-known_.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64300
|
||||||
|
Patch69: fix-utf8-handling-in-pass-renderer-and-make-it-more-.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/63403
|
||||||
|
Patch70: zypper-pkgrepo-alreadyconfigured-585.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64530
|
||||||
|
Patch71: fix-the-regression-of-user.present-state-when-group-.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64179
|
||||||
|
Patch72: fix-regression-multiple-values-for-keyword-argument-.patch
|
||||||
|
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64554
|
||||||
|
Patch73: mark-salt-3006-as-released-586.patch
|
||||||
|
|
||||||
### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
|
### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
|
||||||
### SALT PATCHES LIST END
|
### SALT PATCHES LIST END
|
||||||
@ -844,7 +866,7 @@ install -Dpm 0755 scripts/suse/watchdog/salt-daemon-watcher %{buildroot}%{_bindi
|
|||||||
#
|
#
|
||||||
## install config files
|
## install config files
|
||||||
install -Dpm 0640 conf/minion %{buildroot}%{_sysconfdir}/salt/minion
|
install -Dpm 0640 conf/minion %{buildroot}%{_sysconfdir}/salt/minion
|
||||||
install -Dpm 0640 /dev/null %{buildroot}%{_sysconfdir}/salt/minion_id
|
touch -m 0640 -r conf/minion %{buildroot}%{_sysconfdir}/salt/minion_id # ghost file
|
||||||
install -Dpm 0640 conf/master %{buildroot}%{_sysconfdir}/salt/master
|
install -Dpm 0640 conf/master %{buildroot}%{_sysconfdir}/salt/master
|
||||||
install -Dpm 0640 conf/roster %{buildroot}%{_sysconfdir}/salt/roster
|
install -Dpm 0640 conf/roster %{buildroot}%{_sysconfdir}/salt/roster
|
||||||
install -Dpm 0640 conf/cloud %{buildroot}%{_sysconfdir}/salt/cloud
|
install -Dpm 0640 conf/cloud %{buildroot}%{_sysconfdir}/salt/cloud
|
||||||
|
35
tornado-fix-an-open-redirect-in-staticfilehandler-cv.patch
Normal file
35
tornado-fix-an-open-redirect-in-staticfilehandler-cv.patch
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
From 78f5a76315891168d24e923d2b08211baefefb4f Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Thu, 22 Jun 2023 16:36:20 +0100
|
||||||
|
Subject: [PATCH] tornado: Fix an open redirect in StaticFileHandler
|
||||||
|
(CVE-2023-28370, bsc#1211741) (#583)
|
||||||
|
|
||||||
|
---
|
||||||
|
salt/ext/tornado/web.py | 9 +++++++++
|
||||||
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/salt/ext/tornado/web.py b/salt/ext/tornado/web.py
|
||||||
|
index 60bde695d3..97fadcf87d 100644
|
||||||
|
--- a/salt/ext/tornado/web.py
|
||||||
|
+++ b/salt/ext/tornado/web.py
|
||||||
|
@@ -2544,6 +2544,15 @@ class StaticFileHandler(RequestHandler):
|
||||||
|
# but there is some prefix to the path that was already
|
||||||
|
# trimmed by the routing
|
||||||
|
if not self.request.path.endswith("/"):
|
||||||
|
+ if self.request.path.startswith("//"):
|
||||||
|
+ # A redirect with two initial slashes is a "protocol-relative" URL.
|
||||||
|
+ # This means the next path segment is treated as a hostname instead
|
||||||
|
+ # of a part of the path, making this effectively an open redirect.
|
||||||
|
+ # Reject paths starting with two slashes to prevent this.
|
||||||
|
+ # This is only reachable under certain configurations.
|
||||||
|
+ raise HTTPError(
|
||||||
|
+ 403, "cannot redirect path with two initial slashes"
|
||||||
|
+ )
|
||||||
|
self.redirect(self.request.path + "/", permanent=True)
|
||||||
|
return
|
||||||
|
absolute_path = os.path.join(absolute_path, self.default_filename)
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
366
zypper-pkgrepo-alreadyconfigured-585.patch
Normal file
366
zypper-pkgrepo-alreadyconfigured-585.patch
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
From 6b6ba4bdbd4b4c52a46bf3d0bcdbaca6b47534d1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Georg <georg@lysergic.dev>
|
||||||
|
Date: Wed, 28 Jun 2023 16:39:30 +0200
|
||||||
|
Subject: [PATCH] Zypper pkgrepo alreadyconfigured (#585)
|
||||||
|
|
||||||
|
* Fix zypper repository reconfiguration
|
||||||
|
|
||||||
|
See https://github.com/saltstack/salt/issues/63402 for issue details.
|
||||||
|
|
||||||
|
Signed-off-by: Georg Pfuetzenreuter <georg.pfuetzenreuter@suse.com>
|
||||||
|
|
||||||
|
* Functional pkgrepo tests for SUSE
|
||||||
|
|
||||||
|
Signed-off-by: Georg Pfuetzenreuter <georg.pfuetzenreuter@suse.com>
|
||||||
|
|
||||||
|
* Change pkgrepo state to use f-strings
|
||||||
|
|
||||||
|
Follow new styling rules.
|
||||||
|
|
||||||
|
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
|
||||||
|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Signed-off-by: Georg Pfuetzenreuter <georg.pfuetzenreuter@suse.com>
|
||||||
|
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
|
||||||
|
---
|
||||||
|
changelog/63402.fixed.md | 1 +
|
||||||
|
salt/states/pkgrepo.py | 27 ++-
|
||||||
|
.../functional/states/pkgrepo/test_suse.py | 219 ++++++++++++++++++
|
||||||
|
3 files changed, 235 insertions(+), 12 deletions(-)
|
||||||
|
create mode 100644 changelog/63402.fixed.md
|
||||||
|
create mode 100644 tests/pytests/functional/states/pkgrepo/test_suse.py
|
||||||
|
|
||||||
|
diff --git a/changelog/63402.fixed.md b/changelog/63402.fixed.md
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..c38715738a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/changelog/63402.fixed.md
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Repaired zypper repositories being reconfigured without changes
|
||||||
|
diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py
|
||||||
|
index c2d23f95bb..f041644287 100644
|
||||||
|
--- a/salt/states/pkgrepo.py
|
||||||
|
+++ b/salt/states/pkgrepo.py
|
||||||
|
@@ -464,7 +464,7 @@ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs):
|
||||||
|
pre = __salt__["pkg.get_repo"](repo=repo, **kwargs)
|
||||||
|
except CommandExecutionError as exc:
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "Failed to examine repo '{}': {}".format(name, exc)
|
||||||
|
+ ret["comment"] = f"Failed to examine repo '{name}': {exc}"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# This is because of how apt-sources works. This pushes distro logic
|
||||||
|
@@ -500,7 +500,10 @@ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs):
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
- break
|
||||||
|
+ if kwarg in ("comps", "key_url"):
|
||||||
|
+ break
|
||||||
|
+ else:
|
||||||
|
+ continue
|
||||||
|
elif kwarg in ("comps", "key_url"):
|
||||||
|
if sorted(sanitizedkwargs[kwarg]) != sorted(pre[kwarg]):
|
||||||
|
break
|
||||||
|
@@ -546,7 +549,7 @@ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
ret["result"] = True
|
||||||
|
- ret["comment"] = "Package repo '{}' already configured".format(name)
|
||||||
|
+ ret["comment"] = f"Package repo '{name}' already configured"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
if __opts__["test"]:
|
||||||
|
@@ -581,7 +584,7 @@ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs):
|
||||||
|
# This is another way to pass information back from the mod_repo
|
||||||
|
# function.
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "Failed to configure repo '{}': {}".format(name, exc)
|
||||||
|
+ ret["comment"] = f"Failed to configure repo '{name}': {exc}"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -597,10 +600,10 @@ def managed(name, ppa=None, copr=None, aptkey=True, **kwargs):
|
||||||
|
ret["changes"] = {"repo": repo}
|
||||||
|
|
||||||
|
ret["result"] = True
|
||||||
|
- ret["comment"] = "Configured package repo '{}'".format(name)
|
||||||
|
+ ret["comment"] = f"Configured package repo '{name}'"
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "Failed to confirm config of repo '{}': {}".format(name, exc)
|
||||||
|
+ ret["comment"] = f"Failed to confirm config of repo '{name}': {exc}"
|
||||||
|
|
||||||
|
# Clear cache of available packages, if present, since changes to the
|
||||||
|
# repositories may change the packages that are available.
|
||||||
|
@@ -700,11 +703,11 @@ def absent(name, **kwargs):
|
||||||
|
repo = __salt__["pkg.get_repo"](stripname, **kwargs)
|
||||||
|
except CommandExecutionError as exc:
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "Failed to configure repo '{}': {}".format(name, exc)
|
||||||
|
+ ret["comment"] = f"Failed to configure repo '{name}': {exc}"
|
||||||
|
return ret
|
||||||
|
|
||||||
|
if not repo:
|
||||||
|
- ret["comment"] = "Package repo {} is absent".format(name)
|
||||||
|
+ ret["comment"] = f"Package repo {name} is absent"
|
||||||
|
ret["result"] = True
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -727,7 +730,7 @@ def absent(name, **kwargs):
|
||||||
|
repos = __salt__["pkg.list_repos"]()
|
||||||
|
if stripname not in repos:
|
||||||
|
ret["changes"]["repo"] = name
|
||||||
|
- ret["comment"] = "Removed repo {}".format(name)
|
||||||
|
+ ret["comment"] = f"Removed repo {name}"
|
||||||
|
|
||||||
|
if not remove_key:
|
||||||
|
ret["result"] = True
|
||||||
|
@@ -736,14 +739,14 @@ def absent(name, **kwargs):
|
||||||
|
removed_keyid = __salt__["pkg.del_repo_key"](stripname, **kwargs)
|
||||||
|
except (CommandExecutionError, SaltInvocationError) as exc:
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] += ", but failed to remove key: {}".format(exc)
|
||||||
|
+ ret["comment"] += f", but failed to remove key: {exc}"
|
||||||
|
else:
|
||||||
|
ret["result"] = True
|
||||||
|
ret["changes"]["keyid"] = removed_keyid
|
||||||
|
- ret["comment"] += ", and keyid {}".format(removed_keyid)
|
||||||
|
+ ret["comment"] += f", and keyid {removed_keyid}"
|
||||||
|
else:
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "Failed to remove repo {}".format(name)
|
||||||
|
+ ret["comment"] = f"Failed to remove repo {name}"
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
diff --git a/tests/pytests/functional/states/pkgrepo/test_suse.py b/tests/pytests/functional/states/pkgrepo/test_suse.py
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..19ba928ce6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/tests/pytests/functional/states/pkgrepo/test_suse.py
|
||||||
|
@@ -0,0 +1,219 @@
|
||||||
|
+import pytest
|
||||||
|
+
|
||||||
|
+pytestmark = [
|
||||||
|
+ pytest.mark.destructive_test,
|
||||||
|
+ pytest.mark.skip_if_not_root,
|
||||||
|
+]
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.fixture
|
||||||
|
+def pkgrepo(states, grains):
|
||||||
|
+ if grains["os_family"] != "Suse":
|
||||||
|
+ raise pytest.skip.Exception(
|
||||||
|
+ "Test is only applicable to SUSE based operating systems",
|
||||||
|
+ _use_item_location=True,
|
||||||
|
+ )
|
||||||
|
+ return states.pkgrepo
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.fixture
|
||||||
|
+def suse_state_tree(grains, pkgrepo, state_tree):
|
||||||
|
+ managed_sls_contents = """
|
||||||
|
+ salttest:
|
||||||
|
+ pkgrepo.managed:
|
||||||
|
+ - enabled: 1
|
||||||
|
+ - gpgcheck: 1
|
||||||
|
+ - comments:
|
||||||
|
+ - '# Salt Test'
|
||||||
|
+ - refresh: 1
|
||||||
|
+ {% if grains['osmajorrelease'] == 15 %}
|
||||||
|
+ - baseurl: https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15-SP4/standard/
|
||||||
|
+ - humanname: openSUSE Backports for SLE 15 SP4
|
||||||
|
+ - gpgkey: https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15-SP4/standard/repodata/repomd.xml.key
|
||||||
|
+ {% elif grains['osfullname'] == 'openSUSE Tumbleweed' %}
|
||||||
|
+ - baseurl: http://download.opensuse.org/tumbleweed/repo/oss/
|
||||||
|
+ - humanname: openSUSE Tumbleweed OSS
|
||||||
|
+ - gpgkey: https://download.opensuse.org/tumbleweed/repo/oss/repodata/repomd.xml.key
|
||||||
|
+ {% endif %}
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ absent_sls_contents = """
|
||||||
|
+ salttest:
|
||||||
|
+ pkgrepo:
|
||||||
|
+ - absent
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ modified_sls_contents = """
|
||||||
|
+ salttest:
|
||||||
|
+ pkgrepo.managed:
|
||||||
|
+ - enabled: 1
|
||||||
|
+ - gpgcheck: 1
|
||||||
|
+ - comments:
|
||||||
|
+ - '# Salt Test (modified)'
|
||||||
|
+ - refresh: 1
|
||||||
|
+ {% if grains['osmajorrelease'] == 15 %}
|
||||||
|
+ - baseurl: https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15-SP4/standard/
|
||||||
|
+ - humanname: Salt modified Backports
|
||||||
|
+ - gpgkey: https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15-SP4/standard/repodata/repomd.xml.key
|
||||||
|
+ {% elif grains['osfullname'] == 'openSUSE Tumbleweed' %}
|
||||||
|
+ - baseurl: http://download.opensuse.org/tumbleweed/repo/oss/
|
||||||
|
+ - humanname: Salt modified OSS
|
||||||
|
+ - gpgkey: https://download.opensuse.org/tumbleweed/repo/oss/repodata/repomd.xml.key
|
||||||
|
+ {% endif %}
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ managed_state_file = pytest.helpers.temp_file(
|
||||||
|
+ "pkgrepo/managed.sls", managed_sls_contents, state_tree
|
||||||
|
+ )
|
||||||
|
+ absent_state_file = pytest.helpers.temp_file(
|
||||||
|
+ "pkgrepo/absent.sls", absent_sls_contents, state_tree
|
||||||
|
+ )
|
||||||
|
+ modified_state_file = pytest.helpers.temp_file(
|
||||||
|
+ "pkgrepo/modified.sls", modified_sls_contents, state_tree
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ try:
|
||||||
|
+ with managed_state_file, absent_state_file, modified_state_file:
|
||||||
|
+ yield
|
||||||
|
+ finally:
|
||||||
|
+ pass
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.requires_salt_states("pkgrepo.managed", "pkgrepo.absent")
|
||||||
|
+def test_pkgrepo_managed_absent(grains, modules, subtests, suse_state_tree):
|
||||||
|
+ """
|
||||||
|
+ Test adding and removing a repository
|
||||||
|
+ """
|
||||||
|
+ add_repo_test_passed = False
|
||||||
|
+
|
||||||
|
+ def _run(name, test=False):
|
||||||
|
+ return modules.state.sls(
|
||||||
|
+ mods=name,
|
||||||
|
+ test=test,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ with subtests.test("Add repository"):
|
||||||
|
+ ret = _run("pkgrepo.managed")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.result is True
|
||||||
|
+ add_repo_test_passed = True
|
||||||
|
+
|
||||||
|
+ if add_repo_test_passed is False:
|
||||||
|
+ pytest.skip("Adding the repository failed, skipping removal tests.")
|
||||||
|
+
|
||||||
|
+ with subtests.test("Remove repository, test"):
|
||||||
|
+ ret = _run("pkgrepo.absent", test=True)
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {}
|
||||||
|
+ assert state.comment.startswith("Package repo 'salttest' will be removed.")
|
||||||
|
+ assert state.result is None
|
||||||
|
+
|
||||||
|
+ with subtests.test("Remove repository"):
|
||||||
|
+ ret = _run("pkgrepo.absent")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.result is True
|
||||||
|
+
|
||||||
|
+ with subtests.test("Remove repository again, test"):
|
||||||
|
+ ret = _run("pkgrepo.absent", test=True)
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {}
|
||||||
|
+ assert state.comment == "Package repo salttest is absent"
|
||||||
|
+ assert state.result is True
|
||||||
|
+
|
||||||
|
+ with subtests.test("Remove repository again"):
|
||||||
|
+ ret = _run("pkgrepo.absent")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {}
|
||||||
|
+ assert state.comment == "Package repo salttest is absent"
|
||||||
|
+ assert state.result is True
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@pytest.mark.requires_salt_states("pkgrepo.managed")
|
||||||
|
+def test_pkgrepo_managed_modify(grains, modules, subtests, suse_state_tree):
|
||||||
|
+ """
|
||||||
|
+ Test adding and modifying a repository
|
||||||
|
+ """
|
||||||
|
+ add_repo_test_passed = False
|
||||||
|
+
|
||||||
|
+ def _run(name, test=False):
|
||||||
|
+ return modules.state.sls(
|
||||||
|
+ mods=name,
|
||||||
|
+ test=test,
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ with subtests.test("Add repository, test"):
|
||||||
|
+ ret = _run("pkgrepo.managed", test=True)
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {"repo": "salttest"}
|
||||||
|
+ assert state.comment.startswith(
|
||||||
|
+ "Package repo 'salttest' would be configured."
|
||||||
|
+ )
|
||||||
|
+ assert state.result is None
|
||||||
|
+
|
||||||
|
+ with subtests.test("Add repository"):
|
||||||
|
+ ret = _run("pkgrepo.managed")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {"repo": "salttest"}
|
||||||
|
+ assert state.comment == "Configured package repo 'salttest'"
|
||||||
|
+ assert state.result is True
|
||||||
|
+ add_repo_test_passed = True
|
||||||
|
+
|
||||||
|
+ if add_repo_test_passed is False:
|
||||||
|
+ pytest.skip("Adding the repository failed, skipping modification tests.")
|
||||||
|
+
|
||||||
|
+ with subtests.test("Add repository again, test"):
|
||||||
|
+ ret = _run("pkgrepo.managed", test=True)
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {}
|
||||||
|
+ assert state.comment == "Package repo 'salttest' already configured"
|
||||||
|
+ assert state.result is True
|
||||||
|
+
|
||||||
|
+ with subtests.test("Add repository again"):
|
||||||
|
+ ret = _run("pkgrepo.managed")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.result is True
|
||||||
|
+ assert state.changes == {}
|
||||||
|
+ assert state.comment == "Package repo 'salttest' already configured"
|
||||||
|
+
|
||||||
|
+ with subtests.test("Modify repository, test"):
|
||||||
|
+ ret = _run("pkgrepo.modified", test=True)
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.changes == {
|
||||||
|
+ "comments": {"new": ["# Salt Test (modified)"], "old": None},
|
||||||
|
+ "refresh": {"new": 1, "old": None},
|
||||||
|
+ "gpgkey": {
|
||||||
|
+ "new": "https://download.opensuse.org/repositories/openSUSE:/Backports:/SLE-15-SP4/standard/repodata/repomd.xml.key",
|
||||||
|
+ "old": None,
|
||||||
|
+ },
|
||||||
|
+ "name": {
|
||||||
|
+ "new": "Salt modified Backports",
|
||||||
|
+ "old": "openSUSE Backports for SLE 15 SP4",
|
||||||
|
+ },
|
||||||
|
+ }
|
||||||
|
+ assert state.comment.startswith(
|
||||||
|
+ "Package repo 'salttest' would be configured."
|
||||||
|
+ )
|
||||||
|
+ assert state.result is None
|
||||||
|
+
|
||||||
|
+ with subtests.test("Modify repository"):
|
||||||
|
+ ret = _run("pkgrepo.modified")
|
||||||
|
+ assert ret.failed is False
|
||||||
|
+ for state in ret:
|
||||||
|
+ assert state.result is True
|
||||||
|
+ assert state.changes == {
|
||||||
|
+ "name": {
|
||||||
|
+ "new": "Salt modified Backports",
|
||||||
|
+ "old": "openSUSE Backports for SLE 15 SP4",
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ assert state.comment == "Configured package repo 'salttest'"
|
||||||
|
--
|
||||||
|
2.41.0
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user