From ebd6466113b9e2abef89db59eb9cee97ea038f37 Mon Sep 17 00:00:00 2001 From: Smyja Date: Mon, 26 Jan 2026 23:31:05 +0100 Subject: [PATCH] feat: added kubescape compatibility and scraper --- .../compatibilities/kubescape-operator.yaml | 221 ++++++++++++++++++ static/compatibilities/manifest.yaml | 1 + .../scrapers/kubescape-operator.py | 90 +++++++ 3 files changed, 312 insertions(+) create mode 100644 static/compatibilities/kubescape-operator.yaml create mode 100644 utils/compatibility/scrapers/kubescape-operator.py diff --git a/static/compatibilities/kubescape-operator.yaml b/static/compatibilities/kubescape-operator.yaml new file mode 100644 index 0000000000..4d9464484a --- /dev/null +++ b/static/compatibilities/kubescape-operator.yaml @@ -0,0 +1,221 @@ +icon: https://avatars.githubusercontent.com/u/100554170?v=4 +git_url: https://github.com/kubescape/helm-charts +release_url: https://github.com/kubescape/helm-charts/releases/tag/kubescape-operator-{vsn} +helm_repository_url: https://kubescape.github.io/helm-charts +helm_values: clusterName=example,account=example +versions: +- version: 1.30.2 + kube: ['1.35', '1.34', '1.33'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.30.2 + images: ['quay.io/kubescape/http-request:v0.2.16', 'quay.io/kubescape/kubescape:v3.0.47', + 'quay.io/kubescape/kubevuln:v0.3.98', 'quay.io/kubescape/node-agent:v0.3.11', + 'quay.io/kubescape/operator:v0.2.121', 'quay.io/kubescape/storage:v0.0.237'] +- version: 1.30.0 + kube: ['1.35', '1.34', '1.33'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.30.0 + images: ['quay.io/kubescape/http-request:v0.2.16', 'quay.io/kubescape/kubescape:v3.0.47', + 'quay.io/kubescape/kubevuln:v0.3.98', 'quay.io/kubescape/node-agent:v0.3.3', 'quay.io/kubescape/operator:v0.2.119', + 'quay.io/kubescape/storage:v0.0.233'] +- version: 1.29.12 + kube: ['1.35', '1.34', '1.33'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.29.12 + images: ['quay.io/kubescape/http-request:v0.2.15', 'quay.io/kubescape/kubescape:v3.0.45', + 'quay.io/kubescape/kubevuln:v0.3.97', 'quay.io/kubescape/node-agent:v0.2.398', + 'quay.io/kubescape/operator:v0.2.114', 'quay.io/kubescape/storage:v0.0.224'] +- version: 1.29.1 + kube: ['1.34', '1.33', '1.32'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.29.1 + images: ['quay.io/kubescape/http-request:v0.2.14', 'quay.io/kubescape/kubescape:v3.0.38', + 'quay.io/kubescape/kubevuln:v0.3.84', 'quay.io/kubescape/node-agent:v0.2.377', + 'quay.io/kubescape/operator:v0.2.99', 'quay.io/kubescape/storage:v0.0.208'] +- version: 1.29.0 + kube: ['1.33', '1.32', '1.31'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.29.0 + images: ['quay.io/kubescape/http-request:v0.2.12', 'quay.io/kubescape/kubescape:v3.0.37', + 'quay.io/kubescape/kubevuln:v0.3.82', 'quay.io/kubescape/node-agent:v0.2.357', + 'quay.io/kubescape/operator:v0.2.97', 'quay.io/kubescape/storage:v0.0.206'] +- version: 1.28.0 + kube: ['1.33', '1.32', '1.31'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.28.0 + images: ['quay.io/kubescape/http-request:v0.2.11', 'quay.io/kubescape/kubescape:v3.0.34', + 'quay.io/kubescape/kubevuln:v0.3.80', 'quay.io/kubescape/node-agent:v0.2.345', + 'quay.io/kubescape/operator:v0.2.91', 'quay.io/kubescape/storage:v0.0.185'] +- version: 1.27.3 + kube: ['1.33', '1.32', '1.31'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.27.3 + images: ['quay.io/kubescape/kubescape:v3.0.34', 'quay.io/kubescape/kubevuln:v0.3.72', + 'quay.io/kubescape/node-agent:v0.2.298', 'quay.io/kubescape/operator:v0.2.84', + 'quay.io/kubescape/storage:v0.0.172'] +- version: 1.27.0 + kube: ['1.32', '1.31', '1.30'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.27.0 + images: ['quay.io/kubescape/kubescape:v3.0.34', 'quay.io/kubescape/kubevuln:v0.3.69', + 'quay.io/kubescape/node-agent:v0.2.282', 'quay.io/kubescape/operator:v0.2.81', + 'quay.io/kubescape/storage:v0.0.172'] +- version: 1.26.0 + kube: ['1.32', '1.31', '1.30'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.26.0 + images: ['quay.io/kubescape/kubescape:v3.0.30', 'quay.io/kubescape/kubevuln:v0.3.62', + 'quay.io/kubescape/node-agent:v0.2.259', 'quay.io/kubescape/operator:v0.2.74', + 'quay.io/kubescape/storage:v0.0.161'] +- version: 1.25.0 + kube: ['1.32', '1.31', '1.30'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.25.0 + images: ['quay.io/kubescape/kubescape:v3.0.23', 'quay.io/kubescape/kubevuln:v0.3.52', + 'quay.io/kubescape/node-agent:v0.2.210', 'quay.io/kubescape/operator:v0.2.63', + 'quay.io/kubescape/storage:v0.0.148'] +- version: 1.24.0 + kube: ['1.32', '1.31', '1.30'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.24.0 + images: ['quay.io/kubescape/kubescape:v3.0.22', 'quay.io/kubescape/kubevuln:v0.3.48', + 'quay.io/kubescape/node-agent:v0.2.204', 'quay.io/kubescape/operator:v0.2.55', + 'quay.io/kubescape/storage:v0.0.146'] +- version: 1.23.4 + kube: ['1.32', '1.31', '1.30'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.23.4 + images: ['quay.io/kubescape/kubescape:v3.0.21', 'quay.io/kubescape/kubevuln:v0.3.41', + 'quay.io/kubescape/node-agent:v0.2.197', 'quay.io/kubescape/operator:v0.2.51', + 'quay.io/kubescape/storage:v0.0.141'] +- version: 1.23.0 + kube: ['1.31', '1.30', '1.29'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.23.0 + images: ['quay.io/kubescape/kubescape:v3.0.21', 'quay.io/kubescape/kubevuln:v0.3.36', + 'quay.io/kubescape/node-agent:v0.2.178', 'quay.io/kubescape/operator:v0.2.41', + 'quay.io/kubescape/storage:v0.0.137'] +- version: 1.22.0 + kube: ['1.31', '1.30', '1.29'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.22.0 + images: ['quay.io/kubescape/kubescape:v3.0.17', 'quay.io/kubescape/kubevuln:v0.3.33', + 'quay.io/kubescape/node-agent:v0.2.141', 'quay.io/kubescape/operator:v0.2.31', + 'quay.io/kubescape/storage:v0.0.117'] +- version: 1.21.0 + kube: ['1.31', '1.30', '1.29'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.21.0 + images: ['docker.io/bitnami/kubectl:1.30.3', 'quay.io/kubescape/kubescape:v3.0.16', + 'quay.io/kubescape/kubevuln:v0.3.30', 'quay.io/kubescape/node-agent:v0.2.130', + 'quay.io/kubescape/operator:v0.2.28', 'quay.io/kubescape/storage:v0.0.106'] +- version: 1.20.3 + kube: ['1.31', '1.30', '1.29'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.20.3 + images: ['quay.io/kubescape/kubescape:v3.0.15', 'quay.io/kubescape/kubevuln:v0.3.25', + 'quay.io/kubescape/node-agent:v0.2.109', 'quay.io/kubescape/operator:v0.2.20', + 'quay.io/kubescape/storage:v0.0.90'] +- version: 1.20.1 + kube: ['1.30', '1.29', '1.28'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.20.1 + images: ['quay.io/kubescape/kubescape:v3.0.15', 'quay.io/kubescape/kubevuln:v0.3.25', + 'quay.io/kubescape/node-agent:v0.2.105', 'quay.io/kubescape/operator:v0.2.20', + 'quay.io/kubescape/storage:v0.0.90'] +- version: 1.19.1 + kube: ['1.30', '1.29', '1.28'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.19.1 + images: ['quay.io/kubescape/kubescape:v3.0.13', 'quay.io/kubescape/kubevuln:v0.3.25', + 'quay.io/kubescape/node-agent:v0.2.93', 'quay.io/kubescape/operator:v0.2.13', + 'quay.io/kubescape/storage:v0.0.89'] +- version: 1.18.11 + kube: ['1.30', '1.29', '1.28'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.18.11 + images: ['quay.io/kubescape/kubescape:v3.0.8', 'quay.io/kubescape/kubevuln:v0.3.14', + 'quay.io/kubescape/node-agent:v0.2.50', 'quay.io/kubescape/operator:v0.2.9', 'quay.io/kubescape/storage:v0.0.81'] +- version: 1.18.0 + kube: ['1.29', '1.28', '1.27'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.18.0 + images: ['quay.io/kubescape/kubescape:v3.0.3', 'quay.io/kubescape/kubevuln:v0.3.0', + 'quay.io/kubescape/node-agent:v0.2.4', 'quay.io/kubescape/operator:v0.2.1', 'quay.io/kubescape/storage:v0.0.60'] +- version: 1.17.0 + kube: ['1.29', '1.28', '1.27'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.17.0 + images: [] +- version: 1.16.5 + kube: ['1.29', '1.28', '1.27'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.16.5 + images: [] +- version: 1.16.0 + kube: ['1.28', '1.27', '1.26'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.16.0 + images: [] +- version: 1.15.0 + kube: ['1.28', '1.27', '1.26'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 1.15.0 + images: [] +- version: 0.29.6 + kube: ['1.34', '1.33', '1.32'] + requirements: [] + incompatibilities: [] + summary: null + chart_version: 0.29.6 + images: ['quay.io/kubescape/http-request:v0.2.14', 'quay.io/kubescape/kubescape:v3.0.40', + 'quay.io/kubescape/kubevuln:v0.3.86', 'quay.io/kubescape/node-agent:test-0a5ff33', + 'quay.io/kubescape/operator:v0.2.103', 'quay.io/kubescape/storage:v0.0.212'] diff --git a/static/compatibilities/manifest.yaml b/static/compatibilities/manifest.yaml index b800a06c0c..13179197f6 100644 --- a/static/compatibilities/manifest.yaml +++ b/static/compatibilities/manifest.yaml @@ -36,3 +36,4 @@ names: - elastic-agent - rabbitmq-cluster-operator - kserve +- kubescape-operator diff --git a/utils/compatibility/scrapers/kubescape-operator.py b/utils/compatibility/scrapers/kubescape-operator.py new file mode 100644 index 0000000000..42b8db4fc9 --- /dev/null +++ b/utils/compatibility/scrapers/kubescape-operator.py @@ -0,0 +1,90 @@ +from __future__ import annotations + +from typing import Optional + +from utils import ( + clean_kube_version, + find_last_n_releases, + get_chart_versions, + get_github_releases_timestamps, + get_kube_release_info, + print_error, + update_compatibility_info, + validate_semver, +) + + +app_name = "kubescape-operator" +TAG_PREFIX = "kubescape-operator-" + + +def _parse_release_tag(tag: str) -> Optional[str]: + if not tag.startswith(TAG_PREFIX): + return None + + version = tag[len(TAG_PREFIX) :] + if "-" in version: + return None + + semver = validate_semver(version) + if not semver: + return None + + return str(semver) + + +def _load_chart_releases() -> list[tuple[str, object]]: + releases = [] + for tag, ts in get_github_releases_timestamps("kubescape", "helm-charts"): + version = _parse_release_tag(tag) + if not version: + continue + releases.append((version, ts)) + + releases.sort(key=lambda item: item[1]) + return releases + + +def scrape() -> None: + kube_releases = get_kube_release_info() + chart_versions = get_chart_versions(app_name) + if not chart_versions: + print_error("No chart versions found for kubescape-operator.") + return + + releases = _load_chart_releases() + if not releases: + print_error("No kubescape-operator releases found.") + return + + versions = [] + for idx, (release_vsn, ts) in enumerate(releases): + chart_version = chart_versions.get(release_vsn) + if not chart_version: + continue + + future_release_ts = ts + if idx < len(releases) - 1: + future_release_ts = releases[idx + 1][1] + + compatible_kube_releases = find_last_n_releases( + kube_releases, future_release_ts, n=3 + ) + kube_versions = [ + clean_kube_version(kube_release[0]) + for kube_release in compatible_kube_releases + ] + + versions.append( + { + "version": release_vsn, + "kube": kube_versions, + "requirements": [], + "chart_version": chart_version, + "incompatibilities": [], + } + ) + + update_compatibility_info( + f"../../static/compatibilities/{app_name}.yaml", versions + )