Atreides Services 0.0.3: datamap verplaatsbaar naar USB (umbrelOS 2.0)

storage: dataRoot: data in het manifest, zodat de gebruiker de datamap in de
app-instellingen naar een USB-schijf met ext4 kan verplaatsen. Geen
netwerkshare: umbrelOS weigert dat voor app-opslag, en de SQLite-bestanden in
WAL-stand horen er ook niet op.

test_appstore_vorm.py kent de nieuwe veldvolgorde (storage, folderAccess en
environment direct na id) en toetst dat storage precies dataRoot: data is en
dat de mounts onder data/ door umbreld om te leiden zijn.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
HarmenandClaude Opus 5.5 committed 2026-10-09 14:31:18 +02:00
1 parent 103f8c456a
commit 26e36de417
3 files changed
+81 -4

No files matched your search

+63 -1
View File
@@ -44,8 +44,12 @@ STORE = os.path.join(REPO, "umbrel-app-store.yml")
# De volgorde uit de packaging-documentatie. Wat de spec niet noemt (icon,
# backupIgnore, submitter, submission) mag erachter, niet ertussen.
#
# `storage`, `folderAccess` en `environment` zijn er sinds umbrelOS 2.0 bij en
# staan direct na `id` (skill umbrel-package-app, opgehaald 09-10-2026).
VOORGESCHREVEN = [
"manifestVersion", "id", "category", "name", "version", "tagline",
"manifestVersion", "id", "storage", "folderAccess", "environment",
"category", "name", "version", "tagline",
"description", "releaseNotes", "developer", "website", "dependencies",
"repo", "support", "port", "gallery", "path",
]
@@ -327,6 +331,63 @@ def test_data_onder_data(u, app):
not ontbreekt, "ontbreekt: %r" % ontbreekt)
# De mount-opties die umbreld toestaat op een bron onder ${APP_DATA_DIR}/data
# zodra de datamap verplaatsbaar is. Elke andere optie laat de compose falen met
# [apps-data-root-invalid-compose]. Uit app.ts van umbreld, 09-10-2026.
DATAROOT_OPTIES = {
"ro", "rw", "private", "rprivate", "shared", "rshared", "slave", "rslave",
"z", "Z", "consistent", "cached", "delegated",
}
def test_verplaatsbare_opslag(u, app):
"""Een app met `storage:` heeft precies `dataRoot: data`, en mounts die umbreld kan omleiden.
Dit is het enige manifestveld dat umbreld wél streng valideert: elke andere
waarde dan `data` maakt het manifest ongeldig, en dan verschijnt de app niet.
Met het veld erin herschrijft umbreld elke bron onder ${APP_DATA_DIR}/data naar
de plek die de gebruiker kiest, en weigert dan een pad dat uit data/ ontsnapt
of een mount-optie die niet in DATAROOT_OPTIES staat.
Een app zonder `storage:` valt hier buiten; het veld is optioneel. Maar het
kan er niet meer uit als het er eenmaal in staat: een installatie die al
verplaatst is, start dan niet meer.
"""
tekst = lees(os.path.join(REPO, app, "umbrel-app.yml"))
regels = tekst.splitlines()
if not any(r.startswith("storage:") for r in regels):
return
i = next(i for i, r in enumerate(regels) if r.startswith("storage:"))
blok = []
for r in regels[i + 1:]:
if r and not r[0].isspace():
break
if r.strip() and not r.strip().startswith("#"):
blok.append(r.strip())
u.check("%s: storage heeft precies dataRoot: data" % app,
blok == ["dataRoot: data"], "gevonden: %r" % blok)
pad = os.path.join(REPO, app, "docker-compose.yml")
if not os.path.isfile(pad):
return
fout = []
for regel in lees(pad).splitlines():
kaal = regel.strip()
if not kaal.startswith("- ${APP_DATA_DIR}/data"):
continue
delen = kaal[2:].strip().strip('"').split(":")
bron = delen[0][len("${APP_DATA_DIR}/"):]
if ".." in bron.split("/"):
fout.append(kaal)
if len(delen) > 2:
opties = delen[2].split(",")
if any(o not in DATAROOT_OPTIES for o in opties):
fout.append(kaal)
u.check("%s: elke mount onder data/ kan umbreld omleiden" % app,
not fout, "geweigerd: %r" % fout)
def test_containernamen_zijn_volledig(u, app):
"""Verwijzingen tussen containers gebruiken de volledige naam.
@@ -534,6 +595,7 @@ def main():
test_compose_bestaat_en_hangt_samen(u, app)
test_image_tag_is_de_gebouwde(u, app)
test_data_onder_data(u, app)
test_verplaatsbare_opslag(u, app)
test_containernamen_zijn_volledig(u, app)
test_geen_werkbestanden_in_de_app_map(u, app)
test_templates_hebben_geen_losse_dollars(u, app)