summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md32
-rw-r--r--poetry.lock100
-rw-r--r--pyproject.toml4
-rw-r--r--requirements.txt68
-rw-r--r--robusta_krr/core/integrations/prometheus/__init__.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/loader.py6
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/__init__.py4
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/base.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/cpu.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics/memory.py2
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py8
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py37
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py11
-rw-r--r--robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py11
-rw-r--r--robusta_krr/core/integrations/prometheus/prometheus_client.py91
-rw-r--r--robusta_krr/core/integrations/prometheus/prometheus_utils.py50
-rw-r--r--robusta_krr/core/models/config.py11
-rw-r--r--robusta_krr/core/runner.py4
-rw-r--r--robusta_krr/main.py49
19 files changed, 294 insertions, 200 deletions
diff --git a/README.md b/README.md
index 677354c..e91856b 100644
--- a/README.md
+++ b/README.md
@@ -377,6 +377,38 @@ Than run the following command with PROMETHEUS_URL substituted for your Azure Ma
```sh
python krr.py simple --namespace default -p PROMETHEUS_URL --prometheus-auth-header "Bearer $AZURE_BEARER"
```
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
+
+<p align="right">(<a href="#readme-top">back to top</a>)</p>
+
+## EKS managed Prometheus
+
+For EKS managed Prometheus you need to add your prometheus link and the flag --eks-managed-prom and krr will automatically use your aws credentials
+
+```sh
+python krr.py simple -p "https://aps-workspaces.REGION.amazonaws.com/workspaces/..." --eks-managed-prom
+```
+Additional optional parameters are:
+```sh
+--eks-profile-name PROFILE_NAME_HERE # to specify the profile to use from your config
+--eks-access-key ACCESS_KEY # to specify your access key
+--eks-secret-key SECRET_KEY # to specify your secret key
+--eks-service-name SERVICE_NAME # to use a specific service name in the signature
+--eks-managed-prom-region REGION_NAME # to specify the region the prometheus is in
+```
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
+
+<p align="right">(<a href="#readme-top">back to top</a>)</p>
+
+## Coralogix managed Prometheus
+
+For Coralogix managed Prometheus you need to specify your prometheus link and add the flag coralogix_token with your Logs Query Key
+
+```sh
+python krr.py simple -p "https://prom-api.coralogix..." --coralogix_token
+```
+
+<p ><a href="#scanning-with-a-centralized-prometheus">See here about configuring labels for centralized prometheus</a></p>
<p align="right">(<a href="#readme-top">back to top</a>)</p>
diff --git a/poetry.lock b/poetry.lock
index 0e1b413..5dbdfd4 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -95,6 +95,44 @@ jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
uvloop = ["uvloop (>=0.15.2)"]
[[package]]
+name = "boto3"
+version = "1.28.15"
+description = "The AWS SDK for Python"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "boto3-1.28.15-py3-none-any.whl", hash = "sha256:84b7952858e9319968b0348d9894a91a6bb5f31e81a45c68044d040a12362abe"},
+ {file = "boto3-1.28.15.tar.gz", hash = "sha256:a6e711e0b6960c3a5b789bd30c5a18eea7263f2a59fc07f85efa5e04804e49d2"},
+]
+
+[package.dependencies]
+botocore = ">=1.31.15,<1.32.0"
+jmespath = ">=0.7.1,<2.0.0"
+s3transfer = ">=0.6.0,<0.7.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
+
+[[package]]
+name = "botocore"
+version = "1.31.15"
+description = "Low-level, data-driven core of boto 3."
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "botocore-1.31.15-py3-none-any.whl", hash = "sha256:b3a0f787f275711875476cbe12a0123b2e6570b2f505e2fa509dcec3c5410b57"},
+ {file = "botocore-1.31.15.tar.gz", hash = "sha256:b46d1ce4e0cf42d28fdf61ce0c999904645d38b51cb809817a361c0cec16d487"},
+]
+
+[package.dependencies]
+jmespath = ">=0.7.1,<2.0.0"
+python-dateutil = ">=2.1,<3.0.0"
+urllib3 = ">=1.25.4,<1.27"
+
+[package.extras]
+crt = ["awscrt (==0.16.26)"]
+
+[[package]]
name = "cachetools"
version = "5.3.1"
description = "Extensible memoizing collections and decorators"
@@ -526,6 +564,17 @@ plugins = ["setuptools"]
requirements-deprecated-finder = ["pip-api", "pipreqs"]
[[package]]
+name = "jmespath"
+version = "1.0.1"
+description = "JSON Matching Expressions"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
+ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
+]
+
+[[package]]
name = "kiwisolver"
version = "1.4.4"
description = "A fast implementation of the Cassowary constraint solver"
@@ -1041,6 +1090,23 @@ pandas = ">=1.4.0"
requests = "*"
[[package]]
+name = "prometrix"
+version = "0.1.10"
+description = ""
+optional = false
+python-versions = ">=3.8,<4.0"
+files = [
+ {file = "prometrix-0.1.10-py3-none-any.whl", hash = "sha256:5caa0ee06d49d7ad1f881614edb81fe4b2f47f730bcd4286209627fdc41d550d"},
+ {file = "prometrix-0.1.10.tar.gz", hash = "sha256:9ed61c0b77b503d38ce9c66d70742ad81a84b7afc6fbf63e8dbba9316b41a4df"},
+]
+
+[package.dependencies]
+boto3 = ">=1.28.15,<2.0.0"
+botocore = ">=1.31.15,<2.0.0"
+prometheus-api-client = ">=0.5.3,<0.6.0"
+pydantic = ">=1.8.1,<2.0.0"
+
+[[package]]
name = "pyasn1"
version = "0.5.0"
description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)"
@@ -1487,6 +1553,23 @@ files = [
pyasn1 = ">=0.1.3"
[[package]]
+name = "s3transfer"
+version = "0.6.1"
+description = "An Amazon S3 Transfer Manager"
+optional = false
+python-versions = ">= 3.7"
+files = [
+ {file = "s3transfer-0.6.1-py3-none-any.whl", hash = "sha256:3c0da2d074bf35d6870ef157158641178a4204a6e689e82546083e31e0311346"},
+ {file = "s3transfer-0.6.1.tar.gz", hash = "sha256:640bb492711f4c0c0905e1f62b6aaeb771881935ad27884852411f8e9cacbca9"},
+]
+
+[package.dependencies]
+botocore = ">=1.12.36,<2.0a.0"
+
+[package.extras]
+crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
+
+[[package]]
name = "setuptools"
version = "68.0.0"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
@@ -1661,20 +1744,19 @@ devenv = ["black", "check-manifest", "flake8", "pyroma", "pytest (>=4.3)", "pyte
[[package]]
name = "urllib3"
-version = "2.0.4"
+version = "1.26.16"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
-python-versions = ">=3.7"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
files = [
- {file = "urllib3-2.0.4-py3-none-any.whl", hash = "sha256:de7df1803967d2c2a98e4b11bb7d6bd9210474c46e8a0401514e3a42a75ebde4"},
- {file = "urllib3-2.0.4.tar.gz", hash = "sha256:8d22f86aae8ef5e410d4f539fde9ce6b2113a001bb4d189e0aed70642d602b11"},
+ {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
+ {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
]
[package.extras]
-brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
-secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"]
-socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
-zstd = ["zstandard (>=0.18.0)"]
+brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"]
+secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"]
+socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
[[package]]
name = "websocket-client"
@@ -1710,4 +1792,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.12"
-content-hash = "936ab8c06cf4a6e5cc8c3a8cbe6bb50ff8edf019e11cc9a1e20847505a8b62a5"
+content-hash = "bcef0de696e4fbf7bd3140cc79c6d72fdbf3d39c20b7101c55c9613a1cd56a40"
diff --git a/pyproject.toml b/pyproject.toml
index ef99a74..a4f0cca 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -27,9 +27,11 @@ python = ">=3.9,<3.12"
typer = {extras = ["all"], version = "^0.7.0"}
pydantic = "1.10.7"
kubernetes = "^26.1.0"
-prometheus-api-client = "^0.5.3"
numpy = "^1.24.2"
alive-progress = "^3.1.2"
+botocore = "^1.31.10"
+boto3 = "^1.28.10"
+prometrix = "^0.1.10"
[tool.poetry.group.dev.dependencies]
diff --git a/requirements.txt b/requirements.txt
index 907cfed..f887a5e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,52 +1,54 @@
about-time==4.2.1 ; python_version >= "3.9" and python_version < "3.12"
-aiostream==0.4.5 ; python_version >= "3.9" and python_version < "3.12"
-alive-progress==3.1.2 ; python_version >= "3.9" and python_version < "3.12"
-cachetools==5.3.0 ; python_version >= "3.9" and python_version < "3.12"
-certifi==2022.12.7 ; python_version >= "3.9" and python_version < "3.12"
-charset-normalizer==3.0.1 ; python_version >= "3.9" and python_version < "3.12"
-click==8.1.3 ; python_version >= "3.9" and python_version < "3.12"
-colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.12"
+alive-progress==3.1.4 ; python_version >= "3.9" and python_version < "3.12"
+boto3==1.28.15 ; python_version >= "3.9" and python_version < "3.12"
+botocore==1.31.15 ; python_version >= "3.9" and python_version < "3.12"
+cachetools==5.3.1 ; python_version >= "3.9" and python_version < "3.12"
+certifi==2023.7.22 ; python_version >= "3.9" and python_version < "3.12"
+charset-normalizer==3.2.0 ; python_version >= "3.9" and python_version < "3.12"
+click==8.1.6 ; python_version >= "3.9" and python_version < "3.12"
+colorama==0.4.6 ; python_version >= "3.9" and python_version < "3.12" and platform_system == "Windows"
commonmark==0.9.1 ; python_version >= "3.9" and python_version < "3.12"
-contourpy==1.0.7 ; python_version >= "3.9" and python_version < "3.12"
+contourpy==1.1.0 ; python_version >= "3.9" and python_version < "3.12"
cycler==0.11.0 ; python_version >= "3.9" and python_version < "3.12"
-dateparser==1.1.7 ; python_version >= "3.9" and python_version < "3.12"
-fonttools==4.39.0 ; python_version >= "3.9" and python_version < "3.12"
-google-auth==2.16.2 ; python_version >= "3.9" and python_version < "3.12"
+dateparser==1.1.8 ; python_version >= "3.9" and python_version < "3.12"
+fonttools==4.42.0 ; python_version >= "3.9" and python_version < "3.12"
+google-auth==2.17.3 ; python_version >= "3.9" and python_version < "3.12"
grapheme==0.6.0 ; python_version >= "3.9" and python_version < "3.12"
httmock==1.4.0 ; python_version >= "3.9" and python_version < "3.12"
idna==3.4 ; python_version >= "3.9" and python_version < "3.12"
-importlib-resources==5.12.0 ; python_version >= "3.9" and python_version < "3.10"
+importlib-resources==6.0.0 ; python_version >= "3.9" and python_version < "3.10"
+jmespath==1.0.1 ; python_version >= "3.9" and python_version < "3.12"
kiwisolver==1.4.4 ; python_version >= "3.9" and python_version < "3.12"
kubernetes==26.1.0 ; python_version >= "3.9" and python_version < "3.12"
-matplotlib==3.7.1 ; python_version >= "3.9" and python_version < "3.12"
-numpy==1.24.2 ; python_version >= "3.9" and python_version < "3.12"
+matplotlib==3.7.2 ; python_version >= "3.9" and python_version < "3.12"
+numpy==1.25.2 ; python_version >= "3.9" and python_version < "3.12"
oauthlib==3.2.2 ; python_version >= "3.9" and python_version < "3.12"
-packaging==23.0 ; python_version >= "3.9" and python_version < "3.12"
-pandas==1.5.3 ; python_version >= "3.9" and python_version < "3.12"
-pillow==9.4.0 ; python_version >= "3.9" and python_version < "3.12"
+packaging==23.1 ; python_version >= "3.9" and python_version < "3.12"
+pandas==2.0.3 ; python_version >= "3.9" and python_version < "3.12"
+pillow==10.0.0 ; python_version >= "3.9" and python_version < "3.12"
prometheus-api-client==0.5.3 ; python_version >= "3.9" and python_version < "3.12"
-pyasn1-modules==0.2.8 ; python_version >= "3.9" and python_version < "3.12"
-pyasn1==0.4.8 ; python_version >= "3.9" and python_version < "3.12"
+prometrix==0.1.10 ; python_version >= "3.9" and python_version < "3.12"
+pyasn1-modules==0.3.0 ; python_version >= "3.9" and python_version < "3.12"
+pyasn1==0.5.0 ; python_version >= "3.9" and python_version < "3.12"
pydantic==1.10.7 ; python_version >= "3.9" and python_version < "3.12"
-pygments==2.14.0 ; python_version >= "3.9" and python_version < "3.12"
+pygments==2.15.1 ; python_version >= "3.9" and python_version < "3.12"
pyparsing==3.0.9 ; python_version >= "3.9" and python_version < "3.12"
python-dateutil==2.8.2 ; python_version >= "3.9" and python_version < "3.12"
-pytz-deprecation-shim==0.1.0.post0 ; python_version >= "3.9" and python_version < "3.12"
-pytz==2022.7.1 ; python_version >= "3.9" and python_version < "3.12"
-pyyaml==6.0 ; python_version >= "3.9" and python_version < "3.12"
-regex==2022.10.31 ; python_version >= "3.9" and python_version < "3.12"
+pytz==2023.3 ; python_version >= "3.9" and python_version < "3.12"
+pyyaml==6.0.1 ; python_version >= "3.9" and python_version < "3.12"
+regex==2023.6.3 ; python_version >= "3.9" and python_version < "3.12"
requests-oauthlib==1.3.1 ; python_version >= "3.9" and python_version < "3.12"
-requests==2.28.2 ; python_version >= "3.9" and python_version < "3.12"
+requests==2.31.0 ; python_version >= "3.9" and python_version < "3.12"
rich==12.6.0 ; python_version >= "3.9" and python_version < "3.12"
rsa==4.9 ; python_version >= "3.9" and python_version < "3.12"
-setuptools==67.4.0 ; python_version >= "3.9" and python_version < "3.12"
+s3transfer==0.6.1 ; python_version >= "3.9" and python_version < "3.12"
+setuptools==68.0.0 ; python_version >= "3.9" and python_version < "3.12"
shellingham==1.5.0.post1 ; python_version >= "3.9" and python_version < "3.12"
six==1.16.0 ; python_version >= "3.9" and python_version < "3.12"
typer[all]==0.7.0 ; python_version >= "3.9" and python_version < "3.12"
-typing-extensions==4.5.0 ; python_version >= "3.9" and python_version < "3.12"
-tzdata==2022.7 ; python_version >= "3.9" and python_version < "3.12"
-tzlocal==4.2 ; python_version >= "3.9" and python_version < "3.12"
-urllib3==1.26.14 ; python_version >= "3.9" and python_version < "3.12"
-websocket-client==1.5.1 ; python_version >= "3.9" and python_version < "3.12"
-zipp==3.15.0 ; python_version >= "3.9" and python_version < "3.10"
-slack-sdk==3.21.3 ; python_version >= "3.9" and python_version < "3.12"
+typing-extensions==4.7.1 ; python_version >= "3.9" and python_version < "3.12"
+tzdata==2023.3 ; python_version >= "3.9" and python_version < "3.12"
+tzlocal==5.0.1 ; python_version >= "3.9" and python_version < "3.12"
+urllib3==1.26.16 ; python_version >= "3.9" and python_version < "3.12"
+websocket-client==1.6.1 ; python_version >= "3.9" and python_version < "3.12"
+zipp==3.16.2 ; python_version >= "3.9" and python_version < "3.10"
diff --git a/robusta_krr/core/integrations/prometheus/__init__.py b/robusta_krr/core/integrations/prometheus/__init__.py
index e7e545b..cedf1c0 100644
--- a/robusta_krr/core/integrations/prometheus/__init__.py
+++ b/robusta_krr/core/integrations/prometheus/__init__.py
@@ -1,3 +1,3 @@
from .loader import PrometheusMetricsLoader
from .metrics_service.prometheus_metrics_service import PrometheusDiscovery, PrometheusNotFound
-from .prometheus_client import CustomPrometheusConnect, ClusterNotSpecifiedException
+from .prometheus_utils import ClusterNotSpecifiedException
diff --git a/robusta_krr/core/integrations/prometheus/loader.py b/robusta_krr/core/integrations/prometheus/loader.py
index ca0d6f1..70d839a 100644
--- a/robusta_krr/core/integrations/prometheus/loader.py
+++ b/robusta_krr/core/integrations/prometheus/loader.py
@@ -2,21 +2,21 @@ from __future__ import annotations
import datetime
from concurrent.futures import ThreadPoolExecutor
-from typing import Optional, TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
from kubernetes import config as k8s_config
from kubernetes.client.api_client import ApiClient
+from prometrix import MetricsNotFound, PrometheusNotFound
from robusta_krr.core.models.objects import K8sObjectData
from robusta_krr.utils.configurable import Configurable
-from .metrics_service.base_metric_service import MetricsNotFound
from .metrics_service.prometheus_metrics_service import PrometheusMetricsService, PrometheusNotFound
from .metrics_service.thanos_metrics_service import ThanosMetricsService
from .metrics_service.victoria_metrics_service import VictoriaMetricsService
if TYPE_CHECKING:
- from robusta_krr.core.abstract.strategies import MetricsPodData, BaseStrategy
+ from robusta_krr.core.abstract.strategies import BaseStrategy, MetricsPodData
from robusta_krr.core.models.config import Config
METRICS_SERVICES = {
diff --git a/robusta_krr/core/integrations/prometheus/metrics/__init__.py b/robusta_krr/core/integrations/prometheus/metrics/__init__.py
index daee396..6212a35 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/__init__.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/__init__.py
@@ -1,3 +1,3 @@
-from .cpu import CPULoader, MaxCPULoader, PercentileCPULoader
-from .memory import MemoryLoader, MaxMemoryLoader, PercentileMemoryLoader
from .base import PrometheusMetric
+from .cpu import CPULoader, MaxCPULoader, PercentileCPULoader
+from .memory import MaxMemoryLoader, MemoryLoader, PercentileMemoryLoader
diff --git a/robusta_krr/core/integrations/prometheus/metrics/base.py b/robusta_krr/core/integrations/prometheus/metrics/base.py
index d076ff4..709be92 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/base.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/base.py
@@ -5,7 +5,7 @@ import asyncio
import datetime
import enum
from concurrent.futures import ThreadPoolExecutor
-from typing import Any, TYPE_CHECKING, Optional
+from typing import TYPE_CHECKING, Any, Optional
import numpy as np
import pydantic as pd
diff --git a/robusta_krr/core/integrations/prometheus/metrics/cpu.py b/robusta_krr/core/integrations/prometheus/metrics/cpu.py
index 3aab7b4..f4b9058 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/cpu.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/cpu.py
@@ -1,6 +1,6 @@
from robusta_krr.core.models.objects import K8sObjectData
-from .base import QueryMetric, QueryRangeMetric, FilterMetric
+from .base import FilterMetric, QueryMetric, QueryRangeMetric
class CPULoader(QueryRangeMetric, FilterMetric):
diff --git a/robusta_krr/core/integrations/prometheus/metrics/memory.py b/robusta_krr/core/integrations/prometheus/metrics/memory.py
index 5fc6f73..d8779f2 100644
--- a/robusta_krr/core/integrations/prometheus/metrics/memory.py
+++ b/robusta_krr/core/integrations/prometheus/metrics/memory.py
@@ -1,6 +1,6 @@
from robusta_krr.core.models.objects import K8sObjectData
-from .base import QueryMetric, QueryRangeMetric, FilterMetric
+from .base import FilterMetric, QueryMetric, QueryRangeMetric
class MemoryLoader(QueryRangeMetric, FilterMetric):
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
index b0adfb7..8b4beef 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/base_metric_service.py
@@ -13,14 +13,6 @@ from robusta_krr.utils.configurable import Configurable
from ..metrics import PrometheusMetric
-class MetricsNotFound(Exception):
- """
- An exception raised when Metrics service is not found.
- """
-
- pass
-
-
class MetricsService(Configurable, abc.ABC):
def __init__(
self,
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
index b2cc135..5480512 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/prometheus_metrics_service.py
@@ -1,11 +1,12 @@
import asyncio
import datetime
import time
-from typing import List, Optional
from concurrent.futures import ThreadPoolExecutor
+from typing import List, Optional
from kubernetes.client import ApiClient
from prometheus_api_client import PrometheusApiClientException
+from prometrix import PrometheusNotFound, get_custom_prometheus_connect
from requests.exceptions import ConnectionError, HTTPError
from robusta_krr.core.abstract.strategies import PodsTimeData
@@ -14,8 +15,8 @@ from robusta_krr.core.models.objects import K8sObjectData, PodData
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
from ..metrics import PrometheusMetric
-from ..prometheus_client import ClusterNotSpecifiedException, CustomPrometheusConnect
-from .base_metric_service import MetricsNotFound, MetricsService
+from ..prometheus_utils import ClusterNotSpecifiedException, generate_prometheus_config
+from .base_metric_service import MetricsService
class PrometheusDiscovery(MetricsServiceDiscovery):
@@ -41,14 +42,6 @@ class PrometheusDiscovery(MetricsServiceDiscovery):
)
-class PrometheusNotFound(MetricsNotFound):
- """
- An exception raised when Prometheus is not found.
- """
-
- pass
-
-
class PrometheusMetricsService(MetricsService):
"""
A class for fetching metrics from Prometheus.
@@ -90,8 +83,10 @@ class PrometheusMetricsService(MetricsService):
headers |= {"Authorization": self.auth_header}
elif not self.config.inside_cluster and self.api_client is not None:
self.api_client.update_params_for_auth(headers, {}, ["BearerToken"])
-
- self.prometheus = CustomPrometheusConnect(url=self.url, disable_ssl=not self.ssl_enabled, headers=headers)
+ self.prom_config = generate_prometheus_config(
+ config, url=self.url, headers=headers, metrics_service=self
+ )
+ self.prometheus = get_custom_prometheus_connect(self.prom_config)
def check_connection(self):
"""
@@ -99,20 +94,8 @@ class PrometheusMetricsService(MetricsService):
Raises:
PrometheusNotFound: If the connection to Prometheus cannot be established.
"""
- try:
- response = self.prometheus._session.get(
- f"{self.prometheus.url}/api/v1/query",
- verify=self.prometheus.ssl_verification,
- headers=self.prometheus.headers,
- # This query should return empty results, but is correct
- params={"query": "example"},
- )
- response.raise_for_status()
- except (ConnectionError, HTTPError) as e:
- raise PrometheusNotFound(
- f"Couldn't connect to Prometheus found under {self.prometheus.url}\nCaused by {e.__class__.__name__}: {e})"
- ) from e
-
+ self.prometheus.check_prometheus_connection()
+
async def query(self, query: str) -> dict:
loop = asyncio.get_running_loop()
return await loop.run_in_executor(self.executor, lambda: self.prometheus.custom_query(query=query))
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
index 3b7ef85..eaf1620 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/thanos_metrics_service.py
@@ -1,10 +1,11 @@
from typing import Optional
from kubernetes.client import ApiClient
+from prometrix import MetricsNotFound, ThanosMetricsNotFound
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
-from .prometheus_metrics_service import MetricsNotFound, PrometheusMetricsService
+from .prometheus_metrics_service import PrometheusMetricsService
class ThanosMetricsDiscovery(MetricsServiceDiscovery):
@@ -27,14 +28,6 @@ class ThanosMetricsDiscovery(MetricsServiceDiscovery):
)
-class ThanosMetricsNotFound(MetricsNotFound):
- """
- An exception raised when Thanos is not found.
- """
-
- pass
-
-
class ThanosMetricsService(PrometheusMetricsService):
"""
A class for fetching metrics from Thanos.
diff --git a/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py b/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
index 925136a..a0f1010 100644
--- a/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
+++ b/robusta_krr/core/integrations/prometheus/metrics_service/victoria_metrics_service.py
@@ -1,10 +1,11 @@
from typing import Optional
from kubernetes.client import ApiClient
+from prometrix import MetricsNotFound, VictoriaMetricsNotFound
from robusta_krr.utils.service_discovery import MetricsServiceDiscovery
-from .prometheus_metrics_service import MetricsNotFound, PrometheusMetricsService
+from .prometheus_metrics_service import PrometheusMetricsService
class VictoriaMetricsDiscovery(MetricsServiceDiscovery):
@@ -26,14 +27,6 @@ class VictoriaMetricsDiscovery(MetricsServiceDiscovery):
)
-class VictoriaMetricsNotFound(MetricsNotFound):
- """
- An exception raised when Victoria Metrics is not found.
- """
-
- pass
-
-
class VictoriaMetricsService(PrometheusMetricsService):
"""
A class for fetching metrics from Victoria Metrics.
diff --git a/robusta_krr/core/integrations/prometheus/prometheus_client.py b/robusta_krr/core/integrations/prometheus/prometheus_client.py
deleted file mode 100644
index ac93608..0000000
--- a/robusta_krr/core/integrations/prometheus/prometheus_client.py
+++ /dev/null
@@ -1,91 +0,0 @@
-from typing import no_type_check
-
-import requests
-from datetime import datetime
-from prometheus_api_client import PrometheusConnect, Retry, PrometheusApiClientException
-from requests.adapters import HTTPAdapter
-
-
-class ClusterNotSpecifiedException(Exception):
- """
- An exception raised when a prometheus requires a cluster label but an invalid one is provided.
- """
-
- pass
-
-
-class CustomPrometheusConnect(PrometheusConnect):
- """
- Custom PrometheusConnect class to handle retries.
- """
-
- @no_type_check
- def __init__(
- self,
- url: str = "http://127.0.0.1:9090",
- headers: dict = None,
- disable_ssl: bool = False,
- retry: Retry = None,
- auth: tuple = None,
- ):
- super().__init__(url, headers, disable_ssl, retry, auth)
- self._session = requests.Session()
- self._session.mount(self.url, HTTPAdapter(max_retries=retry, pool_maxsize=10, pool_block=True))
-
- @no_type_check
- def custom_query(self, query: str, params: dict = None):
- params = params or {}
- data = None
- query = str(query)
- # using the query API to get raw data
- response = self._session.post(
- "{0}/api/v1/query".format(self.url),
- data={"query": query, **params},
- verify=self.ssl_verification,
- headers=self.headers,
- auth=self.auth,
- )
- if response.status_code == 200:
- data = response.json()["data"]["result"]
- else:
- raise PrometheusApiClientException(
- "HTTP Status Code {} ({!r})".format(response.status_code, response.content)
- )
-
- return data
-
- @no_type_check
- def custom_query_range(
- self,
- query: str,
- start_time: datetime,
- end_time: datetime,
- step: str,
- params: dict = None,
- ):
- start = round(start_time.timestamp())
- end = round(end_time.timestamp())
- params = params or {}
- data = None
- query = str(query)
- # using the query_range API to get raw data
- response = self._session.post(
- "{0}/api/v1/query_range".format(self.url),
- data={
- "query": query,
- "start": start,
- "end": end,
- "step": step,
- **params,
- },
- verify=self.ssl_verification,
- headers=self.headers,
- auth=self.auth,
- )
- if response.status_code == 200:
- data = response.json()["data"]["result"]
- else:
- raise PrometheusApiClientException(
- "HTTP Status Code {} ({!r})".format(response.status_code, response.content)
- )
- return data
diff --git a/robusta_krr/core/integrations/prometheus/prometheus_utils.py b/robusta_krr/core/integrations/prometheus/prometheus_utils.py
new file mode 100644
index 0000000..d4c6fd4
--- /dev/null
+++ b/robusta_krr/core/integrations/prometheus/prometheus_utils.py
@@ -0,0 +1,50 @@
+import boto3
+from prometrix import AWSPrometheusConfig, CoralogixPrometheusConfig, PrometheusConfig, VictoriaMetricsPrometheusConfig
+
+from robusta_krr.core.models.config import Config
+
+
+class ClusterNotSpecifiedException(Exception):
+ """
+ An exception raised when a prometheus requires a cluster label but an invalid one is provided.
+ """
+
+ pass
+
+
+def generate_prometheus_config(
+ config: Config, url: str, headers: dict[str, str], metrics_service: "PrometheusMetricsService"
+) -> PrometheusConfig:
+ from .metrics_service.victoria_metrics_service import VictoriaMetricsService
+
+ baseconfig = {
+ "url": url,
+ "disable_ssl": not config.prometheus_ssl_enabled,
+ "headers": headers,
+ }
+
+ # aws config
+ if config.eks_managed_prom:
+ session = boto3.Session(profile_name=config.eks_managed_prom_profile_name)
+ credentials = session.get_credentials()
+ credentials = credentials.get_frozen_credentials()
+ region = config.eks_managed_prom_region if config.eks_managed_prom_region else session.region_name
+ access_key = config.eks_access_key if config.eks_access_key else credentials.access_key
+ secret_key = config.eks_secret_key if config.eks_secret_key else credentials.secret_key
+ service_name = config.eks_service_name if config.eks_secret_key else "aps"
+ if not region:
+ raise Exception("No eks region specified")
+
+ return AWSPrometheusConfig(
+ access_key=access_key,
+ secret_access_key=secret_key,
+ aws_region=region,
+ service_name=service_name,
+ **baseconfig,
+ )
+ # coralogix config
+ if config.coralogix_token:
+ return CoralogixPrometheusConfig(**baseconfig, prometheus_token=config.coralogix_token)
+ if isinstance(metrics_service, VictoriaMetricsService):
+ return VictoriaMetricsPrometheusConfig(**baseconfig)
+ return PrometheusConfig(**baseconfig)
diff --git a/robusta_krr/core/models/config.py b/robusta_krr/core/models/config.py
index 7354a3d..70ae7a9 100644
--- a/robusta_krr/core/models/config.py
+++ b/robusta_krr/core/models/config.py
@@ -19,8 +19,8 @@ class Config(pd.BaseSettings):
selector: Optional[str] = None
# Value settings
- cpu_min_value: int = pd.Field(5, ge=0) # in millicores
- memory_min_value: int = pd.Field(10, ge=0) # in megabytes
+ cpu_min_value: int = pd.Field(100, ge=0) # in millicores
+ memory_min_value: int = pd.Field(100, ge=0) # in megabytes
# Prometheus Settings
prometheus_url: Optional[str] = pd.Field(None)
@@ -29,6 +29,13 @@ class Config(pd.BaseSettings):
prometheus_ssl_enabled: bool = pd.Field(False)
prometheus_cluster_label: Optional[str] = pd.Field(None)
prometheus_label: Optional[str] = pd.Field(None)
+ eks_managed_prom: bool = pd.Field(False)
+ eks_managed_prom_profile_name: Optional[str] = pd.Field(None)
+ eks_access_key: Optional[str] = pd.Field(None)
+ eks_secret_key: Optional[str] = pd.Field(None)
+ eks_service_name: Optional[str] = pd.Field(None)
+ eks_managed_prom_region: Optional[str] = pd.Field(None)
+ coralogix_token: Optional[str] = pd.Field(None)
# Threading settings
max_workers: int = pd.Field(6, ge=1)
diff --git a/robusta_krr/core/runner.py b/robusta_krr/core/runner.py
index 26ac3b1..f419c7c 100644
--- a/robusta_krr/core/runner.py
+++ b/robusta_krr/core/runner.py
@@ -9,10 +9,10 @@ import warnings
from robusta_krr.core.abstract.strategies import ResourceRecommendation, RunResult
from robusta_krr.core.integrations.kubernetes import KubernetesLoader
from robusta_krr.core.integrations.prometheus import (
- ClusterNotSpecifiedException,
PrometheusMetricsLoader,
- PrometheusNotFound,
+ ClusterNotSpecifiedException,
)
+from prometrix import PrometheusNotFound
from robusta_krr.core.models.config import Config
from robusta_krr.core.models.objects import K8sObjectData
from robusta_krr.core.models.result import (
diff --git a/robusta_krr/main.py b/robusta_krr/main.py
index 0b460d6..5fbe456 100644
--- a/robusta_krr/main.py
+++ b/robusta_krr/main.py
@@ -118,6 +118,48 @@ def load_commands() -> None:
help="The label in prometheus used to differentiate clusters. (Only relevant for centralized prometheus)",
rich_help_panel="Prometheus Settings",
),
+ eks_managed_prom: bool = typer.Option(
+ False,
+ "--eks-managed-prom",
+ help="Adds additional signitures for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_managed_prom_profile_name: Optional[str] = typer.Option(
+ None,
+ "--eks-profile-name",
+ help="Sets the profile name for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_access_key: Optional[str] = typer.Option(
+ None,
+ "--eks-access-key",
+ help="Sets the access key for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_secret_key: Optional[str] = typer.Option(
+ None,
+ "--eks-secret-key",
+ help="Sets the secret key for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_service_name: Optional[str] = typer.Option(
+ "aps",
+ "--eks-service-name",
+ help="Sets the service name for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ eks_managed_prom_region: Optional[str] = typer.Option(
+ None,
+ "--eks-managed-prom-region",
+ help="Sets the region for eks prometheus connection.",
+ rich_help_panel="Prometheus EKS Settings",
+ ),
+ coralogix_token: Optional[str] = typer.Option(
+ None,
+ "--coralogix-token",
+ help="Adds the token needed to query Coralogix managed prometheus.",
+ rich_help_panel="Prometheus Coralogix Settings",
+ ),
max_workers: int = typer.Option(
10,
"--max-workers",
@@ -146,6 +188,13 @@ def load_commands() -> None:
prometheus_ssl_enabled=prometheus_ssl_enabled,
prometheus_cluster_label=prometheus_cluster_label,
prometheus_label=prometheus_label,
+ eks_managed_prom=eks_managed_prom,
+ eks_managed_prom_region=eks_managed_prom_region,
+ eks_managed_prom_profile_name=eks_managed_prom_profile_name,
+ eks_access_key=eks_access_key,
+ eks_secret_key=eks_secret_key,
+ eks_service_name=eks_service_name,
+ coralogix_token=coralogix_token,
max_workers=max_workers,
format=format,
verbose=verbose,