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)
@@ -57,4 +57,10 @@ services:
# De datamap: db.sqlite, de minuutbestanden per maand en secrets.json. Een
# koersreeks per moment is niet opnieuw op te halen, dus dit is de map die
# in de back-up van umbrelOS hoort.
#
# Sinds `storage: dataRoot: data` in het manifest (0.0.3) herschrijft
# umbrelOS 2.0 deze bron naar de plek die de gebruiker kiest, en zet hij
# er `create_host_path: false` bij. Daarom moet data/app in de repo staan
# (.gitkeep), en mag hier geen mount-optie bij die umbreld niet kent.
# Staat de map op een USB-schijf, dan gaat hij NIET mee in de back-up.
- ${APP_DATA_DIR}/data/app:/data
+12 -3
View File
@@ -6,9 +6,17 @@
# Wat de spec niet noemt, staat onderaan dit bestand en niet ertussen.
manifestVersion: 1
id: whatsnext-atreides-services
# umbrelOS 2.0: de gebruiker kan de hele datamap (${APP_DATA_DIR}/data) in de
# app-instellingen naar een USB-schijf verplaatsen. Alleen ext4 en geen
# netwerkshare; die laatste weigert umbrelOS voor app-opslag, en de SQLite-
# bestanden in WAL-stand horen er ook niet op. De waarde moet letterlijk `data`
# zijn, en het veld kan er niet meer uit: een installatie die al verplaatst is,
# start dan niet meer. Zie Umbrel-appstore-spec.md §7.
storage:
dataRoot: data
category: finance
name: Atreides Services
version: "0.0.2"
version: "0.0.3"
tagline: Your own price feed, recorded around the clock
description: >-
A price service that runs on your Umbrel and keeps what it records. It fetches prices day
@@ -26,8 +34,9 @@ description: >-
mempool.space, and brings the administration app with its System page and an optional
login of its own. The API for other apps follows in a later version.
releaseNotes: >-
First version in this store: spot prices every minute from Bitvavo and mempool.space, and
the administration app. The API for other apps is not there yet.
On umbrelOS 2.0 the app's storage can now be moved to a USB drive (ext4) in the app
settings. Keep in mind that umbrelOS does not back up an app whose storage is on a USB
drive.
developer: "WhatsNext?"
website: https://sc.kamenier-hamer.nl/sysop/UmbrelApps
dependencies: []