mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2026-11-01 10:22:08 +00:00
Manyfold, BookStack and NetBox declare the services they need. Lychee and Manyfold install with their own SQLite database. Folding@home, Healthchecks, NetBird, Speedtest Tracker, Twingate Connector, HA Bridge, ChatGPT Next Web, DDNS Updater and Minisatip explain each value, propose one or leave it to the advanced installation. Pinchflat gets 1024 MB.
82 lines
4.3 KiB
Python
82 lines
4.3 KiB
Python
"""A path that holds content of the user is offered as a container volume or
|
|
as a host directory. Either way it belongs to the user the application writes
|
|
with: a volume left to root is one the application cannot write to."""
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
import unittest
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(ROOT / "src"))
|
|
|
|
from proxmenux_oci.catalog import Catalog
|
|
|
|
|
|
def owners(template):
|
|
profile = template["proxmox"]["installer_profile"]
|
|
return {item["container_path"]: item["owner_strategy"] for item in profile["volume_preparations"]}
|
|
|
|
|
|
class ContentVolumeOwnerTests(unittest.TestCase):
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
cls.catalog = Catalog(ROOT)
|
|
|
|
def test_the_content_of_the_user_belongs_to_the_application(self):
|
|
found = owners(self.catalog.compose("duplicati"))
|
|
self.assertEqual(found["/backups"], "mapped-application-user")
|
|
self.assertEqual(found["/source"], "mapped-application-user")
|
|
|
|
def test_the_state_of_the_application_stays_as_the_recipe_says(self):
|
|
self.assertEqual(owners(self.catalog.compose("duplicati"))["/config"], "mapped-root")
|
|
|
|
def test_it_follows_the_choice_the_installation_offers(self):
|
|
contract = {"volumes": [
|
|
{"container_path": "/downloads", "installation_choice": ["managed-volume", "host-bind", "skip"]},
|
|
{"container_path": "/config", "installation_choice": ["managed-volume", "host-bind"],
|
|
"managed_volume": {"default_size_gb": 4}}]}
|
|
profile = {"volume_preparations": [
|
|
{"container_path": "/downloads", "owner_strategy": "mapped-root"},
|
|
{"container_path": "/config", "owner_strategy": "mapped-root"}]}
|
|
self.catalog._apply_volume_policy("an-application", contract, profile)
|
|
self.assertEqual({item["container_path"]: item["owner_strategy"] for item in profile["volume_preparations"]},
|
|
{"/downloads": "mapped-application-user", "/config": "mapped-root"})
|
|
self.assertEqual(contract["volumes"][1]["installation_choice"], ["managed-volume"])
|
|
|
|
def test_the_content_of_the_user_is_always_mounted(self):
|
|
contract = {"volumes": [
|
|
{"container_path": "/downloads", "installation_choice": ["managed-volume", "host-bind", "skip"],
|
|
"default": "skip"},
|
|
{"container_path": "/var/run/docker.sock", "installation_choice": ["host-bind", "skip"], "default": "skip"}]}
|
|
self.catalog._apply_volume_policy("an-application", contract, {})
|
|
self.assertEqual(contract["volumes"][0]["installation_choice"], ["managed-volume", "host-bind"])
|
|
self.assertEqual(contract["volumes"][0]["default"], "managed-volume")
|
|
# What is not content of the user, as a socket of the host, can still be left out.
|
|
self.assertEqual(contract["volumes"][1]["installation_choice"], ["host-bind", "skip"])
|
|
for app, path in (("sonarr", "/downloads"), ("manyfold", "/libraries"), ("qbittorrent", "/downloads")):
|
|
volume = next(item for item in self.catalog.compose(app)["container_contract"]["volumes"]
|
|
if item["container_path"] == path)
|
|
self.assertNotIn("skip", volume["installation_choice"], app)
|
|
self.assertEqual(volume["default"], "managed-volume", app)
|
|
|
|
def test_a_container_volume_is_never_read_only(self):
|
|
source = (ROOT / "src" / "proxmenux_oci" / "installer.py").read_text()
|
|
self.assertIn('"read_only": item["read_only"] and volume_mode != "managed-volume"', source)
|
|
|
|
def test_the_time_files_of_the_host_are_not_mounted(self):
|
|
for app in ("openhab", "lyrionmusicserver"):
|
|
template = self.catalog.compose(app)
|
|
paths = [volume["container_path"] for volume in template["container_contract"]["volumes"]]
|
|
self.assertNotIn("/etc/localtime", paths, app)
|
|
self.assertNotIn("/etc/timezone", paths, app)
|
|
self.assertNotIn("/etc/localtime", owners(template), app)
|
|
|
|
def test_a_recipe_without_preparations_is_left_alone(self):
|
|
contract = {"volumes": [{"container_path": "/downloads", "installation_choice": ["managed-volume", "host-bind"]}]}
|
|
self.catalog._apply_volume_policy("an-application", contract, None)
|
|
self.catalog._apply_volume_policy("an-application", contract, {})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|