Merge pull request #894 from progrium/dokku-client

Dokku client
This commit is contained in:
Jose Diaz-Gonzalez
2015-01-18 17:43:09 -05:00
6 changed files with 323 additions and 41 deletions

View File

@@ -1,32 +1,112 @@
if [ -z "$DOKKU_HOST" ]
then
function dokku {
appname=$(git remote -v 2>/dev/null | grep dokku | head -n 1 | cut -f1 -d' ' | cut -f2 -d':' 2>/dev/null)
if [ "$?" != "0" ]
then
donotshift="YES"
fi
if [ "$1" = "create" ]
then
appname=$(echo "print(elfs.GenName())" | lua -l elfs)
if git remote add dokku dokku@$DOKKU_HOST:$appname
then
echo "-----> Dokku remote added at $DOKKU_HOST"
echo "-----> Application name is $appname"
else
echo "! Dokku remote not added! Do you already have a dokku remote?"
return
fi
git push dokku master
else
if [ -z "$donotshift" ]
then
ssh dokku@$DOKKU_HOST $*
exit
fi
verb=$1
shift
ssh dokku@$DOKKU_HOST "$verb" "$appname" $@
fi
}
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
MOVES=(ABLE ABNORMA AGAIN AIREXPL ANG ANGER ASAIL ATTACK AURORA AWL BAN BAND BARE BEAT BEATED BELLY BIND BITE BLOC BLOOD BODY BOOK BREATH BUMP CAST CHAM CLAMP CLAP CLAW CLEAR CLI CLIP CLOUD CONTRO CONVY COOLHIT CRASH CRY CUT DESCRI D-FIGHT DIG DITCH DIV DOZ DRE DUL DU-PIN DYE EARTH EDU EG-BOMB EGG ELEGY ELE-HIT EMBODY EMPLI ENGL ERUPT EVENS EXPLOR EYES FALL FAST F-CAR F-DANCE FEARS F-FIGHT FIGHT FIR FIRE FIREHIT FLAME FLAP FLASH FLEW FORCE FRA FREEZE FROG G-BIRD GENKISS GIFT G-KISS G-MOUSE GRADE GROW HAMMER HARD HAT HATE H-BOMB HELL-R HEMP HINT HIT HU HUNT HYPNOSI INHA IRO IRONBAR IR-WING J-GUN KEE KICK KNIF KNIFE KNOCK LEVEL LIGH LIGHHIT LIGHT LIVE L-WALL MAD MAJUS MEL MELO MESS MILK MIMI MISS MIXING MOVE MUD NI-BED NOISY NOONLI NULL N-WAVE PAT PEACE PIN PLAN PLANE POIS POL POWDE POWE POWER PRIZE PROTECT PROUD RAGE RECOR REFLAC REFREC REGR RELIV RENEW R-FIGHT RING RKICK ROCK ROUND RUS RUSH SAND SAW SCISSOR SCRA SCRIPT SEEN SERVER SHADOW SHELL SHINE SHO SIGHT SIN SMALL SMELT SMOK SNAKE SNO SNOW SOU SO-WAVE SPAR SPEC SPID S-PIN SPRA STAM STARE STEA STONE STORM STRU STRUG STUDEN SUBS SUCID SUN-LIG SUNRIS SUPLY S-WAVE TAILS TANGL TASTE TELLI THANK TONKICK TOOTH TORL TRAIN TRIKICK TUNGE VOLT WA-GUN WATCH WAVE W-BOMB WFALL WFING WHIP WHIRL WIND WOLF WOOD WOR YUJA)
NAMES=(SEED GRASS FLOWE SHAD CABR SNAKE GOLD COW GUIKI PEDAL DELAN B-FLY BIDE KEYU FORK LAP PIGE PIJIA CAML LAT BIRD BABOO VIV ABOKE PIKAQ RYE SAN BREAD LIDEL LIDE PIP PIKEX ROK JUGEN PUD BUDE ZHIB GELU GRAS FLOW LAFUL ATH BALA CORN MOLUF DESP DAKED MIMI BOLUX KODA GELUD MONK SUMOY GEDI WENDI NILEM NILE NILEC KEZI YONGL HUDE WANLI GELI GUAIL MADAQ WUCI WUCI MUJEF JELLY SICIB GELU NELUO BOLI JIALE YED YEDE CLO SCARE AOCO DEDE DEDEI BAWU JIUG BADEB BADEB HOLE BALUX GES FANT QUAR YIHE SWAB SLIPP CLU DEPOS BILIY YUANO SOME NO YELA EMPT ZECUN XIAHE BOLEL DEJI MACID XIHON XITO LUCK MENJI GELU DECI XIDE DASAJ DONGN RICUL MINXI BALIY ZENDA LUZEL HELE5 0FENB KAIL JIAND CARP JINDE LAPU MUDE YIFU LINLI SANDI HUSI JINC OUMU OUMUX CAP KUIZA PUD TIAO FRMAN CLAU SPARK DRAGO BOLIU GUAIL MIYOU MIY QIAOK BEIL MUKEI RIDED MADAM BAGEP CROC ALIGE OUDAL OUD DADA HEHE YEDEA NUXI NUXIN ROUY ALIAD STICK QIANG LAAND PIQI PI PUPI DEKE DEKEJ NADI NADIO MALI PEA ELECT FLOWE MAL MALI HUSHU NILEE YUZI POPOZ DUZI HEBA XIAN SHAN YEYEA WUY LUO KEFE HULA CROW YADEH MOW ANNAN SUONI KYLI HULU HUDEL YEHE GULAE YEHE BLU GELAN BOAT NIP POIT HELAK XINL BEAR LINB MAGEH MAGEJ WULI YIDE RIVE FISH AOGU DELIE MANTE KONMU DELU HELU HUAN HUMA DONGF JINCA HEDE DEFU LIBY JIAPA MEJI HELE BUHU MILK HABI THUN GARD DON YANGQ SANAQ BANQ LUJ PHIX SIEI EGG)
function random_number() {
[[ -n "$1" ]] && RANGE="$1"
if [[ -n "$RANGE" ]];then
number=$RANDOM
let "number %= $RANGE"
else
number=$RANDOM
fi
echo $number
}
function random_name() {
NUM1=$(random_number ${#MOVES[@]})
NUM2=$(random_number ${#MOVES[@]})
NUM3=$(random_number ${#NAMES[@]})
UPPER_APPNAME="${MOVES[${NUM1}]}-${MOVES[${NUM2}]}-${NAMES[${NUM3}]}"
[[ "$BASH_VERSION" =~ 4.* ]] && lower_appname=${UPPER_APPNAME,,}
[[ -z "$lower_appname" ]] && lower_appname=$(echo $UPPER_APPNAME | tr '[:upper:]' '[:lower:]')
echo "$lower_appname"
}
function client_help_msg() {
echo "==> Configure the DOKKU_HOST environment variable or run $0 from a repository with a git remote named dokku"
echo "--> i.e. git remote add dokku dokku@<dokku-host>:<app-name>"
exit 20 # exit with specific status. only used in units tests for now
}
if [[ -z $DOKKU_HOST ]]; then
if [[ -d .git ]] || git rev-parse --git-dir > /dev/null 2>&1; then
DOKKU_HOST=$(git remote -v 2>/dev/null | grep -Ei "^dokku" | head -n 1 | cut -f1 -d' ' | cut -f2 -d '@' | cut -f1 -d':' 2>/dev/null || true)
else
client_help_msg
fi
fi
if [[ ! -z $DOKKU_HOST ]]; then
function _dokku {
appname=""
if [[ -d .git ]] || git rev-parse --git-dir > /dev/null 2>&1; then
set +e
appname=$(git remote -v 2>/dev/null | grep -Ei "^dokku" | head -n 1 | cut -f1 -d' ' | cut -f2 -d':' 2>/dev/null)
set -e
else
echo "This is not a git repository"
fi
if [[ "$appname" != "" ]] && [[ -n "$*" ]]; then
case "$1" in
apps|backup*|help|plugins*|ps:restartall|trace|version)
true
;;
apps:destroy)
if [[ -z "$2" ]] || [[ "$2" == "force" ]];then
donotshift="YES"
fi
;;
*)
donotshift="YES"
;;
esac
fi
if [[ "$1" = "apps:create" ]] && [[ -z "$2" ]]; then
appname=$(random_name)
counter=0
while ssh "dokku@$DOKKU_HOST" apps 2>/dev/null| grep -q "$appname"; do
if [[ $counter -ge 100 ]];then
echo "Error: could not reasonably generate a new app name. try cleaning up some apps..."
ssh "dokku@$DOKKU_HOST" apps
exit 1
else
appname=$(random_name)
counter=$((counter+1))
fi
done
if git remote add dokku "dokku@$DOKKU_HOST:$appname"
then
echo "-----> Dokku remote added at $DOKKU_HOST"
echo "-----> Application name is $appname"
else
echo "! Dokku remote not added! Do you already have a dokku remote?"
return
fi
git push dokku master
return $?
fi
if [[ -z "$donotshift" ]]; then
ssh "dokku@$DOKKU_HOST" "$@"
exit $?
fi
[[ -z "$verb" ]] && verb=$1
shift
ssh "dokku@$DOKKU_HOST" "$verb" "$appname" "$@"
}
if [[ "$0" == "dokku" ]] || [[ "$0" == *dokku_client.sh ]]; then
_dokku "$@"
exit $?
fi
else
client_help_msg
fi

View File

@@ -20,17 +20,19 @@ case "$1" in
[[ -z $2 ]] && echo "Please specify an app to run the command on" && exit 1
[[ ! -d "$DOKKU_ROOT/$2" ]] && echo "App $2 does not exist" && exit 1
[[ "$2" == "tls" ]] && echo "Unable to destroy tls directory" && exit 1
APP="$2"; IMAGE="dokku/$APP";
APP="$2"; IMAGE="dokku/$APP"; FORCE="$3"
echo " ! WARNING: Potentially Destructive Action"
echo " ! This command will destroy $APP (including all add-ons)."
echo " ! To proceed, type \"$APP\""
echo ""
if [[ "$FORCE" != "force" ]]; then
echo " ! WARNING: Potentially Destructive Action"
echo " ! This command will destroy $APP (including all add-ons)."
echo " ! To proceed, type \"$APP\""
echo ""
read -p "> " app_name
if [[ "$app_name" != "$APP" ]]; then
echo " ! Confirmation did not match $APP. Aborted."
exit 1
read -p "> " app_name
if [[ "$app_name" != "$APP" ]]; then
echo " ! Confirmation did not match $APP. Aborted."
exit 1
fi
fi
echo "Destroying $APP (including all add-ons)"

View File

@@ -56,7 +56,8 @@ lint:
# SC2143: Instead of [ -n $(foo | grep bar) ], use foo | grep -q bar - https://github.com/koalaman/shellcheck/wiki/SC2143
# SC2001: See if you can use ${variable//search/replace} instead. - https://github.com/koalaman/shellcheck/wiki/SC2001
@echo linting...
@$(QUIET) find . -not -path '*/\.*' | xargs file | egrep "shell|bash" | awk '{ print $$1 }' | sed 's/://g' | xargs shellcheck -e SC2034,SC2086,SC2143,SC2001
@$(QUIET) shellcheck -e SC2029 ./contrib/dokku_client.sh
@$(QUIET) find . -not -path '*/\.*' | xargs file | egrep "shell|bash" | awk '{ print $$1 }' | sed 's/://g' | grep -v dokku_client.sh | xargs shellcheck -e SC2034,SC2086,SC2143,SC2001
unit-tests:
@echo running unit tests...

178
tests/unit/client.bats Normal file
View File

@@ -0,0 +1,178 @@
#!/usr/bin/env bats
load test_helper
setup() {
export DOKKU_HOST=dokku.me
create_app
}
teardown() {
destroy_app
unset DOKKU_HOST
}
@test "dokku client (unconfigured DOKKU_HOST)" {
unset DOKKU_HOST
run ./contrib/dokku_client.sh apps
echo "output: "$output
echo "status: "$status
assert_exit_status 20
}
@test "dokku client (no args should print help)" {
run /bin/bash -c "./contrib/dokku_client.sh | head -1 | grep -q 'dokku COMMAND <app>'"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (apps:create)" {
destroy_app
run ./contrib/dokku_client.sh apps:create $TEST_APP
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (apps:destroy)" {
run ./contrib/dokku_client.sh apps:destroy $TEST_APP force
echo "output: "$output
echo "status: "$status
assert_success
create_app # prevent teardown() failure
}
@test "dokku client (config:set)" {
run ./contrib/dokku_client.sh config:set $TEST_APP test_var=true test_var2=\"hello world\"
echo "output: "$output
echo "status: "$status
assert_success
run /bin/bash -c "./contrib/dokku_client.sh config:get $TEST_APP test_var2 | grep -q 'hello world'"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (config:unset)" {
run ./contrib/dokku_client.sh config:set $TEST_APP test_var=true test_var2=\"hello world\"
echo "output: "$output
echo "status: "$status
assert_success
run ./contrib/dokku_client.sh config:get $TEST_APP test_var
echo "output: "$output
echo "status: "$status
assert_success
run ./contrib/dokku_client.sh config:unset $TEST_APP test_var
echo "output: "$output
echo "status: "$status
assert_success
run /bin/bash -c "./contrib/dokku_client.sh config:get $TEST_APP test_var | grep test_var"
echo "output: "$output
echo "status: "$status
assert_failure
}
@test "dokku client (domains)" {
run bash -c "./contrib/dokku_client.sh domains $TEST_APP | grep -q ${TEST_APP}.dokku.me"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (domains:add)" {
run ./contrib/dokku_client.sh domains:add $TEST_APP www.test.app.dokku.me
echo "output: "$output
echo "status: "$status
assert_success
run ./contrib/dokku_client.sh domains:add $TEST_APP test.app.dokku.me
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (domains:remove)" {
run ./contrib/dokku_client.sh domains:add $TEST_APP test.app.dokku.me
echo "output: "$output
echo "status: "$status
assert_success
run ./contrib/dokku_client.sh domains:remove $TEST_APP test.app.dokku.me
echo "output: "$output
echo "status: "$status
refute_line "test.app.dokku.me"
}
@test "dokku client (domains:clear)" {
run ./contrib/dokku_client.sh domains:add $TEST_APP test.app.dokku.me
echo "output: "$output
echo "status: "$status
assert_success
run ./contrib/dokku_client.sh domains:clear $TEST_APP
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (ps)" {
# CI support: 'Ah. I just spoke with our Docker expert --
# looks like docker exec is built to work with docker-under-libcontainer,
# but we're using docker-under-lxc. I don't have an estimated time for the fix, sorry
skip "circleci does not support docker exec at the moment."
deploy_app
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh ps $TEST_APP | grep -q 'node web.js'"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (ps:start)" {
deploy_app
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh ps:stop $TEST_APP"
echo "output: "$output
echo "status: "$status
assert_success
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh ps:start $TEST_APP"
echo "output: "$output
echo "status: "$status
assert_success
run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (ps:stop)" {
deploy_app
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh ps:stop $TEST_APP"
echo "output: "$output
echo "status: "$status
assert_success
run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)"
echo "output: "$output
echo "status: "$status
assert_failure
}
@test "dokku client (ps:restart)" {
deploy_app
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh ps:restart $TEST_APP"
echo "output: "$output
echo "status: "$status
assert_success
run bash -c "docker ps -q --no-trunc | grep -q $(< $DOKKU_ROOT/$TEST_APP/CONTAINER)"
echo "output: "$output
echo "status: "$status
assert_success
}
@test "dokku client (apps:create AND apps:destroy)" {
setup_client_repo
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh apps:create"
echo "output: "$output
echo "status: "$status
assert_success
run bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh apps:destroy force"
echo "output: "$output
echo "status: "$status
assert_success
}

View File

@@ -21,6 +21,7 @@ teardown() {
run ssh dokku@dokku.me config:set $TEST_APP test_var=true test_var2=\"hello world\"
echo "output: "$output
echo "status: "$status
assert_success
run dokku config:get $TEST_APP test_var2
echo "output: "$output
echo "status: "$status
@@ -31,12 +32,15 @@ teardown() {
run ssh dokku@dokku.me config:set $TEST_APP test_var=true test_var2=\"hello world\"
echo "output: "$output
echo "status: "$status
assert_success
run dokku config:get $TEST_APP test_var
echo "output: "$output
echo "status: "$status
assert_success
run dokku config:unset $TEST_APP test_var
echo "output: "$output
echo "status: "$status
assert_success
run dokku config:get $TEST_APP test_var
echo "output: "$output
echo "status: "$status

View File

@@ -79,6 +79,10 @@ assert() {
fi
}
assert_exit_status() {
assert_equal "$status" "$1"
}
# dokku functions
create_app() {
dokku apps:create $TEST_APP
@@ -103,6 +107,19 @@ deploy_app() {
git push target master || destroy_app
}
setup_client_repo() {
TMP=$(mktemp -d -t "$TARGET.XXXXX")
rmdir $TMP && cp -r ./tests/apps/nodejs-express $TMP
cd $TMP
git init
git config user.email "robot@example.com"
git config user.name "Test Robot"
[[ -f gitignore ]] && mv gitignore .gitignore
git add .
git commit -m 'initial commit'
}
setup_test_tls() {
TLS="/home/dokku/$TEST_APP/tls"
mkdir -p $TLS