add app-admin/salt with python-3.11 compat

This commit is contained in:
2023-06-08 08:27:35 +03:00
parent 7397049453
commit 60d7412b0b
24 changed files with 776 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
# /etc/conf.d/salt-api: config file for /etc/init.d/salt-api
# see man pages for salt-minion or run `salt-api --help`
# for valid cmdline options
SALT_OPTS="--log-level=warning"

View File

@@ -0,0 +1,19 @@
#!/sbin/openrc-run
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
command="/usr/bin/salt-api"
command_args="${SALT_OPTS}"
pidfile="/var/run/supervisor-salt-api.pid"
daemon_pidfile="/var/run/salt-api.pid"
command_args_background="--daemon --pid-file=\"${daemon_pidfile}\""
name="SALT API daemon"
retry="20"
supervisor=supervise-daemon
output_logger="logger -p daemon.info -t salt-api.stdout --"
error_logger="logger -p daemon.err -t salt-api.error --"
depend() {
use net logger
}

View File

@@ -0,0 +1,5 @@
# /etc/conf.d/salt-master: config file for /etc/init.d/salt-master
# see man pages for salt-minion or run `salt-master --help`
# for valid cmdline options
SALT_OPTS="--log-level=warning"

View File

@@ -0,0 +1,19 @@
#!/sbin/openrc-run
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
command="/usr/bin/salt-master"
command_args="${SALT_OPTS}"
pidfile="/var/run/supervisor-salt-master.pid"
daemon_pidfile="/var/run/salt-master.pid"
command_args_background="--daemon --pid-file=\"${daemon_pidfile}\""
name="SALT master daemon"
retry="20"
supervisor=supervise-daemon
output_logger="logger -p daemon.info -t salt-master.stdout --"
error_logger="logger -p daemon.err -t salt-master.error --"
depend() {
use net logger
}

View File

@@ -0,0 +1,5 @@
# /etc/conf.d/salt-minion: config file for /etc/init.d/salt-minion
# see man pages for salt-minion or run `salt-minion --help`
# for valid cmdline options
SALT_OPTS="--log-level=warning"

View File

@@ -0,0 +1,20 @@
#!/sbin/openrc-run
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
command="/usr/bin/salt-minion"
command_args="${SALT_OPTS}"
pidfile="/var/run/supervisor-salt-minion.pid"
daemon_pidfile="/var/run/salt-minion.pid"
command_args_background="--daemon --pid-file=\"${daemon_pidfile}\""
name="SALT minion daemon"
retry="20"
supervisor=supervise-daemon
output_logger="logger -p daemon.info -t salt-minion.stdout --"
error_logger="logger -p daemon.err -t salt-minion.error --"
depend() {
need net
use logger
}

View File

@@ -0,0 +1,27 @@
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

@@ -0,0 +1,13 @@
diff --git a/salt/modules/gentoolkitmod.py b/salt/modules/gentoolkitmod.py
index cc78c37114..f0949d19a8 100644
--- a/salt/modules/gentoolkitmod.py
+++ b/salt/modules/gentoolkitmod.py
@@ -49,7 +49,7 @@ def revdep_rebuild(lib=None):
salt '*' gentoolkit.revdep_rebuild
"""
- cmd = "revdep-rebuild -i --quiet --no-progress"
+ cmd = "revdep-rebuild -i --quiet"
if lib is not None:
cmd += " --library={0}".format(lib)
return __salt__["cmd.retcode"](cmd, python_shell=False) == 0

View File

@@ -0,0 +1,20 @@
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

@@ -0,0 +1,25 @@
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

@@ -0,0 +1,12 @@
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

@@ -0,0 +1,94 @@
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

@@ -0,0 +1,29 @@
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

@@ -0,0 +1,123 @@
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

@@ -0,0 +1,13 @@
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

@@ -0,0 +1,40 @@
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,10 @@
[Unit]
Description=The Salt Master Server
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/salt-api
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,10 @@
[Unit]
Description=The Salt Master Server
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/salt-master
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,10 @@
[Unit]
Description=The Salt Minion
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/salt-minion
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,10 @@
[Unit]
Description=The Salt Master Server
After=syslog.target network.target
[Service]
Type=simple
ExecStart=/usr/bin/salt-syndic
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,5 @@
# /etc/conf.d/salt-syndic: config file for /etc/init.d/salt-syndic
# see man pages for salt-minion or run `salt-syndic --help`
# for valid cmdline options
SALT_OPTS="--log-level=warning"

View File

@@ -0,0 +1,19 @@
#!/sbin/openrc-run
# Copyright 1999-2021 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
command="/usr/bin/salt-syndic"
command_args="${SALT_OPTS}"
pidfile="/var/run/supervisor-salt-syndic.pid"
daemon_pidfile="/var/run/salt-syndic.pid"
command_args_background="--daemon --pid-file=\"${daemon_pidfile}\""
name="SALT syndic daemon"
retry="20"
supervisor=supervise-daemon
output_logger="logger -p daemon.info -t salt-syndic.stdout --"
error_logger="logger -p daemon.err -t salt-syndic.error --"
depend() {
use net logger
}