#!/usr/bin/env python3 # Usage: ./app-json.py # # Gather metadata from Co-op Cloud apps in $ABRA_DIR/apps (default # ~/.abra/apps), and format it as JSON so that it can be hosted here: # https://abra-apps.cloud.autonomic.zone from json import dump from os import chdir, listdir, mkdir from os.path import exists, expanduser from pathlib import Path from re import findall, search from shlex import split from subprocess import check_output, run from requests import get HOME_PATH = expanduser("~/") CLONES_PATH = Path(f"{HOME_PATH}/.abra/apps").absolute() SCRIPT_PATH = Path(__file__).absolute().parent def clone_apps(): if not exists(CLONES_PATH): mkdir(CLONES_PATH) response = get("https://git.autonomic.zone/api/v1/orgs/coop-cloud/repos") repos = [[p["name"], p["ssh_url"]] for p in response.json()] skips = ("organising", "cloud.autonomic.zone", "docs.cloud.autonomic.zone", "abra") for name, url in repos: if name in skips: continue try: if not exists(f"{CLONES_PATH}/{name}"): run(split(f"git clone {url} {CLONES_PATH}/{name}")) chdir(f"{CLONES_PATH}/{name}") if not int(check_output("git branch --list | wc -l", shell=True)): run(split("git checkout main")) except Exception: pass def gen_apps_json(): apps_json = {} for app in listdir(CLONES_PATH): app_path = f"{CLONES_PATH}/{app}" chdir(app_path) output = check_output("git tag --list", shell=True) tags = output.decode("utf-8").strip().split() if not tags: continue for tag in tags: apps_json[app] = { "category": "apps", "repository": f"https://git.autonomic.zone/coop-cloud/{app}.git", "features": get_app_features(app_path, tag), "versions": get_app_versions(app_path, tag), } return apps_json def get_app_features(app_path, tag): print(f"Gathering features for {app_path}, tag: {tag}") features = {} chdir(app_path) run(f"git checkout {tag}", shell=True) with open(f"{app_path}/README.md", "r") as handle: contents = handle.read() for match in findall(r"\*\*.*\s\*", contents): title = search(r"(?<=\*\*).*(?=\*\*)", match).group().lower() if title == "image": value = { "image": search(r"(?<=`).*(?=`)", match).group(), "url": search(r"(?<=\().*(?=\))", match).group(), "rating": match.split(",")[1].strip(), "source": match.split(",")[-1].replace("*", "").strip(), } else: value = match.split(":")[-1].replace("*", "").strip() features[title] = value run(f"git checkout HEAD", shell=True) return features def get_app_versions(app_path, tag): print(f"Gathering versions for {app_path}, tag: {tag}") versions = [] chdir(app_path) run(f"git checkout {tag}", shell=True) services_command = "yq e '.services | keys | .[]' compose*.yml" services = check_output(services_command, shell=True).decode("utf-8").split() for service in services: images_command = f"yq e '.services.{service}.image' compose*.yml" images = check_output(images_command, shell=True).decode("utf-8").split() for image in images: if image in ("null", "---"): continue digest_command = f"skopeo inspect docker://{image} | jq '.Digest'" output = check_output(digest_command, shell=True).decode("utf-8") digest = output.strip().split(":")[-1][:8] image_name = image.split(":")[0] versions.append( {service: {"image": image_name, "tag": tag, "digest": digest}} ) run(f"git checkout HEAD", shell=True) return versions clone_apps() target = f"{SCRIPT_PATH}/../deploy/abra-apps.cloud.autonomic.zone/abra-apps.json" with open(target, "w", encoding="utf-8") as handle: dump(gen_apps_json(), handle, ensure_ascii=False, indent=4) print(f"Output saved to {target}")