app-admin/salt: bump to v3007.2

This commit is contained in:
2025-05-24 13:18:17 +03:00
parent 065c7f9947
commit 66e4c264fe
15 changed files with 716 additions and 626 deletions

View File

@@ -1,27 +0,0 @@
diff --git a/tests/unit/utils/test_verify.py b/tests/unit/utils/test_verify.py
index 5662cf621b..16aa6d08da 100644
--- a/tests/unit/utils/test_verify.py
+++ b/tests/unit/utils/test_verify.py
@@ -329,6 +329,7 @@ class TestVerifyLog(TestCase):
self.assertTrue(os.path.exists(path))
+@skipIf(True, "skipping since temp dir is a symlink")
class TestCleanPath(TestCase):
"""
salt.utils.clean_path works as expected
@@ -394,12 +395,14 @@ class TestCleanPathLink(TestCase):
def tearDown(self):
shutil.rmtree(self.tmpdir)
+ @skipIf(True, "skipping since temp dir is a symlink")
def test_clean_path_symlinked_src(self):
test_path = os.path.join(self.from_path, "test")
expect_path = os.path.join(self.to_path, "test")
ret = clean_path(self.from_path, test_path)
assert ret == expect_path, "{} is not {}".format(ret, expect_path)
+ @skipIf(True, "skipping since temp dir is a symlink")
def test_clean_path_symlinked_tgt(self):
test_path = os.path.join(self.to_path, "test")
expect_path = os.path.join(self.to_path, "test")

View File

@@ -1,20 +0,0 @@
diff --git a/tests/unit/modules/test_boto_apigateway.py b/tests/unit/modules/test_boto_apigateway.py
index 6ee6aeb002..db9aeaee95 100644
--- a/tests/unit/modules/test_boto_apigateway.py
+++ b/tests/unit/modules/test_boto_apigateway.py
@@ -154,6 +154,7 @@ def _has_required_botocore():
return True
+@skipIf(True, "Causes machines to OOM")
class BotoApiGatewayTestCaseBase(TestCase, LoaderModuleMockMixin):
conn = None
@@ -190,6 +191,7 @@ class BotoApiGatewayTestCaseBase(TestCase, LoaderModuleMockMixin):
self.addCleanup(delattr, self, "utils")
+@skipIf(True, "Causes machines to OOM")
class BotoApiGatewayTestCaseMixin:
def _diff_list_dicts(self, listdict1, listdict2, sortkey):
"""

View File

@@ -1,25 +0,0 @@
diff --git a/tests/integration/files/file/base/_modules/runtests_helpers.py b/tests/integration/files/file/base/_modules/runtests_helpers.py
index 3ee0e2da5f..abf9b71431 100644
--- a/tests/integration/files/file/base/_modules/runtests_helpers.py
+++ b/tests/integration/files/file/base/_modules/runtests_helpers.py
@@ -27,7 +27,7 @@ except ImportError:
else "/tmp"
)
# This tempdir path is defined on tests.integration.__init__
- TMP = os.path.join(SYS_TMP_DIR, "salt-tests-tmpdir")
+ TMP = os.path.join(SYS_TMP_DIR, "salt-t")
class RUNTIME_VARS:
TMP = TMP
diff --git a/tests/unit/ext/test_ipaddress.py b/tests/unit/ext/test_ipaddress.py
index 4fd87d1c3f..43306ba8f4 100644
--- a/tests/unit/ext/test_ipaddress.py
+++ b/tests/unit/ext/test_ipaddress.py
@@ -137,6 +137,7 @@ class CommonTestMixin:
class CommonTestMixin_v4(CommonTestMixin):
+ @pytest.mark.skipif(sys.hexversion >= 0x03090000, reason="leading zeros disallowed in 3.9+")
def test_leading_zeros(self):
self.assertInstancesEqual("000.000.000.000", "0.0.0.0")
self.assertInstancesEqual("192.168.000.001", "192.168.0.1")

View File

