diff options
-rw-r--r-- | sos/collector/clusters/ocp.py | 65 | ||||
-rw-r--r-- | sos/collector/sosnode.py | 4 |
2 files changed, 65 insertions, 4 deletions
diff --git a/sos/collector/clusters/ocp.py b/sos/collector/clusters/ocp.py index 283fcfd1..ddff84a4 100644 --- a/sos/collector/clusters/ocp.py +++ b/sos/collector/clusters/ocp.py @@ -8,6 +8,8 @@ # # See the LICENSE file in the source distribution for further information. +import os + from pipes import quote from sos.collector.clusters import Cluster @@ -18,10 +20,14 @@ class ocp(Cluster): cluster_name = 'OpenShift Container Platform v4' packages = ('openshift-hyperkube', 'openshift-clients') + api_collect_enabled = False + token = None + option_list = [ ('label', '', 'Colon delimited list of labels to select nodes with'), ('role', '', 'Colon delimited list of roles to select nodes with'), - ('kubeconfig', '', 'Path to the kubeconfig file') + ('kubeconfig', '', 'Path to the kubeconfig file'), + ('token', '', 'Service account token to use for oc authorization') ] def fmt_oc_cmd(self, cmd): @@ -32,9 +38,20 @@ class ocp(Cluster): return "oc --config %s %s" % (self.get_option('kubeconfig'), cmd) return "oc %s" % cmd + def _attempt_oc_login(self): + """Attempt to login to the API using the oc command using a provided + token + """ + _res = self.exec_primary_cmd("oc login --insecure-skip-tls-verify=True" + " --token=%s" % self.token) + return _res['status'] == 0 + def check_enabled(self): if super(ocp, self).check_enabled(): return True + self.token = self.get_option('token') or os.getenv('SOSOCPTOKEN', None) + if self.token: + self._attempt_oc_login() _who = self.fmt_oc_cmd('whoami') return self.exec_master_cmd(_who)['status'] == 0 @@ -106,4 +123,48 @@ class ocp(Cluster): return 'master' in self.node_dict[sosnode.address]['roles'] def set_master_options(self, node): - node.opts.enable_plugins.append('openshift') + node.enable_plugins.append('openshift') + if self.api_collect_enabled: + # a primary has already been enabled for API collection, disable + # it among others + node.plugin_options.append('openshift.no-oc=on') + else: + _oc_cmd = 'oc' + if node.host.containerized: + _oc_cmd = '/host/bin/oc' + # when run from a container, the oc command does not inherit + # the default config, so if it's present then pass it here to + # detect a funcitonal oc command. This is sidestepped in sos + # report by being able to chroot the `oc` execution which we + # 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("%s whoami" % _oc_cmd, + use_container=node.host.containerized, + # container is available only to root + # and if rhel, need to run sos as root + # anyways which will run oc as root + need_root=True) + if can_oc['status'] == 0: + # the primary node can already access the API + self.api_collect_enabled = True + elif self.token: + node.sos_env_vars['SOSOCPTOKEN'] = self.token + self.api_collect_enabled = True + elif self.get_option('kubeconfig'): + kc = self.get_option('kubeconfig') + if node.file_exists(kc): + if node.host.containerized: + kc = "/host/%s" % kc + node.sos_env_vars['KUBECONFIG'] = kc + 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) + self.soslog.info(msg) + self.ui_log.info(msg) + + def set_node_options(self, node): + # don't attempt OC API collections on non-primary nodes + node.plugin_options.append('openshift.no-oc=on') diff --git a/sos/collector/sosnode.py b/sos/collector/sosnode.py index 1c25cc34..6597d236 100644 --- a/sos/collector/sosnode.py +++ b/sos/collector/sosnode.py @@ -202,11 +202,11 @@ class SosNode(): self.opts.registry_authfile or self.host.container_authfile ) - def file_exists(self, fname): + def file_exists(self, fname, need_root=False): """Checks for the presence of fname on the remote node""" if not self.local: try: - res = self.run_command("stat %s" % fname) + res = self.run_command("stat %s" % fname, need_root=need_root) return res['status'] == 0 except Exception: return False |