RPC-based (host-agnostic) lifecycle coverage for the manifest-driven immich stack (immich + immich-postgres + immich-redis): presence + valid state of all 3 members, a guard that no legacy underscore containers exist (catches botched migration / legacy-installer fallback), destructive stop/start/restart of the server with postgres+redis staying up, and cascade uninstall/reinstall (preserve_data). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
123 lines
5.4 KiB
Bash
123 lines
5.4 KiB
Bash
#!/usr/bin/env bats
|
|
# tests/lifecycle/bats/immich.bats
|
|
#
|
|
# Lifecycle tests for the immich stack (manifest-driven: immich + immich-postgres
|
|
# + immich-redis, installed via the orchestrator — NOT the legacy install_immich_stack).
|
|
#
|
|
# Tiers:
|
|
# - Read-only (always): presence + valid state of all 3 members
|
|
# - Destructive (ARCHY_ALLOW_DESTRUCTIVE=1): stop → start → restart the server
|
|
# - Cascade (ARCHY_ALLOW_CASCADE_DESTRUCTIVE=1): uninstall → reinstall the stack
|
|
# (preserve_data so the photo library + DB survive)
|
|
#
|
|
# All checks are RPC-based so the suite is correct whether run on the host or
|
|
# against a remote ARCHY_HOST.
|
|
|
|
load '../lib/rpc.bash'
|
|
|
|
IMMICH_IMAGE="146.59.87.168:3000/lfg2025/immich-server:release"
|
|
|
|
setup_file() {
|
|
: "${ARCHY_PASSWORD:?Set ARCHY_PASSWORD env var to the UI password}"
|
|
export ARCHY_FORCE_LOGIN=1
|
|
rpc_login
|
|
unset ARCHY_FORCE_LOGIN
|
|
}
|
|
|
|
teardown_file() {
|
|
rpc_logout_local
|
|
}
|
|
|
|
container_state() {
|
|
rpc_result container-list | jq -r --arg n "$1" '.[] | select(.name == $n) | .state'
|
|
}
|
|
|
|
# ────────────────────────────────────────────────────────────────────
|
|
# Read-only tier
|
|
# ────────────────────────────────────────────────────────────────────
|
|
|
|
@test "container-list includes the immich stack members" {
|
|
run rpc_result container-list
|
|
[ "$status" -eq 0 ]
|
|
echo "$output" | jq -e '.[] | select(.name == "immich")' >/dev/null
|
|
echo "$output" | jq -e '.[] | select(.name == "immich-postgres")' >/dev/null
|
|
echo "$output" | jq -e '.[] | select(.name == "immich-redis")' >/dev/null
|
|
}
|
|
|
|
@test "immich stack members report valid states" {
|
|
for c in immich immich-postgres immich-redis; do
|
|
local state
|
|
state=$(container_state "$c")
|
|
[[ "$state" =~ ^(running|stopped|exited|created|paused)$ ]] || {
|
|
echo "unexpected state for $c: $state"; return 1
|
|
}
|
|
done
|
|
}
|
|
|
|
@test "no legacy underscore immich containers (immich_postgres/_redis/_server)" {
|
|
# The legacy install_immich_stack named members with underscores. The
|
|
# manifest-driven stack uses hyphenated app_id names. Underscore containers
|
|
# mean a botched migration (or a fallback to the legacy installer).
|
|
run rpc_result container-list
|
|
[ "$status" -eq 0 ]
|
|
echo "$output" | jq -e '[.[] | select(.name | test("^immich_"))] | length == 0' >/dev/null
|
|
}
|
|
|
|
# ────────────────────────────────────────────────────────────────────
|
|
# Destructive tier (stop → start → restart the server)
|
|
# ────────────────────────────────────────────────────────────────────
|
|
|
|
@test "package.stop transitions immich to stopped" {
|
|
[[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set"
|
|
run rpc_result package.stop '{"id":"immich"}'
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich stopped 60
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "package.start brings immich back to running" {
|
|
[[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set"
|
|
run rpc_result package.start '{"id":"immich"}'
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich running 120
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "package.restart leaves immich in running state" {
|
|
[[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set"
|
|
run rpc_result package.restart '{"id":"immich"}'
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich running 120
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "postgres + redis stay running across an immich server restart" {
|
|
[[ "${ARCHY_ALLOW_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_DESTRUCTIVE not set"
|
|
[ "$(container_state immich-postgres)" == "running" ]
|
|
[ "$(container_state immich-redis)" == "running" ]
|
|
}
|
|
|
|
# ────────────────────────────────────────────────────────────────────
|
|
# Cascade tier (uninstall + reinstall the stack)
|
|
# ────────────────────────────────────────────────────────────────────
|
|
|
|
@test "package.uninstall removes the immich stack (data preserved)" {
|
|
[[ "${ARCHY_ALLOW_CASCADE_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_CASCADE_DESTRUCTIVE not set"
|
|
run rpc_result package.uninstall '{"id":"immich","preserve_data":true}'
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich absent 120
|
|
[ "$status" -eq 0 ]
|
|
}
|
|
|
|
@test "package.install immich brings the whole stack back to running" {
|
|
[[ "${ARCHY_ALLOW_CASCADE_DESTRUCTIVE:-0}" == "1" ]] || skip "ARCHY_ALLOW_CASCADE_DESTRUCTIVE not set"
|
|
run rpc_result package.install "{\"id\":\"immich\",\"dockerImage\":\"${IMMICH_IMAGE}\"}"
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich running 180
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich-postgres running 120
|
|
[ "$status" -eq 0 ]
|
|
run wait_for_container_status immich-redis running 120
|
|
[ "$status" -eq 0 ]
|
|
}
|