Files
dokku/tests/unit/storage.bats
Jose Diaz-Gonzalez 58042b9330 feat: delegate storage:exec to scheduler plugins, harden the flow
Moves the actual exec out of the storage plugin and into a new scheduler-storage-exec plugn trigger. scheduler-docker-local does docker run with TTY-aware -it/-i selection and --user derived from entry.Chown; scheduler-k3s creates a throwaway Pod via the kubernetes API, waits for it to reach Running with structured error reporting (ImagePullBackOff and friends are surfaced from the container status verbatim, no kubectl involvement), execs the user command via the existing SPDY plumbing in k8s.go, and deletes the Pod on the way out. (Entry).Validate now accepts either an absolute path or a docker named-volume token for docker-local entries so the migration synthesizer's named-volume legacy entries work cleanly. storage:exec gains --as-user for one-off uid overrides, propagates the underlying tool's exit code via os.Exit, and detects TTY/interactive mode from os.Stdin so non-interactive scripted use no longer trips over docker's input-device-is-not-a-tty error.
2026-04-29 23:29:30 -04:00

332 lines
10 KiB
Bash

#!/usr/bin/env bats
load test_helper
setup() {
global_setup
create_app
rm -rf "$DOKKU_LIB_ROOT/data/storage/rdmtestapp*"
}
teardown() {
destroy_app
global_teardown
}
@test "(storage) storage:help" {
run /bin/bash -c "dokku storage"
echo "output: $output"
echo "status: $status"
assert_output_contains "Manage mounted volumes"
help_output="$output"
run /bin/bash -c "dokku storage:help"
echo "output: $output"
echo "status: $status"
assert_output_contains "Manage mounted volumes"
assert_output "$help_output"
}
@test "(storage) storage:ensure-directory" {
run /bin/bash -c "test -d $DOKKU_LIB_ROOT/data/storage/$TEST_APP"
echo "output: $output"
echo "status: $status"
assert_failure
run /bin/bash -c "dokku storage:ensure-directory @"
echo "output: $output"
echo "status: $status"
assert_failure
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP/"
echo "output: $output"
echo "status: $status"
assert_failure
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP/$TEST_APP"
echo "output: $output"
echo "status: $status"
assert_failure
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 0
assert_output_contains "Setting directory ownership to 2000:2000" 0
assert_output_contains "Setting directory ownership to 32767:32767" 1
run /bin/bash -c "test -d $DOKKU_LIB_ROOT/data/storage/$TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:ensure-directory --chown false $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 0
assert_output_contains "Setting directory ownership to 2000:2000" 0
assert_output_contains "Setting directory ownership to 32767:32767" 0
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP --chown false"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 0
assert_output_contains "Setting directory ownership to 2000:2000" 0
assert_output_contains "Setting directory ownership to 32767:32767" 0
run /bin/bash -c "dokku storage:ensure-directory --chown heroku $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 1
assert_output_contains "Setting directory ownership to 2000:2000" 0
assert_output_contains "Setting directory ownership to 32767:32767" 0
run /bin/bash -c "dokku storage:ensure-directory --chown paketo $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 0
assert_output_contains "Setting directory ownership to 2000:2000" 1
assert_output_contains "Setting directory ownership to 32767:32767" 0
run /bin/bash -c "dokku storage:ensure-directory --chown herokuish $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "Setting directory ownership to 1000:1000" 0
assert_output_contains "Setting directory ownership to 2000:2000" 0
assert_output_contains "Setting directory ownership to 32767:32767" 1
}
@test "(storage) storage:mount, storage:list, storage:umount" {
run /bin/bash -c "dokku storage:mount $TEST_APP /tmp/mount:/mount"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku --quiet storage:list $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "/tmp/mount:/mount"
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "1"
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '.[].host_path'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "/tmp/mount"
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '.[].container_path'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "/mount"
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '.[].volume_options'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_not_exists
run /bin/bash -c "dokku storage:mount $TEST_APP /tmp/mount:/mount"
echo "output: $output"
echo "status: $status"
assert_output " ! Mount path already exists."
assert_failure
run /bin/bash -c "dokku storage:unmount $TEST_APP /tmp/mount:/mount"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku --quiet storage:list $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_not_exists
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "0"
run /bin/bash -c "dokku storage:unmount $TEST_APP /tmp/mount:/mount"
echo "output: $output"
echo "status: $status"
assert_output " ! Mount path does not exist."
assert_failure
run /bin/bash -c "dokku storage:mount $TEST_APP mount_volume:/mount"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku --quiet storage:list $TEST_APP"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "mount_volume:/mount"
}
@test "(storage) storage:create / storage:list-entries / storage:destroy" {
run /bin/bash -c "dokku storage:create rdmtest-entry"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:list-entries --format json | jq -r '.[].name' | grep '^rdmtest-entry$'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "rdmtest-entry"
run /bin/bash -c "dokku storage:info rdmtest-entry --format json | jq -r '.scheduler'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "docker-local"
run /bin/bash -c "dokku storage:destroy rdmtest-entry"
echo "output: $output"
echo "status: $status"
assert_success
}
@test "(storage) storage:create rejects invalid names" {
# underscore: rejected
run /bin/bash -c "dokku storage:create rdmtest_invalid"
echo "output: $output"
echo "status: $status"
assert_failure
# uppercase: rejected
run /bin/bash -c "dokku storage:create RdmTest"
echo "output: $output"
echo "status: $status"
assert_failure
# 46 chars: too long
long_name=$(printf 'a%.0s' {1..46})
run /bin/bash -c "dokku storage:create $long_name"
echo "output: $output"
echo "status: $status"
assert_failure
# legacy- prefix: reserved
run /bin/bash -c "dokku storage:create legacy-foo"
echo "output: $output"
echo "status: $status"
assert_failure
}
@test "(storage) storage:create + storage:mount with named entry attaches multiple entries to one app" {
run /bin/bash -c "dokku storage:create rdmtest-data"
assert_success
run /bin/bash -c "dokku storage:create rdmtest-cache"
assert_success
run /bin/bash -c "dokku storage:mount $TEST_APP rdmtest-data --container-dir /data"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:mount $TEST_APP rdmtest-cache --container-dir /cache"
echo "output: $output"
echo "status: $status"
assert_success
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "2"
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '.[].entry_name' | sort | xargs"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "rdmtest-cache rdmtest-data"
# cleanup
run /bin/bash -c "dokku storage:unmount $TEST_APP rdmtest-data"
assert_success
run /bin/bash -c "dokku storage:unmount $TEST_APP rdmtest-cache"
assert_success
run /bin/bash -c "dokku storage:list $TEST_APP --format json | jq -r '. | length'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output "0"
run /bin/bash -c "dokku storage:destroy rdmtest-data"
assert_success
run /bin/bash -c "dokku storage:destroy rdmtest-cache"
assert_success
}
@test "(storage) storage:destroy refuses to remove a still-mounted entry" {
run /bin/bash -c "dokku storage:create rdmtest-busy"
assert_success
run /bin/bash -c "dokku storage:mount $TEST_APP rdmtest-busy --container-dir /data"
assert_success
run /bin/bash -c "dokku storage:destroy rdmtest-busy"
echo "output: $output"
echo "status: $status"
assert_failure
assert_output_contains "still mounted"
run /bin/bash -c "dokku storage:unmount $TEST_APP rdmtest-busy"
assert_success
run /bin/bash -c "dokku storage:destroy rdmtest-busy"
assert_success
}
@test "(storage) storage:exec runs a non-interactive command and propagates exit code" {
run /bin/bash -c "dokku storage:create rdmtest-exec"
assert_success
# docker pull image up-front so the test isn't gated on registry latency.
run /bin/bash -c "docker pull alpine:3 >/dev/null"
assert_success
run /bin/bash -c "dokku storage:exec rdmtest-exec -- /bin/sh -c 'touch /data/marker && ls /data/marker'"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "/data/marker"
run /bin/bash -c "dokku storage:exec rdmtest-exec -- /bin/sh -c 'exit 42'"
echo "output: $output"
echo "status: $status"
assert_equal "$status" 42
run /bin/bash -c "dokku storage:destroy rdmtest-exec"
assert_success
}
@test "(storage) storage:ensure-directory emits deprecation warning" {
run /bin/bash -c "dokku storage:ensure-directory $TEST_APP 2>&1"
echo "output: $output"
echo "status: $status"
assert_success
assert_output_contains "deprecated"
}