diff options
-rw-r--r-- | sos/report/plugins/microshift.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/sos/report/plugins/microshift.py b/sos/report/plugins/microshift.py new file mode 100644 index 00000000..953eb88e --- /dev/null +++ b/sos/report/plugins/microshift.py @@ -0,0 +1,167 @@ +# Copyright 2023 Red Hat, Inc. Pablo Acevedo <pacevedo@redhat.com> +# This file is part of the sos project: https://github.com/sosreport/sos +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# version 2 of the GNU General Public License. +# +# See the LICENSE file in the source distribution for further information. + +from sos.report.plugins import Plugin, RedHatPlugin, PluginOpt +import re + + +class Microshift(Plugin, RedHatPlugin): + """This is the plugin for MicroShift 4.X. Even though it shares some of + the OpenShift components, its IoT/Edge target makes the product nimble and + light, thus requiring different a approach when operating it. + + When enabled, this plugin will collect cluster information (such as + systemd service logs, configuration, versions, etc.)and also inspect API + resources in certain namespaces. The namespaces to scan are kube.* and + openshift.*. Other namespaces may be collected by making use of the + ``only-namespaces`` or ``add-namespaces`` options. + """ + + short_desc = 'Microshift' + plugin_name = 'microshift' + plugin_timeout = 900 + packages = ('microshift', 'microshift-selinux', 'microshift-networking') + services = (plugin_name,) + profiles = (plugin_name,) + localhost_kubeconfig = '/var/lib/microshift/resources/kubeadmin/kubeconfig' + + option_list = [ + PluginOpt('kubeconfig', default=localhost_kubeconfig, val_type=str, + desc='Path to a locally available kubeconfig file'), + PluginOpt('only-namespaces', default='', val_type=str, + desc='colon-delimited list of namespaces to collect from'), + PluginOpt('add-namespaces', default='', val_type=str, + desc=('colon-delimited list of namespaces to add to the ' + 'default collection list')) + ] + + def _setup_namespace_regexes(self): + """Combine a set of regexes for collection with any namespaces passed + to sos via the -k openshift.add-namespaces option. Note that this does + allow for end users to specify namespace regexes of their own. + """ + if self.get_option('only-namespaces'): + return [n for n in self.get_option('only-namespaces').split(':')] + + collect_regexes = [ + r'^openshift\-.+$', + r'^kube\-.+$' + ] + + if self.get_option('add-namespaces'): + for nsp in self.get_option('add-namespaces').split(':'): + collect_regexes.append(r'^%s$' % nsp) + + return collect_regexes + + def _reduce_namespace_list(self, nsps): + """Reduce the namespace listing returned to just the ones we want to + collect from. By default, as requested by OCP support personnel, this + must include all 'openshift' prefixed namespaces + + :param nsps list: Namespace names from oc output + """ + + def _match_namespace(namespace): + """Match a particular namespace for inclusion (or not) in the + collection phases + + :param namespace str: The name of a namespace + """ + + for regex in self.collect_regexes: + if re.match(regex, namespace): + return True + return False + + self.collect_regexes = self._setup_namespace_regexes() + + return list(set([n for n in nsps if _match_namespace(n)])) + + def _get_namespaces(self): + res = self.exec_cmd( + 'microshift get namespaces' + ' -o custom-columns=NAME:.metadata.name' + ' --no-headers') + if res['status'] == 0: + return self._reduce_namespace_list(res['output'].split('\n')) + return [] + + def _get_cluster_resources(self): + """Get cluster-level (non-namespaced) resources to collect + """ + global_resources = [ + 'apiservices', + 'certificatesigningrequests', + 'clusterrolebindings', + 'clusterroles', + 'componentstatuses', + 'csidrivers', + 'csinodes', + 'customresourcedefinitions', + 'flowschemas', + 'ingressclasses', + 'logicalvolumes', + 'mutatingwebhookconfigurations', + 'nodes', + 'persistentvolumes', + 'priorityclasses', + 'prioritylevelconfigurations', + 'rangeallocations', + 'runtimeclasses', + 'securitycontextconstraints', + 'selfsubjectaccessreviews', + 'selfsubjectrulesreviews', + 'storageclasses', + 'subjectaccessreviews', + 'tokenreviews', + 'validatingwebhookconfigurations', + 'volumeattachments' + ] + + _filtered_resources = [] + + for resource in global_resources: + res = self.exec_cmd( + "oc get --kubeconfig %s %s" % ( + self.get_option('kubeconfig'), resource), + timeout=Microshift.plugin_timeout) + if res['status'] == 0: + _filtered_resources.append(resource) + return _filtered_resources + + def setup(self): + """The setup() phase of this plugin will first gather system + information and then iterate through all default namespaces, and/or + those specified via the `add-namespaces` and `only-namespaces` plugin + options. Both of these options accept shell-style regexes. + + Output format for this function is based on `oc adm inspect` command, + which is used to retrieve all API resources from the cluster. + """ + self.add_forbidden_path('/var/lib/microshift') + + _cluster_resources_to_collect = ",".join( + self._get_cluster_resources()) + _namespaces_to_collect = " ".join( + ['ns/%s' % n for n in self._get_namespaces()]) + + if self.is_service_running(Microshift.plugin_name): + _subdir = self.get_cmd_output_path(make=False) + _kubeconfig = self.get_option('kubeconfig') + self.add_cmd_output( + 'oc adm inspect --kubeconfig %s --dest-dir %s %s' % ( + _kubeconfig, _subdir, _cluster_resources_to_collect), + suggest_filename='inspect_cluster_resources.log', + timeout=Microshift.plugin_timeout) + self.add_cmd_output( + 'oc adm inspect --kubeconfig %s --dest-dir %s %s' % ( + _kubeconfig, _subdir, _namespaces_to_collect), + suggest_filename='inspect_namespaces.log', + timeout=Microshift.plugin_timeout) |