@@ -1,12 +0,0 @@
diff --git a/requirements/zeromq.txt b/requirements/zeromq.txt
index eb4d796418..ffa1589043 100644
--- a/requirements/zeromq.txt
+++ b/requirements/zeromq.txt
@@ -1,6 +1,4 @@
-r base.txt
-r crypto.txt
-pyzmq<=20.0.0 ; python_version < "3.6"
-pyzmq>=17.0.0 ; python_version < "3.9"
-pyzmq>19.0.2 ; python_version >= "3.9"
+pyzmq

View File

@@ -1,94 +0,0 @@
diff --git a/tests/conftest.py b/tests/conftest.py
index 24ecf57e04..babc7ced90 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -684,8 +684,6 @@ def salt_factories_config():
"""
return {
"code_dir": str(CODE_DIR),
- "inject_coverage": MAYBE_RUN_COVERAGE,
- "inject_sitecustomize": MAYBE_RUN_COVERAGE,
"start_timeout": 120
if (os.environ.get("JENKINS_URL") or os.environ.get("CI"))
else 60,
diff --git a/tests/pytests/unit/_logging/handlers/test_deferred_stream_handler.py b/tests/pytests/unit/_logging/handlers/test_deferred_stream_handler.py
index 230da8abc8..f6f1a70ce4 100644
--- a/tests/pytests/unit/_logging/handlers/test_deferred_stream_handler.py
+++ b/tests/pytests/unit/_logging/handlers/test_deferred_stream_handler.py
@@ -62,6 +62,7 @@ def _deferred_write_on_flush_proc_target():
assert stds.stderr == "Foo\nBar\n"
+@pytest.mark.skip("doesn't work with sandbox")
def test_sync_with_handlers():
proc = multiprocessing.Process(target=_sync_with_handlers_proc_target)
proc.start()
@@ -69,6 +70,7 @@ def test_sync_with_handlers():
assert proc.exitcode == 0
+@pytest.mark.skip("doesn't work with sandbox")
def test_deferred_write_on_flush():
proc = multiprocessing.Process(target=_deferred_write_on_flush_proc_target)
proc.start()
diff --git a/tests/pytests/unit/modules/test_portage_config.py b/tests/pytests/unit/modules/test_portage_config.py
index 5cc6b90596..f344526909 100644
--- a/tests/pytests/unit/modules/test_portage_config.py
+++ b/tests/pytests/unit/modules/test_portage_config.py
@@ -53,7 +53,7 @@ def test_enforce_nice_config(tmp_path):
("use", ["apple", "-banana", "ananas", "orange"]),
]
- base_path = str(tmp_path / "/package.{0}")
+ base_path = str(f"{tmp_path}/package.{{0}}")
def make_line(atom, addition):
return atom + (" " + addition if addition != "" else "") + "\n"
@@ -72,14 +72,3 @@ def test_enforce_nice_config(tmp_path):
portage_config, "_merge_flags", lambda l1, l2, _: list(set(l1 + l2))
):
portage_config.enforce_nice_config()
-
- for typ, additions in supported:
- for atom, file_name in atoms:
- with salt.utils.files.fopen(
- base_path.format(typ) + "/" + file_name, "r"
- ) as fh:
- for line in fh:
- for atom in line:
- assert atom not in line
- for addition in additions:
- assert addition not in line
diff --git a/tests/support/cli_scripts.py b/tests/support/cli_scripts.py
index 270af75d4b..50c08f4ed2 100644
--- a/tests/support/cli_scripts.py
+++ b/tests/support/cli_scripts.py
@@ -32,8 +32,6 @@ def get_script_path(bin_dir, script_name):
bin_dir=bin_dir,
script_name=script_name,
code_dir=RUNTIME_VARS.CODE_DIR,
- inject_coverage="COVERAGE_PROCESS_START" in os.environ,
- inject_sitecustomize="COVERAGE_PROCESS_START" in os.environ,
)
log.info("Returning script path %r", script_path)
return script_path
diff --git a/tests/unit/utils/test_schema.py b/tests/unit/utils/test_schema.py
index 8c648f5288..ce5715a562 100644
--- a/tests/unit/utils/test_schema.py
+++ b/tests/unit/utils/test_schema.py
@@ -873,6 +873,7 @@ class ConfigTestCase(TestCase):
)
@skipIf(HAS_JSONSCHEMA is False, "The 'jsonschema' library is missing")
+ @skipIf(True, "Does not work with sandbox")
def test_hostname_config_validation(self):
class TestConf(schema.Schema):
item = schema.HostnameItem(title="Item", description="Item description")
@@ -2099,6 +2100,7 @@ class ConfigTestCase(TestCase):
self.assertEqual(item.serialize(), {"not": item.item.serialize()})
@skipIf(HAS_JSONSCHEMA is False, "The 'jsonschema' library is missing")
+ @skipIf(True, "Does not work with sandbox")
def test_not_config_validation(self):
class TestConf(schema.Schema):
item = schema.ArrayItem(

View File

@@ -1,29 +0,0 @@
diff --git a/salt/utils/entrypoints.py b/salt/utils/entrypoints.py
index 3effa0b494..9452878ade 100644
--- a/salt/utils/entrypoints.py
+++ b/salt/utils/entrypoints.py
@@ -38,13 +38,20 @@ def iter_entry_points(group, name=None):
entry_points_listing = []
entry_points = importlib_metadata.entry_points()
- for entry_point_group, entry_points_list in entry_points.items():
- if entry_point_group != group:
- continue
- for entry_point in entry_points_list:
+ try:
+ for entry_point in entry_points.select(group=group):
if name is not None and entry_point.name != name:
continue
entry_points_listing.append(entry_point)
+ except AttributeError:
+ # importlib-metadata<5.0.0
+ for entry_point_group, entry_points_list in entry_points.items():
+ if entry_point_group != group:
+ continue
+ for entry_point in entry_points_list:
+ if name is not None and entry_point.name != name:
+ continue
+ entry_points_listing.append(entry_point)
return entry_points_listing

View File

@@ -1,123 +0,0 @@
diff --git a/salt/modules/file.py b/salt/modules/file.py
index f39d618203..93eeaf312e 100644
--- a/salt/modules/file.py
+++ b/salt/modules/file.py
@@ -16,7 +16,6 @@ import hashlib
import itertools
import logging
import mmap
-import operator
import os
import re
import shutil
@@ -28,7 +27,6 @@ import time
import urllib.parse
from collections import namedtuple
from collections.abc import Iterable, Mapping
-from functools import reduce
import salt.utils.args
import salt.utils.atomicfile
@@ -1622,38 +1620,38 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
def _get_flags(flags):
"""
- Return an integer appropriate for use as a flag for the re module from a
- list of human-readable strings
+ Return the names of the Regex flags that correspond to flags
.. code-block:: python
- >>> _get_flags(['MULTILINE', 'IGNORECASE'])
- 10
+ >>> _get_flags(['IGNORECASE', 'MULTILINE'])
+ re.IGNORECASE|re.MULTILINE
>>> _get_flags('MULTILINE')
- 8
- >>> _get_flags(2)
- 2
+ re.MULTILINE
+ >>> _get_flags(8)
+ re.MULTILINE
+ >>> _get_flags(re.IGNORECASE)
+ re.IGNORECASE
"""
- if isinstance(flags, str):
+ if isinstance(flags, re.RegexFlag):
+ return flags
+ elif isinstance(flags, int):
+ return re.RegexFlag(flags)
+ elif isinstance(flags, str):
flags = [flags]
if isinstance(flags, Iterable) and not isinstance(flags, Mapping):
- _flags_acc = [0] # An initial 0 avoids resucing on empty list, an error
+ _flags = re.RegexFlag(0)
for flag in flags:
- _flag = getattr(re, str(flag).upper())
-
- if not isinstance(_flag, int):
- raise SaltInvocationError("Invalid re flag given: {}".format(flag))
-
- _flags_acc.append(_flag)
-
- return reduce(operator.__or__, _flags_acc)
- elif isinstance(flags, int):
- return flags
+ _flag = getattr(re.RegexFlag, str(flag).upper(), None)
+ if not _flag:
+ raise CommandExecutionError(f"Invalid re flag given: {flag}")
+ _flags |= _flag
+ return _flags
else:
- raise SaltInvocationError(
- 'Invalid re flags: "{}", must be given either as a single flag '
- "string, a list of strings, or as an integer".format(flags)
+ raise CommandExecutionError(
+ f'Invalid re flags: "{flags}", must be given either as a single flag '
+ "string, a list of strings, as an integer, or as an re flag"
)
@@ -2513,8 +2511,8 @@ def replace(
"Only one of append and prepend_if_not_found is permitted"
)
- flags_num = _get_flags(flags)
- cpattern = re.compile(salt.utils.stringutils.to_bytes(pattern), flags_num)
+ re_flags = _get_flags(flags)
+ cpattern = re.compile(salt.utils.stringutils.to_bytes(pattern), re_flags)
filesize = os.path.getsize(path)
if bufsize == "file":
bufsize = filesize
@@ -2582,7 +2580,7 @@ def replace(
"^{}($|(?=\r\n))".format(re.escape(content))
),
r_data,
- flags=flags_num,
+ flags=re_flags,
):
# Content was found, so set found.
found = True
@@ -3132,7 +3130,11 @@ def search(path, pattern, flags=8, bufsize=1, ignore_if_missing=False, multiline
salt '*' file.search /etc/crontab 'mymaintenance.sh'
"""
if multiline:
- flags = _add_flags(flags, "MULTILINE")
+ re_flags = _add_flags(flags, "MULTILINE")
+ else:
+ re_flags = _get_flags(flags)
+
+ if re.RegexFlag.MULTILINE in re_flags:
bufsize = "file"
# This function wraps file.replace on purpose in order to enforce
@@ -3142,7 +3144,7 @@ def search(path, pattern, flags=8, bufsize=1, ignore_if_missing=False, multiline
path,
pattern,
"",
- flags=flags,
+ flags=re_flags,
bufsize=bufsize,
dry_run=True,
search_only=True,

View File

@@ -1,13 +0,0 @@
diff --git a/setup.py b/setup.py
index bd11ff95f7..3b83f7b6ff 100755
--- a/setup.py
+++ b/setup.py
@@ -1173,7 +1173,7 @@ class SaltDistribution(distutils.dist.Distribution):
return scripts
@property
- def _property_entry_points(self):
+ def _property_entry_points_disabled(self):
entrypoints = {
"pyinstaller40": [
"hook-dirs = salt.utils.pyinstaller:get_hook_dirs",

View File

@@ -1,40 +0,0 @@
diff --git a/tests/unit/utils/test_schema.py b/tests/unit/utils/test_schema.py
index 8c648f5288..5886813e28 100644
--- a/tests/unit/utils/test_schema.py
+++ b/tests/unit/utils/test_schema.py
@@ -528,7 +528,7 @@ class ConfigTestCase(TestCase):
jsonschema.validate(
{"personal_access_token": "foo"}, Requirements.serialize()
)
- if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0"):
+ if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0") and JSONSCHEMA_VERSION < _LooseVersion("4.17.0"):
self.assertIn(
"'ssh_key_file' is a required property", excinfo.exception.message
)
@@ -1851,7 +1851,7 @@ class ConfigTestCase(TestCase):
jsonschema.validate(
{"item": {"sides": "4", "color": "blue"}}, TestConf.serialize()
)
- if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0"):
+ if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0") and JSONSCHEMA_VERSION < _LooseVersion("4.17.0"):
self.assertIn("'4'", excinfo.exception.message)
self.assertIn("is not of type", excinfo.exception.message)
self.assertIn("'boolean'", excinfo.exception.message)
@@ -1974,7 +1974,7 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": ["maybe"]}, TestConf.serialize())
- if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0"):
+ if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0") and JSONSCHEMA_VERSION < _LooseVersion("4.17.0"):
self.assertIn("'maybe'", excinfo.exception.message)
self.assertIn("is not one of", excinfo.exception.message)
self.assertIn("'yes'", excinfo.exception.message)
@@ -2036,7 +2036,7 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": ["maybe"]}, TestConf.serialize())
- if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0"):
+ if JSONSCHEMA_VERSION >= _LooseVersion("3.0.0") and JSONSCHEMA_VERSION < _LooseVersion("4.17.0"):
self.assertIn("'maybe'", excinfo.exception.message)
self.assertIn("is not one of", excinfo.exception.message)
self.assertIn("'yes'", excinfo.exception.message)

View File

@@ -0,0 +1,13 @@
diff --git a/salt/auth/pam.py b/salt/auth/pam.py
index 6e179deb7c..935c523606 100644
--- a/salt/auth/pam.py
+++ b/salt/auth/pam.py
@@ -228,7 +228,7 @@ def authenticate(username, password):
env["SALT_PAM_PASSWORD"] = password
env["SALT_PAM_SERVICE"] = __opts__.get("auth.pam.service", "login")
env["SALT_PAM_ENCODING"] = __salt_system_encoding__
- pyexe = pathlib.Path(__opts__.get("auth.pam.python", "/usr/bin/python3")).resolve()
+ pyexe = pathlib.Path(__opts__.get("auth.pam.python", f"/usr/bin/{os.environ['EPYTHON']}")).resolve()
pyfile = pathlib.Path(__file__).resolve()
if not pyexe.exists():
log.error("Error 'auth.pam.python' config value does not exist: %s", pyexe)

View File

@@ -0,0 +1,53 @@
From 0f69a5a227bfba6ced8a3826d69d556967967fcc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?=
<marmarek@invisiblethingslab.com>
Date: Wed, 18 Sep 2024 04:54:24 +0200
Subject: [PATCH] Fix Python3.13 compatibility regarding urllib.parse module
Python 3.13 fixed handling relative paths in urllib.parse module.
Specifically, relative file URL is now constructed as file:path instead
of converting it to absolute file:///path. This breaks
salt.utils.url.create which expects file:/// specifically. The mismatch
results in for example changing salt://top.sls into salt://.sls and thus
not finding the top file.
Fix this by handling both prefixes.
Relevant python change: https://github.com/python/cpython/issues/85110
Fixes: #66898
---
changelog/66898.fixed.md | 1 +
salt/utils/url.py | 5 ++---
2 files changed, 3 insertions(+), 3 deletions(-)
create mode 100644 changelog/66898.fixed.md
diff --git a/changelog/66898.fixed.md b/changelog/66898.fixed.md
new file mode 100644
index 000000000000..2549d5e00ed1
--- /dev/null
+++ b/changelog/66898.fixed.md
@@ -0,0 +1 @@
+Fixed Python 3.13 compatibility regarding urllib.parse module
diff --git a/salt/utils/url.py b/salt/utils/url.py
index 478d8e911c2b..839db611c972 100644
--- a/salt/utils/url.py
+++ b/salt/utils/url.py
@@ -4,7 +4,7 @@
import re
import sys
-from urllib.parse import urlparse, urlunparse
+from urllib.parse import urlparse, urlunparse, urlunsplit
import salt.utils.data
import salt.utils.path
@@ -46,8 +46,7 @@ def create(path, saltenv=None):
path = salt.utils.data.decode(path)
query = f"saltenv={saltenv}" if saltenv else ""
- url = salt.utils.data.decode(urlunparse(("file", "", path, "", query, "")))
- return "salt://{}".format(url[len("file:///") :])
+ return f'salt://{salt.utils.data.decode(urlunsplit(("", "", path, query, "")))}'
def is_escaped(url):