diff options
author | Jake Hunsaker <jhunsake@redhat.com> | 2020-10-12 12:33:30 -0400 |
---|---|---|
committer | Jake Hunsaker <jhunsake@redhat.com> | 2020-11-03 13:40:18 -0500 |
commit | 55ca9a849121b9058f8e0768eb4d4bef84db49ab (patch) | |
tree | 5951b559a6bc3acf88edd860bb9d32bd1740e52b | |
parent | a5162c73ddd948085ca99fba81353104c54623de (diff) | |
download | sos-55ca9a849121b9058f8e0768eb4d4bef84db49ab.tar.gz |
[report] Allow users to specify commands and files to skip
Adds two new options, `--skip-commands` and `--skip-files`, that allow
users to selectively skip specific command or file collection instead of
having to disable whole plugins to skip those collections.
These options are also exposed via `sos collect`, being gated by a
version of 4.1 since that is the next scheduled release where we can
guarantee this functionality will be present.
Closes: #2203
Resolves: #2271
Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
-rw-r--r-- | man/en/sos-collect.1 | 14 | ||||
-rw-r--r-- | man/en/sos-report.1 | 14 | ||||
-rw-r--r-- | sos/collector/__init__.py | 8 | ||||
-rw-r--r-- | sos/collector/sosnode.py | 10 | ||||
-rw-r--r-- | sos/report/__init__.py | 8 | ||||
-rw-r--r-- | sos/report/plugins/__init__.py | 27 | ||||
-rw-r--r-- | tests/option_tests.py | 2 | ||||
-rw-r--r-- | tests/plugin_tests.py | 2 |
8 files changed, 85 insertions, 0 deletions
diff --git a/man/en/sos-collect.1 b/man/en/sos-collect.1 index 7d6f8b87..d4e5e648 100644 --- a/man/en/sos-collect.1 +++ b/man/en/sos-collect.1 @@ -30,6 +30,8 @@ sos collect \- Collect sosreports from multiple (cluster) nodes [\-\-password] [\-\-password\-per\-node] [\-\-preset PRESET] + [\-\-skip-commands COMMANDS] + [\-\-skip-files FILES] [\-s|\-\-sysroot SYSROOT] [\-\-ssh\-user SSH_USER] [\-\-sos-cmd SOS_CMD] @@ -261,6 +263,18 @@ defined, or has a version of sos prior to 3.6, this option is ignored for that n \fB\-p\fR SSH_PORT, \fB\-\-ssh\-port\fR SSH_PORT Specify SSH port for all nodes. Use this if SSH runs on any port other than 22. .TP +\fB\-\-skip-commands\fR COMMANDS +A comma delimited list of commands to skip execution of, but still allowing the +rest of the plugin that calls the command to run. This will generally need to +be some form of UNIX shell-style wildcard matching. For example, using a value +of \fBhostname\fR will skip only that single command, while using \fBhostname*\fR +will skip all commands with names that begin with the string "hostname". +.TP +\fB\-\-skip-files\fR FILES +A comma delimited list of files or filepath wildcard matches to skip collection +of. Values may either be exact filepaths or paths using UNIX shell-style wildcards, +for example \fB/etc/sos/*\fR. +.TP \fB\-\-ssh\-user\fR SSH_USER Specify an SSH user for sos collect to connect to nodes with. Default is root. diff --git a/man/en/sos-report.1 b/man/en/sos-report.1 index 0a571d18..19fb6aae 100644 --- a/man/en/sos-report.1 +++ b/man/en/sos-report.1 @@ -26,6 +26,8 @@ sosreport \- Collect and package diagnostic and support data [--log-size]\fR [--all-logs]\fR [--since YYYYMMDD[HHMMSS]]\fR + [--skip-commands commands]\fR + [--skip-files files]\fR [--allow-system-changes]\fR [-z|--compression-type method]\fR [--encrypt-key KEY]\fR @@ -180,6 +182,18 @@ compression-type file extension for example ".zip". ".1", ".gz" etc.). This also affects \--all-logs. The date string will be padded with zeros if HHMMSS is not specified. .TP +.B \--skip-commands COMMANDS +A comma delimited list of commands to skip execution of, but still allowing the +rest of the plugin that calls the command to run. This will generally need to +be some form of UNIX shell-style wildcard matching. For example, using a value +of \fBhostname\fR will skip only that single command, while using \fBhostname*\fR +will skip all commands with names that begin with the string "hostname". +.TP +.B \--skip-files FILES +A comma delimited list of files or filepath wildcard matches to skip collection +of. Values may either be exact filepaths or paths using UNIX shell-style wildcards, +for example \fB/etc/sos/*\fR. +.TP .B \--allow-system-changes Run commands even if they can change the system (e.g. load kernel modules). .TP diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py index 3390e0b0..1abb08ae 100644 --- a/sos/collector/__init__.py +++ b/sos/collector/__init__.py @@ -84,6 +84,8 @@ class SoSCollector(SoSComponent): 'preset': '', 'save_group': '', 'since': '', + 'skip_cmds': [], + 'skip_files': [], 'skip_plugins': [], 'sos_opt_line': '', 'ssh_key': '', @@ -277,6 +279,12 @@ class SoSCollector(SoSComponent): help=('Escapes archived files older than date. ' 'This will also affect --all-logs. ' 'Format: YYYYMMDD[HHMMSS]')) + sos_grp.add_argument('--skip-commands', default=[], action='extend', + dest='skip_cmds', + help="do not execute these commands") + sos_grp.add_argument('--skip-files', default=[], action='extend', + dest='skip_files', + help="do not collect these files") sos_grp.add_argument('--verify', action="store_true", help='perform pkg verification during collection') diff --git a/sos/collector/sosnode.py b/sos/collector/sosnode.py index d0e836a8..75daef22 100644 --- a/sos/collector/sosnode.py +++ b/sos/collector/sosnode.py @@ -651,6 +651,16 @@ class SosNode(): if self.check_sos_version('4.0'): self.sos_bin = 'sos report' + if self.check_sos_version('4.1'): + if self.opts.skip_cmds: + sos_opts.append( + '--skip-commands=%s' % (quote(self.opts.skip_cmds)) + ) + if self.opts.skip_files: + sos_opts.append( + '--skip-files=%s' % (quote(self.opts.skip_files)) + ) + sos_cmd = sos_cmd.replace( 'sosreport', os.path.join(self.host.sos_bin_path, self.sos_bin) diff --git a/sos/report/__init__.py b/sos/report/__init__.py index a938f706..7838d60a 100644 --- a/sos/report/__init__.py +++ b/sos/report/__init__.py @@ -94,6 +94,8 @@ class SoSReport(SoSComponent): 'list_profiles': False, 'log_size': 25, 'map_file': '/etc/sos/cleaner/default_mapping', + 'skip_cmds': [], + 'skip_files': [], 'skip_plugins': [], 'noreport': False, 'no_env_vars': False, @@ -258,6 +260,12 @@ class SoSReport(SoSComponent): dest="profiles", type=str, default=[], help="enable plugins used by the given " "profiles") + report_grp.add_argument('--skip-commands', default=[], action='extend', + dest='skip_cmds', + help="do not execute these commands") + report_grp.add_argument('--skip-files', default=[], action='extend', + dest='skip_files', + help="do not collect these files") report_grp.add_argument("--verify", action="store_true", dest="verify", default=False, help="perform data verification during " diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py index 4e1a263d..ed0a07ef 100644 --- a/sos/report/plugins/__init__.py +++ b/sos/report/plugins/__init__.py @@ -495,6 +495,8 @@ class Plugin(object): self.policy = commons['policy'] self.devices = commons['devices'] self.manifest = None + self.skip_files = commons['cmdlineopts'].skip_files + self.skip_cmds = commons['cmdlineopts'].skip_cmds self.soslog = self.commons['soslog'] if 'soslog' in self.commons \ else logging.getLogger('sos') @@ -1080,6 +1082,20 @@ class Plugin(object): def _is_forbidden_path(self, path): return _path_in_path_list(path, self.forbidden_paths) + def _is_skipped_path(self, path): + """Check if the given path matches a user-provided specification to + ignore collection of via the ``--skip-files`` option + + :param path: The filepath being collected + :type path: ``str`` + + :returns: ``True`` if file should be skipped, else ``False`` + """ + for _skip_path in self.skip_files: + if fnmatch.fnmatch(path, _skip_path): + return True + return False + def _copy_node(self, path, st): dev_maj = os.major(st.st_rdev) dev_min = os.minor(st.st_rdev) @@ -1425,6 +1441,9 @@ class Plugin(object): if self._is_forbidden_path(_file): self._log_debug("skipping forbidden path '%s'" % _file) continue + if self._is_skipped_path(_file): + self._log_debug("skipping excluded path '%s'" % _file) + continue if limit_reached: self._log_info("skipping '%s' over size limit" % _file) continue @@ -1577,6 +1596,14 @@ class Plugin(object): pred = kwargs.pop('pred') if 'pred' in kwargs else None soscmd = SoSCommand(**kwargs) self._log_debug("packed command: " + soscmd.__str__()) + for _skip_cmd in self.skip_cmds: + # This probably seems weird to be doing filename matching on the + # commands, however we want to remain consistent with our regex + # matching with file paths, which sysadmins are almost guaranteed + # to assume will use shell-style unix matching + if fnmatch.fnmatch(soscmd.cmd, _skip_cmd): + self._log_debug("skipping excluded command '%s'" % soscmd.cmd) + return if self.test_predicate(cmd=True, pred=pred): self.collect_cmds.append(soscmd) self._log_info("added cmd output '%s'" % soscmd.cmd) diff --git a/tests/option_tests.py b/tests/option_tests.py index 56480a58..44e2079f 100644 --- a/tests/option_tests.py +++ b/tests/option_tests.py @@ -16,6 +16,8 @@ class MockOptions(object): dry_run = False log_size = 25 allow_system_changes = False + skip_cmds = [] + skip_files = [] class GlobalOptionTest(unittest.TestCase): diff --git a/tests/plugin_tests.py b/tests/plugin_tests.py index 9290003a..0acf07f4 100644 --- a/tests/plugin_tests.py +++ b/tests/plugin_tests.py @@ -114,6 +114,8 @@ class MockOptions(object): log_size = 25 allow_system_changes = False no_postproc = False + skip_files = [] + skip_cmds = [] class PluginToolTests(unittest.TestCase): |