test: cover the legacy -v migration with go and bats tests

Adds plugins/storage/migrate_test.go exercising migrateApp and MigrateLegacyMounts: single deploy phase, cross-phase grouping into one attachment, :ro and free-form volume options preserved on the attachment, idempotency on a second pass, the per-app flag-file fast path that skips already-migrated apps, and the name-collision refusal that aborts before draining. tests/unit/storage.bats gains an end-to-end case that stages a -v line via docker-options:add, runs storage:migrate, and asserts the synthesized colon form shows up in storage:list, the legacy-<hash> entry shows up in storage:list-entries, and the original -v line is gone from docker-options:report on both phases. To make that test (and operators with restored backups) practical, storage gains a storage:migrate <app>|--all subcommand backed by a new MigrateApp helper that skips the per-app flag file so a re-run actually re-scans.
This commit is contained in:
Jose Diaz-Gonzalez
2026-04-30 02:37:01 -04:00
parent e9a53ac82d
commit f0d088bc1d
8 changed files with 446 additions and 1 deletions

View File

@@ -322,6 +322,74 @@ teardown() {
assert_success
}
@test "(storage) storage:migrate converts legacy docker-options -v lines into attachments" {
# Stage a legacy `-v` line directly via docker-options:add. This
# bypasses the new storage:mount path so the line lives in
# docker-options without a corresponding attachment, simulating an
# app upgraded from a pre-PR Dokku version.
run /bin/bash -c "dokku docker-options:add $TEST_APP deploy,run \"-v /tmp/legacy-mount:/legacy\""
echo "output: $output"
echo "status: $status"
assert_success
# Before migration, storage:list shows nothing (attachment-only) and
# docker-options has the -v line.
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
assert_success
assert_output "0"
run /bin/bash -c "dokku docker-options:report $TEST_APP --docker-options-deploy"
assert_success
assert_output_contains "-v /tmp/legacy-mount:/legacy"
# Run the migration for this app.
run /bin/bash -c "dokku storage:migrate $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
# storage:list now surfaces the synthesized colon form.
run /bin/bash -c "dokku --quiet storage:list $TEST_APP"
assert_success
assert_output "/tmp/legacy-mount:/legacy"
# The synthesized entry shows up under the legacy- prefix.
run /bin/bash -c "dokku storage:list-entries --format json | jq -r '.[].name' | grep '^legacy-' | head -1"
echo "output: $output"
echo "status: $status"
assert_success
# docker-options no longer holds the -v line on either phase.
run /bin/bash -c "dokku docker-options:report $TEST_APP --docker-options-deploy"
assert_success
assert_output_not_contains "-v /tmp/legacy-mount:/legacy"
run /bin/bash -c "dokku docker-options:report $TEST_APP --docker-options-run"
assert_success
assert_output_not_contains "-v /tmp/legacy-mount:/legacy"
# Idempotency: re-running storage:migrate is a no-op (still one
# attachment, no errors).
run /bin/bash -c "dokku storage:migrate $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
assert_success
assert_output "1"
# Cleanup: unmount + destroy the synthesized legacy entry. We need
# the entry name from list-entries since legacy-<hash> is content-derived.
legacy_name=$(dokku storage:list-entries --format json | jq -r '.[] | select(.name | startswith("legacy-")) | .name' | head -1)
if [[ -n "$legacy_name" ]]; then
run /bin/bash -c "dokku storage:unmount $TEST_APP $legacy_name --container-dir /legacy"
assert_success
run /bin/bash -c "dokku storage:destroy $legacy_name"
assert_success
fi
}
@test "(storage) storage:ensure-directory emits deprecation warning" {
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP 2>&1"
echo "output: $output"