diff --git a/docs/development/plugin-creation.md b/docs/development/plugin-creation.md index 55098a826..b5dd86fb6 100644 --- a/docs/development/plugin-creation.md +++ b/docs/development/plugin-creation.md @@ -20,8 +20,8 @@ source "$PLUGIN_PATH/common/functions" case "$1" in hello) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - APP="$2"; + APP="$2"; TAG=$(get_running_image_tag $APP) + verify_app_name "$2" "$TAG" echo "Hello $APP" ;; diff --git a/docs/development/pluginhooks.md b/docs/development/pluginhooks.md index 130332d96..202328e28 100644 --- a/docs/development/pluginhooks.md +++ b/docs/development/pluginhooks.md @@ -244,7 +244,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. - Invoked by: `dokku release` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell @@ -252,8 +252,9 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x # Installs the graphicsmagick package into the container set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - source "$PLUGIN_PATH/common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" dokku_log_info1" Installing GraphicsMagick..." @@ -270,7 +271,7 @@ docker commit $ID $IMAGE > /dev/null - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using buildpacks. - Invoked by: `dokku release` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell @@ -278,8 +279,9 @@ docker commit $ID $IMAGE > /dev/null # Installs a package specified by the `CONTAINER_PACKAGE` env var set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - source "$PLUGIN_PATH/common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" dokku_log_info1" Installing $CONTAINER_PACKAGE..." @@ -296,13 +298,16 @@ docker commit $ID $IMAGE > /dev/null - Description: Allows you to run commands before environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. - Invoked by: `dokku release` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" # TODO ``` @@ -311,13 +316,16 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - Description: Allows you to run commands after environment variables are set for the release step of the deploy. Only applies to applications using a dockerfile. - Invoked by: `dokku release` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" # TODO ``` @@ -352,7 +360,7 @@ fi - Description: Allows the running of code before the container's process is started. - Invoked by: `dokku deploy` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell @@ -360,11 +368,9 @@ fi # Runs gulp in our container set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - source "$PLUGIN_PATH/common/functions" - -APP="$1" -IMAGE="dokku/$APP" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" dokku_log_info1 "Running gulp" id=$(docker run -d $IMAGE /bin/bash -c "cd /app && gulp default") @@ -401,8 +407,11 @@ curl "http://httpstat.us/200" # Clears out the gulp asset build cache for applications set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" -APP="$1"; IMAGE="dokku/$APP"; GULP_CACHE_DIR="$DOKKU_ROOT/$APP/gulp" +APP="$1"; GULP_CACHE_DIR="$DOKKU_ROOT/$APP/gulp" +TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" if [[ -d $GULP_CACHE_DIR ]]; then docker run --rm -v "$GULP_CACHE_DIR:/gulp" "$IMAGE" find /gulp -depth -mindepth 1 -maxdepth 1 -exec rm -Rf {} \; || true @@ -447,13 +456,16 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - Description: - Invoked by: `dokku deploy` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" # TODO ``` @@ -462,13 +474,16 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x - Description: - Invoked by: `dokku run` -- Arguments: `$APP` +- Arguments: `$APP $TAG` - Example: ```shell #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" +APP="$1"; TAG=$(get_running_image_tag $APP) +verify_app_name "$APP" "$TAG" # TODO ``` diff --git a/docs/process-management.md b/docs/process-management.md index f7c5e6b4c..64d88a4c1 100644 --- a/docs/process-management.md +++ b/docs/process-management.md @@ -42,3 +42,57 @@ dokku ps:scale app_name web=1 worker=2 ## The web proctype Like Heroku, we handle the `web` proctype differently from others. The `web` proctype is the only proctype that will invoke custom checks as defined by a CHECKS file. It is also the only proctype that will be launched in a container that is either proxied via nginx or bound to an external port. + +## Image tagging + +The dokku tag plugin allows you to add docker image tags to the currently deployed app image for versioning and subsequent deployment. + +``` +tag:add Add tag to latest running app image +tag:deploy Deploy tagged app image +tag:list List all app image tags +tag:rm Remove app image tag +``` + +Example: +``` +root@dokku:~# dokku tag:list node-js-app +=====> Image tags for dokku/node-js-app +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +dokku/node-js-app latest 936a42f25901 About a minute ago 1.025 GB + +root@dokku:~# dokku tag:add node-js-app v0.9.0 +=====> Added v0.9.0 tag to dokku/node-js-app +root@dokku:~# dokku tag:list node-js-app +=====> Image tags for dokku/node-js-app +REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE +dokku/node-js-app latest 936a42f25901 About a minute ago 1.025 GB +dokku/node-js-app v0.9.0 936a42f25901 About a minute ago 1.025 GB + +root@dokku:~# dokku tag:deploy node-js-app v0.9.0 +-----> Releasing node-js-app (dokku/node-js-app:v0.9.0)... +-----> Deploying node-js-app (dokku/node-js-app:v0.9.0)... +-----> Running pre-flight checks + For more efficient zero downtime deployments, create a file CHECKS. + See http://progrium.viewdocs.io/dokku/checks-examples.md for examples + CHECKS file not found in container: Running simple container check... +-----> Waiting for 10 seconds ... +-----> Default container check successful! +=====> node-js-app container output: + Detected 512 MB available memory, 512 MB limit per process (WEB_MEMORY) + Recommending WEB_CONCURRENCY=1 + > node-js-sample@0.1.0 start /app + > node index.js + Node app is running at localhost:5000 +=====> end node-js-app container output +-----> Running post-deploy +-----> Configuring node-js-app.dokku.me... +-----> Creating http nginx.conf +-----> Running nginx-pre-reload + Reloading nginx +-----> Shutting down old containers in 60 seconds +=====> 025eec3fa3b442fded90933d58d8ed8422901f0449f5ea0c23d00515af5d3137 +=====> Application deployed: + http://node-js-app.dokku.me + +``` diff --git a/dokku b/dokku index f1adf488e..7881fcf26 100755 --- a/dokku +++ b/dokku @@ -51,15 +51,12 @@ fi case "$1" in receive) - APP="$2"; IMAGE="dokku/$APP"; IMAGE_SOURCE_TYPE="$3"; TMP_WORK_DIR="$4" + APP="$2"; IMAGE_SOURCE_TYPE="$3"; TMP_WORK_DIR="$4" dokku_log_info1 "Cleaning up..." dokku cleanup dokku_log_info1 "Building $APP from $IMAGE_SOURCE_TYPE..." dokku build "$APP" "$IMAGE_SOURCE_TYPE" "$TMP_WORK_DIR" - dokku_log_info1 "Releasing $APP..." - dokku release "$APP" "$IMAGE_SOURCE_TYPE" - dokku_log_info1 "Deploying $APP..." - dokku deploy "$APP" + release_and_deploy "$APP" dokku_log_info2 "Application deployed:" dokku urls "$APP" | sed "s/^/ /" echo @@ -67,10 +64,8 @@ case "$1" in deploy) [[ -z $2 ]] && dokku_log_fail "Please specify an app to deploy" - APP="$2"; IMAGE="dokku/$APP" - verify_app_name "$APP" - - pluginhook pre-deploy $APP + APP="$2"; TAG="$3"; verify_app_name "$APP" "$TAG" + pluginhook pre-deploy $APP $TAG is_image_herokuish_based "$IMAGE" && DOKKU_HEROKUISH=true DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" @@ -90,10 +85,10 @@ case "$1" in DOKKU_PORT_FILE="$DOKKU_ROOT/$APP/PORT.$PROC_TYPE.$CONTAINER_INDEX" # start the app - DOCKER_ARGS=$(: | pluginhook docker-args $APP deploy) + DOCKER_ARGS=$(: | pluginhook docker-args $APP deploy $TAG) DOCKER_ARGS+=" -e DYNO=$PROC_TYPE " DOCKER_ARGS+=" -e DYNO_TYPE_NUMBER='$PROC_TYPE.$CONTAINER_INDEX' " - DOCKER_ARGS+=$(: | pluginhook docker-args-deploy $APP) + DOCKER_ARGS+=$(: | pluginhook docker-args-deploy $APP $TAG) BIND_EXTERNAL=$(pluginhook bind-external-ip $APP) [[ -n "$DOKKU_HEROKUISH" ]] && START_CMD="/start $PROC_TYPE" diff --git a/plugins/00_dokku-standard/commands b/plugins/00_dokku-standard/commands index 2a450c864..fc0a42a3c 100755 --- a/plugins/00_dokku-standard/commands +++ b/plugins/00_dokku-standard/commands @@ -5,7 +5,9 @@ source "$PLUGIN_PATH/config/functions" case "$1" in build) - APP="$2"; IMAGE="dokku/$APP"; IMAGE_SOURCE_TYPE="$3"; TMP_WORK_DIR="$4" + APP="$2"; IMAGE_SOURCE_TYPE="$3"; TMP_WORK_DIR="$4" + verify_app_name "$APP" + CACHE_DIR="$DOKKU_ROOT/$APP/cache" eval "$(config_export app $APP)" @@ -58,14 +60,16 @@ case "$1" in ;; release) - APP="$2"; IMAGE="dokku/$APP"; IMAGE_SOURCE_TYPE="$3" + APP="$2"; IMAGE_SOURCE_TYPE="$3"; TAG="$4" + verify_app_name "$APP" "$TAG" + case "$IMAGE_SOURCE_TYPE" in herokuish) # *DEPRECATED* in v0.3.15: `pluginhook pre-release` will be removed in future releases - pluginhook pre-release "$APP" + pluginhook pre-release "$APP" "$TAG" # *DEPRECATED* in v0.3.22: `pluginhook pre-release-buildstep` will be removed in future releases - pluginhook pre-release-buildstep "$APP" - pluginhook pre-release-buildpack "$APP" + pluginhook pre-release-buildstep "$APP" "$TAG" + pluginhook pre-release-buildpack "$APP" "$TAG" if [[ -n $(config_export global) ]]; then id=$(config_export global | docker run -i -a stdin $IMAGE /bin/bash -c "mkdir -p /app/.profile.d && cat > /app/.profile.d/00-global-env.sh") test "$(docker wait $id)" -eq 0 @@ -77,15 +81,15 @@ case "$1" in docker commit $id $IMAGE > /dev/null fi # *DEPRECATED* in v0.3.15: `pluginhook post-release` will be removed in future releases - pluginhook post-release "$APP" + pluginhook post-release "$APP" "$TAG" # *DEPRECATED* in v0.3.22: `pluginhook post-release-buildstep` will be removed in future releases - pluginhook post-release-buildstep "$APP" - pluginhook post-release-buildpack "$APP" + pluginhook post-release-buildstep "$APP" "$TAG" + pluginhook post-release-buildpack "$APP" "$TAG" ;; dockerfile) - pluginhook pre-release-dockerfile "$APP" - pluginhook post-release-dockerfile "$APP" + pluginhook pre-release-dockerfile "$APP" "$TAG" + pluginhook post-release-dockerfile "$APP" "$TAG" ;; *) @@ -140,8 +144,7 @@ case "$1" in logs) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - APP="$2"; + APP="$2"; verify_app_name "$2" if (is_deployed $APP); then CONTAINER_IDS=( $(get_app_container_ids $APP) ) @@ -167,13 +170,13 @@ case "$1" in run) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - APP="$2"; IMAGE="dokku/$APP" + APP="$2"; TAG=$(get_running_image_tag $APP) + verify_app_name "$APP" "$TAG" shift 2 - DOCKER_ARGS=$(: | pluginhook docker-args $APP run) - DOCKER_ARGS+=$(: | pluginhook docker-args-run $APP) + DOCKER_ARGS=$(: | pluginhook docker-args $APP run $TAG) + DOCKER_ARGS+=$(: | pluginhook docker-args-run $APP $TAG) [[ $DOKKU_RM_CONTAINER ]] && DOKKU_RUN_OPTS="--rm" has_tty && DOKKU_RUN_OPTS+=" -i -t" is_image_herokuish_based "$IMAGE" && EXEC_CMD="/exec" @@ -183,9 +186,7 @@ case "$1" in url | urls) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - APP="$2"; - + APP="$2"; verify_app_name "$2" eval "$(config_export app $APP)" if [[ -s "$DOKKU_ROOT/$APP/URLS" ]]; then diff --git a/plugins/apps/commands b/plugins/apps/commands index 4e303e26d..4924fb13b 100755 --- a/plugins/apps/commands +++ b/plugins/apps/commands @@ -19,11 +19,10 @@ case "$1" in apps:destroy) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" [[ "$2" == "tls" ]] && echo "Unable to destroy tls directory" && exit 1 - APP="$2"; IMAGE="dokku/$APP" - [[ "$3" == "force" ]] && DOKKU_APPS_FORCE_DELETE=1 + APP="$2"; verify_app_name "$APP" + if [[ -z "$DOKKU_APPS_FORCE_DELETE" ]]; then dokku_log_warn "WARNING: Potentially Destructive Action" dokku_log_warn "This command will destroy $APP (including all add-ons)." @@ -48,8 +47,6 @@ case "$1" in done fi - docker images | grep $IMAGE | awk '{print $3}' | xargs docker rmi &> /dev/null & - pluginhook post-delete $APP ;; diff --git a/plugins/apps/post-delete b/plugins/apps/post-delete index b164bb44b..66b4f40f8 100755 --- a/plugins/apps/post-delete +++ b/plugins/apps/post-delete @@ -1,4 +1,11 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +APP="$1" -[[ -n $1 ]] && rm -r "$DOKKU_ROOT/$1" > /dev/null +[[ -n $APP ]] && rm -r "$DOKKU_ROOT/$APP" > /dev/null + +# remove all application containers & images +# shellcheck disable=SC2046 +docker rm -f $(docker ps -a --no-trunc | egrep "dokku/${APP}:" | awk '{ print $1 }' | xargs) &>/dev/null || true +# shellcheck disable=SC2046 +docker rmi $(docker images -q $IMAGE | xargs) &>/dev/null || true diff --git a/plugins/apps/pre-delete b/plugins/apps/pre-delete index 55ca79e73..c6f563d2c 100755 --- a/plugins/apps/pre-delete +++ b/plugins/apps/pre-delete @@ -1,7 +1,10 @@ #!/usr/bin/env bash set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" + +APP="$1"; CACHE_DIR="$DOKKU_ROOT/$APP/cache" +verify_app_name "$APP" -APP="$1"; IMAGE="dokku/$APP"; CACHE_DIR="$DOKKU_ROOT/$APP/cache" if [[ -d $CACHE_DIR ]]; then docker run --rm -v "$CACHE_DIR:/cache" "$IMAGE" find /cache -depth -mindepth 1 -maxdepth 1 -exec rm -Rf {} \; || true fi diff --git a/plugins/build-env/pre-build b/plugins/build-env/pre-build index 74e11f861..900ee800f 100755 --- a/plugins/build-env/pre-build +++ b/plugins/build-env/pre-build @@ -3,7 +3,8 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_PATH/common/functions" source "$PLUGIN_PATH/config/functions" -APP="$1"; IMAGE="dokku/$APP"; BUILD_ENV="" +APP="$1"; BUILD_ENV="" +verify_app_name "$APP" [[ -f "$DOKKU_ROOT/BUILD_ENV" ]] && cat "$DOKKU_ROOT/BUILD_ENV" >> "$DOKKU_ROOT/ENV" && { dokku_log_info2 "Using a global BUILD_ENV file is deprecated as of 0.3.26" diff --git a/plugins/common/functions b/plugins/common/functions index a55ea466d..7b0111c45 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -114,23 +114,38 @@ dokku_container_log_verbose_quiet() { } verify_app_name() { - local APP="$1" + local APP="$1"; local TAG="$2" [[ ! -n "$APP" ]] && dokku_log_fail "(verify_app_name) APP must not be null" [[ ! -d "$DOKKU_ROOT/$APP" ]] && dokku_log_fail "App $APP does not exist" - IMAGE="dokku/$APP" + + if [[ -n "$TAG" ]]; then + IMAGE="dokku/$APP:$TAG" + else + IMAGE="dokku/$APP" + fi + export IMAGE return 0 } verify_image() { local IMAGE="$1" - DOKKU_APP_IMAGES=$(docker images -q $IMAGE) - if [[ -n "$DOKKU_APP_IMAGES" ]]; then + if (docker inspect "$IMAGE" &>/dev/null); then return 0 else return 1 fi } +get_running_image_tag() { + local APP="$1" + [[ ! -n "$APP" ]] && dokku_log_fail "(get_running_image_tag) APP must not be null" + verify_app_name "$APP" + + CIDS=( $(get_container_ids $APP) ) + RUNNING_IMAGE_TAG=$(docker ps -a --no-trunc | egrep ${CIDS[0]} 2>/dev/null | awk '{ print $2 }' | awk -F: '{ print $2 }' || echo '') + echo $RUNNING_IMAGE_TAG +} + is_image_herokuish_based() { # circleci can't support --rm as they run lxc in lxc [[ ! -f "/home/ubuntu/.circlerc" ]] && local DOCKER_ARGS="--rm" @@ -267,3 +282,23 @@ is_app_running() { return 1 fi } + +release_and_deploy() { + local APP="$1"; local TAG="$2"; verify_app_name "$APP" "$TAG" + + if verify_image "$IMAGE"; then + if is_image_herokuish_based "$IMAGE"; then + IMAGE_SOURCE_TYPE="herokuish" + else + IMAGE_SOURCE_TYPE="dockerfile" + fi + + dokku_log_info1 "Releasing $APP ($IMAGE)..." + dokku release "$APP" "$IMAGE_SOURCE_TYPE" "$TAG" + dokku_log_info1 "Deploying $APP ($IMAGE)..." + dokku deploy "$APP" "$TAG" + dokku_log_info2 "Application deployed:" + dokku urls $APP | sed "s/^/ /" + echo + fi +} diff --git a/plugins/config/docker-args-deploy b/plugins/config/docker-args-deploy index 14263ef96..9fee5b7c6 100755 --- a/plugins/config/docker-args-deploy +++ b/plugins/config/docker-args-deploy @@ -3,8 +3,9 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_PATH/common/functions" source "$PLUGIN_PATH/config/functions" -STDIN=$(cat); APP="$1"; IMAGE="dokku/$APP" +STDIN=$(cat); APP="$1"; TAG="$2" DOCKERFILE_ENV_FILE="$DOKKU_ROOT/$APP/DOCKERFILE_ENV_FILE" +verify_app_name "$APP" "$TAG" if ! is_image_herokuish_based "$IMAGE"; then > "$DOCKERFILE_ENV_FILE" diff --git a/plugins/ps/commands b/plugins/ps/commands index bdebeaa3b..0cc80d937 100755 --- a/plugins/ps/commands +++ b/plugins/ps/commands @@ -6,24 +6,23 @@ source "$(dirname $0)/functions" case "$1" in ps) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - - APP="$2"; CONTAINER_IDS=$(get_app_container_ids $APP) + APP="$2"; verify_app_name "$APP"; local DOKKU_APP_RUNNING_CONTAINER_IDS=$(get_app_running_container_ids $APP) ! (is_deployed $APP) && echo "App $APP has not been deployed" && exit 0 - for CID in $CONTAINER_IDS; do + for CID in $DOKKU_APP_RUNNING_CONTAINER_IDS; do has_tty && DOKKU_RUN_OPTS="-i -t" + dokku_log_info1_quiet "running processes in container: $CID" docker exec $DOKKU_RUN_OPTS $CID /bin/sh -c "ps auxwww" done ;; ps:start) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2"; APP="$2" + APP="$2"; TAG=$(get_running_image_tag "$APP"); verify_app_name "$APP" "$TAG" ! (is_deployed $APP) && echo "App $APP has not been deployed" && exit 0 if ! (is_app_running $APP); then - release_and_deploy $APP + release_and_deploy "$APP" "$TAG" else echo "App $APP already running" fi @@ -31,12 +30,9 @@ case "$1" in ps:stop) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - - APP="$2"; CONTAINER_IDS=$(get_app_container_ids $APP) + APP="$2"; verify_app_name "$APP"; local DOKKU_APP_RUNNING_CONTAINER_IDS=$(get_app_running_container_ids $APP) ! (is_deployed $APP) && echo "App $APP has not been deployed" && exit 0 - DOKKU_APP_RUNNING_CONTAINER_IDS=$(get_app_running_container_ids $APP) if [[ -n "$DOKKU_APP_RUNNING_CONTAINER_IDS" ]]; then echo "Stopping $APP ..." docker stop $DOKKU_APP_RUNNING_CONTAINER_IDS > /dev/null || true @@ -47,8 +43,7 @@ case "$1" in ps:rebuild) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - APP="$2" + APP="$2"; verify_app_name "$APP" pluginhook -p receive-app $APP ;; @@ -65,12 +60,10 @@ case "$1" in ps:restart) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" - - APP="$2" + APP="$2"; TAG=$(get_running_image_tag $APP); verify_app_name "$APP" "$TAG" ! (is_deployed $APP) && echo "App $APP has not been deployed" && exit 0 - release_and_deploy $APP + release_and_deploy "$APP" "$TAG" ;; ps:restartall) @@ -85,18 +78,18 @@ case "$1" in ps:scale) [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 - verify_app_name "$2" + APP="$2"; TAG=$(get_running_image_tag "$APP"); verify_app_name "$APP" "$TAG" - APP="$2"; DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" + DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" shift 2 - generate_scale_file "$APP" + generate_scale_file "$APP" "$TAG" if [[ -z "$@" ]];then dokku_log_info1 "Scaling for $APP" dokku_log_info2 "$(< $DOKKU_SCALE_FILE)" else set_scale "$APP" "$@" - release_and_deploy "$APP" + release_and_deploy "$APP" "$TAG" fi ;; diff --git a/plugins/ps/functions b/plugins/ps/functions index 6517d8259..f54f10101 100755 --- a/plugins/ps/functions +++ b/plugins/ps/functions @@ -2,27 +2,6 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_PATH/common/functions" -release_and_deploy() { - source "$PLUGIN_PATH/common/functions" - local APP="$1"; local IMAGE="dokku/$APP" - - if verify_image "$IMAGE"; then - if is_image_herokuish_based "$IMAGE"; then - IMAGE_SOURCE_TYPE="herokuish" - else - IMAGE_SOURCE_TYPE="dockerfile" - fi - - dokku_log_info1 "Releasing $APP ..." - dokku release "$APP" "$IMAGE_SOURCE_TYPE" - dokku_log_info1 "Deploying $APP ..." - dokku deploy "$APP" - dokku_log_info2 "Application deployed:" - dokku urls $APP | sed "s/^/ /" - echo - fi -} - print_dokku_scale_file(){ local APP="$1"; local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" while read line || [ -n "$line" ] @@ -32,7 +11,8 @@ print_dokku_scale_file(){ } generate_scale_file() { - local APP="$1"; local IMAGE="dokku/$APP"; local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" + local APP="$1"; local TAG="$3"; local DOKKU_SCALE_FILE="$DOKKU_ROOT/$APP/DOKKU_SCALE" + verify_app_name "$APP" "$TAG" copy_from_image "$IMAGE" "/app/DOKKU_SCALE" "$DOKKU_ROOT/$APP" 2>/dev/null || true if [[ ! -f $DOKKU_SCALE_FILE ]]; then dokku_log_info1_quiet "DOKKU_SCALE file not found in app image. Defaulting to a single web process" @@ -62,4 +42,3 @@ set_scale() { fi done } - diff --git a/plugins/tag/commands b/plugins/tag/commands new file mode 100755 index 000000000..f035cbca4 --- /dev/null +++ b/plugins/tag/commands @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" +source "$(dirname $0)/functions" + +case "$1" in + tag:add) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + APP="$2"; TAG="$3" + verify_app_name "$APP" + verify_image "$IMAGE" || dokku_log_fail "App image ($IMAGE) not found" + + tag_image "$IMAGE:latest" "$IMAGE:$TAG" + dokku_log_info2_quiet "Added $TAG tag to $IMAGE" + ;; + + tag:deploy) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + APP="$2"; TAG="$3" + verify_app_name "$APP" + verify_image "$IMAGE:$TAG" || dokku_log_fail "App image ($IMAGE:$TAG) not found" + + release_and_deploy $APP $TAG + ;; + + tag:list) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + APP="$2"; verify_app_name "$APP" + + dokku_log_info2_quiet "Image tags for $IMAGE" + docker images "$IMAGE" + ;; + + tag:rm) + [[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1 + APP="$2"; TAG="$3" + verify_app_name "$2" + + case "$TAG" in + latest) + dokku_log_fail "You can't remove internal dokku tag ($TAG) for $IMAGE" + ;; + + *) + docker rmi "$IMAGE:$TAG" + ;; + esac + ;; + + help | tag:help) + cat && cat< Add tag to latest running app image + tag:deploy Deploy tagged app image + tag:list List all app image tags + tag:rm Remove app image tag +EOF + ;; + + *) + exit $DOKKU_NOT_IMPLEMENTED_EXIT + ;; + +esac diff --git a/plugins/tag/functions b/plugins/tag/functions new file mode 100755 index 000000000..717eefb8c --- /dev/null +++ b/plugins/tag/functions @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(dirname $0)/../common/functions" + +tag_image() { + docker tag -f "$1" "$2" +} diff --git a/tests/unit/tag.bats b/tests/unit/tag.bats new file mode 100644 index 000000000..879f1ef8c --- /dev/null +++ b/tests/unit/tag.bats @@ -0,0 +1,47 @@ +#!/usr/bin/env bats + +load test_helper + +setup() { + deploy_app +} + +teardown() { + destroy_app +} + +@test "(tag) tag:add, tag:list, tag:rm" { + run /bin/bash -c "dokku tag:add $TEST_APP v0.9.0" + echo "output: "$output + echo "status: "$status + assert_success + run /bin/bash -c "dokku tag:list $TEST_APP | egrep -q 'v0.9.0'" + echo "output: "$output + echo "status: "$status + assert_success + + run /bin/bash -c "dokku tag:rm $TEST_APP v0.9.0" + echo "output: "$output + echo "status: "$status + assert_success + run /bin/bash -c "dokku tag:list $TEST_APP | egrep -q 'v0.9.0'" + echo "output: "$output + echo "status: "$status + assert_failure + +} + +@test "(tag) tag:deploy" { + run /bin/bash -c "dokku tag:add $TEST_APP v0.9.0" + echo "output: "$output + echo "status: "$status + assert_success + run /bin/bash -c "dokku tag:deploy $TEST_APP v0.9.0" + echo "output: "$output + echo "status: "$status + assert_success + run /bin/bash -c "docker ps | egrep '/start web'| egrep -q dokku/node-js-app:v0.9.0" + echo "output: "$output + echo "status: "$status + assert_success +}