katalon-cli 0.3.3__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/PKG-INFO +1 -1
  2. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/pyproject.toml +1 -1
  3. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/pyproject.toml.orig +1 -1
  4. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/checks.py +29 -0
  5. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/docker.py +6 -0
  6. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/main.py +11 -0
  7. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/templates/compose.yaml.j2 +10 -2
  8. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/README.md +0 -0
  9. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/__init__.py +0 -0
  10. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/__init__.py +0 -0
  11. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/backup.py +0 -0
  12. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/compose_gen.py +0 -0
  13. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/paths.py +0 -0
  14. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/permissions.py +0 -0
  15. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/reindex.py +0 -0
  16. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/release.py +0 -0
  17. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/selfupdate.py +0 -0
  18. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/core/state.py +0 -0
  19. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/py.typed +0 -0
  20. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/templates/Caddyfile.j2 +0 -0
  21. {katalon_cli-0.3.3 → katalon_cli-0.3.5}/src/katalon_cli/templates/nginx.conf.j2 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: katalon-cli
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Installer & Updater CLI für Katalon Production-Instanzen
5
5
  Author: Karl Krägelin
6
6
  Author-email: Karl Krägelin <karlkraegelin@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "katalon-cli"
3
- version = "0.3.3"
3
+ version = "0.3.5"
4
4
  description = "Installer & Updater CLI für Katalon Production-Instanzen"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "katalon-cli"
3
- version = "0.3.3"
3
+ version = "0.3.5"
4
4
  description = "Installer & Updater CLI für Katalon Production-Instanzen"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -9,6 +9,9 @@ from dataclasses import dataclass
9
9
  from pathlib import Path
10
10
 
11
11
  MIN_FREE_DISK_GB = 5
12
+ # Elasticsearch verweigert Shard-Allokation ab 90 % (high watermark).
13
+ MAX_USED_PERCENT = 90
14
+ REAL_FS = {"ext2", "ext3", "ext4", "xfs", "btrfs", "zfs", "f2fs"}
12
15
 
13
16
 
14
17
  @dataclass
@@ -49,6 +52,32 @@ def check_disk_space(path: Path, min_gb: int = MIN_FREE_DISK_GB) -> CheckResult:
49
52
  "Diskspace", ok, f"{free_gb:.1f} GB frei (min. {min_gb} GB) in {path}"
50
53
  )
51
54
 
55
+ def _mount_points(instance_dir: Path) -> list[Path]:
56
+ """Alle echten Dateisysteme des Hosts; ohne /proc/mounts Instanzverzeichnis und `/`."""
57
+ try:
58
+ lines = Path("/proc/mounts").read_text().splitlines()
59
+ except OSError:
60
+ return [instance_dir, Path("/")]
61
+ return [Path(f[1].replace("\\040", " ")) for f in map(str.split, lines) if f[2] in REAL_FS]
62
+
63
+
64
+ def check_server_disk(instance_dir: Path, max_used: int = MAX_USED_PERCENT) -> CheckResult:
65
+ full = []
66
+ for mount in _mount_points(instance_dir):
67
+ try:
68
+ usage = shutil.disk_usage(mount)
69
+ except OSError:
70
+ continue
71
+ used = usage.used * 100 / (usage.used + usage.free)
72
+ if used >= max_used:
73
+ full.append(f"{mount} {used:.0f} %")
74
+ if full:
75
+ return CheckResult(
76
+ "Server-Disk", False, f"≥ {max_used} % belegt: {', '.join(full)} — Elasticsearch blockiert ab 90 %"
77
+ )
78
+ return CheckResult("Server-Disk", True, f"alle Dateisysteme < {max_used} % belegt")
79
+
80
+
52
81
  def check_openssl() -> CheckResult:
53
82
  if not shutil.which("openssl"):
54
83
  return CheckResult("OpenSSL", False, "nicht gefunden — für TLS-Modus 'standalone' erforderlich")
@@ -45,6 +45,12 @@ def compose(
45
45
  )
46
46
 
47
47
 
48
+ def reload_nginx(instance_dir: Path) -> None:
49
+ """`up -d` erstellt nginx nicht neu, wenn nur die gemountete nginx.conf sich ändert."""
50
+ compose(instance_dir, "exec", "-T", "nginx", "nginx", "-t")
51
+ compose(instance_dir, "exec", "-T", "nginx", "nginx", "-s", "reload")
52
+
53
+
48
54
  def is_healthy(instance_dir: Path, service: str = "api") -> bool:
