import yaml import json import requests import sys import os from urllib.parse import urljoin def load_yaml(path): with open(path, 'r') as f: return yaml.safe_load(f) def fetch_index(repo_url): index_url = urljoin(repo_url + '/', 'index.yaml') print(f"Fetching index from {index_url}...") try: r = requests.get(index_url) r.raise_for_status() return yaml.safe_load(r.text) except Exception as e: print(f"Error fetching {index_url}: {e}") return None def main(): if len(sys.argv) < 2: print("Usage: python helm_sync.py [output_lock_file]") sys.exit(1) chartfile_path = sys.argv[1] lockfile_path = sys.argv[2] if len(sys.argv) > 2 else chartfile_path.replace('.yaml', '.lock.json') print(f"Reading {chartfile_path}...") chartfile = load_yaml(chartfile_path) repos = {r['name']: r['url'] for r in chartfile.get('repositories', [])} indices = {} lock_data = {"charts": {}} for req in chartfile.get('requires', []): chart_ref = req['chart'] version = req['version'] if '/' not in chart_ref: print(f"Invalid chart reference: {chart_ref}. Expected repo/name.") continue repo_name, chart_name = chart_ref.split('/', 1) if repo_name not in repos: print(f"Repository '{repo_name}' not found for chart {chart_ref}") continue repo_url = repos[repo_name] if repo_name not in indices: indices[repo_name] = fetch_index(repo_url) index = indices[repo_name] if not index: print(f"Skipping {chart_ref} due to missing index.") continue entries = index.get('entries', {}).get(chart_name, []) # Find exact version matched_entry = None for entry in entries: if entry['version'] == version: matched_entry = entry break if not matched_entry: print(f"Version {version} not found for chart {chart_ref}") continue # Resolve URL urls = matched_entry.get('urls', []) if not urls: print(f"No URLs found for {chart_ref} version {version}") continue # URL can be relative or absolute chart_url = urls[0] if not chart_url.startswith('http'): chart_url = urljoin(repo_url + '/', chart_url) digest = matched_entry.get('digest') print(f"Resolved {chart_ref} {version} -> {chart_url}") lock_data["charts"][chart_ref] = { "version": version, "url": chart_url, "digest": digest } print(f"Writing lockfile to {lockfile_path}...") with open(lockfile_path, 'w') as f: json.dump(lock_data, f, indent=2, sort_keys=True) f.write('\n') if __name__ == "__main__": main()