From 118087f8bd5e8b29c0688c6de5cdd5796aac97b3 Mon Sep 17 00:00:00 2001 From: Trevor Benson Date: Sat, 24 Feb 2024 23:38:50 -0800 Subject: [PATCH] Fifth pass, restore oc.py from f-string leakage and manual conversions Signed-off-by: Trevor Benson --- bin/sos-collector | 2 +- bin/sosreport | 2 +- plugins_overview.py | 37 ++- sos/archive.py | 95 +++--- sos/cleaner/__init__.py | 102 +++--- sos/cleaner/archives/__init__.py | 12 +- sos/cleaner/mappings/ip_map.py | 2 +- sos/cleaner/mappings/mac_map.py | 12 +- sos/collector/__init__.py | 123 ++++---- sos/collector/clusters/ocp.py | 24 +- sos/collector/clusters/ovirt.py | 15 +- sos/collector/clusters/pacemaker.py | 10 +- sos/collector/clusters/satellite.py | 5 +- sos/collector/exceptions.py | 13 +- sos/collector/sosnode.py | 105 +++---- sos/collector/transports/__init__.py | 43 ++- sos/collector/transports/control_persist.py | 25 +- sos/collector/transports/oc.py | 111 ++++--- sos/component.py | 6 +- sos/help/__init__.py | 19 +- sos/options.py | 17 +- sos/policies/__init__.py | 8 +- sos/policies/auth/__init__.py | 11 +- sos/policies/distros/__init__.py | 2 +- sos/policies/distros/redhat.py | 4 +- sos/policies/runtimes/crio.py | 14 +- sos/presets/__init__.py | 14 +- sos/report/__init__.py | 171 ++++------ sos/report/plugins/__init__.py | 291 ++++++++---------- sos/report/plugins/abrt.py | 5 +- sos/report/plugins/alternatives.py | 9 +- sos/report/plugins/azure.py | 8 +- sos/report/plugins/buildah.py | 12 +- sos/report/plugins/candlepin.py | 8 +- .../plugins/canonical_livepatch_onprem.py | 2 +- sos/report/plugins/ceph_common.py | 6 +- sos/report/plugins/ceph_mds.py | 13 +- sos/report/plugins/collectd.py | 7 +- sos/report/plugins/console.py | 6 +- sos/report/plugins/containers_common.py | 11 +- sos/report/plugins/crio.py | 16 +- sos/report/plugins/crypto.py | 18 +- sos/report/plugins/cs.py | 16 +- sos/report/plugins/dnf.py | 6 +- sos/report/plugins/docker.py | 26 +- sos/report/plugins/ebpf.py | 5 +- sos/report/plugins/elastic.py | 20 +- sos/report/plugins/fibrechannel.py | 12 +- sos/report/plugins/filesys.py | 22 +- sos/report/plugins/foreman.py | 50 ++- sos/report/plugins/foreman_installer.py | 4 +- sos/report/plugins/gluster.py | 28 +- sos/report/plugins/grafana.py | 2 +- sos/report/plugins/haproxy.py | 16 +- sos/report/plugins/hpssm.py | 20 +- sos/report/plugins/ipa.py | 30 +- sos/report/plugins/ipmitool.py | 30 +- sos/report/plugins/iprconfig.py | 2 +- sos/report/plugins/iscsi.py | 14 +- sos/report/plugins/juju.py | 2 +- sos/report/plugins/kubernetes.py | 6 +- sos/report/plugins/libraries.py | 6 +- sos/report/plugins/logrotate.py | 6 +- sos/report/plugins/lstopo.py | 12 +- sos/report/plugins/lustre.py | 8 +- sos/report/plugins/lvm2.py | 21 +- sos/report/plugins/maas.py | 7 +- sos/report/plugins/megacli.py | 4 +- sos/report/plugins/microshift.py | 14 +- sos/report/plugins/mssql.py | 6 +- sos/report/plugins/networking.py | 55 ++-- sos/report/plugins/networkmanager.py | 13 +- sos/report/plugins/omnipath_client.py | 5 +- sos/report/plugins/openshift.py | 31 +- sos/report/plugins/openssl.py | 2 +- sos/report/plugins/openstack_aodh.py | 6 +- sos/report/plugins/openstack_barbican.py | 6 +- sos/report/plugins/openstack_ceilometer.py | 6 +- sos/report/plugins/openstack_cinder.py | 34 +- sos/report/plugins/openstack_designate.py | 11 +- sos/report/plugins/openstack_glance.py | 15 +- sos/report/plugins/openstack_heat.py | 12 +- sos/report/plugins/openstack_horizon.py | 3 +- sos/report/plugins/openstack_instack.py | 18 +- sos/report/plugins/openstack_ironic.py | 20 +- sos/report/plugins/openstack_keystone.py | 11 +- sos/report/plugins/openstack_manila.py | 16 +- sos/report/plugins/openstack_masakari.py | 7 +- .../plugins/openstack_masakarimonitors.py | 3 +- sos/report/plugins/openstack_neutron.py | 7 +- sos/report/plugins/openstack_nova.py | 20 +- sos/report/plugins/openstack_octavia.py | 21 +- sos/report/plugins/openstack_placement.py | 10 +- sos/report/plugins/openstack_sahara.py | 7 +- sos/report/plugins/openstack_swift.py | 7 +- sos/report/plugins/openstack_trove.py | 7 +- sos/report/plugins/openvswitch.py | 3 + sos/report/plugins/origin.py | 22 +- sos/report/plugins/ovirt.py | 22 +- sos/report/plugins/ovirt_engine_backup.py | 7 +- sos/report/plugins/ovirt_node.py | 6 +- sos/report/plugins/ovn_central.py | 4 +- sos/report/plugins/pacemaker.py | 9 +- sos/report/plugins/perccli.py | 6 +- sos/report/plugins/podman.py | 40 +-- sos/report/plugins/postgresql.py | 16 +- sos/report/plugins/powerpc.py | 2 +- sos/report/plugins/process.py | 7 +- sos/report/plugins/pulp.py | 24 +- sos/report/plugins/pulpcore.py | 27 +- sos/report/plugins/puppet.py | 2 +- sos/report/plugins/python.py | 5 +- sos/report/plugins/qaucli.py | 9 +- sos/report/plugins/qpid.py | 6 +- sos/report/plugins/qpid_dispatch.py | 5 +- sos/report/plugins/redis.py | 12 +- sos/report/plugins/rhui.py | 2 +- sos/report/plugins/rpm.py | 4 +- sos/report/plugins/saphana.py | 40 +-- sos/report/plugins/sapnw.py | 18 +- sos/report/plugins/sar.py | 5 +- sos/report/plugins/seagate_ses.py | 5 +- sos/report/plugins/shmcli.py | 11 +- sos/report/plugins/slurm.py | 3 +- sos/report/plugins/smclient.py | 3 +- sos/report/plugins/sos_extras.py | 9 +- sos/report/plugins/subscription_manager.py | 28 +- sos/report/plugins/tomcat.py | 3 +- sos/report/plugins/ubuntu.py | 6 +- sos/report/plugins/ultrapath.py | 5 +- sos/report/plugins/vdsm.py | 10 +- sos/report/plugins/vectordev.py | 3 +- sos/report/plugins/virsh.py | 18 +- sos/report/plugins/vmware.py | 5 +- sos/report/plugins/zvm.py | 9 +- sos/utilities.py | 9 +- 136 files changed, 1157 insertions(+), 1437 deletions(-) diff --git a/bin/sos-collector b/bin/sos-collector index df2c9774a2..43df4388d8 100755 --- a/bin/sos-collector +++ b/bin/sos-collector @@ -24,7 +24,7 @@ except KeyboardInterrupt: if __name__ == '__main__': msg = ("Please note the 'sos-collector' command has been deprecated in " " favor of the new 'sos' command, E.G. 'sos collect'.\n" - "Redirecting to 'sos collect %s'" % (' '.join(sys.argv[1:]) or '')) + f"Redirecting to 'sos collect {' '.join(sys.argv[1:]) or ''}'") print(msg) time.sleep(0.5) args = sys.argv[1:] diff --git a/bin/sosreport b/bin/sosreport index a298d6362b..c683c3115e 100755 --- a/bin/sosreport +++ b/bin/sosreport @@ -24,7 +24,7 @@ except KeyboardInterrupt: if __name__ == '__main__': msg = ("Please note the 'sosreport' command has been deprecated in favor " "of the new 'sos' command, E.G. 'sos report'.\n" - "Redirecting to 'sos report %s'" % (' '.join(sys.argv[1:]) or '')) + f"Redirecting to 'sos report {' '.join(sys.argv[1:]) or ''}'") print(msg) time.sleep(0.5) args = sys.argv[1:] diff --git a/plugins_overview.py b/plugins_overview.py index 46bcbf5a8c..c6a6e41ef8 100644 --- a/plugins_overview.py +++ b/plugins_overview.py @@ -8,7 +8,7 @@ # - list of paths it forbits to collect (add_forbidden_path) # - list of commands it calls (add_cmd_output) # -# Output of the script: +# Output of the script: # - a JSON object with plugins in keys # - or CSV format in case "csv" cmdline is provided # @@ -29,9 +29,11 @@ plugs_data = {} # the map of all plugins data to collect plugcontent = '' # content of plugin file just being processed + # method to parse an item of a_s_c/a_c_o/.. methods # we work on an assumption the item is a string quoted by \" or optionally -# by \'. If we detect at least 2 such chars in the item, take what is between those. +# by \'. If we detect at least 2 such chars in the item, take what is between +# those. def add_valid_item(dest, item): for qoutemark in "\"\'": split = item.split(qoutemark) @@ -39,13 +41,14 @@ def add_valid_item(dest, item): dest.append(split[1]) return -# method to find in `plugcontent` all items of given method (a_c_s/a_c_o/..) split -# by comma; add each valid item to the `dest` list + +# method to find in `plugcontent` all items of given method (a_c_s/a_c_o/..) +# split by comma; add each valid item to the `dest` list def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): - regexp = "%s%s(.*?)%s" % (method, wrapopen, wrapclose) + regexp = f"{method}{wrapopen}(.*?){wrapclose}" for match in re.findall(regexp, plugcontent, flags=re.MULTILINE|re.DOTALL): # tuple of distros ended by either (class|from|import) - if isinstance(match,tuple): + if isinstance(match, tuple): for item in list(match): if item not in ['class', 'from', 'import']: for it in item.split(','): @@ -63,7 +66,8 @@ def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): else: add_valid_item(dest, match) -# main body: traverse report's plugins directory and for each plugin, grep for + +# main body: traverse report's plugins directory and for each plugin, grep for # add_copy_spec / add_forbidden_path / add_cmd_output there for plugfile in sorted(os.listdir(PLUGDIR)): # ignore non-py files and __init__.py @@ -73,7 +77,8 @@ def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): # if plugname != 'bcache': # continue plugs_data[plugname] = { - 'sourcecode': 'https://github.com/sosreport/sos/blob/main/sos/report/plugins/%s.py' % plugname, + 'sourcecode': 'https://github.com/sosreport/sos/blob/' + f'main/sos/report/plugins/{plugname}.py', 'distros': [], 'profiles': [], 'packages': [], @@ -84,8 +89,13 @@ def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): 'journals': [], 'env': [], } - plugcontent = open(os.path.join(PLUGDIR, plugfile)).read().replace('\n','') - add_all_items("from sos.report.plugins import ", plugs_data[plugname]['distros'], wrapopen='', wrapclose='(class|from|import)') + plugcontent = open(os.path.join(PLUGDIR, plugfile)).read().replace('\n', '') + add_all_items( + "from sos.report.plugins import ", + plugs_data[plugname]['distros'], + wrapopen='', + wrapclose='(class|from|import)' + ) add_all_items("profiles = ", plugs_data[plugname]['profiles'], wrapopen='') add_all_items("packages = ", plugs_data[plugname]['packages'], wrapopen='') add_all_items("add_copy_spec", plugs_data[plugname]['copyspecs']) @@ -98,7 +108,8 @@ def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): # print output; if "csv" is cmdline argument, print in CSV format, else JSON if (len(sys.argv) > 1) and (sys.argv[1] == "csv"): - print("plugin;url;distros;profiles;packages;copyspecs;forbidden;commands;service_status;journals;env_vars") + print("plugin;url;distros;profiles;packages;copyspecs;forbidden;commands;" + "service_status;journals;env_vars") for plugname in plugs_data.keys(): plugin = plugs_data[plugname] # determine max number of lines - usually "max(len(copyspec),len(commands))" @@ -109,10 +120,10 @@ def add_all_items(method, dest, wrapopen='\(', wrapclose='\)'): for key in plugkeys: maxline = max(maxline, len(plugin[key])) for line in range(maxline): - out = ";" if line>0 else ("%s;%s" % (plugname, plugin['sourcecode'])) + out = ";" if line > 0 else f"{plugname};{plugin['sourcecode']}" for key in plugkeys: out += ";" - if line '{target}'" - ) + self.log_debug("Making symlink " + f"'{abs_path}' -> '{target}'") os.symlink(target, abs_path) else: self.log_debug(f"Making directory {abs_path}") @@ -298,9 +296,8 @@ def check_path(self, src, path_type, dest=None, force=False): # Check containing directory presence and path type if os.path.exists(dest_dir) and not os.path.isdir(dest_dir): - raise ValueError( - f"path '{dest_dir}' exists and is not a directory" - ) + raise ValueError(f"path '{dest_dir}' exists and is not a " + "directory") if not os.path.exists(dest_dir): src_dir = src if path_type == P_DIR else os.path.split(src)[0] self._make_leading_paths(src_dir) @@ -320,15 +317,23 @@ def is_special(mode): if os.path.exists(dest): # Use lstat: we care about the current object, not the referent. st = os.lstat(dest) - ve_msg = "path '%s' exists and is not a %s" + ve_msg = "path '{path}' exists and is not a {path_type}" if path_type == P_FILE and not stat.S_ISREG(st.st_mode): - raise ValueError(ve_msg % (dest, "regular file")) + raise ValueError( + f"{ve_msg.format(path=dest, path_type='regular file')}" + ) if path_type == P_LINK and not stat.S_ISLNK(st.st_mode): - raise ValueError(ve_msg % (dest, "symbolic link")) + raise ValueError( + f"{ve_msg.format(path=dest, path_type='symbolic link')}" + ) if path_type == P_NODE and not is_special(st.st_mode): - raise ValueError(ve_msg % (dest, "special file")) + raise ValueError( + f"{ve_msg.format(path=dest, path_type='special file')}" + ) if path_type == P_DIR and not stat.S_ISDIR(st.st_mode): - raise ValueError(ve_msg % (dest, "directory")) + raise ValueError( + f"{ve_msg.format(path=dest, path_type='directory')}" + ) # Path has already been copied: skip return None return dest @@ -379,9 +384,8 @@ def add_file(self, src, dest=None, force=False): f.write(line) file_name = "open file" - self.log_debug( - f"added {file_name} to FileCacheArchive '{self._archive_root}'" - ) + self.log_debug(f"added {file_name} to FileCacheArchive " + f"'{self._archive_root}'") def add_string(self, content, dest, mode='w'): with self._path_lock: @@ -399,10 +403,8 @@ def add_string(self, content, dest, mode='w'): f.write(content) if os.path.exists(src): self._copy_attributes(src, dest) - self.log_debug( - f"added string at '{src}' to FileCacheArchive" - f" '{self._archive_root}'" - ) + self.log_debug(f"added string at '{src}' to FileCacheArchive" + f" '{self._archive_root}'") def add_binary(self, content, dest): with self._path_lock: @@ -412,10 +414,8 @@ def add_binary(self, content, dest): with codecs.open(dest, 'wb', encoding=None) as f: f.write(content) - self.log_debug( - f"added binary content at '{dest}' to archive" - f" '{self._archive_root}'" - ) + self.log_debug(f"added binary content at '{dest}' to archive" + f" '{self._archive_root}'") def add_link(self, source, link_name): self.log_debug(f"adding symlink at '{link_name}' -> '{source}'") @@ -426,10 +426,8 @@ def add_link(self, source, link_name): if not os.path.lexists(dest): os.symlink(source, dest) - self.log_debug( - f"added symlink at '{dest}' to '{source}' in archive" - f" '{self._archive_root}'" - ) + self.log_debug(f"added symlink at '{dest}' to '{source}' in " + f"archive '{self._archive_root}'") # Follow-up must be outside the path lock: we recurse into # other monitor methods that will attempt to reacquire it. @@ -476,13 +474,11 @@ def is_loop(link_name, source): source = os.path.join(dest_dir, os.readlink(host_path_name)) source = os.path.relpath(source, dest_dir) if is_loop(link_name, source): - self.log_debug( - f"Link '{link_name}' - '{source}' loops: skipping..." - ) + self.log_debug(f"Link '{link_name}' - '{source}' loops: " + "skipping...") return - self.log_debug( - f"Adding link {link_name} -> {source} for link follow up" - ) + self.log_debug(f"Adding link {link_name} -> {source} for " + "link follow up") self.add_link(source, link_name) elif os.path.isdir(host_path_name): self.log_debug(f"Adding dir {source} for link follow up") @@ -491,9 +487,8 @@ def is_loop(link_name, source): self.log_debug(f"Adding file {source} for link follow up") self.add_file(host_path_name) else: - self.log_debug( - f"No link follow up: source={source} link_name={link_name}" - ) + self.log_debug(f"No link follow up: source={source} " + f"link_name={link_name}") def add_dir(self, path): """Create a directory in the archive. @@ -539,10 +534,8 @@ def makedirs(self, path, mode=0o700): Used by sos.sosreport to set up sos_* directories. """ os.makedirs(os.path.join(self._archive_root, path), mode=mode) - self.log_debug( - f"created directory at '{path}' in FileCacheArchive" - f" '{self._archive_root}'" - ) + self.log_debug(f"created directory at '{path}' in FileCacheArchive" + f" '{self._archive_root}'") def open_file(self, path): path = self.dest_path(path) @@ -624,8 +617,10 @@ def finalize(self, method): return self.name() self.cleanup() - self.log_info("built archive at '%s' (size=%d)" % (self._archive_name, - os.stat(self._archive_name).st_size)) + self.log_info( + f"built archive at '{self._archive_name}'" + f" (size={os.stat(self._archive_name).st_size})" + ) if self.enc_opts['encrypt']: try: @@ -661,10 +656,11 @@ def _encrypt(self, archive): if self.enc_opts["password"]: # prevent change of gpg options using a long password, but also # prevent the addition of quote characters to the passphrase - passwd = "%s" % self.enc_opts["password"].replace('\'"', '') + replaced_password = self.enc_opts['password'].replace('\'\"', '') + passwd = f"{replaced_password}" env = {"sos_gpg": passwd} enc_cmd += "-c --passphrase-fd 0 " - enc_cmd = "/bin/bash -c \"echo $sos_gpg | %s\"" % enc_cmd + enc_cmd = f"/bin/bash -c \"echo $sos_gpg | {enc_cmd}\"" enc_cmd += archive r = sos_get_command_output(enc_cmd, timeout=0, env=env) if r["status"] == 0: @@ -753,11 +749,8 @@ def _build_archive(self, method): kwargs = {'compresslevel': 6} else: kwargs = {'preset': 3} - tar = tarfile.open( - self._archive_name, - mode=f"w:{_comp_mode}", - **kwargs - ) + tar = tarfile.open(self._archive_name, + mode=f"w:{_comp_mode}", **kwargs) # add commonly reviewed files first, so that they can be more easily # read from memory without needing to extract the whole archive for _content in ['version.txt', 'sos_reports', 'sos_logs']: diff --git a/sos/cleaner/__init__.py b/sos/cleaner/__init__.py index fdaf3e38bb..0e73161a7c 100644 --- a/sos/cleaner/__init__.py +++ b/sos/cleaner/__init__.py @@ -140,9 +140,9 @@ def __init__(self, parser=None, args=None, cmdline=None, in_place=False, if _parser.lower().strip() == _loaded_name: self.log_info(f"Disabling parser: {_loaded_name}") self.ui_log.warning( - "Disabling the '%s' parser. Be aware that this may " - "leave sensitive plain-text data in the archive." - % _parser + f"Disabling the '{_parser}' parser. Be aware that " + "this may leave sensitive plain-text data in the " + "archive." ) self.parsers.remove(_loaded) @@ -195,14 +195,13 @@ def load_map_file(self): _conf = {} default_map = '/etc/sos/cleaner/default_mapping' if os.path.isdir(self.opts.map_file): - raise Exception( - f"Requested map file {self.opts.map_file} is a directory" - ) + raise Exception(f"Requested map file {self.opts.map_file} is a " + "directory") if not os.path.exists(self.opts.map_file): if self.opts.map_file != default_map: self.log_error( - "ERROR: map file %s does not exist, will not load any " - "obfuscation matches" % self.opts.map_file) + f"ERROR: map file {self.opts.map_file} does not exist," + " will not load any obfuscation matches") else: with open(self.opts.map_file, 'r') as mf: try: @@ -211,9 +210,8 @@ def load_map_file(self): self.log_error("ERROR: Unable to parse map file, json is " "malformed. Will not load any mappings.") except Exception as err: - self.log_error( - f"ERROR: Could not load '{self.opts.map_file}': {err}" - ) + self.log_error("ERROR: Could not load " + f"'{self.opts.map_file}': {err}") return _conf def print_disclaimer(self): @@ -234,7 +232,7 @@ def print_disclaimer(self): by this utility for remaining sensitive content before being passed to a \ third party. """) - self.ui_log.info("\nsos clean (version %s)\n" % __version__) + self.ui_log.info(f"\nsos clean (version {__version__})\n") self.ui_log.info(msg) if not self.opts.batch: try: @@ -354,9 +352,8 @@ def execute(self): self.print_disclaimer() self.report_paths = [] if not os.path.exists(self.opts.target): - self.ui_log.error( - f"Invalid target: no such file or directory {self.opts.target}" - ) + self.ui_log.error("Invalid target: no such file or directory " + f"{self.opts.target}") self._exit(1) self.inspect_target_archive() @@ -382,8 +379,8 @@ def execute(self): self.ui_log.info("No reports obfuscated, aborting...\n") self._exit(1) - self.ui_log.info("\nSuccessfully obfuscated %s report(s)\n" - % len(self.completed_reports)) + self.ui_log.info("\nSuccessfully obfuscated" + f" {len(self.completed_reports)} report(s)\n") _map = self.compile_mapping_dict() map_path = self.write_map_for_archive(_map) @@ -482,9 +479,8 @@ def write_map_to_file(self, _map, path): def write_map_for_archive(self, _map): try: map_path = os.path.join( - self.sys_tmp, self.obfuscate_string( - f"{self.arc_name}-private_map" - ) + self.sys_tmp, + self.obfuscate_string(f"{self.arc_name}-private_map") ) return self.write_map_to_file(_map, map_path) except Exception as err: @@ -551,8 +547,8 @@ def obfuscate_report_paths(self): """ try: msg = ( - "Found %s total reports to obfuscate, processing up to %s " - "concurrently\n" % (len(self.report_paths), self.opts.jobs) + f"Found {len(self.report_paths)} total reports to obfuscate," + f" processing up to {self.opts.jobs} concurrently\n" ) self.ui_log.info(msg) if self.opts.keep_binary_files: @@ -696,18 +692,14 @@ def obfuscate_report(self, archive): try: self.obfuscate_directory_names(archive) except Exception as err: - self.log_info( - f"Failed to obfuscate directories: {err}", - caller=archive.archive_name, - ) + self.log_info(f"Failed to obfuscate directories: {err}", + caller=archive.archive_name) try: self.obfuscate_symlinks(archive) except Exception as err: - self.log_info( - f"Failed to obfuscate symlinks: {err}", - caller=archive.archive_name, - ) + self.log_info(f"Failed to obfuscate symlinks: {err}", + caller=archive.archive_name) # if the archive was already a tarball, repack it if not archive.is_nested: @@ -720,13 +712,10 @@ def obfuscate_report(self, archive): ) archive.compress(method) except Exception as err: - self.log_debug( - f"Archive {archive.archive_name} failed to" - f" compress: {err}" - ) - archive.report_msg( - f"Failed to re-compress archive: {err}" - ) + self.log_debug(f"Archive {archive.archive_name} " + f"failed to compress: {err}") + archive.report_msg("Failed to re-compress archive: " + f"{err}") return self.completed_reports.append(archive) @@ -737,14 +726,13 @@ def obfuscate_report(self, archive): arc_md.add_field('total_substitutions', archive.total_sub_count) rmsg = '' if archive.removed_file_count: - rmsg = " [removed %s unprocessable files]" - rmsg = rmsg % archive.removed_file_count + rmsg = (f" [removed {archive.removed_file_count}" + " unprocessable files]") archive.report_msg(f"Obfuscation completed{rmsg}") except Exception as err: - self.ui_log.info( - f"Exception while processing {archive.archive_name}: {err}" - ) + self.ui_log.info("Exception while processing " + f"{archive.archive_name}: {err}") def obfuscate_file(self, filename, short_name=None, arc_name=None): """Obfuscate and individual file, line by line. @@ -769,10 +757,8 @@ def obfuscate_file(self, filename, short_name=None, arc_name=None): if not os.path.islink(filename): # don't run the obfuscation on the link, but on the actual file # at some other point. - self.log_debug( - f"Obfuscating {short_name}" or filename, - caller=arc_name - ) + self.log_debug(f"Obfuscating {short_name}" or filename, + caller=arc_name) tfile = tempfile.NamedTemporaryFile(mode='w', dir=self.tmpdir) _parsers = [ _p for _p in self.parsers if not @@ -787,20 +773,17 @@ def obfuscate_file(self, filename, short_name=None, arc_name=None): subs += count tfile.write(line) except Exception as err: - self.log_debug( - f"Unable to obfuscate {short_name}: {err}", - caller=arc_name, - ) + self.log_debug(f"Unable to obfuscate {short_name}: " + f"{err}", + caller=arc_name) tfile.seek(0) if subs: shutil.copyfile(tfile.name, filename) tfile.close() _ob_short_name = self.obfuscate_string(short_name.split('/')[-1]) - _ob_filename = short_name.replace( - short_name.split('/')[-1], - _ob_short_name - ) + _ob_filename = short_name.replace(short_name.split('/')[-1], + _ob_short_name) if _ob_filename != short_name: arc_path = filename.split(short_name)[0] @@ -837,10 +820,8 @@ def obfuscate_symlinks(self, archive): try: # relative name of the symlink in the archive _sym = symlink.split(archive.extracted_path)[1].lstrip('/') - self.log_debug( - f"Obfuscating symlink {_sym}", - caller=archive.archive_name - ) + self.log_debug(f"Obfuscating symlink {_sym}", + caller=archive.archive_name) # current target of symlink, again relative to the archive _target = os.readlink(symlink) # get the potentially renamed symlink name, this time the full @@ -862,9 +843,8 @@ def obfuscate_directory_names(self, archive): """For all directories that exist within the archive, obfuscate the directory name if it contains sensitive strings found during execution """ - self.log_info( - f"Obfuscating directory names in archive {archive.archive_name}" - ) + self.log_info("Obfuscating directory names in archive " + f"{archive.archive_name}") for dirpath in sorted(archive.get_directory_list(), reverse=True): for _name in os.listdir(dirpath): _dirname = os.path.join(dirpath, _name) diff --git a/sos/cleaner/archives/__init__.py b/sos/cleaner/archives/__init__.py index 423e4b2cae..61c3748392 100644 --- a/sos/cleaner/archives/__init__.py +++ b/sos/cleaner/archives/__init__.py @@ -172,9 +172,8 @@ def get_file_content(self, fname): try: return self.tarobj.extractfile(filename).read().decode('utf-8') except KeyError: - self.log_debug( - f"Unable to retrieve {fname}: no such file in archive" - ) + self.log_debug(f"Unable to retrieve {fname}: no such file in" + " archive") return '' else: try: @@ -212,10 +211,9 @@ def extract(self, quiet=False): continue if (not os.access(fname, os.R_OK) or not os.access(fname, os.W_OK)): - self.log_debug( - "Adding owner rw permissions to" - f" {fname.split(self.archive_path)[-1]}" - ) + file_name = fname.split(self.archive_path)[-1] + self.log_debug("Adding owner rw permissions to" + f" {file_name}") os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR) except Exception as err: self.log_debug(f"Error while trying to set perms: {err}") diff --git a/sos/cleaner/mappings/ip_map.py b/sos/cleaner/mappings/ip_map.py index e640a084d6..11d779b5a3 100644 --- a/sos/cleaner/mappings/ip_map.py +++ b/sos/cleaner/mappings/ip_map.py @@ -166,7 +166,7 @@ def _gen_address(): _octets = [] for i in range(0, 4): _octets.append(random.randint(11, 99)) - return "%s.%s.%s.%s" % tuple(_octets) + return f"{_octets[0]}.{_octets[1]}.{_octets[2]}.{_octets[3]}" _addr = _gen_address() if _addr in self.dataset.values(): diff --git a/sos/cleaner/mappings/mac_map.py b/sos/cleaner/mappings/mac_map.py index c9d38d16e2..b1f598077c 100644 --- a/sos/cleaner/mappings/mac_map.py +++ b/sos/cleaner/mappings/mac_map.py @@ -45,9 +45,9 @@ class SoSMacMap(SoSMap): '00:00:00:00:00:00' ] - mac_template = '53:4f:53:%s:%s:%s' - mac6_template = '53:4f:53:ff:fe:%s:%s:%s' - mac6_quad_template = '534f:53ff:fe%s:%s%s' + mac_template = '53:4f:53:{}:{}:{}' + mac6_template = '53:4f:53:ff:fe:{}:{}:{}' + mac6_quad_template = '534f:53ff:fe{}:{}{}' compile_regexes = False def add(self, item): @@ -70,11 +70,11 @@ def sanitize_item(self, item): hextets = tuple(hextets) # match 64-bit IPv6 MAC addresses matching MM:MM:MM:FF:FE:SS:SS:SS if re.match('(([0-9a-fA-F]{2}:){7}[0-9a-fA-F]{2})', item): - return self.mac6_template % hextets + return self.mac6_template.format(*hextets) # match 64-bit IPv6 MAC addresses matching MMMM:MMFF:FESS:SSSS if re.match('(([0-9a-fA-F]{4}:){3}([0-9a-fA-F]){4})', item): - return self.mac6_quad_template % hextets + return self.mac6_quad_template.format(*hextets) # match 48-bit IPv4 MAC addresses if re.match('([0-9a-fA-F][:_]?){12}', item): - return self.mac_template % hextets + return self.mac_template.format(*hextets) return None diff --git a/sos/collector/__init__.py b/sos/collector/__init__.py index ca8b38a930..e3cd91bb1c 100644 --- a/sos/collector/__init__.py +++ b/sos/collector/__init__.py @@ -186,9 +186,8 @@ def __init__(self, parser, parsed_args, cmdline_args): self.parse_node_strings() self.parse_cluster_options() self.log_debug(f"Executing {' '.join(s for s in sys.argv)}") - self.log_debug( - f"Found cluster profiles: {self.clusters.keys()}" - ) + self.log_debug("Found cluster profiles: " + f"{self.clusters.keys()}") self.verify_cluster_options() except KeyboardInterrupt: @@ -596,11 +595,9 @@ def verify_cluster_options(self): opt.value = self._validate_option(option, opt) break if not match: - self.exit( - "Unknown cluster option provided:" - f" {opt.cluster}.{opt.name}", - 1, - ) + self.exit("Unknown cluster option provided:" + f" {opt.cluster}.{opt.name}", + 1) def _validate_option(self, default, cli): """Checks to make sure that the option given on the CLI is valid. @@ -612,15 +609,16 @@ def _validate_option(self, default, cli): """ if not default.opt_type == bool: if not default.opt_type == cli.opt_type: - msg = "Invalid option type for %s. Expected %s got %s" - self.exit(msg % (cli.name, default.opt_type, cli.opt_type), 1) + msg = (f"Invalid option type for {cli.name}." + f" Expected {default.opt_type} got {cli.opt_type}") + self.exit(msg, 1) return cli.value else: val = cli.value.lower() if val not in ['true', 'on', 'yes', 'false', 'off', 'no']: - msg = ("Invalid value for %s. Accepted values are: 'true', " - "'false', 'on', 'off', 'yes', 'no'.") - self.exit(msg % cli.name, 1) + msg = (f"Invalid value for {cli.name}. Accepted values are:" + " 'true', 'false', 'on', 'off', 'yes', 'no'.") + self.exit(msg, 1) else: if val in ['true', 'on', 'yes']: return True @@ -753,10 +751,8 @@ def _load_group_config(self): _group = json.load(hf) for key in ['primary', 'cluster_type']: if _group[key]: - self.log_debug( - f"Setting option '{key}' to '{_group[key]}' per host" - " group" - ) + self.log_debug(f"Setting option '{key}' to " + f"'{_group[key]}' per host group") setattr(self.opts, key, _group[key]) if _group['nodes']: self.log_debug(f"Adding {_group['nodes']} to node list") @@ -802,9 +798,8 @@ def prep(self): self.opts.primary)) and not self.opts.batch): self.log_debug('password specified, not using SSH keys') - msg = ( - f"Provide the SSH password for user {self.opts.ssh_user}: " - ) + msg = ("Provide the SSH password for user " + f"{self.opts.ssh_user}: ") self.opts.password = getpass(prompt=msg) if ((self.commons['need_sudo'] and not self.opts.nopasswd_sudo) @@ -812,9 +807,9 @@ def prep(self): if not self.opts.password and not self.opts.password_per_node: self.log_debug('non-root user specified, will request ' 'sudo password') - msg = ('A non-root user has been provided. Provide sudo ' - 'password for %s on remote nodes: ' - % self.opts.ssh_user) + msg = ('A non-root user has been provided. Provide sudo' + f' password for {self.opts.ssh_user} on remote ' + 'nodes: ') self.opts.sudo_pw = getpass(prompt=msg) else: if not self.opts.nopasswd_sudo: @@ -830,8 +825,8 @@ def prep(self): "to become root remotely.") self.exit(msg, 1) self.log_debug('non-root user asking to become root remotely') - msg = ('User %s will attempt to become root. ' - 'Provide root password: ' % self.opts.ssh_user) + msg = (f'User {self.opts.ssh_user} will attempt to become ' + 'root. Provide root password: ') self.opts.root_password = getpass(prompt=msg) self.commons['need_sudo'] = False else: @@ -843,9 +838,8 @@ def prep(self): try: self._load_group_config() except Exception as err: - msg = ( - f"Could not load specified group {self.opts.group}: {err}" - ) + msg = (f"Could not load specified group {self.opts.group}: " + f"{err}") self.exit(msg, 1) try: @@ -885,9 +879,8 @@ def prep(self): local_sudo=local_sudo, load_facts=can_run_local) except Exception as err: - self.log_debug( - f"Unable to determine local installation: {err}" - ) + self.log_debug("Unable to determine local installation: " + f"{err}") self.exit('Unable to determine local installation. Use the ' '--no-local option if localhost should not be ' 'included.\nAborting...\n', 1) @@ -926,10 +919,9 @@ def prep(self): self.cluster.setup() if self.cluster.cluster_ssh_key: if not self.opts.ssh_key: - self.log_debug( - "Updating SSH key to" - f" {self.cluster.cluster_ssh_key} per cluster" - ) + self.log_debug("Updating SSH key to" + f" {self.cluster.cluster_ssh_key} per " + "cluster") self.opts.ssh_key = self.cluster.cluster_ssh_key self.get_nodes() @@ -1009,10 +1001,8 @@ def connect_to_primary(self): """ try: self.primary = SosNode(self.opts.primary, self.commons) - self.ui_log.info( - f"Connected to {self.opts.primary}, determining cluster" - " type..." - ) + self.ui_log.info(f"Connected to {self.opts.primary}, determining" + " cluster type...") except Exception as e: self.log_debug(f'Failed to connect to primary node: {e}') self.exit('Could not connect to primary node. Aborting...', 1) @@ -1032,20 +1022,19 @@ def determine_cluster(self): cluster.primary = self.primary if cluster.check_enabled(): cname = cluster.__class__.__name__ - self.log_debug("Installation matches %s, checking for layered " - "profiles" % cname) + self.log_debug(f"Installation matches {cname}, checking for " + "layered profiles") for remaining in checks: if issubclass(remaining.__class__, cluster.__class__): rname = remaining.__class__.__name__ - self.log_debug("Layered profile %s found. " - "Checking installation" - % rname) + self.log_debug(f"Layered profile {rname} found. " + "Checking installation") remaining.primary = self.primary if remaining.check_enabled(): self.log_debug("Installation matches both layered " - "profile %s and base profile %s, " - "setting cluster type to layered " - "profile" % (rname, cname)) + f"profile {rname} and base profile " + f"{cname}, setting cluster type to " + "layered profile") cluster = remaining break self.cluster = cluster @@ -1090,8 +1079,9 @@ def compare_node_to_regex(self, node): if re.match(regex, node): return True except re.error as err: - msg = 'Error comparing %s to provided node regex %s: %s' - self.log_debug(msg % (node, regex, err)) + msg = (f'Error comparing {node} to provided node regex ' + f'{regex}: {err}') + self.log_debug(msg) return False def get_nodes(self): @@ -1168,13 +1158,14 @@ def intro(self): """Print the intro message and prompts for a case ID if one is not provided on the command line """ - disclaimer = ("""\ + disclaimer = (f"""\ This utility is used to collect sos reports from multiple \ nodes simultaneously. Remote connections are made and/or maintained \ to those nodes via well-known transport protocols such as SSH. An archive of sos report tarballs collected from the nodes will be \ -generated in %s and may be provided to an appropriate support representative. +generated in {self.tmpdir} and may be provided to an appropriate support \ +representative. The generated archive may contain data considered sensitive \ and its content should be reviewed by the originating \ @@ -1183,8 +1174,8 @@ def intro(self): No configuration changes will be made to the system running \ this utility or remote systems that it connects to. """) - self.ui_log.info("\nsos-collector (version %s)\n" % __version__) - intro_msg = self._fmt_msg(disclaimer % self.tmpdir) + self.ui_log.info(f"\nsos-collector (version {__version__})\n") + intro_msg = self._fmt_msg(disclaimer) self.ui_log.info(intro_msg) prompt = "\nPress ENTER to continue, or CTRL-C to quit\n" @@ -1236,10 +1227,8 @@ def collect(self): if self.opts.password_per_node: _nodes = [] for node in nodes: - msg = ( - "Please enter the password for" - f" {self.opts.ssh_user}@{node[0]}: " - ) + msg = ("Please enter the password for" + f" {self.opts.ssh_user}@{node[0]}: ") node_pwd = getpass(msg) _nodes.append((node[0], node_pwd)) nodes = _nodes @@ -1267,10 +1256,9 @@ def collect(self): "Aborting...", 1 ) - self.ui_log.info("\nBeginning collection of sosreports from %s " - "nodes, collecting a maximum of %s " - "concurrently\n" - % (self.report_num, self.opts.jobs)) + self.ui_log.info("\nBeginning collection of sosreports from " + f"{self.report_num} nodes, collecting a maximum " + f"of {self.opts.jobs} concurrently\n") npool = ThreadPoolExecutor(self.opts.jobs) npool.map(self._finalize_sos_cmd, self.client_list, chunksize=1) @@ -1290,8 +1278,9 @@ def collect(self): files = self.cluster._run_extra_cmd() if files: self.primary.collect_extra_cmd(files) - msg = '\nSuccessfully captured %s of %s sosreports' - self.log_info(msg % (self.retrieved, self.report_num)) + msg = (f'\nSuccessfully captured {self.retrieved} of ' + f'{self.report_num} sosreports') + self.log_info(msg) self.close_all_connections() if self.retrieved > 0: arc_name = self.create_cluster_archive() @@ -1426,14 +1415,14 @@ def create_cluster_archive(self): ) os.rename(map_file, map_name) self.ui_log.info("A mapping of obfuscated elements is " - "available at\n\t%s" % map_name) + f"available at\n\t{map_name}") self.soslog.info(f'Archive created as {final_name}') self.ui_log.info('\nThe following archive has been created. ' 'Please provide it to your support team.') - self.ui_log.info('\t%s\n' % final_name) + self.ui_log.info(f'\t{final_name}\n') return final_name except Exception as err: - msg = ("Could not finalize archive: %s\n\nData may still be " - "available uncompressed at %s" % (err, self.archive_path)) + msg = (f"Could not finalize archive: {err}\n\nData may still be " + f"available uncompressed at {self.archive_path}") self.exit(msg, 2) diff --git a/sos/collector/clusters/ocp.py b/sos/collector/clusters/ocp.py index 33e1822f7d..036cdbb147 100644 --- a/sos/collector/clusters/ocp.py +++ b/sos/collector/clusters/ocp.py @@ -90,9 +90,8 @@ def oc_cmd(self): "Unable to to determine PATH for 'oc' command, " "node enumeration may fail." ) - self.log_debug( - f"Locating 'oc' failed: {_oc_path['output']}" - ) + self.log_debug("Locating 'oc' failed: " + f"{_oc_path['output']}") if self.get_option('kubeconfig'): self._oc_cmd += " --kubeconfig " \ f"{self.get_option('kubeconfig')}" @@ -110,9 +109,8 @@ def _attempt_oc_login(self): token """ _res = self.exec_primary_cmd( - self.fmt_oc_cmd( - f"login --insecure-skip-tls-verify=True --token={self.token}" - ) + self.fmt_oc_cmd("login --insecure-skip-tls-verify=True " + f"--token={self.token}") ) return _res['status'] == 0 @@ -349,11 +347,9 @@ def set_primary_options(self, node): # cannot do remotely if node.file_exists('/root/.kube/config', need_root=True): _oc_cmd += ' --kubeconfig /host/root/.kube/config' - can_oc = node.run_command( - f"{_oc_cmd} whoami", - use_container=node.host.containerized, - need_root=True, - ) + can_oc = node.run_command(f"{_oc_cmd} whoami", + use_container=node.host.containerized, + need_root=True) if can_oc['status'] == 0: # the primary node can already access the API self._toggle_api_opt(node, True) @@ -370,9 +366,9 @@ def set_primary_options(self, node): self._toggle_api_opt(node, True) self.api_collect_enabled = True if self.api_collect_enabled: - msg = ("API collections will be performed on %s\nNote: API " - "collections may extend runtime by 10s of minutes\n" - % node.address) + msg = ("API collections will be performed on " + f"{node.address}\nNote: API collections may extend " + "runtime by 10s of minutes\n") self.soslog.info(msg) self.ui_log.info(msg) diff --git a/sos/collector/clusters/ovirt.py b/sos/collector/clusters/ovirt.py index 2bf4c24408..311a2efe61 100644 --- a/sos/collector/clusters/ovirt.py +++ b/sos/collector/clusters/ovirt.py @@ -75,8 +75,8 @@ def _sql_scrub(self, val): invalid_chars = ['\x00', '\\', '\n', '\r', '\032', '"', '\''] if any(x in invalid_chars for x in val): - self.log_warn("WARNING: Cluster option \'%s\' contains invalid " - "characters. Using '%%' instead." % val) + self.log_warn(f"WARNING: Cluster option \'{val}\' contains " + "invalid characters. Using '%%' instead.") return '%' return val @@ -109,9 +109,9 @@ def format_db_cmd(self): cluster = self._sql_scrub(self.get_option('cluster')) datacenter = self._sql_scrub(self.get_option('datacenter')) self.dbquery = ("SELECT host_name from vds where cluster_id in " - "(select cluster_id FROM cluster WHERE name like '%s'" - " and storage_pool_id in (SELECT id FROM storage_pool " - "WHERE name like '%s'))" % (cluster, datacenter)) + "(select cluster_id FROM cluster WHERE name like " + f"'{cluster}' and storage_pool_id in (SELECT id FROM " + f"storage_pool WHERE name like '{datacenter}'))") if self.get_option('spm-only'): # spm_status is an integer with the following meanings # 0 - Normal (not SPM) @@ -128,9 +128,8 @@ def get_nodes(self): nodes = res['output'].splitlines()[2:-1] return [n.split('(')[0].strip() for n in nodes] else: - raise Exception( - f"database query failed, return code: {res['status']}" - ) + raise Exception("database query failed, return code: " + f"{res['status']}") def run_extra_cmd(self): if not self.get_option('no-database') and self.conf: diff --git a/sos/collector/clusters/pacemaker.py b/sos/collector/clusters/pacemaker.py index e1916bbe53..d778454c35 100644 --- a/sos/collector/clusters/pacemaker.py +++ b/sos/collector/clusters/pacemaker.py @@ -36,7 +36,7 @@ def get_nodes(self): self.get_nodes_from_crm() except Exception as err: self.log_warn("Falling back to sourcing corosync.conf. " - "Could not parse crm_mon output: %s" % err) + f"Could not parse crm_mon output: {err}") if not self.nodes: # fallback to corosync.conf, in case the node we're inspecting # is offline from the cluster @@ -47,10 +47,10 @@ def get_nodes(self): _shorts = [n for n in self.nodes if '.' not in n] if _shorts: self.log_warn( - "WARNING: Node addresses '%s' may not resolve locally if you " - "are not running on a node in the cluster. Try using option " - "'-c pacemaker.only-corosync' if these connections fail." - % ','.join(_shorts) + f"WARNING: Node addresses '{','.join(_shorts)}' may not " + "resolve locally if you are not running on a node in the " + "cluster. Try using option '-c pacemaker.only-corosync' if " + "these connections fail." ) return self.nodes diff --git a/sos/collector/clusters/satellite.py b/sos/collector/clusters/satellite.py index 5e28531da7..8002dfde0d 100644 --- a/sos/collector/clusters/satellite.py +++ b/sos/collector/clusters/satellite.py @@ -26,9 +26,8 @@ class satellite(Cluster): packages = ('satellite', 'satellite-installer') def _psql_cmd(self, query): - _cmd = "su postgres -c %s" - _dbcmd = "psql foreman -c %s" - return _cmd % quote(_dbcmd % quote(query)) + _dbcmd = f"psql foreman -c {quote(query)}" + return f"su postgres -c {quote(_dbcmd)}" def get_nodes(self): cmd = self._psql_cmd('copy (select name from smart_proxies) to stdout') diff --git a/sos/collector/exceptions.py b/sos/collector/exceptions.py index 87f623dfde..477323ec8b 100644 --- a/sos/collector/exceptions.py +++ b/sos/collector/exceptions.py @@ -47,9 +47,8 @@ class ConnectionException(Exception): """Raised when an attempt to connect fails""" def __init__(self, address='', port=''): - message = ( - f"Could not connect to host {address} on specified port {port}" - ) + message = (f"Could not connect to host {address} on specified port " + f"{port}") super(ConnectionException, self).__init__(message) @@ -100,11 +99,9 @@ class InvalidTransportException(Exception): not supported locally""" def __init__(self, transport=None): - message = ( - f"Connection failed: unknown or unsupported transport {transport}" - if transport - else '' - ) + message = ("Connection failed: unknown or unsupported transport " + f"{transport}" + if transport else '') super(InvalidTransportException, self).__init__(message) diff --git a/sos/collector/sosnode.py b/sos/collector/sosnode.py index a0b316a1b6..70d4cbe44c 100644 --- a/sos/collector/sosnode.py +++ b/sos/collector/sosnode.py @@ -202,21 +202,16 @@ def create_sos_container(self): ret = self.run_command(self.host.restart_sos_container(), need_root=True) if ret['status'] == 0: - self.log_info( - "Temporary container" - f" {self.host.sos_container_name} created" - ) + self.log_info("Temporary container" + f" {self.host.sos_container_name} created") return True else: - self.log_error( - "Could not start container after create:" - f" {ret['output']}" - ) + self.log_error("Could not start container after create:" + f" {ret['output']}") raise Exception else: - self.log_error( - f"Could not create container on host: {res['output']}" - ) + self.log_error("Could not create container on host: " + f"{res['output']}") raise Exception return False @@ -393,9 +388,8 @@ def determine_host_policy(self): distributions """ if self.local: - self.log_info( - f"using local policy {self.commons['policy'].distro}" - ) + self.log_info("using local policy " + f"{self.commons['policy'].distro}") return self.commons['policy'] host = load(cache={}, sysroot=self.opts.sysroot, init=InitSystem(), probe_runtime=True, @@ -560,9 +554,9 @@ def update_cmd_from_cluster(self): if not self.preset: self.preset = self.cluster.sos_preset else: - self.log_info('Cluster specified preset %s but user has also ' - 'defined a preset. Using user specification.' - % self.cluster.sos_preset) + self.log_info('Cluster specified preset ' + f'{self.cluster.sos_preset} but user has also ' + 'defined a preset. Using user specification.') if self.cluster.sos_plugins: for plug in self.cluster.sos_plugins: if plug not in self.enable_plugins: @@ -618,9 +612,8 @@ def finalize_sos_cmd(self): # sos-3.7 added options if self.check_sos_version('3.7'): if self.opts.plugin_timeout: - sos_opts.append( - f"--plugin-timeout={quote(str(self.opts.plugin_timeout))}" - ) + sos_opts.append("--plugin-timeout=" + f"{quote(str(self.opts.plugin_timeout))}") # sos-3.8 added options if self.check_sos_version('3.8'): @@ -635,14 +628,11 @@ def finalize_sos_cmd(self): if self.check_sos_version('4.1'): if self.opts.skip_commands: - sos_opts.append( - "--skip-commands=" - f"{quote(','.join(self.opts.skip_commands))}" - ) + sos_opts.append("--skip-commands=" + f"{quote(','.join(self.opts.skip_commands))}") if self.opts.skip_files: - sos_opts.append( - f"--skip-files={quote(','.join(self.opts.skip_files))}" - ) + sos_opts.append("--skip-files=" + f"{quote(','.join(self.opts.skip_files))}") if self.check_sos_version('4.2'): if self.opts.cmd_timeout: @@ -653,9 +643,8 @@ def finalize_sos_cmd(self): # handle downstream versions that backported this option if self.check_sos_version('4.3') or self.check_sos_version('4.2-13'): if self.opts.container_runtime != 'auto': - sos_opts.append( - f"--container-runtime={self.opts.container_runtime}" - ) + sos_opts.append("--container-runtime=" + f"{self.opts.container_runtime}") if self.opts.namespaces: sos_opts.append(f"--namespaces={self.opts.namespaces}") @@ -687,15 +676,15 @@ def finalize_sos_cmd(self): if self._preset_exists(self.preset): sos_opts.append(f'--preset={quote(self.preset)}') else: - self.log_debug('Requested to enable preset %s but preset does ' - 'not exist on node' % self.preset) + self.log_debug(f'Requested to enable preset {self.preset} but ' + 'preset does not exist on node') if self.only_plugins: plugs = [o for o in self.only_plugins if self._plugin_exists(o)] if len(plugs) != len(self.only_plugins): not_only = list(set(self.only_plugins) - set(plugs)) - self.log_debug('Requested plugins %s were requested to be ' - 'enabled but do not exist' % not_only) + self.log_debug(f'Requested plugins {not_only} were requested ' + 'to be enabled but do not exist') only = self._fmt_sos_opt_list(self.only_plugins) if only: sos_opts.append(f'--only-plugins={quote(only)}') @@ -709,8 +698,8 @@ def finalize_sos_cmd(self): skip = [o for o in self.skip_plugins if self._check_enabled(o)] if len(skip) != len(self.skip_plugins): not_skip = list(set(self.skip_plugins) - set(skip)) - self.log_debug('Requested to skip plugins %s, but plugins are ' - 'already not enabled' % not_skip) + self.log_debug(f'Requested to skip plugins {not_skip}, but ' + 'plugins are already not enabled') skipln = self._fmt_sos_opt_list(skip) if skipln: sos_opts.append(f'--skip-plugins={quote(skipln)}') @@ -722,8 +711,8 @@ def finalize_sos_cmd(self): and self._check_disabled(o) and self._plugin_exists(o)] if len(opts) != len(self.enable_plugins): not_on = list(set(self.enable_plugins) - set(opts)) - self.log_debug('Requested to enable plugins %s, but plugins ' - 'are already enabled or do not exist' % not_on) + self.log_debug(f'Requested to enable plugins {not_on}, but ' + 'plugins are already enabled or do not exist') enable = self._fmt_sos_opt_list(opts) if enable: sos_opts.append(f'--enable-plugins={quote(enable)}') @@ -811,10 +800,8 @@ def execute_sos_command(self): self.manifest.add_field('checksum_type', 'unknown') else: err = self.determine_sos_error(res['status'], res['output']) - self.log_debug( - f"Error running sos report. rc = {res['status']} msg =" - f" {res['output']}" - ) + self.log_debug(f"Error running sos report. rc = " + f"{res['status']} msg = {res['output']}") raise Exception(err) return path except CommandTimeoutException: @@ -834,8 +821,8 @@ def retrieve_file(self, path): self.log_info(f"Copying remote {path} to local {destdir}") return self._transport.retrieve_file(path, dest) else: - self.log_debug("Attempting to copy remote file %s, but it " - "does not exist on filesystem" % path) + self.log_debug(f"Attempting to copy remote file {path}, but " + "it does not exist on filesystem") return False except Exception as err: self.log_debug(f"Failed to retrieve {path}: {err}") @@ -848,8 +835,8 @@ def remove_file(self, path): path = ''.join(path.split()) try: if len(path.split('/')) <= 2: # ensure we have a non '/' path - self.log_debug("Refusing to remove path %s: appears to be " - "incorrect and possibly dangerous" % path) + self.log_debug(f"Refusing to remove path {path}: appears to " + "be incorrect and possibly dangerous") return False if self.file_exists(path): self.log_info(f"Removing file {path}") @@ -857,8 +844,8 @@ def remove_file(self, path): res = self.run_command(cmd, need_root=True) return res['status'] == 0 else: - self.log_debug("Attempting to remove remote file %s, but it " - "does not exist on filesystem" % path) + self.log_debug(f"Attempting to remove remote file {path}, " + "but it does not exist on filesystem") return False except Exception as e: self.log_debug(f'Failed to remove {path}: {e}') @@ -893,9 +880,8 @@ def retrieve_sosreport(self): e = self.stderr.read() else: e = [x.strip() for x in self.stdout.readlines() if x.strip][-1] - self.soslog.error( - f"Failed to run sos report on {self.address}: {e}" - ) + self.soslog.error(f"Failed to run sos report on {self.address}:" + f" {e}") self.log_error(f'Failed to run sos report. {e}') return False @@ -907,8 +893,8 @@ def remove_sos_archive(self): # is no archive at the original location to remove return if 'sosreport' not in self.sos_path: - self.log_debug("Node sos report path %s looks incorrect. Not " - "attempting to remove path" % self.sos_path) + self.log_debug(f"Node sos report path {self.sos_path} looks " + "incorrect. Not attempting to remove path") return removed = self.remove_file(self.sos_path) if not removed: @@ -934,9 +920,8 @@ def collect_extra_cmd(self, filenames): self.make_archive_readable(filename) except Exception as err: self.log_error(f"Unable to retrieve file {filename}") - self.log_debug( - f"Failed to make file {filename} readable: {err}" - ) + self.log_debug(f"Failed to make file {filename} " + f"readable: {err}") continue ret = self.retrieve_file(filename) if ret: @@ -945,8 +930,8 @@ def collect_extra_cmd(self, filenames): else: self.log_error(f"Unable to retrieve file {filename}") except Exception as e: - msg = f'Error collecting additional data from primary: {e}' - self.log_error(msg) + self.log_error('Error collecting additional data from ' + f'primary: {e}') def make_archive_readable(self, filepath): """Used to make the given archive world-readable, which is slightly @@ -959,8 +944,8 @@ def make_archive_readable(self, filepath): if res['status'] == 0: return True else: - msg = "Exception while making %s readable. Return code was %s" - self.log_error(msg % (filepath, res['status'])) + self.log_error(f"Exception while making {filepath} readable. " + f"Return code was {res['status']}") raise Exception # vim: set et ts=4 sw=4 : diff --git a/sos/collector/transports/__init__.py b/sos/collector/transports/__init__.py index 9bbf930a6b..a6a8d6aca2 100644 --- a/sos/collector/transports/__init__.py +++ b/sos/collector/transports/__init__.py @@ -94,9 +94,8 @@ def remote_exec(self): def display_help(cls, section): if cls is RemoteTransport: return cls.display_self_help(section) - section.set_title( - f"{cls.name.title().replace('_', ' ')} Transport Detailed Help" - ) + section.set_title(f"{cls.name.title().replace('_', ' ')} " + "Transport Detailed Help") if cls.__doc__ and cls.__doc__ is not RemoteTransport.__doc__: section.add_text(cls.__doc__) else: @@ -110,18 +109,16 @@ def display_self_help(cls, section): section.set_title('SoS Remote Transport Help') section.add_text( "\nTransports define how SoS connects to nodes and executes " - "commands on them for the purposes of an %s run. Generally, " - "this means transports define how commands are wrapped locally " - "so that they are executed on the remote node(s) instead." - % bold('sos collect') - ) + f"commands on them for the purposes of an {bold('sos collect')} " + "run. Generally, this means transports define how commands are " + "wrapped locally so that they are executed on the remote node(s) " + "instead.") section.add_text( "Transports are generally selected by the cluster profile loaded " "for a given execution, however users may explicitly set one " - "using '%s'. Note that not all transports will function for all " - "cluster/node types." - % bold('--transport=$transport_name') + f"using '{bold('--transport=$transport_name')}'. Note that not " + "all transports will function for all cluster/node types." ) section.add_text( @@ -154,9 +151,8 @@ def _connect(self, password): """Actually perform the connection requirements. Should be overridden by specific transports that subclass RemoteTransport """ - raise NotImplementedError( - f"Transport {self.name} does not define connect" - ) + raise NotImplementedError(f"Transport {self.name} does not define " + "connect") def reconnect(self, password): """Attempts to reconnect to the node using the standard connect() @@ -192,9 +188,8 @@ def disconnect(self): self.log_error(f"Failed to disconnect: {err}") def _disconnect(self): - raise NotImplementedError( - f"Transport {self.name} does not define disconnect" - ) + raise NotImplementedError(f"Transport {self.name} does not define " + "disconnect") @property def _need_shell(self): @@ -378,14 +373,13 @@ def retrieve_file(self, fname, dest): self.log_info("File retrieval failed after 5 attempts") return False except Exception as err: - self.log_error("Exception encountered during retrieval attempt %s " - "for %s: %s" % (attempts, fname, err)) + self.log_error("Exception encountered during retrieval attempt " + f"{attempts} for {fname}: {err}") raise err def _retrieve_file(self, fname, dest): - raise NotImplementedError( - f"Transport {self.name} does not support file copying" - ) + raise NotImplementedError(f"Transport {self.name} does not support " + "file copying") def read_file(self, fname): """Read the given file fname and return its contents @@ -407,9 +401,8 @@ def _read_file(self, fname): if 'No such file' in res['output']: self.log_debug(f"File {fname} does not exist on node") else: - self.log_error( - f"Error reading {fname}: {res['output'].split(':')[1:]}" - ) + self.log_error(f"Error reading {fname}: " + f"{res['output'].split(':')[1:]}") return '' # vim: set et ts=4 sw=4 : diff --git a/sos/collector/transports/control_persist.py b/sos/collector/transports/control_persist.py index 5715e03bcc..1a8c62640e 100644 --- a/sos/collector/transports/control_persist.py +++ b/sos/collector/transports/control_persist.py @@ -105,13 +105,11 @@ def _connect(self, password=''): if self.opts.ssh_key: ssh_key = f"-i{self.opts.ssh_key}" - cmd = ("ssh %s %s -oControlPersist=600 -oControlMaster=auto " - "-oStrictHostKeyChecking=no -oControlPath=%s %s@%s " - "\"echo Connected\"" % (ssh_key, - ssh_port, - self.control_path, - self.opts.ssh_user, - self.address)) + cmd = (f"ssh {ssh_key} {ssh_port} -oControlPersist=600 " + "-oControlMaster=auto " + "-oStrictHostKeyChecking=no " + f"-oControlPath={self.control_path} " + f"{self.opts.ssh_user}@{self.address} \"echo Connected\"") res = pexpect.spawn(cmd, encoding='utf-8') connect_expects = [ @@ -160,9 +158,8 @@ def _connect(self, password=''): if connected: if not os.path.exists(self.control_path): raise ControlSocketMissingException - self.log_debug( - f"Successfully created control socket at {self.control_path}" - ) + self.log_debug("Successfully created control socket at " + f"{self.control_path}") return True return False @@ -200,11 +197,9 @@ def remote_exec(self): return self.ssh_cmd def _retrieve_file(self, fname, dest): - cmd = ( - "/usr/bin/scp -oControlPath=" - f"{self.control_path} {self.opts.ssh_user}@{self.address}:{fname}" - f" {dest}" - ) + cmd = ("/usr/bin/scp -oControlPath=" + f"{self.control_path} " + f"{self.opts.ssh_user}@{self.address}:{fname} {dest}") res = sos_get_command_output(cmd) return res['status'] == 0 diff --git a/sos/collector/transports/oc.py b/sos/collector/transports/oc.py index 2c55e13d88..0c6d02ffa8 100644 --- a/sos/collector/transports/oc.py +++ b/sos/collector/transports/oc.py @@ -50,7 +50,10 @@ def run_oc(self, cmd, **kwargs): """Format and run a command with `oc` in the project defined for our execution """ - return sos_get_command_output(f"oc -n {self.project} {cmd}", **kwargs) + return sos_get_command_output( + f"oc -n {self.project} {cmd}", + **kwargs + ) @property def connected(self): @@ -69,47 +72,72 @@ def get_node_pod_config(self): "apiVersion": "v1", "metadata": { "name": f"{self.address.split('.')[0]}-sos-collector", - "namespace": self.project, + "namespace": self.project }, "priorityClassName": "system-cluster-critical", "spec": { "volumes": [ { "name": "host", - "hostPath": {"path": "/", "type": "Directory"}, + "hostPath": { + "path": "/", + "type": "Directory" + } }, { "name": "run", - "hostPath": {"path": "/run", "type": "Directory"}, + "hostPath": { + "path": "/run", + "type": "Directory" + } }, { "name": "varlog", - "hostPath": {"path": "/var/log", "type": "Directory"}, + "hostPath": { + "path": "/var/log", + "type": "Directory" + } }, { "name": "machine-id", "hostPath": { - "path": "/etc/machine-id", "type": "File" - }, - }, + "path": "/etc/machine-id", + "type": "File" + } + } ], "containers": [ { "name": "sos-collector-tmp", "image": "registry.redhat.io/rhel8/support-tools" - if not self.opts.image - else self.opts.image, - "command": ["/bin/bash"], - "env": [{"name": "HOST", "value": "/host"}], + if not self.opts.image else self.opts.image, + "command": [ + "/bin/bash" + ], + "env": [ + { + "name": "HOST", + "value": "/host" + } + ], "resources": {}, "volumeMounts": [ - {"name": "host", "mountPath": "/host"}, - {"name": "run", "mountPath": "/run"}, - {"name": "varlog", "mountPath": "/var/log"}, + { + "name": "host", + "mountPath": "/host" + }, + { + "name": "run", + "mountPath": "/run" + }, + { + "name": "varlog", + "mountPath": "/var/log" + }, { "name": "machine-id", "mountPath": "/etc/machine-id" - }, + } ], "securityContext": { "privileged": True, @@ -117,18 +145,17 @@ def get_node_pod_config(self): }, "stdin": True, "stdinOnce": True, - "tty": True, + "tty": True } ], - "imagePullPolicy": "Always" - if self.opts.force_pull_image - else "IfNotPresent", + "imagePullPolicy": + "Always" if self.opts.force_pull_image else "IfNotPresent", "restartPolicy": "Never", "nodeName": self.address, "hostNetwork": True, "hostPID": True, - "hostIPC": True, - }, + "hostIPC": True + } } def _connect(self, password): @@ -144,24 +171,23 @@ def _connect(self, password): json.dump(podconf, cfile) self.log_debug(f"Starting sos collector container '{self.pod_name}'") # this specifically does not need to run with a project definition - out = sos_get_command_output(f"oc create -f {self.pod_tmp_conf}") - if ( - out['status'] != 0 - or f"pod/{self.pod_name} created" not in out['output'] - ): + out = sos_get_command_output( + f"oc create -f {self.pod_tmp_conf}" + ) + if (out['status'] != 0 or f"pod/{self.pod_name} created" not in + out['output']): self.log_error("Unable to deploy sos collect pod") self.log_debug(f"Debug pod deployment failed: {out['output']}") return False - self.log_debug("Pod '%s' successfully deployed, waiting for pod to " - "enter ready state" % self.pod_name) + self.log_debug(f"Pod '{self.pod_name}' successfully deployed, waiting" + " for pod to enter ready state") # wait for the pod to report as running try: - up = self.run_oc( - "wait --for=condition=Ready" - f" pod/{self.pod_name} --timeout=30s", - timeout=40, - ) + up = self.run_oc(f"wait --for=condition=Ready pod/{self.pod_name}" + " --timeout=30s", + # timeout is for local safety, not oc + timeout=40) if not up['status'] == 0: self.log_error("Pod not available after 30 seconds") return False @@ -176,10 +202,8 @@ def _connect(self, password): def _format_cmd_for_exec(self, cmd): if cmd.startswith('oc'): - return ( - f"oc -n {self.project} exec --request-timeout=0" - f" {self.pod_name} -- chroot /host {cmd}" - ) + return (f"oc -n {self.project} exec --request-timeout=0" + f" {self.pod_name} -- chroot /host {cmd}") return super(OCTransport, self)._format_cmd_for_exec(cmd) def run_command(self, cmd, timeout=180, need_root=False, env=None, @@ -198,18 +222,15 @@ def _disconnect(self): os.unlink(self.pod_tmp_conf) removed = self.run_oc(f"delete pod {self.pod_name}") if "deleted" not in removed['output']: - self.log_debug( - f"Calling delete on pod '{self.pod_name}' failed: {removed}" - ) + self.log_debug(f"Calling delete on pod '{self.pod_name}' failed:" + f" {removed}") return False return True @property def remote_exec(self): - return ( - f"oc -n {self.project} exec --request-timeout=0 {self.pod_name} --" - " /bin/bash -c" - ) + return (f"oc -n {self.project} exec --request-timeout=0" + f" {self.pod_name} -- /bin/bash -c") def _retrieve_file(self, fname, dest): # check if --retries flag is available for given version of oc diff --git a/sos/component.py b/sos/component.py index 16dd7e7b1f..bee42951ff 100644 --- a/sos/component.py +++ b/sos/component.py @@ -281,7 +281,7 @@ def load_options(self): if opts.preset != self._arg_defaults["preset"]: self.preset = self.policy.find_preset(opts.preset) if not self.preset: - sys.stderr.write("Unknown preset: '%s'\n" % opts.preset) + sys.stderr.write(f"Unknown preset: '{opts.preset}'\n") self.preset = self.policy.probe_preset() opts.list_presets = True @@ -310,8 +310,8 @@ def cleanup(self): if self.tmpdir: rmtree(self.tmpdir) except Exception as err: - print("Failed to finish cleanup: %s\nContents may remain in %s" - % (err, self.tmpdir)) + print(f"Failed to finish cleanup: {err}\nContents may remain in" + f" {self.tmpdir}") def _set_encrypt_from_env_vars(self): msg = ('No encryption environment variables set, archive will not be ' diff --git a/sos/help/__init__.py b/sos/help/__init__.py index dc951e09a2..e8aabfad4b 100644 --- a/sos/help/__init__.py +++ b/sos/help/__init__.py @@ -176,22 +176,21 @@ def display_self_help(self): 'SoS - officially pronounced "ess-oh-ess" - is a diagnostic and ' 'supportability utility used by several Linux distributions as an ' 'easy-to-use tool for standardized data collection. The most known' - ' component of which is %s (formerly sosreport) which is used to ' - 'collect troubleshooting information into an archive for review ' - 'by sysadmins or technical support teams.' - % bold('sos report') + f' component of which is {bold("sos report")} (formerly ' + 'sosreport) which is used to collect troubleshooting information ' + 'into an archive for review by sysadmins or technical support ' + 'teams.' ) subsect = self_help.add_section('How to search using sos help') usage = bold('$component.$topic.$subtopic') - subsect.add_text( - 'To get more information on a given topic, use the form \'%s\'.' - % usage - ) + subsect.add_text('To get more information on a given topic, use the ' + f'form \'{usage}\'.') rep_ex = bold('sos help report.plugins.kernel') - subsect.add_text("For example '%s' will provide more information on " - "the kernel plugin for the report function." % rep_ex) + subsect.add_text(f"For example '{rep_ex}' will provide more " + "information on the kernel plugin for the report " + "function.") avail_help = self_help.add_section('Available Help Sections') avail_help.add_text( diff --git a/sos/options.py b/sos/options.py index cf8b4f4abe..3111aa3d1b 100644 --- a/sos/options.py +++ b/sos/options.py @@ -70,7 +70,7 @@ def __str(self, quote=False, sep=" ", prefix="", suffix=""): :param literal: print values as Python literals """ args = prefix - arg_fmt = "=%s" + arg_fmt = "={}" for arg in self.arg_names: args += arg + arg_fmt + sep args.strip(sep) @@ -83,7 +83,7 @@ def __str(self, quote=False, sep=" ", prefix="", suffix=""): # Only quote strings if quote=False vals = [f"'{v}'" if isinstance(v, str) else v for v in vals] - return (args % tuple(vals)).strip(sep) + suffix + return (args.format(*vals)).strip(sep) + suffix def __str__(self): return self.__str() @@ -167,8 +167,7 @@ def _convert_to_type(self, key, val, conf): if val is None: raise Exception( f"Value of '{key}' in {conf}" - " must be True or False or analagous" - ) + " must be True or False or analagous") else: return val if isinstance(self.arg_defaults[key], int): @@ -227,14 +226,10 @@ def _update_from_section(section, config): with open(config_file) as f: config.read_file(f, config_file) except DuplicateOptionError as err: - raise exit( - f"Duplicate option '{err.option}' in section" - f" '{err.section}' in file {config_file}" - ) + raise exit(f"Duplicate option '{err.option}' in section" + f" '{err.section}' in file {config_file}") except (ParsingError, Error): - raise exit( - f'Failed to parse configuration file {config_file}' - ) + raise exit(f'Failed to parse configuration file {config_file}') except (OSError, IOError) as e: print( 'WARNING: Unable to read configuration file' diff --git a/sos/policies/__init__.py b/sos/policies/__init__.py index f8845d9746..a9075478e6 100644 --- a/sos/policies/__init__.py +++ b/sos/policies/__init__.py @@ -373,15 +373,15 @@ def display_help(self, section): ) section.add_text( - "When SoS intializes most functions, for example %s and %s, one " - "of the first operations is to determine the correct policy to " - "load for the local system. Policies will determine the proper " + "When SoS intializes most functions, for example " + f"{bold('sos report')} and {bold('sos collect')}, one of the " + "first operations is to determine the correct policy to load " + "for the local system. Policies will determine the proper " "package manager to use, any applicable container runtime(s), and " "init systems so that SoS and report plugins can properly function" " for collections. Generally speaking a single policy will map to" " a single distribution; for example there are separate policies " "for Debian, Ubuntu, RHEL, and Fedora." - % (bold('sos report'), bold('sos collect')) ) section.add_text( diff --git a/sos/policies/auth/__init__.py b/sos/policies/auth/__init__.py index 78298242b3..6fe65a6fbd 100644 --- a/sos/policies/auth/__init__.py +++ b/sos/policies/auth/__init__.py @@ -196,12 +196,11 @@ def _use_refresh_token_grant(self, refresh_token=None): elif refresh_token_res.status_code == 400 and 'invalid' in\ refresh_token_res.json()['error']: - logger.warning( - "Problem while fetching the new tokens from refresh token" - f" grant - {refresh_token_res.status_code}" - f" {refresh_token_res.json()['error']}." - " New Device code will be requested !" - ) + logger.warning("Problem while fetching the new tokens from " + "refresh token grant - " + f"{refresh_token_res.status_code} " + f"{refresh_token_res.json()['error']}." + " New Device code will be requested !") self._use_device_code_grant() else: raise Exception( diff --git a/sos/policies/distros/__init__.py b/sos/policies/distros/__init__.py index 1cc8ae5a7e..485eeecb2a 100644 --- a/sos/policies/distros/__init__.py +++ b/sos/policies/distros/__init__.py @@ -317,7 +317,7 @@ def pre_work(self): else: self.commons['cmdlineopts'].case_id = input( _("Optionally, please enter the case id that you are " - "generating this report for [%s]: ") % caseid + f"generating this report for [{caseid}]: ") ) except KeyboardInterrupt: raise diff --git a/sos/policies/distros/redhat.py b/sos/policies/distros/redhat.py index 49d6a3f85c..5da3b1f880 100644 --- a/sos/policies/distros/redhat.py +++ b/sos/policies/distros/redhat.py @@ -299,8 +299,8 @@ def get_upload_url(self): self.ui_log.info("No case id provided, uploading to SFTP") return RH_SFTP_HOST else: - rh_case_api = "/support/v1/cases/%s/attachments" - return RH_API_HOST + rh_case_api % self.case_id + rh_case_api = f"/support/v1/cases/{self.case_id}/attachments" + return RH_API_HOST + rh_case_api def _get_upload_https_auth(self): str_auth = f"Bearer {self._device_token}" diff --git a/sos/policies/runtimes/crio.py b/sos/policies/runtimes/crio.py index 7614cdd6a9..47a5757a39 100644 --- a/sos/policies/runtimes/crio.py +++ b/sos/policies/runtimes/crio.py @@ -49,10 +49,8 @@ def get_images(self): """ images = [] if self.active: - out = sos_get_command_output( - f"{self.binary} images -o json", - chroot=self.policy.sysroot - ) + out = sos_get_command_output(f"{self.binary} images -o json", + chroot=self.policy.sysroot) if out['status'] == 0: out_json = json.loads(out["output"]) for image in out_json["images"]: @@ -88,10 +86,8 @@ def fmt_container_cmd(self, container, cmd, quotecmd): else: quoted_cmd = cmd container_id = self.get_container_by_name(container) - return ( - f"{self.run_cmd} {container_id} {quoted_cmd}" - if container_id is not None - else '' - ) + msg = (f"{self.run_cmd} {container_id} {quoted_cmd}" + ) if container_id is not None else '' + return msg # vim: set et ts=4 sw=4 : diff --git a/sos/presets/__init__.py b/sos/presets/__init__.py index 9708036fab..6101fc320d 100644 --- a/sos/presets/__init__.py +++ b/sos/presets/__init__.py @@ -53,20 +53,16 @@ def __str__(self): """Return a human readable string representation of this ``PresetDefaults`` object. """ - return ( - f"name={self.name} desc={self.desc}" - f" note={self.note} opts=({str(self.opts)})" - ) + return (f"name={self.name} desc={self.desc}" + f" note={self.note} opts=({str(self.opts)})") def __repr__(self): """Return a machine readable string representation of this ``PresetDefaults`` object. """ - return ( - f"PresetDefaults(name='{self.name}'" - f" desc='{self.desc}' note='{self.note}'" - f" opts=({repr(self.opts)})" - ) + return (f"PresetDefaults(name='{self.name}'" + f" desc='{self.desc}' note='{self.note}'" + f" opts=({repr(self.opts)})") def __init__(self, name="", desc="", note=None, opts=SoSOptions()): """Initialise a new ``PresetDefaults`` object with the specified diff --git a/sos/report/__init__.py b/sos/report/__init__.py index f57f270c8b..a514af404f 100644 --- a/sos/report/__init__.py +++ b/sos/report/__init__.py @@ -423,8 +423,8 @@ def display_help(cls, section): "For information on available options for report, see" f" {bold('sos report --help')} and {bold('man sos-report')}" ) - ssec.add_text("The following %s sections may be of interest:\n" - % bold('sos help')) + ssec.add_text(f"The following {bold('sos help')} sections may be of " + "interest:\n") help_lines = { 'report.plugins': 'Information on the plugin design of sos', 'report.plugins.$plugin': 'Information on a specific $plugin', @@ -436,7 +436,7 @@ def display_help(cls, section): ssec.add_text(helpln) def print_header(self): - print("\n%s\n" % _(f"sosreport (version {__version__})")) + print(f"\nsosreport (version {__version__}\n") def _get_hardware_devices(self): self.devices = { @@ -464,15 +464,14 @@ def _check_container_runtime(self): ) elif not self.policy.runtimes: msg = ("WARNING: No container runtimes are active, ignoring " - "option to set default runtime to '%s'\n" % crun) + f"option to set default runtime to '{crun}'\n") self.soslog.warning(msg) elif crun not in self.policy.runtimes.keys(): valid = ', '.join(p for p in self.policy.runtimes.keys() if p != 'default') - raise Exception( - f"Cannot use container runtime{crun}%s': no such " - f"runtime detected. Available runtimes: {valid}" - ) + raise Exception(f"Cannot use container runtime{crun}': no " + "such runtime detected. Available runtimes: " + f"{valid}") else: self.policy.runtimes['default'] = self.policy.runtimes[crun] self.soslog.info( @@ -824,7 +823,7 @@ def load_plugins(self): if not validate_plugin(plugin_class, experimental=self.opts.experimental): self.soslog.warning( - _("plugin %s does not validate, skipping") % plug) + _(f"plugin {plug} does not validate, skipping")) if self.opts.verbosity > 0: self._skip(plugin_class, _("does not validate")) continue @@ -864,12 +863,12 @@ def load_plugins(self): remaining_profiles.remove(i) self._load(plugin_class) except Exception as e: - self.soslog.warning(_("plugin %s does not install, " - "skipping: %s") % (plug, e)) + self.soslog.warning(_(f"plugin {plug} does not install, " + f"skipping: {e}")) self.handle_exception() if len(remaining_profiles) > 0: self.soslog.error(_("Unknown or inactive profile(s) provided:" - " %s") % ", ".join(remaining_profiles)) + f" {', '.join(remaining_profiles)}")) self.list_profiles() self._exit(1) @@ -918,8 +917,8 @@ def _set_tunables(self): if plugname in opts: for opt in opts[plugname]: if opt not in plug.options: - self.soslog.error('no such option "%s" for plugin ' - '(%s)' % (opt, plugname)) + self.soslog.error(f'no such option "{opt}" for ' + f'plugin ({plugname})') self._exit(1) try: plug.options[opt].set_value(opts[plugname][opt]) @@ -932,10 +931,8 @@ def _set_tunables(self): self._exit(1) del opts[plugname] for plugname in opts.keys(): - self.soslog.error( - 'WARNING: unable to set option for disabled ' - 'or non-existing plugin (%s).' % (plugname) - ) + self.soslog.error('WARNING: unable to set option for disabled ' + f'or non-existing plugin ({plugname}).') # in case we printed warnings above, visually intend them from # subsequent header text if opts.keys(): @@ -947,15 +944,14 @@ def _check_for_unknown_plugins(self): self.opts.enable_plugins): plugin_name = plugin.split(".")[0] if plugin_name not in self.plugin_names: - self.soslog.fatal( - 'a non-existing plugin (%s) was specified ' - 'in the command line.' % (plugin_name)) + self.soslog.fatal(f'a non-existing plugin ({plugin_name}) was ' + 'specified in the command line.') self._exit(1) for plugin in self.opts.skip_plugins: if plugin not in self.plugin_names: self.soslog.warning( f"Requested to skip non-existing plugin '{plugin}'." - ) + ) def _set_plugin_options(self): for plugin_name, plugin in self.loaded_plugins: @@ -1008,8 +1004,7 @@ def list_plugins(self): self.ui_log.info(_("The following plugins are currently enabled:")) self.ui_log.info("") for (plugname, plug) in self.loaded_plugins: - self.ui_log.info(" %-20s %s" % (plugname, - plug.get_description())) + self.ui_log.info(f" {plugname:<20} {plug.get_description()}") else: self.ui_log.info(_("No plugin enabled.")) self.ui_log.info("") @@ -1019,10 +1014,8 @@ def list_plugins(self): "disabled:")) self.ui_log.info("") for (plugname, plugclass, reason) in self.skipped_plugins: - self.ui_log.info(" %-20s %-14s %s" % ( - plugname, - reason, - plugclass.get_description())) + self.ui_log.info(f" {plugname:<20} {reason:<14} " + f"{plugclass.get_description()}") self.ui_log.info("") if self.all_options: @@ -1041,7 +1034,7 @@ def list_plugins(self): val = TIMEOUT_DEFAULT if opt.name == 'postproc': val = not self.opts.no_postproc - self.ui_log.info(" %-25s %-15s %s" % (opt.name, val, opt.desc)) + self.ui_log.info(f" {opt.name:<25} {val:<15} {opt.desc}") self.ui_log.info("") self.ui_log.info(_("The following plugin options are available:")) @@ -1061,12 +1054,8 @@ def list_plugins(self): if tmpopt is None: tmpopt = 0 - self.ui_log.info( - ( - " %-25s %-15s %s" - % (f"{opt.plugin}.{opt.name}", tmpopt, opt.desc) - ) - ) + self.ui_log.info(f" {opt.plugin}.{opt.name:<25} " + f"{tmpopt:<15} {opt.desc}") else: self.ui_log.info(_("No plugin options available.")) @@ -1111,14 +1100,13 @@ def list_presets(self): if not preset: continue preset = self.policy.find_preset(preset) - self.ui_log.info("%14s %s" % ("name:", preset.name)) - self.ui_log.info("%14s %s" % ("description:", preset.desc)) + self.ui_log.info(f"{'name:':<14} {preset.name}") + self.ui_log.info(f"{'description:':<14} {preset.desc}") if preset.note: - self.ui_log.info("%14s %s" % ("note:", preset.note)) - + self.ui_log.info(f"{'note:':<14} {preset.note}") if self.opts.verbosity > 0: args = preset.opts.to_args() - options_str = "%14s " % "options:" + options_str = f"{'options:':<14} " lines = _format_list(options_str, args, indent=True, sep=' ') for line in lines: self.ui_log.info(line) @@ -1149,8 +1137,8 @@ def add_preset(self, name, desc="", note=""): arg_index = self.cmdline.index("--add-preset") args = self.cmdline[0:arg_index] + self.cmdline[arg_index + 2:] - self.ui_log.info("Added preset '%s' with options %s\n" % - (name, " ".join(args))) + self.ui_log.info(f"Added preset '{name}' with options " + f"{' '.join(args)}\n") return True def del_preset(self, name): @@ -1170,7 +1158,7 @@ def del_preset(self, name): self.ui_log.error(str(e) + "\n") return False - self.ui_log.info("Deleted preset '%s'\n" % name) + self.ui_log.info(f"Deleted preset '{name}'\n") return True def batch(self): @@ -1196,7 +1184,7 @@ def _log_plugin_exception(self, plugin, method): logpath = os.path.join(self.logdir, plugin_err_log) self.soslog.error(f'{msg} "{plugin}.{method}()"') self.soslog.error(f'writing traceback to {logpath}') - self.archive.add_string("%s\n" % trace, logpath, mode='a') + self.archive.add_string(f"{trace}\n", logpath, mode='a') def prework(self): self.policy.pre_work() @@ -1246,9 +1234,8 @@ def setup(self): except (OSError, IOError) as e: if e.errno in fatal_fs_errors: self.ui_log.error("") - self.ui_log.error( - f" {e.strerror} while setting up plugins" - ) + self.ui_log.error(f" {e.strerror} while setting up " + "plugins") self.ui_log.error("") self._exit(1) self.handle_exception(plugname, "setup") @@ -1310,7 +1297,7 @@ def _collect_plugin(self, plugin): # log to ui_log.error to show the user, log to soslog.info # so that someone investigating the sos execution has it all # in one place, but without double notifying the user. - self.ui_log.error("\n %s\n" % msg) + self.ui_log.error(f"\n {msg}\n") self.soslog.info(msg) self.running_plugs.remove(plugin[1]) self.loaded_plugins[plugin[0]-1][1].set_timeout_hit() @@ -1346,11 +1333,8 @@ def collect_plugin(self, plugin): except Exception: return False numplugs = len(self.loaded_plugins) - status_line = " Starting %-5s %-15s %s" % ( - "%d/%d" % (count, numplugs), - plugname, - f"[Running: {' '.join(p for p in self.running_plugs)}]", - ) + status_line = (f" Starting {count}/{numplugs:<5} {plugname:<15} " + f"[Running: {' '.join(p for p in self.running_plugs)}]") self.ui_progress(status_line) try: plug.collect_plugin() @@ -1368,9 +1352,9 @@ def collect_plugin(self, plugin): status = '' if (len(self.pluglist) <= int(self.opts.threads) and self.running_plugs): - status = " Finishing plugins %-12s %s" % ( - " ", - f"[Running: {' '.join(p for p in self.running_plugs)}]", + status = ( + f" Finishing plugins {' ':<12} " + f"[Running: {' '.join(p for p in self.running_plugs)}]" ) if not self.running_plugs and not self.pluglist: status = "\n Finished running plugins" @@ -1382,10 +1366,10 @@ def collect_plugin(self, plugin): pass except (OSError, IOError) as e: if e.errno in fatal_fs_errors: - self.ui_log.error("\n %s while collecting plugin data" - % e.strerror) - self.ui_log.error(" Data collected still available at %s\n" - % self.tmpdir) + self.ui_log.error(f"\n {e.strerror} while collecting plugin " + "data") + self.ui_log.error(" Data collected still available at " + f"{self.tmpdir}\n") os._exit(1) self.handle_exception(plugname, "collect") except Exception: @@ -1394,9 +1378,9 @@ def collect_plugin(self, plugin): def ui_progress(self, status_line): if self.opts.verbosity == 0 and not self.opts.batch: - status_line = "\r%s" % status_line.ljust(90) + status_line = f"\r{status_line.ljust(90)}" else: - status_line = "%s\n" % status_line + status_line = f"{status_line}\n" if not self.opts.quiet: sys.stdout.write(status_line) sys.stdout.flush() @@ -1404,19 +1388,12 @@ def ui_progress(self, status_line): def collect_env_vars(self): if not self.env_vars: return - env = ( - '\n'.join( - [ - f"{name}={val}" - for (name, val) in [ - (name, f'{os.environ.get(name)}') - for name in self.env_vars - if os.environ.get(name) is not None - ] - ] - ) - + '\n' - ) + env = '\n'.join([ + f"{name}={val}" + for (name, val) in + [(name, f'{os.environ.get(name)}') for name in self.env_vars if + os.environ.get(name) is not None] + ]) + '\n' self.archive.add_string(env, 'environment') def generate_reports(self): @@ -1469,9 +1446,8 @@ def generate_reports(self): except (OSError, IOError) as e: if e.errno in fatal_fs_errors: self.ui_log.error("") - self.ui_log.error( - f" {e.strerror} while writing {type_} report" - ) + self.ui_log.error(f" {e.strerror} while writing {type_} " + "report") self.ui_log.error("") self._exit(1) @@ -1481,15 +1457,13 @@ def postproc(self): if plug.get_option('postproc'): plug.postproc() else: - self.soslog.info( - f"Skipping postproc for plugin {plugname}" - ) + self.soslog.info("Skipping postproc for plugin " + f"{plugname}") except (OSError, IOError) as e: if e.errno in fatal_fs_errors: self.ui_log.error("") - self.ui_log.error( - f" {e.strerror} while post-processing plugin data" - ) + self.ui_log.error(f" {e.strerror} while post-processing " + "plugin data") self.ui_log.error("") self._exit(1) self.handle_exception(plugname, "postproc") @@ -1584,11 +1558,10 @@ def final_work(self): _sum = get_human_readable(sum(self.estimated_plugsizes.values())) self.ui_log.info("Estimated disk space requirement for whole " - "uncompressed sos report directory: %s" % _sum) + f"uncompressed sos report directory: {_sum}") bigplugins = sorted(self.estimated_plugsizes.items(), key=lambda x: x[1], reverse=True)[:5] - bp_out = ", ".join("%s: %s" % - (p, get_human_readable(v, precision=0)) + bp_out = ", ".join(f"{p}: {get_human_readable(v, precision=0)}" for p, v in bigplugins) self.ui_log.info(f"Five biggest plugins: {bp_out}") self.ui_log.info("") @@ -1612,12 +1585,8 @@ def final_work(self): self.opts.compression_type) except (OSError, IOError) as e: print("") - print( - _( - f" {e.strerror} while finalizing archive" - f" {self.archive.get_archive_path()}" - ) - ) + print(_(f" {e.strerror} while finalizing archive" + f" {self.archive.get_archive_path()}")) print("") if e.errno in fatal_fs_errors: self._exit(1) @@ -1799,22 +1768,18 @@ def compile_tags(ent, key='filepath'): def _merge_preset_options(self): # Log command line options - msg = "[%s:%s] executing 'sos %s'" - self.soslog.info(msg % (__name__, "setup", " ".join(self.cmdline))) + msg = f"[{__name__}:setup] executing 'sos {' '.join(self.cmdline)}'" + self.soslog.info(msg) # Log active preset defaults preset_args = self.preset.opts.to_args() - msg = ( - f"""[{__name__}:{"setup"}] using '{self.preset.name}'""" - f""" preset defaults ({" ".join(preset_args)})""" - ) + msg = (f"""[{__name__}:{"setup"}] using '{self.preset.name}'""" + f""" preset defaults ({" ".join(preset_args)})""") self.soslog.info(msg) # Log effective options after applying preset defaults - self.soslog.info( - f'[{__name__}:{"setup"}] effective options now:' - f' {" ".join(self.opts.to_args())}' - ) + self.soslog.info(f'[{__name__}:{"setup"}] effective options now:' + f' {" ".join(self.opts.to_args())}') def execute(self): try: diff --git a/sos/report/plugins/__init__.py b/sos/report/plugins/__init__.py index 2d0b532247..171d671db9 100644 --- a/sos/report/plugins/__init__.py +++ b/sos/report/plugins/__init__.py @@ -133,28 +133,30 @@ def __str(self, quote=False, prefix="", suffix=""): """Return a string representation of this SoSPredicate with optional prefix, suffix and value quoting. """ - quotes = '"%s"' + quotes = '"{}"' pstr = f"dry_run={self.dry_run}, " - kmods = self.kmods - kmods = [quotes % k for k in kmods] if quote else kmods - pstr += f'kmods=[{",".join(kmods)}], ' - - services = self.services - services = [quotes % s for s in services] if quote else services - pstr += f'services=[{",".join(services)}], ' - - pkgs = self.packages - pkgs = [quotes % p for p in pkgs] if quote else pkgs - pstr += f'packages=[{",".join(pkgs)}], ' - - cmdoutputs = [ - "{ %s: %s, %s: %s }" % (quotes % "cmd", - quotes % cmdoutput['cmd'], - quotes % "output", - quotes % cmdoutput['output']) - for cmdoutput in self.cmd_outputs - ] + kmods = [ + quotes.format(k) for k in self.kmods + ] if quote else self.kmods + pstr += f'kmods={[",".join(kmods)]}, ' + + services = [ + quotes.format(s) for s in self.services + ] if quote else self.services + pstr += f'services={[",".join(services)]}, ' + + pkgs = [ + quotes.format(p) for p in self.packages + ] if quote else self.packages + pstr += f'packages={[",".join(pkgs)]}, ' + + cmdoutputs = [f"{{ {quotes.format('cmd')}: " + f"{quotes.format(cmdoutput['cmd'])}, " + f"{quotes.format('output')}: " + f"{quotes.format(cmdoutput['output'])} }}" + for cmdoutput in self.cmd_outputs + ] pstr += f'cmdoutputs=[{",".join(cmdoutputs)}], ' arches = self.arch @@ -296,12 +298,11 @@ def _report_failed(self): evaluation """ msg = '' - _substr = "required %s missing: %s." for key, val in self._failed.items(): if not val: continue val = set(val) - msg += _substr % (key, ', '.join(v for v in val)) + msg += f"required {key} missing: {', '.join(v for v in val)}." return msg def _report_forbidden(self): @@ -309,12 +310,11 @@ def _report_forbidden(self): which caused the predicate to fail """ msg = '' - _substr = "forbidden %s '%s' found." for key, val in self._forbidden.items(): if not val: continue val = set(val) - msg += _substr % (key, ', '.join(v for v in val)) + msg += f"forbidden {key} '{', '.join(v for v in val)}' found." return msg def report_failure(self): @@ -390,8 +390,8 @@ def __init__(self, **kwargs): def __str__(self): """Return a human readable string representation of this SoSCommand """ - return ', '.join("%s=%r" % (param, val) for (param, val) in - sorted(self.__dict__.items())) + return ', '.join(f"{param}={val!r}" + for param, val in sorted(self.__dict__.items())) class PluginOpt(): @@ -443,7 +443,7 @@ def __init__(self, name='undefined', default=None, desc='', long_desc='', def __str__(self): items = [ f'name={self.name}', - 'desc=\'%s\'' % self.desc, + f'desc=\'{self.desc}\'', f'value={self.value}', f'default={self.default}', ] @@ -633,10 +633,8 @@ def set_default_cmd_environment(self, env_vars): "Environment variables for Plugin must be specified by dict" ) self.default_environment = env_vars - self._log_debug( - "Default environment for all commands now set to" - f" {self.default_environment}" - ) + self._log_debug("Default environment for all commands now set to" + f" {self.default_environment}") def add_default_cmd_environment(self, env_vars): """ @@ -777,9 +775,8 @@ def display_help(cls, section): @classmethod def display_plugin_help(cls, section): from sos.help import TERMSIZE - section.set_title( - f"{cls.plugin_name.title()} Plugin Information - {cls.short_desc}" - ) + section.set_title(f"{cls.plugin_name.title()} Plugin Information - " + f"{cls.short_desc}") missing = '\nDetailed information is not available for this plugin.\n' # Concatenate the docstrings of distro-specific plugins with their @@ -794,7 +791,7 @@ def display_plugin_help(cls, section): except Exception: _doc = None - section.add_text('\n %s' % _doc if _doc else missing) + section.add_text(f"\n {_doc or missing}") if not any([cls.packages, cls.commands, cls.files, cls.kernel_mods, cls.services, cls.containers]): @@ -823,8 +820,8 @@ def display_plugin_help(cls, section): if hasattr(cls, 'verify_packages'): section.add_text( - "\nVerfies packages (when using --verify): %s" - % ', '.join(pkg for pkg in cls.verify_packages), + f"\nVerifies packages (when using --verify): " + f"{', '.join(pkg for pkg in cls.verify_packages)}", newline=False, ) @@ -880,13 +877,13 @@ def display_plugin_help(cls, section): def display_self_help(cls, section): section.set_title("SoS Plugin Detailed Help") section.add_text( - "Plugins are what define what collections occur for a given %s " - "execution. Plugins are generally representative of a single " - "system component (e.g. kernel), package (e.g. podman), or similar" - " construct. Plugins will typically specify multiple files or " - "directories to copy, as well as commands to execute and collect " - "the output of for further analysis." - % bold('sos report') + "Plugins are what define what collections occur for a given " + f"{bold('sos report')} execution. Plugins are generally " + "representative of a single system component (e.g. kernel), " + "package (e.g. podman), or similar construct. Plugins will " + "typically specify multiple files or directories to copy, as " + "well as commands to execute and collect the output of for " + "further analysis." ) subsec = section.add_section('Plugin Enablement') @@ -896,30 +893,28 @@ def display_self_help(cls, section): 'existing, a kernel module being loaded, etc...' ) subsec.add_text( - "Plugins may also be enabled or disabled by name using the %s or " - "%s options respectively." - % (bold('-e $name'), bold('-n $name')) + "Plugins may also be enabled or disabled by name using the " + f"{bold('-e $name')} or {bold('-n $name')} options respectively." ) subsec.add_text( "Certain plugins may only be available for specific distributions " "or may behave differently on different distributions based on how" - " the component for that plugin is installed or how it operates." - " When using %s, help will be displayed for the version of the " - "plugin appropriate for your distribution." - % bold('sos help report.plugins.$plugin') + " the component for that plugin is installed or how it operates. " + f"When using {bold('sos help report.plugins.$plugin')}, help will" + " be displayed for the version of the plugin appropriate for your" + " distribution." ) optsec = section.add_section('Using Plugin Options') optsec.add_text( "Many plugins support additional options to enable/disable or in " "some other way modify the collections it makes. Plugin options " - "are set using the %s syntax. Options that are on/off toggles " - "may exclude setting a value, which will be interpreted as " - "enabling that option.\n\nSee specific plugin help sections " - "or %s for more information on these options" - % (bold('-k $plugin_name.$option_name=$value'), - bold('sos report -l')) + f"are set using the {bold('-k $plugin_name.$option_name=$value')} " + "syntax. Options that are on/off toggles may exclude setting a " + "value, which will be interpreted as enabling that option.\n\n" + f"See specific plugin help sections or {bold('sos report -l')} for" + " more information on these options" ) seealso = section.add_section('See Also') @@ -929,16 +924,17 @@ def display_self_help(cls, section): } seealso.add_text( "Additional relevant information may be available in these " - "help sections:\n\n%s" % "\n".join( + "help sections:\n\n" + + "\n".join( f"{' ':>8}{sec:<30}{desc:<30}" for sec, desc in _also.items() - ), newline=False + ), + newline=False ) def _format_msg(self, msg): - return ( - f"[plugin:{self.name()}] {msg.encode('utf-8', 'replace').decode()}" - ) + return (f"[plugin:{self.name()}] " + f"{msg.encode('utf-8', 'replace').decode()}") def _log_error(self, msg): self.soslog.error(self._format_msg(msg)) @@ -1169,9 +1165,8 @@ def do_cmd_private_sub(self, cmd, desc=""): if not self.executed_commands: return 0 - self._log_debug( - f"Scrubbing certs and keys for commands matching {cmd}" - ) + self._log_debug("Scrubbing certs and keys for commands matching " + f"{cmd}") replace = f"{_cert_replace} {desc}" if desc else _cert_replace @@ -1217,7 +1212,7 @@ def do_cmd_output_sub(self, cmd, regexp, subst): continue if called['binary'] == 'yes': self._log_warn("Cannot apply regex substitution to binary" - " output: '%s'" % called['exe']) + F" output: '{called['exe']}'") continue if fnmatch.fnmatch(called['cmd'], globstr): path = os.path.join(self.commons['cmddir'], called['file']) @@ -1229,8 +1224,8 @@ def do_cmd_output_sub(self, cmd, regexp, subst): self.archive.add_string(result, path) except Exception as e: - msg = "regex substitution failed for '%s' with: '%s'" - self._log_error(msg % (called['exe'], e)) + self._log_error(f"regex substitution failed for '{called['exe']}'" + f" with: '{e}'") replacements = None return replacements @@ -1281,11 +1276,11 @@ def do_file_sub(self, srcpath, regexp, subst): try: path = self._get_dest_for_srcpath(srcpath) self._log_debug(f"substituting scrpath '{srcpath}'") - self._log_debug("substituting '%s' for '%s' in '%s'" - % (subst, - regexp.pattern if hasattr(regexp, "pattern") - else regexp, - path)) + self._log_debug( + f"substituting '{subst}' for " + f"'{regexp.pattern if hasattr(regexp, 'pattern') else regexp}'" + f" in '{path}'" + ) if not path: return 0 replacements = self.archive.do_file_sub(path, regexp, subst) @@ -1293,11 +1288,11 @@ def do_file_sub(self, srcpath, regexp, subst): # if trying to regexp a nonexisting file, dont log it as an # error to stdout if e.errno == errno.ENOENT: - msg = "file '%s' not collected, substitution skipped" - self._log_debug(msg % path) + self._log_debug(f"file '{path}' not collected, substitution " + "skipped") else: - msg = "regex substitution failed for '%s' with: '%s'" - self._log_error(msg % (path, e)) + self._log_error(f"regex substitution failed for '{path}' " + f"with: '{e}'") replacements = 0 return replacements @@ -1347,10 +1342,8 @@ def _copy_symlink(self, srcpath): else: reldest = linkdest - self._log_debug( - f"copying link '{srcpath}' pointing to '{linkdest}' with" - f" isdir={self.path_isdir(absdest)}" - ) + self._log_debug(f"copying link '{srcpath}' pointing to '{linkdest}' " + f"with isdir={self.path_isdir(absdest)}") dstpath = self.strip_sysroot(srcpath) # use the relative target path in the tarball @@ -1371,8 +1364,8 @@ def _copy_symlink(self, srcpath): os.stat(absdest) except OSError as e: if e.errno == 40: - self._log_debug("link '%s' is part of a file system " - "loop, skipping target..." % dstpath) + self._log_debug(f"link '{dstpath}' is part of a file system " + "loop, skipping target...") return # copy the symlink target translating relative targets @@ -1387,16 +1380,14 @@ def _copy_symlink(self, srcpath): self.policy._in_container) self._do_copy_path(absdest, force=force) else: - self._log_debug( - f"link '{linkdest}' points to itself, skipping target..." - ) + self._log_debug(f"link '{linkdest}' points to itself, skipping " + "target...") def _copy_dir(self, srcpath): try: for name in self.listdir(srcpath): - self._log_debug( - f"recursively adding '{name}' from '{srcpath}'" - ) + self._log_debug(f"recursively adding '{name}' from " + f"'{srcpath}'") path = os.path.join(srcpath, name) self._do_copy_path(path) except OSError as e: @@ -1689,8 +1680,8 @@ def add_copy_spec(self, copyspecs, sizelimit=None, maxage=None, configfile_pattern = re.compile(f'^{self.path_join("etc")}/*') if not self.test_predicate(pred=pred): - self._log_info("skipped copy spec '%s' due to predicate (%s)" % - (copyspecs, self.get_predicate(pred=pred))) + self._log_info(f"skipped copy spec '{copyspecs}' due to predicate" + f" ({self.get_predicate(pred=pred)})") return None if sizelimit is None: @@ -1768,16 +1759,15 @@ def get_filename_tag(fname): _tail = True except ValueError: self._log_info( - "unable to determine size of '%s' in " - "container '%s'. Skipping collection." - % (copyspec, con) + f"unable to determine size of '{copyspec}'" + f" in container '{con}'. Skipping" + " collection." ) continue else: self._log_debug( - "stat of '%s' in container '%s' failed, " - "skipping collection: %s" - % (copyspec, con, ret['output']) + f"stat of '{copyspec}' in container '{con}' " + f"failed, skipping collection: {ret['output']}" ) continue self.container_copy_paths.append( @@ -1860,14 +1850,14 @@ def time_filter(path): if tailit: if file_is_binary(_file): self._log_info( - "File '%s' is over size limit and is binary. " - "Skipping collection." % _file + f"File '{_file}' is over size limit and is " + "binary. Skipping collection." ) continue self._log_info( - "File '%s' is over size limit, will instead tail " - "the file during collection phase." % _file + f"File '{_file}' is over size limit, will instead " + "tail the file during collection phase." ) add_size = sizelimit + file_size - current_size self._tail_files_list.append((_file, add_size)) @@ -1955,21 +1945,15 @@ def add_device_cmd(self, cmds, devices, timeout=None, sizelimit=None, if isinstance(whitelist, str): whitelist = [whitelist] - _devs = [ - d - for d in _devs - if any(re.match(f"(.*)?{wl}", d) for wl in whitelist) - ] + _devs = [d for d in _devs if + any(re.match(f"(.*)?{wl}", d) for wl in whitelist)] if blacklist: if isinstance(blacklist, str): blacklist = [blacklist] - _devs = [ - d - for d in _devs - if not any(re.match(f"(.*)?{bl}", d) for bl in blacklist) - ] + _devs = [d for d in _devs if not + any(re.match(f"(.*)?{bl}", d) for bl in blacklist)] _dev_tags.extend(tags) self._add_device_cmd(cmds, _devs, timeout=timeout, @@ -2120,9 +2104,9 @@ def add_cmd_output(self, cmds, suggest_filename=None, container_cmd = (ocmd, container) cmd = self.fmt_container_cmd(container, cmd) if not cmd: - self._log_debug("Skipping command '%s' as the requested " - "container '%s' does not exist." - % (ocmd, container)) + self._log_debug(f"Skipping command '{ocmd}' as the " + f"requested container '{ocmd, }' does not " + "exist.") continue self._add_cmd_output(cmd=cmd, suggest_filename=suggest_filename, root_symlink=root_symlink, timeout=timeout, @@ -2274,8 +2258,8 @@ def add_string_as_file(self, content, filename, pred=None, plug_dir=False, """ if not self.test_predicate(cmd=False, pred=pred): - self._log_info("skipped string due to predicate (%s)" % - (self.get_predicate(pred=pred))) + self._log_info("skipped string due to predicate " + f"({self.get_predicate(pred=pred)})") return sos_dir = 'sos_commands' if plug_dir else 'sos_strings' @@ -2378,11 +2362,11 @@ def _collect_cmd_output(self, cmd, suggest_filename=None, run_time = end - start if result['status'] == 124: - warn = "command '%s' timed out after %ds" % (cmd, timeout) + warn = f"command '{cmd}' timed out after {timeout}s" self._log_warn(warn) if to_file: msg = (" - output up until the timeout may be available at " - "%s" % outfn) + f"{outfn}") self._log_debug(f"{warn}{msg}") manifest_cmd = { @@ -2404,9 +2388,8 @@ def _collect_cmd_output(self, cmd, suggest_filename=None, # automatically retry chroot'ed commands in the host namespace if root and root != '/': if self.commons['cmdlineopts'].chroot != 'always': - self._log_info("command '%s' not found in %s - " - "re-trying in host root" - % (cmd.split()[0], root)) + self._log_info(f"command '{cmd.split()[0]}' not found in " + f"{root} - re-trying in host root") result = sos_get_command_output( cmd, timeout=timeout, chroot=False, chdir=runat, env=env, binary=binary, sizelimit=sizelimit, @@ -2421,15 +2404,12 @@ def _collect_cmd_output(self, cmd, suggest_filename=None, self.manifest.commands.append(manifest_cmd) return result - self._log_debug( - f"collected output of '{cmd.split()[0]}' in" - f" {run_time} (changes={changes})" - ) + self._log_debug(f"collected output of '{cmd.split()[0]}' in" + f" {run_time} (changes={changes})") if result['truncated']: - self._log_info( - f"collected output of '{cmd.split()[0]}' was truncated" - ) + self._log_info(f"collected output of '{cmd.split()[0]}' was " + "truncated") linkfn = outfn outfn = outfn.replace('sos_commands', 'sos_strings') + '.tailed' @@ -2604,15 +2584,14 @@ def exec_cmd(self, cmd, timeout=None, stderr=True, chroot=True, if container: if self._get_container_runtime() is None: - self._log_info("Cannot run cmd '%s' in container %s: no " - "runtime detected on host." % (cmd, container)) + self._log_info(f"Cannot run cmd '%s' in container {cmd}: no " + "runtime detected on host.") return _default if self.container_exists(container): cmd = self.fmt_container_cmd(container, cmd, quotecmd) else: - self._log_info("Cannot run cmd '%s' in container %s: no such " - "container is running." % (cmd, container)) - + self._log_info(f"Cannot run cmd '%s' in container {cmd}: no " + "such container is running.") return sos_get_command_output(cmd, timeout=timeout, chroot=root, chdir=runat, binary=binary, env=_env, foreground=foreground, stderr=stderr) @@ -2943,13 +2922,13 @@ def add_journal(self, units=None, boot=None, since=None, until=None, :type sizelimit: ``int`` """ journal_cmd = "journalctl --no-pager " - unit_opt = " --unit %s" - boot_opt = " --boot %s" - since_opt = " --since '%s'" - until_opt = " --until %s" - lines_opt = " --lines %s" - output_opt = " --output %s" - identifier_opt = " --identifier %s" + unit_opt = " --unit {}" + boot_opt = " --boot {}" + since_opt = " --since '{}'" + until_opt = " --until {}" + lines_opt = " --lines {}" + output_opt = " --output {}" + identifier_opt = " --identifier {}" catalog_opt = " --catalog" if sizelimit == 0 or self.get_option("all_logs"): @@ -2968,11 +2947,11 @@ def add_journal(self, units=None, boot=None, since=None, until=None, if units: for unit in units: - journal_cmd += unit_opt % unit + journal_cmd += unit_opt.format(unit) tags.append(f"journal_{unit}") if identifier: - journal_cmd += identifier_opt % identifier + journal_cmd += identifier_opt.format(identifier) if catalog: journal_cmd += catalog_opt @@ -2985,19 +2964,19 @@ def add_journal(self, units=None, boot=None, since=None, until=None, boot = "" if boot == "last": boot = "-1" - journal_cmd += boot_opt % boot + journal_cmd += boot_opt.format(boot) if since: - journal_cmd += since_opt % since + journal_cmd += since_opt.format(since) if until: - journal_cmd += until_opt % until + journal_cmd += until_opt.format(until) if lines: - journal_cmd += lines_opt % lines + journal_cmd += lines_opt.format(lines) if output: - journal_cmd += output_opt % output + journal_cmd += output_opt.format(output) self._log_debug(f"collecting journal: {journal_cmd}") self._add_cmd_output(cmd=journal_cmd, timeout=timeout, @@ -3093,10 +3072,8 @@ def _collect_container_copy_specs(self): self.archive.add_string(cpret['output'], arcdest) self._add_container_file_to_manifest(con, path, arcdest, tags) else: - self._log_info( - f"error copying '{path}' from container '{con}':" - f" {cpret['output']}" - ) + self._log_info(f"error copying '{path}' from container " + f"'{con}': {cpret['output']}") def _collect_cmds(self): self.collect_cmds.sort(key=lambda x: x.priority) @@ -3209,7 +3186,7 @@ def collect_plugin(self): self._collect_cmds() self._collect_manual() fields = (self.name(), time() - start) - self._log_debug("collected plugin '%s' in %s" % fields) + self._log_debug(f"collected plugin '{fields[0]}' in {fields[1]}") def get_description(self): """This function will return the description for the plugin""" @@ -3513,8 +3490,7 @@ def filter_namespaces(self, ns_list, ns_pattern=None, ns_max=None): if ns_max: if len(out_ns) == ns_max: self._log_warn("Limiting namespace iteration " - "to first %s namespaces found" - % ns_max) + f"to first {ns_max} namespaces found") break return out_ns @@ -3592,7 +3568,7 @@ def _get_scls(self): def convert_cmd_scl(self, scl, cmd): """wrapping command in "scl enable" call """ - scl_cmd = "scl enable %s \"%s\"" % (scl, cmd) + scl_cmd = f"scl enable {scl} \"{cmd}\"" return scl_cmd # config files for Software Collections are under /etc/${prefix}/${scl} and @@ -3603,9 +3579,8 @@ def convert_copyspec_scl(self, scl, copyspec): scl_prefix = self.policy.get_default_scl_prefix() for rootdir in ['etc', 'var']: p = re.compile(f'^/{rootdir}/') - copyspec = os.path.abspath( - p.sub(f"/{rootdir}/{scl_prefix}/{scl}/", copyspec) - ) + copyspec = os.path.abspath(p.sub(f"/{rootdir}/{scl_prefix}/{scl}/", + copyspec)) return copyspec def add_copy_spec_scl(self, scl, copyspecs): diff --git a/sos/report/plugins/abrt.py b/sos/report/plugins/abrt.py index f95de82208..8a9e06517e 100644 --- a/sos/report/plugins/abrt.py +++ b/sos/report/plugins/abrt.py @@ -32,9 +32,8 @@ def setup(self): if self.get_option("detailed") and abrt_list['status'] == 0: for line in abrt_list["output"].splitlines(): if line.startswith("Directory"): - self.add_cmd_output( - f"abrt-cli info -d '{line.split()[1]}'" - ) + self.add_cmd_output("abrt-cli info -d " + f"'{line.split()[1]}'") self.add_copy_spec([ "/etc/abrt/abrt.conf", diff --git a/sos/report/plugins/alternatives.py b/sos/report/plugins/alternatives.py index 5197d94d9d..33a016980b 100644 --- a/sos/report/plugins/alternatives.py +++ b/sos/report/plugins/alternatives.py @@ -35,8 +35,9 @@ def setup(self): alt = line.split()[0] if alt not in ignore: alts.append(alt) - disp_cmd = f'{self.alternatives_cmd} --display {"%s"}' - self.add_cmd_output([disp_cmd % alt for alt in alts]) + self.add_cmd_output([ + f'{self.alternatives_cmd} --display {alt}' for alt in alts + ]) class RedHatAlternatives(Alternatives, RedHatPlugin): @@ -45,7 +46,7 @@ class RedHatAlternatives(Alternatives, RedHatPlugin): commands = ('alternatives',) alternatives_cmd = 'alternatives' - alternatives_list = '%s --list' % alternatives_cmd + alternatives_list = f'{alternatives_cmd} --list' def setup(self): @@ -64,7 +65,7 @@ class UbuntuAlternatives(Alternatives, UbuntuPlugin): commands = ('update-alternatives',) alternatives_cmd = 'update-alternatives' - alternatives_list = '%s --get-selections' % alternatives_cmd + alternatives_list = f'{alternatives_cmd} --get-selections' def setup(self): diff --git a/sos/report/plugins/azure.py b/sos/report/plugins/azure.py index f59cd0e6b8..a85c2fdc0b 100644 --- a/sos/report/plugins/azure.py +++ b/sos/report/plugins/azure.py @@ -54,11 +54,11 @@ def setup(self): if self.path_isfile('/etc/yum.repos.d/rh-cloud.repo'): curl_cmd = ('curl -s -m 5 -vvv ' - 'https://rhui-%s.microsoft.com/pulp/repos/%s') + 'https://rhui-{}.microsoft.com/pulp/repos/{}') self.add_cmd_output([ - curl_cmd % ('1', 'microsoft-azure-rhel7'), - curl_cmd % ('2', 'microsoft-azure-rhel7'), - curl_cmd % ('3', 'microsoft-azure-rhel7') + curl_cmd.format('1', 'microsoft-azure-rhel7'), + curl_cmd.format('2', 'microsoft-azure-rhel7'), + curl_cmd.format('3', 'microsoft-azure-rhel7') ]) crt_path = '/etc/pki/rhui/product/content.crt' diff --git a/sos/report/plugins/buildah.py b/sos/report/plugins/buildah.py index d2ec2ff662..82b406a8d0 100644 --- a/sos/report/plugins/buildah.py +++ b/sos/report/plugins/buildah.py @@ -41,18 +41,14 @@ def make_chowdah(aurdah): for containah in containahs['auutput'].splitlines(): # obligatory Tom Brady goat = containah.split()[-1] - self.add_cmd_output( - f'buildah inspect -t container {goat}', - subdir='containers' - ) + self.add_cmd_output(f'buildah inspect -t container {goat}', + subdir='containers') pitchez = make_chowdah('buildah images -n') if pitchez['is_wicked_pissah']: for pitchah in pitchez['auutput'].splitlines(): brady = pitchah.split()[1] - self.add_cmd_output( - f"buildah inspect -t image {brady}", - subdir="images" - ) + self.add_cmd_output(f"buildah inspect -t image {brady}", + subdir="images") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/candlepin.py b/sos/report/plugins/candlepin.py index 9c14ea2d63..098400a42f 100644 --- a/sos/report/plugins/candlepin.py +++ b/sos/report/plugins/candlepin.py @@ -118,9 +118,9 @@ def build_query_cmd(self, query, csv=False): a large amount of quoting in sos logs referencing the command being run """ csvformat = "-A -F , -X" if csv else "" - _dbcmd = "psql --no-password -h %s -p 5432 -U candlepin \ - -d candlepin %s -c %s" - return _dbcmd % (self.dbhost, csvformat, quote(query)) + _dbcmd = (f"psql --no-password -h {self.dbhost} -p 5432 -U candlepin" + f" -d candlepin {csvformat} -c {quote(query)}") + return _dbcmd def postproc(self): reg = r"(((.*)(pass|token|secret)(.*))=)(.*)" @@ -130,7 +130,7 @@ def postproc(self): self.do_file_sub("/var/log/candlepin/cpdb.log", cpdbreg, repl) for key in ["trustStorePassword", "keyStorePassword"]: self.do_file_sub("/etc/candlepin/broker.xml", - r"(%s)=(\w*)([;<])" % key, + rf"({key})=(\w*)([;<])", r"\1=********\3") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/canonical_livepatch_onprem.py b/sos/report/plugins/canonical_livepatch_onprem.py index 2bf82b84c0..da3d85bbe5 100644 --- a/sos/report/plugins/canonical_livepatch_onprem.py +++ b/sos/report/plugins/canonical_livepatch_onprem.py @@ -32,7 +32,7 @@ def postproc(self): ] # Redact simple yaml style "key: value". - keys_regex = r"(^(-|\s)*(%s)\s*:\s*)(.*)" % "|".join(protect_keys) + keys_regex = rf"(^(-|\s)*({'|'.join(protect_keys)})\s*:\s*)(.*)" sub_regex = r"\1*********" self.do_path_regex_sub(onprem_conf, keys_regex, sub_regex) diff --git a/sos/report/plugins/ceph_common.py b/sos/report/plugins/ceph_common.py index 444e0f52ba..32aea225fa 100644 --- a/sos/report/plugins/ceph_common.py +++ b/sos/report/plugins/ceph_common.py @@ -31,9 +31,9 @@ class Ceph_Common(Plugin, RedHatPlugin, UbuntuPlugin): services = ( 'ceph-nfs@pacemaker', - 'ceph-mds@%s' % ceph_hostname, - 'ceph-mon@%s' % ceph_hostname, - 'ceph-mgr@%s' % ceph_hostname, + f'ceph-mds@{ceph_hostname}', + f'ceph-mon@{ceph_hostname}', + f'ceph-mgr@{ceph_hostname}', 'ceph-radosgw@*', 'ceph-osd@*' ) diff --git a/sos/report/plugins/ceph_mds.py b/sos/report/plugins/ceph_mds.py index 709af8ad0f..486ae2b42c 100644 --- a/sos/report/plugins/ceph_mds.py +++ b/sos/report/plugins/ceph_mds.py @@ -87,14 +87,11 @@ def setup(self): except Exception: cname = None - self.add_cmd_output( - [ - f"ceph daemon {mdsid} {cmd}" - for mdsid in mds_ids - for cmd in ceph_cmds - ], - container=cname, - ) + self.add_cmd_output([ + f"ceph daemon {mdsid} {cmd}" + for mdsid in mds_ids + for cmd in ceph_cmds + ], container=cname) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/collectd.py b/sos/report/plugins/collectd.py index 33cbfd1eb6..b9d8e14497 100644 --- a/sos/report/plugins/collectd.py +++ b/sos/report/plugins/collectd.py @@ -39,9 +39,8 @@ def setup(self): with open(self.path_join("/etc/collectd.conf"), 'r') as f: for line in f: if p.match(line): - self.add_alert( - f"Active Plugin found: {line.split()[-1]}" - ) + self.add_alert("Active Plugin found: " + f"{line.split()[-1]}") except IOError as e: self._log_warn(f"could not open /etc/collectd.conf: {e}") @@ -52,7 +51,7 @@ def postproc(self): "Password", "User", "[<]*URL", "Address" ] - regexp = r"(^[#]*\s*(%s)\s* \s*)(.*)" % "|".join(protect_keys) + regexp = rf"(^[#]*\s*({'|'.join(protect_keys)})\s* \s*)(.*)" self.do_path_regex_sub( "/etc/collectd.d/*.conf", regexp, r'\1"*********"' diff --git a/sos/report/plugins/console.py b/sos/report/plugins/console.py index 1611e8e0fe..7ef7ac5875 100644 --- a/sos/report/plugins/console.py +++ b/sos/report/plugins/console.py @@ -22,8 +22,8 @@ def setup(self): self.add_copy_spec("/proc/consoles") self.add_cmd_output("fgconsole") - self.add_cmd_output( - [f"kbdinfo -C {tty} gkbled" for tty in glob("/dev/tty[0-8]")] - ) + self.add_cmd_output([ + f"kbdinfo -C {tty} gkbled" for tty in glob("/dev/tty[0-8]") + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/containers_common.py b/sos/report/plugins/containers_common.py index 0419cafc0d..6dee9bf22c 100644 --- a/sos/report/plugins/containers_common.py +++ b/sos/report/plugins/containers_common.py @@ -70,12 +70,9 @@ def setup(self): # collect user-status self.add_cmd_output(f'loginctl user-status {user}') # collect the user's related commands - self.add_cmd_output( - [ - f'machinectl -q shell {user}@ /usr/bin/{cmd}' - for cmd in user_subcmds - ], - foreground=True, - ) + self.add_cmd_output([ + f'machinectl -q shell {user}@ /usr/bin/{cmd}' + for cmd in user_subcmds + ], foreground=True) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/crio.py b/sos/report/plugins/crio.py index dc30087333..3af3ed7a3a 100644 --- a/sos/report/plugins/crio.py +++ b/sos/report/plugins/crio.py @@ -81,17 +81,13 @@ def setup(self): self._get_crio_goroutine_stacks() for container in containers: - self.add_cmd_output( - f"crictl inspect {container}", - subdir="containers" - ) + self.add_cmd_output(f"crictl inspect {container}", + subdir="containers") if self.get_option('logs'): - self.add_cmd_output( - f"crictl logs -t {container}", - subdir="containers/logs", - priority=100, - tags="crictl_logs", - ) + self.add_cmd_output(f"crictl logs -t {container}", + subdir="containers/logs", + priority=100, + tags="crictl_logs") for image in images: self.add_cmd_output(f"crictl inspecti {image}", subdir="images") diff --git a/sos/report/plugins/crypto.py b/sos/report/plugins/crypto.py index 497ab297c3..c9fa502226 100644 --- a/sos/report/plugins/crypto.py +++ b/sos/report/plugins/crypto.py @@ -22,18 +22,12 @@ def setup(self): cpth = '/etc/crypto-policies/back-ends' - self.add_file_tags( - { - f"{cpth}/bind.config": 'crypto_policies_bind', - f"{cpth}/opensshserver.config": ( - 'crypto_policies_opensshserver' - ), - '/etc/crypto-policies/.*/current': ( - 'crypto_policies_state_current' - ), - '/etc/crypto-policies/config': 'crypto_policies_config', - } - ) + self.add_file_tags({ + f"{cpth}/bind.config": 'crypto_policies_bind', + f"{cpth}/opensshserver.config": 'crypto_policies_opensshserver', + '/etc/crypto-policies/.*/current': 'crypto_policies_state_current', + '/etc/crypto-policies/config': 'crypto_policies_config', + }) self.add_copy_spec([ "/proc/crypto", diff --git a/sos/report/plugins/cs.py b/sos/report/plugins/cs.py index 7dc755c925..1694b97a4c 100644 --- a/sos/report/plugins/cs.py +++ b/sos/report/plugins/cs.py @@ -104,15 +104,13 @@ def setup(self): if csversion == 9: # Get logs and configs for each subsystem if installed for subsystem in ('ca', 'kra', 'ocsp', 'tks', 'tps'): - self.add_copy_spec( - [ - f"/var/lib/pki/*/{subsystem}/conf/CS.cfg", - f"/var/lib/pki/*/logs/{subsystem}/system", - f"/var/lib/pki/*/logs/{subsystem}/transactions", - f"/var/lib/pki/*/logs/{subsystem}/debug", - f"/var/lib/pki/*/logs/{subsystem}/selftests.log", - ] - ) + self.add_copy_spec([ + f"/var/lib/pki/*/{subsystem}/conf/CS.cfg", + f"/var/lib/pki/*/logs/{subsystem}/system", + f"/var/lib/pki/*/logs/{subsystem}/transactions", + f"/var/lib/pki/*/logs/{subsystem}/debug", + f"/var/lib/pki/*/logs/{subsystem}/selftests.log", + ]) # Common log files self.add_copy_spec([ diff --git a/sos/report/plugins/dnf.py b/sos/report/plugins/dnf.py index 703adaa903..cfc7850b72 100644 --- a/sos/report/plugins/dnf.py +++ b/sos/report/plugins/dnf.py @@ -46,10 +46,8 @@ def get_modules_info(self, modules): if "[i]" in line: module = line.split()[0] if module != "Hint:": - self.add_cmd_output( - f"dnf module info {module}", - tags="dnf_module_info" - ) + self.add_cmd_output(f"dnf module info {module}", + tags="dnf_module_info") def setup(self): diff --git a/sos/report/plugins/docker.py b/sos/report/plugins/docker.py index e821f3d448..75bb9a31d9 100644 --- a/sos/report/plugins/docker.py +++ b/sos/report/plugins/docker.py @@ -86,30 +86,22 @@ def setup(self): volumes = self.get_container_volumes(runtime='docker') for container in containers: - self.add_cmd_output( - f"docker inspect {container}", - subdir="containers" - ) + self.add_cmd_output(f"docker inspect {container}", + subdir="containers") if self.get_option('logs'): - self.add_cmd_output( - f"docker logs -t {container}", - subdir="containers" - ) + self.add_cmd_output(f"docker logs -t {container}", + subdir="containers") for img in images: name, img_id = img insp = name if 'none' not in name else img_id - self.add_cmd_output( - f"docker inspect {insp}", - subdir='images', - tags="docker_image_inspect", - ) + self.add_cmd_output(f"docker inspect {insp}", + subdir='images', + tags="docker_image_inspect") for vol in volumes: - self.add_cmd_output( - f"docker volume inspect {vol}", - subdir="volumes" - ) + self.add_cmd_output(f"docker volume inspect {vol}", + subdir="volumes") def postproc(self): # Attempts to match key=value pairs inside container inspect output diff --git a/sos/report/plugins/ebpf.py b/sos/report/plugins/ebpf.py index 2de792459c..2fa9b02fa8 100644 --- a/sos/report/plugins/ebpf.py +++ b/sos/report/plugins/ebpf.py @@ -50,9 +50,8 @@ def setup(self): progs = self.collect_cmd_output("bpftool -j prog list") for prog_id in self.get_bpftool_prog_ids(progs['output']): for dumpcmd in ["xlated", "jited"]: - self.add_cmd_output( - f"bpftool prog dump {dumpcmd} id {prog_id}" - ) + self.add_cmd_output(f"bpftool prog dump {dumpcmd} id " + f"{prog_id}") maps = self.collect_cmd_output("bpftool -j map list") for map_id in self.get_bpftool_map_ids(maps['output']): diff --git a/sos/report/plugins/elastic.py b/sos/report/plugins/elastic.py index 2a746cc33f..e1a4fee401 100644 --- a/sos/report/plugins/elastic.py +++ b/sos/report/plugins/elastic.py @@ -51,16 +51,14 @@ def setup(self): host, port = self.get_hostname_port(els_config_file) endpoint = f"{host}:{port}" - self.add_cmd_output( - [ - f"curl -X GET '{endpoint}/_cluster/settings?pretty'", - f"curl -X GET '{endpoint}/_cluster/health?pretty'", - f"curl -X GET '{endpoint}/_cluster/stats?pretty'", - f"curl -X GET '{endpoint}/_cat/nodes?v'", - f"curl -X GET '{endpoint}/_cat/indices'", - f"curl -X GET '{endpoint}/_cat/shards'", - f"curl -X GET '{endpoint}/_cat/aliases'", - ] - ) + self.add_cmd_output([ + f"curl -X GET '{endpoint}/_cluster/settings?pretty'", + f"curl -X GET '{endpoint}/_cluster/health?pretty'", + f"curl -X GET '{endpoint}/_cluster/stats?pretty'", + f"curl -X GET '{endpoint}/_cat/nodes?v'", + f"curl -X GET '{endpoint}/_cat/indices'", + f"curl -X GET '{endpoint}/_cat/shards'", + f"curl -X GET '{endpoint}/_cat/aliases'", + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/fibrechannel.py b/sos/report/plugins/fibrechannel.py index 9fc4f79c41..745b8681f5 100644 --- a/sos/report/plugins/fibrechannel.py +++ b/sos/report/plugins/fibrechannel.py @@ -44,11 +44,9 @@ def setup(self): for line in listhbas['output'].splitlines(): if 'Port WWN' in line: dev = line.split()[3] - self.add_cmd_output( - [ - f"hbacmd HbaAttributes {dev}", - f"hbacmd PortAttributes {dev}", - f"hbacmd GetXcvrData {dev}", - ] - ) + self.add_cmd_output([ + f"hbacmd HbaAttributes {dev}", + f"hbacmd PortAttributes {dev}", + f"hbacmd GetXcvrData {dev}", + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/filesys.py b/sos/report/plugins/filesys.py index 2c7cf14e8e..875a1fc6a8 100644 --- a/sos/report/plugins/filesys.py +++ b/sos/report/plugins/filesys.py @@ -47,16 +47,12 @@ def setup(self): "/etc/fstab", "/run/mount/utab", ]) - self.add_cmd_output( - "mount -l", - root_symlink="mount", - tags="mount" - ) - self.add_cmd_output( - "df -al -x autofs", - root_symlink="df", - tags='df__al' - ) + self.add_cmd_output("mount -l", + root_symlink="mount", + tags="mount") + self.add_cmd_output("df -al -x autofs", + root_symlink="df", + tags='df__al') self.add_cmd_output([ "df -ali -x autofs", "findmnt", @@ -89,10 +85,8 @@ def setup(self): mounts = '/proc/mounts' ext_fs_regex = r"^(/dev/\S+).+ext[234]\s+" for dev in self.do_regex_find_all(ext_fs_regex, mounts): - self.add_cmd_output( - f"dumpe2fs {dumpe2fs_opts} {dev}", - tags="dumpe2fs_h" - ) + self.add_cmd_output(f"dumpe2fs {dumpe2fs_opts} {dev}", + tags="dumpe2fs_h") if self.get_option('frag'): self.add_cmd_output(f"e2freefrag {dev}", priority=100) diff --git a/sos/report/plugins/foreman.py b/sos/report/plugins/foreman.py index fd0cb240b8..138b55c30a 100644 --- a/sos/report/plugins/foreman.py +++ b/sos/report/plugins/foreman.py @@ -64,10 +64,7 @@ def setup(self): pass # strip wrapping ".." or '..' around password if (self.dbpasswd.startswith('"') and self.dbpasswd.endswith('"')) or \ - ( - self.dbpasswd.startswith('\'') and - self.dbpasswd.endswith('\'') - ): + (self.dbpasswd.startswith('\'') and self.dbpasswd.endswith('\'')): self.dbpasswd = self.dbpasswd[1:-1] # set the password to os.environ when calling psql commands to prevent # printing it in sos logs @@ -122,20 +119,18 @@ def setup(self): f"/var/log/{self.apachepkg}*/katello-reverse-proxy_access_ssl.log*" ]) - self.add_cmd_output( - [ - 'foreman-selinux-relabel -nv', - 'passenger-status --show pool', - 'passenger-status --show requests', - 'passenger-status --show backtraces', - 'passenger-memory-stats', - 'ls -lanR /root/ssl-build', - 'ls -lanR /usr/share/foreman/config/hooks', - f'ping -c1 -W1 {_hostname}', - f'ping -c1 -W1 {_host_f}', - 'ping -c1 -W1 localhost', - ] - ) + self.add_cmd_output([ + 'foreman-selinux-relabel -nv', + 'passenger-status --show pool', + 'passenger-status --show requests', + 'passenger-status --show backtraces', + 'passenger-memory-stats', + 'ls -lanR /root/ssl-build', + 'ls -lanR /usr/share/foreman/config/hooks', + f'ping -c1 -W1 {_hostname}', + f'ping -c1 -W1 {_host_f}', + 'ping -c1 -W1 localhost', + ]) self.add_cmd_output( 'qpid-stat -b amqps://localhost:5671 -q \ --ssl-certificate=/etc/pki/katello/qpid_router_client.crt \ @@ -201,23 +196,21 @@ def setup(self): 'select dynflow_execution_plans.* from foreman_tasks_tasks join ' 'dynflow_execution_plans on (foreman_tasks_tasks.external_id = ' 'dynflow_execution_plans.uuid::varchar) where foreman_tasks_tasks.' - 'started_at > NOW() - interval %s' % quote(days) + f'started_at > NOW() - interval {quote(days)}' ) dactioncmd = ( 'select dynflow_actions.* from foreman_tasks_tasks join ' 'dynflow_actions on (foreman_tasks_tasks.external_id = ' 'dynflow_actions.execution_plan_uuid::varchar) where ' - 'foreman_tasks_tasks.started_at > NOW() - interval %s' - % quote(days) + f'foreman_tasks_tasks.started_at > NOW() - interval {quote(days)}' ) dstepscmd = ( 'select dynflow_steps.* from foreman_tasks_tasks join ' 'dynflow_steps on (foreman_tasks_tasks.external_id = ' 'dynflow_steps.execution_plan_uuid::varchar) where ' - 'foreman_tasks_tasks.started_at > NOW() - interval %s' - % quote(days) + f'foreman_tasks_tasks.started_at > NOW() - interval {quote(days)}' ) # counts of fact_names prefixes/types: much of one type suggests @@ -285,7 +278,7 @@ def setup(self): # proxy is now tuple [name, url] _cmd = 'curl -s --key /etc/foreman/client_key.pem ' \ '--cert /etc/foreman/client_cert.pem ' \ - '%s/v2/features' % proxy[1] + f'{proxy[1]}/v2/features' self.add_cmd_output(_cmd, suggest_filename=proxy[0], subdir='smart_proxies_features', timeout=10) @@ -302,10 +295,11 @@ def build_query_cmd(self, query, csv=False, binary="psql"): a large amount of quoting in sos logs referencing the command being run """ if csv: - query = "COPY (%s) TO STDOUT " \ - "WITH (FORMAT 'csv', DELIMITER ',', HEADER)" % query - _dbcmd = "%s --no-password -h %s -p 5432 -U foreman -d foreman -c %s" - return _dbcmd % (binary, self.dbhost, quote(query)) + query = (f"COPY ({query}) TO STDOUT WITH (FORMAT 'csv', " + "DELIMITER ',', HEADER)") + _dbcmd = (f"{binary} --no-password -h {self.dbhost} -p 5432 " + f"-U foreman -d foreman -c {quote(query)}") + return _dbcmd def postproc(self): self.do_path_regex_sub( diff --git a/sos/report/plugins/foreman_installer.py b/sos/report/plugins/foreman_installer.py index 43d774c8ef..ac07eddc43 100644 --- a/sos/report/plugins/foreman_installer.py +++ b/sos/report/plugins/foreman_installer.py @@ -45,8 +45,8 @@ def setup(self): def postproc(self): install_logs = "/var/log/foreman-installer/" logsreg = r"((foreman.*)?(\"::(foreman(.*?)|katello).*)?((::(.*)::.*" \ - r"(passw|cred|token|secret|key).*(\")?:)|(storepass )" \ - r"|(password =)))(.*)" + r"(passw|cred|token|secret|key).*(\")?:)|(storepass )" \ + r"|(password =)))(.*)" self.do_path_regex_sub(install_logs, logsreg, r"\1 ********") # need to do two passes here, debug output has different formatting logs_debug_reg = (r"(\s)+(Found key: (\"(foreman(.*?)|katello)" diff --git a/sos/report/plugins/gluster.py b/sos/report/plugins/gluster.py index f7a7d2dec0..e486d7ca70 100644 --- a/sos/report/plugins/gluster.py +++ b/sos/report/plugins/gluster.py @@ -104,7 +104,7 @@ def setup(self): "glusterd processes") else: self.soslog.warning("Unable to generate statedumps, no such " - "directory: %s" % self.statedump_dir) + f"directory: {self.statedump_dir}") state = self.exec_cmd("gluster get-state") if state['status'] == 0: state_file = state['output'].split()[-1] @@ -117,19 +117,17 @@ def setup(self): if not line.startswith("Volume Name:"): continue volname = line[12:] - self.add_cmd_output( - [ - f"gluster volume get {volname} all", - f"gluster volume geo-replication {volname} status", - f"gluster volume heal {volname} info", - f"gluster volume heal {volname} info split-brain", - f"gluster volume status {volname} clients", - f"gluster snapshot list {volname}", - f"gluster volume quota {volname} list", - f"gluster volume rebalance {volname} status", - f"gluster snapshot info {volname}", - f"gluster snapshot status {volname}", - ] - ) + self.add_cmd_output([ + f"gluster volume get {volname} all", + f"gluster volume geo-replication {volname} status", + f"gluster volume heal {volname} info", + f"gluster volume heal {volname} info split-brain", + f"gluster volume status {volname} clients", + f"gluster snapshot list {volname}", + f"gluster volume quota {volname} list", + f"gluster volume rebalance {volname} status", + f"gluster snapshot info {volname}", + f"gluster snapshot status {volname}", + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/grafana.py b/sos/report/plugins/grafana.py index 0bc51fd4ab..4e8b14cf3b 100644 --- a/sos/report/plugins/grafana.py +++ b/sos/report/plugins/grafana.py @@ -66,5 +66,5 @@ def postproc(self): else "/etc/grafana/grafana.ini" ) - regexp = r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + regexp = rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)" self.do_path_regex_sub(inifile, regexp, r"\1*********") diff --git a/sos/report/plugins/haproxy.py b/sos/report/plugins/haproxy.py index 44c2152a05..0d3c6ab1ea 100644 --- a/sos/report/plugins/haproxy.py +++ b/sos/report/plugins/haproxy.py @@ -29,12 +29,10 @@ class HAProxy(Plugin, RedHatPlugin, DebianPlugin): files = (var_puppet_gen, ) def setup(self): - self.add_copy_spec( - [ - "/etc/haproxy/haproxy.cfg", - f"{self.var_puppet_gen}/etc/haproxy/haproxy.cfg", - ] - ) + self.add_copy_spec([ + "/etc/haproxy/haproxy.cfg", + f"{self.var_puppet_gen}/etc/haproxy/haproxy.cfg", + ]) self.add_copy_spec("/etc/haproxy/conf.d/*") self.add_cmd_output("haproxy -f /etc/haproxy/haproxy.cfg -c") @@ -67,9 +65,7 @@ def setup(self): if urlparse(f"http://{provision_ip}").port is None: provision_ip = f"{provision_ip}:1993" - self.add_cmd_output( - f"curl http://{provision_ip}" + r"/\;csv", - suggest_filename="haproxy_overview.txt", - ) + self.add_cmd_output(f"curl http://{provision_ip}" + r"/\;csv", + suggest_filename="haproxy_overview.txt") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/hpssm.py b/sos/report/plugins/hpssm.py index 439dc19c59..bfee4d7f4c 100644 --- a/sos/report/plugins/hpssm.py +++ b/sos/report/plugins/hpssm.py @@ -52,20 +52,16 @@ def setup(self): for line in config_detail['output'].splitlines() for m in [pattern.search(line)] if m] ssacli_ctrl_slot_cmd = f'{cmd} ctrl slot=' - self.add_cmd_output( - [ - f"{ssacli_ctrl_slot_cmd}{slot} {slot_subcmd}" - for slot in ctrl_slots - for slot_subcmd in slot_subcmds - ] - ) + self.add_cmd_output([ + f"{ssacli_ctrl_slot_cmd}{slot} {slot_subcmd}" + for slot in ctrl_slots + for slot_subcmd in slot_subcmds + ]) logpath = self.get_cmd_output_path() - self.add_cmd_output( - f'ssaducli -v -adu -f {logpath}/adu-log.zip', - suggest_filename='ssaducli_-v_-adu.log', - ) + self.add_cmd_output(f'ssaducli -v -adu -f {logpath}/adu-log.zip', + suggest_filename='ssaducli_-v_-adu.log') if self.get_option("debug"): self.do_debug(logpath) @@ -74,7 +70,7 @@ def do_debug(self, logpath): self.add_cmd_output( f'ilorest serverlogs --selectlog=AHS --directorypath={logpath}', runat=logpath, - suggest_filename='ilorest.log', + suggest_filename='ilorest.log' ) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/ipa.py b/sos/report/plugins/ipa.py index 1251aac48d..fa698162eb 100644 --- a/sos/report/plugins/ipa.py +++ b/sos/report/plugins/ipa.py @@ -139,22 +139,20 @@ def setup(self): self.add_cmd_output(f"certutil -L -d {self.pki_tomcat_dir}/alias") self.add_copy_spec(f"{self.pki_tomcat_conf_dir}/CS.cfg") - self.add_forbidden_path( - [ - "/etc/pki/nssdb/key*", - "/etc/dirsrv/slapd-*/key*", - "/etc/dirsrv/slapd-*/pin.txt", - "/etc/dirsrv/slapd-*/pwdfile.txt", - "/etc/httpd/alias/ipasession.key", - "/etc/httpd/alias/key*", - "/etc/httpd/alias/pin.txt", - "/etc/httpd/alias/pwdfile.txt", - "/etc/named.keytab", - f"{self.pki_tomcat_dir}/alias/key*", - f"{self.pki_tomcat_conf_dir}/flatfile.txt", - f"{self.pki_tomcat_conf_dir}/password.conf", - ] - ) + self.add_forbidden_path([ + "/etc/pki/nssdb/key*", + "/etc/dirsrv/slapd-*/key*", + "/etc/dirsrv/slapd-*/pin.txt", + "/etc/dirsrv/slapd-*/pwdfile.txt", + "/etc/httpd/alias/ipasession.key", + "/etc/httpd/alias/key*", + "/etc/httpd/alias/pin.txt", + "/etc/httpd/alias/pwdfile.txt", + "/etc/named.keytab", + f"{self.pki_tomcat_dir}/alias/key*", + f"{self.pki_tomcat_conf_dir}/flatfile.txt", + f"{self.pki_tomcat_conf_dir}/password.conf", + ]) self.add_cmd_output([ "ls -la /etc/dirsrv/slapd-*/schema/", diff --git a/sos/report/plugins/ipmitool.py b/sos/report/plugins/ipmitool.py index 2923d99735..5f588060f6 100644 --- a/sos/report/plugins/ipmitool.py +++ b/sos/report/plugins/ipmitool.py @@ -28,25 +28,23 @@ def setup(self): for subcmd in ['channel info', 'channel getaccess', 'lan print']: for channel in [1, 3]: - self.add_cmd_output("%s %s %d" % (cmd, subcmd, channel)) + self.add_cmd_output(f"{cmd} {subcmd} {channel}") # raw 0x30 0x65: Get HDD drive Fault LED State # raw 0x30 0xb0: Get LED Status - self.add_cmd_output( - [ - f"{cmd} raw 0x30 0x65", - f"{cmd} raw 0x30 0xb0", - f"{cmd} sel info", - f"{cmd} sel elist", - f"{cmd} sel list -v", - f"{cmd} sensor list", - f"{cmd} chassis status", - f"{cmd} lan print", - f"{cmd} fru print", - f"{cmd} mc info", - f"{cmd} sdr info", - ] - ) + self.add_cmd_output([ + f"{cmd} raw 0x30 0x65", + f"{cmd} raw 0x30 0xb0", + f"{cmd} sel info", + f"{cmd} sel elist", + f"{cmd} sel list -v", + f"{cmd} sensor list", + f"{cmd} chassis status", + f"{cmd} lan print", + f"{cmd} fru print", + f"{cmd} mc info", + f"{cmd} sdr info", + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/iprconfig.py b/sos/report/plugins/iprconfig.py index b64d3ab5bb..8b2099208f 100644 --- a/sos/report/plugins/iprconfig.py +++ b/sos/report/plugins/iprconfig.py @@ -108,6 +108,6 @@ def setup(self): temp = alt_line.split(' ') # temp[0] holds device name self.add_cmd_output("iprconfig -c " - "query-ses-mode %s" % temp[0]) + f"query-ses-mode {temp[0]}") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/iscsi.py b/sos/report/plugins/iscsi.py index 6e9ced3315..a77505532e 100644 --- a/sos/report/plugins/iscsi.py +++ b/sos/report/plugins/iscsi.py @@ -20,14 +20,12 @@ class Iscsi(Plugin): def setup(self): var_puppet_gen = "/var/lib/config-data/puppet-generated/iscsid" - self.add_copy_spec( - [ - "/etc/iscsi/iscsid.conf", - "/etc/iscsi/initiatorname.iscsi", - f"{var_puppet_gen}/etc/iscsi/initiatorname.iscsi", - "/var/lib/iscsi", - ] - ) + self.add_copy_spec([ + "/etc/iscsi/iscsid.conf", + "/etc/iscsi/initiatorname.iscsi", + f"{var_puppet_gen}/etc/iscsi/initiatorname.iscsi", + "/var/lib/iscsi", + ]) self.add_cmd_output([ "iscsiadm -m session -P 3", "iscsiadm -m node -P 1", diff --git a/sos/report/plugins/juju.py b/sos/report/plugins/juju.py index b0208042a3..4a5abbbf14 100644 --- a/sos/report/plugins/juju.py +++ b/sos/report/plugins/juju.py @@ -63,7 +63,7 @@ def postproc(self): ] # Redact simple yaml style "key: value". - keys_regex = r"(^\s*(%s)\s*:\s*)(.*)" % "|".join(protect_keys) + keys_regex = rf"(^\s*({'|'.join(protect_keys)})\s*:\s*)(.*)" sub_regex = r"\1*********" self.do_path_regex_sub(agents_path, keys_regex, sub_regex) # Redact certificates diff --git a/sos/report/plugins/kubernetes.py b/sos/report/plugins/kubernetes.py index 1b043e314e..6309e825d6 100644 --- a/sos/report/plugins/kubernetes.py +++ b/sos/report/plugins/kubernetes.py @@ -161,10 +161,8 @@ def setup(self): for pod in pods: if reg and not re.match(reg, pod): continue - self.add_cmd_output( - f"{k_cmd} logs {pod}", - subdir="pods" - ) + self.add_cmd_output(f"{k_cmd} logs {pod}", + subdir="pods") if not self.get_option('all'): k_cmd = f'{self.kube_cmd} get --all-namespaces=true' diff --git a/sos/report/plugins/libraries.py b/sos/report/plugins/libraries.py index 8e01bf103b..2d52590e95 100644 --- a/sos/report/plugins/libraries.py +++ b/sos/report/plugins/libraries.py @@ -44,9 +44,7 @@ def setup(self): dirs.add(s[1].rsplit('/', 1)[0]) if dirs: - self.add_cmd_output( - f'ls -lanH {" ".join(dirs)}', - suggest_filename="ld_so_cache", - ) + self.add_cmd_output(f'ls -lanH {" ".join(dirs)}', + suggest_filename="ld_so_cache") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/logrotate.py b/sos/report/plugins/logrotate.py index 2c80fd9001..4b74577e31 100644 --- a/sos/report/plugins/logrotate.py +++ b/sos/report/plugins/logrotate.py @@ -20,10 +20,8 @@ class LogRotate(Plugin, IndependentPlugin): var_ansible_gen = "/var/lib/config-data/ansible-generated/crond" def setup(self): - self.add_cmd_output( - "logrotate --debug /etc/logrotate.conf", - suggest_filename="logrotate_debug" - ) + self.add_cmd_output("logrotate --debug /etc/logrotate.conf", + suggest_filename="logrotate_debug") self.add_copy_spec([ "/etc/logrotate*", "/var/lib/logrotate.status", diff --git a/sos/report/plugins/lstopo.py b/sos/report/plugins/lstopo.py index 94c2bb032d..758c32aaa2 100644 --- a/sos/report/plugins/lstopo.py +++ b/sos/report/plugins/lstopo.py @@ -30,11 +30,7 @@ def setup(self): cmd = "lstopo" else: cmd = "lstopo-no-graphics" - self.add_cmd_output( - f"{cmd} --whole-io --of console", - suggest_filename="lstopo.txt" - ) - self.add_cmd_output( - f"{cmd} --whole-io --of xml", - suggest_filename="lstopo.xml" - ) + self.add_cmd_output(f"{cmd} --whole-io --of console", + suggest_filename="lstopo.txt") + self.add_cmd_output(f"{cmd} --whole-io --of xml", + suggest_filename="lstopo.xml") diff --git a/sos/report/plugins/lustre.py b/sos/report/plugins/lustre.py index c5726837f4..5ccdae2316 100644 --- a/sos/report/plugins/lustre.py +++ b/sos/report/plugins/lustre.py @@ -23,11 +23,9 @@ def get_params(self, name, param_list): file. """ - self.add_cmd_output( - f'lctl get_param {" ".join(param_list)}', - suggest_filename=f"params-{name}", - stderr=False - ) + self.add_cmd_output(f'lctl get_param {" ".join(param_list)}', + suggest_filename=f"params-{name}", + stderr=False) def setup(self): self.add_cmd_output([ diff --git a/sos/report/plugins/lvm2.py b/sos/report/plugins/lvm2.py index be458c17e4..07247851f1 100644 --- a/sos/report/plugins/lvm2.py +++ b/sos/report/plugins/lvm2.py @@ -31,13 +31,12 @@ def do_lvmdump(self, metadata=False): archives for each physical volume present. """ lvmdump_path = self.get_cmd_output_path(name="lvmdump", make=False) - lvmdump_cmd = "lvmdump %s -d '%s'" lvmdump_opts = "" if metadata: lvmdump_opts = "-a -m" - cmd = lvmdump_cmd % (lvmdump_opts, lvmdump_path) + cmd = f"lvmdump {lvmdump_opts} -d '{lvmdump_path}'" self.add_cmd_output(cmd, chroot=self.tmp_in_sysroot()) @@ -93,18 +92,12 @@ def setup(self): vgs_cols = f'{vgs_cols},vg_tags,systemid' lvs_cols = ('lv_tags,devices,lv_kernel_read_ahead,lv_read_ahead,' 'stripes,stripesize') - self.add_cmd_output( - f"lvs -a -o +{lvs_cols} {lvm_opts_foreign}", - tags="lvs_headings" - ) - self.add_cmd_output( - f"pvs -a -v -o +{pvs_cols} {lvm_opts_foreign}", - tags="pvs_headings" - ) - self.add_cmd_output( - f"vgs -v -o +{vgs_cols} {lvm_opts_foreign}", - tags="vgs_headings" - ) + self.add_cmd_output(f"lvs -a -o +{lvs_cols} {lvm_opts_foreign}", + tags="lvs_headings") + self.add_cmd_output(f"pvs -a -v -o +{pvs_cols} {lvm_opts_foreign}", + tags="pvs_headings") + self.add_cmd_output(f"vgs -v -o +{vgs_cols} {lvm_opts_foreign}", + tags="vgs_headings") self.add_cmd_output([ f"pvscan -v {lvm_opts}", f"vgscan -vvv {lvm_opts}" diff --git a/sos/report/plugins/maas.py b/sos/report/plugins/maas.py index 8bd74d5365..984b7d6dc4 100644 --- a/sos/report/plugins/maas.py +++ b/sos/report/plugins/maas.py @@ -121,11 +121,8 @@ def setup(self): if self._has_login_options(): if self._remote_api_login(): - self.add_cmd_output( - 'maas' - f' {self.get_option("profile-name")}' - ' commissioning-results list' - ) + self.add_cmd_output(f'maas {self.get_option("profile-name")}' + ' commissioning-results list') else: self._log_error( "Cannot login into MAAS remote API with provided creds.") diff --git a/sos/report/plugins/megacli.py b/sos/report/plugins/megacli.py index 87c5d79640..6188da5944 100644 --- a/sos/report/plugins/megacli.py +++ b/sos/report/plugins/megacli.py @@ -29,6 +29,8 @@ def setup(self): '-ShowSummary' ] - self.add_cmd_output([f"{cmd} {subcmd} -aALL" for subcmd in subcmds]) + self.add_cmd_output([ + f"{cmd} {subcmd} -aALL" for subcmd in subcmds + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/microshift.py b/sos/report/plugins/microshift.py index 2004cfbcde..0fccd218cf 100644 --- a/sos/report/plugins/microshift.py +++ b/sos/report/plugins/microshift.py @@ -89,7 +89,7 @@ def _get_namespaces(self): 'oc get namespaces' ' -o custom-columns=NAME:.metadata.name' ' --no-headers' - ' --kubeconfig=%s' % self.get_option('kubeconfig')) + f' --kubeconfig={self.get_option("kubeconfig")}') if res['status'] == 0: return self._reduce_namespace_list(res['output'].split('\n')) return [] @@ -132,8 +132,7 @@ def _get_cluster_resources(self): res = self.exec_cmd( "oc get --kubeconfig" f" {self.get_option('kubeconfig')} {resource}", - timeout=Microshift.plugin_timeout, - ) + timeout=Microshift.plugin_timeout) if res['status'] == 0: _filtered_resources.append(resource) return _filtered_resources @@ -164,8 +163,7 @@ def setup(self): _cluster_resources_to_collect = ",".join( self._get_cluster_resources()) _namespaces_to_collect = " ".join( - [f'ns/{n}' for n in self._get_namespaces()] - ) + [f'ns/{n}' for n in self._get_namespaces()]) if self.is_service_running(Microshift.plugin_name): _subdir = self.get_cmd_output_path(make=False) @@ -174,11 +172,9 @@ def setup(self): f'oc adm inspect --kubeconfig {_kubeconfig}' f' --dest-dir {_subdir} {_cluster_resources_to_collect}', suggest_filename='inspect_cluster_resources.log', - timeout=Microshift.plugin_timeout, - ) + timeout=Microshift.plugin_timeout) self.add_cmd_output( f'oc adm inspect --kubeconfig {_kubeconfig}' f' --dest-dir {_subdir} {_namespaces_to_collect}', suggest_filename='inspect_namespaces.log', - timeout=Microshift.plugin_timeout, - ) + timeout=Microshift.plugin_timeout) diff --git a/sos/report/plugins/mssql.py b/sos/report/plugins/mssql.py index 7b04c7edc7..348f612688 100644 --- a/sos/report/plugins/mssql.py +++ b/sos/report/plugins/mssql.py @@ -62,10 +62,8 @@ def setup(self): return # Collect AD authentication configuratoin - keytab_err = ( - 'keytab file is specfieid in mssql_conf but not found in' - f' {kerberoskeytabfile}' - ) + keytab_err = ('keytab file is specfieid in mssql_conf but not found in' + f' {kerberoskeytabfile}') if kerberoskeytabfile is not None: if self.path_isfile(kerberoskeytabfile): self.add_cmd_output(f'ls -l {kerberoskeytabfile}') diff --git a/sos/report/plugins/networking.py b/sos/report/plugins/networking.py index 1e287a32b5..7643b2b11b 100644 --- a/sos/report/plugins/networking.py +++ b/sos/report/plugins/networking.py @@ -20,7 +20,7 @@ class Networking(Plugin): option_list = [ PluginOpt("traceroute", default=False, - desc="collect a traceroute to %s" % trace_host), + desc=f"collect a traceroute to {trace_host}"), PluginOpt("namespace_pattern", default="", val_type=str, desc=("Specific namespace names or patterns to collect, " "whitespace delimited.")), @@ -88,9 +88,8 @@ def setup(self): tags=['ip_route', 'iproute_show_table_all']) self.add_cmd_output("plotnetcfg") - self.add_cmd_output( - f"netstat {self.ns_wide} -neopa", root_symlink="netstat" - ) + self.add_cmd_output(f"netstat {self.ns_wide} -neopa", + root_symlink="netstat") self.add_cmd_output([ "nstat -zas", @@ -142,10 +141,9 @@ def setup(self): # Get ethtool output for every device that does not exist in a # namespace. _ecmds = [f"ethtool -{opt}" for opt in self.ethtool_shortopts] - self.add_device_cmd( - [f"{_cmd} %(dev)s" for _cmd in _ecmds], - devices="ethernet" - ) + self.add_device_cmd([ + f"{_cmd} %(dev)s" for _cmd in _ecmds + ], devices="ethernet") self.add_device_cmd([ "ethtool %(dev)s", @@ -175,10 +173,8 @@ def setup(self): ]) if self.get_option("traceroute"): - self.add_cmd_output( - f"/bin/traceroute -n {self.trace_host}", - priority=100 - ) + self.add_cmd_output(f"/bin/traceroute -n {self.trace_host}", + priority=100) # Capture additional data from namespaces; each command is run # per-namespace. @@ -219,21 +215,15 @@ def setup(self): f"{ns_cmd_prefix}netstat {self.ns_wide} -agn", f"{ns_cmd_prefix}nstat -zas", ], - priority=50, - subdir=_subdir, - ) - self.add_cmd_output( - [f"{ns_cmd_prefix}iptables-save"], - pred=iptables_with_nft, - subdir=_subdir, - priority=50, - ) - self.add_cmd_output( - [f"{ns_cmd_prefix}ip6tables-save"], - pred=ip6tables_with_nft, - subdir=_subdir, - priority=50, - ) + priority=50, subdir=_subdir) + self.add_cmd_output([f"{ns_cmd_prefix}iptables-save"], + pred=iptables_with_nft, + subdir=_subdir, + priority=50) + self.add_cmd_output([f"{ns_cmd_prefix}ip6tables-save"], + pred=ip6tables_with_nft, + subdir=_subdir, + priority=50) ss_cmd = f"{ns_cmd_prefix}ss -peaonmi" # --allow-system-changes is handled directly in predicate @@ -251,11 +241,7 @@ def setup(self): f"{ns_cmd_prefix}ethtool -i %(dev)s", f"{ns_cmd_prefix}ethtool -k %(dev)s", f"{ns_cmd_prefix}ethtool -S %(dev)s", - ], - devices=_devs['ethernet'], - priority=50, - subdir=_subdir, - ) + ], devices=_devs['ethernet'], priority=50, subdir=_subdir) self.add_cmd_tags({ "ethtool [^-].*": "ethtool", @@ -321,9 +307,8 @@ def setup(self): ]) if self.get_option("traceroute"): - self.add_cmd_output( - f"/usr/sbin/traceroute -n {self.trace_host}", priority=100 - ) + self.add_cmd_output(f"/usr/sbin/traceroute -n {self.trace_host}", + priority=100) def postproc(self): diff --git a/sos/report/plugins/networkmanager.py b/sos/report/plugins/networkmanager.py index 8107522177..10ba9bc64d 100644 --- a/sos/report/plugins/networkmanager.py +++ b/sos/report/plugins/networkmanager.py @@ -40,17 +40,18 @@ def setup(self): # All versions conform to the following templates with differnt # strings for the object being operated on. - nmcli_con_details_template = "nmcli con %s id" - nmcli_dev_details_template = "nmcli dev %s" + nmcli_con_details_template = "nmcli con {} id" + nmcli_dev_details_template = "nmcli dev {}" # test NetworkManager status for the specified major version def test_nm_status(version=1): - status_template = "nmcli --terse --fields RUNNING %s status" obj_table = [ "nm", # < 0.9.9 "general" # >= 0.9.9 ] - status = self.exec_cmd(status_template % obj_table[version]) + status_template = ("nmcli --terse --fields RUNNING " + f"{obj_table[version]} status") + status = self.exec_cmd(status_template) return (status['status'] == 0 and status['output'].lower().startswith("running")) @@ -62,8 +63,8 @@ def test_nm_status(version=1): "nmcli -f all con", "nmcli con show --active", "nmcli dev"]) - nmcli_con_details_cmd = nmcli_con_details_template % "show" - nmcli_dev_details_cmd = nmcli_dev_details_template % "show" + nmcli_con_details_cmd = nmcli_con_details_template.format("show") + nmcli_dev_details_cmd = nmcli_dev_details_template.format("show") # NetworkManager < 0.9.9 (Use short name of objects for nmcli) elif test_nm_status(version=0): diff --git a/sos/report/plugins/omnipath_client.py b/sos/report/plugins/omnipath_client.py index ec7bf23d06..2f129dddaa 100644 --- a/sos/report/plugins/omnipath_client.py +++ b/sos/report/plugins/omnipath_client.py @@ -48,9 +48,8 @@ def setup(self): # This command calls 'depmod -a', so lets make sure we # specified the 'allow-system-changes' option before running it. if self.get_option('allow_system_changes'): - self.add_cmd_output("opacapture %s" % - join(self.get_cmd_output_path(), - "opacapture.tgz"), + archive_path = join(self.get_cmd_output_path(), 'opacapture.tgz') + self.add_cmd_output(f"opacapture {archive_path}", changes=True) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/openshift.py b/sos/report/plugins/openshift.py index f90f08dbe2..7e5febcdf5 100644 --- a/sos/report/plugins/openshift.py +++ b/sos/report/plugins/openshift.py @@ -132,9 +132,10 @@ def _check_oc_logged_in(self): token = self.get_option('token') or os.getenv('SOSOCPTOKEN', None) if token: - oc_res = self.exec_cmd("oc login %s --token=%s " - "--insecure-skip-tls-verify=True" - % (self.get_option('host'), token)) + oc_res = self.exec_cmd(f"oc login {self.get_option('host')} " + f"--token={token} " + "--insecure-skip-tls-verify=True") + if oc_res['status'] == 0: if self._check_oc_function(): return True @@ -288,16 +289,14 @@ def collect_cluster_resources(self): for resource in global_resources: _subdir = f"cluster_resources/{resource}" _tag = [f"ocp_{resource}"] - _res = self.collect_cmd_output( - f"{self.oc_cmd} {resource}", - subdir=_subdir, - tags=_tag - ) + _res = self.collect_cmd_output(f"{self.oc_cmd} {resource}", + subdir=_subdir, + tags=_tag) if _res['status'] == 0: for _res_name in _res['output'].splitlines()[1:]: self.add_cmd_output( f"oc describe {resource} {_res_name.split()[0]}", - subdir=_subdir, + subdir=_subdir ) def collect_from_namespace(self, namespace): @@ -347,14 +346,16 @@ def collect_from_namespace(self, namespace): subdir = f"namespaces/{namespace}" # namespace-specific non-resource collections - self.add_cmd_output( - f"oc describe namespace {namespace}", - subdir=subdir - ) + self.add_cmd_output(f"oc describe namespace {namespace}", + subdir=subdir) for res in resources: _subdir = f"{subdir}/{res}" - _tags = [f"ocp_{res}", f"ocp_{namespace}_{res}", namespace] + _tags = [ + f"ocp_{res}", + f"ocp_{namespace}_{res}", + namespace + ] _get_cmd = f"{self.oc_cmd} --namespace={namespace} {res}" # get the 'normal' output first _res_out = self.collect_cmd_output( @@ -421,7 +422,7 @@ def postproc(self): '.*token.*.value' # don't blind match `.*token.*` and lose names ] - regex = r'(\s*(%s):)(.*)' % '|'.join(_fields) + regex = rf'(\s*({"|".join(_fields)}):)(.*)' self.do_path_regex_sub('/etc/kubernetes/*', regex, r'\1 *******') # scrub secret content diff --git a/sos/report/plugins/openssl.py b/sos/report/plugins/openssl.py index 1003f99da0..efbf758acf 100644 --- a/sos/report/plugins/openssl.py +++ b/sos/report/plugins/openssl.py @@ -27,7 +27,7 @@ def postproc(self): "challengePassword" ] - regexp = r"^(\s*#?\s*(%s).*=)(.*)" % "|".join(protect_keys) + regexp = rf"^(\s*#?\s*({'|'.join(protect_keys)}).*=)(.*)" self.do_file_sub( '/etc/ssl/openssl.cnf', diff --git a/sos/report/plugins/openstack_aodh.py b/sos/report/plugins/openstack_aodh.py index dbc4f4f2fd..9d8b3a1835 100644 --- a/sos/report/plugins/openstack_aodh.py +++ b/sos/report/plugins/openstack_aodh.py @@ -79,12 +79,12 @@ def postproc(self): connection_keys = ["connection", "backend_url", "transport_url"] self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)", r"\1*********" ) + # flake8: noqa self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({'|'.join(connection_keys)})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_barbican.py b/sos/report/plugins/openstack_barbican.py index 14a75f1dd1..fa5d61da10 100644 --- a/sos/report/plugins/openstack_barbican.py +++ b/sos/report/plugins/openstack_barbican.py @@ -42,7 +42,7 @@ def postproc(self): ] self.do_file_sub( "/etc/barbican/barbican.conf", - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)", r"\1********" ) @@ -50,8 +50,8 @@ def postproc(self): self.do_path_regex_sub( "/etc/barbican/barbican.conf", - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + # flake8: noqa + rf"(^\s*({'|'.join(connection_keys)})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6") diff --git a/sos/report/plugins/openstack_ceilometer.py b/sos/report/plugins/openstack_ceilometer.py index 5c0acb1ca2..3ab2f6866e 100644 --- a/sos/report/plugins/openstack_ceilometer.py +++ b/sos/report/plugins/openstack_ceilometer.py @@ -60,12 +60,12 @@ def postproc(self): connection_keys = ["connection", "backend_url", "transport_url"] self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)", r"\1*********" ) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + # flake8: noqa + rf"(^\s*({'|'.join(connection_keys)})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_cinder.py b/sos/report/plugins/openstack_cinder.py index 008078f7b8..651d624828 100644 --- a/sos/report/plugins/openstack_cinder.py +++ b/sos/report/plugins/openstack_cinder.py @@ -28,7 +28,7 @@ class OpenStackCinder(Plugin): def setup(self): self.add_forbidden_path('/etc/cinder/volumes') cinder_config = "" - cinder_config_opt = "--config-dir %s/etc/cinder/" + cinder_config_opt = f"--config-dir {self.var_puppet_gen}/etc/cinder/" # check if either standalone (cinder-api) or httpd wsgi (cinder_wsgi) # is up and running @@ -41,8 +41,7 @@ def setup(self): in_container = self.container_exists('.*cinder_api') if in_container: - cinder_config = cinder_config_opt % self.var_puppet_gen - + cinder_config = cinder_config_opt # collect commands output if the standalone, wsgi or container is up if in_ps or in_container: self.add_cmd_output( @@ -111,17 +110,15 @@ def setup(self): self.add_cmd_output(cmd) self.add_forbidden_path('/etc/cinder/volumes') - self.add_copy_spec( - [ - "/etc/cinder/", - f"{self.var_puppet_gen}/etc/cinder/", - f"{self.var_puppet_gen}/etc/httpd/conf/", - f"{self.var_puppet_gen}/etc/httpd/conf.d/", - f"{self.var_puppet_gen}/etc/httpd/conf.modules.d/*.conf", - f"{self.var_puppet_gen}/etc/my.cnf.d/tripleo.cnf", - f"{self.var_puppet_gen}/etc/sysconfig/", - ] - ) + self.add_copy_spec([ + "/etc/cinder/", + f"{self.var_puppet_gen}/etc/cinder/", + f"{self.var_puppet_gen}/etc/httpd/conf/", + f"{self.var_puppet_gen}/etc/httpd/conf.d/", + f"{self.var_puppet_gen}/etc/httpd/conf.modules.d/*.conf", + f"{self.var_puppet_gen}/etc/my.cnf.d/tripleo.cnf", + f"{self.var_puppet_gen}/etc/sysconfig/", + ]) if self.get_option("all_logs"): self.add_copy_spec([ @@ -138,8 +135,7 @@ def apply_regex_sub(self, regexp, subst): self.do_path_regex_sub("/etc/cinder/*", regexp, subst) self.do_path_regex_sub( f"{self.var_puppet_gen}/etc/cinder/*", - regexp, - subst + regexp, subst ) def postproc(self): @@ -158,12 +154,12 @@ def postproc(self): connection_keys = ["connection"] self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)", r"\1*********" ) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + # flake8: noqa + rf"(^\s*({'|'.join(connection_keys)})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_designate.py b/sos/report/plugins/openstack_designate.py index 2c649e45b2..8854a2b5f3 100644 --- a/sos/report/plugins/openstack_designate.py +++ b/sos/report/plugins/openstack_designate.py @@ -69,9 +69,9 @@ def setup(self): ] # commands - self.add_cmd_output( - [f"openstack {sub} --all-projects" for sub in subcmds] - ) + self.add_cmd_output([ + f"openstack {sub} --all-projects" for sub in subcmds + ]) # get recordsets for each zone cmd = "openstack zone list -f value -c id" @@ -81,8 +81,7 @@ def setup(self): zone = zone.split()[0] self.add_cmd_output( f"openstack recordset list --all-projects {zone}", - subdir='recordset', - ) + subdir='recordset') def postproc(self): protect_keys = [ @@ -90,7 +89,7 @@ def postproc(self): "ssl_key_password", "ssl_client_key_password", "memcache_secret_key" ] - regexp = r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + regexp = rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)" self.do_path_regex_sub("/etc/designate/*", regexp, r"\1*********") self.do_path_regex_sub( diff --git a/sos/report/plugins/openstack_glance.py b/sos/report/plugins/openstack_glance.py index 7fbebc40ae..d591ca8e00 100644 --- a/sos/report/plugins/openstack_glance.py +++ b/sos/report/plugins/openstack_glance.py @@ -50,9 +50,8 @@ def setup(self): glance_config = "" # if containerized we need to pass the config to the cont. if in_container: - glance_config = ( - f"--config-dir {self.var_puppet_gen}/etc/glance/" - ) + glance_config = (f"--config-dir {self.var_puppet_gen}" + "/etc/glance/") self.add_cmd_output( f"glance-manage {glance_config} db_version", @@ -93,8 +92,7 @@ def apply_regex_sub(self, regexp, subst): self.do_path_regex_sub("/etc/glance/*", regexp, subst) self.do_path_regex_sub( f"{self.var_puppet_gen}/etc/glance/*", - regexp, - subst + regexp, subst ) def postproc(self): @@ -106,13 +104,14 @@ def postproc(self): ] connection_keys = ["connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_heat.py b/sos/report/plugins/openstack_heat.py index a99acb95c0..bd5321c248 100644 --- a/sos/report/plugins/openstack_heat.py +++ b/sos/report/plugins/openstack_heat.py @@ -32,9 +32,8 @@ def setup(self): heat_config = "" # if containerized we need to pass the config to the cont. if in_container: - heat_config = ( - f"--config-dir {self.var_puppet_gen}_api/etc/heat/" - ) + heat_config = ("--config-dir " + f"{self.var_puppet_gen}_api/etc/heat/") self.add_cmd_output( f"heat-manage {heat_config} db_version", @@ -127,13 +126,14 @@ def postproc(self): ] connection_keys = ["connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_horizon.py b/sos/report/plugins/openstack_horizon.py index 4dcb0faebf..0fd081f006 100644 --- a/sos/report/plugins/openstack_horizon.py +++ b/sos/report/plugins/openstack_horizon.py @@ -51,7 +51,8 @@ def postproc(self): "SECRET_KEY", "EMAIL_HOST_PASSWORD" ] - regexp = r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + keys = "|".join(protect_keys) + regexp = rf"(^\s*({keys})\s*=\s*)(.*)" for regpath in [r"/etc/openstack-dashboard/.*\.json", "/etc/openstack-dashboard/local_settings$"]: self.do_path_regex_sub(regpath, regexp, r"\1*********") diff --git a/sos/report/plugins/openstack_instack.py b/sos/report/plugins/openstack_instack.py index 4e76fac8cc..8bfaa0941a 100644 --- a/sos/report/plugins/openstack_instack.py +++ b/sos/report/plugins/openstack_instack.py @@ -87,12 +87,10 @@ def setup(self): # get status of overcloud stack and resources for _sid in stack_ids: sid = _sid[1] - self.add_cmd_output( - [ - f"openstack stack show {sid}", - f"openstack stack resource list -n 10 {sid}", - ] - ) + self.add_cmd_output([ + f"openstack stack show {sid}", + f"openstack stack resource list -n 10 {sid}", + ]) # get details on failed deployments cmd = f"openstack stack resource list -f value -n 5 {sid}" @@ -107,7 +105,7 @@ def setup(self): continue deploy = deployment.split()[1] cmd = ("openstack software deployment " - "show --long %s" % (deployment)) + f"show --long {deployment}") fname = f"failed-deployment-{deploy}.log" self.add_cmd_output(cmd, suggest_filename=fname) @@ -135,13 +133,15 @@ def postproc(self): "undercloud_swift_password", "undercloud_tuskar_password", ] - regexp = f'(({"|".join(protected_keys)})=)(.*)' + keys = "|".join(protected_keys) + regexp = f'(({keys})=)(.*)' self.do_file_sub("/home/stack/.instack/install-undercloud.log", regexp, r"\1*********") self.do_file_sub(UNDERCLOUD_CONF_PATH, regexp, r"\1*********") protected_json_keys = ["pm_password", "ssh-key", "password"] - json_regexp = f'("({"|".join(protected_json_keys)})": )(".*?")' + keys = "|".join(protected_json_keys) + json_regexp = f'("({keys})": )(".*?")' self.do_file_sub("/home/stack/instackenv.json", json_regexp, r"\1*********") self.do_file_sub('/home/stack/.tripleo/history', diff --git a/sos/report/plugins/openstack_ironic.py b/sos/report/plugins/openstack_ironic.py index 672edd5264..e66dc3d329 100644 --- a/sos/report/plugins/openstack_ironic.py +++ b/sos/report/plugins/openstack_ironic.py @@ -66,13 +66,9 @@ def setup(self): "/var/log/containers/ironic/*.log", "/var/log/containers/ironic-inspector/*.log", ]) - for path in [ - '/var/lib/ironic', - '/httpboot', - '/tftpboot', - f'{self.ins_puppet_gen}/var/lib/httpboot/', - f'{self.ins_puppet_gen}/var/lib/tftpboot/' - ]: + for path in ['/var/lib/ironic', '/httpboot', '/tftpboot', + f'{self.ins_puppet_gen}/var/lib/httpboot/', + f'{self.ins_puppet_gen}/var/lib/tftpboot/']: self.add_cmd_output(f'ls -laRt {path}') self.add_cmd_output(f'ls -laRt {self.var_puppet_gen + path}') @@ -146,14 +142,14 @@ def postproc(self): "os_password", "transport_url" ] connection_keys = ["connection", "sql_connection"] - + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) @@ -188,7 +184,7 @@ def collect_introspection_data(self): if uuid.strip()] for uuid in uuids: self.add_cmd_output('openstack baremetal introspection ' - 'data save %s' % uuid) + f'data save {uuid}') def setup(self): super(RedHatIronic, self).setup() diff --git a/sos/report/plugins/openstack_keystone.py b/sos/report/plugins/openstack_keystone.py index 100792bdb5..6f10150756 100644 --- a/sos/report/plugins/openstack_keystone.py +++ b/sos/report/plugins/openstack_keystone.py @@ -97,21 +97,22 @@ def postproc(self): "admin_password", "admin_token", "ca_password", "transport_url" ] connection_keys = ["connection"] - + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) # obfuscate LDAP plaintext passwords in domain config dir + keys = "|".join(protect_keys) self.do_path_regex_sub( self.domain_config_dir, - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1********" ) diff --git a/sos/report/plugins/openstack_manila.py b/sos/report/plugins/openstack_manila.py index f4f3e22f49..ac352823a8 100644 --- a/sos/report/plugins/openstack_manila.py +++ b/sos/report/plugins/openstack_manila.py @@ -20,10 +20,10 @@ class OpenStackManila(Plugin): var_puppet_gen = "/var/lib/config-data/puppet-generated/manila" def setup(self): - - config_dir = "%s/etc/manila" % ( - self.var_puppet_gen if self.container_exists('.*manila_api') else - '' + # flake8: noqa + config_dir = ( + f"{self.var_puppet_gen if self.container_exists('.*manila_api') else ''}" + f"/etc/manila" ) manila_cmd = f"manila-manage --config-dir {config_dir} db version" self.add_cmd_output(manila_cmd, suggest_filename="manila_db_version") @@ -64,13 +64,15 @@ def postproc(self): "memcache_secret_key"] connection_keys = ["connection", "sql_connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_masakari.py b/sos/report/plugins/openstack_masakari.py index 07def30515..95eba030ee 100644 --- a/sos/report/plugins/openstack_masakari.py +++ b/sos/report/plugins/openstack_masakari.py @@ -58,15 +58,16 @@ def postproc(self): "memcache_secret_key", "rabbit_password"] connection_keys = ["connection", "sql_connection"] + keys = "|".join(protect_keys) self.do_path_regex_sub( f"{self.config_dir}/*", - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.do_path_regex_sub( f"{self.config_dir}/*", - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_masakarimonitors.py b/sos/report/plugins/openstack_masakarimonitors.py index 5e1e83e53f..ad39e56337 100644 --- a/sos/report/plugins/openstack_masakarimonitors.py +++ b/sos/report/plugins/openstack_masakarimonitors.py @@ -47,9 +47,10 @@ def setup(self): def postproc(self): protect_keys = [".*password.*"] + keys = "|".join(protect_keys) self.do_path_regex_sub( f"{self.config_dir}/*", - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) diff --git a/sos/report/plugins/openstack_neutron.py b/sos/report/plugins/openstack_neutron.py index 1efebcfb5a..8cc1838665 100644 --- a/sos/report/plugins/openstack_neutron.py +++ b/sos/report/plugins/openstack_neutron.py @@ -100,13 +100,14 @@ def postproc(self): ] connection_keys = ["connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_nova.py b/sos/report/plugins/openstack_nova.py index be4bbf6fe0..0486adcc66 100644 --- a/sos/report/plugins/openstack_nova.py +++ b/sos/report/plugins/openstack_nova.py @@ -131,11 +131,10 @@ def setup(self): f"{self.var_puppet_gen}_libvirt/etc/nova/migration/", f"{self.var_puppet_gen}_libvirt/var/lib/nova/.ssh/config", ] + list( - filter( - re.compile('^((?!libvirt.+httpd).)*$').match, - [f'{self.var_puppet_gen}{p}{s}' for p in pp for s in sp], - ) - ) + filter(re.compile('^((?!libvirt.+httpd).)*$').match, + [f'{self.var_puppet_gen}{p}{s}' + for p in pp for s in sp + ])) self.add_copy_spec(specs) def apply_regex_sub(self, regexp, subst): @@ -143,9 +142,7 @@ def apply_regex_sub(self, regexp, subst): for p in ['', '_libvirt', '_metadata', '_placement']: self.do_path_regex_sub( f"{self.var_puppet_gen}{p}/etc/nova/*", - regexp, - subst - ) + regexp, subst) def postproc(self): protect_keys = [ @@ -159,13 +156,14 @@ def postproc(self): ] connection_keys = ["connection", "sql_connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_octavia.py b/sos/report/plugins/openstack_octavia.py index e7b91caecd..58f855bef8 100644 --- a/sos/report/plugins/openstack_octavia.py +++ b/sos/report/plugins/openstack_octavia.py @@ -73,8 +73,8 @@ def setup(self): 'OS_TENANT_NAME', 'OS_PROJECT_NAME']] if not (all(vars_all) and any(vars_any)) and not \ - (self.is_installed("python2-octaviaclient") or - self.is_installed("python3-octaviaclient")): + (self.is_installed("python2-octaviaclient") or + self.is_installed("python3-octaviaclient")): self.soslog.warning("Not all environment variables set or " "octavia client package not installed." "Source the environment file for the " @@ -87,10 +87,8 @@ def setup(self): for res in self.resources: # get a list for each resource type - self.add_cmd_output( - f'openstack loadbalancer {res} list', - subdir=res - ) + self.add_cmd_output(f'openstack loadbalancer {res} list', + subdir=res) # get details from each resource cmd = f"openstack loadbalancer {res} list -f value -c id" @@ -98,10 +96,9 @@ def setup(self): if ret['status'] == 0: for ent in ret['output'].splitlines(): ent = ent.split()[0] - self.add_cmd_output( - f"openstack loadbalancer {res} show {ent}", - subdir=res - ) + self.add_cmd_output(f"openstack loadbalancer {res} " + f"show {ent}", + subdir=res) # get capability details from each provider cmd = "openstack loadbalancer provider list -f value -c name" @@ -111,7 +108,7 @@ def setup(self): p = p.split()[0] self.add_cmd_output( "openstack loadbalancer provider capability list" - " %s" % p, + f" {p}", subdir='provider_capability') def postproc(self): @@ -120,7 +117,7 @@ def postproc(self): "connection", "transport_url", "server_certs_key_passphrase", "memcache_secret_key" ] - regexp = r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + regexp = rf"(^\s*({'|'.join(protect_keys)})\s*=\s*)(.*)" self.do_path_regex_sub("/etc/octavia/*", regexp, r"\1*********") self.do_path_regex_sub( diff --git a/sos/report/plugins/openstack_placement.py b/sos/report/plugins/openstack_placement.py index 36496bb262..89100d0f2f 100644 --- a/sos/report/plugins/openstack_placement.py +++ b/sos/report/plugins/openstack_placement.py @@ -100,21 +100,21 @@ def apply_regex_sub(self, regexp, subst): self.do_path_regex_sub("/etc/placement/*", regexp, subst) self.do_path_regex_sub( f"{self.var_puppet_gen}/etc/placement/*", - regexp, - subst + regexp, subst ) def postproc(self): protect_keys = ["password", "memcache_secret_key"] connection_keys = ["database_connection", "slave_connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_sahara.py b/sos/report/plugins/openstack_sahara.py index 691121c14b..ec7ee3637f 100644 --- a/sos/report/plugins/openstack_sahara.py +++ b/sos/report/plugins/openstack_sahara.py @@ -52,13 +52,14 @@ def postproc(self): ] connection_keys = ["connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_swift.py b/sos/report/plugins/openstack_swift.py index 4d3983b9a0..643f3719da 100644 --- a/sos/report/plugins/openstack_swift.py +++ b/sos/report/plugins/openstack_swift.py @@ -61,13 +61,14 @@ def postproc(self): ] connection_keys = ["connection", "sql_connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openstack_trove.py b/sos/report/plugins/openstack_trove.py index 933b51b7f9..e7d87d68be 100644 --- a/sos/report/plugins/openstack_trove.py +++ b/sos/report/plugins/openstack_trove.py @@ -51,13 +51,14 @@ def postproc(self): ] connection_keys = ["connection"] + keys = "|".join(protect_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(protect_keys), + rf"(^\s*({keys})\s*=\s*)(.*)", r"\1*********" ) + keys = "|".join(connection_keys) self.apply_regex_sub( - r"(^\s*(%s)\s*=\s*(.*)://(\w*):)(.*)(@(.*))" % - "|".join(connection_keys), + rf"(^\s*({keys})\s*=\s*(.*)://(\w*):)(.*)(@(.*))", r"\1*********\6" ) diff --git a/sos/report/plugins/openvswitch.py b/sos/report/plugins/openvswitch.py index 21e752abf4..59dc7fefa9 100644 --- a/sos/report/plugins/openvswitch.py +++ b/sos/report/plugins/openvswitch.py @@ -321,7 +321,10 @@ def setup(self): self.add_cmd_output([ f"ovs-appctl cfm/show {port}", f"ovs-appctl qos/show {port}", + # Not all ports are "bond"s, but all "bond"s are + # a single port f"ovs-appctl bond/show {port}", + # In the case of IPSec, we should pull the config f"ovs-vsctl get Interface {port} options", ]) diff --git a/sos/report/plugins/origin.py b/sos/report/plugins/origin.py index 5ec1a7604a..30b62330ae 100644 --- a/sos/report/plugins/origin.py +++ b/sos/report/plugins/origin.py @@ -100,12 +100,10 @@ def setup(self): if self.is_static_pod_compatible(): self.add_copy_spec(self.path_join(self.static_pod_dir, "*.yaml")) - self.add_cmd_output( - [ - f"{static_pod_logs_cmd} api api", - f"{static_pod_logs_cmd} controllers controllers", - ] - ) + self.add_cmd_output([ + f"{static_pod_logs_cmd} api api", + f"{static_pod_logs_cmd} controllers controllers", + ]) if self.is_static_etcd(): self.add_cmd_output(f"{static_pod_logs_cmd} etcd etcd") @@ -133,9 +131,9 @@ def setup(self): "adm top nodes" ] - self.add_cmd_output( - [f"{oc_cmd_admin} {subcmd}" for subcmd in subcmds] - ) + self.add_cmd_output([ + f"{oc_cmd_admin} {subcmd}" for subcmd in subcmds + ]) jcmds = [ "hostsubnet", @@ -143,9 +141,9 @@ def setup(self): "netnamespaces" ] - self.add_cmd_output( - [f"{oc_cmd_admin} get -o json {jcmd}" for jcmd in jcmds] - ) + self.add_cmd_output([ + f"{oc_cmd_admin} get -o json {jcmd}" for jcmd in jcmds + ]) nmsps = [ 'default', diff --git a/sos/report/plugins/ovirt.py b/sos/report/plugins/ovirt.py index 924547697b..8c009b4430 100644 --- a/sos/report/plugins/ovirt.py +++ b/sos/report/plugins/ovirt.py @@ -111,16 +111,15 @@ def setup(self): "engine-config -d", ]) - self.add_cmd_output( - [f"openssl x509 -in {c} -text -noout" for c in certificates] - ) + self.add_cmd_output([ + # process certificate files + f"openssl x509 -in {c} -text -noout" for c in certificates + ]) - self.add_cmd_output( - [ - f"keytool -list -storepass {p} -rfc -keystore {c}" - for (p, c) in keystores - ] - ) + self.add_cmd_output([ + f"keytool -list -storepass {p} -rfc -keystore {c}" + for (p, c) in keystores + ]) # 3.x line uses engine-manage-domains, 4.x uses ovirt-aaa-jdbc-tool manage_domains = 'engine-manage-domains' @@ -235,8 +234,9 @@ def postproc(self): if keys_opt and keys_opt is not True: sensitive_keys = keys_opt key_list = [x for x in sensitive_keys.split(':') if x] + keys = "|".join(key_list) self.do_path_regex_sub( - self.DB_PASS_FILES, f'({"|".join(key_list)})=(.*)', r'\1=********' + self.DB_PASS_FILES, f'({keys})=(.*)', r'\1=********' ) # Answer files contain passwords. @@ -261,7 +261,7 @@ def postproc(self): "pool.default.ssl.truststore.password", "config.datasource.dbpassword" ] - regexp = r"(^\s*#*(%s)\s*=\s*)(.*)" % "|".join(protect_keys) + regexp = rf"(^\s*#*({'|'.join(protect_keys)})\s*=\s*)(.*)" self.do_path_regex_sub(r"/etc/ovirt-engine/aaa/.*\.properties", regexp, r"\1*********") diff --git a/sos/report/plugins/ovirt_engine_backup.py b/sos/report/plugins/ovirt_engine_backup.py index 27f1dd1880..bf9df5346b 100644 --- a/sos/report/plugins/ovirt_engine_backup.py +++ b/sos/report/plugins/ovirt_engine_backup.py @@ -37,11 +37,8 @@ def setup(self): f"engine-db-backup-{now}.log" ) cmd = ("engine-backup --mode=backup --scope=db" - " --file=%s --log=%s --tmpdir=%s") % ( - backup_filename, - log_filename, - self.get_option("tmpdir") - ) + f" --file={backup_filename} --log={log_filename} " + f"--tmpdir={self.get_option('tmpdir')}") res = self.collect_cmd_output(cmd, suggest_filename="engine-backup") if res['status'] == 0: self.add_copy_spec([ diff --git a/sos/report/plugins/ovirt_node.py b/sos/report/plugins/ovirt_node.py index 8e48f01c7d..491dae4a0e 100644 --- a/sos/report/plugins/ovirt_node.py +++ b/sos/report/plugins/ovirt_node.py @@ -49,9 +49,9 @@ def setup(self): ]) # Collect certificate info - self.add_cmd_output( - [f'openssl x509 -in {c} -text -noout' for c in certificates] - ) + self.add_cmd_output([ + f'openssl x509 -in {c} -text -noout' for c in certificates + ]) # vim: expandtab tabstop=4 shiftwidth=4 diff --git a/sos/report/plugins/ovn_central.py b/sos/report/plugins/ovn_central.py index eaec566457..d6492b9947 100644 --- a/sos/report/plugins/ovn_central.py +++ b/sos/report/plugins/ovn_central.py @@ -33,7 +33,7 @@ def _find_sock(self, path, regex_name): if res['status'] != 0 or '\n' not in res['output']: self._log_error( "Could not retrieve ovn_controller socket path " - "from container %s" % self._container_name + f"from container {self._container_name}" ) else: pattern = re.compile(regex_name) @@ -50,7 +50,7 @@ def get_tables_from_schema(self, filename, skip=[]): container=self._container_name) if res['status'] != 0: self._log_error("Could not retrieve DB schema file from " - "container %s" % self._container_name) + f"container {self._container_name}") return None try: db = json.loads(res['output']) diff --git a/sos/report/plugins/pacemaker.py b/sos/report/plugins/pacemaker.py index cf11e2197b..c45fcc63ee 100644 --- a/sos/report/plugins/pacemaker.py +++ b/sos/report/plugins/pacemaker.py @@ -106,8 +106,8 @@ def setup(self): crm_from = self.get_option("crm_from") else: self._log_error( - "crm_from parameter '%s' is not a valid date: using " - "default" % self.get_option("crm_from")) + f"crm_from parameter '{self.get_option('crm_from')}' is " + "not a valid date: using default") crm_dest = self.get_cmd_output_path(name="crm_report", make=False) if self.get_option("crm_scrub"): @@ -117,9 +117,8 @@ def setup(self): self._log_warn("scrubbing of crm passwords has been disabled:") self._log_warn("data collected by crm_report may contain" " sensitive values.") - self.add_cmd_output('crm_report --sos-mode %s -S -d ' - ' --dest %s --from "%s"' % - (crm_scrub, crm_dest, crm_from), + self.add_cmd_output(f'crm_report --sos-mode {crm_scrub} -S -d ' + f' --dest {crm_dest} --from "{crm_from}"', chroot=self.tmp_in_sysroot()) # collect user-defined logfiles, matching a shell-style syntax: diff --git a/sos/report/plugins/perccli.py b/sos/report/plugins/perccli.py index ca889c9ee3..8c33e5faf5 100644 --- a/sos/report/plugins/perccli.py +++ b/sos/report/plugins/perccli.py @@ -45,8 +45,7 @@ def setup(self): self.add_cmd_output( f"{cmd} {subcmd}{json}", suggest_filename=f"perccli64_{subcmd}{json}", - runat=logpath, - ) + runat=logpath) # /call show events need 'file=' option to get adapter info like below # "Adapter: # - Number of Events: xxx". @@ -54,7 +53,6 @@ def setup(self): self.add_cmd_output( f"{cmd} {subcmd} file=/dev/stdout{json}", suggest_filename=f"perccli64_{subcmd}{json}", - runat=logpath, - ) + runat=logpath) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/podman.py b/sos/report/plugins/podman.py index 9edf2761ed..bc743b55d4 100644 --- a/sos/report/plugins/podman.py +++ b/sos/report/plugins/podman.py @@ -88,11 +88,9 @@ def setup(self): tags='podman_list_networks') if pnets['status'] == 0: nets = [pn.split()[0] for pn in pnets['output'].splitlines()[1:]] - self.add_cmd_output( - [f"podman network inspect {net}" for net in nets], - subdir='networks', - tags='podman_network_inspect', - ) + self.add_cmd_output([ + f"podman network inspect {net}" for net in nets + ], subdir='networks', tags='podman_network_inspect') containers = [ c[0] for c in self.get_containers(runtime='podman', @@ -102,35 +100,27 @@ def setup(self): volumes = self.get_container_volumes(runtime='podman') for container in containers: - self.add_cmd_output( - f"podman inspect {container}", - subdir='containers', - tags='podman_container_inspect', - ) + self.add_cmd_output(f"podman inspect {container}", + subdir='containers', + tags='podman_container_inspect') for img in images: name, img_id = img insp = name if 'none' not in name else img_id - self.add_cmd_output( - f"podman inspect {insp}", - subdir='images', - tags='podman_image_inspect', - ) + self.add_cmd_output(f"podman inspect {insp}", + subdir='images', + tags='podman_image_inspect') for vol in volumes: - self.add_cmd_output( - f"podman volume inspect {vol}", - subdir='volumes', - tags='podman_volume_inspect', - ) + self.add_cmd_output(f"podman volume inspect {vol}", + subdir='volumes', + tags='podman_volume_inspect') if self.get_option('logs'): for con in containers: - self.add_cmd_output( - f"podman logs -t {con}", - subdir="containers", - priority=50 - ) + self.add_cmd_output(f"podman logs -t {con}", + subdir="containers", + priority=50) def postproc(self): # Attempts to match key=value pairs inside container inspect output diff --git a/sos/report/plugins/postgresql.py b/sos/report/plugins/postgresql.py index 38b1ab58da..f327fe2597 100644 --- a/sos/report/plugins/postgresql.py +++ b/sos/report/plugins/postgresql.py @@ -55,17 +55,13 @@ def do_pg_dump(self, scl=None, filename="pgdump.tar"): os.environ["PGPASSWORD"] = self.get_option("password") if self.get_option("dbhost"): - cmd = ( - f'pg_dump -U {self.get_option("username")} -h' - f' {self.get_option("dbhost")} -p' - f' {self.get_option("dbport")} -w -F t' - f' {self.get_option("dbname")}' - ) + cmd = (f'pg_dump -U {self.get_option("username")} -h' + f' {self.get_option("dbhost")} -p' + f' {self.get_option("dbport")} -w -F t' + f' {self.get_option("dbname")}') else: - cmd = ( - f'pg_dump -C -U {self.get_option("username")} -w -F t' - f' {self.get_option("dbname")} ' - ) + cmd = (f'pg_dump -C -U {self.get_option("username")} -w ' + f'-F t {self.get_option("dbname")} ') if scl is not None: cmd = self.convert_cmd_scl(scl, cmd) diff --git a/sos/report/plugins/powerpc.py b/sos/report/plugins/powerpc.py index 2c7a797f1b..d8c7122586 100644 --- a/sos/report/plugins/powerpc.py +++ b/sos/report/plugins/powerpc.py @@ -92,7 +92,7 @@ def setup(self): f"ctsnap -xrunrpttr -d {ctsnap_path}", "lsdevinfo", "lsslot", - "amsstat", + "amsstat" ]) # Due to the lack of options in invscout for generating log files diff --git a/sos/report/plugins/process.py b/sos/report/plugins/process.py index c53e377c46..89c5b5c284 100644 --- a/sos/report/plugins/process.py +++ b/sos/report/plugins/process.py @@ -82,10 +82,9 @@ def setup(self): ]) if self.get_option("samples"): - self.add_cmd_output( - f'iotop -b -o -d 0.5 -t -n {self.get_option("samples")}', - priority=100, - ) + self.add_cmd_output(f'iotop -b -o -d 0.5 -t -n ' + f'{self.get_option("samples")}', + priority=100) self.add_cmd_output([ "pidstat -p ALL -rudvwsRU --human -h", diff --git a/sos/report/plugins/pulp.py b/sos/report/plugins/pulp.py index d26f286951..6b4fc33125 100644 --- a/sos/report/plugins/pulp.py +++ b/sos/report/plugins/pulp.py @@ -85,20 +85,20 @@ def setup(self): num_tasks = self.get_option('tasks') mtasks = self.build_mongo_cmd( - '\"DBQuery.shellBatchSize=%s;; ' + f'\"DBQuery.shellBatchSize={num_tasks};; ' 'db.task_status.find().sort({finish_time: -1})' - '.pretty().shellPrint()\"' % num_tasks + '.pretty().shellPrint()\"' ) mres = self.build_mongo_cmd( - '\"DBQuery.shellBatchSize=%s;; ' - 'db.reserved_resources.find().pretty().shellPrint()\"' % num_tasks + f'\"DBQuery.shellBatchSize={num_tasks};; ' + 'db.reserved_resources.find().pretty().shellPrint()\"' ) prun = self.build_mongo_cmd( - r'"DBQuery.shellBatchSize=%s;; ' + rf'"DBQuery.shellBatchSize={num_tasks};; ' r'db.task_status.find({state:{\$ne: \"finished\"}}).pretty()' - r'.shellPrint()"' % num_tasks + r'.shellPrint()"' ) # prints mongo collection sizes sorted from biggest and in human @@ -147,13 +147,11 @@ def setup(self): ) def build_mongo_cmd(self, query): - _cmd = "bash -c %s" - _mondb = ( - f"--host {self.dbhost} --port" - f" {self.dbport} {self.dbuser} {self.dbpassword}" - ) - _moncmd = "mongo pulp_database %s --eval %s" - return _cmd % quote(_moncmd % (_mondb, query)) + _cmd = "bash -c {}" + _mondb = (f"--host {self.dbhost} --port" + f" {self.dbport} {self.dbuser} {self.dbpassword}") + _moncmd = "mongo pulp_database {} --eval {}" + return f"{_cmd.format(quote(_moncmd.format(_mondb, query)))}" def postproc(self): diff --git a/sos/report/plugins/pulpcore.py b/sos/report/plugins/pulpcore.py index 2cd8db0b0b..bdf8c6b305 100644 --- a/sos/report/plugins/pulpcore.py +++ b/sos/report/plugins/pulpcore.py @@ -58,14 +58,15 @@ def separate_value(line, sep=':'): continue # example HOST line to parse: # 'HOST': 'localhost', - pattern = r"\s*['|\"]%s['|\"]\s*:\s*\S+" - if databases_scope and match(pattern % 'HOST', line): + pattern = r"\s*['|\"]{}['|\"]\s*:\s*\S+" + if databases_scope and match(pattern.format('HOST'), line): self.dbhost = separate_value(line) - if databases_scope and match(pattern % 'PORT', line): + if databases_scope and match(pattern.format('PORT'), line): self.dbport = separate_value(line) - if databases_scope and match(pattern % 'NAME', line): + if databases_scope and match(pattern.format('NAME'), line): self.dbname = separate_value(line) - if databases_scope and match(pattern % 'PASSWORD', line): + if databases_scope and match(pattern.format('PASSWORD'), + line): self.dbpasswd = separate_value(line) # if line contains closing '}' database_scope end if databases_scope and '}' in line: @@ -104,10 +105,9 @@ def setup(self): task_days = self.get_option('task-days') for table in ['core_task', 'core_taskgroup', 'core_groupprogressreport', 'core_progressreport']: - _query = ( - f"select * from {table} where pulp_last_updated > NOW()" - f" - interval '{task_days} days' order by pulp_last_updated" - ) + _query = (f"select * from {table} where pulp_last_updated > NOW()" + f" - interval '{task_days} days' order by " + "pulp_last_updated") _cmd = self.build_query_cmd(_query) self.add_cmd_output(_cmd, env=self.env, suggest_filename=table) @@ -139,10 +139,11 @@ def build_query_cmd(self, query, csv=False): a large amount of quoting in sos logs referencing the command being run """ if csv: - query = "COPY (%s) TO STDOUT " \ - "WITH (FORMAT 'csv', DELIMITER ',', HEADER)" % query - _dbcmd = "psql --no-password -h %s -p %s -U pulp -d %s -c %s" - return _dbcmd % (self.dbhost, self.dbport, self.dbname, quote(query)) + query = (f"COPY ({query}) TO STDOUT " + "WITH (FORMAT 'csv', DELIMITER ',', HEADER)") + _dbcmd = (f"psql --no-password -h {self.dbhost} -p {self.dbport} " + f"-U pulp -d {self.dbname} -c {quote(query)}") + return _dbcmd def postproc(self): # obfuscate from /etc/pulp/settings.py and "dynaconf list": diff --git a/sos/report/plugins/puppet.py b/sos/report/plugins/puppet.py index ee6f77246c..1ebfba92e0 100644 --- a/sos/report/plugins/puppet.py +++ b/sos/report/plugins/puppet.py @@ -56,7 +56,7 @@ def postproc(self): self.do_file_sub( device_conf, r"(.*url*.ssh://.*:).*(@.*)", - r"\1%s\2" % ('***') + r"\1***\2" ) return diff --git a/sos/report/plugins/python.py b/sos/report/plugins/python.py index 32b700b8b5..f711b953af 100644 --- a/sos/report/plugins/python.py +++ b/sos/report/plugins/python.py @@ -105,9 +105,8 @@ def get_hashes(self): 'sha256': digest }) except IOError: - self._log_error( - f"Unable to read python file at {filepath}" - ) + self._log_error("Unable to read python file at " + f"{filepath}") return digests # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/qaucli.py b/sos/report/plugins/qaucli.py index b1b5d40759..47bdbf150c 100644 --- a/sos/report/plugins/qaucli.py +++ b/sos/report/plugins/qaucli.py @@ -24,13 +24,11 @@ def setup(self): for subcmd in subcmds: self.add_cmd_output( f"{cmd} {subcmd}", - suggest_filename=f"qaucli_{subcmd}" - ) + suggest_filename=f"qaucli_{subcmd}") result = self.collect_cmd_output( f"{cmd} -i", - suggest_filename="qaucli_-i" - ) + suggest_filename="qaucli_-i") if result['status'] == 0: for line in result['output'].splitlines(): @@ -38,7 +36,6 @@ def setup(self): hba = line.split(':')[1].strip() self.add_cmd_output( f"{cmd} -l {hba}", - suggest_filename=f"qaucli_-l_{hba}" - ) + suggest_filename=f"qaucli_-l_{hba}") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/qpid.py b/sos/report/plugins/qpid.py index 0d40e91efb..e9d33e5791 100644 --- a/sos/report/plugins/qpid.py +++ b/sos/report/plugins/qpid.py @@ -39,10 +39,8 @@ def setup(self): amqps_prefix = "amqps://" options = f"{options} --{option}={self.get_option(option)}" if self.get_option("port"): - options = ( - f"{options} -b {amqps_prefix}" - + f'localhost:{self.get_option("port")}' - ) + options = (f"{options} -b {amqps_prefix}" + f'localhost:{self.get_option("port")}') self.add_cmd_output([ f"qpid-stat -g{options}", diff --git a/sos/report/plugins/qpid_dispatch.py b/sos/report/plugins/qpid_dispatch.py index e8abd4b7a4..9928ae29de 100644 --- a/sos/report/plugins/qpid_dispatch.py +++ b/sos/report/plugins/qpid_dispatch.py @@ -35,9 +35,8 @@ def setup(self): """ performs data collection for qpid dispatch router """ options = "" if self.get_option("port"): - options = ( - f"{options} -b {gethostname()}" + f':{self.get_option("port")}' - ) + options = (f"{options} -b {gethostname()}" + f':{self.get_option("port")}') # gethostname() is due to DISPATCH-156 # for either present option, add --option=value to 'options' variable diff --git a/sos/report/plugins/redis.py b/sos/report/plugins/redis.py index 5963a50b6a..3703882138 100644 --- a/sos/report/plugins/redis.py +++ b/sos/report/plugins/redis.py @@ -54,16 +54,14 @@ def setup(self): def postproc(self): - for path in [ - "/etc/", - f"{self.var_puppet_gen}/etc/", - "/etc/opt/rh/rh-redis32/", - "/etc/opt/rh/rh-redis5/" - ]: + for path in ["/etc/", + f"{self.var_puppet_gen}/etc/", + "/etc/opt/rh/rh-redis32/", + "/etc/opt/rh/rh-redis5/"]: self.do_file_sub( f"{path}redis.conf", r"(masterauth|requirepass)\s.*", - r"\1 ********", + r"\1 ********" ) # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/rhui.py b/sos/report/plugins/rhui.py index 230b2130ed..cf2c8fad57 100644 --- a/sos/report/plugins/rhui.py +++ b/sos/report/plugins/rhui.py @@ -56,7 +56,7 @@ def postproc(self): for cookie in ["csrftoken", "sessionid"]: self.do_path_regex_sub( r"/root/\.rhui/.*/cookies.txt", - r"(%s\s+)(\S+)" % cookie, + rf"({cookie}\s+)(\S+)", r"\1********") diff --git a/sos/report/plugins/rpm.py b/sos/report/plugins/rpm.py index 1e4caeefc6..0f184573fc 100644 --- a/sos/report/plugins/rpm.py +++ b/sos/report/plugins/rpm.py @@ -30,10 +30,10 @@ def setup(self): self.add_cmd_output("ls -lanR /var/lib/rpm") if self.get_option("rpmq"): - rpmq = "rpm --nodigest -qa --qf=%s" # basic installed-rpms nvra = '"%-59{NVRA} %{INSTALLTIME:date}\n"' - irpms = f"sh -c '{rpmq} | sort -V'" % nvra + rpmq = f"rpm --nodigest -qa --qf={nvra}" + irpms = f"sh -c '{rpmq} | sort -V'" self.add_cmd_output(irpms, root_symlink='installed-rpms', tags='installed_rpms') diff --git a/sos/report/plugins/saphana.py b/sos/report/plugins/saphana.py index 11fb096df5..f7335efe24 100644 --- a/sos/report/plugins/saphana.py +++ b/sos/report/plugins/saphana.py @@ -31,26 +31,18 @@ def setup(self): sidadm = f'{sid.lower()}adm' prefix = f'su - {sidadm} -c' - self.add_cmd_output( - f'{prefix} "HDB info"', - suggest_filename=f"{sid}_HDB_info" - ) - - self.add_cmd_output( - f'{prefix} "hdbsrvutil -v"', - suggest_filename=f"{sid}_version", - ) - - self.add_cmd_output( - f'{prefix} \'hdbcons "mm l -s -S -p"\'', - suggest_filename=f"{sid}_memusage", - ) - - self.add_cmd_output( - f'{prefix} \'hdbcons -e hdbindexserver' - ' "replication info"\'', - suggest_filename=f"{sid}_replicainfo", - ) + self.add_cmd_output(f'{prefix} "HDB info"', + suggest_filename=f"{sid}_HDB_info") + + self.add_cmd_output(f'{prefix} "hdbsrvutil -v"', + suggest_filename=f"{sid}_version") + + self.add_cmd_output(f'{prefix} \'hdbcons "mm l -s -S -p"\'', + suggest_filename=f"{sid}_memusage") + + self.add_cmd_output(f'{prefix} \'hdbcons -e hdbindexserver' + ' "replication info"\'', + suggest_filename=f"{sid}_replicainfo") if self.path_isdir(f"/hana/shared/{sid}/"): for inst in self.listdir(f"/hana/shared/{sid}/"): @@ -59,7 +51,8 @@ def setup(self): self.get_inst_info(sid, sidadm, inst) def get_inst_info(self, sid, sidadm, inst): - proc_cmd = 'su - %s -c "sapcontrol -nr %s -function GetProcessList"' + proc_cmd = (f'su - {sid} -c "sapcontrol -nr {inst} -function ' + 'GetProcessList"') status_fname = f"{sid}_{inst}_status" self.add_cmd_output( proc_cmd % (sidadm, inst), @@ -68,10 +61,11 @@ def get_inst_info(self, sid, sidadm, inst): path = f"/usr/sap/{sid}/HDB{inst}/exe/python_support" if self.path_isdir(path): - py_cmd = 'su - %s -c "python %s/landscapeHostConfiguration.py"' + py_cmd = (f'su - {sidadm} -c "python ' + f'{path}/landscapeHostConfiguration.py"') py_fname = f"{sid}_{inst}_landscapeConfig" self.add_cmd_output( - py_cmd % (sidadm, path), + py_cmd, suggest_filename=py_fname ) diff --git a/sos/report/plugins/sapnw.py b/sos/report/plugins/sapnw.py index 6dbd505022..ce961f9d42 100644 --- a/sos/report/plugins/sapnw.py +++ b/sos/report/plugins/sapnw.py @@ -26,10 +26,10 @@ def collect_list_instances(self): return # set the common strings that will be formatted later in each a_c_s - prof_cmd = "env -i %s %s/sappfpar all pf=/usr/sap/%s/SYS/profile/%s" - inst_cmd = "env -i %s %s/sapcontrol -nr %s -function GetProcessList" - vers_cmd = "env -i %s %s/sapcontrol -nr %s -function GetVersionInfo" - user_cmd = 'su - %sadm -c "sapcontrol -nr %s -function GetEnvironment"' + prof_cmd = "env -i {} {}/sappfpar all pf=/usr/sap/{}/SYS/profile/{}" + inst_cmd = "env -i {} {}/sapcontrol -nr {} -function GetProcessList" + vers_cmd = "env -i {} {}/sapcontrol -nr {} -function GetVersionInfo" + user_cmd = 'su - {}adm -c "sapcontrol -nr {} -function GetEnvironment"' sidsunique = set() # Cycle through all the instances, get 'sid', 'instance_number' @@ -57,19 +57,19 @@ def collect_list_instances(self): # collect profiles self.add_cmd_output( - prof_cmd % (ldenv, pt, sid, profile), + prof_cmd.format(ldenv, pt, sid, profile), suggest_filename=f"{profile}_parameters", ) # collect instance status self.add_cmd_output( - inst_cmd % (ldenv, pt, inst), + inst_cmd.format(ldenv, pt, inst), suggest_filename=f"{sid}_{inst}_GetProcList", ) # collect version info for the various components self.add_cmd_output( - vers_cmd % (ldenv, pt, inst), + vers_cmd.format(ldenv, pt, inst), suggest_filename=f"{sid}_{inst}_GetVersInfo", ) @@ -77,7 +77,7 @@ def collect_list_instances(self): lowsid = sid.lower() fname = f"{sid}_{lowsid}adm_{inst}_userenv" self.add_cmd_output( - user_cmd % (lowsid, inst), + user_cmd.format(lowsid, inst), suggest_filename=fname ) @@ -105,7 +105,7 @@ def collect_list_dbs(self): if dbtype == 'db6': # IBM DB2 self.add_cmd_output( - "su - %s -c \"db2 get dbm cfg\"" % dbadm, + f"su - {dbadm} -c \"db2 get dbm cfg\"", suggest_filename=f"{sid}_{dbadm}_db2_info", ) diff --git a/sos/report/plugins/sar.py b/sos/report/plugins/sar.py index 818963e8a8..90db3c5584 100644 --- a/sos/report/plugins/sar.py +++ b/sos/report/plugins/sar.py @@ -80,9 +80,8 @@ def setup(self): continue except Exception as err: self._log_warn( - "Could not determine age of '%s' - skipping " - "converting to sar format: %s" - % (sa_data_path, err) + f"Could not determine age of '{sa_data_path}' " + f"- skipping converting to sar format: {err}" ) continue sar_cmd = f"sar -A -f {sa_data_path}" diff --git a/sos/report/plugins/seagate_ses.py b/sos/report/plugins/seagate_ses.py index f3fd24db22..c0161a58ef 100644 --- a/sos/report/plugins/seagate_ses.py +++ b/sos/report/plugins/seagate_ses.py @@ -59,11 +59,12 @@ def setup(self): for devid in devices: self.add_cmd_output([ - "%s %d -CLI %s" % (cmd, devid, subcmd) for subcmd in subcmds + f"{cmd} {devid} -CLI {subcmd}" for subcmd in subcmds ]) self.add_cmd_output([ - "%s %d -cli %s" % (cmd, devid, subcmd) for subcmd in subcmds + f"{cmd} {devid} -cli {subcmd}" for subcmd in subcmds ]) + # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/shmcli.py b/sos/report/plugins/shmcli.py index 460db79f7f..9309e1dd0d 100644 --- a/sos/report/plugins/shmcli.py +++ b/sos/report/plugins/shmcli.py @@ -78,17 +78,14 @@ def setup(self): adapt_index = _line[-1] enc_index = _line[0] for subcmd in subcmds: - _cmd = ( - f"{cmd} {subcmd} -a={adapt_index} -enc={enc_index}" - ) + _cmd = (f"{cmd} {subcmd} -a={adapt_index} " + f"-enc={enc_index}") _fname = _cmd.replace(cmd, 'shmcli') self.add_cmd_output(_cmd, suggest_filename=_fname) if self.get_option('debug'): logpath = self.get_cmd_output_path(make=False) - _dcmd = ( - f"{cmd} getdebugcli" - f" -a={adapt_index} -enc={enc_index}" - ) + _dcmd = (f"{cmd} getdebugcli -a={adapt_index} " + f"-enc={enc_index}") _dname = _dcmd.replace(cmd, 'shmcli') _odir = f" -outputdir={logpath}" self.add_cmd_output( diff --git a/sos/report/plugins/slurm.py b/sos/report/plugins/slurm.py index aeda9d5be0..3aa64a4d5b 100644 --- a/sos/report/plugins/slurm.py +++ b/sos/report/plugins/slurm.py @@ -121,7 +121,8 @@ def postproc(self): 'AccountingStoragePass', 'JobCompPass', ] - slurm_keys_regex = r"(^\s*(%s)\s*=\s*)(.*)" % "|".join(slurm_keys) + keys = "|".join(slurm_keys) + slurm_keys_regex = rf"(^\s*({keys})\s*=\s*)(.*)" slurmdbd_key_regex = r'(^\s*(StoragePass)\s*=\s*)(.*)' sub = r'\1********' diff --git a/sos/report/plugins/smclient.py b/sos/report/plugins/smclient.py index 85199c540a..366780aeca 100644 --- a/sos/report/plugins/smclient.py +++ b/sos/report/plugins/smclient.py @@ -55,7 +55,8 @@ def do_debug(self, ssnames): subcmd = 'save storageArray supportData file=' for ssname in ssnames: self.add_cmd_output( - "%s %s -c '%s\"support-%s\";'" % (cmd, ssname, subcmd, ssname), + f"{cmd} {ssname} -c '{subcmd}\"support-{ssname}\";'", runat=logpath, timeout=450) + # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/sos_extras.py b/sos/report/plugins/sos_extras.py index c795244d29..b2125dc46d 100644 --- a/sos/report/plugins/sos_extras.py +++ b/sos/report/plugins/sos_extras.py @@ -48,13 +48,12 @@ def setup(self): st = os.stat(self.extras_dir) if (st.st_uid != 0) or (st.st_mode & stat.S_IWGRP) or \ (st.st_mode & stat.S_IWOTH): - self._log_warn("Skipping sos extras as %s has too wide" - " permissions or ownership." % self.extras_dir) + self._log_warn(f"Skipping sos extras as {self.extras_dir} has" + " too wide permissions or ownership.") return except OSError: - self._log_warn( - f"can't stat {self.extras_dir}, skipping sos extras" - ) + self._log_warn(f"can't stat {self.extras_dir}, skipping sos " + "extras") return for path, dirlist, filelist in os.walk(self.extras_dir): diff --git a/sos/report/plugins/subscription_manager.py b/sos/report/plugins/subscription_manager.py index 93caffbe68..2404ab28e1 100644 --- a/sos/report/plugins/subscription_manager.py +++ b/sos/report/plugins/subscription_manager.py @@ -46,10 +46,8 @@ def get_server_url(self, config): # if port is set, prepend it by ':' separating it from hostname if len(port) > 0: port = f":{port}" - return ( - f"http{secure}://{config.get('server', 'hostname')}" - f"{port}{config.get('server', 'prefix')}" - ) + return (f"http{secure}://{config.get('server', 'hostname')}" + f"{port}{config.get('server', 'prefix')}") def setup(self): # rhsm config and logs @@ -74,30 +72,24 @@ def setup(self): "subscription-manager status", ], cmd_as_tag=True) self.add_cmd_output("rhsm-debug system --sos --no-archive " - "--no-subscriptions --destination %s" - % self.get_cmd_output_path()) + "--no-subscriptions --destination " + f"{self.get_cmd_output_path()}") certs = glob.glob('/etc/pki/product-default/*.pem') - self.add_cmd_output( - [f"rct cat-cert {cert}" for cert in certs], - tags='subscription_manager_installed_product_ids', - ) + self.add_cmd_output([f"rct cat-cert {cert}" for cert in certs], + tags='subscription_manager_installed_product_ids') # try curl to the RHSM server for potential certificate/proxy issue - curlcmd = ( - "curl -vv --cacert /etc/rhsm/ca/redhat-uep.pem" - " https://subscription.rhsm.redhat.com:443/subscription" - ) + curlcmd = ("curl -vv --cacert /etc/rhsm/ca/redhat-uep.pem" + " https://subscription.rhsm.redhat.com:443/subscription") env = None # for no_proxy try: from rhsm.config import get_config_parser config = get_config_parser() proxy = self.get_proxy_string(config) server_url = self.get_server_url(config) - curlcmd = ( - f"curl -vv {server_url} --cacert" - f" {config.get('rhsm', 'repo_ca_cert')} {proxy}" - ) + curlcmd = (f"curl -vv {server_url} --cacert" + f" {config.get('rhsm', 'repo_ca_cert')} {proxy}") # honour os.environ no_proxy, if set no_proxy = config.get('server', 'no_proxy') if no_proxy: diff --git a/sos/report/plugins/tomcat.py b/sos/report/plugins/tomcat.py index efa57a7c59..92b876fc4b 100644 --- a/sos/report/plugins/tomcat.py +++ b/sos/report/plugins/tomcat.py @@ -47,9 +47,10 @@ def setup(self): def postproc(self): serverXmlPasswordAttributes = ['keyPass', 'keystorePass', 'truststorePass', 'SSLPassword'] + attributes = "|".join(serverXmlPasswordAttributes) self.do_path_regex_sub( r"\/etc\/tomcat.*\/server.xml", - r"(%s)=(\S*)" % "|".join(serverXmlPasswordAttributes), + rf"({attributes})=(\S*)", r'\1="********"' ) self.do_path_regex_sub( diff --git a/sos/report/plugins/ubuntu.py b/sos/report/plugins/ubuntu.py index 391933a8bd..6706bf2486 100644 --- a/sos/report/plugins/ubuntu.py +++ b/sos/report/plugins/ubuntu.py @@ -33,10 +33,8 @@ def setup(self): ua_pred = SoSPredicate(self, kmods=['tls']) self.add_cmd_output(ua_tools_status, pred=ua_pred, changes=True) - self.add_cmd_output( - f"{ua_tools_status} --format json", - pred=ua_pred, changes=True - ) + self.add_cmd_output(f"{ua_tools_status} --format json", + pred=ua_pred, changes=True) if not self.get_option("all_logs"): self.add_copy_spec([ diff --git a/sos/report/plugins/ultrapath.py b/sos/report/plugins/ultrapath.py index 8e65ce2b3c..e0742b76d6 100644 --- a/sos/report/plugins/ultrapath.py +++ b/sos/report/plugins/ultrapath.py @@ -34,8 +34,7 @@ def setup(self): if result['status'] == 0: for line in result['output'].splitlines(): if line.startswith("Array ID :"): - self.add_cmd_output( - f"upadm show lun array={line.split(':')[1].strip()}" - ) + self.add_cmd_output("upadm show lun array=" + f"{line.split(':')[1].strip()}") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/vdsm.py b/sos/report/plugins/vdsm.py index 94f295c4b2..9c378d96ab 100644 --- a/sos/report/plugins/vdsm.py +++ b/sos/report/plugins/vdsm.py @@ -103,9 +103,9 @@ def setup(self): "su vdsm -s /bin/sh -c 'ls -lR /rhev/data-center'" ]) self.add_cmd_output([ - "lvm vgs -v -o +tags --config \'%s\'" % LVM_CONFIG, - "lvm lvs -v -o +tags --config \'%s\'" % LVM_CONFIG, - "lvm pvs -v -o +all --config \'%s\'" % LVM_CONFIG + f"lvm vgs -v -o +tags --config \'{LVM_CONFIG}\'" + f"lvm lvs -v -o +tags --config \'{LVM_CONFIG}\'" + f"lvm pvs -v -o +all --config \'{LVM_CONFIG}\'" ]) self.add_cmd_output([ @@ -137,9 +137,9 @@ def setup(self): res = self.collect_cmd_output('vdsm-client Host getStorageDomains') if res['status'] == 0: sd_uuids = json.loads(res['output']) - dump_volume_chains_cmd = 'vdsm-tool dump-volume-chains %s' + dump_volume_chains_cmd = 'vdsm-tool dump-volume-chains {}' self.add_cmd_output([ - dump_volume_chains_cmd % uuid for uuid in sd_uuids + dump_volume_chains_cmd.format(uuid) for uuid in sd_uuids ]) except ValueError as e: self._log_error(f'vdsm-client Host getStorageDomains: {e}') diff --git a/sos/report/plugins/vectordev.py b/sos/report/plugins/vectordev.py index 60338ac9ea..a59bc7a046 100644 --- a/sos/report/plugins/vectordev.py +++ b/sos/report/plugins/vectordev.py @@ -31,8 +31,9 @@ def postproc(self): "tls.key_pass", ] + keys = "|".join(protect_keys) # Redact yaml and ini style "key (:|=) value". - keys_regex = r"(^\s*(%s)\s*(:|=)\s*)(.*)" % "|".join(protect_keys) + keys_regex = rf"(^\s*({keys})\s*(:|=)\s*)(.*)" sub_regex = r"\1*********" self.do_path_regex_sub(vector_config_path, keys_regex, sub_regex) # Redact certificates diff --git a/sos/report/plugins/virsh.py b/sos/report/plugins/virsh.py index b4fbaf1c22..6bda55c208 100644 --- a/sos/report/plugins/virsh.py +++ b/sos/report/plugins/virsh.py @@ -45,16 +45,14 @@ def setup(self): for subcmd in subcmds: self.add_cmd_output(f'{cmd} {subcmd}', foreground=True) - self.add_cmd_output( - f"{cmd} list --all", tags="virsh_list_all", - foreground=True - ) + self.add_cmd_output(f"{cmd} list --all", tags="virsh_list_all", + foreground=True) # get network, pool and nwfilter elements for k in ['net', 'nwfilter', 'pool']: - k_list = self.collect_cmd_output('%s %s-list %s' % (cmd, k, '--all' - if k in ['net', 'pool'] else ''), - foreground=True) + k_list = self.collect_cmd_output( + f"{cmd} {k}-list {'--all' if k in ['net', 'pool'] else ''}", + foreground=True) if k_list['status'] == 0: k_lines = k_list['output'].splitlines() # the 'Name' column position changes between virsh cmds @@ -65,10 +63,8 @@ def setup(self): continue for j in filter(lambda x: x, k_lines[2:]): n = j.split()[pos] - self.add_cmd_output( - f"{cmd} {k}-dumpxml {n}", - foreground=True - ) + self.add_cmd_output(f"{cmd} {k}-dumpxml {n}", + foreground=True) # cycle through the VMs/domains list, ignore 2 header lines and latest # empty line, and dumpxml domain name in 2nd column diff --git a/sos/report/plugins/vmware.py b/sos/report/plugins/vmware.py index de7c833f0b..e6f213cd05 100644 --- a/sos/report/plugins/vmware.py +++ b/sos/report/plugins/vmware.py @@ -48,8 +48,7 @@ def setup(self): stats = self.exec_cmd("vmware-toolbox-cmd stat raw") if stats['status'] == 0: for _stat in stats['output'].splitlines(): - self.add_cmd_output( - f"vmware-toolbox-cmd stat raw text {_stat}" - ) + self.add_cmd_output("vmware-toolbox-cmd stat raw text " + f"{_stat}") # vim: set et ts=4 sw=4 : diff --git a/sos/report/plugins/zvm.py b/sos/report/plugins/zvm.py index 27df198523..b7a81d0033 100644 --- a/sos/report/plugins/zvm.py +++ b/sos/report/plugins/zvm.py @@ -94,8 +94,13 @@ def setup(self): vm_id_out = self.collect_cmd_output(f"{self.vm_cmd} q userid") if vm_id_out['status'] == 0: vm_id = vm_id_out['output'].split()[0] - vm_cmds.extend([f"q reorder {vm_id}", f"q quickdsp {vm_id}"]) + vm_cmds.extend([ + f"q reorder {vm_id}", + f"q quickdsp {vm_id}" + ]) - self.add_cmd_output([f"{self.vm_cmd} {vcmd}" for vcmd in vm_cmds]) + self.add_cmd_output([ + f"{self.vm_cmd} {vcmd}" for vcmd in vm_cmds + ]) # vim: set et ts=4 sw=4 : diff --git a/sos/utilities.py b/sos/utilities.py index 1c5a7bad82..3a94e13815 100644 --- a/sos/utilities.py +++ b/sos/utilities.py @@ -224,11 +224,8 @@ def _check_poller(proc): cmd_env.pop(key, None) # use /usr/bin/timeout to implement a timeout if timeout and is_executable("timeout"): - command = "timeout %s %ds %s" % ( - '--foreground' if foreground else '', - timeout, - command - ) + command = (f"timeout {'--foreground' if foreground else ''}" + f" {timeout} {command}") args = shlex.split(command) # Expand arguments that are wildcard root paths. @@ -338,7 +335,7 @@ def get_human_readable(size, precision=2): while size > 1024 and suffixindex < 4: suffixindex += 1 size = size/1024.0 - return "%.*f%s" % (precision, size, suffixes[suffixindex]) + return f"{size:.{precision}f}{suffixes[suffixindex]}" def _os_wrapper(path, sysroot, method, module=os.path):