#!/usr/bin/env python3 """ Laedt die gebauten Installer-Binaries in den Webroot unter /installer/. Getrennt von deploy.py, weil dieses client-dotnet bewusst ausklammert: der Quelltext des Agenten gehoert nicht auf den Webserver, die uebersetzten Binaries schon. Aufruf: python scripts/upload_installer.py Erwartet im Verzeichnis: die Binaries, je eine .sha256 dazu, installer.json sowie install.sh und install.ps1. Erzeugt wird das alles von scripts/build_installer.ps1. """ import ftplib import hashlib import json import os import ssl import sys from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent CONFIG_FILE = SCRIPT_DIR / 'deploy_config.json' REMOTE_DIR = '/installer' def load_config(): if not CONFIG_FILE.exists(): print(f'Fehler: {CONFIG_FILE} fehlt.') sys.exit(1) with open(CONFIG_FILE, 'r', encoding='utf-8') as handle: return json.load(handle) def connect(config): if config.get('secure', False): ftp = ftplib.FTP_TLS(context=ssl.create_default_context()) ftp.connect(config['host'], config.get('port', 21)) ftp.login(config['user'], config['pass']) ftp.prot_p() else: ftp = ftplib.FTP() ftp.connect(config['host'], config.get('port', 21)) ftp.login(config['user'], config['pass']) return ftp def ensure_remote_dir(ftp, path): current = '' for part in [p for p in path.strip('/').split('/') if p]: current += '/' + part try: ftp.cwd(current) except ftplib.error_perm: try: ftp.mkd(current) print(f'Verzeichnis angelegt: {current}') except Exception as exc: # noqa: BLE001 print(f'Warnung: {current} nicht anlegbar: {exc}') def sha256(path): digest = hashlib.sha256() with open(path, 'rb') as handle: while chunk := handle.read(65536): digest.update(chunk) return digest.hexdigest() def main(): if len(sys.argv) < 2: print(__doc__) sys.exit(1) source = Path(sys.argv[1]).resolve() if not source.is_dir(): print(f'Fehler: {source} ist kein Verzeichnis.') sys.exit(1) files = sorted(p for p in source.iterdir() if p.is_file()) if not files: print(f'Fehler: In {source} liegt nichts.') sys.exit(1) config = load_config() print(f'Verbinde mit {config["host"]} ...') ftp = connect(config) print('Angemeldet.') ensure_remote_dir(ftp, REMOTE_DIR) uploaded = 0 try: for path in files: remote = f'{REMOTE_DIR}/{path.name}' size_mb = path.stat().st_size / (1024 * 1024) print(f' {path.name} ({size_mb:.1f} MB) ...') ftp.cwd('/') with open(path, 'rb') as handle: ftp.storbinary(f'STOR {remote}', handle, blocksize=262144) uploaded += 1 finally: try: ftp.quit() except Exception: # noqa: BLE001 pass print(f'\n{uploaded} von {len(files)} Datei(en) uebertragen nach {REMOTE_DIR}.') # Zur Kontrolle: die Pruefsummen, die auch auf der Downloadseite stehen. print('\nPruefsummen:') for path in files: if path.suffix in ('.sha256', '.json', '.ps1', '.sh'): continue print(f' {path.name} {sha256(path)}') if __name__ == '__main__': main()