summaryrefslogtreecommitdiff
path: root/robusta_krr/utils
diff options
context:
space:
mode:
authorПавел Жуков <33721692+LeaveMyYard@users.noreply.github.com>2023-03-13 18:19:29 +0200
committerПавел Жуков <33721692+LeaveMyYard@users.noreply.github.com>2023-03-13 18:19:29 +0200
commitf3f0b6c5d515ff0cca06c96f4c7296eaf0343970 (patch)
treeeeac6fa58a2f82280951783802e46f258024d858 /robusta_krr/utils
parent187db259c68ffafd5d0f2f8a71b902063ff0040b (diff)
Implement prometheus integration
Diffstat (limited to 'robusta_krr/utils')
-rw-r--r--robusta_krr/utils/configurable.py3
-rw-r--r--robusta_krr/utils/service_discovery.py56
2 files changed, 58 insertions, 1 deletions
diff --git a/robusta_krr/utils/configurable.py b/robusta_krr/utils/configurable.py
index e4c80f6..d2f1442 100644
--- a/robusta_krr/utils/configurable.py
+++ b/robusta_krr/utils/configurable.py
@@ -1,3 +1,4 @@
+import abc
from typing import Literal
from rich.console import Console
@@ -7,7 +8,7 @@ from robusta_krr.core.models.config import Config
console = Console()
-class Configurable:
+class Configurable(abc.ABC):
"""
A class that can be configured with a Config object.
Opens the possibility to use echo and debug methods
diff --git a/robusta_krr/utils/service_discovery.py b/robusta_krr/utils/service_discovery.py
new file mode 100644
index 0000000..8c498fe
--- /dev/null
+++ b/robusta_krr/utils/service_discovery.py
@@ -0,0 +1,56 @@
+import logging
+
+from cachetools import TTLCache
+from kubernetes import client
+from kubernetes.client import V1ServiceList
+from kubernetes.client.api_client import ApiClient
+from kubernetes.client.models.v1_service import V1Service
+
+from robusta_krr.utils.configurable import Configurable
+
+
+class ServiceDiscovery(Configurable):
+ SERVICE_CACHE_TTL_SEC = 900
+ cache: TTLCache = TTLCache(maxsize=1, ttl=SERVICE_CACHE_TTL_SEC)
+
+ def find_service_url(self, label_selector: str, *, api_client: ApiClient | None = None) -> str | None:
+ """
+ Get the url of an in-cluster service with a specific label
+ """
+ # we do it this way because there is a weird issue with hikaru's ServiceList.listServiceForAllNamespaces()
+ v1 = client.CoreV1Api(api_client=api_client)
+ svc_list: V1ServiceList = v1.list_service_for_all_namespaces(label_selector=label_selector)
+ if not svc_list.items:
+ return None
+
+ svc: V1Service = svc_list.items[0]
+ name = svc.metadata.name
+ namespace = svc.metadata.namespace
+ port = svc.spec.ports[0].port
+
+ if self.config.inside_cluster:
+ return f"http://{name}.{namespace}.svc.cluster.local:{port}"
+
+ elif api_client is not None:
+ return f"{api_client.configuration.host}/api/v1/namespaces/{namespace}/services/{name}:{port}/proxy"
+
+ return None
+
+ def find_url(self, selectors: list[str], *, api_client: ApiClient | None = None) -> str | None:
+ """
+ Try to autodiscover the url of an in-cluster service
+ """
+ cache_key = ",".join(selectors)
+ cached_value = self.cache.get(cache_key)
+ if cached_value:
+ return cached_value
+
+ for label_selector in selectors:
+ logging.debug(f"Trying to find service with label selector {label_selector}")
+ service_url = self.find_service_url(label_selector, api_client=api_client)
+ if service_url:
+ logging.debug(f"Found service with label selector {label_selector}")
+ self.cache[cache_key] = service_url
+ return service_url
+
+ return None