#!/usr/bin/env python3 import argparse import subprocess import json import re import sys from pathlib import Path import requests DOCKER_NAMESPACE = "esphome" DOCKER_REPO = "esphome" DOCKER_API = f"https://registry.hub.docker.com/v2/repositories/{DOCKER_NAMESPACE}/{DOCKER_REPO}/tags" def parse_version(raw_version): if len(raw_version) == 8 and raw_version.isdigit(): yyyy = raw_version[:4] m = str(int(raw_version[4:6])) d = str(int(raw_version[6:])) return f"{yyyy}.{m}.{d}" return raw_version def list_tags(upto_year): tags = [] pattern = re.compile(r"^(\d{4})\.(\d{1,2})\.(\d{1,2})$") # dokładnie 3 liczby rozdzielone kropkami page = 1 while True: resp = requests.get(DOCKER_API, params={"page_size": 100, "page": page}) resp.raise_for_status() data = resp.json() for entry in data.get("results", []): name = entry["name"] match = pattern.match(name) if match: year = int(match.group(1)) if year <= upto_year: tags.append(name) if not data.get("next"): break page += 1 tags.sort(key=lambda s: list(map(int, s.split('.')))) return tags def pull_image(tag): full = f"{DOCKER_NAMESPACE}/{DOCKER_REPO}:{tag}" subprocess.run(["docker", "pull", full], check=True) return full def run_container(version_tag, port): container = f"esphome-{version_tag.replace('/', '_')}" data_dir = f"/docker/data/esphome/{version_tag}" image = f"{DOCKER_NAMESPACE}/{DOCKER_REPO}:{version_tag}" Path(data_dir).mkdir(parents=True, exist_ok=True) cmd = [ "docker", "run", "-d", "--name", container, "--restart", "always", "-p", f"{port}:6052", "-v", f"{data_dir}:/config", image, "dashboard", "/config" ] print("Uruchamianie:", " ".join(cmd)) subprocess.run(cmd, check=True) print("Kontener uruchomiony.") def main(): parser = argparse.ArgumentParser() parser.add_argument("--version", help="yyyymmdd lub yyyy.m.d") parser.add_argument("--port", type=int, help="Port host →6052") parser.add_argument("--list-available", type=int, metavar="YEAR", help="Wyświetl tagi do danego roku (np. 2025)") args = parser.parse_args() if args.list_available is not None: tags = list_tags(args.list_available) print(f"Dostępne tagi do roku {args.list_available}:") for t in tags: print(" ", t) sys.exit(0) if not args.version or not args.port: parser.error("Wymagane: --version i --port albo sam --list-available") raw = args.version tag = parse_version(raw) # Sprawdź lokalnie exists = subprocess.run(["docker", "images", "-q", f"{DOCKER_NAMESPACE}/{DOCKER_REPO}:{tag}"], stdout=subprocess.DEVNULL).returncode == 0 if not exists: print(f"Obraz {tag} nie znaleziony lokalnie. Pobieram z Docker Hub...") try: pull_image(tag) except subprocess.CalledProcessError: sys.exit(f"Nie udało się pobrać esphome/esphome:{tag}") try: run_container(tag, args.port) except subprocess.CalledProcessError as e: sys.exit(f"Błąd uruchamiania kontenera: {e}") if __name__ == "__main__": main()