Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions static/compatibilities/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ names:
- wiz-network-analyzer
- kuberay-operator
- mongodb-kubernetes
- mariadb-operator
95 changes: 95 additions & 0 deletions static/compatibilities/mariadb-operator.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
icon: https://mariadb-operator.github.io/mariadb-operator/assets/mariadb_profile.svg
git_url: https://github.com/mariadb-operator/mariadb-operator
release_url: https://github.com/mariadb-operator/mariadb-operator/releases/tag/{vsn}
helm_repository_url: https://mariadb-operator.github.io/mariadb-operator
chart_name: mariadb-operator
versions:
- version: 26.6.0
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 26.6.0
images: ['ghcr.io/mariadb-operator/mariadb-operator:26.6.0']
- version: 26.3.0
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 26.3.0
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:26.3.0']
- version: 25.10.4
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 25.10.4
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:25.10.4']
- version: 25.8.4
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 25.8.4
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:25.8.4']
- version: 0.38.1
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.38.1
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:0.38.1']
- version: 0.37.1
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.37.1
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:0.37.1']
- version: 0.36.0
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.36.0
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:0.36.0']
- version: 0.35.1
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.35.1
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:0.35.1']
- version: 0.34.0
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.34.0
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:0.34.0']
- version: 0.0.33
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.33.0
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:v0.0.33']
- version: 0.0.29
kube: ['1.36', '1.35', '1.34', '1.33', '1.32', '1.31', '1.30', '1.29', '1.28', '1.27',
'1.26', '1.25', '1.24', '1.23', '1.22', '1.21', '1.20', '1.19', '1.18', '1.17',
'1.16']
requirements: []
incompatibilities: []
summary: null
chart_version: 0.29.0
images: ['docker-registry3.mariadb.com/mariadb-operator/mariadb-operator:v0.0.29']
215 changes: 215 additions & 0 deletions utils/compatibility/scrapers/mariadb-operator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
from __future__ import annotations

import re
from collections import OrderedDict

import yaml

from utils import (
current_kube_version,
fetch_page,
print_error,
read_yaml,
update_compatibility_info,
validate_semver,
write_yaml,
)


APP_NAME = "mariadb-operator"
CHART_NAME = "mariadb-operator"
HELM_INDEX_URL = "https://mariadb-operator.github.io/mariadb-operator/index.yaml"
OUTPUT_PATH = f"../../static/compatibilities/{APP_NAME}.yaml"


def _clean_version(version):
parsed = validate_semver(str(version).strip().lstrip("v"))
return str(parsed) if parsed else None


def _minor(version):
parsed = validate_semver(version)
if not parsed:
return None
return f"{parsed.major}.{parsed.minor}"


def _minor_bounds(version):
parsed = validate_semver(version)
if not parsed:
return None
return parsed.major, parsed.minor


def _next_minor(major, minor):
return major, minor + 1


def _version_tuple(major, minor, patch=0):
return int(major), int(minor), int(patch or 0)


def _parse_constraints(spec):
normalized = spec.replace(",", " ")
constraints = []

for operator, major, minor, patch in re.findall(
r"(>=|<=|<|>|=)?\s*v?(\d+)\.(\d+)(?:\.(\d+))?",
normalized,
):
constraints.append((operator or ">=", _version_tuple(major, minor, patch)))

return constraints


def _minor_satisfies_constraints(major, minor, constraints):
start = (major, minor, 0)
end = (*_next_minor(major, minor), 0)

for operator, bound in constraints:
if operator in (">=", ">"):
if end <= bound:
return False
elif operator == "<":
if start >= bound:
return False
elif operator == "<=":
if start > bound:
return False
elif operator == "=":
if not (start <= bound < end):
return False

return True


def parse_kube_constraint(spec, latest_kube):
if not spec or not latest_kube:
return []

latest = _minor_bounds(latest_kube)
if not latest:
return []

constraints = _parse_constraints(spec)
lower_bounds = [
(bound[0], bound[1])
for operator, bound in constraints
if operator in (">=", ">", "=")
]
if not constraints or not lower_bounds:
return []

major, minor = max(lower_bounds)
kube_versions = []

while (major, minor) <= latest:
if _minor_satisfies_constraints(major, minor, constraints):
kube_versions.append(f"{major}.{minor}")
major, minor = _next_minor(major, minor)

return kube_versions


def load_index(content):
try:
return yaml.safe_load(content)
except yaml.YAMLError as exc:
print_error(f"Failed to parse MariaDB Operator Helm index: {exc}")
return None


def extract_rows(index_yaml, latest_kube):
rows_by_version = {}
entries = index_yaml.get("entries", {}).get(CHART_NAME, [])

for entry in entries:
app_version = _clean_version(entry.get("appVersion", ""))
chart_version = _clean_version(entry.get("version", ""))
if not app_version or not chart_version:
continue

kube_versions = parse_kube_constraint(entry.get("kubeVersion", ""), latest_kube)
if not kube_versions:
continue

current = rows_by_version.get(app_version)
if current and validate_semver(chart_version) <= validate_semver(current["chart_version"]):
continue

rows_by_version[app_version] = OrderedDict(
[
("version", app_version),
("kube", kube_versions),
("chart_version", chart_version),
("images", []),
("requirements", []),
("incompatibilities", []),
]
)

rows = sorted(
rows_by_version.values(),
key=lambda row: validate_semver(row["version"]),
reverse=True,
)
return _representative_rows(rows)


def _representative_rows(rows):
selected = []
seen = {}

for row in rows:
minor = _minor(row["version"])
if not minor:
continue

kube = tuple(row["kube"])
if minor not in seen:
selected.append(row)
seen[minor] = kube
continue

if seen[minor] != kube:
selected.append(row)
seen[minor] = kube

return selected


def prune_stale_representatives(filepath, rows):
data = read_yaml(filepath)
if not data or "versions" not in data:
return

keep = {row["version"] for row in rows}
data["versions"] = [
version
for version in data.get("versions", [])
if version.get("version") in keep
]
write_yaml(filepath, data)


def scrape():
latest_kube = current_kube_version()
if not latest_kube:
print_error("Could not determine current Kubernetes version from KUBE_VERSION.")
return

content = fetch_page(HELM_INDEX_URL)
if not content:
return

index_yaml = load_index(content)
if not index_yaml:
return

rows = extract_rows(index_yaml, latest_kube)
if not rows:
print_error("No MariaDB Operator versions extracted from Helm index.")
return

prune_stale_representatives(OUTPUT_PATH, rows)
update_compatibility_info(OUTPUT_PATH, rows)
Loading
Loading