Files
ProxMenux/oci/tests/test_stack_resources.py
T
MacRimi 9b5cefb81a feat(oci): GPU selection per host and per image, one notification per update, and App tab for stack containers
- Immich asks what runs its video and its recognition in one menu, in both
  modes, and gives the GPU to the server and to Machine learning; AMD uses ROCm
- Frigate, Ollama, llama.cpp, Faster Whisper and Piper take the image built
  for the chosen GPU
- The acceleration menu offers only what the host can run
- An update or a recreation sends one notification with its result instead of
  the stop, backup and start of each container
- A private bridge with nothing connected is not reported as down
- Secondary containers of a stack appear in the App tab with their version and
  logo; Secure Gateway shows the same update state in both views
- A mistyped value in the wizard asks the same question again
2026-10-02 21:45:38 +02:00

61 lines
3.1 KiB
Python

"""An advanced installation of a multi-container application asks the CPU and
the memory of its application container; a default one keeps the recipe."""
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT / "src"))
sys.path.insert(0, str(Path(__file__).resolve().parent))
from proxmenux_oci.catalog import Catalog
from proxmenux_oci.cli import _deployment_summary_text
from proxmenux_oci.installer import ADVANCED_MODE, DEFAULT_MODE, InstallError, build_deployment
from test_advanced_flow_order import RecordingUI, addresses, storages
SPECIAL = {"nextcloud-stack": (2, 2048), "paperless-ngx": (2, 2048), "tandoor": (2, 2048), "immich": (4, 4096)}
REMOTE = {"nextcloud-stack": "nextcloud", "paperless-ngx": "paperless", "tandoor": "tandoor", "immich": "immich"}
@patch("proxmenux_oci.i18n.language", return_value="en")
@patch("proxmenux_oci.installer.host.storages", side_effect=storages)
@patch("proxmenux_oci.installer.host.bridges", return_value=[{"iface": "vmbr0", "cidr": "192.0.2.10/24"}])
@patch("proxmenux_oci.installer.host.timezone", return_value="Europe/Madrid")
@patch("proxmenux_oci.installer.access.ask_addresses", side_effect=addresses)
class StackResourceTests(unittest.TestCase):
catalog = Catalog(ROOT)
def test_the_advanced_installation_asks_cpu_and_memory_before_the_storage(self, *_):
for app in SPECIAL:
ui = RecordingUI({"CPU cores": "6", "Memory in MB": "4096"})
template = self.catalog.compose(app)
plan = build_deployment(template, ui, ADVANCED_MODE)
self.assertEqual((plan["resources"]["cores"], plan["resources"]["memory_mb"]), (6, 4096), app)
self.assertLess(ui.asked.index("Memory in MB"), ui.asked.index("Storage for rootfs"), app)
self.assertIn("6 CPU, 4096 MB RAM", _deployment_summary_text(template, plan), app)
def test_the_default_installation_keeps_the_resources_of_the_recipe(self, *_):
for app, expected in SPECIAL.items():
ui = RecordingUI()
plan = build_deployment(self.catalog.compose(app), ui, DEFAULT_MODE)
self.assertEqual((plan["resources"]["cores"], plan["resources"]["memory_mb"]), expected, app)
self.assertNotIn("CPU cores", ui.asked, app)
def test_resources_that_cannot_run_the_application_are_refused(self, *_):
ui = RecordingUI({"CPU cores": "0"})
with self.assertRaises(InstallError):
build_deployment(self.catalog.compose("tandoor"), ui, ADVANCED_MODE)
def test_the_installers_create_the_application_with_the_chosen_resources(self, *_):
for app, (cores, memory) in SPECIAL.items():
script = (ROOT / f"remote/install_{REMOTE[app]}_stack.sh").read_text()
self.assertIn(f"jqr '.resources.cores // {cores}'", script, app)
self.assertIn(f"jqr '.resources.memory_mb // {memory}'", script, app)
self.assertIn('--cores "$APPLICATION_CORES" --memory "$APPLICATION_MEMORY"', script, app)
if __name__ == "__main__":
unittest.main()