From 165b6ff46fe56b4a1f4cfe9156fe9bca3bea91f5 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 4 Mar 2018 01:04:21 -0500 Subject: [PATCH] feat: add subcommands to allow app locking and unlocking Unlocking an app will not stop running deploys, so users may need to clean up. However, it is useful for deploys that fail in unusual ways that cause the lock to stay around. Closes #2883 --- docs/deployment/application-management.md | 43 +++++++++++++++++++++-- plugins/apps/internal-functions | 14 ++++++++ plugins/apps/subcommands/lock | 17 +++++++++ plugins/apps/subcommands/report | 2 ++ plugins/apps/subcommands/unlock | 22 ++++++++++++ plugins/common/functions | 4 +-- tests/unit/10_apps.bats | 31 ++++++++++++++++ 7 files changed, 129 insertions(+), 4 deletions(-) create mode 100755 plugins/apps/subcommands/lock create mode 100755 plugins/apps/subcommands/unlock diff --git a/docs/deployment/application-management.md b/docs/deployment/application-management.md index bfbacd755..4162c1f90 100644 --- a/docs/deployment/application-management.md +++ b/docs/deployment/application-management.md @@ -8,8 +8,10 @@ apps:create # Create a new app apps:destroy # Permanently destroy an app apps:exists # Checks if an app exists apps:list # List your apps +apps:lock # Creates a '.deploy.lock' file in an application's repo apps:rename # Rename an app apps:report [] [] # Display report about an app +apps:unlock # Removes the '.deploy.lock' file from an application's repo ``` ## Usage @@ -134,7 +136,7 @@ This will copy all of your app's contents into a new app directory with the name ### Cloning an existing app -> New as of 0.8.1 +> New as of 0.11.5 You can clone an existing app using the `apps:clone` command. Note that the application *must* have been deployed at least once, or cloning will not complete successfully: @@ -156,6 +158,39 @@ By default, Dokku will deploy this new application, though you can skip the depl dokku apps:clone --skip-deploy node-js-app io-js-app ``` +### Locking app deploys + +> New as of 0.11.6 + +If you wish to disable deploying for a period of time, this can be done via deploy locks. Normally, deploy locks exist only for the duration of a deploy so as to avoid deploys from colliding, but a deploy lock can be created by running the `apps:lock` subcommand. + + +```shell +dokku apps:lock node-js-app +``` + +``` +-----> Deploy lock created +``` + +### Unlocking app deploys + +> New as of 0.11.6 + +In some cases, it may be necessary to remove an existing deploy lock. This can be performed via the `apps:unlock` subcommand. + +> Warning: Removing the deploy lock _will not_ stop in progress deploys. At this time, in progress deploys will need to be manually terminated by someone with server access. + +```shell +dokku apps:unlock node-js-app +``` + +``` + ! A deploy may be in progress. + ! Removing the application lock will not stop in progress deploys. +-----> Deploy lock removed. +``` + ### Displaying reports about an app > New as of 0.8.1 @@ -171,12 +206,14 @@ dokku apps:report App dir: /home/dokku/node-js-app Git sha: dbddc3f Deploy method: git + Locked: false =====> python-sample not deployed =====> ruby-sample App dir: /home/dokku/ruby-sample Git sha: a2d477c Deploy method: git + Locked: false ``` You can run the command for a specific app also. @@ -188,7 +225,9 @@ dokku apps:report node-js-app ``` =====> node-js-app App dir: /home/dokku/node-js-app - Git sha: dbddc3f + Git sha: dbddc3f + Deploy method: git + Locked: false ``` You can pass flags which will output only the value of the specific information you want. For example: diff --git a/plugins/apps/internal-functions b/plugins/apps/internal-functions index 4de6de77e..252d68a5d 100755 --- a/plugins/apps/internal-functions +++ b/plugins/apps/internal-functions @@ -10,8 +10,10 @@ apps_help_content_func() { apps:create , Create a new app apps:destroy , Permanently destroy an app apps:list, List your apps + apps:lock , Creates a '.deploy.lock' file in an application's repo apps:rename , Rename an app apps:report [] [], Display report about an app + apps:unlock , Removes the '.deploy.lock' file from an application's repo help_content } @@ -49,3 +51,15 @@ apps_list_cmd() { echo "$app" done } + +apps_is_locked() { + declare desc="check if an app is locked" + declare APP="$1" + local LOCKED=false + + if [[ -f "$DOKKU_ROOT/$APP/.deploy.lock" ]]; then + LOCKED=true + fi + + echo "$LOCKED" +} \ No newline at end of file diff --git a/plugins/apps/subcommands/lock b/plugins/apps/subcommands/lock new file mode 100755 index 000000000..bbe6f017a --- /dev/null +++ b/plugins/apps/subcommands/lock @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_AVAILABLE_PATH/apps/internal-functions" + +apps_lock_cmd() { + declare desc="creates a '.deploy.lock' file in an application's repo" + declare cmd="apps:lock" + [[ "$1" == "$cmd" ]] && shift 1 + declare APP="$1"; verify_app_name "$APP" + + touch "$DOKKU_ROOT/$APP/.deploy.lock" || dokku_log_fail "Unable to create deploy lock" + + dokku_log_info1 "Deploy lock created" +} + +apps_lock_cmd "$@" diff --git a/plugins/apps/subcommands/report b/plugins/apps/subcommands/report index 39e848665..bb3484987 100755 --- a/plugins/apps/subcommands/report +++ b/plugins/apps/subcommands/report @@ -2,6 +2,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/apps/functions" +source "$PLUGIN_AVAILABLE_PATH/apps/internal-functions" report_single_app() { declare APP="$1" INFO_FLAG="$2" @@ -16,6 +17,7 @@ report_single_app() { "--app-dir: $APP_DIR" "--git-sha: $(GIT_DIR="$APP_DIR" git rev-parse --short HEAD 2> /dev/null || false)" "--deploy-source: $(: | plugn trigger deploy-source "$APP")" + "--locked: $(apps_is_locked "$APP")" ) if [[ -z "$INFO_FLAG" ]]; then diff --git a/plugins/apps/subcommands/unlock b/plugins/apps/subcommands/unlock new file mode 100755 index 000000000..4eac17eb3 --- /dev/null +++ b/plugins/apps/subcommands/unlock @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_AVAILABLE_PATH/apps/internal-functions" + +apps_unlock_cmd() { + declare desc="removes the '.deploy.lock' file from an application's repo" + declare cmd="apps:unlock" + [[ "$1" == "$cmd" ]] && shift 1 + declare APP="$1"; verify_app_name "$APP" + + if [[ -f "$DOKKU_ROOT/$APP/.deploy.lock" ]]; then + dokku_log_warn "A deploy may be in progress." + dokku_log_warn "Removing the application lock will not stop in progress deploys." + fi + + rm -f "$DOKKU_ROOT/$APP/.deploy.lock" || dokku_log_fail "Unable to remove deploy lock" + + dokku_log_info1 "Deploy lock removed." +} + +apps_unlock_cmd "$@" diff --git a/plugins/common/functions b/plugins/common/functions index 9b220ab5a..82f82f077 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -1160,8 +1160,8 @@ acquire_app_deploy_lock() { local LOCK_TYPE="${2:-waiting}" local APP_DEPLOY_LOCK_FD="200" local APP_DEPLOY_LOCK_FILE="$DOKKU_ROOT/$APP/.deploy.lock" - local LOCK_WAITING_MSG="$APP is currently being deployed. Waiting..." - local LOCK_FAILED_MSG="$APP is currently being deployed. Exiting..." + local LOCK_WAITING_MSG="$APP currently has a deploy lock in place. Waiting..." + local LOCK_FAILED_MSG="$APP currently has a deploy lock in place. Exiting..." local SHOW_MSG=true eval "exec $APP_DEPLOY_LOCK_FD>$APP_DEPLOY_LOCK_FILE" diff --git a/tests/unit/10_apps.bats b/tests/unit/10_apps.bats index d0ff646f2..5fb722f6b 100644 --- a/tests/unit/10_apps.bats +++ b/tests/unit/10_apps.bats @@ -150,4 +150,35 @@ teardown () { echo "status: "$status assert_success +} + +@test "(apps) apps:lock/unlock" { + create_app + + run bash -c "dokku apps:report $TEST_APP --locked" + echo "output: "$output + echo "status: "$status + assert_output "false" + + run bash -c "dokku apps:lock $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku apps:report $TEST_APP --locked" + echo "output: "$output + echo "status: "$status + assert_output "true" + + run bash -c "dokku apps:unlock $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku apps:report $TEST_APP --locked" + echo "output: "$output + echo "status: "$status + assert_output "false" + + destroy_app } \ No newline at end of file