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.
332 lines
10 KiB
Bash
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"
|
|
}
|