Accepting request 1248212 from systemsmanagement:saltstack

- Fix issue of using update-alternatives with alts

- Fix virt_query outputter and add support for block devices
- Make _auth calls visible with master stats
- Repair mount.fstab_present always returning pending changes
- Set virtual grain in Podman systemd container
- Fix crash due wrong client reference on `SaltMakoTemplateLookup`
- Enhace batch async and fix some detected issues
- Added:
  * repair-virt_query-outputter-655.patch
  * make-_auth-calls-visible-with-master-stats-696.patch
  * repair-fstab_present-test-mode-702.patch
  * set-virtual-grain-in-podman-systemd-container-703.patch
  * fixed-file-client-private-attribute-reference-on-sal.patch
  * backport-batch-async-fixes-and-improvements-701.patch

- Enhacement of Salt packaging
  * Use update-alternatives for all salt scripts
  * Use flexible dependencies for the subpackages
  * Make salt-minion to require flavored zypp-plugin
  * Make zyppnotify to use update-alternatives
  * Drop unused yumnotify plugin
  * Add dependency to python3-dnf-plugins-core for RHEL based
- Fix tests failures after "repo.saltproject.io" deprecation
- Added:
  * fix-tests-failures-after-repo.saltproject.io-depreca.patch

OBS-URL: https://build.opensuse.org/request/show/1248212
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=167
This commit is contained in:
Dominique Leuenberger 2025-02-25 15:41:02 +00:00 committed by Git OBS Bridge
commit 77478fd453
10 changed files with 1690 additions and 54 deletions

View File

@ -1 +1 @@
a9b3f5bf8fd572965c589d95a7f99d36f7f37b62
4e81748d5e88d323e700a458ca0e9680acc81927

View File

