fix: rewrite helm index.yaml URLs post-parse to handle relative URLs (#37)
Closes #33 ## Summary - `_merge_helm_indexes` now parses each member's raw YAML first, then rewrites `urls` entries in-place via the new `_rewrite_urls` helper - **Relative URLs** (e.g. `rancher-2.13.1.tgz`) are prepended with `{proxy_base}/api/v1/remote/{member_name}/` - **Absolute URLs** matching `base_url` are rewritten to the proxy path (existing behaviour, now correct) - **Absolute URLs** with a different prefix are left unchanged - Removes the `_helm.resolve_content` raw-bytes detour from the virtual merge path; `remote/helm.py` is unchanged (still used for direct remote proxying) ## Test plan - [x] 278 unit tests pass (`make test`) - [x] New `TestRewriteUrls` class covering relative, absolute-match, absolute-no-match, leading-slash, and multi-URL cases - [x] New `test_relative_urls_rewritten_to_proxy` in `TestMergeHelmIndexes` - [x] Updated `test_first_member_wins_on_duplicate_name_and_version` to assert on proxy remote name (not upstream hostname) - [x] Live Docker test: Rancher `index.yaml` relative URLs rewritten correctly to `http://localhost:8000/api/v1/remote/rancher-stable/rancher-2.14.1.tgz` etc. - [x] `helm-all` virtual (19 members) returns HTTP 200 with 395k-line merged index on cache miss Reviewed-on: #37
This commit was merged in pull request #37.
This commit is contained in:
@@ -9,8 +9,6 @@ import httpx
|
||||
import yaml
|
||||
from fastapi import HTTPException, Request, Response
|
||||
|
||||
from ..remote import helm as _helm
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -86,6 +84,19 @@ async def _get_member_index(
|
||||
return member_name, member_cfg, member_ttl, raw_data
|
||||
|
||||
|
||||
def _rewrite_urls(urls: list, base_url: str, proxy_base: str, member_name: str) -> list:
|
||||
proxy_remote = f"{proxy_base}/api/v1/remote/{member_name}"
|
||||
rewritten = []
|
||||
for url in urls:
|
||||
if url.startswith(("http://", "https://")):
|
||||
if base_url and url.startswith(base_url):
|
||||
url = proxy_remote + url[len(base_url) :]
|
||||
else:
|
||||
url = f"{proxy_remote}/{url.lstrip('/')}"
|
||||
rewritten.append(url)
|
||||
return rewritten
|
||||
|
||||
|
||||
def _merge_helm_indexes(raw_indexes: list[bytes], member_names: list[str], member_configs: list[dict], proxy_base: str) -> bytes:
|
||||
"""Merge helm index.yaml files with per-member URL rewriting.
|
||||
|
||||
@@ -96,15 +107,21 @@ def _merge_helm_indexes(raw_indexes: list[bytes], member_names: list[str], membe
|
||||
|
||||
for raw_data, member_name, member_cfg in zip(raw_indexes, member_names, member_configs):
|
||||
base_url = member_cfg.get("base_url", "").rstrip("/")
|
||||
rewritten, _ = _helm.resolve_content(raw_data, "index.yaml", "index.yaml", base_url, proxy_base, member_name)
|
||||
|
||||
try:
|
||||
index = yaml.safe_load(rewritten)
|
||||
index = yaml.safe_load(raw_data)
|
||||
except Exception as e:
|
||||
logger.warning(f"Virtual: failed to parse index.yaml from member '{member_name}': {e}")
|
||||
continue
|
||||
|
||||
for chart_name, versions in (index.get("entries") or {}).items():
|
||||
for version_entry in versions:
|
||||
version_entry["urls"] = _rewrite_urls(
|
||||
version_entry.get("urls") or [],
|
||||
base_url,
|
||||
proxy_base,
|
||||
member_name,
|
||||
)
|
||||
if chart_name not in merged_entries:
|
||||
merged_entries[chart_name] = list(versions)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user