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:
1 parent
103f8c456a
commit
26e36de417
3 files changed
+81
-4
No files matched your search
@@ -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,
|
# De volgorde uit de packaging-documentatie. Wat de spec niet noemt (icon,
|
||||||
# backupIgnore, submitter, submission) mag erachter, niet ertussen.
|
# 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 = [
|
VOORGESCHREVEN = [
|
||||||
"manifestVersion", "id", "category", "name", "version", "tagline",
|
"manifestVersion", "id", "storage", "folderAccess", "environment",
|
||||||
|
"category", "name", "version", "tagline",
|
||||||
"description", "releaseNotes", "developer", "website", "dependencies",
|
"description", "releaseNotes", "developer", "website", "dependencies",
|
||||||
"repo", "support", "port", "gallery", "path",
|
"repo", "support", "port", "gallery", "path",
|
||||||
]
|
]
|
||||||
@@ -327,6 +331,63 @@ def test_data_onder_data(u, app):
|
|||||||
not ontbreekt, "ontbreekt: %r" % ontbreekt)
|
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):
|
def test_containernamen_zijn_volledig(u, app):
|
||||||
"""Verwijzingen tussen containers gebruiken de volledige naam.
|
"""Verwijzingen tussen containers gebruiken de volledige naam.
|
||||||
|
|
||||||
@@ -534,6 +595,7 @@ def main():
|
|||||||
test_compose_bestaat_en_hangt_samen(u, app)
|
test_compose_bestaat_en_hangt_samen(u, app)
|
||||||
test_image_tag_is_de_gebouwde(u, app)
|
test_image_tag_is_de_gebouwde(u, app)
|
||||||
test_data_onder_data(u, app)
|
test_data_onder_data(u, app)
|
||||||
|
test_verplaatsbare_opslag(u, app)
|
||||||
test_containernamen_zijn_volledig(u, app)
|
test_containernamen_zijn_volledig(u, app)
|
||||||
test_geen_werkbestanden_in_de_app_map(u, app)
|
test_geen_werkbestanden_in_de_app_map(u, app)
|
||||||
test_templates_hebben_geen_losse_dollars(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
|
# 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
|
# koersreeks per moment is niet opnieuw op te halen, dus dit is de map die
|
||||||
# in de back-up van umbrelOS hoort.
|
# 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
|
- ${APP_DATA_DIR}/data/app:/data
|
||||||
@@ -6,9 +6,17 @@
|
|||||||
# Wat de spec niet noemt, staat onderaan dit bestand en niet ertussen.
|
# Wat de spec niet noemt, staat onderaan dit bestand en niet ertussen.
|
||||||
manifestVersion: 1
|
manifestVersion: 1
|
||||||
id: whatsnext-atreides-services
|
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
|
category: finance
|
||||||
name: Atreides Services
|
name: Atreides Services
|
||||||
version: "0.0.2"
|
version: "0.0.3"
|
||||||
tagline: Your own price feed, recorded around the clock
|
tagline: Your own price feed, recorded around the clock
|
||||||
description: >-
|
description: >-
|
||||||
A price service that runs on your Umbrel and keeps what it records. It fetches prices day
|
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
|
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.
|
login of its own. The API for other apps follows in a later version.
|
||||||
releaseNotes: >-
|
releaseNotes: >-
|
||||||
First version in this store: spot prices every minute from Bitvavo and mempool.space, and
|
On umbrelOS 2.0 the app's storage can now be moved to a USB drive (ext4) in the app
|
||||||
the administration app. The API for other apps is not there yet.
|
settings. Keep in mind that umbrelOS does not back up an app whose storage is on a USB
|
||||||
|
drive.
|
||||||
developer: "WhatsNext?"
|
developer: "WhatsNext?"
|
||||||
website: https://sc.kamenier-hamer.nl/sysop/UmbrelApps
|
website: https://sc.kamenier-hamer.nl/sysop/UmbrelApps
|
||||||
dependencies: []
|
dependencies: []
|
||||||
|
|||||||
Reference in new issue
Block a user