From 1e0c585b742033850dfda9a08754b1921f96a549 Mon Sep 17 00:00:00 2001 From: Michael Hobbs Date: Mon, 9 May 2016 16:03:07 -0700 Subject: [PATCH] allow zero-downtime to be completely disabled. closes #2073. closes #2125 --- docs/appendices/0.6.0-migration-guide.md | 9 ++ docs/checks-examples.md | 33 +++- docs/upgrading.md | 1 + plugins/00_dokku-standard/subcommands/deploy | 25 +-- plugins/checks/check-deploy | 4 +- plugins/checks/commands | 7 +- plugins/checks/functions | 26 ++- plugins/checks/install | 42 +++-- plugins/checks/subcommands/default | 13 +- plugins/checks/subcommands/disable | 39 ++++- plugins/checks/subcommands/enable | 38 ++++- plugins/checks/subcommands/skip | 44 +++++ plugins/common/functions | 19 ++- tests/unit/10_checks.bats | 161 +++++++++++++++++-- 14 files changed, 389 insertions(+), 72 deletions(-) create mode 100644 docs/appendices/0.6.0-migration-guide.md create mode 100755 plugins/checks/subcommands/skip diff --git a/docs/appendices/0.6.0-migration-guide.md b/docs/appendices/0.6.0-migration-guide.md new file mode 100644 index 000000000..bb9313828 --- /dev/null +++ b/docs/appendices/0.6.0-migration-guide.md @@ -0,0 +1,9 @@ +# 0.6.0 Migration Guide + +## zero-downtime deployment +- You can now **actually** disable zero-downtime deployments per-app and per-process-type + - Some config variables have been moved around + - `DOKKU_CHECKS_ENABLED` has been migrated to `DOKKU_CHECKS_SKIPPED` + - `DOKKU_CHECKS_DISABLED` is now a thing + - The values for the above can be a comma-separated list of process-types or the literal string `_all_` + - See the [updated `checks`](/dokku/checks-examples/) docs for more info diff --git a/docs/checks-examples.md b/docs/checks-examples.md index 766bcf07c..9dabd6ffd 100644 --- a/docs/checks-examples.md +++ b/docs/checks-examples.md @@ -3,9 +3,10 @@ > New as of 0.5.0 ``` -checks Show zero-downtime status -checks:disable Disable zero-downtime checks -checks:enable Enable zero-downtime checks +checks Show zero-downtime status +checks:disable [process-type(s)] Disable zero-downtime deployment for all processes (or comma-separated process-type list) ***WARNING: this will cause downtime during deployments*** +checks:enable [process-type(s)] Enable zero-downtime deployment for all processes (or comma-separated process-type list) +checks:skip [process-type(s)] Skip zero-downtime checks for all processes (or comma-separated process-type list) ``` Following a deploy, dokku will wait `10` seconds before routing traffic to the new container to give your application time to boot up. If the application is not running after this time, then the deploy is failed and your old container will continue serving traffic. You can modify this value globally or on a per-application basis: @@ -15,10 +16,32 @@ dokku config:set --global DOKKU_DEFAULT_CHECKS_WAIT=30 dokku config:set DOKKU_DEFAULT_CHECKS_WAIT=30 ``` -You can also choose to skip checks completely on a per-application basis: +You can also choose to skip checks or disable zero-downtime completely on a per-application/per-process basis: ```shell -dokku checks:disable +dokku checks:skip worker,web +``` + +```shell +dokku checks:disable worker,web +``` +> Note that `checks:disable` will now (as of 0.6.0) cause downtime for that process-type during deployments. + +Additionally, any given process can only be configured to skip OR disable zero-downtime. example: + +```shell +$ dokku checks:skip testapp worker,web +-----> Skipping zero downtime for app's (testapp) proctypes (worker,web) +-----> Unsetting testapp +-----> Unsetting DOKKU_CHECKS_DISABLED +-----> Setting config vars + DOKKU_CHECKS_SKIPPED: worker,web +$ dokku checks:disable testapp worker +-----> Disabling zero downtime for app's (testapp) proctypes (worker) +-----> Setting config vars + DOKKU_CHECKS_DISABLED: worker +-----> Setting config vars + DOKKU_CHECKS_SKIPPED: web ``` Dokku will wait `60` seconds before stopping the old container so that existing connections are given a chance to complete. You can modify this value globally or on a per-application basis: diff --git a/docs/upgrading.md b/docs/upgrading.md index 601e35c6b..b0c140a52 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -7,6 +7,7 @@ If your version of dokku is pre 0.3.0 (check with `dokku version`), we recommend Before upgrading, check the migration guides to get comfortable with new features and prepare your deployment to be upgraded. - [0.5 Migration Guide](/dokku/appendices/0.5.0-migration-guide/) +- [0.6 Migration Guide](/dokku/appendices/0.6.0-migration-guide/) ## Upgrade Instructions diff --git a/plugins/00_dokku-standard/subcommands/deploy b/plugins/00_dokku-standard/subcommands/deploy index 307e98143..8ad4a64b0 100755 --- a/plugins/00_dokku-standard/subcommands/deploy +++ b/plugins/00_dokku-standard/subcommands/deploy @@ -19,6 +19,8 @@ dokku_deploy_cmd() { local DOKKU_DEFAULT_DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG") local DOKKU_IS_APP_PROXY_ENABLED="$(is_app_proxy_enabled "$APP")" + local DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" + [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" local line; local PROC_TYPE; local PROC_COUNT; local CONTAINER_INDEX while read -r line || [[ -n "$line" ]]; do @@ -28,6 +30,16 @@ dokku_deploy_cmd() { PROC_COUNT=${line#*=} CONTAINER_INDEX=1 + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "true" ]]; then + dokku_log_info1 "zero downtime is disabled for app ($APP.$PROC_TYPE). stopping currently running containers" + local cid proctype_oldids="$(get_app_container_ids "$APP" "$PROC_TYPE")" + for cid in $proctype_oldids; do + dokku_log_info2 "stopping $APP.$PROC_TYPE ($cid)" + # shellcheck disable=SC2086 + docker stop $DOCKER_STOP_TIME_ARG "$cid" &> /dev/null + done + fi + while [[ $CONTAINER_INDEX -le $PROC_COUNT ]]; do local id=""; local port=""; local ipaddr="" local DOKKU_CONTAINER_ID_FILE="$DOKKU_ROOT/$APP/CONTAINER.$PROC_TYPE.$CONTAINER_INDEX" @@ -82,7 +94,6 @@ dokku_deploy_cmd() { local id=$(docker run $DOKKU_GLOBAL_RUN_ARGS -d $DOCKER_ARGS $IMAGE $START_CMD) fi - # if we can't post-deploy successfully, kill new container kill_new() { declare desc="wrapper function to kill newly started app container" local id="$1" @@ -92,14 +103,12 @@ dokku_deploy_cmd() { } # run checks first, then post-deploy hooks, which switches Nginx traffic - if [[ "$(is_app_checks_enabled "$APP")" == "false" ]]; then - dokku_log_info1 "zero downtime is disabled for app ($APP). skipping pre-flight checks" - else - trap 'kill_new $id' INT TERM EXIT - dokku_log_info1 "Running pre-flight checks" + trap 'kill_new $id' INT TERM EXIT + if [[ "$(is_app_proctype_checks_disabled "$APP" "$PROC_TYPE")" == "false" ]]; then + dokku_log_info1 "Attempting pre-flight checks" plugn trigger check-deploy "$APP" "$id" "$PROC_TYPE" "$port" "$ipaddr" - trap - INT TERM EXIT fi + trap - INT TERM EXIT # now using the new container [[ -n "$id" ]] && echo "$id" > "$DOKKU_CONTAINER_ID_FILE" @@ -143,8 +152,6 @@ dokku_deploy_cmd() { for oldid in $oldids; do dokku_log_info2 "$oldid" done - local DOKKU_DOCKER_STOP_TIMEOUT="$(config_get "$APP" DOKKU_DOCKER_STOP_TIMEOUT || true)" - [[ $DOKKU_DOCKER_STOP_TIMEOUT ]] && DOCKER_STOP_TIME_ARG="--time=${DOKKU_DOCKER_STOP_TIMEOUT}" ( exec >/dev/null 2>/dev/null , Show zero-downtime status - checks:enable , Enable zero-downtime checks - checks:disable , Disable zero-downtime checks + checks:disable [process-type(s)], Disable zero-downtime deployment for all processes (or comma-separated process-type list) ***WARNING: this will cause downtime during deployments*** + checks:enable [process-type(s)], Enable zero-downtime deployment for all processes (or comma-separated process-type list) + checks:skip [process-type(s)], Skip zero-downtime checks for all processes (or comma-separated process-type list) help_content } if [[ $1 = "checks:help" ]] ; then echo -e 'Usage: dokku checks[:COMAND]' echo '' - echo 'Manage zero-downtime checks.' + echo 'Manage zero-downtime settings.' echo '' echo 'Additional commands:' help_content_func | sort | column -c2 -t -s, diff --git a/plugins/checks/functions b/plugins/checks/functions index e0bca091e..f50ccc444 100755 --- a/plugins/checks/functions +++ b/plugins/checks/functions @@ -3,15 +3,27 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" -is_app_checks_enabled() { - declare desc="return app zero-downtime checks status" +is_app_proctype_checks_disabled() { + declare desc="return true if app's proctype(s) checks are disabled" local APP="$1"; verify_app_name "$APP" - local DOKKU_CHECKS_ENABLED=$(config_get "$APP" DOKKU_CHECKS_ENABLED) + local PROCTYPE="$2" status=false + local DOKKU_CHECKS_DISABLED=$(config_get "$APP" DOKKU_CHECKS_DISABLED || true) - if [[ -z "$DOKKU_CHECKS_ENABLED" ]] || [[ "$DOKKU_CHECKS_ENABLED" == "1" ]];then - local status=true - else - local status=false + if [[ "$DOKKU_CHECKS_DISABLED" == "_all_" ]] || [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" == "true" ]] ;then + status=true + fi + + echo $status +} + +is_app_proctype_checks_skipped() { + declare desc="return true if app's proctype(s) checks are skipped" + local APP="$1"; verify_app_name "$APP" + local PROCTYPE="$2" status=false + local DOKKU_CHECKS_SKIPPED=$(config_get "$APP" DOKKU_CHECKS_SKIPPED || true) + + if [[ "$DOKKU_CHECKS_SKIPPED" == "_all_" ]] || [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" == "true" ]] ;then + status=true fi echo $status diff --git a/plugins/checks/install b/plugins/checks/install index 3d5f6e3da..be3feb8d3 100755 --- a/plugins/checks/install +++ b/plugins/checks/install @@ -3,7 +3,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/config/functions" -migrate_checks_vars() { +migrate_checks_vars_0_5_0() { declare desc="migrates deprecated CHECKS config variables to simplified counter part introduced in 0.5.x" local APPS="$(dokku_apps)" local GLOBAL_SKIP_ALL_CHECKS=$(dokku config:get --global DOKKU_SKIP_ALL_CHECKS || true) @@ -11,7 +11,7 @@ migrate_checks_vars() { local app - dokku_log_info1 "Migrating zero downtime env variables. The following variables have been deprecated" + dokku_log_info1 "Migrating zero downtime env variables to 0.5.x. The following variables have been deprecated" dokku_log_info2 "DOKKU_SKIP_ALL_CHECKS DOKKU_SKIP_DEFAULT_CHECKS" dokku_log_info2 "Please use dokku checks:[disable|enable] to control zero downtime functionality" @@ -19,23 +19,47 @@ migrate_checks_vars() { local APP_SKIP_ALL_CHECKS=$(dokku config:get "$app" DOKKU_SKIP_ALL_CHECKS || true) local APP_SKIP_DEFAULT_CHECKS=$(dokku config:get "$app" DOKKU_SKIP_DEFAULT_CHECKS || true) - if [[ "$APP_SKIP_ALL_CHECKS" == "true" ]] || [[ "$APP_SKIP_DEFAULT_CHECKS" == "true" ]] || \ - [[ "$GLOBAL_SKIP_ALL_CHECKS" == "true" ]] || [[ "$GLOBAL_SKIP_DEFAULT_CHECKS" == "true" ]]; then - dokku_log_info2 "" - dokku_log_info2 "zero downtime disabled for app ($app)" + if [[ "$APP_SKIP_ALL_CHECKS" == "true" ]] || [[ "$APP_SKIP_DEFAULT_CHECKS" == "true" ]] || [[ "$GLOBAL_SKIP_ALL_CHECKS" == "true" ]] || [[ "$GLOBAL_SKIP_DEFAULT_CHECKS" == "true" ]]; then + dokku_log_info2 "" + dokku_log_info2 "zero downtime checks disabled for app ($app)" config_set --no-restart "$app" DOKKU_CHECKS_ENABLED=0 fi if [[ -n "$APP_SKIP_ALL_CHECKS" ]] || [[ -n "$APP_SKIP_DEFAULT_CHECKS" ]]; then config_unset --no-restart "$app" DOKKU_SKIP_ALL_CHECKS DOKKU_SKIP_DEFAULT_CHECKS fi - dokku_log_info2 "Migration complete" - dokku_log_info2 "" done if [[ -n "$GLOBAL_SKIP_ALL_CHECKS" ]] || [[ -n "$GLOBAL_SKIP_DEFAULT_CHECKS" ]]; then dokku_log_info1 "Removing global zero downtime settings" config_unset --global DOKKU_SKIP_ALL_CHECKS DOKKU_SKIP_DEFAULT_CHECKS fi + dokku_log_info2 "Migration complete" + dokku_log_info2 "" } -migrate_checks_vars "$@" +migrate_checks_vars_0_5_0 "$@" + +migrate_checks_vars_0_6_0() { + declare desc="migrates CHECKS config variables from 0.5.x to support fully-disabled zero-downtime checks" + local APPS="$(dokku_apps)" + + local app + + dokku_log_info1 "Migrating zero downtime env variables to 0.6.x. The following variables will be migrated" + dokku_log_info2 "DOKKU_CHECKS_ENABLED -> DOKKU_CHECKS_SKIPPED" + for app in $APPS; do + local APP_DOKKU_CHECKS_ENABLED=$(dokku config:get "$app" DOKKU_CHECKS_ENABLED || true) + if [[ $APP_DOKKU_CHECKS_ENABLED ]]; then + if [[ "$DOKKU_CHECKS_ENABLED" == "0" ]]; then + dokku_log_info2 "" + dokku_log_info2 "zero downtime checks disabled for app ($app)" + config_set --no-restart "$app" DOKKU_CHECKS_SKIPPED="_all_" + fi + config_unset --no-restart "$app" DOKKU_CHECKS_ENABLED || true + fi + done + dokku_log_info2 "Migration complete" + dokku_log_info2 "" +} + +migrate_checks_vars_0_6_0 "$@" diff --git a/plugins/checks/subcommands/default b/plugins/checks/subcommands/default index 1edfaec9d..f1102fb14 100755 --- a/plugins/checks/subcommands/default +++ b/plugins/checks/subcommands/default @@ -4,19 +4,24 @@ source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/checks/functions" checks_main_cmd() { - declare desc="displays app zero-downtime status" + declare desc="displays app zero-downtime checks status" local cmd="checks" + [[ "$1" == "$cmd" ]] && shift 1 local APPS=$(dokku_apps) if [[ -n "$1" ]]; then local APPS="$1" fi - dokku_col_log_info1_quiet "App Name" "Zero-Downtime Status" + dokku_col_log_info1_quiet "App Name" "Proctypes Disabled" "Proctypes Skipped" local app for app in $APPS; do verify_app_name "$app" - dokku_col_log_msg "$app" "$(is_app_checks_enabled "$app")" + local DOKKU_CHECKS_DISABLED=$(config_get "$app" DOKKU_CHECKS_DISABLED) + local DOKKU_CHECKS_SKIPPED=$(config_get "$app" DOKKU_CHECKS_SKIPPED) + local checks_disabled="${DOKKU_CHECKS_DISABLED:-none}" + local checks_skipped="${DOKKU_CHECKS_SKIPPED:-none}" + dokku_col_log_msg "$app" "$checks_disabled" "$checks_skipped" done } -checks_main_cmd "$2" +checks_main_cmd "$@" diff --git a/plugins/checks/subcommands/disable b/plugins/checks/subcommands/disable index 0c5188dc6..8b3970928 100755 --- a/plugins/checks/subcommands/disable +++ b/plugins/checks/subcommands/disable @@ -4,18 +4,41 @@ source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/checks/functions" checks_disable_cmd() { - declare desc="disable zero-downtime for app" - local cmd="check:disable" + declare desc="disable zero-downtime checks for app/proctypes" + local cmd="checks:disable" + [[ "$1" == "$cmd" ]] && shift 1 local APP="$1"; verify_app_name "$APP" + local PROCTYPES="${2:-_all_}" + local DOKKU_CHECKS_DISABLED=$(config_get "$APP" DOKKU_CHECKS_DISABLED || true) + local DOKKU_CHECKS_SKIPPED=$(config_get "$APP" DOKKU_CHECKS_SKIPPED || true) - if [[ "$(is_app_checks_enabled "$APP")" == "true" ]]; then + if [[ "$PROCTYPES" == "_all_" ]]; then dokku_log_info1 "Disabling zero downtime for app ($APP)" - [[ "$2" == "--no-restart" ]] && local CONFIG_SET_ARGS=$2 - # shellcheck disable=SC2086 - config_set $CONFIG_SET_ARGS $APP DOKKU_CHECKS_ENABLED=0 + config_set --no-restart "$APP" DOKKU_CHECKS_DISABLED="$PROCTYPES" + config_unset --no-restart "$APP" DOKKU_CHECKS_SKIPPED else - dokku_log_info1 "zero downtime is already disable for app ($APP)" + dokku_log_info1 "Disabling zero downtime for app's ($APP) proctypes ($PROCTYPES)" + local PROCTYPE OIFS="$IFS" IFS=, + for PROCTYPE in $PROCTYPES; do + IFS="$OIFS" + [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" == "false" ]] && \ + DOKKU_CHECKS_DISABLED="$(add_val_to_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" + [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" == "true" ]] && \ + DOKKU_CHECKS_SKIPPED="$(remove_val_from_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" + done + DOKKU_CHECKS_DISABLED="$(remove_val_from_list "_all_" "$DOKKU_CHECKS_DISABLED")" + if [[ -z "$DOKKU_CHECKS_DISABLED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_DISABLED + else + config_set --no-restart "$APP" DOKKU_CHECKS_DISABLED="$DOKKU_CHECKS_DISABLED" + fi + + if [[ -z "$DOKKU_CHECKS_SKIPPED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_SKIPPED + else + config_set --no-restart "$APP" DOKKU_CHECKS_SKIPPED="$DOKKU_CHECKS_SKIPPED" + fi fi } -checks_disable_cmd "$2" --no-restart +checks_disable_cmd "$@" diff --git a/plugins/checks/subcommands/enable b/plugins/checks/subcommands/enable index 98be76bf0..fc19f9afc 100755 --- a/plugins/checks/subcommands/enable +++ b/plugins/checks/subcommands/enable @@ -4,18 +4,40 @@ source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" source "$PLUGIN_AVAILABLE_PATH/checks/functions" checks_enable_cmd() { - declare desc="enable zero-downtime for app" + declare desc="enable zero-downtime checks for app/proctypes" local cmd="checks:enable" + [[ "$1" == "$cmd" ]] && shift 1 local APP="$1"; verify_app_name "$APP" + local PROCTYPES="${2:-_all_}" - if [[ "$(is_app_checks_enabled "$APP")" == "false" ]]; then - dokku_log_info1 "Enabling zero downtime for app ($APP)" - [[ "$2" == "--no-restart" ]] && local CONFIG_SET_ARGS=$2 - # shellcheck disable=SC2086 - config_set $CONFIG_SET_ARGS $APP DOKKU_CHECKS_ENABLED=1 + local DOKKU_CHECKS_DISABLED=$(config_get "$APP" DOKKU_CHECKS_DISABLED || true) + local DOKKU_CHECKS_SKIPPED=$(config_get "$APP" DOKKU_CHECKS_SKIPPED || true) + + if [[ "$PROCTYPES" == "_all_" ]]; then + dokku_log_info1 "Enabling zero downtime for app's ($APP)" + config_unset --no-restart "$APP" DOKKU_CHECKS_DISABLED + config_unset --no-restart "$APP" DOKKU_CHECKS_SKIPPED else - dokku_log_info1 "zero downtime is already enabled for app ($APP)" + dokku_log_info1 "Enabling zero downtime for app's ($APP) proctypes ($PROCTYPES)" + local PROCTYPE OIFS="$IFS" IFS=, + for PROCTYPE in $PROCTYPES; do + DOKKU_CHECKS_DISABLED="$(remove_val_from_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" + DOKKU_CHECKS_SKIPPED="$(remove_val_from_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" + done + + IFS="$OIFS" + if [[ -z "$DOKKU_CHECKS_DISABLED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_DISABLED + else + config_set --no-restart "$APP" DOKKU_CHECKS_DISABLED="$DOKKU_CHECKS_DISABLED" + fi + + if [[ -z "$DOKKU_CHECKS_SKIPPED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_SKIPPED + else + config_set --no-restart "$APP" DOKKU_CHECKS_SKIPPED="$DOKKU_CHECKS_SKIPPED" + fi fi } -checks_enable_cmd "$2" --no-restart +checks_enable_cmd "$@" diff --git a/plugins/checks/subcommands/skip b/plugins/checks/subcommands/skip new file mode 100755 index 000000000..2a2ce2b83 --- /dev/null +++ b/plugins/checks/subcommands/skip @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" +source "$PLUGIN_AVAILABLE_PATH/checks/functions" + +checks_skip_cmd() { + declare desc="skip zero-downtime checks for app/proctypes" + local cmd="checks:skip" + [[ "$1" == "$cmd" ]] && shift 1 + local APP="$1"; verify_app_name "$APP" + local PROCTYPES="${2:-_all_}" + local DOKKU_CHECKS_DISABLED=$(config_get "$APP" DOKKU_CHECKS_DISABLED || true) + local DOKKU_CHECKS_SKIPPED=$(config_get "$APP" DOKKU_CHECKS_SKIPPED || true) + + if [[ "$PROCTYPES" == "_all_" ]]; then + dokku_log_info1 "Skipping zero downtime for app ($APP)" + config_set --no-restart "$APP" DOKKU_CHECKS_SKIPPED="$PROCTYPES" + config_unset --no-restart "$APP" DOKKU_CHECKS_DISABLED + else + dokku_log_info1 "Skipping zero downtime for app's ($APP) proctypes ($PROCTYPES)" + local PROCTYPE OIFS="$IFS" IFS=, + for PROCTYPE in $PROCTYPES; do + IFS="$OIFS" + [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" == "false" ]] && \ + DOKKU_CHECKS_SKIPPED="$(add_val_to_list "$PROCTYPE" "$DOKKU_CHECKS_SKIPPED")" + [[ "$(is_val_in_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" == "true" ]] && \ + DOKKU_CHECKS_DISABLED="$(remove_val_from_list "$PROCTYPE" "$DOKKU_CHECKS_DISABLED")" + done + DOKKU_CHECKS_SKIPPED="$(remove_val_from_list "_all_" "$DOKKU_CHECKS_SKIPPED")" + if [[ -z "$DOKKU_CHECKS_DISABLED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_DISABLED + else + config_set --no-restart "$APP" DOKKU_CHECKS_DISABLED="$DOKKU_CHECKS_DISABLED" + fi + + if [[ -z "$DOKKU_CHECKS_SKIPPED" ]]; then + config_unset --no-restart "$APP" DOKKU_CHECKS_SKIPPED + else + config_set --no-restart "$APP" DOKKU_CHECKS_SKIPPED="$DOKKU_CHECKS_SKIPPED" + fi + fi +} + +checks_skip_cmd "$@" diff --git a/plugins/common/functions b/plugins/common/functions index d3367c2ef..91e8bda23 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -269,7 +269,7 @@ copy_from_image() { } get_app_container_ids() { - declare desc="returns list of docker container ids for given app" + declare desc="returns list of docker container ids for given app/container_type" local APP="$1"; local CONTAINER_TYPE="$2" verify_app_name "$APP" [[ -f $DOKKU_ROOT/$APP/CONTAINER ]] && DOKKU_CIDS+=$(< "$DOKKU_ROOT/$APP/CONTAINER") @@ -766,3 +766,20 @@ is_val_in_list() { echo "$val_in_list" } + +remove_val_from_list() { + declare desc="remove value ($1) from list ($2) separated by delimiter ($3) (delimiter defaults to comma) and return list" + local value="$1" list="$2" delimiter="${3:-,}" + list="${list//$value/}" + list="${list//$delimiter$delimiter/$delimiter}" + list="${list/#$delimiter/}" + list="${list/%$delimiter/}" + echo "$list" +} + +add_val_to_list() { + declare desc="add value ($1) to list ($2) separated by delimiter ($3) (delimiter defaults to comma) and return list" + local value="$1" list="$2" delimiter="${3:-,}" + list+="${delimiter}$value" + echo "$list" +} diff --git a/tests/unit/10_checks.bats b/tests/unit/10_checks.bats index 3ccc79988..2d49ae37f 100644 --- a/tests/unit/10_checks.bats +++ b/tests/unit/10_checks.bats @@ -15,31 +15,160 @@ teardown() { } @test "(checks) checks" { - run bash -c "dokku checks $TEST_APP | grep -q true" + run bash -c "dokku checks $TEST_APP| grep $TEST_APP | xargs" echo "output: "$output echo "status: "$status - assert_success + assert_output "$TEST_APP none none" } @test "(checks) checks:disable" { - dokku checks:disable $TEST_APP - assert_success - - run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_ENABLED" + run bash -c "dokku checks:disable $TEST_APP" echo "output: "$output echo "status: "$status - assert_output "0" -} - -@test "(checks) checks:enable" { - dokku checks:disable $TEST_APP assert_success - dokku checks:enable $TEST_APP - assert_success - - run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_ENABLED" + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" echo "output: "$output echo "status: "$status - assert_output "1" + assert_output "_all_" +} + +@test "(checks) checks:disable -> checks:enable" { + run bash -c "dokku checks:disable $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "_all_" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku checks:enable $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "" +} + +@test "(checks) checks:disable -> checks:skip" { + run bash -c "dokku checks:disable $TEST_APP web,worker,urgentworker,notifications" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "web,worker,urgentworker,notifications" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku checks:skip $TEST_APP urgentworker,worker" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "urgentworker,worker" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "web,notifications" +} + +@test "(checks) checks:skip" { + run bash -c "dokku checks:skip $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "_all_" +} + +@test "(checks) checks:skip -> checks:enable" { + run bash -c "dokku checks:skip $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "_all_" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku checks:enable $TEST_APP" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "" +} + +@test "(checks) checks:skip -> checks:disable" { + run bash -c "dokku checks:skip $TEST_APP web,worker,urgentworker,notifications" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "web,worker,urgentworker,notifications" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "" + + run bash -c "dokku checks:disable $TEST_APP urgentworker,worker" + echo "output: "$output + echo "status: "$status + assert_success + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_DISABLED" + echo "output: "$output + echo "status: "$status + assert_output "urgentworker,worker" + + run bash -c "dokku config:get $TEST_APP DOKKU_CHECKS_SKIPPED" + echo "output: "$output + echo "status: "$status + assert_output "web,notifications" }