Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
215aaca98b | ||
|
|
2dd39933dd | ||
|
|
7be6471c1a | ||
| a86f542cfd | |||
| d6f98c0e3f | |||
| baa3d1b3ab | |||
| bec308ba16 | |||
| ee271c3b5d |
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
SOURCES/sos-4.8.1.tar.gz
|
SOURCES/sos-4.11.2.tar.gz
|
||||||
SOURCES/sos-audit-0.3.tgz
|
SOURCES/sos-audit-0.3-1.tgz
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
26aee6ec0ad73c12a4ad0cf50c02082777d654cc SOURCES/sos-4.8.1.tar.gz
|
d8d5e3e1eb124345417341ef9e9aa84f5cae609f SOURCES/sos-4.11.2.tar.gz
|
||||||
9d478b9f0085da9178af103078bbf2fd77b0175a SOURCES/sos-audit-0.3.tgz
|
00752b68ec5e1141192a9dab7d44377b8d637bf7 SOURCES/sos-audit-0.3-1.tgz
|
||||||
|
|||||||
@ -0,0 +1,167 @@
|
|||||||
|
--- a/sos/report/plugins/coredump.py
|
||||||
|
+++ b/sos/report/plugins/coredump.py
|
||||||
|
@@ -72,8 +72,8 @@
|
||||||
|
cdump = line.split()
|
||||||
|
pid = cdump[4]
|
||||||
|
exe = cdump[-2]
|
||||||
|
- if regex := self.get_option("executable"):
|
||||||
|
- if not re.search(regex, exe, re.I):
|
||||||
|
+ if self.get_option("executable"):
|
||||||
|
+ if not re.search(self.get_option("executable"), exe, re.I):
|
||||||
|
continue
|
||||||
|
cinfo = self.collect_cmd_output(f"coredumpctl info {pid}")
|
||||||
|
if cinfo['status'] != 0:
|
||||||
|
--- a/sos/collector/sosnode.py
|
||||||
|
+++ b/sos/collector/sosnode.py
|
||||||
|
@@ -372,7 +372,8 @@
|
||||||
|
for line in result.splitlines():
|
||||||
|
if not is_list:
|
||||||
|
try:
|
||||||
|
- if ls := line.split():
|
||||||
|
+ ls = line.split()
|
||||||
|
+ if ls:
|
||||||
|
res.append(ls[0])
|
||||||
|
except Exception as err:
|
||||||
|
self.log_debug(f"Error parsing sos help: {err}")
|
||||||
|
--- a/sos/report/plugins/mongodb.py 2026-07-02 09:06:03.860609746 +0200
|
||||||
|
+++ b/sos/report/plugins/mongodb.py 2026-07-02 09:08:00.003595562 +0200
|
||||||
|
@@ -87,10 +87,13 @@
|
||||||
|
)
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
- if get_juju_info := self.path_exists('/var/lib/juju/db'):
|
||||||
|
+ get_juju_info = self.path_exists('/var/lib/juju/db')
|
||||||
|
+ if get_juju_info:
|
||||||
|
self.db_folder = "/var/lib/juju/db"
|
||||||
|
- elif get_juju_info := self.path_exists('/var/snap/juju-db/curent/db'):
|
||||||
|
- self.db_folder = "/var/snap/juju-db/current/db"
|
||||||
|
+ else:
|
||||||
|
+ get_juju_info = self.path_exists('/var/snap/juju-db/current/db')
|
||||||
|
+ if get_juju_info:
|
||||||
|
+ self.db_folder = "/var/snap/juju-db/current/db"
|
||||||
|
|
||||||
|
super().setup()
|
||||||
|
|
||||||
|
--- a/sos/report/plugins/loki.py 2025-11-24 11:20:56.237814760 +0100
|
||||||
|
+++ b/sos/report/plugins/loki.py 2025-11-24 11:28:37.466603011 +0100
|
||||||
|
@@ -143,7 +143,8 @@
|
||||||
|
if self.get_option("collect-logs"):
|
||||||
|
endpoint = self.get_option("endpoint") or "http://localhost:3100"
|
||||||
|
self.labels = []
|
||||||
|
- if labels_option := self.get_option("labels"):
|
||||||
|
+ labels_option = self.get_option("labels")
|
||||||
|
+ if labels_option:
|
||||||
|
if isinstance(labels_option, str) and labels_option:
|
||||||
|
self.labels.extend(labels_option.split(":"))
|
||||||
|
|
||||||
|
--- a/sos/cleaner/__init__.py
|
||||||
|
+++ b/sos/cleaner/__init__.py
|
||||||
|
@@ -40,6 +40,8 @@ from sos.utilities import (get_human_rea
|
||||||
|
|
||||||
|
# an auxiliary method to kick off child processes over its instances
|
||||||
|
def _obfuscate_arc_files(arc, input_queue, output_queue):
|
||||||
|
+ arc.soslog = logging.getLogger('sos')
|
||||||
|
+ arc.ui_log = logging.getLogger('sos_ui')
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
file = input_queue.get()
|
||||||
|
--- a/sos/cleaner/__init__.py 2026-07-01 13:45:34.298955340 +0200
|
||||||
|
+++ b/sos/cleaner/__init__.py 2026-07-01 13:47:15.978445308 +0200
|
||||||
|
@@ -795,6 +795,9 @@
|
||||||
|
# sentinel mark. That triggers the child processes to report back
|
||||||
|
# to output_queue some stats, and finish.
|
||||||
|
files_obfuscated_count = total_sub_count = removed_file_count = 0
|
||||||
|
+ # two nullification required before processes cloning
|
||||||
|
+ archive.soslog = None
|
||||||
|
+ archive.ui_log = None
|
||||||
|
input_queue = multiprocessing.Queue()
|
||||||
|
output_queue = multiprocessing.Queue()
|
||||||
|
|
||||||
|
--- a/sos/collector/sosnode.py 2026-04-02 10:15:34.743009569 +0200
|
||||||
|
+++ b/sos/collector/sosnode.py 2026-04-02 10:17:42.557250748 +0200
|
||||||
|
@@ -163,7 +163,8 @@
|
||||||
|
if not self._sudo_binary:
|
||||||
|
_bin = self.opts.sudo_binary.split('/')[-1]
|
||||||
|
# verify the provided binary is at least in our PATH
|
||||||
|
- if ret := self.run_command(f"command -v {_bin}"):
|
||||||
|
+ ret = self.run_command(f"command -v {_bin}")
|
||||||
|
+ if ret:
|
||||||
|
if not ret['status'] == 0:
|
||||||
|
err = f"Privilege escalation command not in PATH: {_bin}"
|
||||||
|
self.log_error(err)
|
||||||
|
|
||||||
|
--- a/sos/report/plugins/logs.py 2026-04-02 10:19:59.641196712 +0200
|
||||||
|
+++ b/sos/report/plugins/logs.py 2026-04-02 10:20:28.313299348 +0200
|
||||||
|
@@ -38,7 +38,8 @@
|
||||||
|
# this WILL break on anything other than basic echos
|
||||||
|
# as shown in the rsyslog documentation
|
||||||
|
if _ent.startswith('echo '):
|
||||||
|
- if envc := os.getenv(_ent.split()[1].strip(' $`')):
|
||||||
|
+ envc = os.getenv(_ent.split()[1].strip(' $`'))
|
||||||
|
+ if envc:
|
||||||
|
confs += glob.glob(envc)
|
||||||
|
else:
|
||||||
|
confs += glob.glob(_ent)
|
||||||
|
|
||||||
|
--- a/sos/report/plugins/charmed_cruise_control.py 2026-07-16 13:00:22.269714807 +0200
|
||||||
|
+++ b/sos/report/plugins/charmed_cruise_control.py 2026-07-16 13:01:56.710522628 +0200
|
||||||
|
@@ -35,7 +35,8 @@
|
||||||
|
) as f:
|
||||||
|
content = f.read().strip()
|
||||||
|
|
||||||
|
- if match := re.match(r"balancer: (?P<pwd>\w+),ADMIN", content):
|
||||||
|
+ match = re.match(r"balancer: (?P<pwd>\w+),ADMIN", content)
|
||||||
|
+ if match:
|
||||||
|
pwd = match.group("pwd")
|
||||||
|
return f"-u balancer:{pwd}"
|
||||||
|
|
||||||
|
--- a/sos/report/plugins/__init__.py
|
||||||
|
+++ b/sos/report/plugins/__init__.py
|
||||||
|
@@ -3262,7 +3262,10 @@
|
||||||
|
# skip forbidden paths; since we might recursivelly copied
|
||||||
|
# whole directory, we must find the forbidden files in dest
|
||||||
|
# path and delete the unwanted
|
||||||
|
- base_dir = dest.removesuffix(f"{path.lstrip('/')}")
|
||||||
|
+ _suffix = path.lstrip('/')
|
||||||
|
+ base_dir = (dest[:-len(_suffix)]
|
||||||
|
+ if dest.endswith(_suffix) and _suffix
|
||||||
|
+ else dest)
|
||||||
|
for relname in [file.relative_to(base_dir).as_posix()
|
||||||
|
for file in Path(dest).rglob('*')]:
|
||||||
|
absname = f"/{relname}"
|
||||||
|
|
||||||
|
--- a/sos/cleaner/__init__.py
|
||||||
|
+++ b/sos/cleaner/__init__.py
|
||||||
|
@@ -846,6 +846,8 @@
|
||||||
|
# *all* mapping.all(item) methods - so replaying this will
|
||||||
|
# generate the right datasets!
|
||||||
|
archive.load_parser_entries()
|
||||||
|
+ archive.soslog = logging.getLogger('sos')
|
||||||
|
+ archive.ui_log = logging.getLogger('sos_ui')
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.obfuscate_directory_names(archive)
|
||||||
|
|
||||||
|
--- a/sos/report/plugins/charmed_mongodb.py 2026-07-16 14:48:09.639484635 +0200
|
||||||
|
+++ b/sos/report/plugins/charmed_mongodb.py 2026-07-16 14:49:02.337015148 +0200
|
||||||
|
@@ -122,8 +122,8 @@
|
||||||
|
encoding="utf-8",
|
||||||
|
) as f:
|
||||||
|
data = yaml.safe_load(f)
|
||||||
|
-
|
||||||
|
- if sharding_conf := data.get("sharding", {}):
|
||||||
|
+ sharding_conf = data.get("sharding", {})
|
||||||
|
+ if sharding_conf:
|
||||||
|
role = sharding_conf.get("clusterRole", "")
|
||||||
|
|
||||||
|
return self._match_role(role)
|
||||||
|
@@ -144,7 +144,8 @@
|
||||||
|
return None
|
||||||
|
|
||||||
|
data = yaml.safe_load(result.get("output", ""))
|
||||||
|
- if sharding_conf := data.get("sharding", {}):
|
||||||
|
+ sharding_conf = data.get("sharding", {})
|
||||||
|
+ if sharding_conf:
|
||||||
|
role = sharding_conf.get("clusterRole", "")
|
||||||
|
return self._match_role(role)
|
||||||
|
|
||||||
1436
SOURCES/0002-remove-unsupported-python36-plugins.patch
Normal file
1436
SOURCES/0002-remove-unsupported-python36-plugins.patch
Normal file
File diff suppressed because it is too large
Load Diff
27
SOURCES/0003-sosreport-binary.patch
Normal file
27
SOURCES/0003-sosreport-binary.patch
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
--- /dev/null 2025-10-28 14:11:21.494784405 +0100
|
||||||
|
+++ sos-4.10.1/bin/sosreport 2025-12-04 08:46:53.277857061 +0100
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+echo "sosreport binary is deprecated, use 'sos report' instead"
|
||||||
|
+exec sos report "$@"
|
||||||
|
+
|
||||||
|
+# vim:ts=4 et sw=4
|
||||||
|
--- /dev/null 2025-10-28 14:11:21.494784405 +0100
|
||||||
|
+++ sos-4.10.1/bin/sos-collector 2025-12-04 08:48:04.661880220 +0100
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+#!/bin/bash
|
||||||
|
+echo "sos-collector binary is deprecated, use 'sos collector' instead"
|
||||||
|
+exec sos collector "$@"
|
||||||
|
+
|
||||||
|
+# vim:ts=4 et sw=4
|
||||||
|
--- sos-4.10.1/setup.py 2025-04-15 15:17:21.938635468 +0200
|
||||||
|
+++ sos-4.10.1/setup.py 2025-04-15 15:17:41.328198501 +0200
|
||||||
|
@@ -34,7 +34,7 @@
|
||||||
|
maintainer_email='jacob.r.hunsaker@gmail.com',
|
||||||
|
url='https://github.com/sosreport/sos',
|
||||||
|
license="GPLv2+",
|
||||||
|
- scripts=['bin/sos'],
|
||||||
|
+ scripts=['bin/sos', 'bin/sosreport', 'bin/sos-collector'],
|
||||||
|
data_files=data_files,
|
||||||
|
packages=find_packages(include=['sos', 'sos.*'])
|
||||||
|
)
|
||||||
121
SOURCES/0004-revert-PR4092-and-PR4275.patch
Normal file
121
SOURCES/0004-revert-PR4092-and-PR4275.patch
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
diff --git a/sos/upload/targets/__init__.py b/sos/upload/targets/__init__.py
|
||||||
|
index 9e905e1063..6f72d963ea 100644
|
||||||
|
--- a/sos/upload/targets/__init__.py
|
||||||
|
+++ b/sos/upload/targets/__init__.py
|
||||||
|
@@ -540,36 +540,7 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
raise Exception("Unable to connect via SFTP to "
|
||||||
|
f"{self.get_upload_url_string()}")
|
||||||
|
|
||||||
|
- # user_dir indicates that we need to switch into a specific user
|
||||||
|
- # directory. If ChRootDirectory is set, this happens automatically
|
||||||
|
- # so check if the PWD contains the user. If it does, we are
|
||||||
|
- # already in the user directory so set user_dir to None
|
||||||
|
- if user_dir:
|
||||||
|
- user_match = False
|
||||||
|
- ret.sendline('pwd')
|
||||||
|
- pwd_expects = [
|
||||||
|
- 'sftp>',
|
||||||
|
- 'Invalid command.',
|
||||||
|
- pexpect.TIMEOUT,
|
||||||
|
- pexpect.EOF
|
||||||
|
- ]
|
||||||
|
- pwd_cmd = ret.expect(pwd_expects, timeout=10) == 0
|
||||||
|
- if pwd_cmd:
|
||||||
|
- # Extract the path from child.before
|
||||||
|
- raw_output = ret.before
|
||||||
|
- user_match = re.search(user, raw_output)
|
||||||
|
- else:
|
||||||
|
- self.ui_log.warning("This server does not support the PWD "
|
||||||
|
- "command - unable to verify user "
|
||||||
|
- "directory. Attempting upload without "
|
||||||
|
- "changing to user directory.")
|
||||||
|
- user_dir = None
|
||||||
|
-
|
||||||
|
- if user_match:
|
||||||
|
- user_dir = None
|
||||||
|
-
|
||||||
|
# certain implementations require file to be put in the user dir
|
||||||
|
- # so we prepend the user directory to the file path
|
||||||
|
put_cmd = (
|
||||||
|
f"put {self.upload_archive_name} "
|
||||||
|
f"{f'{user_dir}/' if user_dir else ''}"
|
||||||
|
diff --git a/sos/upload/targets/redhat.py b/sos/upload/targets/redhat.py
|
||||||
|
index 636a645fe6..0cfb80eecd 100644
|
||||||
|
--- a/sos/upload/targets/redhat.py
|
||||||
|
+++ b/sos/upload/targets/redhat.py
|
||||||
|
@@ -158,7 +158,6 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
" for obtaining SFTP auth token.")
|
||||||
|
_token = None
|
||||||
|
_user = None
|
||||||
|
- _user_dir = None
|
||||||
|
|
||||||
|
# We may have a device token already if we attempted
|
||||||
|
# to upload via http but the upload failed. So
|
||||||
|
@@ -192,7 +191,6 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
# credentials are valid
|
||||||
|
_user = json.loads(ret.text)['username']
|
||||||
|
_token = json.loads(ret.text)['token']
|
||||||
|
- _user_dir = f"/users/{_user}"
|
||||||
|
else:
|
||||||
|
self.ui_log.debug(
|
||||||
|
f"DEBUG: auth attempt failed (status: {ret.status_code}): "
|
||||||
|
@@ -220,7 +218,7 @@ def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
)
|
||||||
|
if _user and _token:
|
||||||
|
return super().upload_sftp(user=_user, password=_token,
|
||||||
|
- user_dir=_user_dir)
|
||||||
|
+ user_dir=_user)
|
||||||
|
raise Exception("Could not retrieve valid or anonymous credentials")
|
||||||
|
|
||||||
|
def check_file_too_big(self, archive):
|
||||||
|
--
|
||||||
|
2.47.0
|
||||||
|
--- a/sos/upload/targets/__init__.py 2025-09-16 19:57:27.294642506 +0200
|
||||||
|
+++ b/sos/upload/targets/__init__.py 2025-09-16 19:59:44.498573843 +0200
|
||||||
|
@@ -465,7 +465,7 @@
|
||||||
|
self.upload_password or
|
||||||
|
self._upload_password)
|
||||||
|
|
||||||
|
- def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
+ def upload_sftp(self, user=None, password=None):
|
||||||
|
"""Attempts to upload the archive to an SFTP location.
|
||||||
|
|
||||||
|
Due to the lack of well maintained, secure, and generally widespread
|
||||||
|
@@ -540,13 +540,10 @@
|
||||||
|
raise Exception("Unable to connect via SFTP to "
|
||||||
|
f"{self.get_upload_url_string()}")
|
||||||
|
|
||||||
|
- # certain implementations require file to be put in the user dir
|
||||||
|
- put_cmd = (
|
||||||
|
- f"put {self.upload_archive_name} "
|
||||||
|
- f"{f'{user_dir}/' if user_dir else ''}"
|
||||||
|
- f"{self._get_sftp_upload_name()}"
|
||||||
|
- )
|
||||||
|
+ put_cmd = (f'put {self.upload_archive_name} '
|
||||||
|
+ f'{self._get_sftp_upload_name()}')
|
||||||
|
ret.sendline(put_cmd)
|
||||||
|
+
|
||||||
|
put_expects = [
|
||||||
|
'100%',
|
||||||
|
pexpect.TIMEOUT,
|
||||||
|
--- a/sos/upload/targets/redhat.py 2025-09-16 19:57:36.804628207 +0200
|
||||||
|
+++ b/sos/upload/targets/redhat.py 2025-09-16 20:00:52.578728154 +0200
|
||||||
|
@@ -145,7 +145,7 @@
|
||||||
|
return fname
|
||||||
|
|
||||||
|
# pylint: disable=too-many-branches
|
||||||
|
- def upload_sftp(self, user=None, password=None, user_dir=None):
|
||||||
|
+ def upload_sftp(self, user=None, password=None):
|
||||||
|
"""Override the base upload_sftp to allow for setting an on-demand
|
||||||
|
generated anonymous login for the RH SFTP server if a username and
|
||||||
|
password are not given
|
||||||
|
@@ -217,8 +217,7 @@
|
||||||
|
f"{anon.status_code}): {anon.json()}"
|
||||||
|
)
|
||||||
|
if _user and _token:
|
||||||
|
- return super().upload_sftp(user=_user, password=_token,
|
||||||
|
- user_dir=_user)
|
||||||
|
+ return super().upload_sftp(user=_user, password=_token)
|
||||||
|
raise Exception("Could not retrieve valid or anonymous credentials")
|
||||||
|
|
||||||
|
def check_file_too_big(self, archive):
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
From 2fab657e3909f76e31bc6c56a5ad26f86a9925e5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Moravec <pmoravec@redhat.com>
|
||||||
|
Date: Tue, 23 Jun 2026 17:17:01 +0200
|
||||||
|
Subject: [PATCH] [foreman-installer] Scrub secrets in CLI arg dumps
|
||||||
|
|
||||||
|
Installer logs dump CLI args we need to scrub.
|
||||||
|
|
||||||
|
Closes: #4367
|
||||||
|
|
||||||
|
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
|
||||||
|
---
|
||||||
|
sos/report/plugins/foreman_installer.py | 7 ++++---
|
||||||
|
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/sos/report/plugins/foreman_installer.py b/sos/report/plugins/foreman_installer.py
|
||||||
|
index f55cde23..89eef2e4 100644
|
||||||
|
--- a/sos/report/plugins/foreman_installer.py
|
||||||
|
+++ b/sos/report/plugins/foreman_installer.py
|
||||||
|
@@ -54,11 +54,12 @@ class ForemanInstaller(Plugin, DebianPlugin, UbuntuPlugin):
|
||||||
|
r"::(.*(token|secret|key|passw).*)\") value:) "
|
||||||
|
r"(.*)")
|
||||||
|
self.do_path_regex_sub(install_logs, logs_debug_reg, r"\1 \2 ********")
|
||||||
|
- # also hide passwords in yet different formats
|
||||||
|
+ # also hide passwords in yet different formats, including CLI arg dumps
|
||||||
|
self.do_path_regex_sub(
|
||||||
|
install_logs,
|
||||||
|
- r"password(\", \"|=|\" value: \"|\": \")(.*?)(\", \".*|\"]]|\"|$)",
|
||||||
|
- r"password\1********\3")
|
||||||
|
+ r"((?:password|consumer-key|consumer-secret|key-secret|secret-key|"
|
||||||
|
+ r"oauth-key|oauth-secret)(?:\", \"|\": \"|=))([^\"\n]*)(\"|$)",
|
||||||
|
+ r"\1********\3")
|
||||||
|
self.do_path_regex_sub(
|
||||||
|
"/var/log/foreman-installer/foreman-proxy*",
|
||||||
|
r"(\s*proxy_password\s=) (.*)",
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
97
SOURCES/0006-foremanctl-valkey-PR4376.patch
Normal file
97
SOURCES/0006-foremanctl-valkey-PR4376.patch
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
From 5e7a01d9df2bc4e1f2659ace959ea52228ee1eee Mon Sep 17 00:00:00 2001
|
||||||
|
From: akumari <akumari@redhat.com>
|
||||||
|
Date: Wed, 1 Jul 2026 09:26:52 +0530
|
||||||
|
Subject: [PATCH 1/2] [foremanctl] Enable plugin for containerized deployments
|
||||||
|
|
||||||
|
The plugin required foremanctl package which doesn't exist in
|
||||||
|
containerized mode. Add container detection to enable the plugin
|
||||||
|
and collect foremanctl health diagnostics for support cases.
|
||||||
|
|
||||||
|
Signed-off-by: akumari <akumari@redhat.com>
|
||||||
|
---
|
||||||
|
sos/report/plugins/foremanctl.py | 29 +++++++++++++++++++++++++----
|
||||||
|
1 file changed, 25 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/sos/report/plugins/foremanctl.py b/sos/report/plugins/foremanctl.py
|
||||||
|
index 1b6ba4a4..0425cc05 100644
|
||||||
|
--- a/sos/report/plugins/foremanctl.py
|
||||||
|
+++ b/sos/report/plugins/foremanctl.py
|
||||||
|
@@ -19,6 +19,7 @@ class Foremanctl(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
|
||||||
|
plugin_name = 'foremanctl'
|
||||||
|
profiles = ('sysmgmt',)
|
||||||
|
packages = ('foremanctl', )
|
||||||
|
+ containers = ('foreman', 'foreman-proxy',)
|
||||||
|
|
||||||
|
def setup(self):
|
||||||
|
self.add_copy_spec([
|
||||||
|
@@ -29,14 +30,34 @@ class Foremanctl(Plugin, RedHatPlugin, DebianPlugin, UbuntuPlugin):
|
||||||
|
|
||||||
|
self.add_cmd_output([
|
||||||
|
"foremanctl features",
|
||||||
|
+ "foremanctl health",
|
||||||
|
])
|
||||||
|
|
||||||
|
self.add_dir_listing(["/var/lib/foremanctl/"], recursive=True)
|
||||||
|
|
||||||
|
def postproc(self):
|
||||||
|
- self.do_path_regex_sub("/var/lib/foremanctl/parameters.yaml",
|
||||||
|
- r"(foreman_initial_admin_password:\s*)(.*)",
|
||||||
|
- r"\1********")
|
||||||
|
-
|
||||||
|
+ # Scrub passwords, credentials, tokens, secrets, and keys
|
||||||
|
+ self.do_path_regex_sub(
|
||||||
|
+ "/var/lib/foremanctl/parameters.yaml",
|
||||||
|
+ r"((.*)?(passw|cred|token|secret|key).*(\:\s|=))(.*)",
|
||||||
|
+ r"\1********")
|
||||||
|
+
|
||||||
|
+ # Scrub passwords from foremanctl logs - Pattern 1: key=value format
|
||||||
|
+ self.do_path_regex_sub(
|
||||||
|
+ "/var/log/foremanctl/foremanctl.*log*",
|
||||||
|
+ r"((passw|cred|token|secret|key)\w*\s*=\s*)(.*?)(\s|,|\"|'|$)",
|
||||||
|
+ r"\1********\4")
|
||||||
|
+
|
||||||
|
+ # Scrub passwords from foremanctl logs - Pattern 2: "password something" format
|
||||||
|
+ self.do_path_regex_sub(
|
||||||
|
+ "/var/log/foremanctl/foremanctl.*log*",
|
||||||
|
+ r"(password\s+)(.*?)(\s|,|\"|$)",
|
||||||
|
+ r"\1********\3")
|
||||||
|
+
|
||||||
|
+ # Scrub admin credentials in username:password format
|
||||||
|
+ self.do_path_regex_sub(
|
||||||
|
+ "/var/log/foremanctl/foremanctl.*log*",
|
||||||
|
+ r"(Admin credentials:\s+\w+:)(.*?)(\"|,|$)",
|
||||||
|
+ r"\1********\3")
|
||||||
|
|
||||||
|
# vim: set et ts=4 sw=4 :
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
|
From 3b6bbcb819e05aecf0fec4767588ea0376c9f218 Mon Sep 17 00:00:00 2001
|
||||||
|
From: akumari <akumari@redhat.com>
|
||||||
|
Date: Tue, 7 Jul 2026 14:06:40 +0530
|
||||||
|
Subject: [PATCH 2/2] [valkey] Add container support for containerized
|
||||||
|
deployments
|
||||||
|
|
||||||
|
Adds container support to the valkey plugin to enable it
|
||||||
|
for containerized deployments using foremanctl/quadlet.
|
||||||
|
|
||||||
|
Signed-off-by: akumari <akumari@redhat.com>
|
||||||
|
---
|
||||||
|
sos/report/plugins/valkey.py | 1 +
|
||||||
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
|
diff --git a/sos/report/plugins/valkey.py b/sos/report/plugins/valkey.py
|
||||||
|
index 26a74a56..f7b49253 100644
|
||||||
|
--- a/sos/report/plugins/valkey.py
|
||||||
|
+++ b/sos/report/plugins/valkey.py
|
||||||
|
@@ -19,6 +19,7 @@ class Valkey(Plugin, IndependentPlugin):
|
||||||
|
profiles = ('services',)
|
||||||
|
|
||||||
|
packages = ('valkey',)
|
||||||
|
+ containers = ('valkey',)
|
||||||
|
|
||||||
|
var_puppet_gen = "/var/lib/config-data/puppet-generated/valkey"
|
||||||
|
|
||||||
|
--
|
||||||
|
2.54.0
|
||||||
|
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
From 6085b2580173a7a43de8b541584c82481c617aa2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: asadawar <asadawar@users.noreply.github.com>
|
||||||
|
Date: Mon, 27 Jul 2026 17:50:42 +0530
|
||||||
|
Subject: [PATCH] [policies] Prefer most specific policy when multiple match
|
||||||
|
|
||||||
|
When multiple policies within the same module return True from
|
||||||
|
check(), the policy loader now selects the most specific one
|
||||||
|
(deepest in the class hierarchy) instead of whichever happens
|
||||||
|
to sort first alphabetically.
|
||||||
|
|
||||||
|
Previously, import_policy() returned classes sorted by name via
|
||||||
|
inspect.getmembers(), and load() picked the first match. This
|
||||||
|
caused RHELPolicy to always win over RedHatCoreOSPolicy inside
|
||||||
|
a toolbox container on RHCOS, because uppercase 'H' sorts before
|
||||||
|
lowercase 'e' in ASCII. Both policies return True in that context
|
||||||
|
(RHEL for the container's /etc/redhat-release, RHCOS for the
|
||||||
|
host's /host/etc/os-release), but the more specific RHCOS policy
|
||||||
|
was never reached.
|
||||||
|
|
||||||
|
This has existed since RedHatCoreOSPolicy was introduced in 2019
|
||||||
|
(commit fa06bc09c95c) but was never visible because RHCOS had no
|
||||||
|
behavioral differences from RHEL until the archive naming change
|
||||||
|
in commit 0e919b6.
|
||||||
|
|
||||||
|
The fix collects all matching policies from a module and sorts by
|
||||||
|
MRO depth (descending), so a subclass is always preferred over
|
||||||
|
its parent. This is safe because a subclass that returns True from
|
||||||
|
check() is by definition a more precise match than its parent.
|
||||||
|
|
||||||
|
Assisted-by: Claude Code <https://claude.ai/code>
|
||||||
|
Signed-off-by: asadawar <asadawar@users.noreply.github.com>
|
||||||
|
---
|
||||||
|
sos/policies/__init__.py | 18 +++++++++++-------
|
||||||
|
1 file changed, 11 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py
|
||||||
|
index 35b3a532..b4920e82 100644
|
||||||
|
--- a/sos/policies/__init__.py
|
||||||
|
+++ b/sos/policies/__init__.py
|
||||||
|
@@ -29,20 +29,24 @@ def import_policy(name):
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
-def load(cache={}, sysroot=None, init=None, probe_runtime=True,
|
||||||
|
+def load(cache=None, sysroot=None, init=None, probe_runtime=True,
|
||||||
|
remote_exec=None, remote_check=''):
|
||||||
|
+ if cache is None:
|
||||||
|
+ cache = {}
|
||||||
|
if 'policy' in cache:
|
||||||
|
return cache.get('policy')
|
||||||
|
|
||||||
|
import sos.policies.distros
|
||||||
|
helper = ImporterHelper(sos.policies.distros)
|
||||||
|
+ matches = []
|
||||||
|
for module in helper.get_modules():
|
||||||
|
- for policy in import_policy(module):
|
||||||
|
- if policy.check(remote=remote_check):
|
||||||
|
- cache['policy'] = policy(sysroot=sysroot, init=init,
|
||||||
|
- probe_runtime=probe_runtime,
|
||||||
|
- remote_exec=remote_exec)
|
||||||
|
- break
|
||||||
|
+ matches.extend([policy for policy in (import_policy(module) or [])
|
||||||
|
+ if policy.check(remote=remote_check)])
|
||||||
|
+ if matches:
|
||||||
|
+ matches.sort(key=lambda p: len(p.__mro__), reverse=True)
|
||||||
|
+ cache['policy'] = matches[0](sysroot=sysroot, init=init,
|
||||||
|
+ probe_runtime=probe_runtime,
|
||||||
|
+ remote_exec=remote_exec)
|
||||||
|
|
||||||
|
if sys.platform != 'linux':
|
||||||
|
raise Exception("SoS is not supported on this platform")
|
||||||
|
--
|
||||||
|
2.55.0
|
||||||
|
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
From d94095e55d69d5e4135df0193c9726c2789526ab Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pavel Moravec <pmoravec@redhat.com>
|
||||||
|
Date: Wed, 29 Jul 2026 10:46:25 +0200
|
||||||
|
Subject: [PATCH] [processor] Limit /sys/devices/system/cpu/cpu* subdirs
|
||||||
|
collected
|
||||||
|
|
||||||
|
For systems with >500 CPUs, collecting all such directories means
|
||||||
|
millions of files to be collected, what excessivelly slows down the
|
||||||
|
plugin until its timeout.
|
||||||
|
|
||||||
|
Limit the default number of such directories to 64, configurable via a
|
||||||
|
plugin option.
|
||||||
|
|
||||||
|
Resolves: #4399
|
||||||
|
|
||||||
|
Signed-off-by: Pavel Moravec <pmoravec@redhat.com>
|
||||||
|
---
|
||||||
|
sos/report/plugins/processor.py | 41 ++++++++++++++++++++++++++++++++-
|
||||||
|
1 file changed, 40 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/sos/report/plugins/processor.py b/sos/report/plugins/processor.py
|
||||||
|
index 9375b5a1..593bd36b 100644
|
||||||
|
--- a/sos/report/plugins/processor.py
|
||||||
|
+++ b/sos/report/plugins/processor.py
|
||||||
|
@@ -6,7 +6,9 @@
|
||||||
|
#
|
||||||
|
# See the LICENSE file in the source distribution for further information.
|
||||||
|
|
||||||
|
-from sos.report.plugins import Plugin, IndependentPlugin, SoSPredicate
|
||||||
|
+import re
|
||||||
|
+from sos.report.plugins import (Plugin, IndependentPlugin, SoSPredicate,
|
||||||
|
+ PluginOpt)
|
||||||
|
from sos.policies.distros.ubuntu import UbuntuPolicy
|
||||||
|
|
||||||
|
|
||||||
|
@@ -18,6 +20,11 @@ class Processor(Plugin, IndependentPlugin):
|
||||||
|
profiles = ('system', 'hardware', 'memory')
|
||||||
|
files = ('/proc/cpuinfo',)
|
||||||
|
packages = ('cpufreq-utils', 'cpuid')
|
||||||
|
+ option_list = [
|
||||||
|
+ PluginOpt('max_cpu_dirs', default=64, val_type=int,
|
||||||
|
+ desc='Maximum number of cpu[0-9]+ directories '
|
||||||
|
+ 'to collect from /sys/devices/system/cpu'),
|
||||||
|
+ ]
|
||||||
|
|
||||||
|
cpu_kmods = []
|
||||||
|
|
||||||
|
@@ -43,7 +50,39 @@ class Processor(Plugin, IndependentPlugin):
|
||||||
|
# copy /sys/devices/system/cpu/cpuX with separately applied sizelimit
|
||||||
|
# this is required for systems with tens/hundreds of CPUs where the
|
||||||
|
# cumulative directory size exceeds 25MB or even 100MB.
|
||||||
|
+ # Limit cpu[0-9]* directories to avoid excessive collection.
|
||||||
|
+ # All non-cpu* directories are always collected.
|
||||||
|
+ max_cpu_dirs = self.get_option('max_cpu_dirs')
|
||||||
|
+ if max_cpu_dirs < 0:
|
||||||
|
+ self._log_info(f"Invalid max_cpu_dirs={max_cpu_dirs} value "
|
||||||
|
+ f"provided, replacing by 0."
|
||||||
|
+ )
|
||||||
|
+ max_cpu_dirs = 0
|
||||||
|
cdirs = self.listdir('/sys/devices/system/cpu')
|
||||||
|
+
|
||||||
|
+ if len(cdirs) > max_cpu_dirs:
|
||||||
|
+ # separate cpu from non-cpu, then limit cpu dirs
|
||||||
|
+ cpu_pattern = re.compile(r'cpu(\d+)')
|
||||||
|
+ cpu_dirs = []
|
||||||
|
+ other_dirs = []
|
||||||
|
+
|
||||||
|
+ for cdir in cdirs:
|
||||||
|
+ if cpu_pattern.fullmatch(cdir):
|
||||||
|
+ cpu_dirs.append(cdir)
|
||||||
|
+ else:
|
||||||
|
+ other_dirs.append(cdir)
|
||||||
|
+
|
||||||
|
+ # Only limit if cpu_dirs specifically exceeds max
|
||||||
|
+ if len(cpu_dirs) > max_cpu_dirs:
|
||||||
|
+ self._log_info(
|
||||||
|
+ f"Limiting cpu directories from {len(cpu_dirs)} to "
|
||||||
|
+ f"{max_cpu_dirs} (use '-k processor.max_cpu_dirs=N' "
|
||||||
|
+ f"to change)."
|
||||||
|
+ )
|
||||||
|
+ cpu_dirs = sorted(cpu_dirs)[:max_cpu_dirs]
|
||||||
|
+
|
||||||
|
+ cdirs = other_dirs + cpu_dirs
|
||||||
|
+
|
||||||
|
self.add_copy_spec([
|
||||||
|
self.path_join('/sys/devices/system/cpu', cdir) for cdir in cdirs
|
||||||
|
])
|
||||||
|
--
|
||||||
|
2.55.0
|
||||||
|
|
||||||
@ -1,11 +1,11 @@
|
|||||||
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
|
%{!?python_sitelib: %define python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")}
|
||||||
|
|
||||||
%global auditversion 0.3
|
%global auditversion 0.3-1
|
||||||
|
|
||||||
Summary: A set of tools to gather troubleshooting information from a system
|
Summary: A set of tools to gather troubleshooting information from a system
|
||||||
Name: sos
|
Name: sos
|
||||||
Version: 4.8.1
|
Version: 4.11.2
|
||||||
Release: 1%{?dist}
|
Release: 4%{?dist}
|
||||||
Group: Applications/System
|
Group: Applications/System
|
||||||
Source0: https://github.com/sosreport/sos/archive/%{version}/sos-%{version}.tar.gz
|
Source0: https://github.com/sosreport/sos/archive/%{version}/sos-%{version}.tar.gz
|
||||||
Source1: sos-audit-%{auditversion}.tgz
|
Source1: sos-audit-%{auditversion}.tgz
|
||||||
@ -22,6 +22,14 @@ Recommends: python3-pexpect
|
|||||||
Recommends: python3-pyyaml
|
Recommends: python3-pyyaml
|
||||||
Conflicts: vdsm < 4.40
|
Conflicts: vdsm < 4.40
|
||||||
Obsoletes: sos-collector
|
Obsoletes: sos-collector
|
||||||
|
Patch1: 0001-python3-walrus-operator-and-rhel8-changes-only.patch
|
||||||
|
Patch2: 0002-remove-unsupported-python36-plugins.patch
|
||||||
|
Patch3: 0003-sosreport-binary.patch
|
||||||
|
Patch4: 0004-revert-PR4092-and-PR4275.patch
|
||||||
|
Patch5: 0005-foreman-installer-Scrub-secrets-in-CLI-arg-dumps.patch
|
||||||
|
Patch6: 0006-foremanctl-valkey-PR4376.patch
|
||||||
|
Patch7: 0007-policies-Prefer-most-specific-policy-when-multiple-m.patch
|
||||||
|
Patch8: 0008-processor-Limit-sys-devices-system-cpu-cpu-subdirs-c.patch
|
||||||
|
|
||||||
%description
|
%description
|
||||||
Sos is a set of tools that gathers information about system
|
Sos is a set of tools that gathers information about system
|
||||||
@ -32,6 +40,14 @@ support technicians and developers.
|
|||||||
%prep
|
%prep
|
||||||
%setup -qn %{name}-%{version}
|
%setup -qn %{name}-%{version}
|
||||||
%setup -T -D -a1 -q
|
%setup -T -D -a1 -q
|
||||||
|
%patch -P 1 -p1
|
||||||
|
%patch -P 2 -p1
|
||||||
|
%patch -P 3 -p1
|
||||||
|
%patch -P 4 -p1
|
||||||
|
%patch -P 5 -p1
|
||||||
|
%patch -P 6 -p1
|
||||||
|
%patch -P 7 -p1
|
||||||
|
%patch -P 8 -p1
|
||||||
|
|
||||||
%build
|
%build
|
||||||
%py3_build
|
%py3_build
|
||||||
@ -55,18 +71,17 @@ mkdir -p %{buildroot}%{_sysconfdir}/sos/{cleaner,presets.d,extras.d,groups.d}
|
|||||||
# internationalization is currently broken. Uncomment this line once fixed.
|
# internationalization is currently broken. Uncomment this line once fixed.
|
||||||
# %%files -f %%{name}.lang
|
# %%files -f %%{name}.lang
|
||||||
%files
|
%files
|
||||||
%{_sbindir}/sosreport
|
|
||||||
%{_sbindir}/sos
|
%{_sbindir}/sos
|
||||||
|
%{_sbindir}/sosreport
|
||||||
%{_sbindir}/sos-collector
|
%{_sbindir}/sos-collector
|
||||||
%dir /etc/sos/presets.d
|
%dir /etc/sos/presets.d
|
||||||
%dir /etc/sos/extras.d
|
%dir /etc/sos/extras.d
|
||||||
%dir /etc/sos/groups.d
|
%dir /etc/sos/groups.d
|
||||||
/etc/tmpfiles.d/%{name}.conf
|
/etc/tmpfiles.d/%{name}.conf
|
||||||
%{python3_sitelib}/*
|
%{python3_sitelib}/*
|
||||||
%{_mandir}/man1/sosreport.1.gz
|
|
||||||
%{_mandir}/man1/sos-clean.1.gz
|
%{_mandir}/man1/sos-clean.1.gz
|
||||||
|
%{_mandir}/man1/sos-upload.1.gz
|
||||||
%{_mandir}/man1/sos-collect.1.gz
|
%{_mandir}/man1/sos-collect.1.gz
|
||||||
%{_mandir}/man1/sos-collector.1.gz
|
|
||||||
%{_mandir}/man1/sos-help.1.gz
|
%{_mandir}/man1/sos-help.1.gz
|
||||||
%{_mandir}/man1/sos-mask.1.gz
|
%{_mandir}/man1/sos-mask.1.gz
|
||||||
%{_mandir}/man1/sos-report.1.gz
|
%{_mandir}/man1/sos-report.1.gz
|
||||||
@ -79,7 +94,7 @@ mkdir -p %{buildroot}%{_sysconfdir}/sos/{cleaner,presets.d,extras.d,groups.d}
|
|||||||
|
|
||||||
%package audit
|
%package audit
|
||||||
Summary: Audit use of some commands for support purposes
|
Summary: Audit use of some commands for support purposes
|
||||||
License: GPLv2+
|
License: GPL-2.0-or-later
|
||||||
Group: Application/System
|
Group: Application/System
|
||||||
|
|
||||||
%description audit
|
%description audit
|
||||||
@ -102,8 +117,66 @@ of the system. Currently storage and filesystem commands are audited.
|
|||||||
%{_mandir}/man8/sos-audit.sh.8.gz
|
%{_mandir}/man8/sos-audit.sh.8.gz
|
||||||
%ghost /etc/audit/rules.d/40-sos-filesystem.rules
|
%ghost /etc/audit/rules.d/40-sos-filesystem.rules
|
||||||
%ghost /etc/audit/rules.d/40-sos-storage.rules
|
%ghost /etc/audit/rules.d/40-sos-storage.rules
|
||||||
|
%license LICENSE
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Wed Aug 05 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-4
|
||||||
|
- Update to 4.11.2-4
|
||||||
|
|
||||||
|
* Fri Jul 17 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-2
|
||||||
|
- Update to 4.11.2-2
|
||||||
|
|
||||||
|
* Wed Jul 15 2026 Jan Jansky <jjansky@redhat.com> = 4.11.2-1
|
||||||
|
- Update to 4.11.2-1
|
||||||
|
|
||||||
|
* Thu Apr 02 2026 Jan Jansky <jjansky@redhat.com> = 4.11.0-1
|
||||||
|
- Update to 4.11.0-1
|
||||||
|
Resolves: RHEL-157813
|
||||||
|
|
||||||
|
* Thu Feb 26 2026 Jan Jansky <jjansky@redhat.com> = 4.10.2-2
|
||||||
|
- Update to 4.10.2-2
|
||||||
|
Resolves: RHEL-142630
|
||||||
|
|
||||||
|
* Thu Jan 22 2026 Jan Jansky <jjansky@redhat.com> = 4.10.2-1
|
||||||
|
- Update to 4.10.2-1
|
||||||
|
Resolves: RHEL-142630
|
||||||
|
|
||||||
|
* Fri Dec 05 2025 Jan Jansky <jjansky@redhat.com> = 4.10.1-2
|
||||||
|
- Fixing sosreport and sos-collector binary
|
||||||
|
Resolves: RHEL-121468
|
||||||
|
|
||||||
|
* Tue Nov 25 2025 Jan Jansky <jjansky@redhat.com> = 4.10.1-1
|
||||||
|
- Update to 4.10.1-1
|
||||||
|
Resolves: RHEL-121468
|
||||||
|
|
||||||
|
* Tue Sep 23 2025 Jan Jansky <jjansky@redhat.com> = 4.10.0-4
|
||||||
|
- Update to 4.10.0-4
|
||||||
|
Resolves: RHEL-112413
|
||||||
|
|
||||||
|
* Wed Sep 17 2025 Jan Jansky <jjansky@redhat.com> = 4.10.0-2
|
||||||
|
- Update to 4.10.0-2
|
||||||
|
Resolves: RHEL-112413
|
||||||
|
|
||||||
|
* Thu Aug 21 2025 Jan Jansky <jjansky@redhat.com> = 4.10.0-1
|
||||||
|
- Update to 4.10.0
|
||||||
|
Resolves: RHEL-110499
|
||||||
|
|
||||||
|
* Fri Jul 04 2025 Jan Jansky <jjansky@redhat.com> = 4.9.2-1
|
||||||
|
- Update to 4.9.2 in RHEL 8
|
||||||
|
Resolves: RHEL-101716
|
||||||
|
|
||||||
|
* Fri May 30 2025 Jan Jansky <jjansky@redhat.com> = 4.9.1-2
|
||||||
|
- Update to 4.9.1-2 in RHEL 8
|
||||||
|
Resolves: RHEL-86645
|
||||||
|
|
||||||
|
* Tue Apr 15 2025 Jan Jansky <jjansky@redhat.com> = 4.9.1-1
|
||||||
|
- Update to 4.9.1 in RHEL 8
|
||||||
|
Resolves: RHEL-86645
|
||||||
|
|
||||||
|
* Tue Jan 07 2025 Jan Jansky <jjansky@redhat.com> = 4.8.2-1
|
||||||
|
- Update to 4.8.2 in RHEL 8
|
||||||
|
Resolves: RHEL-72941
|
||||||
|
|
||||||
* Wed Oct 23 2024 Jan Jansky <jjansky@redhat.com> = 4.8.1-1
|
* Wed Oct 23 2024 Jan Jansky <jjansky@redhat.com> = 4.8.1-1
|
||||||
- Update to 4.8.1 in RHEL 8
|
- Update to 4.8.1 in RHEL 8
|
||||||
Resolves: RHEL-64160
|
Resolves: RHEL-64160
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user