49
55
  result = compose(
50
56
  instance_dir, "ps", "--format", "json", service, check=False, capture=True
@@ -689,6 +689,7 @@ def update(
689
689
  ):
690
690
  """Update auf neue Version — Backup zuerst, immer."""
691
691
  dir = instance_dir_or_raise(dir)
692
+ _require_disk(dir)
692
693
  state = InstallationState.load(dir)
693
694
  try:
694
695
  meta = release.get_release(target) if target else release.get_latest_release()
@@ -754,6 +755,7 @@ def update(
754
755
  ("Medienrechte prüfen", lambda: _ensure_media_permissions(dir)),
755
756
  # DB-Migration läuft automatisch im api-Container-Entrypoint beim Start.
756
757
  ("Container neu starten", lambda: docker.compose(dir, "up", "-d")),
758
+ ("nginx-Konfiguration neu laden", lambda: docker.reload_nginx(dir)),
757
759
  ]
758
760
 
759
761
  with Progress(SpinnerColumn(), TextColumn("[progress.description]{task.description}"), console=console) as progress:
@@ -843,10 +845,19 @@ def rollback(
843
845
 
844
846
  _ensure_media_permissions(dir)
845
847
  docker.compose(dir, "up", "-d")
848
+ docker.reload_nginx(dir)
846
849
  console.print("[green]✔[/] Rollback abgeschlossen.")
847
850
 
848
851
 
852
+ def _require_disk(dir: Path) -> None:
853
+ result = checks.check_server_disk(dir)
854
+ if not result.ok:
855
+ console.print(f"[red]✖[/] {result.name}: {result.detail}")
856
+ raise typer.Exit(1)
857
+
858
+
849
859
  def _run_reindex(dir: Path, wait: bool = True) -> None:
860
+ _require_disk(dir)
850
861
  if not docker.is_healthy(dir, "api") or not docker.is_running(dir, "worker"):
851
862
  console.print("[red]✖[/] API oder Worker laufen nicht — erst `katalon start`.")
852
863
  raise typer.Exit(1)
@@ -42,7 +42,7 @@ services:
42
42
  # Legt den Derivat-Cache an und übergibt ihn dem Cantaloupe-User des Images.
43
43
  # Ändert nur Einträge mit falschem Eigentümer (idempotent, schnell bei vollem Cache).
44
44
  cantaloupe-cache-init:
45
- image: islandora/cantaloupe:main
45
+ image: islandora/cantaloupe:7.0.22
46
46
  user: "0:0"
47
47
  entrypoint: ["sh", "-c", "mkdir -p /data/cache && find /data ! -user cantaloupe -exec chown cantaloupe:cantaloupe {} +"]
48
48
  volumes:
@@ -50,7 +50,7 @@ services:
50
50
  restart: "no"
51
51
 
52
52
  cantaloupe:
53
- image: islandora/cantaloupe:main
53
+ image: islandora/cantaloupe:7.0.22
54
54
  restart: unless-stopped
55
55
  volumes:
56
56
  - ${MEDIA_ROOT:-./media}:/var/lib/cantaloupe/images:ro
@@ -65,6 +65,10 @@ services:
65
65
  depends_on:
66
66
  cantaloupe-cache-init: { condition: service_completed_successfully }
67
67
  environment:
68
+ # Image-Default wäre 3G/5G fest reserviert; gemessen reichen unter paralleler
69
+ # Last ~0,6 GB. Große Scans: CANTALOUPE_HEAP_MAX in .env erhöhen.
70
+ CANTALOUPE_HEAP_MIN: ${CANTALOUPE_HEAP_MIN:-256m}
71
+ CANTALOUPE_HEAP_MAX: ${CANTALOUPE_HEAP_MAX:-1g}
68
72
  CANTALOUPE_SOURCE_STATIC: FilesystemSource
69
73
  CANTALOUPE_FILESYSTEMSOURCE_LOOKUP_STRATEGY: BasicLookupStrategy
70
74
  CANTALOUPE_FILESYSTEMSOURCE_BASICLOOKUPSTRATEGY_PATH_PREFIX: /var/lib/cantaloupe/images/
@@ -80,6 +84,10 @@ services:
80
84
  # nach Sichtbarkeit (X-Media-Visibility aus /v1/media/_authorize).
81
85
  CANTALOUPE_CACHE_CLIENT_PUBLIC: "false"
82
86
  CANTALOUPE_CACHE_CLIENT_PRIVATE: "true"
87
+ # Das Image loggt ab Werk auf debug (mehrere Zeilen pro Bild und Healthcheck);
88
+ # Zugriffe protokolliert nginx bereits. Zur Fehlersuche CANTALOUPE_LOG_LEVEL=debug.
89
+ CANTALOUPE_LOG_APPLICATION_LEVEL: ${CANTALOUPE_LOG_LEVEL:-info}
90
+ CANTALOUPE_LOG_ACCESS_CONSOLEAPPENDER_ENABLED: "false"
83
91
  healthcheck:
84
92
  # Prüft neben der Erreichbarkeit, dass der Cantaloupe-Prozess in seinen Cache
85
93
  # schreiben kann — sonst liefert er Bilder mit 0 Bytes bei HTTP 200.
File without changes