diff --git a/debian/postinst b/debian/postinst index c5f578c4640..0663ca6510b 100755 --- a/debian/postinst +++ b/debian/postinst @@ -126,8 +126,7 @@ dpkg-handling() { case "$1" in abort-upgrade | abort-remove | abort-deconfigure) ;; - \ - configure) + configure) mandb [ ! -x /usr/bin/docker.io ] || ln -sf /usr/bin/docker.io /usr/local/bin/docker if [[ -f /sbin/modprobe ]]; then diff --git a/debian/preinst b/debian/preinst index 7493eca0543..e4dfdef5ed6 100755 --- a/debian/preinst +++ b/debian/preinst @@ -22,11 +22,9 @@ case "$1" in upgrade) ;; - \ - abort-upgrade) ;; + abort-upgrade) ;; - \ - *) + *) echo "preinst called with unknown argument \`$1'" >&2 exit 1 ;; diff --git a/docs/advanced-usage/persistent-storage.md b/docs/advanced-usage/persistent-storage.md index 5ef3457e388..4ebf2b1852f 100644 --- a/docs/advanced-usage/persistent-storage.md +++ b/docs/advanced-usage/persistent-storage.md @@ -6,7 +6,7 @@ The preferred method to mount external containers to a Dokku managed container, ``` storage:ensure-directory [--chown option] # Creates a persistent storage directory in the recommended storage path -storage:list # List bind mounts for app's container(s) (host:container) +storage:list [--format text|json] # List bind mounts for app's container(s) (host:container) storage:mount # Create a new bind mount storage:report [] [] # Displays a checks report for one or more apps storage:unmount # Remove an existing bind mount @@ -21,6 +21,36 @@ The storage plugin supports the following mount points: ## Usage +### Listing persistent storage + +Persistent storage bind mounts are specified on a per-app basis, and can be listed with the `storage:list` command: + +```shell +dokku storage:list node-js-app +``` + +``` +-----> node-js-app volume bind-mounts: + /var/lib/dokku/data/storage/node-js-app:/app/storage +``` + +The output format can also be set to `json` for programmatic access: + + +```shell +dokku storage:list node-js-app --format json +``` + +``` +[ + { + "host_path": "/var/lib/dokku/data/storage/node-js-app", + "container_path": "/app/storage", + "volume_options": "" + } +] +``` + ### Creating storage directories > New as of 0.25.5 @@ -28,11 +58,11 @@ The storage plugin supports the following mount points: A storage directory can be created with the `storage:ensure-directory` command. This command will create a subdirectory in the recommended `/var/lib/dokku/data/storage` path - created during Dokku installation - and prepare it for use with an app. ```shell -dokku storage:ensure-directory lollipop +dokku storage:ensure-directory node-js-app ``` ``` ------> Ensuring /var/lib/dokku/data/storage/lollipop exists +-----> Ensuring /var/lib/dokku/data/storage/node-js-app exists Setting directory ownership to 32767:32767 Directory ready for mounting ``` diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md index 57dc999b3ec..18909330df1 100644 --- a/docs/development/plugin-triggers.md +++ b/docs/development/plugin-triggers.md @@ -2424,7 +2424,7 @@ DOKKU_SCHEDULER="$1"; APP="$2"; REMOVE_CONTAINERS="$3"; - Description: Returns a list of storage mounts - Invoked by: `dokku storage:list` and `dokku deploy` -- Arguments: `$APP` +- Arguments: `$APP $PHASE $FORMAT` - Example: ```shell diff --git a/plugins/storage/functions b/plugins/storage/functions index f6d87e8bb32..611e92397cd 100755 --- a/plugins/storage/functions +++ b/plugins/storage/functions @@ -26,6 +26,6 @@ get_bind_mounts() { declare desc="strips docker options and prints mounts" local -r phase_file_path=$1 if [[ -r "$phase_file_path" ]]; then - sed -e '/^-v/!d' -e 's/^-v/ /' <"$phase_file_path" + sed -e '/^-v/!d' -e 's/^-v //' <"$phase_file_path" fi } diff --git a/plugins/storage/help-functions b/plugins/storage/help-functions index dacb089a1c9..14ce66f5799 100755 --- a/plugins/storage/help-functions +++ b/plugins/storage/help-functions @@ -28,7 +28,7 @@ fn-help-content() { declare desc="return help content" cat <, Creates a persistent storage directory in the recommended storage path - storage:list , List bind mounts for app's container(s) (host:container) + storage:list [--format text|json], List bind mounts for app's container(s) (host:container) storage:mount , Create a new bind mount storage:report [] [], Displays a checks report for one or more apps storage:unmount , Remove an existing bind mount diff --git a/plugins/storage/internal-functions b/plugins/storage/internal-functions index 7dedc62b58a..58896997b0c 100755 --- a/plugins/storage/internal-functions +++ b/plugins/storage/internal-functions @@ -135,10 +135,24 @@ cmd-storage-list() { declare desc="List all bound mounts" declare cmd="storage:list" [[ "$1" == "$cmd" ]] && shift 1 - declare APP="$1" - local phase="deploy" + declare APP="$1" FORMAT_FLAG="$2" FORMAT_FLAG_VALUE="$3" + local phase="deploy" format="text" + + if [[ "$FORMAT_FLAG" == "--format" ]]; then + if [[ "$FORMAT_FLAG_VALUE" == "json" ]] || [[ "$FORMAT_FLAG_VALUE" == "text" ]]; then + format="$FORMAT_FLAG_VALUE" + else + dokku_log_fail "Invalid --format value specified" + fi + elif [[ -n "$FORMAT_FLAG" ]]; then + dokku_log_fail "Invalid argument specified" + fi verify_app_name "$APP" - dokku_log_quiet "$APP volume bind-mounts:" - plugn trigger storage-list "$APP" "$phase" + if [[ "$FORMAT_FLAG_VALUE" == "text" ]]; then + dokku_log_info1_quiet "$APP volume bind-mounts:" + plugn trigger storage-list "$APP" "$phase" "$format" | sed "s/^/ /" + else + plugn trigger storage-list "$APP" "$phase" "$format" + fi } diff --git a/plugins/storage/storage-list b/plugins/storage/storage-list index 554336baae5..aeb17782960 100755 --- a/plugins/storage/storage-list +++ b/plugins/storage/storage-list @@ -7,9 +7,18 @@ source "$PLUGIN_AVAILABLE_PATH/storage/functions" trigger-storage-storage-list() { declare desc="storage storage-list trigger" declare trigger="storage-list" - declare APP="$1" PHASE="$2" + declare APP="$1" PHASE="$2" FORMAT="$3" - get_bind_mounts "$(fn-get-phase-file-path "$APP" "$PHASE")" + if [[ "$FORMAT" != "json" ]]; then + get_bind_mounts "$(fn-get-phase-file-path "$APP" "$PHASE")" + else + while read -r line; do + local host_path="$(awk -F: '{print $1}' <<<"$line")" + local container_path="$(awk -F: '{print $2}' <<<"$line")" + local volume_options="$(awk -F: '{print $3}' <<<"$line")" + jq -n --arg host_path "$host_path" --arg container_path "$container_path" --arg volume_options "$volume_options" '{host_path: $host_path, container_path: $container_path, volume_options: $volume_options}' + done < <(get_bind_mounts "$(fn-get-phase-file-path "$APP" "$PHASE")") | jq -M -n '[inputs]' + fi } trigger-storage-storage-list "$@" diff --git a/tests/unit/storage.bats b/tests/unit/storage.bats index 87ae535821f..13bd0c15524 100644 --- a/tests/unit/storage.bats +++ b/tests/unit/storage.bats @@ -112,30 +112,74 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "dokku storage:list $TEST_APP | grep -qe '^\s*/tmp/mount:/mount'" + + 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 "" + 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 storage:list $TEST_APP | grep -vqe '^\s*/tmp/mount:/mount'" + + run /bin/bash -c "dokku --quiet storage:list $TEST_APP" echo "output: $output" echo "status: $status" assert_success + assert_output "" + + 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" }