Merge pull request #27 from dokku/lg-export-config

Revamp link/unlink commands
This commit is contained in:
Jose Diaz-Gonzalez
2015-09-28 12:26:48 -04:00
12 changed files with 217 additions and 114 deletions

View File

@@ -22,7 +22,6 @@ dokku plugin:install https://github.com/dokku/dokku-postgres.git postgres
## commands
```
postgres:alias <name> <alias> Set an alias for the docker link
postgres:clone <name> <new-name> Create container <new-name> then copy data from <name> into <new-name>
postgres:connect <name> Connect via psql to a postgres service
postgres:create <name> Create a postgres service
@@ -34,6 +33,7 @@ postgres:info <name> Print the connection information
postgres:link <name> <app> Link the postgres service to the app
postgres:list List all postgres services
postgres:logs <name> [-t] Print the most recent log(s) for this service
postgres:promote <name> <app> Promote service <name> as DATABASE_URL in <app>
postgres:restart <name> Graceful shutdown and restart of the postgres service container
postgres:start <name> Start a previously stopped postgres service
postgres:stop <name> Stop a running postgres service
@@ -57,8 +57,6 @@ dokku postgres:create lolipop
# get connection information as follows
dokku postgres:info lolipop
# lets assume the ip of our postgres service is 172.17.0.1
# a postgres service can be linked to a
# container this will use native docker
# links via the docker-options plugin
@@ -68,24 +66,42 @@ dokku postgres:link lolipop playground
# the above will expose the following environment variables
#
# DATABASE_URL=postgres://postgres:SOME_PASSWORD@172.17.0.1:5432/lolipop
# DATABASE_NAME=/lolipop/DATABASE
# DATABASE_PORT=tcp://172.17.0.1:5432
# DATABASE_PORT_5432_TCP=tcp://172.17.0.1:5432
# DATABASE_PORT_5432_TCP_PROTO=tcp
# DATABASE_PORT_5432_TCP_PORT=5432
# DATABASE_PORT_5432_TCP_ADDR=172.17.0.1
# DOKKU_POSTGRES_LOLIPOP_NAME=/lolipop/DATABASE
# DOKKU_POSTGRES_LOLIPOP_PORT=tcp://172.17.0.1:5432
# DOKKU_POSTGRES_LOLIPOP_PORT_5432_TCP=tcp://172.17.0.1:5432
# DOKKU_POSTGRES_LOLIPOP_PORT_5432_TCP_PROTO=tcp
# DOKKU_POSTGRES_LOLIPOP_PORT_5432_TCP_PORT=5432
# DOKKU_POSTGRES_LOLIPOP_PORT_5432_TCP_ADDR=172.17.0.1
#
# and the following will be set on the linked application by default
#
# DATABASE_URL=postgres://postgres:SOME_PASSWORD@dokku-postgres-lolipop:5432/lolipop
#
# NOTE: the host exposed here only works internally in docker containers. If
# you want your container to be reachable from outside, you should use `expose`.
# you can examine the environment variables
# using our 'playground' app's env command
dokku run playground env
# another service can be linked to your app
dokku postgres:link other_service playground
# you can customize the environment
# variables through a custom docker link alias
dokku postgres:alias lolipop POSTGRES_DATABASE
# since DATABASE_URL is already in use, another environment variable will be
# generated automatically
#
# DOKKU_POSTGRES_BLUE_URL=postgres://postgres:ANOTHER_PASSWORD@dokku-postgres-other_service:5432/other_service
# you can then promote the new service to be the primary one
# NOTE: this will restart your app
dokku postgres:promote other_service playground
# this will replace DATABASE_URL with the url from other_service and generate
# another environment variable to hold the previous value if necessary.
# you could end up with the following for example:
#
# DATABASE_URL=postgres://postgres:ANOTHER_PASSWORD@dokku-postgres-other_service:5432/other_service
# DOKKU_POSTGRES_BLUE_URL=postgres://postgres:ANOTHER_PASSWORD@dokku-postgres-other_service:5432/other_service
# DOKKU_POSTGRES_SILVER_URL=postgres://postgres:SOME_PASSWORD@dokku-postgres-lolipop:5432/lolipop
# you can also unlink a postgres service
# NOTE: this will restart your app
# NOTE: this will restart your app and unset related environment variables
dokku postgres:unlink lolipop playground
# you can tail logs for a particular service

View File

@@ -16,13 +16,6 @@ if [[ $1 == $PLUGIN_COMMAND_PREFIX:* ]]; then
fi
case "$1" in
$PLUGIN_COMMAND_PREFIX:alias)
[[ -z $2 ]] && dokku_log_fail "Please specify a name for the service"
[[ -z $3 ]] && dokku_log_fail "Please specify an alias for the service"
verify_service_name "$2"
service_set_alias "$2" "$3"
;;
$PLUGIN_COMMAND_PREFIX:create)
[[ -z $2 ]] && dokku_log_fail "Please specify a name for the service"
[[ ! -d "$PLUGIN_DATA_ROOT/$2" ]] || dokku_log_fail "$PLUGIN_SERVICE service $2 already exists"
@@ -206,9 +199,16 @@ case "$1" in
service_port_unexpose "$2"
;;
$PLUGIN_COMMAND_PREFIX:promote)
[[ -z $2 ]] && dokku_log_fail "Please specify a name for the service"
[[ -z $3 ]] && dokku_log_fail "Please specify an app to run the command on"
verify_service_name "$2"
verify_app_name "$3"
promote "$2" "$3"
;;
help | $PLUGIN_COMMAND_PREFIX:help)
HELP=$(cat<<EOF
$PLUGIN_COMMAND_PREFIX:alias <name> <alias>, Set an alias for the docker link
$PLUGIN_COMMAND_PREFIX:create <name>, Create a $PLUGIN_SERVICE service
$PLUGIN_COMMAND_PREFIX:destroy <name>, Delete the $PLUGIN_SERVICE service and stop its container if there are no links left
$PLUGIN_COMMAND_PREFIX:link <name> <app>, Link the $PLUGIN_SERVICE service to the app
@@ -225,6 +225,7 @@ case "$1" in
$PLUGIN_COMMAND_PREFIX:unexpose <name>, Unexpose a previously exposed $PLUGIN_SERVICE service
$PLUGIN_COMMAND_PREFIX:start <name>, Start a previously stopped $PLUGIN_SERVICE service
$PLUGIN_COMMAND_PREFIX:stop <name>, Stop a running $PLUGIN_SERVICE service
$PLUGIN_COMMAND_PREFIX:promote <name> <app>, Promote service <name> as ${PLUGIN_DEFAULT_ALIAS}_URL in <app>
EOF
)
if [[ -n $DOKKU_API_VERSION ]]; then

1
config
View File

@@ -7,6 +7,7 @@ export PLUGIN_COMMAND_PREFIX="postgres"
export PLUGIN_DATA_ROOT=$POSTGRES_ROOT
export PLUGIN_DATASTORE_PORTS=(5432)
export PLUGIN_DEFAULT_ALIAS="DATABASE"
export PLUGIN_ALT_ALIAS="DOKKU_POSTGRES"
export PLUGIN_IMAGE=$POSTGRES_IMAGE
export PLUGIN_IMAGE_VERSION=$POSTGRES_IMAGE_VERSION
export PLUGIN_SCHEME="postgres"

View File

@@ -1 +0,0 @@
docker-args-deploy

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env bash
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
PLUGIN_BASE_PATH="$PLUGIN_PATH"
if [[ -n $DOKKU_API_VERSION ]]; then
PLUGIN_BASE_PATH="$PLUGIN_ENABLED_PATH"
fi
source "$PLUGIN_BASE_PATH/common/functions"
source "$(dirname "$0")/functions"
source "$(dirname "$0")/config"
STDIN=$(cat)
APP="$1"
output=""
for i in $PLUGIN_DATA_ROOT/*; do
[[ -d $i ]] || continue
SERVICE=$(echo "$i" | cut -d'/' -f 7)
LINKS_FILE="$PLUGIN_DATA_ROOT/$SERVICE/LINKS"
ALIAS="$(service_alias "$SERVICE")"
SERVICE_URL="$(service_url "$SERVICE")"
if [[ -f "$LINKS_FILE" ]]; then
while read line; do
if [[ "$line" == "$APP" ]]; then
output="$output --link dokku.postgres.$SERVICE:$ALIAS --env ${ALIAS}_URL=$SERVICE_URL"
break
fi
done < "$LINKS_FILE"
fi
done
echo "$STDIN$output"

View File

@@ -1 +0,0 @@
docker-args-deploy

View File

@@ -32,14 +32,8 @@ verify_service_name() {
service_alias() {
local SERVICE="$1"
local ALIAS_FILE="$PLUGIN_DATA_ROOT/$SERVICE/ALIAS"
verify_service_name "$1"
if [[ -f "$ALIAS_FILE" ]]; then
cat "$ALIAS_FILE"
else
echo "$PLUGIN_DEFAULT_ALIAS"
fi
local SERVICE_NAME=$(get_service_name "$SERVICE")
echo "$SERVICE_NAME" | tr . -
}
service_info() {
@@ -77,16 +71,45 @@ service_exposed_ports() {
service_link() {
local APP="$2"
local SERVICE="$1"
local SERVICE_URL=$(service_url "$SERVICE")
local SERVICE_NAME=$(get_service_name "$SERVICE")
local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
local EXISTING_CONFIG=$(dokku config "$APP")
local DATABASE_NAME=$(get_database_name "$SERVICE")
local LINK=$(echo "$EXISTING_CONFIG" | grep "$PLUGIN_SCHEME://.*/$DATABASE_NAME" | cut -d: -f1) || true
local DEFAULT_ALIAS=$(echo "$EXISTING_CONFIG" | grep "${PLUGIN_DEFAULT_ALIAS}_URL") || true
local SERVICE_ALIAS=$(service_alias "$SERVICE")
local LINKS_FILE="$SERVICE_ROOT/LINKS"
[[ -n $LINK ]] && dokku_log_fail "Already linked as $LINK"
mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory"
touch "$LINKS_FILE"
echo "$APP" >> "$LINKS_FILE"
sort "$LINKS_FILE" -u -o "$LINKS_FILE"
dokku_log_info1 "Restarting app $APP"
dokku ps:restart "$APP"
local ALIAS="$PLUGIN_DEFAULT_ALIAS"
if [[ -n $DEFAULT_ALIAS ]]; then
ALIAS=$(service_alternative_alias "$EXISTING_CONFIG")
fi
dokku docker-options:add "$APP" build,deploy,run "--link $SERVICE_NAME:$SERVICE_ALIAS"
dokku config:set "$APP" "${ALIAS}_URL=$SERVICE_URL"
}
service_alternative_alias() {
local EXISTING_CONFIG="$1"
local COLORS=(AQUA BLACK BLUE FUCHSIA GRAY GREEN LIME MAROON NAVY OLIVE PURPLE RED SILVER TEAL WHITE YELLOW)
local ALIAS;
while [[ -z $ALIAS ]]; do
local IDX=$((RANDOM % ${#COLORS[*]}))
local COLOR=${COLORS[IDX]}
ALIAS="${PLUGIN_ALT_ALIAS}_${COLOR}"
local IN_USE=$(echo "$EXISTING_CONFIG" | grep "${ALIAS}_URL")
if [[ -n $IN_USE ]]; then
unset ALIAS
fi
done
echo "$ALIAS"
}
service_logs() {
@@ -232,27 +255,33 @@ service_stop() {
service_unlink() {
local APP="$2"
local SERVICE="$1"
local SERVICE_URL=$(service_url "$SERVICE")
local SERVICE_NAME=$(get_service_name "$SERVICE")
local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
local EXISTING_CONFIG=$(dokku config "$APP")
local DATABASE_NAME=$(get_database_name "$SERVICE")
local SERVICE_ALIAS=$(service_alias "$SERVICE")
local LINK=($(echo "$EXISTING_CONFIG" | grep "$PLUGIN_SCHEME://.*/$DATABASE_NAME" | cut -d: -f1)) || true
local LINKS_FILE="$SERVICE_ROOT/LINKS"
[[ -z ${LINK[*]} ]] && dokku_log_fail "Not linked to app $APP"
mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory"
touch "$LINKS_FILE"
sed -i "/^$APP\$/d" "$LINKS_FILE"
sort "$LINKS_FILE" -u -o "$LINKS_FILE"
dokku_log_info1 "Restarting app $APP"
dokku ps:restart "$APP"
dokku docker-options:remove "$APP" build,deploy,run "--link $SERVICE_NAME:$SERVICE_ALIAS"
dokku config:unset "$APP" "${LINK[*]}"
}
service_url() {
local SERVICE="$1"
local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"
local ID="$(cat "$SERVICE_ROOT/ID")"
local IP="$(get_container_ip "$ID")"
local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")"
local DATABASE_NAME="$(get_database_name $SERVICE)"
echo "$PLUGIN_SCHEME://postgres:$PASSWORD@$IP:${PLUGIN_DATASTORE_PORTS[0]}/$DATABASE_NAME"
local DATABASE_NAME="$(get_database_name "$SERVICE")"
local SERVICE_ALIAS="$(service_alias "$SERVICE")"
echo "$PLUGIN_SCHEME://postgres:$PASSWORD@$SERVICE_ALIAS:${PLUGIN_DATASTORE_PORTS[0]}/$DATABASE_NAME"
}
is_container_status () {
@@ -283,3 +312,34 @@ service_version() {
local SERVICE_NAME="$(get_service_name "$SERVICE")"
docker inspect -f '{{.Config.Image}}' "$SERVICE_NAME"
}
get_url_from_config() {
local EXISTING_CONFIG="$1"
local CONFIG_VAR="$2"
echo "$EXISTING_CONFIG" | grep "$CONFIG_VAR" | sed "s/$CONFIG_VAR:\s*//"
}
promote() {
local SERVICE="$1"
local APP="$2"
local PLUGIN_DEFAULT_CONFIG_VAR="${PLUGIN_DEFAULT_ALIAS}_URL"
local EXISTING_CONFIG=$(dokku config "$APP")
local DATABASE_NAME=$(get_database_name "$SERVICE")
local CONFIG_VARS=($(echo "$EXISTING_CONFIG" | grep "$PLUGIN_SCHEME://.*/$DATABASE_NAME" | cut -d: -f1)) || true
local PREVIOUS_DEFAULT_URL=$(get_url_from_config "$EXISTING_CONFIG" "$PLUGIN_DEFAULT_CONFIG_VAR")
[[ -z ${CONFIG_VARS[*]} ]] && dokku_log_fail "Not linked to app $APP"
[[ ${CONFIG_VARS[*]} =~ $PLUGIN_DEFAULT_CONFIG_VAR ]] && dokku_log_fail "Service $1 already promoted as $PLUGIN_DEFAULT_CONFIG_VAR"
local NEW_CONFIG_VARS=""
if [[ -n $PREVIOUS_DEFAULT_URL ]]; then
local PREVIOUS_ALIAS=$(echo "$EXISTING_CONFIG" | grep "$PREVIOUS_DEFAULT_URL" | grep -v "$PLUGIN_DEFAULT_CONFIG_VAR") || true
if [[ -z $PREVIOUS_ALIAS ]]; then
local ALIAS=$(service_alternative_alias "$EXISTING_CONFIG")
NEW_CONFIG_VARS+="${ALIAS}_URL=$PREVIOUS_DEFAULT_URL "
fi
fi
local PROMOTE_URL=$(get_url_from_config "$EXISTING_CONFIG" "${CONFIG_VARS[0]}")
NEW_CONFIG_VARS+="$PLUGIN_DEFAULT_CONFIG_VAR=$PROMOTE_URL"
dokku config:set "$APP" $NEW_CONFIG_VARS
}

View File

@@ -1,32 +0,0 @@
#!/usr/bin/env bats
load test_helper
setup() {
dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2
}
teardown() {
dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2
}
@test "($PLUGIN_COMMAND_PREFIX:alias) error when there are no arguments" {
run dokku "$PLUGIN_COMMAND_PREFIX:alias"
assert_contains "${lines[*]}" "Please specify a name for the service"
}
@test "($PLUGIN_COMMAND_PREFIX:alias) error when alias is missing" {
run dokku "$PLUGIN_COMMAND_PREFIX:alias" l
assert_contains "${lines[*]}" "Please specify an alias for the service"
}
@test "($PLUGIN_COMMAND_PREFIX:alias) error when service does not exist" {
run dokku "$PLUGIN_COMMAND_PREFIX:alias" not_existing_service MY_ALIAS
assert_contains "${lines[*]}" "service not_existing_service does not exist"
}
@test "($PLUGIN_COMMAND_PREFIX:alias) success" {
run dokku "$PLUGIN_COMMAND_PREFIX:alias" l MY_ALIAS
new_alias=$(cat "$PLUGIN_DATA_ROOT/l/ALIAS")
[[ $new_alias == "MY_ALIAS" ]]
}

View File

@@ -22,5 +22,5 @@ teardown() {
@test "($PLUGIN_COMMAND_PREFIX:info) success" {
run dokku "$PLUGIN_COMMAND_PREFIX:info" l
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_contains "${lines[*]}" "DSN: postgres://postgres:$password@172.17.0.34:5432/l"
assert_contains "${lines[*]}" "DSN: postgres://postgres:$password@dokku-postgres-l:5432/l"
}

View File

@@ -31,8 +31,31 @@ teardown() {
assert_contains "${lines[*]}" "service not_existing_service does not exist"
}
@test "($PLUGIN_COMMAND_PREFIX:link) success" {
@test "($PLUGIN_COMMAND_PREFIX:link) error when the service is already linked to app" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
run dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
links=$(cat "$PLUGIN_DATA_ROOT/l/LINKS")
assert_equal "$links" "my_app"
assert_contains "${lines[*]}" "Already linked as DATABASE_URL"
}
@test "($PLUGIN_COMMAND_PREFIX:link) exports DATABASE_URL to app" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
url=$(dokku config:get my_app DATABASE_URL)
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
assert_contains "$url" "postgres://postgres:$password@dokku-postgres-l:5432/l"
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
}
@test "($PLUGIN_COMMAND_PREFIX:link) generates an alternate config url when DATABASE_URL already in use" {
dokku config:set my_app DATABASE_URL=postgres://user:pass@host:5432/db
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
run dokku config my_app
assert_contains "${lines[*]}" "DOKKU_POSTGRES_"
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
}
@test "($PLUGIN_COMMAND_PREFIX:link) links to app with docker-options" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
run dokku docker-options my_app
assert_contains "${lines[*]}" "--link dokku.postgres.l:dokku-postgres-l"
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
}

55
tests/service_promote.bats Executable file
View File

@@ -0,0 +1,55 @@
#!/usr/bin/env bats
load test_helper
setup() {
dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2
dokku apps:create my_app >&2
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app
}
teardown() {
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2
rm "$DOKKU_ROOT/my_app" -rf
}
@test "($PLUGIN_COMMAND_PREFIX:promote) error when there are no arguments" {
run dokku "$PLUGIN_COMMAND_PREFIX:promote"
assert_contains "${lines[*]}" "Please specify a name for the service"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) error when the app argument is missing" {
run dokku "$PLUGIN_COMMAND_PREFIX:promote" l
assert_contains "${lines[*]}" "Please specify an app to run the command on"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) error when the app does not exist" {
run dokku "$PLUGIN_COMMAND_PREFIX:promote" l not_existing_app
assert_contains "${lines[*]}" "App not_existing_app does not exist"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) error when the service does not exist" {
run dokku "$PLUGIN_COMMAND_PREFIX:promote" not_existing_service my_app
assert_contains "${lines[*]}" "service not_existing_service does not exist"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) error when the service is already promoted" {
run dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
assert_contains "${lines[*]}" "already promoted as DATABASE_URL"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) changes DATABASE_URL" {
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
dokku config:set my_app "DATABASE_URL=postgres://u:p@host:5432/db" "DOKKU_POSTGRES_BLUE_URL=postgres://postgres:$password@dokku-postgres-l:5432/l"
dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
url=$(dokku config:get my_app DATABASE_URL)
assert_equal "$url" "postgres://postgres:$password@dokku-postgres-l:5432/l"
}
@test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" {
password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")"
dokku config:set my_app "DATABASE_URL=postgres://u:p@host:5432/db" "DOKKU_POSTGRES_BLUE_URL=postgres://postgres:$password@dokku-postgres-l:5432/l"
dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app
run dokku config my_app
assert_contains "${lines[*]}" "DOKKU_POSTGRES_"
}

View File

@@ -31,9 +31,21 @@ teardown() {
assert_contains "${lines[*]}" "service not_existing_service does not exist"
}
@test "($PLUGIN_COMMAND_PREFIX:unlink) success" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2
@test "($PLUGIN_COMMAND_PREFIX:unlink) error when service not linked to app" {
run dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
links=$(cat "$PLUGIN_DATA_ROOT/l/LINKS")
assert_equal "$links" ""
assert_contains "${lines[*]}" "Not linked to app my_app"
}
@test "($PLUGIN_COMMAND_PREFIX:unlink) removes link from docker-options" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
options=$(dokku docker-options my_app)
assert_equal "$options" ""
}
@test "($PLUGIN_COMMAND_PREFIX:unlink) unsets config url from app" {
dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2
dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app
config=$(dokku config:get my_app DATABASE_URL)
assert_equal "$config" ""
}