├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── Vagrantfile ├── commands ├── common-functions ├── config ├── functions ├── help-functions ├── install ├── plugin.toml ├── pre-delete ├── subcommands ├── create ├── destroy ├── expose ├── info ├── link ├── linked ├── list ├── logs ├── promote ├── restart ├── start ├── stop ├── unexpose └── unlink └── tests ├── hook_pre_delete.bats ├── service_create.bats ├── service_destroy.bats ├── service_expose.bats ├── service_info.bats ├── service_link.bats ├── service_list.bats ├── service_logs.bats ├── service_promote.bats ├── service_restart.bats ├── service_start.bats ├── service_stop.bats ├── service_unexpose.bats ├── service_unlink.bats ├── setup.sh └── test_helper.bash /.gitignore: -------------------------------------------------------------------------------- 1 | tests/dokku 2 | tests/fixtures 3 | tests/bin/plugn 4 | tests/bin/readlink 5 | .vagrant 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | language: bash 3 | install: make setup 4 | script: make test 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL=/bin/bash 2 | 3 | test: setup clean lint 4 | @echo Running tests... 5 | @$(QUIET) bats tests 6 | 7 | shellcheck: 8 | ifeq ($(shell shellcheck > /dev/null 2>&1 ; echo $$?),127) 9 | ifeq ($(shell uname),Darwin) 10 | brew install shellcheck 11 | else 12 | sudo add-apt-repository 'deb http://archive.ubuntu.com/ubuntu trusty-backports main restricted universe multiverse' 13 | sudo apt-get update -qq && sudo apt-get install -qq -y shellcheck 14 | endif 15 | endif 16 | 17 | bats: 18 | ifeq ($(shell bats > /dev/null 2>&1 ; echo $$?),127) 19 | ifeq ($(shell uname),Darwin) 20 | git clone https://github.com/sstephenson/bats.git /tmp/bats 21 | cd /tmp/bats && sudo ./install.sh /usr/local 22 | rm -rf /tmp/bats 23 | else 24 | sudo add-apt-repository ppa:duggan/bats --yes 25 | sudo apt-get update -qq && sudo apt-get install -qq -y bats 26 | endif 27 | endif 28 | 29 | dokku: 30 | ifeq ($(shell dokku > /dev/null 2>&1 ; echo $$?),127) 31 | @echo Installing dokku 32 | curl https://raw.githubusercontent.com/dokku/dokku/v0.14.6/bootstrap.sh | sudo bash 33 | endif 34 | 35 | dependencies: dokku shellcheck bats 36 | 37 | lint: 38 | # these are disabled due to their expansive existence in the codebase. we should clean it up though 39 | # SC1090: Can't follow non-constant source. Use a directive to specify location. 40 | # SC2034: Variable appears unused. Verify it or export it. 41 | # SC2155: Declare and assign separately to avoid masking return values. 42 | @echo Linting... 43 | @$(QUIET) find ./ -maxdepth 1 -not -path '*/\.*' | xargs file | egrep "shell|bash" | awk '{ print $$1 }' | sed 's/://g' | xargs shellcheck -e SC1090,SC2034,SC2155 44 | 45 | setup: dependencies 46 | bash tests/setup.sh 47 | 48 | clean: 49 | . $(shell pwd)/tests/test_helper.bash && reset_system_data 50 | 51 | .PHONY: test clean setup lint dependencies dokku shellcheck bats 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dokku chrome 2 | 3 | A headless browser service for dokku which can be used by applications to generate PDFs, take screenshots and so on. 4 | 5 | This service runs a Chrome browser via the [browserless/chrome](https://hub.docker.com/r/browserless/chrome) image from Docker. This image is kindly provided by [browserless](https://browserless.io), and if you are planning to use it as part of a commercial service, you must [purchase a license](https://www.browserless.io/commercial-license). However, it is free for use by open-source projects. 6 | 7 | One of the main benefits of the browserless docker image is that it includes a REST API which can be used to easily generate PDFs, screenshots and so on. REST API documentation can be found at https://docs.browserless.io/docs/pdf.html 8 | 9 | ## Requirements 10 | 11 | - dokku 0.8.1+ 12 | - docker 1.8.x 13 | 14 | ## Installation 15 | 16 | ```shell 17 | # on 0.4.x+ 18 | sudo dokku plugin:install https://github.com/lazyatom/dokku-chrome.git chrome 19 | ``` 20 | 21 | ## Commands 22 | 23 | ``` 24 | chrome:app-links List all chrome service links for a given app 25 | chrome:create Create a chrome service with environment variables 26 | chrome:destroy Delete the service, delete the data and stop its container if there are no links left 27 | chrome:enter [command] Enter or run a command in a running chrome service container 28 | chrome:exists Check if the chrome service exists 29 | chrome:expose [port] Expose a chrome service on custom port if provided (random port otherwise) 30 | chrome:info Print the connection information 31 | chrome:link Link the chrome service to the app 32 | chrome:linked Check if the chrome service is linked to an app 33 | chrome:list List all chrome services 34 | chrome:logs [-t] Print the most recent log(s) for this service 35 | chrome:promote Promote service as CHROME_URL in 36 | chrome:restart Graceful shutdown and restart of the chrome service container 37 | chrome:start Start a previously stopped chrome service 38 | chrome:stop Stop a running chrome service 39 | chrome:unexpose Unexpose a previously exposed chrome service 40 | chrome:unlink Unlink the chrome service from the app 41 | chrome:upgrade Upgrade service to the specified version 42 | ``` 43 | 44 | ## Rsage 45 | 46 | ```shell 47 | # Create a chrome service named lolipop 48 | dokku chrome:create lolipop 49 | 50 | # You can also specify the image and image 51 | # version to use for the service 52 | # it *must* be compatible with the 53 | # official browserless/chrome image 54 | export CHROME_IMAGE="browserless/chrome" 55 | export CHROME_IMAGE_VERSION="1.6.2" 56 | dokku chrome:create lolipop 57 | 58 | # You can also specify custom environment 59 | # variables to start the chrome service 60 | # in semi-colon separated form 61 | export CHROME_CUSTOM_ENV="MAX_CONCURRENT_SESSIONS=10" 62 | dokku chrome:create lolipop 63 | 64 | # Get connection information as follows 65 | dokku chrome:info lolipop 66 | 67 | # You can also retrieve a specific piece of service info via flags 68 | dokku chrome:info lolipop --config-dir 69 | dokku chrome:info lolipop --data-dir 70 | dokku chrome:info lolipop --dsn 71 | dokku chrome:info lolipop --exposed-ports 72 | dokku chrome:info lolipop --id 73 | dokku chrome:info lolipop --internal-ip 74 | dokku chrome:info lolipop --links 75 | dokku chrome:info lolipop --service-root 76 | dokku chrome:info lolipop --status 77 | dokku chrome:info lolipop --version 78 | 79 | # A bash prompt can be opened against a running service 80 | # filesystem changes will not be saved to disk 81 | dokku chrome:enter lolipop 82 | 83 | # You may also run a command directly against the service 84 | # filesystem changes will not be saved to disk 85 | dokku chrome:enter lolipop ls -lah / 86 | 87 | # A chrome service can be linked to a 88 | # container this will use native docker 89 | # links via the docker-options plugin 90 | # here we link it to our 'playground' app 91 | # NOTE: this will restart your app 92 | dokku chrome:link lolipop playground 93 | 94 | # The following environment variables will be set automatically by docker (not 95 | # on the app itself, so they won’t be listed when calling dokku config) 96 | # 97 | # DOKKU_CHROME_LOLIPOP_NAME=/random_name/CHROME 98 | # DOKKU_CHROME_LOLIPOP_PORT=tcp://172.17.0.1:3000 99 | # DOKKU_CHROME_LOLIPOP_PORT_3000_TCP=tcp://172.17.0.1:3000 100 | # DOKKU_CHROME_LOLIPOP_PORT_3000_TCP_PROTO=tcp 101 | # DOKKU_CHROME_LOLIPOP_PORT_3000_TCP_PORT=3000 102 | # DOKKU_CHROME_LOLIPOP_PORT_3000_TCP_ADDR=172.17.0.1 103 | # 104 | # and the following will be set on the linked application by default 105 | # 106 | # CHROME_URL=http://dokku-chrome-lolipop:3000 107 | # 108 | # NOTE: the host exposed here only works internally in docker containers. If 109 | # you want your container to be reachable from outside, you should use `expose`. 110 | 111 | # Another service can be linked to your app 112 | dokku chrome:link other_service playground 113 | 114 | # Since CHROME_URL is already in use, another environment variable will be 115 | # generated automatically 116 | # 117 | # DOKKU_CHROME_BLUE_URL=http://dokku-chrome-other-service:3000 118 | 119 | # You can then promote the new service to be the primary one 120 | # NOTE: this will restart your app 121 | dokku chrome:promote other_service playground 122 | 123 | # This will replace CHROME_URL with the url from other_service and generate 124 | # another environment variable to hold the previous value if necessary. 125 | # you could end up with the following for example: 126 | # 127 | # CHROME_URL=http://dokku-chrome-other-service:3000 128 | # DOKKU_CHROME_BLUE_URL=http://dokku-chrome-other-service:3000 129 | # DOKKU_CHROME_SILVER_URL=http://dokku-chrome-lolipop:3000 130 | 131 | # You can also unlink a chrome service 132 | # NOTE: this will restart your app and unset related environment variables 133 | dokku chrome:unlink lolipop playground 134 | 135 | # You can tail logs for a particular service 136 | dokku chrome:logs lolipop 137 | dokku chrome:logs lolipop -t # to tail 138 | 139 | # Finally, you can destroy the container 140 | dokku chrome:destroy lolipop 141 | ``` 142 | 143 | ## Disabling `docker pull` calls 144 | 145 | If you wish to disable the `docker pull` calls that the plugin triggers, you may set the `CHROME_DISABLE_PULL` environment variable to `true`. Once disabled, you will need to pull the service image you wish to deploy as shown in the `stderr` output. 146 | 147 | Please ensure the proper images are in place when `docker pull` is disabled. 148 | 149 | 150 | ## Thanks 151 | 152 | This plugin was extensively based on the official storage plugins for dokku (e.g. https://github.com/dokku/dokku-postgres) -- thanks to the authors of those plugins for all their hard work! 153 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | BOX_NAME = ENV["BOX_NAME"] || "bento/ubuntu-18.04" 5 | BOX_MEMORY = ENV["BOX_MEMORY"] || "512" 6 | DOKKU_VERSION = "master" 7 | 8 | Vagrant.configure(2) do |config| 9 | config.vm.box = BOX_NAME 10 | config.ssh.forward_agent = true 11 | 12 | config.vm.provider :virtualbox do |vb| 13 | # Ubuntu's Raring 64-bit cloud image is set to a 32-bit Ubuntu OS type by 14 | # default in Virtualbox and thus will not boot. Manually override that. 15 | vb.customize ["modifyvm", :id, "--ostype", "Ubuntu_64"] 16 | vb.customize ["modifyvm", :id, "--memory", BOX_MEMORY] 17 | end 18 | 19 | config.vm.provider :vmware_fusion do |v, override| 20 | v.vmx["memsize"] = BOX_MEMORY 21 | end 22 | 23 | config.vm.define "default", primary: true do |vm| 24 | vm.vm.synced_folder File.dirname(__FILE__), "/vagrant" 25 | 26 | vm.vm.provision :shell, :inline => "curl https://raw.githubusercontent.com/dokku/dokku/v0.14.6/bootstrap.sh | bash" 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /commands: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | [[ " help $PLUGIN_COMMAND_PREFIX:help $PLUGIN_COMMAND_PREFIX $PLUGIN_COMMAND_PREFIX:default " == *" $1 "* ]] || [[ "$1" == "$PLUGIN_COMMAND_PREFIX:"* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT" 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 6 | 7 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/help-functions" 8 | 9 | if [[ ! -d $PLUGIN_CONFIG_ROOT ]]; then 10 | dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" 11 | fi 12 | 13 | if [[ ! -d $PLUGIN_DATA_ROOT ]]; then 14 | dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" 15 | fi 16 | 17 | fn-help "$@" 18 | -------------------------------------------------------------------------------- /common-functions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 3 | source "$PLUGIN_AVAILABLE_PATH/config/functions" 4 | 5 | docker_ports_options() { 6 | declare desc="Exports a list of exposed ports" 7 | declare PORTS=("$@") 8 | for (( i=0; i < ${#PLUGIN_PORTS[@]}; i++ )); do 9 | echo -n "-p ${PORTS[i]}:${PLUGIN_PORTS[i]} " 10 | done 11 | } 12 | 13 | get_container_ip() { 14 | declare desc="Retrieves the ip address of a container" 15 | declare CONTAINER_ID="$1" 16 | docker inspect --format '{{ .NetworkSettings.IPAddress }}' "$CONTAINER_ID" 17 | } 18 | 19 | get_random_ports() { 20 | declare desc="Retrieves N random ports" 21 | declare iterations="${1:-1}" 22 | for (( i=0; i < iterations; i++ )); do 23 | local port=$RANDOM 24 | local quit=0 25 | while [ "$quit" -ne 1 ]; do 26 | netstat -an | grep $port > /dev/null 27 | # shellcheck disable=SC2181 28 | if [ $? -gt 0 ]; then 29 | quit=1 30 | else 31 | port=$((port + 1)) 32 | fi 33 | done 34 | echo $port 35 | done 36 | } 37 | 38 | get_service_name() { 39 | declare desc="Retrieves a docker service label" 40 | declare SERVICE="$1" 41 | echo "dokku.${PLUGIN_COMMAND_PREFIX}.$SERVICE" 42 | } 43 | 44 | get_url_from_config() { 45 | declare desc="Retrieves a given _URL from a list of configuration variables" 46 | declare EXISTING_CONFIG="$1" CONFIG_VAR="$2" 47 | echo "$EXISTING_CONFIG" | grep "$CONFIG_VAR" | sed "s/$CONFIG_VAR:\s*//" | xargs 48 | } 49 | 50 | is_container_status() { 51 | declare desc="Returns 0 or 1 depending upon whether a given container has a certain status" 52 | declare CID="$1" STATUS="$2" 53 | local TEMPLATE="{{.State.$STATUS}}" 54 | local CONTAINER_STATUS=$(docker inspect -f "$TEMPLATE" "$CID" 2> /dev/null || true) 55 | 56 | if [[ "$CONTAINER_STATUS" == "true" ]]; then 57 | return 0 58 | fi 59 | return 1 60 | } 61 | 62 | is_implemented_command() { 63 | declare desc="return true if value ($1) is in list (all other arguments)" 64 | declare CMD="$1" 65 | CMD="$(echo "$CMD" | cut -d ':' -f2)" 66 | 67 | if [[ ${#PLUGIN_UNIMPLEMENTED_SUBCOMMANDS[@]} -eq 0 ]]; then 68 | return 0 69 | fi 70 | 71 | local e 72 | for e in "${PLUGIN_UNIMPLEMENTED_SUBCOMMANDS[@]}"; do 73 | [[ "$e" == "$CMD" ]] && return 1 74 | done 75 | return 0 76 | } 77 | 78 | remove_from_links_file() { 79 | declare desc="Removes an app from the service link file" 80 | declare SERVICE="$1" APP="$2" 81 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 82 | local LINKS_FILE="$SERVICE_ROOT/LINKS" 83 | 84 | mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" 85 | touch "$LINKS_FILE" 86 | sed -i.bak "/^$APP\$/d" "$LINKS_FILE" && rm "$LINKS_FILE.bak" 87 | sort "$LINKS_FILE" -u -o "$LINKS_FILE" 88 | } 89 | 90 | service_dns_hostname() { 91 | declare desc="Retrieves the alias of a service" 92 | declare SERVICE="$1" 93 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 94 | echo "$SERVICE_NAME" | tr ._ - 95 | } 96 | 97 | service_alternative_alias() { 98 | declare desc="Retrieves an alternative alias for a service" 99 | declare EXISTING_CONFIG="$1" 100 | local COLORS=(AQUA BLACK BLUE FUCHSIA GRAY GREEN LIME MAROON NAVY OLIVE PURPLE RED SILVER TEAL WHITE YELLOW) 101 | local ALIAS; 102 | 103 | for COLOR in "${COLORS[@]}"; do 104 | ALIAS="${PLUGIN_ALT_ALIAS}_${COLOR}" 105 | local IN_USE=$(echo "$EXISTING_CONFIG" | grep "${ALIAS}_URL") 106 | if [[ -n $IN_USE ]]; then 107 | unset ALIAS 108 | fi 109 | done 110 | echo "$ALIAS" 111 | } 112 | 113 | service_app_links() { 114 | declare desc="Outputs all service links for a given app" 115 | declare APP="$1" 116 | local SERVICE LINKED_APP 117 | 118 | pushd "$PLUGIN_DATA_ROOT" > /dev/null 119 | for SERVICE in *; do 120 | [[ -f "$SERVICE/LINKS" ]] || continue 121 | for LINKED_APP in $(<"$SERVICE/LINKS"); do 122 | if [[ "$LINKED_APP" == "$APP" ]] ; then 123 | echo "$SERVICE" 124 | fi 125 | done 126 | done 127 | } 128 | 129 | service_backup() { 130 | declare desc="Creates a backup of a service to an existing s3 bucket" 131 | declare SERVICE="$1" BUCKET_NAME="$2" USE_IAM_OPTIONAL_FLAG="$3" 132 | local SERVICE_BACKUP_ROOT="$PLUGIN_DATA_ROOT/$SERVICE/backup" 133 | local BACKUP_ENCRYPTION_CONFIG_ROOT="$PLUGIN_DATA_ROOT/$SERVICE/backup-encryption" 134 | local AWS_ACCESS_KEY_ID_FILE="$SERVICE_BACKUP_ROOT/AWS_ACCESS_KEY_ID" 135 | local AWS_SECRET_ACCESS_KEY_FILE="$SERVICE_BACKUP_ROOT/AWS_SECRET_ACCESS_KEY" 136 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 137 | local ID="$(cat "$SERVICE_ROOT/ID")" 138 | local BACKUP_PARAMETERS="" 139 | 140 | if [[ -z "$USE_IAM_OPTIONAL_FLAG" ]]; then 141 | [[ ! -f "$AWS_ACCESS_KEY_ID_FILE" ]] && dokku_log_fail "Missing AWS_ACCESS_KEY_ID file" 142 | [[ ! -f "$AWS_SECRET_ACCESS_KEY_FILE" ]] && dokku_log_fail "Missing AWS_SECRET_ACCESS_KEY file" 143 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e AWS_ACCESS_KEY_ID=$(cat "$AWS_ACCESS_KEY_ID_FILE") -e AWS_SECRET_ACCESS_KEY=$(cat "$AWS_SECRET_ACCESS_KEY_FILE")" 144 | elif [[ "$USE_IAM_OPTIONAL_FLAG" != "--use-iam" ]] && [[ "$USE_IAM_OPTIONAL_FLAG" != "-u" ]]; then 145 | dokku_log_fail "Provide AWS credentials or use the --use-iam flag" 146 | fi 147 | 148 | TMPDIR=$(mktemp -d) 149 | trap 'rm -rf "$TMPDIR" > /dev/null' RETURN INT TERM EXIT 150 | 151 | docker inspect "$ID" &> /dev/null || dokku_log_fail "Service container does not exist" 152 | is_container_status "$ID" "Running" || dokku_log_fail "Service container is not running" 153 | 154 | (service_export "$SERVICE" > "${TMPDIR}/export") 155 | 156 | # Build parameter list for s3backup tool 157 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e BUCKET_NAME=$BUCKET_NAME" 158 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e BACKUP_NAME=${PLUGIN_COMMAND_PREFIX}-${SERVICE}" 159 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -v ${TMPDIR}:/backup" 160 | 161 | if [[ -f "$SERVICE_BACKUP_ROOT/AWS_DEFAULT_REGION" ]]; then 162 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e AWS_DEFAULT_REGION=$(cat "$SERVICE_BACKUP_ROOT/AWS_DEFAULT_REGION")" 163 | fi 164 | 165 | if [[ -f "$SERVICE_BACKUP_ROOT/AWS_SIGNATURE_VERSION" ]]; then 166 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e AWS_SIGNATURE_VERSION=$(cat "$SERVICE_BACKUP_ROOT/AWS_SIGNATURE_VERSION")" 167 | fi 168 | 169 | if [[ -f "$SERVICE_BACKUP_ROOT/ENDPOINT_URL" ]]; then 170 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e ENDPOINT_URL=$(cat "$SERVICE_BACKUP_ROOT/ENDPOINT_URL")" 171 | fi 172 | 173 | if [[ -f "$BACKUP_ENCRYPTION_CONFIG_ROOT/ENCRYPTION_KEY" ]]; then 174 | BACKUP_PARAMETERS="$BACKUP_PARAMETERS -e ENCRYPTION_KEY=$(cat "$BACKUP_ENCRYPTION_CONFIG_ROOT/ENCRYPTION_KEY")" 175 | fi 176 | 177 | # shellcheck disable=SC2086 178 | docker run --rm $BACKUP_PARAMETERS dokku/s3backup:0.14.0 179 | } 180 | 181 | service_backup_auth() { 182 | declare desc="Sets up authentication" 183 | declare SERVICE="$1" AWS_ACCESS_KEY_ID="$2" AWS_SECRET_ACCESS_KEY="$3" AWS_DEFAULT_REGION="$4" AWS_SIGNATURE_VERSION="$5" ENDPOINT_URL="$6" 184 | local SERVICE_BACKUP_ROOT="$PLUGIN_DATA_ROOT/$SERVICE/backup" 185 | 186 | mkdir -p "$SERVICE_BACKUP_ROOT" 187 | echo "$AWS_ACCESS_KEY_ID" > "$SERVICE_BACKUP_ROOT/AWS_ACCESS_KEY_ID" 188 | echo "$AWS_SECRET_ACCESS_KEY" > "$SERVICE_BACKUP_ROOT/AWS_SECRET_ACCESS_KEY" 189 | 190 | if [[ -n "$AWS_DEFAULT_REGION" ]]; then 191 | echo "$AWS_DEFAULT_REGION" > "$SERVICE_BACKUP_ROOT/AWS_DEFAULT_REGION" 192 | fi 193 | 194 | if [[ -n "$AWS_SIGNATURE_VERSION" ]]; then 195 | echo "$AWS_SIGNATURE_VERSION" > "$SERVICE_BACKUP_ROOT/AWS_SIGNATURE_VERSION" 196 | fi 197 | 198 | if [[ -n "$ENDPOINT_URL" ]]; then 199 | echo "$ENDPOINT_URL" > "$SERVICE_BACKUP_ROOT/ENDPOINT_URL" 200 | fi 201 | } 202 | 203 | service_backup_deauth() { 204 | declare desc="Removes authentication" 205 | declare SERVICE="$1" 206 | local SERVICE_ROOT="${PLUGIN_DATA_ROOT}/${SERVICE}" 207 | local SERVICE_BACKUP_ROOT="${SERVICE_ROOT}/backup/" 208 | 209 | rm -rf "$SERVICE_BACKUP_ROOT" 210 | } 211 | 212 | service_backup_schedule() { 213 | declare desc="schedules a backup of the service" 214 | declare SERVICE="$1" SCHEDULE="$2" BUCKET_NAME="$3" USE_IAM_OPTIONAL_FLAG="$4" 215 | local DOKKU_BIN="$(which dokku)" 216 | local CRON_FILE="/etc/cron.d/dokku-${PLUGIN_COMMAND_PREFIX}-${SERVICE}" 217 | local TMP_CRON_FILE="${PLUGIN_DATA_ROOT}/.TMP_CRON_FILE" 218 | 219 | if [[ -n "$USE_IAM_OPTIONAL_FLAG" ]] && [[ "$USE_IAM_OPTIONAL_FLAG" != "--use-iam" ]] && [[ "$USE_IAM_OPTIONAL_FLAG" != "-u" ]]; then 220 | dokku_log_fail "Invalid flag provided, only '--use-iam' allowed" 221 | fi 222 | 223 | echo "${SCHEDULE} dokku ${DOKKU_BIN} ${PLUGIN_COMMAND_PREFIX}:backup ${SERVICE} ${BUCKET_NAME} ${USE_IAM_OPTIONAL_FLAG}" > "$TMP_CRON_FILE" 224 | sudo /bin/mv "$TMP_CRON_FILE" "$CRON_FILE" 225 | sudo /bin/chown root:root "$CRON_FILE" 226 | sudo /bin/chmod 644 "$CRON_FILE" 227 | } 228 | 229 | service_backup_schedule_cat() { 230 | declare desc="cat the contents of the configured backup cronfile for the service" 231 | declare SERVICE="$1" 232 | local CRON_FILE="/etc/cron.d/dokku-${PLUGIN_COMMAND_PREFIX}-${SERVICE}" 233 | 234 | if [[ ! -f "$CRON_FILE" ]]; then 235 | dokku_log_fail "There is no scheduled backup for ${SERVICE}." 236 | fi 237 | 238 | cat "$CRON_FILE" 239 | } 240 | 241 | service_backup_unschedule() { 242 | declare desc="unschedules the backup of the service" 243 | declare SERVICE="$1" 244 | local CRON_FILE="/etc/cron.d/dokku-${PLUGIN_COMMAND_PREFIX}-${SERVICE}" 245 | 246 | sudo /bin/rm -f "$CRON_FILE" 247 | } 248 | 249 | service_backup_set_encryption() { 250 | declare desc="Sets up backup encryption" 251 | declare SERVICE="$1" ENCRYPTION_KEY="$2" 252 | local SERVICE_ROOT="${PLUGIN_DATA_ROOT}/${SERVICE}" 253 | local SERVICE_BACKUP_ENCRYPTION_ROOT="${SERVICE_ROOT}/backup-encryption/" 254 | 255 | mkdir -p "$SERVICE_BACKUP_ENCRYPTION_ROOT" 256 | echo "$ENCRYPTION_KEY" > "${SERVICE_BACKUP_ENCRYPTION_ROOT}/ENCRYPTION_KEY" 257 | } 258 | 259 | service_backup_unset_encryption() { 260 | declare desc="Removes backup encryption" 261 | declare SERVICE="$1" 262 | local SERVICE_ROOT="${PLUGIN_DATA_ROOT}/${SERVICE}" 263 | local SERVICE_BACKUP_ENCRYPTION_ROOT="${SERVICE_ROOT}/backup-encryption/" 264 | 265 | rm -rf "$SERVICE_BACKUP_ENCRYPTION_ROOT" 266 | } 267 | 268 | service_container_rm() { 269 | declare desc="Stops a service and removes the running container" 270 | declare SERVICE="$1" 271 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 272 | local ID 273 | 274 | service_stop "$SERVICE" 275 | ID=$(docker inspect "$SERVICE_NAME" -f '{{ .ID }}' 2> /dev/null || true) 276 | 277 | # this may be 'true' in tests... 278 | if [[ -z "$ID" ]] || [[ "$ID" == "true" ]]; then 279 | dokku_log_info2_quiet "I guess.. just returning." 280 | return 0 281 | fi 282 | 283 | dokku_log_verbose_quiet "Removing container" 284 | docker update --restart=no "$SERVICE_NAME" > /dev/null 2>&1 285 | if ! docker rm "$SERVICE_NAME" > /dev/null 2>&1; then 286 | dokku_log_fail "Unable to remove container for service $SERVICE" 287 | else 288 | dokku_log_info2_quiet "Removed container" 289 | fi 290 | } 291 | 292 | service_enter() { 293 | declare desc="enters running app container of specified proc type" 294 | declare SERVICE="$1" && shift 1 295 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 296 | local ID="$(cat "$SERVICE_ROOT/ID")" 297 | 298 | docker inspect "$ID" &> /dev/null || dokku_log_fail "Service container does not exist" 299 | is_container_status "$ID" "Running" || dokku_log_fail "Service container is not running" 300 | 301 | local EXEC_CMD="" 302 | has_tty && local DOKKU_RUN_OPTS+=" -i -t" 303 | # shellcheck disable=SC2086 304 | docker exec $DOKKU_RUN_OPTS $ID $EXEC_CMD "${@:-/bin/bash}" 305 | } 306 | 307 | service_exposed_ports() { 308 | declare desc="Lists exposed ports for a service" 309 | declare SERVICE="$1" 310 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 311 | local PORT_FILE="$SERVICE_ROOT/PORT" 312 | [[ ! -f $PORT_FILE ]] && echo '-' && return 0 313 | local PORTS=($(cat "$PORT_FILE")) 314 | for (( i=0; i < ${#PLUGIN_PORTS[@]}; i++ )); do 315 | echo -n "${PLUGIN_PORTS[i]}->${PORTS[i]} " 316 | done 317 | } 318 | 319 | service_image_exists() { 320 | declare desc="Checks if the current image exists" 321 | local IMAGE="$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" 322 | 323 | if [[ "$(docker images -q "$IMAGE" 2> /dev/null)" == "" ]]; then 324 | return 1 325 | fi 326 | 327 | return 0 328 | } 329 | 330 | service_info() { 331 | declare desc="Retrieves information about a given service" 332 | declare SERVICE="$1" INFO_FLAG="$2" 333 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 334 | local SERVICE_URL=$(service_url "$SERVICE") 335 | local PORT_FILE="$SERVICE_ROOT/PORT" 336 | local SERVICE_CONTAINER_ID="$(cat "$SERVICE_ROOT/ID")" 337 | local flag key valid_flags 338 | 339 | local flag_map=( 340 | "--config-dir: ${SERVICE_ROOT}/config" 341 | "--data-dir: ${SERVICE_ROOT}/data" 342 | "--dsn: ${SERVICE_URL}" 343 | "--exposed-ports: $(service_exposed_ports "$SERVICE")" 344 | "--id: ${SERVICE_CONTAINER_ID}" 345 | "--internal-ip: $(get_container_ip "${SERVICE_CONTAINER_ID}")" 346 | "--links: $(service_linked_apps "$SERVICE")" 347 | "--service-root: ${SERVICE_ROOT}" 348 | "--status: $(service_status "$SERVICE")" 349 | "--version: $(service_version "$SERVICE")" 350 | ) 351 | if [[ -z "$INFO_FLAG" ]]; then 352 | dokku_log_info2 "Container Information" 353 | for flag in "${flag_map[@]}"; do 354 | key="$(echo "${flag#--}" | cut -f1 -d' ' | tr - ' ')" 355 | dokku_log_verbose "$(printf "%-20s %-25s" "${key^}" "${flag#*: }")" 356 | done 357 | else 358 | local match=false 359 | for flag in "${flag_map[@]}"; do 360 | valid_flags="${valid_flags} $(echo "$flag" | cut -d':' -f1)" 361 | if [[ "$flag" == "${INFO_FLAG}:"* ]]; then 362 | echo "${flag#*: }" && match=true 363 | fi 364 | done 365 | [[ "$match" == "true" ]] || dokku_log_fail "Invalid flag passed, valid flags:${valid_flags}" 366 | fi 367 | } 368 | 369 | service_is_linked() { 370 | declare desc="Links a service to an application" 371 | declare SERVICE="$1" APP="$2" 372 | update_plugin_scheme_for_app "$APP" 373 | local SERVICE_URL=$(service_url "$SERVICE") 374 | local EXISTING_CONFIG=$(config_all "$APP") 375 | local LINK=$(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1) || true 376 | if [[ -z $LINK ]]; then 377 | dokku_log_warn "Service $SERVICE is not linked to $APP" 378 | exit 1 379 | fi 380 | dokku_log_info1 "Service $SERVICE is linked to $APP" 381 | } 382 | 383 | service_link() { 384 | declare desc="Links a service to an application" 385 | declare SERVICE="$1" APP="$2" 386 | update_plugin_scheme_for_app "$APP" 387 | local SERVICE_URL=$(service_url "$SERVICE") 388 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 389 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 390 | local EXISTING_CONFIG=$(config_all "$APP") 391 | local LINK=$(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1) || true 392 | local SERVICE_DNS_HOSTNAME=$(service_dns_hostname "$SERVICE") 393 | local LINKS_FILE="$SERVICE_ROOT/LINKS" 394 | local ALIAS="$PLUGIN_DEFAULT_ALIAS" 395 | local DEFAULT_ALIAS 396 | 397 | if [[ -n "$SERVICE_ALIAS" ]]; then 398 | ALIAS="$SERVICE_ALIAS" 399 | ALIAS_IN_USE=$(echo "$EXISTING_CONFIG" | grep "${ALIAS}_URL") || true 400 | [[ -n "$ALIAS_IN_USE" ]] && dokku_log_fail "Specified alias $ALIAS already in use" 401 | else 402 | DEFAULT_ALIAS=$(echo "$EXISTING_CONFIG" | grep "${PLUGIN_DEFAULT_ALIAS}_URL") || true 403 | if [[ -n "$DEFAULT_ALIAS" ]]; then 404 | ALIAS=$(service_alternative_alias "$EXISTING_CONFIG") 405 | fi 406 | [[ -z "$ALIAS" ]] && dokku_log_fail "Unable to use default or generated URL alias" 407 | fi 408 | 409 | [[ -n $LINK ]] && dokku_log_fail "Already linked as $LINK" 410 | mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" 411 | touch "$LINKS_FILE" 412 | echo "$APP" >> "$LINKS_FILE" 413 | sort "$LINKS_FILE" -u -o "$LINKS_FILE" 414 | 415 | if declare -f -F add_passed_docker_option > /dev/null; then 416 | # shellcheck disable=SC2034 417 | local passed_phases=(build deploy run) 418 | add_passed_docker_option passed_phases[@] "--link $SERVICE_NAME:$SERVICE_DNS_HOSTNAME" 419 | else 420 | dokku docker-options:add "$APP" build,deploy,run "--link $SERVICE_NAME:$SERVICE_DNS_HOSTNAME" 421 | fi 422 | [[ -n "$SERVICE_QUERYSTRING" ]] && SERVICE_URL="${SERVICE_URL}?${SERVICE_QUERYSTRING}" 423 | config_set "$APP" "${ALIAS}_URL=$SERVICE_URL" 424 | } 425 | 426 | service_linked_apps() { 427 | declare desc="Lists all applications linked to a service" 428 | declare SERVICE="$1" 429 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 430 | local LINKS_FILE="$SERVICE_ROOT/LINKS" 431 | 432 | touch "$LINKS_FILE" 433 | [[ -z $(< "$LINKS_FILE") ]] && echo '-' && return 0 434 | 435 | tr '\n' ' ' < "$LINKS_FILE" 436 | } 437 | 438 | service_list() { 439 | declare desc="Lists all services and their status" 440 | local SERVICES=$(ls "$PLUGIN_DATA_ROOT" 2> /dev/null) 441 | if [[ -z $SERVICES ]]; then 442 | dokku_log_warn "There are no $PLUGIN_SERVICE services" 443 | else 444 | LIST="" 445 | if [[ -z "$DOKKU_QUIET_OUTPUT" ]]; then 446 | LIST="NAME,VERSION,STATUS,EXPOSED PORTS,LINKS\n" 447 | fi 448 | 449 | for SERVICE in $SERVICES; do 450 | LIST+="$SERVICE,$(service_version "$SERVICE"),$(service_status "$SERVICE"),$(service_exposed_ports "$SERVICE"),$(service_linked_apps "$SERVICE")\n" 451 | done 452 | printf "%b" "$LIST" | column -t -s, 453 | fi 454 | } 455 | 456 | service_logs() { 457 | declare desc="Displays logs for a service" 458 | declare SERVICE="$1" TAIL_FLAG="$2" 459 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 460 | local ID=$(cat "$SERVICE_ROOT/ID") 461 | local RE_INTEGER='^[0-9]+$' 462 | 463 | DOKKU_LOGS_ARGS="--tail 100" 464 | if [[ "$TAIL_FLAG" == "-t" ]] || [[ "$TAIL_FLAG" == "--tail" ]]; then 465 | DOKKU_LOGS_ARGS="--follow" 466 | fi 467 | 468 | docker inspect "$ID" &> /dev/null || dokku_log_fail "Service container does not exist" 469 | is_container_status "$ID" "Running" || dokku_log_warn "Service logs may not be output as service is not running" 470 | 471 | # shellcheck disable=SC2086 472 | docker logs $DOKKU_LOGS_ARGS "$ID" 2> /dev/null 473 | } 474 | 475 | service_parse_args() { 476 | declare desc="cli arg parser" 477 | local next_index=1; local skip=false; local args=("$@") 478 | 479 | for arg in "$@"; do 480 | shift 481 | case "$arg" in 482 | "--alias") set -- "$@" "-a" ;; 483 | "--config-options") set -- "$@" "-c" ;; 484 | "--custom-env") set -- "$@" "-C" ;; 485 | "--database") set -- "$@" "-d" ;; 486 | "--image-version") set -- "$@" "-I" ;; 487 | "--image") set -- "$@" "-i" ;; 488 | "--memory") set -- "$@" "-m" ;; 489 | "--password") set -- "$@" "-p" ;; 490 | "--querystring") set -- "$@" "-q" ;; 491 | "--restart-apps") set -- "$@" "-R" ;; 492 | "--root-password") set -- "$@" "-r" ;; 493 | "--user") set -- "$@" "-u" ;; 494 | *) set -- "$@" "$arg" 495 | esac 496 | done 497 | 498 | OPTIND=1 499 | while getopts "a:c:C:d:i:I:m:p:q:R:r:u:" opt; do 500 | case "$opt" in 501 | a) 502 | SERVICE_ALIAS="${OPTARG^^}"; export SERVICE_ALIAS="${SERVICE_ALIAS%_URL}" 503 | ;; 504 | c) export PLUGIN_CONFIG_OPTIONS=$OPTARG 505 | ;; 506 | C) export SERVICE_CUSTOM_ENV=$OPTARG 507 | ;; 508 | d) export SERVICE_DATABASE=$OPTARG 509 | ;; 510 | i) export PLUGIN_IMAGE=$OPTARG 511 | ;; 512 | I) export PLUGIN_IMAGE_VERSION=$OPTARG 513 | ;; 514 | m) export SERVICE_MEMORY=$OPTARG 515 | ;; 516 | p) export SERVICE_PASSWORD=$OPTARG 517 | ;; 518 | q) export SERVICE_QUERYSTRING=${OPTARG#"?"} 519 | ;; 520 | R) export SERVICE_RESTART_APPS=$OPTARG 521 | ;; 522 | r) export SERVICE_ROOT_PASSWORD=$OPTARG 523 | ;; 524 | u) export SERVICE_USER=$OPTARG 525 | ;; 526 | esac 527 | done 528 | shift "$(( OPTIND - 1 ))" # remove options from positional parameters 529 | } 530 | 531 | service_port_expose() { 532 | declare desc="Wrapper for exposing service ports" 533 | declare SERVICE="$1" 534 | service_start "$SERVICE" "true" 535 | service_port_unpause "$SERVICE" "true" "${@:2}" 536 | } 537 | 538 | service_port_pause() { 539 | declare desc="Pauses service exposure" 540 | declare SERVICE="$1" LOG_FAIL="$2" 541 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 542 | local EXPOSED_NAME="$(get_service_name "$SERVICE").ambassador" 543 | local PORT_FILE="$SERVICE_ROOT/PORT" 544 | 545 | if [[ "$LOG_FAIL" == "true" ]]; then 546 | [[ ! -f "$PORT_FILE" ]] && dokku_log_fail "Service not exposed" 547 | else 548 | [[ ! -f "$PORT_FILE" ]] && return 0 549 | fi 550 | 551 | local GREP_NAME="^/${EXPOSED_NAME}$" 552 | local CONTAINER_NAME="$(docker ps -f name="$GREP_NAME" --format "{{.Names}}")" 553 | if [[ -z "$CONTAINER_NAME" ]]; then 554 | if [[ "$LOG_FAIL" == "true" ]]; then 555 | dokku_log_info1 "Service $SERVICE unexposed" 556 | fi 557 | 558 | return 559 | fi 560 | 561 | docker stop "$EXPOSED_NAME" > /dev/null 2>&1 || true 562 | docker rm "$EXPOSED_NAME" > /dev/null 2>&1 || true 563 | if [[ "$LOG_FAIL" == "true" ]]; then 564 | dokku_log_info1 "Service $SERVICE unexposed" 565 | fi 566 | } 567 | 568 | service_port_unexpose() { 569 | declare desc="Wrapper for pausing exposed service ports" 570 | declare SERVICE="$1" 571 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 572 | local PORT_FILE="$SERVICE_ROOT/PORT" 573 | service_port_pause "$SERVICE" "true" 574 | rm -rf "$PORT_FILE" 575 | } 576 | 577 | service_port_unpause() { 578 | declare desc="Starts service exposure" 579 | declare SERVICE="$1" LOG_FAIL="$2" 580 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 581 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 582 | local EXPOSED_NAME="${SERVICE_NAME}.ambassador" 583 | local PORT_FILE="$SERVICE_ROOT/PORT" 584 | # shellcheck disable=SC2068 585 | local PORTS=(${@:3}) 586 | # shellcheck disable=SC2068 587 | PORTS=(${PORTS[@]:-$(get_random_ports ${#PLUGIN_PORTS[@]})}) 588 | local ID=$(cat "$SERVICE_ROOT/ID") 589 | 590 | [[ "${#PORTS[@]}" != "${#PLUGIN_PORTS[@]}" ]] && dokku_log_fail "${#PLUGIN_PORTS[@]} ports to be exposed need to be provided in the following order: ${PLUGIN_PORTS[*]}" 591 | 592 | if [[ "$LOG_FAIL" == "true" ]]; then 593 | [[ -f "$PORT_FILE" ]] && PORTS=($(cat "$PORT_FILE")) && dokku_log_fail "Service $SERVICE already exposed on port(s) ${PORTS[*]}" 594 | else 595 | [[ ! -f "$PORT_FILE" ]] && return 0 596 | PORTS=($(cat "$PORT_FILE")) 597 | fi 598 | 599 | echo "${PORTS[@]}" > "$PORT_FILE" 600 | 601 | # shellcheck disable=SC2046 602 | docker run -d --link "$SERVICE_NAME:$PLUGIN_COMMAND_PREFIX" --name "$EXPOSED_NAME" $(docker_ports_options "${PORTS[@]}") --restart always --label dokku=ambassador --label "dokku.ambassador=$PLUGIN_COMMAND_PREFIX" svendowideit/ambassador > /dev/null 603 | if [[ "$LOG_FAIL" == "true" ]]; then 604 | dokku_log_info1 "Service $SERVICE exposed on port(s) [container->host]: $(service_exposed_ports "$SERVICE")" 605 | fi 606 | } 607 | 608 | service_promote() { 609 | declare desc="Promotes a secondary service to the primary env var" 610 | declare SERVICE="$1" APP="$2" 611 | local PLUGIN_DEFAULT_CONFIG_VAR="${PLUGIN_DEFAULT_ALIAS}_URL" 612 | local EXISTING_CONFIG=$(config_all "$APP") 613 | update_plugin_scheme_for_app "$APP" 614 | local SERVICE_URL=$(service_url "$SERVICE") 615 | local CONFIG_VARS=($(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1)) || true 616 | local PREVIOUS_DEFAULT_URL=$(get_url_from_config "$EXISTING_CONFIG" "$PLUGIN_DEFAULT_CONFIG_VAR") 617 | 618 | [[ -z ${CONFIG_VARS[*]} ]] && dokku_log_fail "Not linked to app $APP" 619 | [[ ${CONFIG_VARS[*]} =~ $PLUGIN_DEFAULT_CONFIG_VAR ]] && dokku_log_fail "Service $1 already promoted as $PLUGIN_DEFAULT_CONFIG_VAR" 620 | 621 | local NEW_CONFIG_VARS="" 622 | if [[ -n $PREVIOUS_DEFAULT_URL ]]; then 623 | local PREVIOUS_ALIAS=$(echo "$EXISTING_CONFIG" | grep "$PREVIOUS_DEFAULT_URL" | grep -v "$PLUGIN_DEFAULT_CONFIG_VAR") || true 624 | if [[ -z $PREVIOUS_ALIAS ]]; then 625 | local ALIAS=$(service_alternative_alias "$EXISTING_CONFIG") 626 | NEW_CONFIG_VARS+="${ALIAS}_URL=$PREVIOUS_DEFAULT_URL " 627 | fi 628 | fi 629 | local PROMOTE_URL=$(get_url_from_config "$EXISTING_CONFIG" "${CONFIG_VARS[0]}") 630 | NEW_CONFIG_VARS+="$PLUGIN_DEFAULT_CONFIG_VAR=$PROMOTE_URL" 631 | 632 | # shellcheck disable=SC2086 633 | config_set "$APP" $NEW_CONFIG_VARS 634 | } 635 | 636 | service_set_alias() { 637 | declare desc="Sets the alias in use for a service" 638 | declare SERVICE="$1" ALIAS="$2" 639 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 640 | local ALIAS_FILE="$SERVICE_ROOT/ALIAS" 641 | 642 | mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" 643 | touch "$ALIAS_FILE" 644 | echo "$ALIAS" > "$ALIAS_FILE" 645 | } 646 | 647 | service_status() { 648 | declare desc="Displays the status of a service" 649 | declare SERVICE="$1" 650 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 651 | local ID="$(cat "$SERVICE_ROOT/ID")" 652 | local CONTAINER_STATUS 653 | 654 | is_container_status "$ID" "Dead" && echo "dead" && return 0 655 | is_container_status "$ID" "OOMKilled" && echo "oomkilled" && return 0 656 | is_container_status "$ID" "Paused" && echo "paused" && return 0 657 | is_container_status "$ID" "Restarting" && echo "restarting" && return 0 658 | is_container_status "$ID" "Running" && echo "running" && return 0 659 | 660 | CONTAINER_STATUS=$(docker inspect -f "{{.State.Status}}" "$CID" 2> /dev/null || true) 661 | [[ -n "$CONTAINER_STATUS" ]] && echo "$CONTAINER_STATUS" && return 0 662 | echo "missing" && return 0 663 | } 664 | 665 | service_stop() { 666 | declare desc="Stops a running service" 667 | declare SERVICE="$1" 668 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"; 669 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 670 | local ID=$(docker ps -f status=running --no-trunc | grep -e "$SERVICE_NAME" | awk '{print $1}') || true 671 | [[ -z $ID ]] && dokku_log_warn "Service is already stopped" && return 0 672 | 673 | if [[ -n $ID ]]; then 674 | dokku_log_info2_quiet "Stopping container" 675 | docker stop "$SERVICE_NAME" > /dev/null 676 | service_port_pause "$SERVICE" 677 | dokku_log_verbose_quiet "Container stopped" 678 | else 679 | dokku_log_verbose_quiet "No container exists for $SERVICE" 680 | fi 681 | } 682 | 683 | service_unlink() { 684 | declare desc="Unlinks an application from a service" 685 | declare SERVICE="$1" APP="$2" 686 | update_plugin_scheme_for_app "$APP" 687 | local SERVICE_URL=$(service_url "$SERVICE") 688 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 689 | local EXISTING_CONFIG=$(config_all "$APP") 690 | local SERVICE_DNS_HOSTNAME=$(service_dns_hostname "$SERVICE") 691 | local LINK=($(echo "$EXISTING_CONFIG" | grep "$SERVICE_URL" | cut -d: -f1)) || true 692 | 693 | remove_from_links_file "$SERVICE" "$APP" 694 | 695 | if declare -f -F add_passed_docker_option > /dev/null; then 696 | # shellcheck disable=SC2034 697 | local passed_phases=(build deploy run) 698 | remove_passed_docker_option passed_phases[@] "--link $SERVICE_NAME:$SERVICE_DNS_HOSTNAME" 699 | else 700 | dokku docker-options:remove "$APP" build,deploy,run "--link $SERVICE_NAME:$SERVICE_DNS_HOSTNAME" 701 | fi 702 | 703 | [[ -z ${LINK[*]} ]] && dokku_log_fail "Not linked to app $APP" 704 | config_unset "$APP" "${LINK[*]}" 705 | } 706 | 707 | service_version() { 708 | declare desc="Displays the running version for an image" 709 | declare SERVICE="$1" 710 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 711 | docker inspect -f '{{.Config.Image}}' "$SERVICE_NAME" 2> /dev/null || true 712 | } 713 | 714 | update_plugin_scheme_for_app() { 715 | declare desc="Retrieves the updated plugin scheme" 716 | declare APP="$1" 717 | local DATABASE_SCHEME 718 | 719 | DATABASE_SCHEME=$(config_get "$APP" "${PLUGIN_VARIABLE}_DATABASE_SCHEME" || true) 720 | PLUGIN_SCHEME=${DATABASE_SCHEME:-$PLUGIN_SCHEME} 721 | } 722 | 723 | verify_service_name() { 724 | declare desc="Verifies that a service exists" 725 | declare SERVICE="$1" 726 | [[ ! -n "$SERVICE" ]] && dokku_log_fail "(verify_service_name) SERVICE must not be null" 727 | [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] && dokku_log_fail "$PLUGIN_SERVICE service $SERVICE does not exist" 728 | return 0 729 | } 730 | 731 | is_valid_service_name() { 732 | declare desc="Validates a service name" 733 | declare SERVICE="$1" 734 | [[ -z "$SERVICE" ]] && return 1 735 | 736 | if [[ "$SERVICE" =~ ^[A-Za-z0-9_]+$ ]]; then 737 | return 0 738 | fi 739 | 740 | return 1 741 | } 742 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export CHROME_IMAGE=${CHROME_IMAGE:="browserless/chrome"} 3 | export CHROME_IMAGE_VERSION=${CHROME_IMAGE_VERSION:="latest"} 4 | export CHROME_ROOT=${CHROME_ROOT:="/var/lib/dokku/services/chrome"} 5 | export CHROME_HOST_ROOT=${CHROME_HOST_ROOT:=$CHROME_ROOT} 6 | 7 | export PLUGIN_UNIMPLEMENTED_SUBCOMMANDS=("backup" "backup-auth" "backup-deauth" "backup-schedule" "backup-schedule-cat" "backup-set-encryption" "backup-unschedule" "backup-unset-encryption" "clone" "connect" "export" "import") 8 | export PLUGIN_COMMAND_PREFIX="chrome" 9 | export PLUGIN_CONFIG_ROOT=${PLUGIN_CONFIG_ROOT:="$DOKKU_LIB_ROOT/config/$PLUGIN_COMMAND_PREFIX"} 10 | export PLUGIN_DATA_ROOT=$CHROME_ROOT 11 | export PLUGIN_DATA_HOST_ROOT=$CHROME_HOST_ROOT 12 | export PLUGIN_PORTS=(3000) 13 | export PLUGIN_WAIT_PORT=3000 14 | export PLUGIN_DEFAULT_ALIAS="CHROME" 15 | export PLUGIN_DISABLE_PULL=${CHROME_DISABLE_PULL:=} 16 | export PLUGIN_DISABLE_PULL_VARIABLE="CHROME_DISABLE_PULL" 17 | export PLUGIN_ALT_ALIAS="DOKKU_CHROME" 18 | export PLUGIN_IMAGE=$CHROME_IMAGE 19 | export PLUGIN_IMAGE_VERSION=$CHROME_IMAGE_VERSION 20 | export PLUGIN_SCHEME="http" 21 | export PLUGIN_SERVICE="Chrome" 22 | export PLUGIN_VARIABLE="CHROME" 23 | export PLUGIN_BASE_PATH="$PLUGIN_PATH" 24 | if [[ -n $DOKKU_API_VERSION ]]; then 25 | export PLUGIN_BASE_PATH="$PLUGIN_ENABLED_PATH" 26 | fi 27 | 28 | if [[ -d "$PLUGIN_DATA_ROOT/*" ]]; then 29 | rm -rf "${PLUGIN_DATA_ROOT:?}/*" 30 | fi 31 | -------------------------------------------------------------------------------- /functions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 5 | source "$PLUGIN_BASE_PATH/common/functions" 6 | source "$PLUGIN_AVAILABLE_PATH/config/functions" 7 | if [[ -f "$PLUGIN_AVAILABLE_PATH/docker-options/functions" ]]; then 8 | source "$PLUGIN_AVAILABLE_PATH/docker-options/functions" 9 | fi 10 | 11 | service_create() { 12 | local SERVICE="$1" 13 | is_valid_service_name "$SERVICE" || dokku_log_fail "Please specify a valid name for the service. Valid characters are: [A-Za-z0-9_]+" 14 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 15 | [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] || dokku_log_fail "$PLUGIN_SERVICE service $SERVICE already exists" 16 | SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE"; LINKS_FILE="$SERVICE_ROOT/LINKS" 17 | 18 | service_parse_args "${@:2}" 19 | 20 | if ! service_image_exists "$SERVICE"; then 21 | if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then 22 | dokku_log_warn "${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2 23 | dokku_log_warn " docker pull ${IMAGE}" 1>&2 24 | dokku_log_warn "$PLUGIN_SERVICE service creation failed" 25 | exit 1 26 | fi 27 | docker pull "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" || dokku_log_fail "$PLUGIN_SERVICE image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION pull failed" 28 | fi 29 | 30 | mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" 31 | mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory" 32 | mkdir -p "$SERVICE_ROOT/config" || dokku_log_fail "Unable to create service config directory" 33 | touch "$LINKS_FILE" 34 | 35 | [[ -n "$SERVICE_CUSTOM_ENV" ]] && ELASTICSEARCH_CUSTOM_ENV="$SERVICE_CUSTOM_ENV" 36 | if [[ -n $CHROME_CUSTOM_ENV ]]; then 37 | echo "$CHROME_CUSTOM_ENV" | tr ';' "\n" > "$SERVICE_ROOT/ENV" 38 | else 39 | echo "" > "$SERVICE_ROOT/ENV" 40 | fi 41 | service_create_container "$SERVICE" 42 | } 43 | 44 | service_create_container() { 45 | local SERVICE="$1" 46 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 47 | local SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE" 48 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 49 | 50 | ID=$(docker run --name "$SERVICE_NAME" --env-file="$SERVICE_ROOT/ENV" -d --restart always --label dokku=service --label dokku.service=chrome "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION") 51 | echo "$ID" > "$SERVICE_ROOT/ID" 52 | 53 | dokku_log_verbose_quiet "Waiting for container to be ready" 54 | docker run --rm --link "$SERVICE_NAME:$PLUGIN_COMMAND_PREFIX" dokku/wait:0.6 -p "$PLUGIN_DATASTORE_WAIT_PORT" > /dev/null 55 | 56 | dokku_log_info2 "$PLUGIN_SERVICE container created: $SERVICE" 57 | service_info "$SERVICE" 58 | } 59 | 60 | retry-docker-command() { 61 | local ID="$1" COMMAND="$2" 62 | local i=0 success=false 63 | until [ $i -ge 100 ]; do 64 | set +e; docker exec -it "$ID" sh -c "$COMMAND" 2> /dev/null; exit_code=$? ; set -e 65 | if [[ "$exit_code" == 0 ]]; then 66 | success=true 67 | break 68 | fi 69 | i=$(( i + 1 )) 70 | sleep 1 71 | done 72 | if [[ $i -gt 0 ]]; then 73 | dokku_log_verbose "Container command retried ${i} time(s): ${COMMAND}" 74 | fi 75 | [[ "$success" == "true" ]] || dokku_log_fail "Failed to run command: ${COMMAND}" 76 | } 77 | 78 | service_start() { 79 | local SERVICE="$1" 80 | local QUIET="$2" 81 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 82 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 83 | local ID=$(docker ps -f status=running --no-trunc | grep -e "$SERVICE_NAME$" | awk '{print $1}') || true 84 | if [[ -n $ID ]]; then 85 | [[ -z $QUIET ]] && dokku_log_warn "Service is already started" 86 | return 0 87 | fi 88 | 89 | dokku_log_info2_quiet "Starting container" 90 | local PREVIOUS_ID=$(docker ps -f status=exited --no-trunc | grep -e "$SERVICE_NAME$" | awk '{print $1}') || true 91 | 92 | if [[ -n $PREVIOUS_ID ]]; then 93 | docker start "$PREVIOUS_ID" > /dev/null 94 | service_port_unpause "$SERVICE" 95 | dokku_log_info2 "Container started" 96 | elif service_image_exists "$SERVICE"; then 97 | service_create_container "$SERVICE" 98 | else 99 | dokku_log_verbose_quiet "Neither container nor valid configuration exists for $SERVICE" 100 | fi 101 | } 102 | 103 | service_url() { 104 | local SERVICE="$1" 105 | local SERVICE_DNS_HOSTNAME="$(service_dns_hostname "$SERVICE")" 106 | echo "$PLUGIN_SCHEME://$SERVICE_DNS_HOSTNAME:${PLUGIN_PORTS[0]}" 107 | } 108 | -------------------------------------------------------------------------------- /help-functions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 5 | export SUBCOMMAND_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands" 6 | 7 | fn-help() { 8 | declare CMD="$1" 9 | local cmd EXIT_CODE 10 | 11 | if [[ "$CMD" == "help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]]; then 12 | fn-help-all "$@" 13 | exit 0 14 | fi 15 | 16 | pushd "$SUBCOMMAND_ROOT" > /dev/null 2>&1 17 | for cmd in *; do 18 | if [[ "$CMD" == "${PLUGIN_COMMAND_PREFIX}:$cmd" ]]; then 19 | "$SUBCOMMAND_ROOT/$cmd" "$@" 20 | EXIT_CODE="$?" 21 | exit "$EXIT_CODE" 22 | fi 23 | done 24 | popd > /dev/null 2>&1 25 | 26 | exit "$DOKKU_NOT_IMPLEMENTED_EXIT" 27 | } 28 | 29 | fn-help-all() { 30 | declare CMD="$1" SUBCOMMAND="$2" 31 | local CMD_OUTPUT BLUE BOLD FULL_OUTPUT NORMAL 32 | FULL_OUTPUT=true 33 | 34 | if [[ "$CMD" = "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]] ; then 35 | BOLD="$(fn-help-fancy-tput bold)" 36 | NORMAL="$(fn-help-fancy-color "\033[m")" 37 | BLUE="$(fn-help-fancy-color "\033[0;34m")" 38 | CYAN="$(fn-help-fancy-color "\033[1;36m")" 39 | if [[ -n "$SUBCOMMAND" ]] && [[ "$SUBCOMMAND" != "--all" ]]; then 40 | fn-help-contents-subcommand "$SUBCOMMAND" "$FULL_OUTPUT" 41 | return "$?" 42 | fi 43 | 44 | echo -e "${BOLD}usage${NORMAL}: dokku $PLUGIN_COMMAND_PREFIX[:COMMAND]" 45 | echo '' 46 | echo -e "${BOLD}List your $PLUGIN_COMMAND_PREFIX services.${NORMAL}" 47 | echo '' 48 | echo -e "${BLUE}Example:${NORMAL}" 49 | echo '' 50 | echo " \$ dokku $PLUGIN_COMMAND_PREFIX:list" 51 | echo '' 52 | fn-help-list-example | column -c5 -t -s, 53 | echo '' 54 | echo -e "dokku ${BOLD}${PLUGIN_COMMAND_PREFIX}${NORMAL} commands: (get help with ${CYAN}dokku ${PLUGIN_COMMAND_PREFIX}:help SUBCOMMAND${NORMAL})" 55 | echo '' 56 | fn-help-contents | sort | column -c2 -t -s, 57 | echo '' 58 | elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then 59 | fn-help-contents 60 | else 61 | cat< /dev/null 2>&1 71 | for cmd in *; do 72 | fn-help-contents-subcommand "$cmd" || true 73 | done 74 | } 75 | 76 | fn-help-contents-subcommand() { 77 | declare SUBCOMMAND="$1" FULL_OUTPUT="$2" 78 | local TMPDIR=$(mktemp -d) 79 | local UNCLEAN_FILE="${TMPDIR}/cmd-unclean" CLEAN_FILE="${TMPDIR}/cmd-clean" 80 | local BOLD CMD_OUTPUT CYAN EXAMPLE LIGHT_GRAY NORMAL 81 | trap 'rm -rf "$TMPDIR" > /dev/null' RETURN INT TERM EXIT 82 | 83 | rm -rf "$UNCLEAN_FILE" "$CLEAN_FILE" 84 | cat "$SUBCOMMAND_ROOT/$SUBCOMMAND" > "$UNCLEAN_FILE" 85 | 86 | fn-help-subcommand-sanitize "$UNCLEAN_FILE" "$CLEAN_FILE" 87 | if ! is_implemented_command "$SUBCOMMAND"; then 88 | return 1 89 | fi 90 | 91 | args="$(fn-help-subcommand-args "$CLEAN_FILE" "$FULL_OUTPUT")" 92 | SUBCOMMAND=":$SUBCOMMAND" 93 | [[ "$SUBCOMMAND" == ":default" ]] && SUBCOMMAND="" 94 | cmd_line="$(echo -e "${SUBCOMMAND} ${args}" | sed -e 's/[[:space:]]*$//')" 95 | desc="$(grep desc "$CLEAN_FILE" | head -1)" 96 | eval "$desc" 97 | 98 | BLUE="$(fn-help-fancy-color "\033[0;34m")" 99 | BOLD="$(fn-help-fancy-tput bold)" 100 | CYAN="$(fn-help-fancy-color "\033[1;36m")" 101 | NORMAL="$(fn-help-fancy-color "\033[m")" 102 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 103 | LIGHT_RED="$(fn-help-fancy-color "\033[1;31m")" 104 | CMD_OUTPUT="$(echo -e " ${PLUGIN_COMMAND_PREFIX}${cmd_line}, ${LIGHT_GRAY}${desc}${NORMAL}")" 105 | if [[ "$FULL_OUTPUT" != "true" ]]; then 106 | echo "$CMD_OUTPUT" 107 | return 0 108 | fi 109 | 110 | echo -e "${BOLD}usage:${NORMAL} dokku ${PLUGIN_COMMAND_PREFIX}${cmd_line}" 111 | echo '' 112 | echo -e "${BOLD}${desc}${NORMAL}" 113 | echo '' 114 | 115 | ARGS="$(fn-help-subcommand-list-args "$CLEAN_FILE")" 116 | if [[ -n "$ARGS" ]]; then 117 | echo -e "${CYAN}arguments:${NORMAL}" 118 | echo '' 119 | echo "$ARGS" | column -c2 -t -s, 120 | echo '' 121 | fi 122 | 123 | FLAGS="$(fn-help-subcommand-list-flags "$CLEAN_FILE")" 124 | if [[ -n "$FLAGS" ]]; then 125 | echo -e "${BLUE}flags:${NORMAL}" 126 | echo '' 127 | echo "$FLAGS" | column -c2 -t -s, 128 | echo '' 129 | fi 130 | 131 | EXAMPLE="$(fn-help-subcommand-example "$CLEAN_FILE")" 132 | if [[ -n "$EXAMPLE" ]]; then 133 | echo -e "${LIGHT_RED}examples:${NORMAL}" 134 | echo '' 135 | echo "$EXAMPLE" 136 | echo '' 137 | fi 138 | 139 | return 0 140 | } 141 | 142 | fn-help-fancy-tput() { 143 | declare desc="A wrapper around tput" 144 | 145 | if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" = "unknown" ]] || [[ "$TERM" == "dumb" ]]; then 146 | return 147 | fi 148 | 149 | tput "$@" 150 | } 151 | 152 | fn-help-fancy-color() { 153 | declare desc="A wrapper around colors" 154 | 155 | if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" = "unknown" ]] || [[ "$TERM" == "dumb" ]]; then 156 | return 157 | fi 158 | 159 | echo "$@" 160 | } 161 | 162 | fn-help-list-example() { 163 | # shellcheck disable=SC2034 164 | declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" 165 | cat<* ]] && line="\n ${BOLD}${line}${NORMAL}" 239 | # shellcheck disable=SC2001 240 | [[ "$line" == " "* ]] && line=" ${OTHER_GRAY}$(echo "$line" | sed -e 's/^[[:space:]]*//')${NORMAL}" 241 | echo -e "${NEWLINE}${line}" 242 | LAST_LINE="sentence" 243 | NEWLINE="\n" 244 | fi 245 | done 246 | } 247 | 248 | fn-help-subcommand-list-args() { 249 | declare FUNC_FILE="$1" 250 | local EXAMPLE LIGHT_GRAY NORMAL 251 | 252 | FLAGS=$(grep "#A" "$FUNC_FILE" | cut -d'A' -f2- | sed -e 's/^[[:space:]]*//' || true) 253 | if [[ -z "$FLAGS" ]]; then 254 | return 0 255 | fi 256 | 257 | NORMAL="$(fn-help-fancy-color "\033[m")" 258 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 259 | 260 | _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do 261 | echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" 262 | done 263 | } 264 | 265 | fn-help-subcommand-list-flags() { 266 | declare FUNC_FILE="$1" 267 | local EXAMPLE LIGHT_GRAY NORMAL 268 | 269 | FLAGS=$(grep "#F" "$FUNC_FILE" | cut -d'F' -f2- | sed -e 's/^[[:space:]]*//' || true) 270 | if [[ -z "$FLAGS" ]]; then 271 | return 0 272 | fi 273 | 274 | NORMAL="$(fn-help-fancy-color "\033[m")" 275 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 276 | 277 | _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do 278 | echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" 279 | done 280 | } 281 | 282 | fn-help-subcommand-sanitize() { 283 | declare FUNC_FILE="$1" OUTGOING_FUNC_FILE="$2" 284 | local FUNCTION_FOUND=false 285 | local IFS OIFS 286 | 287 | touch "$OUTGOING_FUNC_FILE" 288 | 289 | OIFS="$IFS" 290 | IFS=, 291 | while read -r p; do 292 | IFS="$OIFS" 293 | if [[ "$p" == *"-cmd \"\$@\""* ]] || [[ "$p" == "" ]]; then 294 | continue 295 | fi 296 | 297 | if [[ "$FUNCTION_FOUND" == true ]]; then 298 | echo "$p" >> "$OUTGOING_FUNC_FILE" 299 | continue 300 | fi 301 | 302 | if [[ "$p" == *"()"* ]]; then 303 | FUNCTION_FOUND=true 304 | echo "$p" >> "$OUTGOING_FUNC_FILE" 305 | continue 306 | fi 307 | done < "$FUNC_FILE" 308 | } 309 | 310 | _fn-help-apply-shell-expansion() { 311 | declare desc="Expand environment variables for a shell command" 312 | declare data="$1" 313 | declare delimiter="__apply_shell_expansion_delimiter__" 314 | declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter" 315 | eval "$command" 316 | } 317 | -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | 5 | plugin-install() { 6 | pull-docker-image() { 7 | declare IMAGE="$1" 8 | if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then 9 | echo " ! ${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2 10 | echo " ! docker pull ${IMAGE}" 1>&2 11 | return 12 | fi 13 | if [[ "$(docker images -q "${IMAGE}" 2> /dev/null)" == "" ]]; then 14 | docker pull "${IMAGE}" 15 | fi 16 | } 17 | 18 | pull-docker-image "${PLUGIN_IMAGE}:${PLUGIN_IMAGE_VERSION}" 19 | 20 | mkdir -p "$PLUGIN_DATA_ROOT" || echo "Failed to create $PLUGIN_SERVICE data directory" 21 | chown dokku:dokku "$PLUGIN_DATA_ROOT" 22 | 23 | mkdir -p "$PLUGIN_CONFIG_ROOT" || echo "Failed to create $PLUGIN_SERVICE config directory" 24 | chown dokku:dokku "$PLUGIN_CONFIG_ROOT" 25 | 26 | rm -f "/etc/sudoers.d/dokku-${PLUGIN_COMMAND_PREFIX}*" 27 | _SUDOERS_FILE="/etc/sudoers.d/dokku-${PLUGIN_COMMAND_PREFIX}" 28 | 29 | touch "$_SUDOERS_FILE" 30 | cat > "$_SUDOERS_FILE" < " service_name 34 | if [[ "$service_name" != "$SERVICE" ]]; then 35 | dokku_log_warn "Confirmation did not match $SERVICE. Aborted." 36 | exit 1 37 | fi 38 | fi 39 | 40 | dokku_log_info2_quiet "Deleting $SERVICE" 41 | service_container_rm "$SERVICE" 42 | 43 | dokku_log_verbose_quiet "Removing data" 44 | docker run --rm -v "$SERVICE_HOST_ROOT/data:/data" -v "$SERVICE_HOST_ROOT/config:/config" busybox chmod 777 -R /config /data 45 | rm -rf "$SERVICE_ROOT" 46 | 47 | dokku_log_info2 "$PLUGIN_SERVICE container deleted: $SERVICE" 48 | } 49 | 50 | service-destroy-cmd "$@" 51 | -------------------------------------------------------------------------------- /subcommands/expose: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-expose-cmd() { 8 | #E expose the service on the service's normal ports, allowing access to it from the public interface (0.0.0.0) 9 | #E dokku $PLUGIN_COMMAND_PREFIX:expose lolipop ${PLUGIN_PORTS[@]} 10 | #A service, service to run command against 11 | #A ports, a list of ports to run against 12 | declare desc="expose a $PLUGIN_SERVICE service on custom port if provided (random port otherwise)" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:expose" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 14 | declare SERVICE="$1" PORTS_LIST="${@:2}" 15 | 16 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 17 | verify_service_name "$SERVICE" 18 | service_port_expose "$SERVICE" "${@:2}" 19 | } 20 | 21 | service-expose-cmd "$@" 22 | -------------------------------------------------------------------------------- /subcommands/info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-info-cmd() { 8 | #E get connection information as follows: 9 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop 10 | #E you can also retrieve a specific piece of service info via flags: 11 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --config-dir 12 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --data-dir 13 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --dsn 14 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --exposed-ports 15 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --id 16 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --internal-ip 17 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --links 18 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --service-root 19 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --status 20 | #E dokku $PLUGIN_COMMAND_PREFIX:info lolipop --version 21 | #A service, service to run command against 22 | #F --config-dir, show the service configuration directory 23 | #F --data-dir, show the service data directory 24 | #F --dsn, show the service DSN 25 | #F --exposed-ports, show service exposed ports 26 | #F --id, show the service container id 27 | #F --internal-ip, show the service internal ip 28 | #F --links, show the service app links 29 | #F --service-root, show the service root directory 30 | #F --status, show the service running status 31 | #F --version, show the service image version 32 | declare desc="print the connection information" 33 | local cmd="$PLUGIN_COMMAND_PREFIX:info" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 34 | declare SERVICE="$1" INFO_FLAG="$2" 35 | 36 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 37 | verify_service_name "$SERVICE" 38 | service_info "$SERVICE" "$INFO_FLAG" 39 | } 40 | 41 | service-info-cmd "$@" 42 | -------------------------------------------------------------------------------- /subcommands/link: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-link-cmd() { 8 | #E a $PLUGIN_COMMAND_PREFIX service can be linked to a container. 9 | #E this will use native docker links via the docker-options plugin. 10 | #E here we link it to our 'playground' app. 11 | #E > NOTE: this will restart your app 12 | #E dokku $PLUGIN_COMMAND_PREFIX:link lolipop playground 13 | #E the following environment variables will be set automatically by docker 14 | #E (not on the app itself, so they won’t be listed when calling dokku config): 15 | #E 16 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_NAME=/lolipop/DATABASE 17 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_PORT=tcp://172.17.0.1:${PLUGIN_PORTS[0]} 18 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_PORT_${PLUGIN_PORTS[0]}_TCP=tcp://172.17.0.1:${PLUGIN_PORTS[0]} 19 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_PORT_${PLUGIN_PORTS[0]}_TCP_PROTO=tcp 20 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_PORT_${PLUGIN_PORTS[0]}_TCP_PORT=${PLUGIN_PORTS[0]} 21 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_LOLIPOP_PORT_${PLUGIN_PORTS[0]}_TCP_ADDR=172.17.0.1 22 | #E 23 | #E the following will be set on the linked application by default: 24 | #E 25 | #E ${PLUGIN_DEFAULT_ALIAS}_URL=${PLUGIN_SCHEME}://lolipop:SOME_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-lolipop:${PLUGIN_PORTS[0]}/lolipop 26 | #E 27 | #E the host exposed here only works internally in docker containers. 28 | #E if you want your container to be reachable from outside, you should 29 | #E use the 'expose' subcommand. another service can be linked to your app: 30 | #E dokku $PLUGIN_COMMAND_PREFIX:link other_service playground 31 | #E it is possible to change the protocol for ${PLUGIN_DEFAULT_ALIAS}_URL by setting the 32 | #E environment variable ${PLUGIN_DEFAULT_ALIAS}_DATABASE_SCHEME on the app. doing so will 33 | #E after linking will cause the plugin to think the service is not 34 | #E linked, and we advise you to unlink before proceeding. 35 | #E dokku config:set playground ${PLUGIN_DEFAULT_ALIAS}_DATABASE_SCHEME=${PLUGIN_SCHEME}2 36 | #E dokku $PLUGIN_COMMAND_PREFIX:link lolipop playground 37 | #E this will cause ${PLUGIN_DEFAULT_ALIAS}_URL to be set as: 38 | #E 39 | #E ${PLUGIN_SCHEME}2://lolipop:SOME_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-lolipop:${PLUGIN_PORTS[0]}/lolipop 40 | #A service, service to run command against 41 | #A app, app to run command against 42 | #F -a|--alias "BLUE_DATABASE", an alternative alias to use for linking to an app via environment variable 43 | #F -q|--querystring "pool=5", ampersand delimited querystring arguments to append to the service link 44 | declare desc="link the $PLUGIN_SERVICE service to the app" 45 | local cmd="$PLUGIN_COMMAND_PREFIX:link" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 46 | declare SERVICE="$1" APP="$2" LINK_FLAGS_LIST="${@:3}" 47 | APP=${APP:="$DOKKU_APP_NAME"} 48 | 49 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 50 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 51 | verify_app_name "$APP" 52 | verify_service_name "$SERVICE" 53 | 54 | service_parse_args "${@:3}" 55 | service_link "$SERVICE" "$APP" 56 | } 57 | 58 | service-link-cmd "$@" 59 | -------------------------------------------------------------------------------- /subcommands/linked: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-linked-cmd() { 8 | #E here we check if the lolipop $PLUGIN_COMMAND_PREFIX service is linked to the 'playground' app. 9 | #E dokku $PLUGIN_COMMAND_PREFIX:linked lolipop playground 10 | #A service, service to run command against 11 | #A app, app to run command against 12 | declare desc="check if the $PLUGIN_SERVICE service is linked to an app" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:linked" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 14 | declare SERVICE="$1" APP="$2" 15 | APP=${APP:="$DOKKU_APP_NAME"} 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 19 | verify_app_name "$APP" 20 | verify_service_name "$SERVICE" 21 | service_is_linked "$SERVICE" "$APP" 22 | } 23 | 24 | service-linked-cmd "$@" 25 | -------------------------------------------------------------------------------- /subcommands/list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-list-cmd() { 8 | #E list all services 9 | #E dokku $PLUGIN_COMMAND_PREFIX:list 10 | declare desc="list all $PLUGIN_SERVICE services" 11 | local cmd="$PLUGIN_COMMAND_PREFIX:list" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 12 | 13 | service_list 14 | } 15 | 16 | service-list-cmd "$@" 17 | -------------------------------------------------------------------------------- /subcommands/logs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-logs-cmd() { 8 | #E you can tail logs for a particular service: 9 | #E dokku $PLUGIN_COMMAND_PREFIX:logs lolipop 10 | #E by default, logs will not be tailed, but you can do this with the --tail flag: 11 | #E dokku $PLUGIN_COMMAND_PREFIX:logs lolipop --tail 12 | #A service, service to run command against 13 | #F -t|--tail, do not stop when end of the logs are reached and wait for additional output 14 | declare desc="print the most recent log(s) for this service" 15 | local cmd="$PLUGIN_COMMAND_PREFIX:logs" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" TAIL_FLAG="$2" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_logs "$SERVICE" "$TAIL_FLAG" 21 | } 22 | 23 | service-logs-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/promote: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-promote-cmd() { 8 | #E if you have a $PLUGIN_COMMAND_PREFIX service linked to an app and try to link another $PLUGIN_COMMAND_PREFIX service 9 | #E another link environment variable will be generated automatically: 10 | #E 11 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_BLUE_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_PORTS[0]}/other_service 12 | #E 13 | #E you can promote the new service to be the primary one 14 | #E > NOTE: this will restart your app 15 | #E dokku $PLUGIN_COMMAND_PREFIX:promote other_service playground 16 | #E this will replace ${PLUGIN_DEFAULT_ALIAS}_URL with the url from other_service and generate 17 | #E another environment variable to hold the previous value if necessary. 18 | #E you could end up with the following for example: 19 | #E 20 | #E ${PLUGIN_DEFAULT_ALIAS}_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_PORTS[0]}/other_service 21 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_BLUE_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_PORTS[0]}/other_service 22 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_SILVER_URL=${PLUGIN_SCHEME}://lolipop:SOME_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-lolipop:${PLUGIN_PORTS[0]}/lolipop 23 | #A service, service to run command against 24 | #A app, app to run command against 25 | declare desc="promote service as ${PLUGIN_DEFAULT_ALIAS}_URL in " 26 | local cmd="$PLUGIN_COMMAND_PREFIX:promote" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 27 | declare SERVICE="$1" APP="$2" 28 | APP=${APP:="$DOKKU_APP_NAME"} 29 | 30 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 31 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 32 | verify_service_name "$SERVICE" 33 | verify_app_name "$APP" 34 | service_promote "$SERVICE" "$APP" 35 | } 36 | 37 | service-promote-cmd "$@" 38 | -------------------------------------------------------------------------------- /subcommands/restart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-restart-cmd() { 8 | #E restart the service 9 | #E dokku $PLUGIN_COMMAND_PREFIX:restart lolipop 10 | #A service, service to run command against 11 | declare desc="graceful shutdown and restart of the $PLUGIN_SERVICE service container" 12 | local cmd="$PLUGIN_COMMAND_PREFIX:restart" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 13 | declare SERVICE="$1" 14 | 15 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 16 | verify_service_name "$SERVICE" 17 | service_stop "$SERVICE" 18 | service_start "$SERVICE" 19 | dokku_log_info1 "Please call dokku ps:restart on all linked apps" 20 | } 21 | 22 | service-restart-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-start-cmd() { 8 | #E start the service 9 | #E dokku $PLUGIN_COMMAND_PREFIX:start lolipop 10 | #A service, service to run command against 11 | declare desc="start a previously stopped $PLUGIN_SERVICE service" 12 | local cmd="$PLUGIN_COMMAND_PREFIX:start" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 13 | declare SERVICE="$1" 14 | 15 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 16 | verify_service_name "$SERVICE" 17 | service_start "$SERVICE" 18 | } 19 | 20 | service-start-cmd "$@" 21 | -------------------------------------------------------------------------------- /subcommands/stop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-stop-cmd() { 8 | #E stop the service and the running container 9 | #E dokku $PLUGIN_COMMAND_PREFIX:stop lolipop 10 | #A service, service to run command against 11 | declare desc="stop a running $PLUGIN_SERVICE service" 12 | local cmd="$PLUGIN_COMMAND_PREFIX:stop" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 13 | declare SERVICE="$1" 14 | 15 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 16 | verify_service_name "$SERVICE" 17 | service_stop "$SERVICE" 18 | } 19 | 20 | service-stop-cmd "$@" 21 | -------------------------------------------------------------------------------- /subcommands/unexpose: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-unexpose-cmd() { 8 | #E unexpose the service, removing access to it from the public interface (0.0.0.0) 9 | #E dokku $PLUGIN_COMMAND_PREFIX:unexpose lolipop 10 | #A service, service to run command against 11 | declare desc="unexpose a previously exposed $PLUGIN_SERVICE service" 12 | local cmd="$PLUGIN_COMMAND_PREFIX:unexpose" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 13 | declare SERVICE="$1" 14 | 15 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 16 | verify_service_name "$SERVICE" 17 | service_port_unexpose "$SERVICE" 18 | } 19 | 20 | service-unexpose-cmd "$@" 21 | -------------------------------------------------------------------------------- /subcommands/unlink: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 4 | source "$PLUGIN_BASE_PATH/common/functions" 5 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 6 | 7 | service-unlink-cmd() { 8 | #E you can unlink a $PLUGIN_COMMAND_PREFIX service 9 | #E > NOTE: this will restart your app and unset related environment variables 10 | #E dokku $PLUGIN_COMMAND_PREFIX:unlink lolipop playground 11 | #A service, service to run command against 12 | #A app, app to run command against 13 | declare desc="unlink the $PLUGIN_SERVICE service from the app" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:unlink" argv=("$@"); [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" APP="$2" 16 | APP=${APP:="$DOKKU_APP_NAME"} 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 20 | verify_service_name "$SERVICE" 21 | verify_app_name "$APP" 22 | service_unlink "$SERVICE" "$APP" 23 | } 24 | 25 | service-unlink-cmd "$@" 26 | -------------------------------------------------------------------------------- /tests/hook_pre_delete.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku apps:create my_app >&2 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 7 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2 8 | } 9 | 10 | teardown() { 11 | reset_system_data 12 | } 13 | 14 | @test "($PLUGIN_COMMAND_PREFIX:hook:pre-delete) removes app from links file when destroying app" { 15 | [[ -n $(< "$PLUGIN_DATA_ROOT/l/LINKS") ]] 16 | dokku --force apps:destroy my_app 17 | [[ -z $(< "$PLUGIN_DATA_ROOT/l/LINKS") ]] 18 | } 19 | -------------------------------------------------------------------------------- /tests/service_create.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | teardown() { 5 | reset_system_data 6 | } 7 | 8 | @test "($PLUGIN_COMMAND_PREFIX:create) success" { 9 | run dokku "$PLUGIN_COMMAND_PREFIX:create" l 10 | assert_contains "${lines[*]}" "container created: l" 11 | } 12 | 13 | @test "($PLUGIN_COMMAND_PREFIX:create) error when there are no arguments" { 14 | run dokku "$PLUGIN_COMMAND_PREFIX:create" 15 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:create) error when there is an invalid name specified" { 19 | run dokku "$PLUGIN_COMMAND_PREFIX:create" d.erp 20 | assert_failure 21 | 22 | run dokku "$PLUGIN_COMMAND_PREFIX:create" d-erp 23 | assert_failure 24 | } 25 | -------------------------------------------------------------------------------- /tests/service_destroy.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | teardown() { 5 | reset_system_data 6 | } 7 | 8 | @test "($PLUGIN_COMMAND_PREFIX:destroy) success with --force" { 9 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 10 | run dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 11 | assert_contains "${lines[*]}" "container deleted: l" 12 | assert_contains "${lines[*]}" "Removed container" 13 | } 14 | 15 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when there are no arguments" { 16 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" 17 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 18 | } 19 | 20 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when container does not exist" { 21 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" non_existing_container 22 | assert_contains "${lines[*]}" "service non_existing_container does not exist" 23 | } 24 | 25 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when container is linked to an app" { 26 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 27 | dokku apps:create app 28 | dokku "$PLUGIN_COMMAND_PREFIX:link" l app 29 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" l 30 | assert_contains "${lines[*]}" "Cannot delete linked service" 31 | } 32 | -------------------------------------------------------------------------------- /tests/service_expose.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | reset_system_data 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:expose) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:expose) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:expose) success when not providing custom ports" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" l 24 | [[ "${lines[*]}" =~ exposed\ on\ port\(s\)\ \[container\-\>host\]\:\ [[:digit:]]+ ]] 25 | } 26 | 27 | @test "($PLUGIN_COMMAND_PREFIX:expose) success when providing custom ports" { 28 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" l 4000 29 | assert_contains "${lines[*]}" "exposed on port(s) [container->host]: 3000->4000" 30 | } 31 | -------------------------------------------------------------------------------- /tests/service_info.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 10 | reset_system_data 11 | } 12 | 13 | @test "($PLUGIN_COMMAND_PREFIX:info) error when there are no arguments" { 14 | run dokku "$PLUGIN_COMMAND_PREFIX:info" 15 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:info) error when service does not exist" { 19 | run dokku "$PLUGIN_COMMAND_PREFIX:info" not_existing_service 20 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 21 | } 22 | 23 | @test "($PLUGIN_COMMAND_PREFIX:info) success" { 24 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l 25 | assert_contains "${lines[*]}" "http://dokku-chrome-l:3000" 26 | } 27 | 28 | @test "($PLUGIN_COMMAND_PREFIX:info) replaces underscores by dash in hostname" { 29 | dokku "$PLUGIN_COMMAND_PREFIX:create" test_with_underscores 30 | run dokku "$PLUGIN_COMMAND_PREFIX:info" test_with_underscores 31 | assert_contains "${lines[*]}" "http://dokku-chrome-test-with-underscores:3000" 32 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" test_with_underscores 33 | } 34 | 35 | @test "($PLUGIN_COMMAND_PREFIX:info) success with flag" { 36 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn 37 | assert_output "http://dokku-chrome-l:3000" 38 | 39 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --config-dir 40 | assert_success 41 | 42 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --data-dir 43 | assert_success 44 | 45 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn 46 | assert_success 47 | 48 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --exposed-ports 49 | assert_success 50 | 51 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --id 52 | assert_success 53 | 54 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --internal-ip 55 | assert_success 56 | 57 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --links 58 | assert_success 59 | 60 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --service-root 61 | assert_success 62 | 63 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --status 64 | assert_success 65 | 66 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --version 67 | assert_success 68 | } 69 | 70 | @test "($PLUGIN_COMMAND_PREFIX:info) error when invalid flag" { 71 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --invalid-flag 72 | assert_failure 73 | } 74 | -------------------------------------------------------------------------------- /tests/service_link.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | dokku apps:create my_app >&2 7 | } 8 | 9 | teardown() { 10 | reset_system_data 11 | } 12 | 13 | @test "($PLUGIN_COMMAND_PREFIX:link) error when there are no arguments" { 14 | run dokku "$PLUGIN_COMMAND_PREFIX:link" 15 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the app argument is missing" { 19 | run dokku "$PLUGIN_COMMAND_PREFIX:link" l 20 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 21 | } 22 | 23 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the app does not exist" { 24 | run dokku "$PLUGIN_COMMAND_PREFIX:link" l not_existing_app 25 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 26 | } 27 | 28 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the service does not exist" { 29 | run dokku "$PLUGIN_COMMAND_PREFIX:link" not_existing_service my_app 30 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 31 | } 32 | 33 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the service is already linked to app" { 34 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 35 | run dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 36 | assert_contains "${lines[*]}" "Already linked as CHROME_URL" 37 | } 38 | 39 | @test "($PLUGIN_COMMAND_PREFIX:link) exports CHROME_URL to app" { 40 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 41 | url=$(dokku config:get my_app CHROME_URL) 42 | assert_contains "$url" "http://dokku-chrome-l:3000" 43 | } 44 | 45 | @test "($PLUGIN_COMMAND_PREFIX:link) generates an alternate config url when CHROME_URL already in use" { 46 | dokku config:set my_app CHROME_URL=http://host:3000 47 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 48 | run dokku config my_app 49 | assert_contains "${lines[*]}" "DOKKU_CHROME_" 50 | } 51 | 52 | @test "($PLUGIN_COMMAND_PREFIX:link) links to app with docker-options" { 53 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 54 | run dokku docker-options my_app 55 | assert_contains "${lines[*]}" "--link dokku.chrome.l:dokku-chrome-l" 56 | } 57 | 58 | @test "($PLUGIN_COMMAND_PREFIX:link) uses a specified config url when alias is specified" { 59 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app --alias "ALIAS" 60 | url=$(dokku config:get my_app ALIAS_URL) 61 | assert_contains "$url" "http://dokku-chrome-l:3000" 62 | } 63 | -------------------------------------------------------------------------------- /tests/service_list.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 || true 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 7 | } 8 | 9 | teardown() { 10 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 11 | } 12 | 13 | @test "($PLUGIN_COMMAND_PREFIX:list) with no exposed ports, no linked apps" { 14 | run dokku "$PLUGIN_COMMAND_PREFIX:list" 15 | assert_contains "${lines[*]}" "l browserless/chrome:latest running - -" 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:list) with exposed ports" { 19 | dokku "$PLUGIN_COMMAND_PREFIX:expose" l 4000 20 | run dokku "$PLUGIN_COMMAND_PREFIX:list" 21 | assert_contains "${lines[*]}" "l browserless/chrome:latest running 3000->4000 -" 22 | } 23 | 24 | @test "($PLUGIN_COMMAND_PREFIX:list) with linked app" { 25 | dokku apps:create my_app 26 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 27 | run dokku "$PLUGIN_COMMAND_PREFIX:list" 28 | assert_contains "${lines[*]}" "l browserless/chrome:latest running - my_app" 29 | dokku --force apps:destroy my_app 30 | } 31 | 32 | @test "($PLUGIN_COMMAND_PREFIX:list) when there are no services" { 33 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 34 | run dokku "$PLUGIN_COMMAND_PREFIX:list" 35 | assert_contains "${lines[*]}" "There are no Chrome services" 36 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 37 | } 38 | -------------------------------------------------------------------------------- /tests/service_logs.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | export ECHO_DOCKER_COMMAND="false" 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 7 | } 8 | 9 | teardown() { 10 | export ECHO_DOCKER_COMMAND="false" 11 | reset_system_data 12 | } 13 | 14 | @test "($PLUGIN_COMMAND_PREFIX:logs) error when there are no arguments" { 15 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" 16 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 17 | } 18 | 19 | @test "($PLUGIN_COMMAND_PREFIX:logs) error when service does not exist" { 20 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" not_existing_service 21 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 22 | } 23 | 24 | # @test "($PLUGIN_COMMAND_PREFIX:logs) success when not tailing" { 25 | # export ECHO_DOCKER_COMMAND="true" 26 | # run dokku "$PLUGIN_COMMAND_PREFIX:logs" l 27 | # assert_contains "docker logs --tail 100 testid" 28 | # } 29 | 30 | # @test "($PLUGIN_COMMAND_PREFIX:logs) success when tailing" { 31 | # export ECHO_DOCKER_COMMAND="true" 32 | # run dokku "$PLUGIN_COMMAND_PREFIX:logs" l -t 33 | # assert_contains "docker logs --follow testid" 34 | # } 35 | -------------------------------------------------------------------------------- /tests/service_promote.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | dokku apps:create my_app >&2 7 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app 8 | } 9 | 10 | teardown() { 11 | reset_system_data 12 | } 13 | 14 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when there are no arguments" { 15 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" 16 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 17 | } 18 | 19 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the app argument is missing" { 20 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l 21 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 22 | } 23 | 24 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the app does not exist" { 25 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l not_existing_app 26 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 27 | } 28 | 29 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the service does not exist" { 30 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" not_existing_service my_app 31 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 32 | } 33 | 34 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the service is already promoted" { 35 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app 36 | assert_contains "${lines[*]}" "already promoted as CHROME_URL" 37 | } 38 | 39 | @test "($PLUGIN_COMMAND_PREFIX:promote) changes CHROME_URL" { 40 | dokku config:set my_app "CHROME_URL=http://host:3000" "DOKKU_CHROME_BLUE_URL=http://dokku-chrome-l:3000" 41 | dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app 42 | url=$(dokku config:get my_app CHROME_URL) 43 | assert_equal "$url" "http://dokku-chrome-l:3000" 44 | } 45 | 46 | @test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" { 47 | dokku config:set my_app "CHROME_URL=http://host:3000" "DOKKU_CHROME_BLUE_URL=http://dokku-chrome-l:3000" 48 | dokku "$PLUGIN_COMMAND_PREFIX:promote" l my_app 49 | run dokku config my_app 50 | assert_contains "${lines[*]}" "DOKKU_CHROME_" 51 | } 52 | -------------------------------------------------------------------------------- /tests/service_restart.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | reset_system_data 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:restart) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:restart" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:restart) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:restart" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:restart) success" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:restart" l 24 | assert_success 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tests/service_start.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | reset_system_data 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:start) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:start" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:start) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:start" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:start) success" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:start" l 24 | assert_success 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tests/service_stop.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l >&2 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:stop) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:stop) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:stop) success" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" l 24 | assert_success 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tests/service_unexpose.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 6 | } 7 | 8 | teardown() { 9 | reset_system_data 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:unexpose) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:unexpose" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:unexpose) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:unexpose" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:unexpose) success" { 23 | dokku "$PLUGIN_COMMAND_PREFIX:expose" l 24 | run dokku "$PLUGIN_COMMAND_PREFIX:unexpose" l 25 | [[ ! -f $PLUGIN_DATA_ROOT/PORT ]] 26 | assert_contains "${lines[*]}" "Service l unexposed" 27 | } 28 | 29 | -------------------------------------------------------------------------------- /tests/service_unlink.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku apps:create my_app >&2 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" l >&2 7 | } 8 | 9 | teardown() { 10 | reset_system_data 11 | } 12 | 13 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when there are no arguments" { 14 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" 15 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the app argument is missing" { 19 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" l 20 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 21 | } 22 | 23 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the app does not exist" { 24 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" l not_existing_app 25 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 26 | } 27 | 28 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the service does not exist" { 29 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" not_existing_service my_app 30 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 31 | } 32 | 33 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when service not linked to app" { 34 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app 35 | assert_contains "${lines[*]}" "Not linked to app my_app" 36 | } 37 | 38 | @test "($PLUGIN_COMMAND_PREFIX:unlink) removes link from docker-options" { 39 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2 40 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app 41 | 42 | check_value="" 43 | report_action="docker-options" 44 | check_value="Docker options build: Docker options deploy: --restart=on-failure:10 Docker options run:" 45 | report_action="docker-options:report" 46 | 47 | options=$(dokku --quiet $report_action my_app | xargs) 48 | assert_equal "$options" "$check_value" 49 | } 50 | 51 | @test "($PLUGIN_COMMAND_PREFIX:unlink) unsets config url from app" { 52 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my_app >&2 53 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my_app 54 | config=$(dokku config:get my_app ELASTICSEARCH_URL || true) 55 | assert_equal "$config" "" 56 | } 57 | -------------------------------------------------------------------------------- /tests/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/test_helper.bash" 4 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 5 | export DOKKU_INSTALL_ROOT=/var/lib/dokku 6 | 7 | echo "Uninstalling plugin and clearing data..." 8 | sudo dokku plugin:uninstall $PLUGIN_COMMAND_PREFIX || true 9 | sudo rm -fr $CHROME_ROOT $PLUGIN_DATA_ROOT $PLUGIN_CONFIG_ROOT 10 | 11 | echo "Linking plugin files..." 12 | sudo -u dokku mkdir -p $DOKKU_INSTALL_ROOT/plugins/available/$PLUGIN_COMMAND_PREFIX $DOKKU_INSTALL_ROOT/plugins/available/$PLUGIN_COMMAND_PREFIX/subcommands 13 | sudo -u dokku find ./ -maxdepth 1 -type f -exec cp '{}' $DOKKU_INSTALL_ROOT/plugins/available/$PLUGIN_COMMAND_PREFIX \; 14 | sudo -u dokku find ./subcommands -maxdepth 1 -type f -exec cp '{}' $DOKKU_INSTALL_ROOT/plugins/available/$PLUGIN_COMMAND_PREFIX/subcommands \; 15 | 16 | echo "Enabling plugin and running installation..." 17 | sudo -u dokku ln -s $DOKKU_INSTALL_ROOT/plugins/available/$PLUGIN_COMMAND_PREFIX $DOKKU_INSTALL_ROOT/plugins/enabled/$PLUGIN_COMMAND_PREFIX 18 | sudo dokku plugin:install 19 | -------------------------------------------------------------------------------- /tests/test_helper.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | 4 | reset_system_data() { 5 | local containers=$(sudo docker ps -aq) 6 | if [ "$containers" != "" ]; then 7 | sudo docker stop $containers > /dev/null 2>&1 8 | fi 9 | sudo docker system prune -f > /dev/null 2>&1 10 | if [ -z $CHROME_ROOT ]; then 11 | echo "CHROME_ROOT not set, can't clean up tests" 12 | exit -1 13 | else 14 | sudo -u dokku rm -rf /home/dokku/app /home/dokku/my_app $CHROME_ROOT/* 15 | fi 16 | } 17 | 18 | flunk() { 19 | { if [ "$#" -eq 0 ]; then cat - 20 | else echo "$*" 21 | fi 22 | } 23 | return 1 24 | } 25 | 26 | assert_equal() { 27 | if [ "$1" != "$2" ]; then 28 | { echo "expected: $1" 29 | echo "actual: $2" 30 | } | flunk 31 | fi 32 | } 33 | 34 | assert_exit_status() { 35 | assert_equal "$status" "$1" 36 | } 37 | 38 | assert_success() { 39 | if [ "$status" -ne 0 ]; then 40 | flunk "command failed with exit status $status" 41 | elif [ "$#" -gt 0 ]; then 42 | assert_output "$1" 43 | fi 44 | } 45 | 46 | assert_failure() { 47 | if [[ "$status" -eq 0 ]]; then 48 | flunk "expected failed exit status" 49 | elif [[ "$#" -gt 0 ]]; then 50 | assert_output "$1" 51 | fi 52 | } 53 | 54 | assert_exists() { 55 | if [ ! -f "$1" ]; then 56 | flunk "expected file to exist: $1" 57 | fi 58 | } 59 | 60 | assert_contains() { 61 | if [[ "$1" != *"$2"* ]]; then 62 | flunk "expected $2 to be in: $1" 63 | fi 64 | } 65 | 66 | assert_output() { 67 | local expected 68 | if [ $# -eq 0 ]; then expected="$(cat -)" 69 | else expected="$1" 70 | fi 71 | assert_equal "$expected" "$output" 72 | } 73 | --------------------------------------------------------------------------------