@ -0,0 +1,336 @@
From 4fe7231fa99de8edc848367386f1a6a5192a0f58 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Fri, 21 Feb 2025 11:15:42 +0100
Subject: [PATCH] Backport batch async fixes and improvements (#701)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Backport batch async fixes and improvements
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
* Align batch_async tests
---------
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
---
salt/cli/batch_async.py | 60 ++++++++++++++++-----
tests/pytests/unit/cli/test_batch_async.py | 63 ++++++++--------------
2 files changed, 69 insertions(+), 54 deletions(-)
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
index 5d49993faa..92215d0e04 100644
--- a/salt/cli/batch_async.py
+++ b/salt/cli/batch_async.py
@@ -35,7 +35,7 @@ def batch_async_required(opts, minions, extra):
Check opts to identify if batch async is required for the operation.
"""
if not isinstance(minions, list):
- False
+ return False
batch_async_opts = opts.get("batch_async", {})
batch_async_threshold = (
batch_async_opts.get("threshold", 1)
@@ -179,6 +179,7 @@ class SharedEventsChannel:
self._used_by.discard(subscriber_id)
def destroy_unused(self):
+ log.trace("SharedEventsChannel.destroy_unused called")
if self._used_by:
return False
self.master_event.remove_event_handler(self.__handle_event)
@@ -267,6 +268,7 @@ class BatchAsync:
self.ended = False
self.event = self.events_channel.master_event
self.scheduled = False
+ self._start_batch_on_timeout = None
def __set_event_handler(self):
self.events_channel.subscribe(
@@ -278,6 +280,8 @@ class BatchAsync:
@salt.ext.tornado.gen.coroutine
def __event_handler(self, tag, data, op):
+ # IMPORTANT: This function must run fast and not wait for any other task,
+ # otherwise it would cause events to be stuck.
if not self.event:
return
try:
@@ -285,7 +289,9 @@ class BatchAsync:
if op == "ping_return":
self.minions.add(minion)
if self.targeted_minions == self.minions:
- yield self.start_batch()
+ # call start_batch and do not wait for timeout as we received
+ # the responses from all the targets
+ self.io_loop.add_callback(self.start_batch)
elif op == "find_job_return":
if data.get("return", None):
self.find_job_returned.add(minion)
@@ -293,7 +299,8 @@ class BatchAsync:
if minion in self.active:
self.active.remove(minion)
self.done_minions.add(minion)
- yield self.schedule_next()
+ if not self.active:
+ self.io_loop.add_callback(self.schedule_next)
except Exception as ex: # pylint: disable=W0703
log.error(
"Exception occured while processing event: %s: %s",
@@ -333,7 +340,7 @@ class BatchAsync:
)
if timedout_minions:
- yield self.schedule_next()
+ self.io_loop.add_callback(self.schedule_next)
if self.event and running:
self.find_job_returned = self.find_job_returned.difference(running)
@@ -344,6 +351,9 @@ class BatchAsync:
"""
Find if the job was finished on the minions
"""
+ log.trace(
+ "[%s] BatchAsync.find_job called for minions: %s", self.batch_jid, minions
+ )
if not self.event:
return
not_done = minions.difference(self.done_minions).difference(
@@ -386,6 +396,7 @@ class BatchAsync:
if not self.event:
return
self.__set_event_handler()
+ # call test.ping for all the targets in async way
ping_return = yield self.events_channel.local_client.run_job_async(
self.opts["tgt"],
"test.ping",
@@ -398,19 +409,24 @@ class BatchAsync:
listen=False,
**self.eauth,
)
+ # ping_return contains actual targeted minions and no actual responses
+ # from the minions as it's async and intended to populate targeted_minions set
self.targeted_minions = set(ping_return["minions"])
- # start batching even if not all minions respond to ping
- yield salt.ext.tornado.gen.sleep(
- self.batch_presence_ping_timeout or self.opts["gather_job_timeout"]
+ # schedule start_batch to perform even if not all the minions responded
+ # self.__event_handler can push start_batch in case if all targets responded
+ self._start_batch_on_timeout = self.io_loop.call_later(
+ self.batch_presence_ping_timeout or self.opts["gather_job_timeout"],
+ self.start_batch,
)
- if self.event:
- yield self.start_batch()
@salt.ext.tornado.gen.coroutine
def start_batch(self):
"""
Fire `salt/batch/*/start` and continue batch with `run_next`
"""
+ if self._start_batch_on_timeout is not None:
+ self.io_loop.remove_timeout(self._start_batch_on_timeout)
+ self._start_batch_on_timeout = None
if self.initialized:
return
self.batch_size = get_bnum(self.opts, self.minions, True)
@@ -431,6 +447,7 @@ class BatchAsync:
"""
End the batch and call safe closing
"""
+ log.trace("[%s] BatchAsync.end_batch called", self.batch_jid)
left = self.minions.symmetric_difference(
self.done_minions.union(self.timedout_minions)
)
@@ -452,10 +469,11 @@ class BatchAsync:
# release to the IOLoop to allow the event to be published
# before closing batch async execution
- yield salt.ext.tornado.gen.sleep(1)
+ yield salt.ext.tornado.gen.sleep(0.03)
self.close_safe()
def close_safe(self):
+ log.trace("[%s] BatchAsync.close_safe called", self.batch_jid)
if self.events_channel is not None:
self.events_channel.unsubscribe(None, None, id(self))
self.events_channel.unuse(id(self))
@@ -465,11 +483,22 @@ class BatchAsync:
@salt.ext.tornado.gen.coroutine
def schedule_next(self):
+ log.trace("[%s] BatchAsync.schedule_next called", self.batch_jid)
if self.scheduled:
+ log.trace(
+ "[%s] BatchAsync.schedule_next -> Batch already scheduled, nothing to do.",
+ self.batch_jid,
+ )
return
self.scheduled = True
- # call later so that we maybe gather more returns
- yield salt.ext.tornado.gen.sleep(self.batch_delay)
+ if self._get_next():
+ # call later so that we maybe gather more returns
+ log.trace(
+ "[%s] BatchAsync.schedule_next delaying batch %s second(s).",
+ self.batch_jid,
+ self.batch_delay,
+ )
+ yield salt.ext.tornado.gen.sleep(self.batch_delay)
if self.event:
yield self.run_next()
@@ -480,6 +509,11 @@ class BatchAsync:
"""
self.scheduled = False
next_batch = self._get_next()
+ log.trace(
+ "[%s] BatchAsync.run_next called. Next Batch -> %s",
+ self.batch_jid,
+ next_batch,
+ )
if not next_batch:
yield self.end_batch()
return
@@ -504,7 +538,7 @@ class BatchAsync:
yield salt.ext.tornado.gen.sleep(self.opts["timeout"])
# The batch can be done already at this point, which means no self.event
- if self.event:
+ if self.event and self.active.intersection(next_batch):
yield self.find_job(set(next_batch))
except Exception as ex: # pylint: disable=W0703
log.error(
diff --git a/tests/pytests/unit/cli/test_batch_async.py b/tests/pytests/unit/cli/test_batch_async.py
index bc871aba54..be8de692e6 100644
--- a/tests/pytests/unit/cli/test_batch_async.py
+++ b/tests/pytests/unit/cli/test_batch_async.py
@@ -85,11 +85,17 @@ def test_batch_start_on_batch_presence_ping_timeout(batch):
future.set_result({})
with patch.object(batch, "events_channel", MagicMock()), patch(
"salt.ext.tornado.gen.sleep", return_value=future
- ), patch.object(batch, "start_batch", return_value=future) as start_batch_mock:
+ ), patch.object(batch, "io_loop", MagicMock()), patch.object(
+ batch, "start_batch", return_value=future
+ ) as start_batch_mock:
batch.events_channel.local_client.run_job_async.return_value = future_ret
ret = batch.start()
- # assert start_batch is called
- start_batch_mock.assert_called_once()
+ # start_batch is scheduled to be called later
+ assert batch.io_loop.call_later.call_args[0] == (
+ batch.batch_presence_ping_timeout,
+ batch.start_batch,
+ )
+ assert batch._start_batch_on_timeout is not None
# assert test.ping called
assert batch.events_channel.local_client.run_job_async.call_args[0] == (
"*",
@@ -109,16 +115,21 @@ def test_batch_start_on_gather_job_timeout(batch):
batch.batch_presence_ping_timeout = None
with patch.object(batch, "events_channel", MagicMock()), patch(
"salt.ext.tornado.gen.sleep", return_value=future
+ ), patch.object(batch, "io_loop", MagicMock()), patch.object(
+ batch, "start_batch", return_value=future
), patch.object(
batch, "start_batch", return_value=future
) as start_batch_mock, patch.object(
batch, "batch_presence_ping_timeout", None
):
batch.events_channel.local_client.run_job_async.return_value = future_ret
- # ret = batch_async.start(batch)
ret = batch.start()
- # assert start_batch is called
- start_batch_mock.assert_called_once()
+ # start_batch is scheduled to be called later
+ assert batch.io_loop.call_later.call_args[0] == (
+ batch.opts["gather_job_timeout"],
+ batch.start_batch,
+ )
+ assert batch._start_batch_on_timeout is not None
def test_batch_fire_start_event(batch):
@@ -271,34 +282,10 @@ def test_batch__event_handler_ping_return(batch):
assert batch.done_minions == set()
-def test_batch__event_handler_call_start_batch_when_all_pings_return(batch):
- batch.targeted_minions = {"foo"}
- future = salt.ext.tornado.gen.Future()
- future.set_result({})
- with patch.object(batch, "start_batch", return_value=future) as start_batch_mock:
- batch.start()
- batch._BatchAsync__event_handler(
- "salt/job/1234/ret/foo", {"id": "foo"}, "ping_return"
- )
- start_batch_mock.assert_called_once()
-
-
-def test_batch__event_handler_not_call_start_batch_when_not_all_pings_return(batch):
- batch.targeted_minions = {"foo", "bar"}
- future = salt.ext.tornado.gen.Future()
- future.set_result({})
- with patch.object(batch, "start_batch", return_value=future) as start_batch_mock:
- batch.start()
- batch._BatchAsync__event_handler(
- "salt/job/1234/ret/foo", {"id": "foo"}, "ping_return"
- )
- start_batch_mock.assert_not_called()
-
-
def test_batch__event_handler_batch_run_return(batch):
future = salt.ext.tornado.gen.Future()
future.set_result({})
- with patch.object(
+ with patch.object(batch, "io_loop", MagicMock()), patch.object(
batch, "schedule_next", return_value=future
) as schedule_next_mock:
batch.start()
@@ -308,7 +295,7 @@ def test_batch__event_handler_batch_run_return(batch):
)
assert batch.active == set()
assert batch.done_minions == {"foo"}
- schedule_next_mock.assert_called_once()
+ batch.io_loop.add_callback.call_args[0] == (batch.schedule_next)
def test_batch__event_handler_find_job_return(batch):
@@ -322,9 +309,7 @@ def test_batch__event_handler_find_job_return(batch):
def test_batch_run_next_end_batch_when_no_next(batch):
future = salt.ext.tornado.gen.Future()
future.set_result({})
- with patch.object(
- batch, "_get_next", return_value={}
- ), patch.object(
+ with patch.object(batch, "_get_next", return_value={}), patch.object(
batch, "end_batch", return_value=future
) as end_batch_mock:
batch.run_next()
@@ -337,9 +322,7 @@ def test_batch_find_job(batch):
batch.minions = {"foo", "bar"}
with patch("salt.ext.tornado.gen.sleep", return_value=future), patch.object(
batch, "check_find_job", return_value=future
- ) as check_find_job_mock, patch.object(
- batch, "jid_gen", return_value="1236"
- ):
+ ) as check_find_job_mock, patch.object(batch, "jid_gen", return_value="1236"):
batch.events_channel.local_client.run_job_async.return_value = future
batch.find_job({"foo", "bar"})
assert check_find_job_mock.call_args[0] == (
@@ -355,9 +338,7 @@ def test_batch_find_job_with_done_minions(batch):
batch.minions = {"foo", "bar"}
with patch("salt.ext.tornado.gen.sleep", return_value=future), patch.object(
batch, "check_find_job", return_value=future
- ) as check_find_job_mock, patch.object(
- batch, "jid_gen", return_value="1236"
- ):
+ ) as check_find_job_mock, patch.object(batch, "jid_gen", return_value="1236"):
batch.events_channel.local_client.run_job_async.return_value = future
batch.find_job({"foo", "bar"})
assert check_find_job_mock.call_args[0] == (
--
2.48.1

View File

@ -0,0 +1,518 @@
From a630c6a707a1d5227b4a1fa8f0f751fefd3ef47f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 19 Feb 2025 13:56:01 +0000
Subject: [PATCH] Fix tests failures after "repo.saltproject.io"
deprecation (#704)
* Use broadcom.com instead of repo.saltproject.io for test_cp
* Change repo.saltproject.io to new url
---------
Co-authored-by: Daniel A. Wozniak <daniel.wozniak@broadcom.com>
Co-authored-by: twangboy <shane.d.lee@gmail.com>
---
README.rst | 4 +-
doc/_themes/saltstack2/layout.html | 15 +--
doc/conf.py | 12 +-
doc/ref/configuration/delta_proxy.rst | 6 +-
doc/topics/cloud/windows.rst | 2 +-
pkg/tests/support/helpers.py | 115 ++++++++++++------
salt/modules/saltutil.py | 4 +-
salt/runners/manage.py | 5 +-
salt/states/pkgrepo.py | 6 +-
tests/integration/modules/test_cp.py | 41 ++++---
tests/pytests/functional/modules/test_pkg.py | 8 +-
.../functional/states/pkgrepo/test_debian.py | 6 +-
.../integration/netapi/test_ssh_client.py | 3 +-
tests/support/win_installer.py | 1 +
14 files changed, 135 insertions(+), 93 deletions(-)
diff --git a/README.rst b/README.rst
index f5121f1a74..77806aa14a 100644
--- a/README.rst
+++ b/README.rst
@@ -93,7 +93,9 @@ for more information.
To download and install Salt, see:
* `The Salt install guide <https://docs.saltproject.io/salt/install-guide/en/latest/index.html>`_
-* `Salt Project repository <https://repo.saltproject.io/>`_
+* `Salt Project repository <https://packages.broadcom.com/artifactory/saltproject-generic/>`_
+* `Salt Project debian repository <https://packages.broadcom.com/artifactory/saltproject-deb/>`_
+* `Salt Project redhat repository <https://packages.broadcom.com/artifactory/saltproject-rpm/>`_
Technical support
diff --git a/doc/_themes/saltstack2/layout.html b/doc/_themes/saltstack2/layout.html
index 04bff89e1f..83918a7fb3 100644
--- a/doc/_themes/saltstack2/layout.html
+++ b/doc/_themes/saltstack2/layout.html
@@ -157,16 +157,11 @@
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="nav navbar-nav">
- <li><a href="/en/latest/">Overview</a></li>
- <li><a href="https://docs.saltproject.io/salt/user-guide/en/latest/">Salt User Guide</a></li>
- <li><a href="/en/latest/contents.html">Documentation</a></li>
- <li><a href="https://repo.saltproject.io">Downloads</a></li>
- <li><a href="/en/latest/topics/development/">Develop</a></li>
- <!--<li><a href="/en/2016.3/faq/">FAQ</a></li>
- <li><a href="/en/2016.3/samples/">Code Samples</a></li>-->
- <!-- <li><a href="https://repo.saltproject.io" target="_blank">Downloads</a></li>-->
- <!--<li><a href="http://saltstack.com/training" target="_blank">Training</a></li>
- <li><a href="http://saltstack.com/support" target="_blank">Support</a></li>-->
+ <li><a href="/en/latest/">Overview</a></li>
+ <li><a href="https://docs.saltproject.io/salt/user-guide/en/latest/">Salt User Guide</a></li>
+ <li><a href="/en/latest/contents.html">Documentation</a></li>
+ <li><a href="https://packages.broadcom.com/artifactory/saltproject-generic/">Downloads</a></li>
+ <li><a href="/en/latest/topics/development/">Develop</a></li>
</ul>
</div>
</div>
diff --git a/doc/conf.py b/doc/conf.py
index 653d912c20..24420d402e 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -178,17 +178,17 @@ rst_prolog = """\
.. |windownload| raw:: html
<p>Python3 x86: <a
- href="https://repo.saltproject.io/windows/Salt-Minion-{release}-Py3-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
- | <a href="https://repo.saltproject.io/windows/Salt-Minion-{release}-Py3-x86-Setup.exe.md5"><strong>md5</strong></a></p>
+ href="https://packages.broadcom.com/artifactory/saltproject-generic/windows/{release}/Salt-Minion-{release}-Py3-x86-Setup.exe"><strong>Salt-Minion-{release}-x86-Setup.exe</strong></a>
+ | <a href="https://packages.broadcom.com/artifactory/saltproject-generic/windows/{release}/Salt-Minion-{release}-Py3-x86-Setup.exe.md5"><strong>md5</strong></a></p>
<p>Python3 AMD64: <a
- href="https://repo.saltproject.io/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
- | <a href="https://repo.saltproject.io/windows/Salt-Minion-{release}-Py3-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
+ href="https://packages.broadcom.com/artifactory/saltproject-generic/windows/{release}/Salt-Minion-{release}-Py3-AMD64-Setup.exe"><strong>Salt-Minion-{release}-AMD64-Setup.exe</strong></a>
+ | <a href="https://packages.broadcom.com/artifactory/saltproject-generic/windows/{release}/Salt-Minion-{release}-Py3-AMD64-Setup.exe.md5"><strong>md5</strong></a></p>
.. |osxdownloadpy3| raw:: html
- <p>x86_64: <a href="https://repo.saltproject.io/osx/salt-{release}-py3-x86_64.pkg"><strong>salt-{release}-py3-x86_64.pkg</strong></a>
- | <a href="https://repo.saltproject.io/osx/salt-{release}-py3-x86_64.pkg.md5"><strong>md5</strong></a></p>
+ <p>x86_64: <a href="https://packages.broadcom.com/artifactory/saltproject-generic/macos/{release}/salt-{release}-py3-x86_64.pkg"><strong>salt-{release}-py3-x86_64.pkg</strong></a>
+ | <a href="https://packages.broadcom.com/artifactory/saltproject-generic/macos/{release}/salt-{release}-py3-x86_64.pkg.md5"><strong>md5</strong></a></p>
""".format(
release=stripped_release
diff --git a/doc/ref/configuration/delta_proxy.rst b/doc/ref/configuration/delta_proxy.rst
index be1831da39..bce5f821c9 100644
--- a/doc/ref/configuration/delta_proxy.rst
+++ b/doc/ref/configuration/delta_proxy.rst
@@ -146,10 +146,8 @@ Before installing the delta proxy minion, ensure that:
Install or upgrade Salt
-----------------------
Ensure your Salt masters are running at least Salt version 3004. For instructions
-on installing or upgrading Salt, see `repo.saltproject.io
-<http://repo.saltproject.io/>`_. For RedHat systems, see `Install or Upgrade Salt
-<https://enterprise.saltproject.io/en/latest/docs/install-salt.html>`_.
-
+on installing or upgrading Salt, see the `Salt install guide
+<https://docs.saltproject.io/salt/install-guide>`_.
.. _delta-proxy-install:
diff --git a/doc/topics/cloud/windows.rst b/doc/topics/cloud/windows.rst
index 9dfdde6db5..79d6665a5a 100644
--- a/doc/topics/cloud/windows.rst
+++ b/doc/topics/cloud/windows.rst
@@ -62,7 +62,7 @@ from saltstack.com:
* `SaltStack Download Area`__
-.. __: https://repo.saltproject.io/windows/
+.. __: https://packages.broadcom.com/artifactory/saltproject-generic/windows/
.. _new-pywinrm:
diff --git a/pkg/tests/support/helpers.py b/pkg/tests/support/helpers.py
index 90abf8b88e..ce23f699b6 100644
--- a/pkg/tests/support/helpers.py
+++ b/pkg/tests/support/helpers.py
@@ -636,8 +636,7 @@ class SaltPkgInstall:
def install_previous(self):
"""
- Install previous version. This is used for
- upgrade tests.
+ Install previous version. This is used for upgrade tests.
"""
major_ver = self.major
minor_ver = self.minor
@@ -648,16 +647,12 @@ class SaltPkgInstall:
distro_name = self.distro_name
if distro_name == "centos" or distro_name == "fedora":
distro_name = "redhat"
- root_url = "salt/py3/"
- if self.classic:
- root_url = "py3/"
+ root_url = "https://packages.broadcom.com/artifactory"
if self.distro_name in ["redhat", "centos", "amazon", "fedora", "vmware"]:
for fp in pathlib.Path("/etc", "yum.repos.d").glob("epel*"):
fp.unlink()
- gpg_key = "SALTSTACK-GPG-KEY.pub"
- if self.distro_version == "9":
- gpg_key = "SALTSTACK-GPG-KEY2.pub"
+
if platform.is_aarch64():
arch = "aarch64"
else:
@@ -694,46 +689,86 @@ class SaltPkgInstall:
arch = "arm64"
else:
arch = "amd64"
+
pathlib.Path("/etc/apt/keyrings").mkdir(parents=True, exist_ok=True)
+ gpg_full_path = "/etc/apt/keyrings/salt-archive-keyring.gpg"
+
+ # download the gpg pub key
download_file(
- f"https://repo.saltproject.io/{root_url}{distro_name}/{self.distro_version}/{arch}/{major_ver}/salt-archive-keyring.gpg",
- "/etc/apt/keyrings/salt-archive-keyring.gpg",
+ f"{root_url}/api/security/keypair/SaltProjectKey/public",
+ f"{gpg_full_path}",
)
- with open(
+ with salt.utils.files.fopen(
pathlib.Path("/etc", "apt", "sources.list.d", "salt.list"), "w"
) as fp:
fp.write(
- f"deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch={arch}] "
- f"https://repo.saltproject.io/{root_url}{distro_name}/{self.distro_version}/{arch}/{major_ver} {self.distro_codename} main"
+ f"deb [signed-by={gpg_full_path} arch={arch}] "
+ f"{root_url}/saltproject-deb/ {self.distro_codename} main"
)
- ret = self.proc.run(self.pkg_mngr, "update")
- self._check_retcode(ret)
- ret = self.proc.run(
- self.pkg_mngr,
- "install",
- *self.salt_pkgs,
- "-y",
- )
self._check_retcode(ret)
+
+ cmd = [self.pkg_mngr, "install", *self.salt_pkgs, "-y"]
+
+ if downgrade:
+ pref_file = pathlib.Path("/etc", "apt", "preferences.d", "salt.pref")
+ pref_file.parent.mkdir(exist_ok=True)
+ # TODO: There's probably something I should put in here to say what version
+ # TODO: But maybe that's done elsewhere, hopefully in self.salt_pkgs
+ pref_file.write_text(
+ textwrap.dedent(
+ f"""\
+ Package: salt*
+ Pin: origin "{root_url}/saltproject-deb"
+ Pin-Priority: 1001
+ """
+ ),
+ encoding="utf-8",
+ )
+ cmd.append("--allow-downgrades")
+ env = os.environ.copy()
+ env["DEBIAN_FRONTEND"] = "noninteractive"
+ extra_args = [
+ "-o",
+ "DPkg::Options::=--force-confdef",
+ "-o",
+ "DPkg::Options::=--force-confold",
+ ]
+ self.proc.run(self.pkg_mngr, "update", *extra_args, env=env)
+
+ cmd.extend(extra_args)
+
+ ret = self.proc.run(*cmd, env=env)
+ # Pre-relenv packages down get downgraded to cleanly programmatically
+ # They work manually, and the install tests after downgrades will catch problems with the install
+ # Let's not check the returncode if this is the case
+ if not (
+ downgrade
+ and packaging.version.parse(self.prev_version)
+ < packaging.version.parse("3006.0")
+ ):
+ self._check_retcode(ret)
+ if downgrade:
+ pref_file.unlink()
self.stop_services()
elif platform.is_windows():
self.onedir = True
self.installer_pkg = True
self.bin_dir = self.install_dir / "bin"
- self.run_root = self.bin_dir / f"salt.exe"
- self.ssm_bin = self.bin_dir / "ssm.exe"
- if self.file_ext == "msi":
- self.ssm_bin = self.install_dir / "ssm.exe"
+ self.run_root = self.bin_dir / "salt.exe"
+ self.ssm_bin = self.install_dir / "ssm.exe"
- if not self.classic:
- win_pkg = f"salt-{full_version}-windows-amd64.{self.file_ext}"
- win_pkg_url = f"https://repo.saltproject.io/salt/py3/windows/{full_version}/{win_pkg}"
+ if self.file_ext == "exe":
+ win_pkg = (
+ f"Salt-Minion-{self.prev_version}-Py3-AMD64-Setup.{self.file_ext}"
+ )
+ elif self.file_ext == "msi":
+ win_pkg = f"Salt-Minion-{self.prev_version}-Py3-AMD64.{self.file_ext}"
else:
- if self.file_ext == "msi":
- win_pkg = f"Salt-Minion-{min_ver}-1-Py3-AMD64.{self.file_ext}"
- elif self.file_ext == "exe":
- win_pkg = f"Salt-Minion-{min_ver}-1-Py3-AMD64-Setup.{self.file_ext}"
- win_pkg_url = f"https://repo.saltproject.io/windows/{win_pkg}"
+ log.debug(f"Unknown windows file extension: {self.file_ext}")
+
+ win_pkg_url = (
+ f"{root_url}/saltproject-generic/windows/{major_ver}/{win_pkg}"
+ )
pkg_path = pathlib.Path(r"C:\TEMP", win_pkg)
pkg_path.parent.mkdir(exist_ok=True)
ret = requests.get(win_pkg_url)
@@ -763,12 +798,16 @@ class SaltPkgInstall:
self._install_system_service()
elif platform.is_darwin():
- if self.classic:
- mac_pkg = f"salt-{min_ver}.{minor_ver}-1-py3-x86_64.pkg"
- mac_pkg_url = f"https://repo.saltproject.io/osx/{mac_pkg}"
+ if relenv and platform.is_aarch64():
+ arch = "arm64"
+ elif platform.is_aarch64() and self.classic:
+ arch = "arm64"
else:
- mac_pkg = f"salt-{min_ver}.{minor_ver}-1-macos-x86_64.pkg"
- mac_pkg_url = f"https://repo.saltproject.io/salt/py3/macos/{major_ver}.{minor_ver}-1/{mac_pkg}"
+ arch = "x86_64"
+
+ mac_pkg = f"salt-{self.prev_version}-py3-{arch}.pkg"
+ mac_pkg_url = f"{root_url}/saltproject-generic/macos/{major_ver}/{mac_pkg}"
+
mac_pkg_path = f"/tmp/{mac_pkg}"
if not os.path.exists(mac_pkg_path):
download_file(
diff --git a/salt/modules/saltutil.py b/salt/modules/saltutil.py
index a692c3f34d..320b9c34fa 100644
--- a/salt/modules/saltutil.py
+++ b/salt/modules/saltutil.py
@@ -128,8 +128,8 @@ def _sync(form, saltenv=None, extmod_whitelist=None, extmod_blacklist=None):
def update(version=None):
"""
Update the salt minion from the URL defined in opts['update_url']
- VMware, Inc provides the latest builds here:
- update_url: https://repo.saltproject.io/windows/
+ Broadcom, Inc provides the latest builds here:
+ update_url: https://packages.broadcom.com/artifactory/saltproject-generic/windows/
Be aware that as of 2014-8-11 there's a bug in esky such that only the
latest version available in the update_url can be downloaded and installed.
diff --git a/salt/runners/manage.py b/salt/runners/manage.py
index 9dc67ed728..81197ca41f 100644
--- a/salt/runners/manage.py
+++ b/salt/runners/manage.py
@@ -772,7 +772,7 @@ def bootstrap_psexec(
installer_url
URL of minion installer executable. Defaults to the latest version from
- https://repo.saltproject.io/windows/
+ https://packages.broadcom.com/artifactory/saltproject-generic/windows/
username
Optional user name for login on remote computer.
@@ -790,6 +790,9 @@ def bootstrap_psexec(
salt-run manage.bootstrap_psexec hosts='host1,host2' installer_url='http://exampledomain/salt-installer.exe'
"""
+ # TODO: Need to make this gets the latest version from the new repo location
+ # TODO: Similar to tests/support/win_installer.py
+ # TODO: Maybe need to move that ^^^^ to a salt util
if not installer_url:
base_url = "https://repo.saltproject.io/windows/"
source = urllib.request.urlopen(base_url).read()
diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py
index f041644287..4ef5fd9c2f 100644
--- a/salt/states/pkgrepo.py
+++ b/salt/states/pkgrepo.py
@@ -99,17 +99,17 @@ Using ``aptkey: False`` with ``key_url`` example:
.. code-block:: yaml
- deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest bionic main:
+ deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://packages.broadcom.com/artifactory/saltproject-deb/ bionic main:
pkgrepo.managed:
- file: /etc/apt/sources.list.d/salt.list
- - key_url: https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest/salt-archive-keyring.gpg
+ - key_url: https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public
- aptkey: False
Using ``aptkey: False`` with ``keyserver`` and ``keyid``:
.. code-block:: yaml
- deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://repo.saltproject.io/py3/ubuntu/18.04/amd64/latest bionic main:
+ deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://packages.broadcom.com/artifactory/saltproject-deb/ bionic main:
pkgrepo.managed:
- file: /etc/apt/sources.list.d/salt.list
- keyserver: keyserver.ubuntu.com
diff --git a/tests/integration/modules/test_cp.py b/tests/integration/modules/test_cp.py
index cd3e4c2f5a..d417f90ddc 100644
--- a/tests/integration/modules/test_cp.py
+++ b/tests/integration/modules/test_cp.py
@@ -231,12 +231,15 @@ class CPModuleTest(ModuleCase):
"""
cp.get_url with https:// source given
"""
- self.run_function("cp.get_url", ["https://repo.saltproject.io/index.html", tgt])
+ self.run_function(
+ "cp.get_url",
+ ["https://packages.broadcom.com/artifactory/saltproject-generic/", tgt],
+ )
with salt.utils.files.fopen(tgt, "r") as instructions:
data = salt.utils.stringutils.to_unicode(instructions.read())
- self.assertIn("Salt Project", data)
- self.assertIn("Package", data)
- self.assertIn("Repo", data)
+ self.assertIn("Index of saltproject", data)
+ self.assertIn("onedir", data)
+ self.assertIn("Artifactory Online Server", data)
self.assertNotIn("AYBABTU", data)
@pytest.mark.slow_test
@@ -245,14 +248,15 @@ class CPModuleTest(ModuleCase):
cp.get_url with https:// source given and destination omitted.
"""
ret = self.run_function(
- "cp.get_url", ["https://repo.saltproject.io/index.html"]
+ "cp.get_url",
+ ["https://packages.broadcom.com/artifactory/saltproject-generic/"],
)
with salt.utils.files.fopen(ret, "r") as instructions:
data = salt.utils.stringutils.to_unicode(instructions.read())
- self.assertIn("Salt Project", data)
- self.assertIn("Package", data)
- self.assertIn("Repo", data)
+ self.assertIn("Index of saltproject", data)
+ self.assertIn("onedir", data)
+ self.assertIn("Artifactory Online Server", data)
self.assertNotIn("AYBABTU", data)
@pytest.mark.slow_test
@@ -266,16 +270,19 @@ class CPModuleTest(ModuleCase):
tgt = None
while time.time() - start <= timeout:
ret = self.run_function(
- "cp.get_url", ["https://repo.saltproject.io/index.html", tgt]
+ "cp.get_url",
+ ["https://packages.broadcom.com/artifactory/saltproject-generic/", tgt],
)
if ret.find("HTTP 599") == -1:
break
time.sleep(sleep)
if ret.find("HTTP 599") != -1:
- raise Exception("https://repo.saltproject.io/index.html returned 599 error")
- self.assertIn("Salt Project", ret)
- self.assertIn("Package", ret)
- self.assertIn("Repo", ret)
+ raise Exception(
+ "https://packages.broadcom.com/artifactory/saltproject-generic/ returned 599 error"
+ )
+ self.assertIn("Index of saltproject", ret)
+ self.assertIn("onedir", ret)
+ self.assertIn("Artifactory Online Server", ret)
self.assertNotIn("AYBABTU", ret)
@pytest.mark.slow_test
@@ -344,11 +351,11 @@ class CPModuleTest(ModuleCase):
"""
cp.get_file_str with https:// source given
"""
- src = "https://repo.saltproject.io/index.html"
+ src = "https://packages.broadcom.com/artifactory/saltproject-generic/"
ret = self.run_function("cp.get_file_str", [src])
- self.assertIn("Salt Project", ret)
- self.assertIn("Package", ret)
- self.assertIn("Repo", ret)
+ self.assertIn("Index of saltproject", ret)
+ self.assertIn("onedir", ret)
+ self.assertIn("Artifactory Online Server", ret)
self.assertNotIn("AYBABTU", ret)
@pytest.mark.slow_test
diff --git a/tests/pytests/functional/modules/test_pkg.py b/tests/pytests/functional/modules/test_pkg.py
index 82d0801965..addb3da3d1 100644
--- a/tests/pytests/functional/modules/test_pkg.py
+++ b/tests/pytests/functional/modules/test_pkg.py
@@ -130,12 +130,8 @@ def test_mod_del_repo(grains, modules, refresh_db):
elif grains["os_family"] == "RedHat":
repo = "saltstack"
name = "SaltStack repo for RHEL/CentOS {}".format(grains["osmajorrelease"])
- baseurl = "https://repo.saltproject.io/py3/redhat/{}/x86_64/latest/".format(
- grains["osmajorrelease"]
- )
- gpgkey = "https://repo.saltproject.io/py3/redhat/{}/x86_64/latest/SALTSTACK-GPG-KEY.pub".format(
- grains["osmajorrelease"]
- )
+ baseurl = "https://packages.broadcom.com/artifactory/saltproject-rpm/"
+ gpgkey = "https://packages.broadcom.com/artifactory/api/security/keypair/SaltProjectKey/public"
gpgcheck = 1
enabled = 1
ret = modules.pkg.mod_repo(
diff --git a/tests/pytests/functional/states/pkgrepo/test_debian.py b/tests/pytests/functional/states/pkgrepo/test_debian.py
index 7bda100b63..307fcb5819 100644
--- a/tests/pytests/functional/states/pkgrepo/test_debian.py
+++ b/tests/pytests/functional/states/pkgrepo/test_debian.py
@@ -616,8 +616,8 @@ class Repo:
@alt_repo.default
def _default_alt_repo(self):
"""
- Use an alternative repo, packages do not
- exist for the OS on repo.saltproject.io
+ Use an alternative repo, packages do not exist for the OS on
+ packages.broadcom.com
"""
if (
self.grains["osfullname"] == "Ubuntu"
@@ -777,7 +777,7 @@ def test_adding_repo_file_signedby_alt_file(pkgrepo, states, repo):
assert repo.repo_content in ret.comment
key_file = repo.key_file.parent / "salt-alt-key.gpg"
- repo_content = "deb [arch=amd64 signed-by={}] https://repo.saltproject.io/py3/debian/10/amd64/latest buster main".format(
+ repo_content = "deb [arch=amd64 signed-by={}] https://packages.broadcom.com/artifactory/saltproject-deb/ buster main".format(
str(key_file)
)
ret = states.pkgrepo.managed(
diff --git a/tests/pytests/integration/netapi/test_ssh_client.py b/tests/pytests/integration/netapi/test_ssh_client.py
index 457c151c94..7dd540d9b9 100644
--- a/tests/pytests/integration/netapi/test_ssh_client.py
+++ b/tests/pytests/integration/netapi/test_ssh_client.py
@@ -149,7 +149,8 @@ def test_shell_inject_ssh_priv(
"""
# ZDI-CAN-11143
path = tmp_path / "test-11143"
- tgts = ["repo.saltproject.io", "www.zerodayinitiative.com"]
+ tgts = ["packages.broadcom.com", "www.zerodayinitiative.com"]
+ ret = None
for tgt in tgts:
low = {
"roster": "cache",
diff --git a/tests/support/win_installer.py b/tests/support/win_installer.py
index 6a2f387dc8..d67105e8a0 100644
--- a/tests/support/win_installer.py
+++ b/tests/support/win_installer.py
@@ -10,6 +10,7 @@
"""
import hashlib
+from html.parser import HTMLParser
import requests
--
2.48.1

View File

@ -0,0 +1,81 @@
From 1772da828f40e36d2a9eceb7055a1fa1a2257830 Mon Sep 17 00:00:00 2001
From: Georg <georg@lysergic.dev>
Date: Fri, 21 Feb 2025 10:23:38 +0000
Subject: [PATCH] Fixed file client private attribute reference on
`SaltMakoTemplateLookup` (#694)
Fixes #64280
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
(cherry picked from commit 560ab52ccf94c7974d5a418dfbba7409e0493066)
Co-authored-by: Pedro Algarvio <palgarvio@vmware.com>
---
changelog/64280.fixed.md | 1 +
salt/utils/mako.py | 6 ++++--
tests/pytests/unit/utils/test_mako.py | 28 +++++++++++++++++++++++++++
3 files changed, 33 insertions(+), 2 deletions(-)
create mode 100644 changelog/64280.fixed.md
create mode 100644 tests/pytests/unit/utils/test_mako.py
diff --git a/changelog/64280.fixed.md b/changelog/64280.fixed.md
new file mode 100644
index 0000000000..5a9b905dd0
--- /dev/null
+++ b/changelog/64280.fixed.md
@@ -0,0 +1 @@
+Fixed file client private attribute reference on `SaltMakoTemplateLookup`
diff --git a/salt/utils/mako.py b/salt/utils/mako.py
index 037d5d86de..4397ae8cc7 100644
--- a/salt/utils/mako.py
+++ b/salt/utils/mako.py
@@ -99,8 +99,10 @@ if HAS_MAKO:
)
def destroy(self):
- if self.client:
+ if self._file_client:
+ file_client = self._file_client
+ self._file_client = None
try:
- self.client.destroy()
+ file_client.destroy()
except AttributeError:
pass
diff --git a/tests/pytests/unit/utils/test_mako.py b/tests/pytests/unit/utils/test_mako.py
new file mode 100644
index 0000000000..952cf44652
--- /dev/null
+++ b/tests/pytests/unit/utils/test_mako.py
@@ -0,0 +1,28 @@
+import pytest
+
+from tests.support.mock import Mock, call, patch
+
+pytest.importorskip("mako")
+
+# This import needs to be after the above importorskip so that no ImportError
+# is raised if Mako is not installed
+from salt.utils.mako import SaltMakoTemplateLookup
+
+
+def test_mako_template_lookup(minion_opts):
+ """
+ The shudown method can be called without raising an exception when the
+ file_client does not have a destroy method
+ """
+ # Test SaltCacheLoader creating and destroying the file client created
+ file_client = Mock()
+ with patch("salt.fileclient.get_file_client", return_value=file_client):
+ loader = SaltMakoTemplateLookup(minion_opts)
+ assert loader._file_client is None
+ assert loader.file_client() is file_client
+ assert loader._file_client is file_client
+ try:
+ loader.destroy()
+ except AttributeError:
+ pytest.fail("Regression when calling SaltMakoTemplateLookup.destroy()")
+ assert file_client.mock_calls == [call.destroy()]
--
2.48.1

View File

@ -0,0 +1,142 @@
From 32099b97c2fa549cb050d3ae618b5200c07328c8 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Fri, 21 Feb 2025 11:59:00 +0100
Subject: [PATCH] Make `_auth` calls visible with master stats (#696)
* Put _auth calls to the master stats
* Add _auth master stats tests
* test small fix
---
salt/channel/server.py | 9 ++++--
salt/master.py | 5 ++++
tests/pytests/unit/channel/__init__.py | 0
tests/pytests/unit/channel/test_server.py | 34 +++++++++++++++++++++++
tests/pytests/unit/test_master.py | 25 +++++++++++++++++
5 files changed, 70 insertions(+), 3 deletions(-)
create mode 100644 tests/pytests/unit/channel/__init__.py
create mode 100644 tests/pytests/unit/channel/test_server.py
diff --git a/salt/channel/server.py b/salt/channel/server.py
index f1b6f701a9..59da3a2dc2 100644
--- a/salt/channel/server.py
+++ b/salt/channel/server.py
@@ -9,6 +9,7 @@ import hashlib
import logging
import os
import shutil
+import time
import salt.crypt
import salt.ext.tornado.gen
@@ -149,9 +150,11 @@ class ReqServerChannel:
# intercept the "_auth" commands, since the main daemon shouldn't know
# anything about our key auth
if payload["enc"] == "clear" and payload.get("load", {}).get("cmd") == "_auth":
- raise salt.ext.tornado.gen.Return(
- self._auth(payload["load"], sign_messages)
- )
+ start = time.time()
+ ret = self._auth(payload["load"], sign_messages)
+ if self.opts.get("master_stats", False):
+ yield self.payload_handler({"cmd": "_auth", "_start": start})
+ raise salt.ext.tornado.gen.Return(ret)
nonce = None
if version > 1:
diff --git a/salt/master.py b/salt/master.py
index 49cfb68860..c0cd9a366b 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -1036,6 +1036,11 @@ class MWorker(salt.utils.process.SignalHandlingProcess):
:param dict payload: The payload route to the appropriate handler
"""
+ if payload.get("cmd") == "_auth":
+ if self.opts["master_stats"]:
+ self.stats["_auth"]["runs"] += 1
+ self._post_stats(payload["_start"], "_auth")
+ return
key = payload["enc"]
load = payload["load"]
if key == "aes":
diff --git a/tests/pytests/unit/channel/__init__.py b/tests/pytests/unit/channel/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/pytests/unit/channel/test_server.py b/tests/pytests/unit/channel/test_server.py
new file mode 100644
index 0000000000..3fa5d94bea
--- /dev/null
+++ b/tests/pytests/unit/channel/test_server.py
@@ -0,0 +1,34 @@
+import time
+
+import pytest
+
+import salt.channel.server as server
+import salt.ext.tornado.gen
+from tests.support.mock import MagicMock, patch
+
+
+def test__auth_cmd_stats_passing():
+ req_server_channel = server.ReqServerChannel({"master_stats": True}, None)
+
+ fake_ret = {"enc": "clear", "load": b"FAKELOAD"}
+
+ def _auth_mock(*_, **__):
+ time.sleep(0.03)
+ return fake_ret
+
+ future = salt.ext.tornado.gen.Future()
+ future.set_result({})
+
+ with patch.object(req_server_channel, "_auth", _auth_mock):
+ req_server_channel.payload_handler = MagicMock(return_value=future)
+ req_server_channel.handle_message(
+ {"enc": "clear", "load": {"cmd": "_auth", "id": "minion"}}
+ )
+ cur_time = time.time()
+ req_server_channel.payload_handler.assert_called_once()
+ assert req_server_channel.payload_handler.call_args[0][0]["cmd"] == "_auth"
+ auth_call_duration = (
+ cur_time - req_server_channel.payload_handler.call_args[0][0]["_start"]
+ )
+ assert auth_call_duration >= 0.03
+ assert auth_call_duration < 0.05
diff --git a/tests/pytests/unit/test_master.py b/tests/pytests/unit/test_master.py
index 679229066d..7fccb24d73 100644
--- a/tests/pytests/unit/test_master.py
+++ b/tests/pytests/unit/test_master.py
@@ -282,3 +282,28 @@ def test_syndic_return_cache_dir_creation_traversal(encrypted_requests):
)
assert not (cachedir / "syndics").exists()
assert not (cachedir / "mamajama").exists()
+
+
+def test_collect__auth_to_master_stats():
+ """
+ Check if master stats is collecting _auth calls while not calling neither _handle_aes nor _handle_clear
+ """
+ opts = {
+ "master_stats": True,
+ "master_stats_event_iter": 10,
+ }
+ req_channel_mock = MagicMock()
+ mworker = salt.master.MWorker(opts, {}, {}, [req_channel_mock])
+ with patch.object(mworker, "_handle_aes") as handle_aes_mock, patch.object(
+ mworker, "_handle_clear"
+ ) as handle_clear_mock:
+ mworker._handle_payload({"cmd": "_auth", "_start": time.time() - 0.02})
+ assert mworker.stats["_auth"]["runs"] == 1
+ assert mworker.stats["_auth"]["mean"] >= 0.02
+ assert mworker.stats["_auth"]["mean"] < 0.04
+ mworker._handle_payload({"cmd": "_auth", "_start": time.time() - 0.02})
+ assert mworker.stats["_auth"]["runs"] == 2
+ assert mworker.stats["_auth"]["mean"] >= 0.02
+ assert mworker.stats["_auth"]["mean"] < 0.04
+ handle_aes_mock.assert_not_called()
+ handle_clear_mock.assert_not_called()
--
2.48.1

View File

@ -0,0 +1,69 @@
From 73d18711314738796e802a6d929f4b609cee1f67 Mon Sep 17 00:00:00 2001
From: Georg <georg@lysergic.dev>
Date: Fri, 21 Feb 2025 10:26:25 +0000
Subject: [PATCH] Repair fstab_present test mode (#702)
Return no pending changes if the configuration already matches.
Signed-off-by: Georg Pfuetzenreuter <georg.pfuetzenreuter@suse.com>
(cherry picked from commit fc7ed2b53152ab255d7763f200e8d28d526c5e52)
---
changelog/67065.fixed.md | 1 +
salt/states/mount.py | 1 +
tests/pytests/unit/states/test_mount.py | 6 +++---
3 files changed, 5 insertions(+), 3 deletions(-)
create mode 100644 changelog/67065.fixed.md
diff --git a/changelog/67065.fixed.md b/changelog/67065.fixed.md
new file mode 100644
index 0000000000..7b210dc297
--- /dev/null
+++ b/changelog/67065.fixed.md
@@ -0,0 +1 @@
+Repaired mount.fstab_present always returning pending changes
diff --git a/salt/states/mount.py b/salt/states/mount.py
index 36b9a16b5d..97dddbe3b0 100644
--- a/salt/states/mount.py
+++ b/salt/states/mount.py
@@ -1228,6 +1228,7 @@ def fstab_present(
if out == "present":
msg = "{} entry is already in {}."
ret["comment"].append(msg.format(fs_file, config))
+ ret["result"] = True
elif out == "new":
msg = "{} entry will be written in {}."
ret["comment"].append(msg.format(fs_file, config))
diff --git a/tests/pytests/unit/states/test_mount.py b/tests/pytests/unit/states/test_mount.py
index 5e4d5274e8..382fe6d0e8 100644
--- a/tests/pytests/unit/states/test_mount.py
+++ b/tests/pytests/unit/states/test_mount.py
@@ -701,7 +701,7 @@ def test_fstab_present_macos_test_present():
"""
ret = {
"name": "/dev/sda1",
- "result": None,
+ "result": True,
"changes": {},
"comment": ["/home entry is already in /etc/auto_salt."],
}
@@ -730,7 +730,7 @@ def test_fstab_present_aix_test_present():
"""
ret = {
"name": "/dev/sda1",
- "result": None,
+ "result": True,
"changes": {},
"comment": ["/home entry is already in /etc/filesystems."],
}
@@ -761,7 +761,7 @@ def test_fstab_present_test_present():
"""
ret = {
"name": "/dev/sda1",
- "result": None,
+ "result": True,
"changes": {},
"comment": ["/home entry is already in /etc/fstab."],
}
--
2.48.1

View File

@ -0,0 +1,304 @@
From 325506774381cc8edadee9b2f43fd6733d4f9edb Mon Sep 17 00:00:00 2001
From: Georg <georg@lysergic.dev>
Date: Fri, 21 Feb 2025 12:40:45 +0000
Subject: [PATCH] Repair virt_query outputter (#655)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* Repair virt_query outputter
Existing code was not functional.
Only return if a dictionary is passed and reference the correct
data.
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
(cherry picked from commit e3c365ad8f385121aa878950e13892d986d79656)
* Facilitate block devices in virt_query outputter
Disk data in Libvirt VMs does not contain a disk size if the disk
references a block device.
Skip the field for such disks instead of failing with a key error.
Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
(cherry picked from commit ed73abd44117ad745e9c91f2b33caf04402b117c)
* Add unit tests for virt_query outputter
---------
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
---
changelog/65841.fixed.md | 1 +
salt/output/virt_query.py | 64 +++----
tests/pytests/unit/output/test_virt_query.py | 176 +++++++++++++++++++
3 files changed, 210 insertions(+), 31 deletions(-)
create mode 100644 changelog/65841.fixed.md
create mode 100644 tests/pytests/unit/output/test_virt_query.py
diff --git a/changelog/65841.fixed.md b/changelog/65841.fixed.md
new file mode 100644
index 0000000000..7fb6336ea1
--- /dev/null
+++ b/changelog/65841.fixed.md
@@ -0,0 +1 @@
+Restore functionality of virt_query outputter and add support for block devices.
diff --git a/salt/output/virt_query.py b/salt/output/virt_query.py
index d20e6357e6..0f989fedfa 100644
--- a/salt/output/virt_query.py
+++ b/salt/output/virt_query.py
@@ -12,35 +12,37 @@ def output(data, **kwargs): # pylint: disable=unused-argument
Display output for the salt-run virt.query function
"""
out = ""
- for id_ in data["data"]:
- out += "{}\n".format(id_)
- for vm_ in data["data"][id_]["vm_info"]:
- out += " {}\n".format(vm_)
- vm_data = data[id_]["vm_info"][vm_]
- if "cpu" in vm_data:
- out += " CPU: {}\n".format(vm_data["cpu"])
- if "mem" in vm_data:
- out += " Memory: {}\n".format(vm_data["mem"])
- if "state" in vm_data:
- out += " State: {}\n".format(vm_data["state"])
- if "graphics" in vm_data:
- if vm_data["graphics"].get("type", "") == "vnc":
- out += " Graphics: vnc - {}:{}\n".format(
- id_, vm_data["graphics"]["port"]
- )
- if "disks" in vm_data:
- for disk, d_data in vm_data["disks"].items():
- out += " Disk - {}:\n".format(disk)
- out += " Size: {}\n".format(d_data["disk size"])
- out += " File: {}\n".format(d_data["file"])
- out += " File Format: {}\n".format(d_data["file format"])
- if "nics" in vm_data:
- for mac in vm_data["nics"]:
- out += " Nic - {}:\n".format(mac)
- out += " Source: {}\n".format(
- vm_data["nics"][mac]["source"][
- next(iter(vm_data["nics"][mac]["source"].keys()))
- ]
- )
- out += " Type: {}\n".format(vm_data["nics"][mac]["type"])
+ if isinstance(data, dict) and "event" in data:
+ for id_ in data["event"]["data"]:
+ out += "{}\n".format(id_)
+ for vm_ in data["event"]["data"][id_]["vm_info"]:
+ out += " {}\n".format(vm_)
+ vm_data = data["event"]["data"][id_]["vm_info"][vm_]
+ if "cpu" in vm_data:
+ out += " CPU: {}\n".format(vm_data["cpu"])
+ if "mem" in vm_data:
+ out += " Memory: {}\n".format(vm_data["mem"])
+ if "state" in vm_data:
+ out += " State: {}\n".format(vm_data["state"])
+ if "graphics" in vm_data:
+ if vm_data["graphics"].get("type", "") == "vnc":
+ out += " Graphics: vnc - {}:{}\n".format(
+ id_, vm_data["graphics"]["port"]
+ )
+ if "disks" in vm_data:
+ for disk, d_data in vm_data["disks"].items():
+ out += " Disk - {}:\n".format(disk)
+ if "disk size" in d_data:
+ out += " Size: {}\n".format(d_data["disk size"])
+ out += " File: {}\n".format(d_data["file"])
+ out += " File Format: {}\n".format(d_data["file format"])
+ if "nics" in vm_data:
+ for mac in vm_data["nics"]:
+ out += " NIC - {}:\n".format(mac)
+ out += " Source: {}\n".format(
+ vm_data["nics"][mac]["source"][
+ next(iter(vm_data["nics"][mac]["source"].keys()))
+ ]
+ )
+ out += " Type: {}\n".format(vm_data["nics"][mac]["type"])
return out
diff --git a/tests/pytests/unit/output/test_virt_query.py b/tests/pytests/unit/output/test_virt_query.py
new file mode 100644
index 0000000000..3f8814ee26
--- /dev/null
+++ b/tests/pytests/unit/output/test_virt_query.py
@@ -0,0 +1,176 @@
+"""
+unittests for virt_query outputter
+"""
+
+import pytest
+
+import salt.output.virt_query as virt_query
+from tests.support.mock import patch
+
+
+@pytest.fixture
+def configure_loader_modules():
+ return {virt_query: {}}
+
+
+@pytest.fixture
+def data():
+ return {
+ "suffix": "progress",
+ "event": {
+ "data": {
+ "mysystem": {
+ "freecpu": 14,
+ "freemem": 29566.0,
+ "node_info": {
+ "cpucores": 8,
+ "cpumhz": 1089,
+ "cpumodel": "x86_64",
+ "cpus": 16,
+ "cputhreads": 2,
+ "numanodes": 1,
+ "phymemory": 30846,
+ "sockets": 1,
+ },
+ "vm_info": {
+ "vm1": {
+ "cpu": 2,
+ "cputime": 1214270000000,
+ "disks": {
+ "vda": {
+ "file": "default/vm1-main-disk",
+ "type": "disk",
+ "file format": "qcow2",
+ "virtual size": 214748364800,
+ "disk size": 1831731200,
+ "backing file": {
+ "file": "/var/lib/libvirt/images/sles15sp4o",
+ "file format": "qcow2",
+ },
+ },
+ "hdd": {
+ "file": "default/vm1-cloudinit-disk",
+ "type": "cdrom",
+ "file format": "raw",
+ "virtual size": 374784,
+ "disk size": 376832,
+ },
+ },
+ "graphics": {
+ "autoport": "yes",
+ "keymap": "None",
+ "listen": "0.0.0.0",
+ "port": "5900",
+ "type": "spice",
+ },
+ "nics": {
+ "aa:bb:cc:dd:ee:ff": {
+ "type": "network",
+ "mac": "aa:bb:cc:dd:ee:ff",
+ "source": {"network": "default"},
+ "model": "virtio",
+ "address": {
+ "type": "pci",
+ "domain": "0x0000",
+ "bus": "0x00",
+ "slot": "0x03",
+ "function": "0x0",
+ },
+ }
+ },
+ "uuid": "yyyyyy",
+ "loader": {"path": "None"},
+ "on_crash": "destroy",
+ "on_reboot": "restart",
+ "on_poweroff": "destroy",
+ "maxMem": 1048576,
+ "mem": 1048576,
+ "state": "running",
+ },
+ "uyuni-proxy": {
+ "cpu": 2,
+ "cputime": 0,
+ "disks": {
+ "vda": {
+ "file": "default/uyuni-proxy-main-disk",
+ "type": "disk",
+ "file format": "qcow2",
+ "virtual size": 214748364800,
+ "disk size": 4491255808,
+ "backing file": {
+ "file": "/var/lib/libvirt/images/leapmicro55o",
+ "file format": "qcow2",
+ },
+ }
+ },
+ "graphics": {
+ "autoport": "yes",
+ "keymap": "None",
+ "listen": "0.0.0.0",
+ "port": "None",
+ "type": "spice",
+ },
+ "nics": {
+ "aa:bb:cc:dd:ee:aa": {
+ "type": "network",
+ "mac": "aa:bb:cc:dd:ee:aa",
+ "source": {"network": "default"},
+ "model": "virtio",
+ "address": {
+ "type": "pci",
+ "domain": "0x0000",
+ "bus": "0x00",
+ "slot": "0x03",
+ "function": "0x0",
+ },
+ }
+ },
+ "uuid": "xxxxx",
+ "loader": {"path": "None"},
+ "on_crash": "destroy",
+ "on_reboot": "restart",
+ "on_poweroff": "destroy",
+ "maxMem": 2097152,
+ "mem": 2097152,
+ "state": "shutdown",
+ },
+ },
+ }
+ },
+ "outputter": "virt_query",
+ "_stamp": "2025-02-21T11:28:04.406561",
+ },
+ }
+
+
+def test_default_output(data):
+ ret = virt_query.output(data)
+ expected = """mysystem
+ vm1
+ CPU: 2
+ Memory: 1048576
+ State: running
+ Disk - vda:
+ Size: 1831731200
+ File: default/vm1-main-disk
+ File Format: qcow2
+ Disk - hdd:
+ Size: 376832
+ File: default/vm1-cloudinit-disk
+ File Format: raw
+ NIC - aa:bb:cc:dd:ee:ff:
+ Source: default
+ Type: network
+ uyuni-proxy
+ CPU: 2
+ Memory: 2097152
+ State: shutdown
+ Disk - vda:
+ Size: 4491255808
+ File: default/uyuni-proxy-main-disk
+ File Format: qcow2
+ NIC - aa:bb:cc:dd:ee:aa:
+ Source: default
+ Type: network
+"""
+ assert expected == ret
--
2.48.1

View File

@ -1,3 +1,41 @@
-------------------------------------------------------------------
Mon Feb 24 16:17:55 UTC 2025 - Pablo Suárez Hernández <psuarezhernandez@suse.com>
- Fix issue of using update-alternatives with alts
-------------------------------------------------------------------
Fri Feb 21 12:46:01 UTC 2025 - Pablo Suárez Hernández <psuarezhernandez@suse.com>
- Fix virt_query outputter and add support for block devices
- Make _auth calls visible with master stats
- Repair mount.fstab_present always returning pending changes
- Set virtual grain in Podman systemd container
- Fix crash due wrong client reference on `SaltMakoTemplateLookup`
- Enhace batch async and fix some detected issues
- Added:
* repair-virt_query-outputter-655.patch
* make-_auth-calls-visible-with-master-stats-696.patch
* repair-fstab_present-test-mode-702.patch
* set-virtual-grain-in-podman-systemd-container-703.patch
* fixed-file-client-private-attribute-reference-on-sal.patch
* backport-batch-async-fixes-and-improvements-701.patch
-------------------------------------------------------------------
Wed Feb 19 16:06:43 UTC 2025 - Pablo Suárez Hernández <psuarezhernandez@suse.com>
- Enhacement of Salt packaging
* Use update-alternatives for all salt scripts
* Use flexible dependencies for the subpackages
* Make salt-minion to require flavored zypp-plugin
* Make zyppnotify to use update-alternatives
* Drop unused yumnotify plugin
* Add dependency to python3-dnf-plugins-core for RHEL based
- Fix tests failures after "repo.saltproject.io" deprecation
- Added:
* fix-tests-failures-after-repo.saltproject.io-depreca.patch
-------------------------------------------------------------------
Wed Jan 29 10:34:28 UTC 2025 - Pablo Suárez Hernández <psuarezhernandez@suse.com>

170
salt.spec
View File

@ -34,7 +34,7 @@
%define psuffix %{nil}
%endif
%if 0%{?suse_version} > 1210 || 0%{?rhel} >= 7 || 0%{?fedora} >=28
%if 0%{?suse_version} > 1210 || 0%{?rhel} >= 7 || 0%{?fedora} >= 28
%bcond_without systemd
%else
%bcond_with systemd
@ -58,6 +58,7 @@
%{?sle15allpythons}
%define skip_python2 1
%if 0%{?rhel} == 8 || (0%{?suse_version} == 1500 && 0%{?sle_version} < 150400)
%define singlespec_compat 1
%define __python3_bin_suffix 3.6
%if 0%{?rhel} == 8
%define __python3 /usr/libexec/platform-python
@ -77,7 +78,6 @@ args = args:gsub("$python_sitelib", "python3_sitelib")\
args = args:gsub("$python", python_bin)\
print(rpm.expand(args .. "\\n"))\
}
%define _nosinglespec 1
%endif
Name: salt%{psuffix}
Version: 3006.0
@ -509,6 +509,21 @@ Patch151: enhance-find_json-garbage-filtering-bsc-1231605-688.patch
Patch152: update-for-deprecation-of-hex-in-pygit2-1.15.0-and-a.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67186
Patch153: fix-failed-to-stat-root-.gitconfig-issue-on-gitfs-bs.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/58f448405b7f46505b2047ecda72abb42b6df9d1
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/79d4ff772a162b5b8e602e3437c13b90a25bc190
Patch154: fix-tests-failures-after-repo.saltproject.io-depreca.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/60269
Patch155: backport-batch-async-fixes-and-improvements-701.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/commit/560ab52ccf94c7974d5a418dfbba7409e0493066
Patch156: fixed-file-client-private-attribute-reference-on-sal.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67734
Patch157: set-virtual-grain-in-podman-systemd-container-703.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67066
Patch158: repair-fstab_present-test-mode-702.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/67746
Patch159: make-_auth-calls-visible-with-master-stats-696.patch
# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/65843
Patch160: repair-virt_query-outputter-655.patch
### IMPORTANT: The line below is used as a snippet marker. Do not touch it.
### SALT PATCHES LIST END
@ -576,10 +591,6 @@ BuildRequires: bash
BuildRequires: zsh
%endif
%if 0%{?rhel} || 0%{?fedora}
BuildRequires: yum
%endif
%define python_subpackage_only 1
%python_subpackages
@ -593,7 +604,7 @@ servers, handle them quickly and through a simple and manageable interface.
%if "%{flavor}" != "testsuite"
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
%package -n python3-salt
%else
%package -n python-salt
@ -650,7 +661,7 @@ BuildRequires: %{python_module sphinx}
%if 0%{?rhel} == 8
Requires: platform-python
%else
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Requires: %{python_module base}
%else
Requires: python-base
@ -674,16 +685,13 @@ Requires: python3-m2crypto
Requires: python3-markupsafe
Requires: python3-msgpack > 0.3
Requires: python3-zmq >= 2.2.0
Requires: yum
%if 0%{?rhel} == 8 || 0%{?fedora} >= 30
%if 0%{?rhel} >= 8 || 0%{?fedora} >= 30
Requires: dnf
%endif
%if 0%{?rhel} == 6
Requires: yum-plugin-security
Requires: python3-dnf-plugins-core
%endif
%else # SUSE
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Requires: %{python_module Jinja2}
Requires: %{python_module MarkupSafe}
Requires: %{python_module msgpack-python > 0.3}
@ -705,7 +713,7 @@ Requires: python-pycrypto >= 2.6.1
Requires: python-pyzmq >= 2.2.0
%endif
%endif # end of RHEL / SUSE specific section
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Recommends: %{python_module jmespath}
Requires: %{python_module PyYAML}
Requires: %{python_module psutil}
@ -744,17 +752,20 @@ Suggests: python-gnupg
#
%if 0%{?suse_version}
# python-xml is part of python-base in all rhel versions
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Requires: %{python_module xml}
Requires: %{python_module zypp-plugin}
Suggests: %{python_module Mako}
Recommends: %{python_module netaddr}
Recommends: %{python_module pyinotify}
%else
Requires: python-xml
Requires: python-zypp-plugin
Suggests: python-Mako
Recommends: python-netaddr
Recommends: python-pyinotify
%endif
Requires(pre): libzypp(plugin:system) >= 0
%endif
# Required by Salt modules
@ -764,7 +775,7 @@ Requires: file
Recommends: man
Recommends: python3-passlib
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Provides: bundled(%{python_module tornado}) = 4.5.3
%else
Provides: bundled(python-tornado) = 4.5.3
@ -772,7 +783,7 @@ Provides: bundled(python-tornado) = 4.5.3
Provides: %{name}-call = %{version}-%{release}
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
%description -n python3-salt
%else
%description -n python-salt
@ -785,7 +796,11 @@ Group: System/Management
Requires: %{name} = %{version}-%{release}
Requires: %{name}-master = %{version}-%{release}
%if 0%{?suse_version}
%if 0%{?sle_version} >= 150400
Requires: %{python_module CherryPy >= 3.2.2 if %python-salt}
%else
Requires: python3-CherryPy >= 3.2.2
%endif
%else
Requires: python3-cherrypy >= 3.2.2
%endif
@ -798,11 +813,19 @@ Summary: Generic cloud provisioning tool for Saltstack
Group: System/Management
Requires: %{name} = %{version}-%{release}
Requires: %{name}-master = %{version}-%{release}
Requires: python3-apache-libcloud
%if 0%{?suse_version}
%if 0%{?sle_version} >= 150400
Requires: %{python_module apache-libcloud if %python-salt}
Recommends: %{python_module botocore if %python-salt}
Recommends: %{python_module netaddr if %python-salt}
%else
Requires: python3-apache-libcloud
Recommends: python3-botocore
Recommends: python3-netaddr
%endif
%else
Requires: python3-apache-libcloud
%endif
%description cloud
public cloud VM management system
@ -824,8 +847,12 @@ Summary: The management component of Saltstack with zmq protocol supporte
Group: System/Management
Requires: %{name} = %{version}-%{release}
%if 0%{?suse_version}
%if 0%{?sle_version} >= 150400
Recommends: %{python_module pygit2 >= 0.20.3 if %python-salt}
%else
Recommends: python3-pygit2 >= 0.20.3
%endif
%endif
%ifarch %{ix86} x86_64
%if 0%{?suse_version}
%if 0%{?suse_version} > 1110
@ -852,10 +879,6 @@ Requires: %{name} = %{version}-%{release}
%if 0%{?suse_version} > 1500 || 0%{?sle_version} > 150000
Requires: (%{name}-transactional-update = %{version}-%{release} if read-only-root-fs)
%endif
%if 0%{?suse_version}
Requires: python3-zypp-plugin
Requires(pre): libzypp(plugin:system) >= 0
%endif
%if %{with systemd}
%{?systemd_requires}
@ -980,8 +1003,8 @@ list of active executors. This package add the configuration file.
%if "%{flavor}" == "testsuite"
%if 0%{?_nosinglespec}
%package -n %{python_module salt-testsuite}
%if 0%{?singlespec_compat}
%package -n python3-salt-testsuite
%else
%package -n python-salt-testsuite
%endif
@ -995,7 +1018,7 @@ BuildRequires: %{python_module base}
BuildRequires: %{python_module setuptools}
Requires: salt = %{version}
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
Recommends: %{python_module CherryPy}
Requires: %{python_module Genshi}
Requires: %{python_module Mako}
@ -1042,7 +1065,7 @@ Requires: git
Obsoletes: %{name}-tests
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
%description -n python3-salt-testsuite
%else
%description -n python-salt-testsuite
@ -1161,11 +1184,9 @@ cp -a conf %{buildroot}%{$python_sitelib}/salt-testsuite/
%if 0%{?suse_version}
install -Dd -m 0750 %{buildroot}%{_prefix}/lib/zypp/plugins/commit
%{__install} scripts/suse/zypper/plugins/commit/zyppnotify %{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify
sed -i '1s=^#!/usr/bin/\(python\|env python\)[0-9.]*=#!/usr/bin/python3=' %{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify
%endif
# Install Yum plugins only on RH machines
%if 0%{?fedora} || 0%{?rhel}
# Install DNF plugin only on RH machines
%if 0%{?fedora} >= 22 || 0%{?rhel} >= 8
install -Dd %{buildroot}%{python3_sitelib}/dnf-plugins
install -Dd %{buildroot}%{python3_sitelib}/dnf-plugins/__pycache__
@ -1174,14 +1195,6 @@ install -Dd %{buildroot}%{_sysconfdir}/dnf/plugins
%{__install} scripts/suse/dnf/plugins/dnfnotify.conf %{buildroot}%{_sysconfdir}/dnf/plugins
%{__python3} -m compileall -d %{python3_sitelib}/dnf-plugins %{buildroot}%{python3_sitelib}/dnf-plugins/dnfnotify.py
%{__python3} -O -m compileall -d %{python3_sitelib}/dnf-plugins %{buildroot}%{python3_sitelib}/dnf-plugins/dnfnotify.py
%else
install -Dd %{buildroot}%{_prefix}/share/yum-plugins
install -Dd %{buildroot}%{_sysconfdir}/yum/pluginconf.d
%{__install} scripts/suse/yum/plugins/yumnotify.py %{buildroot}%{_prefix}/share/yum-plugins
%{__install} scripts/suse/yum/plugins/yumnotify.conf %{buildroot}%{_sysconfdir}/yum/pluginconf.d
%{__python} -m compileall -d %{_prefix}/share/yum-plugins %{buildroot}%{_prefix}/share/yum-plugins/yumnotify.py
%{__python} -O -m compileall -d %{_prefix}/share/yum-plugins %{buildroot}%{_prefix}/share/yum-plugins/yumnotify.py
%endif
%endif
## install init and systemd scripts
@ -1252,6 +1265,17 @@ install -Dpm 0640 conf/suse/standalone-formulas-configuration.conf %{buildroot}%
%if 0%{?_alternatives}
%python_clone -a %{buildroot}%{_bindir}/salt-call
%python_clone -a %{buildroot}%{_bindir}/salt-support
%python_clone -a %{buildroot}%{_bindir}/spm
install -Dd -m 0750 %{buildroot}%{_exec_prefix}/libexec/salt
for SALT_SCRIPT in salt salt-api salt-cloud salt-cp salt-key salt-master salt-minion salt-proxy salt-run salt-ssh salt-syndic; do
mv "%{buildroot}%{_bindir}/${SALT_SCRIPT}" "%{buildroot}%{_exec_prefix}/libexec/salt/"
%python_clone -a %{buildroot}%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}
ln -s "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}" "%{buildroot}%{_bindir}/${SALT_SCRIPT}"
done
mv "%{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify" "%{buildroot}%{_exec_prefix}/libexec/salt/"
%python_clone -a %{buildroot}%{_exec_prefix}/libexec/salt/zyppnotify
ln -s "%{_exec_prefix}/libexec/salt/zyppnotify" "%{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify"
%endif
%endif
@ -1274,10 +1298,6 @@ getent passwd salt >/dev/null || %{_sbindir}/useradd -r -g salt -d $S_HOME -s /b
if [[ -d "$S_PHOME/.ssh" ]]; then
mv $S_PHOME/.ssh $S_HOME
fi
%if 0%{?_alternatives}
[ -h %{_bindir}/salt-call ] || rm -f %{_bindir}/salt-call
%python_libalternatives_reset_alternative salt-call
%endif
%post
%if %{with systemd}
@ -1486,17 +1506,49 @@ fi
%if 0%{?_alternatives}
%pre -n python-salt
[ -h %{_bindir}/salt-call ] || rm -f %{_bindir}/salt-call
%python_libalternatives_reset_alternative salt-call
for SALT_SCRIPT in salt-call salt-support spm; do
[ -h "%{_bindir}/${SALT_SCRIPT}" ] || rm -f "%{_bindir}/${SALT_SCRIPT}"
if [ "$1" -gt 0 ] && [ -f /usr/sbin/update-alternatives ]; then
update-alternatives --quiet --remove "${SALT_SCRIPT}" "%{_bindir}/${SALT_SCRIPT}-%{python_bin_suffix}"
fi
done
for SALT_SCRIPT in salt salt-api salt-cloud salt-cp salt-key salt-master salt-minion salt-proxy salt-run salt-ssh salt-syndic zyppnotify; do
[ -h "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}" ] || rm -f "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}"
if [ "$1" -gt 0 ] && [ -f /usr/sbin/update-alternatives ]; then
update-alternatives --quiet --remove "${SALT_SCRIPT}" "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}-%{python_bin_suffix}"
fi
done
%if ! %{with libalternatives}
%post -n python-salt
%python_install_alternative salt-call
if [ -f /usr/sbin/update-alternatives ]; then
for SALT_SCRIPT in salt-call salt-support spm; do
update-alternatives --quiet --install "%{_bindir}/${SALT_SCRIPT}" "${SALT_SCRIPT}" \
"%{_bindir}/${SALT_SCRIPT}-%{python_bin_suffix}" %{python_version_nodots}
done
for SALT_SCRIPT in salt salt-api salt-cloud salt-cp salt-key salt-master salt-minion salt-proxy salt-run salt-ssh salt-syndic zyppnotify; do
update-alternatives --quiet --install "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}" "${SALT_SCRIPT}" \
"%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}-%{python_bin_suffix}" %{python_version_nodots}
done
fi
%postun -n python-salt
%python_uninstall_alternative salt-call
if [ -f /usr/sbin/update-alternatives ]; then
for SALT_SCRIPT in salt-call salt-support spm; do
if [ ! -e "%{_bindir}/${SALT_SCRIPT}-%{python_bin_suffix}" ]; then
update-alternatives --quiet --remove "${SALT_SCRIPT}" "%{_bindir}/${SALT_SCRIPT}-%{python_bin_suffix}"
fi
done
for SALT_SCRIPT in salt salt-api salt-cloud salt-cp salt-key salt-master salt-minion salt-proxy salt-run salt-ssh salt-syndic zyppnotify; do
if [ ! -e "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}-%{python_bin_suffix}" ]; then
update-alternatives --quiet --remove "${SALT_SCRIPT}" "%{_exec_prefix}/libexec/salt/${SALT_SCRIPT}-%{python_bin_suffix}"
fi
done
fi
%endif
%endif
%if 0%{?_nosinglespec}
%if 0%{?singlespec_compat}
%posttrans -n %{python_module salt}
%else
%posttrans -n python-salt
@ -1559,16 +1611,11 @@ rm -f %{_localstatedir}/cache/salt/minion/thin/version
%{_prefix}/lib/zypp/plugins/commit/zyppnotify
%endif
# Install Yum plugins only on RH machines
%if 0%{?fedora} || 0%{?rhel}
# Install DNF plugin only on RH machines
%if 0%{?fedora} >= 22 || 0%{?rhel} >= 8
%{python3_sitelib}/dnf-plugins/dnfnotify.py
%{python3_sitelib}/dnf-plugins/__pycache__/dnfnotify.*
%{_sysconfdir}/dnf/plugins/dnfnotify.conf
%else
%{_prefix}/share/yum-plugins/yumnotify.*
%{_sysconfdir}/yum/pluginconf.d/yumnotify.conf
%endif
%endif
%if %{with systemd}
@ -1651,7 +1698,24 @@ rm -f %{_localstatedir}/cache/salt/minion/thin/version
%defattr(-,root,root,-)
%if 0%{?_alternatives}
%python_alternative %{_bindir}/salt-call
%python_alternative %{_bindir}/salt-support
%python_alternative %{_bindir}/spm
%dir %{_exec_prefix}/libexec
%dir %attr(0755, root, root) %{_exec_prefix}/libexec/salt
%python_alternative %{_exec_prefix}/libexec/salt/salt
%python_alternative %{_exec_prefix}/libexec/salt/salt-api
%python_alternative %{_exec_prefix}/libexec/salt/salt-cloud
%python_alternative %{_exec_prefix}/libexec/salt/salt-cp
%python_alternative %{_exec_prefix}/libexec/salt/salt-key
%python_alternative %{_exec_prefix}/libexec/salt/salt-master
%python_alternative %{_exec_prefix}/libexec/salt/salt-minion
%python_alternative %{_exec_prefix}/libexec/salt/salt-proxy
%python_alternative %{_exec_prefix}/libexec/salt/salt-run
%python_alternative %{_exec_prefix}/libexec/salt/salt-ssh
%python_alternative %{_exec_prefix}/libexec/salt/salt-syndic
%python_alternative %{_exec_prefix}/libexec/salt/zyppnotify
%endif
%dir %{python_sitelib}/salt
%dir %{python_sitelib}/salt-*.egg-info
%{python_sitelib}/salt/*

View File

@ -0,0 +1,84 @@
From dde665763bd2f043022f9601dd25d0ca8aa716be Mon Sep 17 00:00:00 2001
From: Georg <georg@lysergic.dev>
Date: Fri, 21 Feb 2025 10:24:51 +0000
Subject: [PATCH] Set virtual grain in Podman systemd container (#703)
Correctly handle the systemd-detect-virt output to identify a Podman
container running systemd as what it is instead of as a physical machine.
Signed-off-by: Georg Pfuetzenreuter <georg.pfuetzenreuter@suse.com>
(cherry picked from commit cf504a06859fb4a4fe9b8ebdd76380697f1f0c25)
---
changelog/67733.fixed.md | 1 +
salt/grains/core.py | 4 ++++
tests/pytests/unit/grains/test_core.py | 31 ++++++++++++++++++++++++++
3 files changed, 36 insertions(+)
create mode 100644 changelog/67733.fixed.md
diff --git a/changelog/67733.fixed.md b/changelog/67733.fixed.md
new file mode 100644
index 0000000000..242f65ec76
--- /dev/null
+++ b/changelog/67733.fixed.md
@@ -0,0 +1 @@
+Set correct virtual grain in systemd based Podman containers
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 84d5b179dd..ceb142a7b8 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -911,6 +911,10 @@ def _virtual(osdata):
grains["virtual"] = "container"
grains["virtual_subtype"] = "LXC"
break
+ elif "podman" in output:
+ grains["virtual"] = "container"
+ grains["virtual_subtype"] = "Podman"
+ break
elif "amazon" in output:
grains["virtual"] = "Nitro"
grains["virtual_subtype"] = "Amazon EC2"
diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py
index 3d2beaa2c9..072287248f 100644
--- a/tests/pytests/unit/grains/test_core.py
+++ b/tests/pytests/unit/grains/test_core.py
@@ -1752,6 +1752,37 @@ def test_lxc_virtual_with_virt_what():
assert ret["virtual_subtype"] == "LXC"
+@pytest.mark.skip_on_windows
+def test_podman_virtual_with_systemd_detect_virt():
+ """
+ Test if virtual grains are parsed correctly in Podman using systemd-detect-virt.
+ """
+
+ def _which_side_effect(path):
+ if path == "systemd-detect-virt":
+ return "/usr/bin/systemd-detect-virt"
+ return None
+
+ with patch.object(
+ salt.utils.platform, "is_windows", MagicMock(return_value=False)
+ ), patch.object(
+ salt.utils.path,
+ "which",
+ MagicMock(return_value=True, side_effect=_which_side_effect),
+ ), patch.dict(
+ core.__salt__,
+ {
+ "cmd.run_all": MagicMock(
+ return_value={"pid": 78, "retcode": 0, "stderr": "", "stdout": "podman"}
+ )
+ },
+ ):
+ osdata = {"kernel": "test"}
+ ret = core._virtual(osdata)
+ assert ret["virtual"] == "container"
+ assert ret["virtual_subtype"] == "Podman"
+
+
@pytest.mark.skip_on_windows
def test_container_inside_virtual_machine():
"""
--
2.48.1