The podman 5.x v1 quadlet generator rejected the whole jellyfin unit on the unsupported Device= key (generator log: unsupported key 'Device' in group 'Container'), so no jellyfin.service was generated and the cutover restart failed with 'Unit not found' after the data root had already migrated cleanly. gluetun proves AddDevice= is the house key. New seam test denies Device= across all six dankserver units and pins the AddDevice=/dev/dri replacement.
59 lines
3.2 KiB
Bash
Executable File
59 lines
3.2 KiB
Bash
Executable File
#!/usr/bin/env bats
|
|
# Seam: the six cutover-era dankserver quadlet units (romm trio, jellyfin,
|
|
# calibre-web, copyparty) must keep their boot-persistence and v1-generator
|
|
# contracts. The podman 5.x v1 Quadlet generator silently drops or hard-fails
|
|
# on several keys; these tests pin the contract that keeps the units loadable
|
|
# and secret-free in the repo.
|
|
|
|
load helpers
|
|
|
|
@test "all six cutover units exist under dankserver/<svc>/quadlet/" {
|
|
for unit in romm/quadlet/romm romm/quadlet/romm-mariadb romm/quadlet/romm-redis jellyfin/quadlet/jellyfin calibre-web/quadlet/calibre-web copyparty/quadlet/copyparty; do
|
|
[ -f "$REPO_ROOT/dankserver/$unit.container" ] || return 1
|
|
done
|
|
}
|
|
|
|
@test "every cutover unit is boot-persistent (WantedBy=default.target)" {
|
|
for unit in romm/quadlet/romm romm/quadlet/romm-mariadb romm/quadlet/romm-redis jellyfin/quadlet/jellyfin calibre-web/quadlet/calibre-web copyparty/quadlet/copyparty; do
|
|
grep -q '^WantedBy=default.target$' "$REPO_ROOT/dankserver/$unit.container" || return 1
|
|
done
|
|
}
|
|
|
|
@test "copyparty uses Exec= not Command= (v1 generator hard-fails on Command=)" {
|
|
unit="$REPO_ROOT/dankserver/copyparty/quadlet/copyparty.container"
|
|
grep -q '^Command=' "$unit" && return 1
|
|
grep -q '^Exec=-a ${COPAY_ACCOUNT}:${COPAY_PASSWORD}' "$unit" || return 1
|
|
}
|
|
|
|
@test "copyparty and romm consume host-local env files, never in-repo secrets" {
|
|
grep -q '^EnvironmentFile=/home/dank/Containers/copyparty/env$' \
|
|
"$REPO_ROOT/dankserver/copyparty/quadlet/copyparty.container" || return 1
|
|
for unit in romm/quadlet/romm romm/quadlet/romm-mariadb; do
|
|
grep -q '^EnvironmentFile=/home/dank/Containers/romm/env$' \
|
|
"$REPO_ROOT/dankserver/$unit.container" || return 1
|
|
done
|
|
# No literal credential may ever appear in a tracked unit file: the only
|
|
# Exec= arguments must be variable expansions, never a literal account:secret.
|
|
! grep -qE '\-a [A-Za-z0-9]+:[A-Za-z0-9]' "$REPO_ROOT/dankserver/copyparty/quadlet/copyparty.container" || return 1
|
|
}
|
|
|
|
@test "romm db services keep their service-discovery aliases on the appnet" {
|
|
grep -q '^Network=dankserver_appnet:alias=mariadb$' \
|
|
"$REPO_ROOT/dankserver/romm/quadlet/romm-mariadb.container" || return 1
|
|
grep -q '^Network=dankserver_appnet:alias=redis$' \
|
|
"$REPO_ROOT/dankserver/romm/quadlet/romm-redis.container" || return 1
|
|
}
|
|
|
|
@test "no unit uses the unsupported Device= key (v1 generator needs AddDevice=)" {
|
|
# A rejected file kills its own unit silently: the deploy would then die
|
|
# with "Unit jellyfin.service not found" only on the target. Device= was
|
|
# the first offender (jellyfin GPU passthrough); Command= is guarded
|
|
# above. Keep this list current with every generator finding.
|
|
for unit in dankserver/romm/quadlet/romm dankserver/romm/quadlet/romm-mariadb \
|
|
dankserver/romm/quadlet/romm-redis dankserver/jellyfin/quadlet/jellyfin \
|
|
dankserver/calibre-web/quadlet/calibre-web dankserver/copyparty/quadlet/copyparty; do
|
|
! grep -q '^Device=' "$REPO_ROOT/$unit.container" || return 1
|
|
done
|
|
grep -q '^AddDevice=/dev/dri$' "$REPO_ROOT/dankserver/jellyfin/quadlet/jellyfin.container" || return 1
|
|
}
|