From 3c0ce13549555237552999d9fa6f6cee33f5e592 Mon Sep 17 00:00:00 2001 From: vsoch Date: Wed, 18 Oct 2023 00:00:54 -0600 Subject: [PATCH] fix: allow metrics operator python sdk to take custom kubeconfig Signed-off-by: vsoch --- sdk/python/v1alpha2/CHANGELOG.md | 1 + sdk/python/v1alpha2/metricsoperator/client.py | 23 +++++++++++++++---- .../v1alpha2/metricsoperator/metrics/base.py | 15 ++++++++++++ sdk/python/v1alpha2/metricsoperator/utils.py | 11 +++++++++ sdk/python/v1alpha2/setup.py | 2 +- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/sdk/python/v1alpha2/CHANGELOG.md b/sdk/python/v1alpha2/CHANGELOG.md index 7a62256..c66adce 100644 --- a/sdk/python/v1alpha2/CHANGELOG.md +++ b/sdk/python/v1alpha2/CHANGELOG.md @@ -14,6 +14,7 @@ and **Merged pull requests**. Critical items to know are: The versions coincide with releases on pip. Only major versions will be released as tags on Github. ## [0.0.x](https://github.com/converged-computing/metrics-operator/tree/main) (0.0.x) + - Support to provide custom kubeconfig (0.1.11) - LAMMPS parsing should include row names for component names (0.1.1) - More specific parsing / control for OSU benchmarks (0.0.21) - Support for OSU benchmark parsing with timed wrappers (0.0.2) diff --git a/sdk/python/v1alpha2/metricsoperator/client.py b/sdk/python/v1alpha2/metricsoperator/client.py index ac0af50..83e5f66 100644 --- a/sdk/python/v1alpha2/metricsoperator/client.py +++ b/sdk/python/v1alpha2/metricsoperator/client.py @@ -12,7 +12,7 @@ class MetricsOperator: - def __init__(self, yaml_file): + def __init__(self, yaml_file, kubeconfig=None): """ Given a YAML file with one or more metrics, apply to create it and stream logs for each metric of interest. @@ -20,7 +20,20 @@ def __init__(self, yaml_file): self._core_v1 = None self.yaml_file = os.path.abspath(yaml_file) self.spec = utils.read_yaml(self.yaml_file) - config.load_kube_config() + self.kubeconfig = kubeconfig + self.load_kube_config() + + def load_kube_config(self, kubeconfig=None): + """ + Allow providing a custom kubeconfig to control a cluster and metric + """ + kubeconfig = kubeconfig or self.kubeconfig + if not kubeconfig: + config.load_kube_config() + return + + self._core_v1 = utils.make_k8s_client(kubeconfig) + config.load_kube_config(config_file=kubeconfig) def watch(self, raw_logs=False, pod_prefix=None, container_name=None): """ @@ -31,10 +44,12 @@ def watch(self, raw_logs=False, pod_prefix=None, container_name=None): for metric in self.spec["spec"]["metrics"]: if raw_logs: - parser = mutils.get_metric()(self.spec, container_name=container_name) + parser = mutils.get_metric()( + self.spec, container_name=container_name, kubeconfig=self.kubeconfig + ) else: parser = mutils.get_metric(metric["name"])( - self.spec, container_name=container_name + self.spec, container_name=container_name, kubeconfig=self.kubeconfig ) print("Watching %s" % metric["name"]) for pod, container in parser.logging_containers(pod_prefix=pod_prefix): diff --git a/sdk/python/v1alpha2/metricsoperator/metrics/base.py b/sdk/python/v1alpha2/metricsoperator/metrics/base.py index 84f8b3e..45ad884 100644 --- a/sdk/python/v1alpha2/metricsoperator/metrics/base.py +++ b/sdk/python/v1alpha2/metricsoperator/metrics/base.py @@ -6,6 +6,8 @@ from kubernetes.client.exceptions import ApiException from kubernetes.client.models.v1_pod_list import V1PodList +import metricsoperator.utils as utils + class MetricBase: separator = "METRICS OPERATOR TIMEPOINT" @@ -23,6 +25,7 @@ def __init__(self, spec=None, **kwargs): """ self.spec = spec self._core_v1 = kwargs.get("core_v1_api") + self.kubeconfig = kwargs.get("kubeconfig") # If we don't have a default container name... if not self.container_name: @@ -30,7 +33,19 @@ def __init__(self, spec=None, **kwargs): # Load kubeconfig on Metricbase init only if self.spec is not None: + self.load_kube_config() + + def load_kube_config(self): + """ + Allow providing a custom kubeconfig to control a cluster and metric + """ + if not self.kubeconfig: config.load_kube_config() + return + + # Assume the core v1 handler is replaced with this kubeconfig + self._core_v1 = utils.make_k8s_client(self.kubeconfig) + config.load_kube_config(config_file=self.kubeconfig) @property def namespace(self): diff --git a/sdk/python/v1alpha2/metricsoperator/utils.py b/sdk/python/v1alpha2/metricsoperator/utils.py index b7f0e40..e570031 100644 --- a/sdk/python/v1alpha2/metricsoperator/utils.py +++ b/sdk/python/v1alpha2/metricsoperator/utils.py @@ -6,6 +6,17 @@ import re import yaml +from kubernetes import client, config + + +def make_k8s_client(kubeconfig_yaml): + """ + Load the yaml config for use in Python + """ + with open(kubeconfig_yaml) as f: + kubeconfig = yaml.safe_load(f) + api_client = config.new_client_from_config_dict(kubeconfig) + return client.CoreV1Api(api_client) def read_file(filename): diff --git a/sdk/python/v1alpha2/setup.py b/sdk/python/v1alpha2/setup.py index 8702733..329620e 100644 --- a/sdk/python/v1alpha2/setup.py +++ b/sdk/python/v1alpha2/setup.py @@ -30,7 +30,7 @@ if __name__ == "__main__": setup( name="metricsoperator", - version="0.1.1", + version="0.1.11", author="Vanessasaurus", author_email="vsoch@users.noreply.github.com", maintainer="Vanessasaurus",