From ba61c4cc635375a4048b821c2287ca79952ec8b4 Mon Sep 17 00:00:00 2001 From: Kane Date: Fri, 6 Jan 2017 10:49:12 +1100 Subject: [PATCH 01/18] Add initial create-database command --- commands | 170 ++++++++++++++++++++++++++++++++++-- functions | 27 ++++++ subcommands/create-database | 15 ++++ 3 files changed, 204 insertions(+), 8 deletions(-) create mode 100755 subcommands/create-database diff --git a/commands b/commands index 6253c45b..e87bc666 100755 --- a/commands +++ b/commands @@ -1,17 +1,171 @@ #!/usr/bin/env bash source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" -[[ " help $PLUGIN_COMMAND_PREFIX:help $PLUGIN_COMMAND_PREFIX $PLUGIN_COMMAND_PREFIX:default " == *" $1 "* ]] || [[ "$1" == "$PLUGIN_COMMAND_PREFIX:"* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT" -source "$PLUGIN_BASE_PATH/common/functions" +[[ " help $PLUGIN_COMMAND_PREFIX:help " == *" $1 "* ]] || [[ "$1" == "$PLUGIN_COMMAND_PREFIX:"* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT" set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/help-functions" - -if [[ ! -d $PLUGIN_CONFIG_ROOT ]]; then - dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" -fi +source "$PLUGIN_BASE_PATH/common/functions" +source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" if [[ ! -d $PLUGIN_DATA_ROOT ]]; then dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" fi -fn-help "$@" +case "$1" in + $PLUGIN_COMMAND_PREFIX:backup) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:backup-auth) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-auth" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:backup-deauth) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-deauth" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:backup-schedule) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-schedule" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:backup-unschedule) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-unschedule" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:clone) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/clone" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:connect) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/connect" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:create) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/create" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:create-database) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/create-database" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:destroy) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/destroy" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:export) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/export" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:expose) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/expose" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:import) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/import" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:info) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/info" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:link) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/link" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:list) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/list" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:logs) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/logs" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:promote) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/promote" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:restart) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/restart" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:start) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/start" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:stop) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/stop" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:unexpose) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/unexpose" "$@" + ;; + + $PLUGIN_COMMAND_PREFIX:unlink) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/unlink" "$@" + ;; + + help | $PLUGIN_COMMAND_PREFIX:help) + help_content_func() { + # shellcheck disable=SC2034 + declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" + cat< , Create a backup of the $PLUGIN_COMMAND_PREFIX service to an existing s3 bucket + $PLUGIN_COMMAND_PREFIX:backup-auth , Sets up authentication for backups on the $PLUGIN_COMMAND_PREFIX service + $PLUGIN_COMMAND_PREFIX:backup-deauth , Removes backup authentication for the $PLUGIN_COMMAND_PREFIX service + $PLUGIN_COMMAND_PREFIX:backup-schedule , Schedules a backup of the $PLUGIN_COMMAND_PREFIX service + $PLUGIN_COMMAND_PREFIX:backup-unschedule , Unschedules the backup of the $PLUGIN_COMMAND_PREFIX service + $PLUGIN_COMMAND_PREFIX:clone , Create container then copy data from into + $PLUGIN_COMMAND_PREFIX:connect , Connect via psql to a $PLUGIN_SERVICE service + $PLUGIN_COMMAND_PREFIX:create , Create a $PLUGIN_SERVICE service + $PLUGIN_COMMAND_PREFIX:create-database , Create a $PLUGIN_SERVICE database in the specified service + $PLUGIN_COMMAND_PREFIX:destroy , Delete the $PLUGIN_SERVICE service and stop its container if there are no links left + $PLUGIN_COMMAND_PREFIX:export , Export a dump of the $PLUGIN_SERVICE service database + $PLUGIN_COMMAND_PREFIX:expose [port], Expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise) + $PLUGIN_COMMAND_PREFIX:import < , Import a dump into the $PLUGIN_SERVICE service database + $PLUGIN_COMMAND_PREFIX:info , Print the connection information + $PLUGIN_COMMAND_PREFIX:link , Link the $PLUGIN_SERVICE service to the app + $PLUGIN_COMMAND_PREFIX:list, List all $PLUGIN_SERVICE services + $PLUGIN_COMMAND_PREFIX:logs [-t], Print the most recent log(s) for this service + $PLUGIN_COMMAND_PREFIX:promote , Promote service as ${PLUGIN_DEFAULT_ALIAS}_URL in + $PLUGIN_COMMAND_PREFIX:restart , Graceful shutdown and restart of the $PLUGIN_SERVICE service container + $PLUGIN_COMMAND_PREFIX:start , Start a previously stopped $PLUGIN_SERVICE service + $PLUGIN_COMMAND_PREFIX:stop , Stop a running $PLUGIN_SERVICE service + $PLUGIN_COMMAND_PREFIX:unexpose , Unexpose a previously exposed $PLUGIN_SERVICE service + $PLUGIN_COMMAND_PREFIX:unlink , Unlink the $PLUGIN_SERVICE service from the app +help_content + } + + help_list_func() { + # shellcheck disable=SC2034 + declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" + cat< /dev/null; then + echo "$password" > "$SERVICE_ROOT/auth/$NAME" + chmod 640 "$SERVICE_ROOT/auth/$NAME" + else + echo 'Already exists' + fi + + dokku_log_verbose_quiet "Creating database" + if docker exec "$SERVICE_NAME" su - postgres -c "createdb -E utf8 $NAME" 2> /dev/null; then + touch "$SERVICE_ROOT/databases/$NAME" + else + echo 'Already exists' + fi + docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE $NAME TO $NAME;\"" > /dev/null +} + service_create_container() { local SERVICE="$1" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" diff --git a/subcommands/create-database b/subcommands/create-database new file mode 100755 index 00000000..fe58b6f8 --- /dev/null +++ b/subcommands/create-database @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_BASE_PATH/common/functions" +source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" + +postgres-create-database-cmd() { + declare desc="create a $PLUGIN_SERVICE database" + local cmd="$PLUGIN_COMMAND_PREFIX:create-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 + declare SERVICE="$1" NAME="$2" + + database_create "$SERVICE" "$NAME" +} + +postgres-create-database-cmd "$@" From cdb4a29f2145a1053e0d53a469731735bae62bbd Mon Sep 17 00:00:00 2001 From: Kane Date: Fri, 6 Jan 2017 14:43:41 +1100 Subject: [PATCH 02/18] Add username/database arguments to link/unlink --- commands | 4 ++-- common-functions | 51 ++++++++++++++++++++++++++++++++++++++++++---- functions | 19 +++++++++-------- subcommands/link | 25 +++++++++++++++++++++-- subcommands/unlink | 25 ++++++++++++++++++++++- 5 files changed, 107 insertions(+), 17 deletions(-) diff --git a/commands b/commands index e87bc666..024af59a 100755 --- a/commands +++ b/commands @@ -122,7 +122,7 @@ case "$1" in $PLUGIN_COMMAND_PREFIX:expose [port], Expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise) $PLUGIN_COMMAND_PREFIX:import < , Import a dump into the $PLUGIN_SERVICE service database $PLUGIN_COMMAND_PREFIX:info , Print the connection information - $PLUGIN_COMMAND_PREFIX:link , Link the $PLUGIN_SERVICE service to the app + $PLUGIN_COMMAND_PREFIX:link [--user user] [--database database], Link the $PLUGIN_SERVICE service to the app $PLUGIN_COMMAND_PREFIX:list, List all $PLUGIN_SERVICE services $PLUGIN_COMMAND_PREFIX:logs [-t], Print the most recent log(s) for this service $PLUGIN_COMMAND_PREFIX:promote , Promote service as ${PLUGIN_DEFAULT_ALIAS}_URL in @@ -130,7 +130,7 @@ case "$1" in $PLUGIN_COMMAND_PREFIX:start , Start a previously stopped $PLUGIN_SERVICE service $PLUGIN_COMMAND_PREFIX:stop , Stop a running $PLUGIN_SERVICE service $PLUGIN_COMMAND_PREFIX:unexpose , Unexpose a previously exposed $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:unlink , Unlink the $PLUGIN_SERVICE service from the app + $PLUGIN_COMMAND_PREFIX:unlink [--user user] [--database database], Unlink the $PLUGIN_SERVICE service from the app help_content } diff --git a/common-functions b/common-functions index 74503397..c436d4ad 100755 --- a/common-functions +++ b/common-functions @@ -254,7 +254,8 @@ service_info() { declare desc="Retrieves information about a given service" declare SERVICE="$1" INFO_FLAG="$2" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - local SERVICE_URL=$(service_url "$SERVICE") + local PASSWORD=$(cat "$SERVICE_ROOT/auth/postgres") + local SERVICE_URL=$(service_url "$SERVICE" postgres "$PASSWORD" "$SERVICE") local PORT_FILE="$SERVICE_ROOT/PORT" local SERVICE_CONTAINER_ID="$(cat "$SERVICE_ROOT/ID")" local flag key valid_flags @@ -307,9 +308,13 @@ service_link() { declare desc="Links a service to an application" declare SERVICE="$1" APP="$2" update_plugin_scheme_for_app "$APP" - local SERVICE_URL=$(service_url "$SERVICE") - local SERVICE_NAME="$(get_service_name "$SERVICE")" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + check_auth_migration "$SERVICE" + local USER=${3:-postgres} + local DATABASE=${4:-$(get_database_name "$SERVICE")} + local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") + local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") + local SERVICE_NAME="$(get_service_name "$SERVICE")" local EXISTING_CONFIG=$(config_all "$APP") local LINK=$(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1) || true local DEFAULT_ALIAS=$(echo "$EXISTING_CONFIG" | grep "${PLUGIN_DEFAULT_ALIAS}_URL") || true @@ -583,8 +588,12 @@ service_stop() { service_unlink() { declare desc="Unlinks an application from a service" declare SERVICE="$1" APP="$2" + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + local USER=${3:-postgres} + local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") + local DATABASE=${4:-$(get_database_name "$SERVICE")} update_plugin_scheme_for_app "$APP" - local SERVICE_URL=$(service_url "$SERVICE") + local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") local SERVICE_NAME="$(get_service_name "$SERVICE")" local EXISTING_CONFIG=$(config_all "$APP") local SERVICE_ALIAS=$(service_alias "$SERVICE") @@ -627,3 +636,37 @@ verify_service_name() { [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] && dokku_log_fail "$PLUGIN_SERVICE service $SERVICE does not exist" return 0 } + +verify_user_name() { + declare desc="Verifies that a user exists" + declare SERVICE="$1" USER="$2" + [[ ! -n "$SERVICE" ]] && dokku_log_fail "(verify_user_name) SERVICE must not be null" + [[ ! -n "$USER" ]] && dokku_log_fail "(verify_user_name) SERVICE must not be null" + [[ ! -f "$PLUGIN_DATA_ROOT/$SERVICE/auth/$USER" ]] && dokku_log_fail "$PLUGIN_SERVICE user $USER for service $SERVICE does not exist" + return 0 +} + +verify_database_name() { + declare desc="Verifies that a database exists" + declare SERVICE="$1" + declare DATABASE="$2" + [[ ! -n "$SERVICE" ]] && dokku_log_fail "(verify_service_name) SERVICE must not be null" + [[ ! -n "$DATABASE" ]] && dokku_log_fail "(verify_service_name) DATABASE must not be null" + [[ ! -f "$PLUGIN_DATA_ROOT/$SERVICE/databases/$DATABASE" ]] && dokku_log_fail "$PLUGIN_SERVICE database $DATABASE for service $SERVICE does not exist" + return 0 +} + +check_auth_migration() { + declare desc="Check whether root credentials need to be migrated into multi-user format and do so if needed" + declare SERVICE="$1" + [[ ! -n "$SERVICE" ]] && dokku_log_fail "(verify_service_name) SERVICE must not be null" + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + if [ -f "$SERVICE_ROOT/PASSWORD" ]; then + dokku_log_verbose_quiet "Migrating root user to multi-user format" + local AUTH_DIR="$SERVICE_ROOT/auth" + mkdir -p "$AUTH_DIR" + chmod 750 "$AUTH_DIR" + mv "$SERVICE_ROOT/PASSWORD" "$AUTH_DIR/postgres" + touch "$SERVICE_ROOT/databases/$SERVICE" + fi +} diff --git a/functions b/functions index b5b23840..703d5133 100755 --- a/functions +++ b/functions @@ -59,12 +59,14 @@ database_create() { [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ -z "$NAME" ]] && dokku_log_fail "Please specify a name for the database" + check_auth_migration "$SERVICE" + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local SERVICE_NAME="$(get_service_name "$SERVICE")" dokku_log_verbose_quiet "Creating user" password=$(openssl rand -hex 16) - if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER $NAME WITH PASSWORD '$password';\"" 2> /dev/null; then + if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER $NAME WITH PASSWORD '$password';\"" > /dev/null 2>&1; then echo "$password" > "$SERVICE_ROOT/auth/$NAME" chmod 640 "$SERVICE_ROOT/auth/$NAME" else @@ -84,7 +86,7 @@ service_create_container() { local SERVICE="$1" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local SERVICE_NAME="$(get_service_name "$SERVICE")" - local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")" + local PASSWORD="$(cat "$SERVICE_ROOT/auth/postgres")" local PREVIOUS_ID ID=$(docker run --name "$SERVICE_NAME" -v "$SERVICE_ROOT/data:/var/lib/postgresql/data" -e "POSTGRES_PASSWORD=$PASSWORD" --env-file="$SERVICE_ROOT/ENV" -d --restart always --label dokku=service --label dokku.service=postgres "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION") @@ -114,7 +116,7 @@ service_export() { local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local SERVICE_NAME="$(get_service_name "$SERVICE")" local DATABASE_NAME="$(get_database_name "$SERVICE")" - local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")" + local PASSWORD="$(cat "$SERVICE_ROOT/auth/postgres")" [[ -n $SSH_TTY ]] && stty -opost docker exec "$SERVICE_NAME" env PGPASSWORD="$PASSWORD" pg_dump -Fc --no-acl --no-owner -h localhost -U postgres -w "$DATABASE_NAME" @@ -128,7 +130,7 @@ service_import() { SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" SERVICE_NAME="$(get_service_name "$SERVICE")" DATABASE_NAME="$(get_database_name "$SERVICE")" - PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")" + PASSWORD="$(cat "$SERVICE_ROOT/auth/postgres")" if [[ -t 0 ]]; then dokku_log_fail "No data provided on stdin." @@ -150,7 +152,7 @@ service_start() { dokku_log_info1_quiet "Starting container" local PREVIOUS_ID=$(docker ps -f status=exited | grep -e "$SERVICE_NAME$" | awk '{print $1}') || true local IMAGE_EXISTS=$(docker images | grep -e "^$PLUGIN_IMAGE " | grep -q " $PLUGIN_IMAGE_VERSION " && true) - local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")" + local PASSWORD="$(cat "$SERVICE_ROOT/auth/postgres")" if [[ -n $PREVIOUS_ID ]]; then docker start "$PREVIOUS_ID" > /dev/null @@ -167,8 +169,9 @@ service_url() { local SERVICE="$1" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - local PASSWORD="$(cat "$SERVICE_ROOT/PASSWORD")" - local DATABASE_NAME="$(get_database_name "$SERVICE")" + local USER="$2" # postgres + local PASSWORD="$3" + local DATABASE_NAME="$4" local SERVICE_ALIAS="$(service_alias "$SERVICE")" - echo "$PLUGIN_SCHEME://postgres:$PASSWORD@$SERVICE_ALIAS:${PLUGIN_DATASTORE_PORTS[0]}/$DATABASE_NAME" + echo "$PLUGIN_SCHEME://$USER:$PASSWORD@$SERVICE_ALIAS:${PLUGIN_DATASTORE_PORTS[0]}/$DATABASE_NAME" } diff --git a/subcommands/link b/subcommands/link index 7dc893f4..16ebf99a 100755 --- a/subcommands/link +++ b/subcommands/link @@ -41,14 +41,35 @@ service-link-cmd() { #A app, app to run command against declare desc="link the $PLUGIN_SERVICE service to the app" local cmd="$PLUGIN_COMMAND_PREFIX:link" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 - declare SERVICE="$1" APP="$2" + + local USER='' + + local next_index=1; local skip=false; local args=("$@"); local positional=() + for arg in "$@"; do + $skip && skip=false && local next_index=$(( next_index + 1 )) && continue + case "$arg" in + --user) + USER=${args[$next_index]}; skip=true + ;; + --database) + DATABASE=${args[$next_index]}; skip=true + ;; + *) + positional+=("$arg") + esac + local next_index=$(( next_index + 1 )) + done + + declare SERVICE="${positional[0]}" APP="${positional[1]}" APP=${APP:="$DOKKU_APP_NAME"} [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_app_name "$APP" verify_service_name "$SERVICE" - service_link "$SERVICE" "$APP" + [[ -z "$USER" ]] || verify_user_name "$SERVICE" "$USER" + [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" + service_link "$SERVICE" "$APP" "$USER" "$DATABASE" } service-link-cmd "$@" diff --git a/subcommands/unlink b/subcommands/unlink index a58e9c7b..23531aca 100755 --- a/subcommands/unlink +++ b/subcommands/unlink @@ -15,11 +15,34 @@ service-unlink-cmd() { declare SERVICE="$1" APP="$2" APP=${APP:="$DOKKU_APP_NAME"} + local USER='' + + local next_index=1; local skip=false; local args=("$@"); local positional=() + for arg in "$@"; do + $skip && skip=false && local next_index=$(( next_index + 1 )) && continue + case "$arg" in + --user) + USER=${args[$next_index]}; skip=true + ;; + --database) + DATABASE=${args[$next_index]}; skip=true + ;; + *) + positional+=("$arg") + esac + local next_index=$(( next_index + 1 )) + done + + declare SERVICE="${positional[0]}" APP="${positional[1]}" + [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_service_name "$SERVICE" verify_app_name "$APP" - service_unlink "$SERVICE" "$APP" + [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" + [[ -z "$USER" ]] || verify_user_name "$SERVICE" "$USER" + service_unlink "$SERVICE" "$APP" "$USER" "$DATABASE" + } service-unlink-cmd "$@" From 98dbbc00a30432a7da237f3a818bd78e4ce2de98 Mon Sep 17 00:00:00 2001 From: Kane Date: Fri, 6 Jan 2017 14:44:02 +1100 Subject: [PATCH 03/18] Show users and databases in list output --- commands | 5 +++++ common-functions | 26 ++++++++++++++++++++++++-- functions | 4 ++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/commands b/commands index 024af59a..4345d2e9 100755 --- a/commands +++ b/commands @@ -51,6 +51,10 @@ case "$1" in "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/destroy" "$@" ;; + $PLUGIN_COMMAND_PREFIX:destroy-database) + "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/destroy-database" "$@" + ;; + $PLUGIN_COMMAND_PREFIX:export) "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/export" "$@" ;; @@ -118,6 +122,7 @@ case "$1" in $PLUGIN_COMMAND_PREFIX:create , Create a $PLUGIN_SERVICE service $PLUGIN_COMMAND_PREFIX:create-database , Create a $PLUGIN_SERVICE database in the specified service $PLUGIN_COMMAND_PREFIX:destroy , Delete the $PLUGIN_SERVICE service and stop its container if there are no links left + $PLUGIN_COMMAND_PREFIX:destroy-database , Delete a $PLUGIN_SERVICE database on the specified service $PLUGIN_COMMAND_PREFIX:export , Export a dump of the $PLUGIN_SERVICE service database $PLUGIN_COMMAND_PREFIX:expose [port], Expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise) $PLUGIN_COMMAND_PREFIX:import < , Import a dump into the $PLUGIN_SERVICE service database diff --git a/common-functions b/common-functions index c436d4ad..def8c391 100755 --- a/common-functions +++ b/common-functions @@ -250,6 +250,28 @@ service_exposed_ports() { done } +service_databases() { + declare desc="Lists databases for a service" + declare SERVICE="$1" + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + local DATABASE_DIR="$SERVICE_ROOT/databases" + [[ ! -d $DATABASE_DIR ]] && echo '-' && return 0 + for DATABASE in $DATABASE_DIR/*; do + echo -n "$(basename "$DATABASE") " + done +} + +service_users() { + declare desc="Lists users for a service" + declare SERVICE="$1" + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + local USER_DIR="$SERVICE_ROOT/auth" + [[ ! -d $USER_DIR ]] && echo '-' && return 0 + for USER in $USER_DIR/*; do + echo -n "$(basename "$USER") " + done +} + service_info() { declare desc="Retrieves information about a given service" declare SERVICE="$1" INFO_FLAG="$2" @@ -360,9 +382,9 @@ service_list() { if [[ -z $SERVICES ]]; then dokku_log_warn "There are no $PLUGIN_SERVICE services" else - LIST="NAME,VERSION,STATUS,EXPOSED PORTS,LINKS\n" + LIST="NAME,VERSION,STATUS,EXPOSED PORTS,DATABASES,USERS,LINKS\n" for SERVICE in $SERVICES; do - LIST+="$SERVICE,$(service_version "$SERVICE"),$(service_status "$SERVICE"),$(service_exposed_ports "$SERVICE"),$(service_linked_apps "$SERVICE")\n" + LIST+="$SERVICE,$(service_version "$SERVICE"),$(service_status "$SERVICE"),$(service_exposed_ports "$SERVICE"),$(service_databases "$SERVICE"),$(service_users "$SERVICE"),$(service_linked_apps "$SERVICE")\n" done printf "%b" "$LIST" | column -t -s, fi diff --git a/functions b/functions index 703d5133..d5b3f9f1 100755 --- a/functions +++ b/functions @@ -66,7 +66,7 @@ database_create() { dokku_log_verbose_quiet "Creating user" password=$(openssl rand -hex 16) - if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER $NAME WITH PASSWORD '$password';\"" > /dev/null 2>&1; then + if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER \\\"$NAME\\\" WITH PASSWORD '$password';\"" > /dev/null 2>&1; then echo "$password" > "$SERVICE_ROOT/auth/$NAME" chmod 640 "$SERVICE_ROOT/auth/$NAME" else @@ -79,7 +79,7 @@ database_create() { else echo 'Already exists' fi - docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE $NAME TO $NAME;\"" > /dev/null + docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \\\"$NAME\\\" TO \\\"$NAME\\\";\"" > /dev/null } service_create_container() { From 42b8d5381e93bcedfe9739a9bb251e1e05f7646e Mon Sep 17 00:00:00 2001 From: Kane Date: Fri, 6 Jan 2017 14:44:11 +1100 Subject: [PATCH 04/18] Add command to destroy databases --- commands | 2 +- subcommands/destroy-database | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100755 subcommands/destroy-database diff --git a/commands b/commands index 4345d2e9..2e03da69 100755 --- a/commands +++ b/commands @@ -122,7 +122,7 @@ case "$1" in $PLUGIN_COMMAND_PREFIX:create , Create a $PLUGIN_SERVICE service $PLUGIN_COMMAND_PREFIX:create-database , Create a $PLUGIN_SERVICE database in the specified service $PLUGIN_COMMAND_PREFIX:destroy , Delete the $PLUGIN_SERVICE service and stop its container if there are no links left - $PLUGIN_COMMAND_PREFIX:destroy-database , Delete a $PLUGIN_SERVICE database on the specified service + $PLUGIN_COMMAND_PREFIX:destroy-database , Delete a $PLUGIN_SERVICE database in the specified service $PLUGIN_COMMAND_PREFIX:export , Export a dump of the $PLUGIN_SERVICE service database $PLUGIN_COMMAND_PREFIX:expose [port], Expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise) $PLUGIN_COMMAND_PREFIX:import < , Import a dump into the $PLUGIN_SERVICE service database diff --git a/subcommands/destroy-database b/subcommands/destroy-database new file mode 100755 index 00000000..40030c7e --- /dev/null +++ b/subcommands/destroy-database @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" +set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$PLUGIN_BASE_PATH/common/functions" +source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" + +postgres-destroy-database-cmd() { + declare desc="delete a $PLUGIN_SERVICE database from the specified service" + local cmd="$PLUGIN_COMMAND_PREFIX:destroy-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 + declare SERVICE="$1" DATABASE="$2" + + [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" + [[ -z "$DATABASE" ]] && dokku_log_fail "Please specify a name for the database" + verify_service_name "$SERVICE" + verify_database_name "$SERVICE" "$DATABASE" + SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + SERVICE_NAME="$(get_service_name "$SERVICE")" + + dokku_log_info1 "Deleting $DATABASE from $SERVICE" + if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP DATABASE $DATABASE;\"" 2> /dev/null && docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP USER $DATABASE;\"" 2> /dev/null; then + rm -f "$SERVICE_ROOT/databases/$DATABASE" + rm -f "$SERVICE_ROOT/auth/$DATABASE" + dokku_log_info2 "$PLUGIN_SERVICE $SERVICE database deleted: $DATABASE" + else + dokku_log_fail "Could not delete the database" + fi +} + +postgres-destroy-database-cmd "$@" From a787aba76f3f29d33eaea938fb46a52ef67776af Mon Sep 17 00:00:00 2001 From: Kane Date: Thu, 26 Jan 2017 10:38:55 +1100 Subject: [PATCH 05/18] Update readme with single container commands --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 78583413..9bf1cfdc 100644 --- a/README.md +++ b/README.md @@ -27,14 +27,16 @@ postgres:backup-unset-encryption , Removes backup encryption for future ba postgres:clone Create container then copy data from into postgres:connect Connect via psql to a postgres service postgres:create Create a postgres service with environment variables +postgres:create-database Create a postgres database in the specified service postgres:destroy Delete the service, delete the data and stop its container if there are no links left +postgres:destroy-database Delete a postgres database in the specified service postgres:enter [command] Enter or run a command in a running postgres service container postgres:exists Check if the postgres service exists postgres:export > Export a dump of the postgres service database postgres:expose [port] Expose a postgres service on custom port if provided (random port otherwise) postgres:import < Import a dump into the postgres service database postgres:info Print the connection information -postgres:link Link the postgres service to the app +postgres:link [--user user] [--database database] Link the postgres service to the app postgres:linked Check if the postgres service is linked to an app postgres:list List all postgres services postgres:logs [-t] Print the most recent log(s) for this service @@ -43,7 +45,7 @@ postgres:restart Graceful shutdown and restart of the postgres postgres:start Start a previously stopped postgres service postgres:stop Stop a running postgres service postgres:unexpose Unexpose a previously exposed postgres service -postgres:unlink Unlink the postgres service from the app +postgres:unlink [--user user] [--database database] Unlink the postgres service from the app ``` ## usage From b482411f7a7578820a170a8034bbccc9fcbed8f7 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Tue, 27 Feb 2018 14:05:31 +0100 Subject: [PATCH 06/18] Move commands --- commands | 175 +++---------------------------------------------------- 1 file changed, 8 insertions(+), 167 deletions(-) diff --git a/commands b/commands index 2e03da69..6253c45b 100755 --- a/commands +++ b/commands @@ -1,176 +1,17 @@ #!/usr/bin/env bash source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" -[[ " help $PLUGIN_COMMAND_PREFIX:help " == *" $1 "* ]] || [[ "$1" == "$PLUGIN_COMMAND_PREFIX:"* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT" +[[ " help $PLUGIN_COMMAND_PREFIX:help $PLUGIN_COMMAND_PREFIX $PLUGIN_COMMAND_PREFIX:default " == *" $1 "* ]] || [[ "$1" == "$PLUGIN_COMMAND_PREFIX:"* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT" +source "$PLUGIN_BASE_PATH/common/functions" set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -source "$PLUGIN_BASE_PATH/common/functions" -source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" +source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/help-functions" -if [[ ! -d $PLUGIN_DATA_ROOT ]]; then +if [[ ! -d $PLUGIN_CONFIG_ROOT ]]; then dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" fi -case "$1" in - $PLUGIN_COMMAND_PREFIX:backup) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:backup-auth) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-auth" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:backup-deauth) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-deauth" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:backup-schedule) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-schedule" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:backup-unschedule) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/backup-unschedule" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:clone) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/clone" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:connect) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/connect" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:create) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/create" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:create-database) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/create-database" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:destroy) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/destroy" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:destroy-database) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/destroy-database" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:export) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/export" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:expose) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/expose" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:import) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/import" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:info) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/info" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:link) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/link" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:list) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/list" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:logs) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/logs" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:promote) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/promote" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:restart) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/restart" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:start) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/start" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:stop) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/stop" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:unexpose) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/unexpose" "$@" - ;; - - $PLUGIN_COMMAND_PREFIX:unlink) - "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands/unlink" "$@" - ;; - - help | $PLUGIN_COMMAND_PREFIX:help) - help_content_func() { - # shellcheck disable=SC2034 - declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" - cat< , Create a backup of the $PLUGIN_COMMAND_PREFIX service to an existing s3 bucket - $PLUGIN_COMMAND_PREFIX:backup-auth , Sets up authentication for backups on the $PLUGIN_COMMAND_PREFIX service - $PLUGIN_COMMAND_PREFIX:backup-deauth , Removes backup authentication for the $PLUGIN_COMMAND_PREFIX service - $PLUGIN_COMMAND_PREFIX:backup-schedule , Schedules a backup of the $PLUGIN_COMMAND_PREFIX service - $PLUGIN_COMMAND_PREFIX:backup-unschedule , Unschedules the backup of the $PLUGIN_COMMAND_PREFIX service - $PLUGIN_COMMAND_PREFIX:clone , Create container then copy data from into - $PLUGIN_COMMAND_PREFIX:connect , Connect via psql to a $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:create , Create a $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:create-database , Create a $PLUGIN_SERVICE database in the specified service - $PLUGIN_COMMAND_PREFIX:destroy , Delete the $PLUGIN_SERVICE service and stop its container if there are no links left - $PLUGIN_COMMAND_PREFIX:destroy-database , Delete a $PLUGIN_SERVICE database in the specified service - $PLUGIN_COMMAND_PREFIX:export , Export a dump of the $PLUGIN_SERVICE service database - $PLUGIN_COMMAND_PREFIX:expose [port], Expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise) - $PLUGIN_COMMAND_PREFIX:import < , Import a dump into the $PLUGIN_SERVICE service database - $PLUGIN_COMMAND_PREFIX:info , Print the connection information - $PLUGIN_COMMAND_PREFIX:link [--user user] [--database database], Link the $PLUGIN_SERVICE service to the app - $PLUGIN_COMMAND_PREFIX:list, List all $PLUGIN_SERVICE services - $PLUGIN_COMMAND_PREFIX:logs [-t], Print the most recent log(s) for this service - $PLUGIN_COMMAND_PREFIX:promote , Promote service as ${PLUGIN_DEFAULT_ALIAS}_URL in - $PLUGIN_COMMAND_PREFIX:restart , Graceful shutdown and restart of the $PLUGIN_SERVICE service container - $PLUGIN_COMMAND_PREFIX:start , Start a previously stopped $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:stop , Stop a running $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:unexpose , Unexpose a previously exposed $PLUGIN_SERVICE service - $PLUGIN_COMMAND_PREFIX:unlink [--user user] [--database database], Unlink the $PLUGIN_SERVICE service from the app -help_content - } - - help_list_func() { - # shellcheck disable=SC2034 - declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" - cat< Date: Tue, 27 Feb 2018 14:09:20 +0100 Subject: [PATCH 07/18] rename subcommands --- subcommands/create-database | 4 ++-- subcommands/destroy-database | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/subcommands/create-database b/subcommands/create-database index fe58b6f8..79890566 100755 --- a/subcommands/create-database +++ b/subcommands/create-database @@ -4,7 +4,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_BASE_PATH/common/functions" source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" -postgres-create-database-cmd() { +service-create-database-cmd() { declare desc="create a $PLUGIN_SERVICE database" local cmd="$PLUGIN_COMMAND_PREFIX:create-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 declare SERVICE="$1" NAME="$2" @@ -12,4 +12,4 @@ postgres-create-database-cmd() { database_create "$SERVICE" "$NAME" } -postgres-create-database-cmd "$@" +service-create-database-cmd "$@" diff --git a/subcommands/destroy-database b/subcommands/destroy-database index 40030c7e..e333273b 100755 --- a/subcommands/destroy-database +++ b/subcommands/destroy-database @@ -4,7 +4,7 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x source "$PLUGIN_BASE_PATH/common/functions" source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" -postgres-destroy-database-cmd() { +service-destroy-database-cmd() { declare desc="delete a $PLUGIN_SERVICE database from the specified service" local cmd="$PLUGIN_COMMAND_PREFIX:destroy-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 declare SERVICE="$1" DATABASE="$2" @@ -26,4 +26,4 @@ postgres-destroy-database-cmd() { fi } -postgres-destroy-database-cmd "$@" +service-destroy-database-cmd "$@" From 4d219209e47d0881d56520c0de01598037f8d6bc Mon Sep 17 00:00:00 2001 From: sarendsen Date: Tue, 27 Feb 2018 14:30:42 +0100 Subject: [PATCH 08/18] Fix missing database dir --- common-functions | 1 + functions | 2 +- subcommands/create-database | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common-functions b/common-functions index def8c391..72099c4d 100755 --- a/common-functions +++ b/common-functions @@ -689,6 +689,7 @@ check_auth_migration() { mkdir -p "$AUTH_DIR" chmod 750 "$AUTH_DIR" mv "$SERVICE_ROOT/PASSWORD" "$AUTH_DIR/postgres" + mkdir -p "$SERVICE_ROOT/databases/" touch "$SERVICE_ROOT/databases/$SERVICE" fi } diff --git a/functions b/functions index d5b3f9f1..4f5d0a65 100755 --- a/functions +++ b/functions @@ -53,7 +53,7 @@ service_create() { service_create_container "$SERVICE" } -database_create() { +service_create_database() { local SERVICE="$1" local NAME="$2" [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" diff --git a/subcommands/create-database b/subcommands/create-database index 79890566..0bea1da4 100755 --- a/subcommands/create-database +++ b/subcommands/create-database @@ -9,7 +9,7 @@ service-create-database-cmd() { local cmd="$PLUGIN_COMMAND_PREFIX:create-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 declare SERVICE="$1" NAME="$2" - database_create "$SERVICE" "$NAME" + service_create_database "$SERVICE" "$NAME" } service-create-database-cmd "$@" From 59072016502818e54a882a6eb076832f30341781 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Tue, 27 Feb 2018 14:34:45 +0100 Subject: [PATCH 09/18] Check if service exists before db creation --- functions | 1 + 1 file changed, 1 insertion(+) diff --git a/functions b/functions index 4f5d0a65..ccd36271 100755 --- a/functions +++ b/functions @@ -59,6 +59,7 @@ service_create_database() { [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ -z "$NAME" ]] && dokku_log_fail "Please specify a name for the database" + verify_service_name "$SERVICE" check_auth_migration "$SERVICE" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" From c2a13794e581bfcffc9297e7986cb97cfc48bf08 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Tue, 27 Feb 2018 15:08:16 +0100 Subject: [PATCH 10/18] Add create databse tests --- functions | 6 ++++-- tests/service_create_database.bats | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/service_create_database.bats diff --git a/functions b/functions index ccd36271..de01bfdd 100755 --- a/functions +++ b/functions @@ -71,16 +71,18 @@ service_create_database() { echo "$password" > "$SERVICE_ROOT/auth/$NAME" chmod 640 "$SERVICE_ROOT/auth/$NAME" else - echo 'Already exists' + dokku_log_verbose_quiet "Already exists" fi dokku_log_verbose_quiet "Creating database" if docker exec "$SERVICE_NAME" su - postgres -c "createdb -E utf8 $NAME" 2> /dev/null; then touch "$SERVICE_ROOT/databases/$NAME" else - echo 'Already exists' + dokku_log_verbose_quiet "Already exists" fi docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \\\"$NAME\\\" TO \\\"$NAME\\\";\"" > /dev/null + + dokku_log_info2 "$PLUGIN_SERVICE database created: $NAME" } service_create_container() { diff --git a/tests/service_create_database.bats b/tests/service_create_database.bats new file mode 100644 index 00000000..26ee6e3b --- /dev/null +++ b/tests/service_create_database.bats @@ -0,0 +1,17 @@ +#!/usr/bin/env bats +load test_helper + +setup() { + dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 + dokku apps:create my_app >&2 +} + +teardown() { + dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 + rm -rf "$DOKKU_ROOT/my_app" +} + +@test "($PLUGIN_COMMAND_PREFIX:create-database) success" { + run dokku "$PLUGIN_COMMAND_PREFIX:create-database" l d + assert_contains "${lines[*]}" "database created: l" +} From 56810b927e258ef1a5d995151a25712575590c08 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 10:09:54 +0000 Subject: [PATCH 11/18] Move logic and add destroy tests --- common-functions | 54 +++++++++++++++++++++++++++++ functions | 32 ----------------- subcommands/create-database | 7 ++-- subcommands/destroy-database | 13 +------ tests/service_create_database.bats | 14 +++++++- tests/service_destroy_database.bats | 28 +++++++++++++++ 6 files changed, 101 insertions(+), 47 deletions(-) create mode 100644 tests/service_destroy_database.bats diff --git a/common-functions b/common-functions index 72099c4d..c85a67c6 100755 --- a/common-functions +++ b/common-functions @@ -642,6 +642,60 @@ service_version() { docker inspect -f '{{.Config.Image}}' "$SERVICE_NAME" } + +service_create_database() { + local SERVICE="$1" + local DATABASE="$2" + local USER="$2" + [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" + [[ -z "$DATABASE" ]] && dokku_log_fail "Please specify a name for the database" + + verify_service_name "$SERVICE" + check_auth_migration "$SERVICE" + + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + local SERVICE_NAME="$(get_service_name "$SERVICE")" + + dokku_log_verbose_quiet "Creating user" + password=$(openssl rand -hex 16) + if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER \\\"$USER\\\" WITH PASSWORD '$password';\"" > /dev/null 2>&1; then + echo "$password" > "$SERVICE_ROOT/auth/$USER" + chmod 640 "$SERVICE_ROOT/auth/$USER" + else + dokku_log_verbose_quiet "Already exists" + fi + + dokku_log_verbose_quiet "Creating database" + if docker exec "$SERVICE_NAME" su - postgres -c "createdb -E utf8 $DATABASE" 2> /dev/null; then + touch "$SERVICE_ROOT/databases/$DATABASE" + else + dokku_log_verbose_quiet "Already exists" + fi + docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \\\"$DATABASE\\\" TO \\\"$USER\\\";\"" > /dev/null + + dokku_log_info2 "$PLUGIN_SERVICE database created: $DATABASE" +} + +service_destroy_database() { + local SERVICE="$1" + local DATABASE="$2" + + verify_service_name "$SERVICE" + verify_database_name "$SERVICE" "$DATABASE" + SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" + SERVICE_NAME="$(get_service_name "$SERVICE")" + + dokku_log_info1 "Deleting $DATABASE from $SERVICE" + if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP DATABASE $DATABASE;\"" 2> /dev/null && docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP USER $DATABASE;\"" 2> /dev/null; then + rm -f "$SERVICE_ROOT/databases/$DATABASE" + rm -f "$SERVICE_ROOT/auth/$DATABASE" + dokku_log_info2 "$PLUGIN_SERVICE $SERVICE database deleted: $DATABASE" + else + dokku_log_fail "Could not delete the database" + fi +} + + update_plugin_scheme_for_app() { declare desc="Retrieves the updated plugin scheme" declare APP="$1" diff --git a/functions b/functions index de01bfdd..1859b271 100755 --- a/functions +++ b/functions @@ -53,38 +53,6 @@ service_create() { service_create_container "$SERVICE" } -service_create_database() { - local SERVICE="$1" - local NAME="$2" - [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" - [[ -z "$NAME" ]] && dokku_log_fail "Please specify a name for the database" - - verify_service_name "$SERVICE" - check_auth_migration "$SERVICE" - - local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - local SERVICE_NAME="$(get_service_name "$SERVICE")" - - dokku_log_verbose_quiet "Creating user" - password=$(openssl rand -hex 16) - if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"CREATE USER \\\"$NAME\\\" WITH PASSWORD '$password';\"" > /dev/null 2>&1; then - echo "$password" > "$SERVICE_ROOT/auth/$NAME" - chmod 640 "$SERVICE_ROOT/auth/$NAME" - else - dokku_log_verbose_quiet "Already exists" - fi - - dokku_log_verbose_quiet "Creating database" - if docker exec "$SERVICE_NAME" su - postgres -c "createdb -E utf8 $NAME" 2> /dev/null; then - touch "$SERVICE_ROOT/databases/$NAME" - else - dokku_log_verbose_quiet "Already exists" - fi - docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE \\\"$NAME\\\" TO \\\"$NAME\\\";\"" > /dev/null - - dokku_log_info2 "$PLUGIN_SERVICE database created: $NAME" -} - service_create_container() { local SERVICE="$1" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" diff --git a/subcommands/create-database b/subcommands/create-database index 0bea1da4..9bbe4d15 100755 --- a/subcommands/create-database +++ b/subcommands/create-database @@ -7,9 +7,12 @@ source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" service-create-database-cmd() { declare desc="create a $PLUGIN_SERVICE database" local cmd="$PLUGIN_COMMAND_PREFIX:create-database" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 - declare SERVICE="$1" NAME="$2" + declare SERVICE="$1" DATABASE="$2" - service_create_database "$SERVICE" "$NAME" + [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" + [[ -z "$DATABASE" ]] && dokku_log_fail "Please specify a name for the database" + + service_create_database "$SERVICE" "$DATABASE" } service-create-database-cmd "$@" diff --git a/subcommands/destroy-database b/subcommands/destroy-database index e333273b..2285268b 100755 --- a/subcommands/destroy-database +++ b/subcommands/destroy-database @@ -11,19 +11,8 @@ service-destroy-database-cmd() { [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ -z "$DATABASE" ]] && dokku_log_fail "Please specify a name for the database" - verify_service_name "$SERVICE" - verify_database_name "$SERVICE" "$DATABASE" - SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - SERVICE_NAME="$(get_service_name "$SERVICE")" - dokku_log_info1 "Deleting $DATABASE from $SERVICE" - if docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP DATABASE $DATABASE;\"" 2> /dev/null && docker exec "$SERVICE_NAME" su - postgres -c "psql -c \"DROP USER $DATABASE;\"" 2> /dev/null; then - rm -f "$SERVICE_ROOT/databases/$DATABASE" - rm -f "$SERVICE_ROOT/auth/$DATABASE" - dokku_log_info2 "$PLUGIN_SERVICE $SERVICE database deleted: $DATABASE" - else - dokku_log_fail "Could not delete the database" - fi + service_destroy_database "$SERVICE" "$DATABASE" } service-destroy-database-cmd "$@" diff --git a/tests/service_create_database.bats b/tests/service_create_database.bats index 26ee6e3b..c4592b94 100644 --- a/tests/service_create_database.bats +++ b/tests/service_create_database.bats @@ -2,16 +2,28 @@ load test_helper setup() { + export ECHO_DOCKER_COMMAND="false" dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 dokku apps:create my_app >&2 } teardown() { + export ECHO_DOCKER_COMMAND="false" dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 rm -rf "$DOKKU_ROOT/my_app" } @test "($PLUGIN_COMMAND_PREFIX:create-database) success" { run dokku "$PLUGIN_COMMAND_PREFIX:create-database" l d - assert_contains "${lines[*]}" "database created: l" + assert_contains "${lines[*]}" "database created: d" } + +@test "($PLUGIN_COMMAND_PREFIX:create-database) error when there is only one argument" { + run dokku "$PLUGIN_COMMAND_PREFIX:create-database" l + assert_contains "${lines[*]}" "Please specify a name for the database" +} + +@test "($PLUGIN_COMMAND_PREFIX:create-database) error when there are no arguments" { + run dokku "$PLUGIN_COMMAND_PREFIX:create-database" + assert_contains "${lines[*]}" "Please specify a name for the service" +} \ No newline at end of file diff --git a/tests/service_destroy_database.bats b/tests/service_destroy_database.bats new file mode 100644 index 00000000..1d663427 --- /dev/null +++ b/tests/service_destroy_database.bats @@ -0,0 +1,28 @@ +#!/usr/bin/env bats +load test_helper + +setup() { + dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 + dokku "$PLUGIN_COMMAND_PREFIX:create-database" l d >&2 + dokku apps:create my_app >&2 +} + +teardown() { + dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 + rm -rf "$DOKKU_ROOT/my_app" +} + +@test "($PLUGIN_COMMAND_PREFIX:destroy-database) success" { + run dokku "$PLUGIN_COMMAND_PREFIX:destroy-database" l d + assert_contains "${lines[*]}" "database deleted: d" +} + +@test "($PLUGIN_COMMAND_PREFIX:destroy-database) error when there are no arguments" { + run dokku "$PLUGIN_COMMAND_PREFIX:destroy-database" + assert_contains "${lines[*]}" "Please specify a name for the service" +} + +@test "($PLUGIN_COMMAND_PREFIX:destroy-database) error when there is only one argument" { + run dokku "$PLUGIN_COMMAND_PREFIX:destroy-database" l + assert_contains "${lines[*]}" "Please specify a name for the database" +} From 0e494be4b6b31b86bf30dd4de69fb3fc63331fb0 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 12:35:59 +0100 Subject: [PATCH 12/18] Move check_auth_migration to install --- README.md | 4 ++-- common-functions | 14 ++++++-------- functions | 11 ++++++++--- install | 5 +++++ subcommands/link | 6 +----- subcommands/unlink | 6 +----- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9bf1cfdc..75ee935d 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ postgres:export > Export a dump of the postgres service database postgres:expose [port] Expose a postgres service on custom port if provided (random port otherwise) postgres:import < Import a dump into the postgres service database postgres:info Print the connection information -postgres:link [--user user] [--database database] Link the postgres service to the app +postgres:link [--database database] Link the postgres service to the app postgres:linked Check if the postgres service is linked to an app postgres:list List all postgres services postgres:logs [-t] Print the most recent log(s) for this service @@ -45,7 +45,7 @@ postgres:restart Graceful shutdown and restart of the postgres postgres:start Start a previously stopped postgres service postgres:stop Stop a running postgres service postgres:unexpose Unexpose a previously exposed postgres service -postgres:unlink [--user user] [--database database] Unlink the postgres service from the app +postgres:unlink [--database database] Unlink the postgres service from the app ``` ## usage diff --git a/common-functions b/common-functions index c85a67c6..8c856f1b 100755 --- a/common-functions +++ b/common-functions @@ -331,9 +331,8 @@ service_link() { declare SERVICE="$1" APP="$2" update_plugin_scheme_for_app "$APP" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - check_auth_migration "$SERVICE" - local USER=${3:-postgres} - local DATABASE=${4:-$(get_database_name "$SERVICE")} + local DATABASE=${3:-$(get_database_name "$SERVICE")} + local USER="$DATABASE" local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") local SERVICE_NAME="$(get_service_name "$SERVICE")" @@ -611,9 +610,9 @@ service_unlink() { declare desc="Unlinks an application from a service" declare SERVICE="$1" APP="$2" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" - local USER=${3:-postgres} + local DATABASE=${3:-$(get_database_name "$SERVICE")} + local USER="$DATABASE" local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") - local DATABASE=${4:-$(get_database_name "$SERVICE")} update_plugin_scheme_for_app "$APP" local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") local SERVICE_NAME="$(get_service_name "$SERVICE")" @@ -651,7 +650,6 @@ service_create_database() { [[ -z "$DATABASE" ]] && dokku_log_fail "Please specify a name for the database" verify_service_name "$SERVICE" - check_auth_migration "$SERVICE" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local SERVICE_NAME="$(get_service_name "$SERVICE")" @@ -738,12 +736,12 @@ check_auth_migration() { [[ ! -n "$SERVICE" ]] && dokku_log_fail "(verify_service_name) SERVICE must not be null" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" if [ -f "$SERVICE_ROOT/PASSWORD" ]; then - dokku_log_verbose_quiet "Migrating root user to multi-user format" + dokku_log_verbose_quiet "Migrating root user to multi-user format for $SERVICE" local AUTH_DIR="$SERVICE_ROOT/auth" mkdir -p "$AUTH_DIR" chmod 750 "$AUTH_DIR" mv "$SERVICE_ROOT/PASSWORD" "$AUTH_DIR/postgres" mkdir -p "$SERVICE_ROOT/databases/" - touch "$SERVICE_ROOT/databases/$SERVICE" + touch "$SERVICE_ROOT/databases/postgres" fi } diff --git a/functions b/functions index 1859b271..28c70a8b 100755 --- a/functions +++ b/functions @@ -25,7 +25,7 @@ service_create() { local SERVICE="$1" [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] || dokku_log_fail "$PLUGIN_SERVICE service $SERVICE already exists" - SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"; LINKS_FILE="$SERVICE_ROOT/LINKS" + SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"; LINKS_FILE="$SERVICE_ROOT/LINKS"; AUTH_DIR="$SERVICE_ROOT/auth"; DB_DIR="$SERVICE_ROOT/databases" service_parse_args "${@:2}" @@ -35,14 +35,17 @@ service_create() { mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory" + mkdir -p "$AUTH_DIR" || dokku_log_fail "Unable to create service auth directory" + chmod 750 "$AUTH_DIR" + mkdir -p "$DB_DIR" || dokku_log_fail "Unable to create service databases directory" touch "$LINKS_FILE" PASSWORD=$(openssl rand -hex 16) if [[ -n "$SERVICE_PASSWORD" ]]; then PASSWORD="$SERVICE_PASSWORD" dokku_log_warn "Specified password may not be as secure as the auto-generated password" fi - echo "$PASSWORD" > "$SERVICE_ROOT/PASSWORD" - chmod 640 "$SERVICE_ROOT/PASSWORD" + echo "$PASSWORD" > "$AUTH_DIR/postgres" + chmod 640 "$AUTH_DIR/postgres" [[ -n "$SERVICE_CUSTOM_ENV" ]] && POSTGRES_CUSTOM_ENV="$SERVICE_CUSTOM_ENV" if [[ -n $POSTGRES_CUSTOM_ENV ]]; then @@ -59,6 +62,7 @@ service_create_container() { local SERVICE_NAME="$(get_service_name "$SERVICE")" local PASSWORD="$(cat "$SERVICE_ROOT/auth/postgres")" local PREVIOUS_ID + local DB_DIR="$SERVICE_ROOT/databases" ID=$(docker run --name "$SERVICE_NAME" -v "$SERVICE_ROOT/data:/var/lib/postgresql/data" -e "POSTGRES_PASSWORD=$PASSWORD" --env-file="$SERVICE_ROOT/ENV" -d --restart always --label dokku=service --label dokku.service=postgres "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION") echo "$ID" > "$SERVICE_ROOT/ID" @@ -68,6 +72,7 @@ service_create_container() { dokku_log_verbose_quiet "Creating container database" DATABASE_NAME="$(get_database_name "$SERVICE")" + touch "$DB_DIR/$DATABASE_NAME" docker exec "$SERVICE_NAME" su - postgres -c "createdb -E utf8 $DATABASE_NAME" 2> /dev/null || echo 'Already exists' dokku_log_verbose_quiet "Securing connection to database" diff --git a/install b/install index 57f88332..39fcc02c 100755 --- a/install +++ b/install @@ -1,6 +1,7 @@ #!/usr/bin/env bash source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x +source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" plugin-install() { pull-docker-image() { @@ -36,6 +37,10 @@ plugin-install() { EOL chmod 0440 "$_SUDOERS_FILE" + + for d in "$PLUGIN_DATA_ROOT"/* ; do + check_auth_migration "$d" + done } plugin-install "$@" diff --git a/subcommands/link b/subcommands/link index 16ebf99a..7c592fce 100755 --- a/subcommands/link +++ b/subcommands/link @@ -51,9 +51,6 @@ service-link-cmd() { --user) USER=${args[$next_index]}; skip=true ;; - --database) - DATABASE=${args[$next_index]}; skip=true - ;; *) positional+=("$arg") esac @@ -67,9 +64,8 @@ service-link-cmd() { [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_app_name "$APP" verify_service_name "$SERVICE" - [[ -z "$USER" ]] || verify_user_name "$SERVICE" "$USER" [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" - service_link "$SERVICE" "$APP" "$USER" "$DATABASE" + service_link "$SERVICE" "$APP" "$DATABASE" } service-link-cmd "$@" diff --git a/subcommands/unlink b/subcommands/unlink index 23531aca..ec780a50 100755 --- a/subcommands/unlink +++ b/subcommands/unlink @@ -21,9 +21,6 @@ service-unlink-cmd() { for arg in "$@"; do $skip && skip=false && local next_index=$(( next_index + 1 )) && continue case "$arg" in - --user) - USER=${args[$next_index]}; skip=true - ;; --database) DATABASE=${args[$next_index]}; skip=true ;; @@ -40,8 +37,7 @@ service-unlink-cmd() { verify_service_name "$SERVICE" verify_app_name "$APP" [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" - [[ -z "$USER" ]] || verify_user_name "$SERVICE" "$USER" - service_unlink "$SERVICE" "$APP" "$USER" "$DATABASE" + service_unlink "$SERVICE" "$APP" "$DATABASE" } From b14c5bde796086fe22bd5d210c261abc96248ecc Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 14:39:11 +0100 Subject: [PATCH 13/18] Make link and unlink play nice with multiple db --- common-functions | 16 +++++++++++++--- functions | 1 - subcommands/link | 11 ++++------- subcommands/unlink | 12 ++++-------- tests/service_link.bats | 4 ++-- tests/service_unlink.bats | 7 ++++--- 6 files changed, 27 insertions(+), 24 deletions(-) diff --git a/common-functions b/common-functions index 8c856f1b..379afd23 100755 --- a/common-functions +++ b/common-functions @@ -24,6 +24,17 @@ get_database_name() { echo "$DATABASE" | tr .- _ } +get_database_user_name() { + declare SERVICE="$1" + declare DATABASE="$2" + + if [ "$DATABASE" = "$SERVICE" ]; then + echo "postgres" + else + echo "$DATABASE" + fi +} + get_random_ports() { declare desc="Retrieves N random ports" declare iterations="${1:-1}" @@ -332,7 +343,7 @@ service_link() { update_plugin_scheme_for_app "$APP" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local DATABASE=${3:-$(get_database_name "$SERVICE")} - local USER="$DATABASE" + local USER=$(get_database_user_name "$SERVICE" "$DATABASE") local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") local SERVICE_NAME="$(get_service_name "$SERVICE")" @@ -611,7 +622,7 @@ service_unlink() { declare SERVICE="$1" APP="$2" local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local DATABASE=${3:-$(get_database_name "$SERVICE")} - local USER="$DATABASE" + local USER=$(get_database_user_name "$SERVICE" "$DATABASE") local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") update_plugin_scheme_for_app "$APP" local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") @@ -739,7 +750,6 @@ check_auth_migration() { dokku_log_verbose_quiet "Migrating root user to multi-user format for $SERVICE" local AUTH_DIR="$SERVICE_ROOT/auth" mkdir -p "$AUTH_DIR" - chmod 750 "$AUTH_DIR" mv "$SERVICE_ROOT/PASSWORD" "$AUTH_DIR/postgres" mkdir -p "$SERVICE_ROOT/databases/" touch "$SERVICE_ROOT/databases/postgres" diff --git a/functions b/functions index 28c70a8b..7714e789 100755 --- a/functions +++ b/functions @@ -36,7 +36,6 @@ service_create() { mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory" mkdir -p "$AUTH_DIR" || dokku_log_fail "Unable to create service auth directory" - chmod 750 "$AUTH_DIR" mkdir -p "$DB_DIR" || dokku_log_fail "Unable to create service databases directory" touch "$LINKS_FILE" PASSWORD=$(openssl rand -hex 16) diff --git a/subcommands/link b/subcommands/link index 7c592fce..532383f2 100755 --- a/subcommands/link +++ b/subcommands/link @@ -41,15 +41,14 @@ service-link-cmd() { #A app, app to run command against declare desc="link the $PLUGIN_SERVICE service to the app" local cmd="$PLUGIN_COMMAND_PREFIX:link" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 - - local USER='' + declare SERVICE="$1" APP="$2" DATABASE_FLAG="" local next_index=1; local skip=false; local args=("$@"); local positional=() for arg in "$@"; do $skip && skip=false && local next_index=$(( next_index + 1 )) && continue case "$arg" in - --user) - USER=${args[$next_index]}; skip=true + --database) + DATABASE=${args[$next_index]}; skip=true ;; *) positional+=("$arg") @@ -57,13 +56,11 @@ service-link-cmd() { local next_index=$(( next_index + 1 )) done - declare SERVICE="${positional[0]}" APP="${positional[1]}" APP=${APP:="$DOKKU_APP_NAME"} - [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" + verify_service_name "$SERVICE" [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_app_name "$APP" - verify_service_name "$SERVICE" [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" service_link "$SERVICE" "$APP" "$DATABASE" } diff --git a/subcommands/unlink b/subcommands/unlink index ec780a50..83c75e38 100755 --- a/subcommands/unlink +++ b/subcommands/unlink @@ -12,10 +12,7 @@ service-unlink-cmd() { #A app, app to run command against declare desc="unlink the $PLUGIN_SERVICE service from the app" local cmd="$PLUGIN_COMMAND_PREFIX:unlink" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 - declare SERVICE="$1" APP="$2" - APP=${APP:="$DOKKU_APP_NAME"} - - local USER='' + declare SERVICE="$1" APP="$2" DATABASE_FLAG="" local next_index=1; local skip=false; local args=("$@"); local positional=() for arg in "$@"; do @@ -30,15 +27,14 @@ service-unlink-cmd() { local next_index=$(( next_index + 1 )) done - declare SERVICE="${positional[0]}" APP="${positional[1]}" + APP=${APP:="$DOKKU_APP_NAME"} [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a name for the service" - [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_service_name "$SERVICE" + [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" verify_app_name "$APP" - [[ -z "$DATABASE" ]] || verify_database_name "$SERVICE" "$DATABASE" + [[ -z "$DATABASE_FLAG" ]] || verify_database_name "$SERVICE" "$DATABASE_FLAG" service_unlink "$SERVICE" "$APP" "$DATABASE" - } service-unlink-cmd "$@" diff --git a/tests/service_link.bats b/tests/service_link.bats index 131e6c48..5986f910 100755 --- a/tests/service_link.bats +++ b/tests/service_link.bats @@ -40,7 +40,7 @@ teardown() { @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")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_contains "$url" "postgres://postgres:$password@dokku-postgres-l:5432/l" dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app } @@ -64,7 +64,7 @@ teardown() { dokku config:set my_app POSTGRES_DATABASE_SCHEME=postgres2 dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app url=$(dokku config:get my_app DATABASE_URL) - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_contains "$url" "postgres2://postgres:$password@dokku-postgres-l:5432/l" dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app } diff --git a/tests/service_unlink.bats b/tests/service_unlink.bats index 704c6e25..302ab73c 100755 --- a/tests/service_unlink.bats +++ b/tests/service_unlink.bats @@ -39,11 +39,12 @@ teardown() { @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 | xargs) + options=$(dokku docker-options:report my_app | xargs) + echo "$options" check_value="" - [[ "$(dokku version)" == "master" ]] && check_value="Deploy options: --restart=on-failure:10" + [[ "$(dokku version)" == "master" ]] && check_value="Docker options deploy: --restart=on-failure:10" [[ "$(at-least-version 0.7.0 "$(dokku version)")" == "true" ]] && check_value="Deploy options: --restart=on-failure:10" - assert_equal "$options" "$check_value" + assert_contains "$options" "$check_value" } @test "($PLUGIN_COMMAND_PREFIX:unlink) unsets config url from app" { From 35876d11c4091b1235378002c52e58f8a1c935f8 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 14:51:36 +0100 Subject: [PATCH 14/18] Fix import/export tests --- tests/service_export.bats | 4 ++-- tests/service_import.bats | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/service_export.bats b/tests/service_export.bats index 8d0c4e06..9dc4419c 100755 --- a/tests/service_export.bats +++ b/tests/service_export.bats @@ -25,7 +25,7 @@ teardown() { export ECHO_DOCKER_COMMAND="true" export SSH_TTY=`tty` run dokku "$PLUGIN_COMMAND_PREFIX:export" l - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_exit_status 0 assert_output "docker exec dokku.postgres.l env PGPASSWORD=$password pg_dump -Fc --no-acl --no-owner -h localhost -U postgres -w l" } @@ -34,7 +34,7 @@ teardown() { export ECHO_DOCKER_COMMAND="true" unset SSH_TTY run dokku "$PLUGIN_COMMAND_PREFIX:export" l - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_exit_status 0 assert_output "docker exec dokku.postgres.l env PGPASSWORD=$password pg_dump -Fc --no-acl --no-owner -h localhost -U postgres -w l" } diff --git a/tests/service_import.bats b/tests/service_import.bats index a9dfb1c4..76f24c05 100755 --- a/tests/service_import.bats +++ b/tests/service_import.bats @@ -31,7 +31,7 @@ teardown() { @test "($PLUGIN_COMMAND_PREFIX:import) success" { export ECHO_DOCKER_COMMAND="true" run dokku "$PLUGIN_COMMAND_PREFIX:import" l < "$PLUGIN_DATA_ROOT/fake.dump" - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_output "docker exec -i dokku.postgres.l env PGPASSWORD=$password pg_restore -h localhost -cO -d l -U postgres -w" } From 7f6d90f1873499f4065f4be37a1f60ea1a1bfe09 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 14:57:27 +0100 Subject: [PATCH 15/18] Fix info tests --- tests/service_info.bats | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/service_info.bats b/tests/service_info.bats index 980d6a88..84d1e77f 100755 --- a/tests/service_info.bats +++ b/tests/service_info.bats @@ -21,21 +21,21 @@ teardown() { @test "($PLUGIN_COMMAND_PREFIX:info) success" { run dokku "$PLUGIN_COMMAND_PREFIX:info" l - local password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + local password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_contains "${lines[*]}" "postgres://postgres:$password@dokku-postgres-l:5432/l" } @test "($PLUGIN_COMMAND_PREFIX:info) replaces underscores by dash in hostname" { dokku "$PLUGIN_COMMAND_PREFIX:create" test_with_underscores run dokku "$PLUGIN_COMMAND_PREFIX:info" test_with_underscores - local password="$(cat "$PLUGIN_DATA_ROOT/test_with_underscores/PASSWORD")" + local password="$(cat "$PLUGIN_DATA_ROOT/test_with_underscores/auth/postgres")" assert_contains "${lines[*]}" "postgres://postgres:$password@dokku-postgres-test-with-underscores:5432/test_with_underscores" dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" test_with_underscores } @test "($PLUGIN_COMMAND_PREFIX:info) success with flag" { run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn - local password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + local password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" assert_output "postgres://postgres:$password@dokku-postgres-l:5432/l" run dokku "$PLUGIN_COMMAND_PREFIX:info" l --config-dir From f464d174f4e4330b47c77c6ec92650075725b505 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 15:06:04 +0100 Subject: [PATCH 16/18] Adjust PASSWORD file for tests --- tests/service_promote.bats | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/service_promote.bats b/tests/service_promote.bats index a5ba44ae..baa373a9 100755 --- a/tests/service_promote.bats +++ b/tests/service_promote.bats @@ -39,7 +39,7 @@ teardown() { } @test "($PLUGIN_COMMAND_PREFIX:promote) changes DATABASE_URL" { - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" 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) @@ -47,14 +47,14 @@ teardown() { } @test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" { - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" 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_" } @test "($PLUGIN_COMMAND_PREFIX:promote) uses POSTGRES_DATABASE_SCHEME variable" { - password="$(cat "$PLUGIN_DATA_ROOT/l/PASSWORD")" + password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" dokku config:set my_app "POSTGRES_DATABASE_SCHEME=postgres2" "DATABASE_URL=postgres://u:p@host:5432/db" "DOKKU_POSTGRES_BLUE_URL=postgres2://postgres:$password@dokku-postgres-l:5432/l" dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app url=$(dokku config:get my_app DATABASE_URL) From 5f2d9c3129565ed913e65e4ba3765d105137b073 Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 15:26:12 +0100 Subject: [PATCH 17/18] Fix false negatives --- tests/service_list.bats | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/service_list.bats b/tests/service_list.bats index de5a859b..cb92576e 100755 --- a/tests/service_list.bats +++ b/tests/service_list.bats @@ -11,20 +11,20 @@ teardown() { @test "($PLUGIN_COMMAND_PREFIX:list) with no exposed ports, no linked apps" { run dokku "$PLUGIN_COMMAND_PREFIX:list" - assert_contains "${lines[*]}" "l postgres:10.2 running - -" + assert_contains "${lines[*]}" "l postgres:10.2 running - l postgres -" } @test "($PLUGIN_COMMAND_PREFIX:list) with exposed ports" { dokku "$PLUGIN_COMMAND_PREFIX:expose" l 4242 run dokku "$PLUGIN_COMMAND_PREFIX:list" - assert_contains "${lines[*]}" "l postgres:10.2 running 5432->4242 -" + assert_contains "${lines[*]}" "l postgres:10.2 running 5432->4242 l postgres -" } @test "($PLUGIN_COMMAND_PREFIX:list) with linked app" { dokku apps:create my_app dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app run dokku "$PLUGIN_COMMAND_PREFIX:list" - assert_contains "${lines[*]}" "l postgres:10.2 running - my_app" + assert_contains "${lines[*]}" "l postgres:10.2 running - l postgres my_app" dokku --force apps:destroy my_app } From c1253ac5b9b3fc226b3ecc581b4f1b37bd5ee29b Mon Sep 17 00:00:00 2001 From: sarendsen Date: Wed, 28 Feb 2018 17:40:41 +0100 Subject: [PATCH 18/18] Fixes to promote --- common-functions | 27 ++++++++++----------------- tests/service_promote.bats | 1 + 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/common-functions b/common-functions index 379afd23..2cc489c0 100755 --- a/common-functions +++ b/common-functions @@ -552,26 +552,19 @@ service_promote() { local PLUGIN_DEFAULT_CONFIG_VAR="${PLUGIN_DEFAULT_ALIAS}_URL" local EXISTING_CONFIG=$(config_all "$APP") update_plugin_scheme_for_app "$APP" - local SERVICE_URL=$(service_url "$SERVICE") - local CONFIG_VARS=($(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1)) || true + local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" local PREVIOUS_DEFAULT_URL=$(get_url_from_config "$EXISTING_CONFIG" "$PLUGIN_DEFAULT_CONFIG_VAR") + local USER="postgres" + local DATABASE="$SERVICE" + local PASSWORD=$(cat "$SERVICE_ROOT/auth/$USER") + local SERVICE_URL=$(service_url "$SERVICE" "$USER" "$PASSWORD" "$DATABASE") + local CONFIG_VAR=$(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1) || true - [[ -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" + [[ -z $CONFIG_VAR ]] && dokku_log_fail "Not linked to app $APP" + [[ $CONFIG_VAR =~ $PLUGIN_DEFAULT_CONFIG_VAR ]] && dokku_log_fail "Service $1 already promoted as $PLUGIN_DEFAULT_CONFIG_VAR" - # shellcheck disable=SC2086 - config_set "$APP" $NEW_CONFIG_VARS + config_set --no-restart "$APP" "${PLUGIN_DEFAULT_CONFIG_VAR}=$SERVICE_URL" + config_set "$APP" "${CONFIG_VAR}=$PREVIOUS_DEFAULT_URL" } service_set_alias() { diff --git a/tests/service_promote.bats b/tests/service_promote.bats index baa373a9..9170e28c 100755 --- a/tests/service_promote.bats +++ b/tests/service_promote.bats @@ -53,6 +53,7 @@ teardown() { run dokku config my_app assert_contains "${lines[*]}" "DOKKU_POSTGRES_" } + @test "($PLUGIN_COMMAND_PREFIX:promote) uses POSTGRES_DATABASE_SCHEME variable" { password="$(cat "$PLUGIN_DATA_ROOT/l/auth/postgres")" dokku config:set my_app "POSTGRES_DATABASE_SCHEME=postgres2" "DATABASE_URL=postgres://u:p@host:5432/db" "DOKKU_POSTGRES_BLUE_URL=postgres2://postgres:$password@dokku-postgres-l:5432/l"