├── .devcontainer ├── 20_init_plugin ├── Dockerfile ├── bin │ └── copy-file └── devcontainer.json ├── .editorconfig ├── .github ├── dependabot.yml ├── labels.yml └── workflows │ ├── ci.yml │ └── tagged-release.yml ├── .gitignore ├── Dockerfile ├── LICENSE.txt ├── Makefile ├── README.md ├── Vagrantfile ├── bin └── generate ├── commands ├── common-functions ├── config ├── docs └── README.md ├── functions ├── help-functions ├── install ├── plugin.toml ├── post-app-clone-setup ├── post-app-rename-setup ├── pre-delete ├── pre-restore ├── pre-start ├── service-list ├── subcommands ├── app-links ├── backup ├── backup-auth ├── backup-deauth ├── backup-schedule ├── backup-schedule-cat ├── backup-set-encryption ├── backup-set-public-key-encryption ├── backup-unschedule ├── backup-unset-encryption ├── backup-unset-public-key-encryption ├── clone ├── connect ├── create ├── destroy ├── enter ├── exists ├── export ├── expose ├── import ├── info ├── link ├── linked ├── links ├── list ├── logs ├── pause ├── promote ├── restart ├── set ├── start ├── stop ├── unexpose ├── unlink └── upgrade ├── tests ├── hook_pre_delete.bats ├── link_networks.bats ├── service_connect.bats ├── service_create.bats ├── service_destroy.bats ├── service_expose.bats ├── service_info.bats ├── service_link.bats ├── service_list.bats ├── service_logs.bats ├── service_pause.bats ├── service_promote.bats ├── service_restart.bats ├── service_start.bats ├── service_stop.bats ├── service_unexpose.bats ├── service_unlink.bats ├── setup.sh ├── shellcheck-exclude ├── shellcheck-to-junit └── test_helper.bash └── update /.devcontainer/20_init_plugin: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | log-info() { 5 | declare desc="Log info formatter" 6 | echo " $*" 1>&2 7 | } 8 | 9 | log-fail() { 10 | declare desc="Log fail formatter" 11 | echo "! $*" 1>&2 12 | exit 1 13 | } 14 | 15 | main() { 16 | dokku plugin:install 17 | 18 | # built in the Dockerfile 19 | PLUGIN_NAME="$(source /tmp/.env && echo "$PLUGIN_NAME")" 20 | PLUGIN_VARIABLE="$(source /tmp/.env && echo "$PLUGIN_VARIABLE")" 21 | echo "export ${PLUGIN_VARIABLE}_HOST_ROOT=${SERVICE_HOST_ROOT}/$PLUGIN_NAME" >/etc/default/dokku 22 | } 23 | 24 | main "$@" 25 | -------------------------------------------------------------------------------- /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM dokku/dokku:latest 2 | 3 | RUN apt-get update 4 | RUN apt-get install --no-install-recommends -y build-essential file nano && \ 5 | apt-get clean autoclean && \ 6 | apt-get autoremove --yes && \ 7 | rm -rf /var/lib/apt/lists/* && \ 8 | mkdir -p /mnt/dokku/home/dokku /mnt/dokku/var/lib/dokku/config /mnt/dokku/var/lib/dokku/data /mnt/dokku/var/lib/dokku/services && \ 9 | chown -R dokku:dokku /mnt/dokku/home/dokku /mnt/dokku/var/lib/dokku/config /mnt/dokku/var/lib/dokku/data /mnt/dokku/var/lib/dokku/services && \ 10 | echo "dokku.me" > /home/dokku/VHOST 11 | 12 | ADD https://raw.githubusercontent.com/dokku/dokku/master/tests/dhparam.pem /mnt/dokku/etc/nginx/dhparam.pem 13 | 14 | COPY .devcontainer/20_init_plugin /etc/my_init.d/20_init_plugin 15 | COPY .devcontainer/bin/ /usr/local/bin/ 16 | 17 | COPY . . 18 | 19 | RUN source /tmp/config && \ 20 | echo "export ${PLUGIN_DISABLE_PULL_VARIABLE}=true" > /tmp/.env && \ 21 | echo "export PLUGIN_NAME=${PLUGIN_COMMAND_PREFIX}" >> /tmp/.env && \ 22 | echo "export PLUGIN_VARIABLE=${PLUGIN_VARIABLE}" >> /tmp/.env 23 | 24 | RUN source /tmp/.env && \ 25 | dokku plugin:install file:///tmp --name $PLUGIN_NAME && \ 26 | make ci-dependencies 27 | -------------------------------------------------------------------------------- /.devcontainer/bin/copy-file: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | main() { 4 | PLUGIN_NAME="$(source /tmp/.env && echo "$PLUGIN_NAME")" 5 | cp "$1" "/var/lib/dokku/plugins/enabled/$PLUGIN_NAME/$1" 6 | } 7 | 8 | main "$@" 9 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "build": { 3 | "dockerfile": "Dockerfile", 4 | "context": ".." 5 | }, 6 | "containerEnv": { 7 | "SERVICE_HOST_ROOT": "${localWorkspaceFolder}/tmp/data" 8 | }, 9 | "initializeCommand": ["mkdir", "-p", "tmp/data"], 10 | "mounts": [ 11 | "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind", 12 | "source=${localWorkspaceFolder}/tmp/data/,target=/var/lib/dokku/services/,type=bind" 13 | ], 14 | "overrideCommand": false, 15 | "runArgs": ["--init"] 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | insert_final_newline = true 5 | indent_style = space 6 | indent_size = 2 7 | 8 | [Makefile] 9 | insert_final_newline = true 10 | indent_style = tab 11 | indent_size = 4 12 | 13 | [*.mk] 14 | insert_final_newline = true 15 | indent_style = tab 16 | indent_size = 4 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "docker" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: daily 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | labels: 2 | - name: bc-break 3 | color: eb6420 4 | - name: blocks release 5 | color: "000000" 6 | - name: 'difficulty: easy' 7 | color: c5def5 8 | - name: 'difficulty: hard' 9 | color: e99695 10 | - name: 'difficulty: medium' 11 | color: fef2c0 12 | - name: hacktoberfest 13 | color: b0581d 14 | - name: 'needs: documentation' 15 | color: c2e0c6 16 | - name: 'needs: more info' 17 | color: c2e0c6 18 | - name: 'needs: rebase' 19 | color: c2e0c6 20 | - name: 'needs: tests' 21 | color: c2e0c6 22 | - name: 'status: duplicate' 23 | color: cccccc 24 | - name: 'status: fix-provided' 25 | color: c5def5 26 | - name: 'status: future' 27 | color: c5def5 28 | - name: 'status: has plan' 29 | color: c5def5 30 | - name: 'status: invalid' 31 | color: cccccc 32 | - name: 'status: merge for next minor' 33 | color: c5def5 34 | - name: 'status: merge for next patch' 35 | color: c5def5 36 | - name: 'status: wontfix' 37 | color: cccccc 38 | - name: 'type: bug' 39 | color: e01b1b 40 | - name: 'type: documentation' 41 | color: 0052cc 42 | - name: 'type: enhancement' 43 | color: 09ab3c 44 | - name: 'type: question' 45 | color: cc317c 46 | - name: 'type: refactor' 47 | color: 0052cc 48 | - name: 'type: rfc' 49 | color: 0052cc 50 | - name: 'type: roadmap' 51 | color: 0052cc 52 | - name: 'type: service' 53 | color: "5319e7" 54 | - name: 'type: support' 55 | color: cc317c 56 | - name: 'type: tests' 57 | color: 0052cc 58 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: CI 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | pull_request: 7 | branches: 8 | - "*" 9 | push: 10 | branches: 11 | - master 12 | 13 | concurrency: 14 | group: build-${{ github.event.pull_request.number || github.ref }} 15 | cancel-in-progress: true 16 | 17 | jobs: 18 | unit-tests-master: 19 | name: unit-tests 20 | runs-on: ubuntu-24.04 21 | env: 22 | DOKKU_VERSION: master 23 | 24 | steps: 25 | - uses: actions/checkout@v4 26 | with: 27 | fetch-depth: 0 28 | 29 | - uses: actions/setup-python@v5 30 | with: 31 | python-version: "3.13" 32 | 33 | - run: make setup 34 | 35 | - run: sudo sysctl -w vm.max_map_count=262144 36 | 37 | - run: | 38 | git fetch -q origin master 39 | changed=$(git --no-pager diff --name-only $GITHUB_SHA..origin/master) 40 | if [ $changed = "Dockerfile" ]; then 41 | echo "Please run 'make generate' to update the image version in the README.md" 42 | else 43 | make generate 44 | if ! git diff --quiet README.md; then 45 | echo "Please run 'make generate'" 46 | git status --short 47 | git --no-pager diff README.md 48 | exit 1 49 | fi 50 | fi 51 | 52 | - run: make test 53 | 54 | - uses: actions/upload-artifact@v4 55 | if: failure() 56 | with: 57 | name: tmp/test-results 58 | path: test-results 59 | 60 | unit-tests-0_19_0: 61 | name: unit-tests-0.19.0 62 | runs-on: ubuntu-24.04 63 | env: 64 | DOKKU_TAG: v0.19.0 65 | 66 | steps: 67 | - uses: actions/checkout@v4 68 | with: 69 | fetch-depth: 0 70 | 71 | - uses: actions/setup-python@v5 72 | with: 73 | python-version: "3.13" 74 | 75 | - run: make setup 76 | 77 | - run: sudo sysctl -w vm.max_map_count=262144 78 | 79 | - run: | 80 | git fetch -q origin master 81 | changed=$(git --no-pager diff --name-only $GITHUB_SHA..origin/master) 82 | if [ $changed = "Dockerfile" ]; then 83 | echo "Please run 'make generate' to update the image version in the README.md" 84 | else 85 | make generate 86 | if ! git diff --quiet README.md; then 87 | echo "Please run 'make generate'" 88 | git status --short 89 | git --no-pager diff README.md 90 | exit 1 91 | fi 92 | fi 93 | 94 | - run: make test 95 | 96 | - uses: actions/upload-artifact@v4 97 | if: failure() 98 | with: 99 | name: tmp/test-results 100 | path: test-results 101 | -------------------------------------------------------------------------------- /.github/workflows/tagged-release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: "tagged-release" 3 | 4 | # yamllint disable-line rule:truthy 5 | on: 6 | push: 7 | tags: 8 | - "*" 9 | 10 | jobs: 11 | tagged-release: 12 | name: tagged-release 13 | runs-on: ubuntu-24.04 14 | 15 | steps: 16 | - name: Release 17 | uses: softprops/action-gh-release@v2.2.2 18 | with: 19 | generate_release_notes: true 20 | make_latest: "true" 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /tmp 2 | .vagrant 3 | bootstrap.sh 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM memcached:1.6.38 2 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2020 Jose Diaz-Gonzalez 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | HARDWARE = $(shell uname -m) 2 | SYSTEM_NAME = $(shell uname -s | tr '[:upper:]' '[:lower:]') 3 | ARCH = $(shell dpkg --print-architecture) 4 | SHFMT_VERSION = 3.0.2 5 | XUNIT_TO_GITHUB_VERSION = 0.3.0 6 | XUNIT_READER_VERSION = 0.1.0 7 | 8 | 9 | bats: 10 | ifeq ($(SYSTEM_NAME),darwin) 11 | ifneq ($(shell bats --version >/dev/null 2>&1 ; echo $$?),0) 12 | brew install bats-core 13 | endif 14 | else 15 | git clone https://github.com/bats-core/bats-core.git /tmp/bats 16 | cd /tmp/bats && sudo ./install.sh /usr/local 17 | rm -rf /tmp/bats 18 | endif 19 | 20 | shellcheck: 21 | ifneq ($(shell shellcheck --version >/dev/null 2>&1 ; echo $$?),0) 22 | ifeq ($(SYSTEM_NAME),darwin) 23 | brew install shellcheck 24 | else 25 | ifeq ($(ARCH),arm64) 26 | sudo add-apt-repository 'deb http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse' 27 | else 28 | sudo add-apt-repository 'deb http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse' 29 | endif 30 | sudo rm -rf /var/lib/apt/lists/* && sudo apt-get clean 31 | sudo apt-get update -qq && sudo apt-get install -qq -y shellcheck 32 | endif 33 | endif 34 | 35 | shfmt: 36 | ifneq ($(shell shfmt --version >/dev/null 2>&1 ; echo $$?),0) 37 | ifeq ($(shfmt),Darwin) 38 | brew install shfmt 39 | else 40 | wget -qO /tmp/shfmt https://github.com/mvdan/sh/releases/download/v$(SHFMT_VERSION)/shfmt_v$(SHFMT_VERSION)_linux_amd64 41 | chmod +x /tmp/shfmt 42 | sudo mv /tmp/shfmt /usr/local/bin/shfmt 43 | endif 44 | endif 45 | 46 | readlink: 47 | ifeq ($(shell uname),Darwin) 48 | ifeq ($(shell greadlink > /dev/null 2>&1 ; echo $$?),127) 49 | brew install coreutils 50 | endif 51 | ln -nfs `which greadlink` tests/bin/readlink 52 | endif 53 | 54 | ci-dependencies: shellcheck bats readlink 55 | 56 | lint-setup: 57 | @mkdir -p tmp/test-results/shellcheck tmp/shellcheck 58 | @find . -not -path '*/\.*' -type f | xargs file | grep text | awk -F ':' '{ print $$1 }' | xargs head -n1 | egrep -B1 "bash" | grep "==>" | awk '{ print $$2 }' > tmp/shellcheck/test-files 59 | @cat tests/shellcheck-exclude | sed -n -e '/^# SC/p' | cut -d' ' -f2 | paste -d, -s - > tmp/shellcheck/exclude 60 | 61 | lint: lint-setup 62 | # these are disabled due to their expansive existence in the codebase. we should clean it up though 63 | @cat tests/shellcheck-exclude | sed -n -e '/^# SC/p' 64 | @echo linting... 65 | @cat tmp/shellcheck/test-files | xargs shellcheck -e $(shell cat tmp/shellcheck/exclude) | tests/shellcheck-to-junit --output tmp/test-results/shellcheck/results.xml --files tmp/shellcheck/test-files --exclude $(shell cat tmp/shellcheck/exclude) 66 | 67 | unit-tests: 68 | @echo running unit tests... 69 | @mkdir -p tmp/test-results/bats 70 | @cd tests && echo "executing tests: $(shell cd tests ; ls *.bats | xargs)" 71 | cd tests && bats --report-formatter junit --timing -o ../tmp/test-results/bats *.bats 72 | 73 | tmp/xunit-reader: 74 | mkdir -p tmp 75 | curl -o tmp/xunit-reader.tgz -sL https://github.com/josegonzalez/go-xunit-reader/releases/download/v$(XUNIT_READER_VERSION)/xunit-reader_$(XUNIT_READER_VERSION)_$(SYSTEM_NAME)_$(HARDWARE).tgz 76 | tar xf tmp/xunit-reader.tgz -C tmp 77 | chmod +x tmp/xunit-reader 78 | 79 | setup: 80 | bash tests/setup.sh 81 | $(MAKE) ci-dependencies 82 | 83 | test: lint unit-tests 84 | 85 | report: tmp/xunit-reader 86 | tmp/xunit-reader -p 'tmp/test-results/bats/*.xml' 87 | tmp/xunit-reader -p 'tmp/test-results/shellcheck/*.xml' 88 | 89 | .PHONY: clean 90 | clean: 91 | rm -f README.md 92 | 93 | .PHONY: generate 94 | generate: clean README.md 95 | 96 | .PHONY: README.md 97 | README.md: 98 | bin/generate 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dokku memcached [![Build Status](https://img.shields.io/github/actions/workflow/status/dokku/dokku-memcached/ci.yml?branch=master&style=flat-square "Build Status")](https://github.com/dokku/dokku-memcached/actions/workflows/ci.yml?query=branch%3Amaster) [![IRC Network](https://img.shields.io/badge/irc-libera-blue.svg?style=flat-square "IRC Libera")](https://webchat.libera.chat/?channels=dokku) 2 | 3 | Official memcached plugin for dokku. Currently defaults to installing [memcached 1.6.38](https://hub.docker.com/_/memcached/). 4 | 5 | ## Requirements 6 | 7 | - dokku 0.19.x+ 8 | - docker 1.8.x 9 | 10 | ## Installation 11 | 12 | ```shell 13 | # on 0.19.x+ 14 | sudo dokku plugin:install https://github.com/dokku/dokku-memcached.git --name memcached 15 | ``` 16 | 17 | ## Commands 18 | 19 | ``` 20 | memcached:app-links # list all memcached service links for a given app 21 | memcached:backup-set-public-key-encryption # set GPG Public Key encryption for all future backups of memcached service 22 | memcached:backup-unset-public-key-encryption # unset GPG Public Key encryption for future backups of the memcached service 23 | memcached:connect # connect to the service via the memcached connection tool 24 | memcached:create [--create-flags...] # create a memcached service 25 | memcached:destroy [-f|--force] # delete the memcached service/data/container if there are no links left 26 | memcached:enter # enter or run a command in a running memcached service container 27 | memcached:exists # check if the memcached service exists 28 | memcached:expose # expose a memcached service on custom host:port if provided (random port on the 0.0.0.0 interface if otherwise unspecified) 29 | memcached:info [--single-info-flag] # print the service information 30 | memcached:link [--link-flags...] # link the memcached service to the app 31 | memcached:linked # check if the memcached service is linked to an app 32 | memcached:links # list all apps linked to the memcached service 33 | memcached:list # list all memcached services 34 | memcached:logs [-t|--tail] # print the most recent log(s) for this service 35 | memcached:pause # pause a running memcached service 36 | memcached:promote # promote service as MEMCACHED_URL in 37 | memcached:restart # graceful shutdown and restart of the memcached service container 38 | memcached:set # set or clear a property for a service 39 | memcached:start # start a previously stopped memcached service 40 | memcached:stop # stop a running memcached service 41 | memcached:unexpose # unexpose a previously exposed memcached service 42 | memcached:unlink # unlink the memcached service from the app 43 | memcached:upgrade [--upgrade-flags...] # upgrade service to the specified versions 44 | ``` 45 | 46 | ## Usage 47 | 48 | Help for any commands can be displayed by specifying the command as an argument to memcached:help. Plugin help output in conjunction with any files in the `docs/` folder is used to generate the plugin documentation. Please consult the `memcached:help` command for any undocumented commands. 49 | 50 | ### Basic Usage 51 | 52 | ### create a memcached service 53 | 54 | ```shell 55 | # usage 56 | dokku memcached:create [--create-flags...] 57 | ``` 58 | 59 | flags: 60 | 61 | - `-c|--config-options "--args --go=here"`: extra arguments to pass to the container create command (default: `None`) 62 | - `-C|--custom-env "USER=alpha;HOST=beta"`: semi-colon delimited environment variables to start the service with 63 | - `-i|--image IMAGE`: the image name to start the service with 64 | - `-I|--image-version IMAGE_VERSION`: the image version to start the service with 65 | - `-m|--memory MEMORY`: container memory limit in megabytes (default: unlimited) 66 | - `-N|--initial-network INITIAL_NETWORK`: the initial network to attach the service to 67 | - `-p|--password PASSWORD`: override the user-level service password 68 | - `-P|--post-create-network NETWORKS`: a comma-separated list of networks to attach the service container to after service creation 69 | - `-r|--root-password PASSWORD`: override the root-level service password 70 | - `-S|--post-start-network NETWORKS`: a comma-separated list of networks to attach the service container to after service start 71 | - `-s|--shm-size SHM_SIZE`: override shared memory size for memcached docker container 72 | 73 | Create a memcached service named lollipop: 74 | 75 | ```shell 76 | dokku memcached:create lollipop 77 | ``` 78 | 79 | You can also specify the image and image version to use for the service. It *must* be compatible with the memcached image. 80 | 81 | ```shell 82 | export MEMCACHED_IMAGE="memcached" 83 | export MEMCACHED_IMAGE_VERSION="${PLUGIN_IMAGE_VERSION}" 84 | dokku memcached:create lollipop 85 | ``` 86 | 87 | You can also specify custom environment variables to start the memcached service in semicolon-separated form. 88 | 89 | ```shell 90 | export MEMCACHED_CUSTOM_ENV="USER=alpha;HOST=beta" 91 | dokku memcached:create lollipop 92 | ``` 93 | 94 | ### print the service information 95 | 96 | ```shell 97 | # usage 98 | dokku memcached:info [--single-info-flag] 99 | ``` 100 | 101 | flags: 102 | 103 | - `--config-dir`: show the service configuration directory 104 | - `--data-dir`: show the service data directory 105 | - `--dsn`: show the service DSN 106 | - `--exposed-ports`: show service exposed ports 107 | - `--id`: show the service container id 108 | - `--internal-ip`: show the service internal ip 109 | - `--initial-network`: show the initial network being connected to 110 | - `--links`: show the service app links 111 | - `--post-create-network`: show the networks to attach to after service container creation 112 | - `--post-start-network`: show the networks to attach to after service container start 113 | - `--service-root`: show the service root directory 114 | - `--status`: show the service running status 115 | - `--version`: show the service image version 116 | 117 | Get connection information as follows: 118 | 119 | ```shell 120 | dokku memcached:info lollipop 121 | ``` 122 | 123 | You can also retrieve a specific piece of service info via flags: 124 | 125 | ```shell 126 | dokku memcached:info lollipop --config-dir 127 | dokku memcached:info lollipop --data-dir 128 | dokku memcached:info lollipop --dsn 129 | dokku memcached:info lollipop --exposed-ports 130 | dokku memcached:info lollipop --id 131 | dokku memcached:info lollipop --internal-ip 132 | dokku memcached:info lollipop --initial-network 133 | dokku memcached:info lollipop --links 134 | dokku memcached:info lollipop --post-create-network 135 | dokku memcached:info lollipop --post-start-network 136 | dokku memcached:info lollipop --service-root 137 | dokku memcached:info lollipop --status 138 | dokku memcached:info lollipop --version 139 | ``` 140 | 141 | ### list all memcached services 142 | 143 | ```shell 144 | # usage 145 | dokku memcached:list 146 | ``` 147 | 148 | List all services: 149 | 150 | ```shell 151 | dokku memcached:list 152 | ``` 153 | 154 | ### print the most recent log(s) for this service 155 | 156 | ```shell 157 | # usage 158 | dokku memcached:logs [-t|--tail] 159 | ``` 160 | 161 | flags: 162 | 163 | - `-t|--tail []`: do not stop when end of the logs are reached and wait for additional output 164 | 165 | You can tail logs for a particular service: 166 | 167 | ```shell 168 | dokku memcached:logs lollipop 169 | ``` 170 | 171 | By default, logs will not be tailed, but you can do this with the --tail flag: 172 | 173 | ```shell 174 | dokku memcached:logs lollipop --tail 175 | ``` 176 | 177 | The default tail setting is to show all logs, but an initial count can also be specified: 178 | 179 | ```shell 180 | dokku memcached:logs lollipop --tail 5 181 | ``` 182 | 183 | ### link the memcached service to the app 184 | 185 | ```shell 186 | # usage 187 | dokku memcached:link [--link-flags...] 188 | ``` 189 | 190 | flags: 191 | 192 | - `-a|--alias "BLUE_DATABASE"`: an alternative alias to use for linking to an app via environment variable 193 | - `-q|--querystring "pool=5"`: ampersand delimited querystring arguments to append to the service link 194 | - `-n|--no-restart "false"`: whether or not to restart the app on link (default: true) 195 | 196 | A memcached service can be linked to a container. This will use native docker links via the docker-options plugin. Here we link it to our `playground` app. 197 | 198 | > NOTE: this will restart your app 199 | 200 | ```shell 201 | dokku memcached:link lollipop playground 202 | ``` 203 | 204 | The following environment variables will be set automatically by docker (not on the app itself, so they won’t be listed when calling dokku config): 205 | 206 | ``` 207 | DOKKU_MEMCACHED_LOLLIPOP_NAME=/lollipop/DATABASE 208 | DOKKU_MEMCACHED_LOLLIPOP_PORT=tcp://172.17.0.1:11211 209 | DOKKU_MEMCACHED_LOLLIPOP_PORT_11211_TCP=tcp://172.17.0.1:11211 210 | DOKKU_MEMCACHED_LOLLIPOP_PORT_11211_TCP_PROTO=tcp 211 | DOKKU_MEMCACHED_LOLLIPOP_PORT_11211_TCP_PORT=11211 212 | DOKKU_MEMCACHED_LOLLIPOP_PORT_11211_TCP_ADDR=172.17.0.1 213 | ``` 214 | 215 | The following will be set on the linked application by default: 216 | 217 | ``` 218 | MEMCACHED_URL=memcached://dokku-memcached-lollipop:11211 219 | ``` 220 | 221 | The host exposed here only works internally in docker containers. If you want your container to be reachable from outside, you should use the `expose` subcommand. Another service can be linked to your app: 222 | 223 | ```shell 224 | dokku memcached:link other_service playground 225 | ``` 226 | 227 | It is possible to change the protocol for `MEMCACHED_URL` by setting the environment variable `MEMCACHED_DATABASE_SCHEME` on the app. Doing so will after linking will cause the plugin to think the service is not linked, and we advise you to unlink before proceeding. 228 | 229 | ```shell 230 | dokku config:set playground MEMCACHED_DATABASE_SCHEME=memcached2 231 | dokku memcached:link lollipop playground 232 | ``` 233 | 234 | This will cause `MEMCACHED_URL` to be set as: 235 | 236 | ``` 237 | memcached2://dokku-memcached-lollipop:11211 238 | ``` 239 | 240 | ### unlink the memcached service from the app 241 | 242 | ```shell 243 | # usage 244 | dokku memcached:unlink 245 | ``` 246 | 247 | flags: 248 | 249 | - `-n|--no-restart "false"`: whether or not to restart the app on unlink (default: true) 250 | 251 | You can unlink a memcached service: 252 | 253 | > NOTE: this will restart your app and unset related environment variables 254 | 255 | ```shell 256 | dokku memcached:unlink lollipop playground 257 | ``` 258 | 259 | ### set or clear a property for a service 260 | 261 | ```shell 262 | # usage 263 | dokku memcached:set 264 | ``` 265 | 266 | Set the network to attach after the service container is started: 267 | 268 | ```shell 269 | dokku memcached:set lollipop post-create-network custom-network 270 | ``` 271 | 272 | Set multiple networks: 273 | 274 | ```shell 275 | dokku memcached:set lollipop post-create-network custom-network,other-network 276 | ``` 277 | 278 | Unset the post-create-network value: 279 | 280 | ```shell 281 | dokku memcached:set lollipop post-create-network 282 | ``` 283 | 284 | ### Service Lifecycle 285 | 286 | The lifecycle of each service can be managed through the following commands: 287 | 288 | ### connect to the service via the memcached connection tool 289 | 290 | ```shell 291 | # usage 292 | dokku memcached:connect 293 | ``` 294 | 295 | Connect to the service via the memcached connection tool: 296 | 297 | > NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098 298 | 299 | ```shell 300 | dokku memcached:connect lollipop 301 | ``` 302 | 303 | ### enter or run a command in a running memcached service container 304 | 305 | ```shell 306 | # usage 307 | dokku memcached:enter 308 | ``` 309 | 310 | A bash prompt can be opened against a running service. Filesystem changes will not be saved to disk. 311 | 312 | > NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098 313 | 314 | ```shell 315 | dokku memcached:enter lollipop 316 | ``` 317 | 318 | You may also run a command directly against the service. Filesystem changes will not be saved to disk. 319 | 320 | ```shell 321 | dokku memcached:enter lollipop touch /tmp/test 322 | ``` 323 | 324 | ### expose a memcached service on custom host:port if provided (random port on the 0.0.0.0 interface if otherwise unspecified) 325 | 326 | ```shell 327 | # usage 328 | dokku memcached:expose 329 | ``` 330 | 331 | Expose the service on the service's normal ports, allowing access to it from the public interface (`0.0.0.0`): 332 | 333 | ```shell 334 | dokku memcached:expose lollipop 11211 335 | ``` 336 | 337 | Expose the service on the service's normal ports, with the first on a specified ip address (127.0.0.1): 338 | 339 | ```shell 340 | dokku memcached:expose lollipop 127.0.0.1:11211 341 | ``` 342 | 343 | ### unexpose a previously exposed memcached service 344 | 345 | ```shell 346 | # usage 347 | dokku memcached:unexpose 348 | ``` 349 | 350 | Unexpose the service, removing access to it from the public interface (`0.0.0.0`): 351 | 352 | ```shell 353 | dokku memcached:unexpose lollipop 354 | ``` 355 | 356 | ### promote service as MEMCACHED_URL in 357 | 358 | ```shell 359 | # usage 360 | dokku memcached:promote 361 | ``` 362 | 363 | If you have a memcached service linked to an app and try to link another memcached service another link environment variable will be generated automatically: 364 | 365 | ``` 366 | DOKKU_MEMCACHED_BLUE_URL=memcached://other_service:ANOTHER_PASSWORD@dokku-memcached-other-service:11211/other_service 367 | ``` 368 | 369 | You can promote the new service to be the primary one: 370 | 371 | > NOTE: this will restart your app 372 | 373 | ```shell 374 | dokku memcached:promote other_service playground 375 | ``` 376 | 377 | This will replace `MEMCACHED_URL` with the url from other_service and generate another environment variable to hold the previous value if necessary. You could end up with the following for example: 378 | 379 | ``` 380 | MEMCACHED_URL=memcached://other_service:ANOTHER_PASSWORD@dokku-memcached-other-service:11211/other_service 381 | DOKKU_MEMCACHED_BLUE_URL=memcached://other_service:ANOTHER_PASSWORD@dokku-memcached-other-service:11211/other_service 382 | DOKKU_MEMCACHED_SILVER_URL=memcached://lollipop:SOME_PASSWORD@dokku-memcached-lollipop:11211/lollipop 383 | ``` 384 | 385 | ### start a previously stopped memcached service 386 | 387 | ```shell 388 | # usage 389 | dokku memcached:start 390 | ``` 391 | 392 | Start the service: 393 | 394 | ```shell 395 | dokku memcached:start lollipop 396 | ``` 397 | 398 | ### stop a running memcached service 399 | 400 | ```shell 401 | # usage 402 | dokku memcached:stop 403 | ``` 404 | 405 | Stop the service and removes the running container: 406 | 407 | ```shell 408 | dokku memcached:stop lollipop 409 | ``` 410 | 411 | ### pause a running memcached service 412 | 413 | ```shell 414 | # usage 415 | dokku memcached:pause 416 | ``` 417 | 418 | Pause the running container for the service: 419 | 420 | ```shell 421 | dokku memcached:pause lollipop 422 | ``` 423 | 424 | ### graceful shutdown and restart of the memcached service container 425 | 426 | ```shell 427 | # usage 428 | dokku memcached:restart 429 | ``` 430 | 431 | Restart the service: 432 | 433 | ```shell 434 | dokku memcached:restart lollipop 435 | ``` 436 | 437 | ### upgrade service to the specified versions 438 | 439 | ```shell 440 | # usage 441 | dokku memcached:upgrade [--upgrade-flags...] 442 | ``` 443 | 444 | flags: 445 | 446 | - `-c|--config-options "--args --go=here"`: extra arguments to pass to the container create command (default: `None`) 447 | - `-C|--custom-env "USER=alpha;HOST=beta"`: semi-colon delimited environment variables to start the service with 448 | - `-i|--image IMAGE`: the image name to start the service with 449 | - `-I|--image-version IMAGE_VERSION`: the image version to start the service with 450 | - `-N|--initial-network INITIAL_NETWORK`: the initial network to attach the service to 451 | - `-P|--post-create-network NETWORKS`: a comma-separated list of networks to attach the service container to after service creation 452 | - `-R|--restart-apps "true"`: whether or not to force an app restart (default: false) 453 | - `-S|--post-start-network NETWORKS`: a comma-separated list of networks to attach the service container to after service start 454 | - `-s|--shm-size SHM_SIZE`: override shared memory size for memcached docker container 455 | 456 | You can upgrade an existing service to a new image or image-version: 457 | 458 | ```shell 459 | dokku memcached:upgrade lollipop 460 | ``` 461 | 462 | ### Service Automation 463 | 464 | Service scripting can be executed using the following commands: 465 | 466 | ### list all memcached service links for a given app 467 | 468 | ```shell 469 | # usage 470 | dokku memcached:app-links 471 | ``` 472 | 473 | List all memcached services that are linked to the `playground` app. 474 | 475 | ```shell 476 | dokku memcached:app-links playground 477 | ``` 478 | 479 | ### check if the memcached service exists 480 | 481 | ```shell 482 | # usage 483 | dokku memcached:exists 484 | ``` 485 | 486 | Here we check if the lollipop memcached service exists. 487 | 488 | ```shell 489 | dokku memcached:exists lollipop 490 | ``` 491 | 492 | ### check if the memcached service is linked to an app 493 | 494 | ```shell 495 | # usage 496 | dokku memcached:linked 497 | ``` 498 | 499 | Here we check if the lollipop memcached service is linked to the `playground` app. 500 | 501 | ```shell 502 | dokku memcached:linked lollipop playground 503 | ``` 504 | 505 | ### list all apps linked to the memcached service 506 | 507 | ```shell 508 | # usage 509 | dokku memcached:links 510 | ``` 511 | 512 | List all apps linked to the `lollipop` memcached service. 513 | 514 | ```shell 515 | dokku memcached:links lollipop 516 | ``` 517 | ### Backups 518 | 519 | Datastore backups are supported via AWS S3 and S3 compatible services like [minio](https://github.com/minio/minio). 520 | 521 | You may skip the `backup-auth` step if your dokku install is running within EC2 and has access to the bucket via an IAM profile. In that case, use the `--use-iam` option with the `backup` command. 522 | 523 | Backups can be performed using the backup commands: 524 | 525 | ### set GPG Public Key encryption for all future backups of memcached service 526 | 527 | ```shell 528 | # usage 529 | dokku memcached:backup-set-public-key-encryption 530 | ``` 531 | 532 | Set the `GPG` Public Key for encrypting backups: 533 | 534 | ```shell 535 | dokku memcached:backup-set-public-key-encryption lollipop 536 | ``` 537 | 538 | ### unset GPG Public Key encryption for future backups of the memcached service 539 | 540 | ```shell 541 | # usage 542 | dokku memcached:backup-unset-public-key-encryption 543 | ``` 544 | 545 | Unset the `GPG` Public Key encryption for backups: 546 | 547 | ```shell 548 | dokku memcached:backup-unset-public-key-encryption lollipop 549 | ``` 550 | 551 | ### Disabling `docker image pull` calls 552 | 553 | If you wish to disable the `docker image pull` calls that the plugin triggers, you may set the `MEMCACHED_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. 554 | 555 | Please ensure the proper images are in place when `docker image pull` is disabled. 556 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | BOX_NAME = ENV["BOX_NAME"] || "bento/ubuntu-24.04" 5 | BOX_MEMORY = ENV["BOX_MEMORY"] || "2048" 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 | vb.customize ["modifyvm", :id, "--memory", BOX_MEMORY] 14 | end 15 | 16 | config.vm.provider :vmware_fusion do |v, override| 17 | v.vmx["memsize"] = BOX_MEMORY 18 | end 19 | 20 | config.vm.define "default", primary: true do |vm| 21 | vm.vm.synced_folder File.dirname(__FILE__), "/vagrant" 22 | 23 | vm.vm.provision :shell, :inline => "apt -q update && apt -y -qq install git software-properties-common" 24 | vm.vm.provision :shell, :inline => "cd /vagrant && DOKKU_VERSION=#{DOKKU_VERSION} make setup" 25 | vm.vm.provision :shell, :inline => "cd /vagrant && DOKKU_TRACE=1 DOKKU_VERSION=#{DOKKU_VERSION} make test" 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /bin/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | 5 | import os 6 | import re 7 | 8 | 9 | def compile( 10 | service, 11 | version, 12 | variable, 13 | alias, 14 | image, 15 | scheme, 16 | ports, 17 | sponsors, 18 | options, 19 | unimplemented, 20 | dokku_version, 21 | ): 22 | prefix = "\n\n".join( 23 | [ 24 | header(service), 25 | description(service, image, version), 26 | ] 27 | ) 28 | 29 | if len(sponsors) > 0: 30 | prefix += "\n\n" 31 | prefix += sponsors_section(service, sponsors) 32 | 33 | return ( 34 | "\n\n".join( 35 | [ 36 | prefix, 37 | requirements_section(dokku_version), 38 | installation_section(service, dokku_version), 39 | commands_section( 40 | service, variable, alias, image, scheme, ports, unimplemented 41 | ), 42 | usage_section( 43 | service, 44 | variable, 45 | alias, 46 | image, 47 | scheme, 48 | ports, 49 | options, 50 | unimplemented, 51 | ), 52 | ] 53 | ) 54 | .replace("\n\n\n\n\n", "\n") 55 | .replace("\n\n\n\n", "\n") 56 | .replace("\n\n\n", "\n\n") 57 | ) 58 | 59 | 60 | def header(service): 61 | return " ".join( 62 | [ 63 | f"# dokku {service}", 64 | f'[![Build Status](https://img.shields.io/github/actions/workflow/status/dokku/dokku-{service}/ci.yml?branch=master&style=flat-square "Build Status")](https://github.com/dokku/dokku-{service}/actions/workflows/ci.yml?query=branch%3Amaster)', 65 | f'[![IRC Network](https://img.shields.io/badge/irc-libera-blue.svg?style=flat-square "IRC Libera")](https://webchat.libera.chat/?channels=dokku)', 66 | ] 67 | ) 68 | 69 | 70 | def description(service, full_image, version): 71 | base = "_" 72 | image = full_image 73 | if "/" in full_image: 74 | base = "r/" + full_image.split("/")[0] 75 | image = full_image.split("/")[1] 76 | 77 | return f"Official {service} plugin for dokku. Currently defaults to installing [{full_image} {version}](https://hub.docker.com/{base}/{image}/)." 78 | 79 | 80 | def sponsors_section(service, sponsors): 81 | if len(sponsors) == 0: 82 | return "" 83 | 84 | sponsor_data = [ 85 | "## Sponsors", 86 | "", 87 | f"The {service} plugin was generously sponsored by the following:", 88 | "", 89 | ] 90 | sponsor_data.extend([f"- [{s}](https://github.com/{s})" for s in sponsors]) 91 | 92 | return "\n".join(sponsor_data) 93 | 94 | 95 | def requirements_section(dokku_version): 96 | return "\n".join( 97 | [ 98 | "## Requirements", 99 | "", 100 | f"- dokku {dokku_version}", 101 | "- docker 1.8.x", 102 | ] 103 | ) 104 | 105 | 106 | def installation_section(service, dokku_version): 107 | return "\n".join( 108 | [ 109 | "## Installation", 110 | "", 111 | "```shell", 112 | f"# on {dokku_version}", 113 | f"sudo dokku plugin:install https://github.com/dokku/dokku-{service}.git --name {service}", 114 | "```", 115 | ] 116 | ) 117 | 118 | 119 | def commands_section(service, variable, alias, image, scheme, ports, unimplemented): 120 | content = [ 121 | "## Commands", 122 | "", 123 | "```", 124 | ] 125 | 126 | subcommands = os.listdir("subcommands") 127 | subcommands.sort() 128 | 129 | command_list = [] 130 | descriptions = [] 131 | for filename in subcommands: 132 | if filename in unimplemented: 133 | continue 134 | data = command_data(filename, service, variable, alias, image, scheme, ports) 135 | description = data["description"] 136 | arguments = data["arguments_string"] 137 | 138 | command_list.append(f"{service}:{filename} {arguments}") 139 | descriptions.append(description) 140 | 141 | maxlen = max(map(len, command_list)) 142 | if maxlen > 50: 143 | maxlen = 50 144 | for command, description in zip(command_list, descriptions): 145 | space_count = maxlen - len(command) 146 | content.append("{0}{1} # {2}".format(command, " " * space_count, description)) 147 | 148 | content.append("```") 149 | return "\n".join(content) 150 | 151 | 152 | def usage_section( 153 | service, variable, alias, image, scheme, ports, options, unimplemented 154 | ): 155 | return "\n\n".join( 156 | [ 157 | "## Usage", 158 | f"Help for any commands can be displayed by specifying the command as an argument to {service}:help. Plugin help output in conjunction with any files in the `docs/` folder is used to generate the plugin documentation. Please consult the `{service}:help` command for any undocumented commands.", 159 | usage_intro( 160 | service, variable, alias, image, scheme, ports, options, unimplemented 161 | ), 162 | usage_lifecycle( 163 | service, variable, alias, image, scheme, ports, options, unimplemented 164 | ), 165 | usage_automation( 166 | service, variable, alias, image, scheme, ports, options, unimplemented 167 | ), 168 | usage_data_management( 169 | service, variable, alias, image, scheme, ports, options, unimplemented 170 | ), 171 | usage_backup( 172 | service, variable, alias, image, scheme, ports, options, unimplemented 173 | ), 174 | usage_docker_pull( 175 | service, variable, alias, image, scheme, ports, options, unimplemented 176 | ), 177 | ] 178 | ) 179 | 180 | 181 | def usage_intro(service, variable, alias, image, scheme, ports, options, unimplemented): 182 | commands = ["create", "info", "list", "logs", "link", "unlink", "set"] 183 | content = ["### Basic Usage"] 184 | 185 | return fetch_commands_content( 186 | service, 187 | variable, 188 | alias, 189 | image, 190 | scheme, 191 | ports, 192 | options, 193 | unimplemented, 194 | commands, 195 | content, 196 | ) 197 | 198 | 199 | def usage_lifecycle( 200 | service, variable, alias, image, scheme, ports, options, unimplemented 201 | ): 202 | commands = [ 203 | "connect", 204 | "enter", 205 | "expose", 206 | "unexpose", 207 | "promote", 208 | "start", 209 | "stop", 210 | "pause", 211 | "restart", 212 | "upgrade", 213 | ] 214 | content = [ 215 | "### Service Lifecycle", 216 | "", 217 | "The lifecycle of each service can be managed through the following commands:", 218 | "", 219 | ] 220 | 221 | return fetch_commands_content( 222 | service, 223 | variable, 224 | alias, 225 | image, 226 | scheme, 227 | ports, 228 | options, 229 | unimplemented, 230 | commands, 231 | content, 232 | ) 233 | 234 | 235 | def usage_automation( 236 | service, variable, alias, image, scheme, ports, options, unimplemented 237 | ): 238 | commands = ["app-links", "clone", "exists", "linked", "links"] 239 | content = [ 240 | "### Service Automation", 241 | "", 242 | "Service scripting can be executed using the following commands:", 243 | "", 244 | ] 245 | 246 | return fetch_commands_content( 247 | service, 248 | variable, 249 | alias, 250 | image, 251 | scheme, 252 | ports, 253 | options, 254 | unimplemented, 255 | commands, 256 | content, 257 | ) 258 | 259 | 260 | def usage_data_management( 261 | service, variable, alias, image, scheme, ports, options, unimplemented 262 | ): 263 | commands = ["import", "export"] 264 | content = [ 265 | "### Data Management", 266 | "", 267 | "The underlying service data can be imported and exported with the following commands:", 268 | "", 269 | ] 270 | 271 | return fetch_commands_content( 272 | service, 273 | variable, 274 | alias, 275 | image, 276 | scheme, 277 | ports, 278 | options, 279 | unimplemented, 280 | commands, 281 | content, 282 | ) 283 | 284 | 285 | def usage_backup( 286 | service, variable, alias, image, scheme, ports, options, unimplemented 287 | ): 288 | commands = [ 289 | "backup-auth", 290 | "backup-deauth", 291 | "backup", 292 | "backup-set-encryption", 293 | "backup-set-public-key-encryption", 294 | "backup-unset-encryption", 295 | "backup-unset-public-key-encryption", 296 | "backup-schedule", 297 | "backup-schedule-cat", 298 | "backup-unschedule", 299 | ] 300 | content = [ 301 | "### Backups", 302 | "", 303 | "Datastore backups are supported via AWS S3 and S3 compatible services like [minio](https://github.com/minio/minio).", 304 | "", 305 | "You may skip the `backup-auth` step if your dokku install is running within EC2 and has access to the bucket via an IAM profile. In that case, use the `--use-iam` option with the `backup` command.", 306 | "", 307 | "Backups can be performed using the backup commands:", 308 | "", 309 | ] 310 | 311 | return fetch_commands_content( 312 | service, 313 | variable, 314 | alias, 315 | image, 316 | scheme, 317 | ports, 318 | options, 319 | unimplemented, 320 | commands, 321 | content, 322 | ) 323 | 324 | 325 | def usage_docker_pull( 326 | service, variable, alias, image, scheme, ports, options, unimplemented 327 | ): 328 | service_prefix = service.upper() 329 | return "\n".join( 330 | [ 331 | "### Disabling `docker image pull` calls", 332 | "", 333 | f"If you wish to disable the `docker image pull` calls that the plugin triggers, you may set the `{service_prefix}_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.", 334 | "", 335 | "Please ensure the proper images are in place when `docker image pull` is disabled.", 336 | ] 337 | ) 338 | 339 | 340 | def fetch_commands_content( 341 | service, 342 | variable, 343 | alias, 344 | image, 345 | scheme, 346 | ports, 347 | options, 348 | unimplemented, 349 | commands, 350 | content, 351 | ): 352 | i = 0 353 | for command in commands: 354 | output = command_help( 355 | command, 356 | service, 357 | variable, 358 | alias, 359 | image, 360 | scheme, 361 | ports, 362 | options, 363 | unimplemented, 364 | ) 365 | if output == "": 366 | continue 367 | content.append(output) 368 | i += 1 369 | 370 | if i == 0: 371 | return "" 372 | 373 | return "\n".join(content) 374 | 375 | 376 | def parse_args(line): 377 | line = line.strip() 378 | arguments = [] 379 | for arg in re.findall("([A-Z_]+)", line): 380 | arg = arg.replace("_", "-").lower() 381 | if arg.endswith("optional-flag"): 382 | arg = arg.replace("-optional-flag", "") 383 | arguments.append(f"[--{arg}]") 384 | elif arg.endswith("-flag"): 385 | if arg == "info-flag": 386 | arguments.append(f"[--single-info-flag]") 387 | else: 388 | arg = arg.replace("-flag", "") 389 | first_letter = arg[0] 390 | arguments.append(f"[-{first_letter}|--{arg}]") 391 | elif arg.endswith("-flags-list"): 392 | arg = arg.replace("-list", "") 393 | arguments.append(f"[--{arg}...]") 394 | elif arg.endswith("list"): 395 | arg = arg.replace("-list", "") 396 | arguments.append(f"<{arg}...>") 397 | else: 398 | arguments.append(f"<{arg}>") 399 | return " ".join(arguments) 400 | 401 | 402 | def command_help( 403 | command, service, variable, alias, image, scheme, ports, options, unimplemented 404 | ): 405 | if command in unimplemented: 406 | return "" 407 | 408 | data = command_data(command, service, variable, alias, image, scheme, ports) 409 | content = [ 410 | f"### {data['description']}", 411 | "", 412 | "```shell", 413 | "# usage", 414 | f"dokku {service}:{command} {data['arguments_string']}".strip(), 415 | "```", 416 | ] 417 | 418 | # if len(data["arguments"]) > 0: 419 | # content.append("") 420 | # content.append("arguments:") 421 | # content.append("") 422 | # for argument in data["arguments"]: 423 | # content.append(f"- {argument}") 424 | 425 | if len(data["flags"]) > 0: 426 | content.append("") 427 | content.append("flags:") 428 | content.append("") 429 | for flag in data["flags"]: 430 | if "--config-options" in flag and options != "": 431 | flag = f"{flag} (default: `{options}`)" 432 | content.append(f"- {flag}") 433 | 434 | if len(data["examples"]) > 0: 435 | content.append("") 436 | content.append(data["examples"]) 437 | 438 | doc_file = os.path.join("docs", f"{command}.md") 439 | if os.path.isfile(doc_file): 440 | content.append("") 441 | with open(doc_file) as f: 442 | content.append(f.read()) 443 | 444 | return "\n" + "\n".join(content) 445 | 446 | 447 | def command_data(command, service, variable, alias, image, scheme, ports): 448 | description = None 449 | arguments = [] 450 | arguments_string = "" 451 | example_lines = [] 452 | flags = [] 453 | with open(os.path.join("subcommands", command)) as f: 454 | for line in f.readlines(): 455 | line = line.strip() 456 | line = line.replace("$PLUGIN_SERVICE", service) 457 | line = line.replace("$PLUGIN_COMMAND_PREFIX", service) 458 | line = line.replace("${PLUGIN_COMMAND_PREFIX}", service) 459 | line = line.replace("${PLUGIN_VARIABLE}", variable) 460 | line = line.replace("${PLUGIN_DEFAULT_ALIAS}", alias) 461 | line = line.replace("${PLUGIN_IMAGE}", image) 462 | line = line.replace("${PLUGIN_SCHEME}", scheme) 463 | line = line.replace("${PLUGIN_DATASTORE_PORTS[0]}", ports[0]) 464 | line = line.replace("${PLUGIN_DATASTORE_PORTS[@]}", " ".join(ports)) 465 | 466 | if "declare desc" in line: 467 | description = re.search('"(.+)"', line).group(1) 468 | elif "$1" in line: 469 | arguments_string = parse_args(line) 470 | elif line.startswith("#A "): 471 | argument = line.replace("#A ", "") 472 | parts = [a.strip() for a in argument.split(",", 1)] 473 | arguments.append(f"`{parts[0]}`: {parts[1]}") 474 | elif line.startswith("#F "): 475 | flag = line.replace("#F ", "") 476 | parts = [a.strip() for a in flag.split(",", 1)] 477 | flags.append(f"`{parts[0]}`: {parts[1]}") 478 | elif line.startswith("#E "): 479 | example_lines.append(line.replace("#E ", "")) 480 | 481 | examples = [] 482 | sentence_lines = [] 483 | command_lines = [] 484 | codeblock_lines = [] 485 | blockquote_lines = [] 486 | for line in example_lines: 487 | if line.startswith("export") or line.startswith("dokku"): 488 | if len(blockquote_lines) > 0: 489 | examples.append("\n" + process_blockquote(blockquote_lines)) 490 | blockquote_lines = [] 491 | if len(codeblock_lines) > 0: 492 | examples.append("\n" + process_codeblock(codeblock_lines)) 493 | codeblock_lines = [] 494 | if len(sentence_lines) > 0: 495 | examples.append("\n" + process_sentence(sentence_lines)) 496 | sentence_lines = [] 497 | 498 | command_lines.append(line) 499 | elif line.startswith(" "): 500 | if len(blockquote_lines) > 0: 501 | examples.append("\n" + process_blockquote(blockquote_lines)) 502 | blockquote_lines = [] 503 | if len(command_lines) > 0: 504 | examples.append("\n" + process_command(command_lines)) 505 | command_lines = [] 506 | if len(sentence_lines) > 0: 507 | examples.append("\n" + process_sentence(sentence_lines)) 508 | sentence_lines = [] 509 | 510 | codeblock_lines.append(line.strip()) 511 | elif line.startswith(">"): 512 | if len(codeblock_lines) > 0: 513 | examples.append("\n" + process_codeblock(codeblock_lines)) 514 | codeblock_lines = [] 515 | if len(command_lines) > 0: 516 | examples.append("\n" + process_command(command_lines)) 517 | command_lines = [] 518 | if len(sentence_lines) > 0: 519 | examples.append("\n" + process_sentence(sentence_lines)) 520 | sentence_lines = [] 521 | 522 | blockquote_lines.append(line) 523 | else: 524 | if len(blockquote_lines) > 0: 525 | examples.append("\n" + process_blockquote(blockquote_lines)) 526 | blockquote_lines = [] 527 | if len(codeblock_lines) > 0: 528 | examples.append("\n" + process_codeblock(codeblock_lines)) 529 | codeblock_lines = [] 530 | if len(command_lines) > 0: 531 | examples.append("\n" + process_command(command_lines)) 532 | command_lines = [] 533 | 534 | sentence_lines.append(line) 535 | 536 | if len(blockquote_lines) > 0: 537 | examples.append("\n" + process_blockquote(blockquote_lines)) 538 | blockquote_lines = [] 539 | if len(codeblock_lines) > 0: 540 | examples.append("\n" + process_codeblock(codeblock_lines)) 541 | codeblock_lines = [] 542 | if len(command_lines) > 0: 543 | examples.append("\n" + process_command(command_lines)) 544 | command_lines = [] 545 | if len(sentence_lines) > 0: 546 | examples.append("\n" + process_sentence(sentence_lines)) 547 | sentence_lines = [] 548 | 549 | return { 550 | "description": description, 551 | "arguments_string": arguments_string, 552 | "arguments": arguments, 553 | "flags": flags, 554 | "examples": "\n".join(examples).strip(), 555 | } 556 | 557 | 558 | def process_sentence(sentence_lines): 559 | sentence_lines = " ".join(sentence_lines) 560 | sentences = ". ".join( 561 | upperfirst(i.strip()) for i in sentence_lines.split(". ") 562 | ).strip() 563 | if not sentences.endswith(".") and not sentences.endswith(":"): 564 | sentences += ":" 565 | 566 | text = [] 567 | for sentence in sentences.split(". "): 568 | parts = [] 569 | for word in sentence.strip().split(" "): 570 | if word.isupper() and len(word) > 1: 571 | for ending in [":", "."]: 572 | if word.endswith(ending): 573 | word = "`{0}`{1}".format(word[:-1], ending) 574 | else: 575 | word = "`{0}`".format(word) 576 | parts.append(word) 577 | text.append(" ".join(parts)) 578 | 579 | text = ". ".join(text) 580 | 581 | # some cleanup 582 | text = text.replace("(0.0.0.0)", "(`0.0.0.0`)") 583 | text = text.replace("'", "`") 584 | text = text.replace("`s", "'s") 585 | text = text.replace("``", "`") 586 | text = text.strip(" ") 587 | 588 | return text 589 | 590 | 591 | def upperfirst(x): 592 | return x[:1].upper() + x[1:] 593 | 594 | 595 | def process_blockquote(blockquote_lines): 596 | return "\n".join(blockquote_lines) 597 | 598 | 599 | def process_command(command_lines): 600 | command_lines = "\n".join(command_lines) 601 | return f"```shell\n{command_lines}\n```" 602 | 603 | 604 | def process_codeblock(codeblock_lines): 605 | codeblock_lines = "\n".join(codeblock_lines) 606 | return f"```\n{codeblock_lines}\n```" 607 | 608 | 609 | def main(): 610 | service = None 611 | version = None 612 | variable = None 613 | image = None 614 | alias = None 615 | options = None 616 | unimplemented = [] 617 | 618 | with open("Dockerfile") as f: 619 | for line in f.readlines(): 620 | if "FROM " in line: 621 | image, version = line.split(" ")[1].split(":") 622 | image = image.strip() 623 | version = version.strip() 624 | 625 | with open("config") as f: 626 | for line in f.readlines(): 627 | if "PLUGIN_COMMAND_PREFIX=" in line: 628 | service = re.search('"(.+)"', line).group(1) 629 | if "PLUGIN_DEFAULT_ALIAS=" in line: 630 | alias = re.search('"(.+)"', line).group(1) 631 | if "PLUGIN_VARIABLE=" in line: 632 | variable = re.search('"(.+)"', line).group(1) 633 | if "PLUGIN_SCHEME=" in line: 634 | scheme = re.search('"(.+)"', line).group(1) 635 | if "PLUGIN_DATASTORE_PORTS=" in line: 636 | ports = re.search("\((.+)\)", line).group(1).split(" ") 637 | if "PLUGIN_UNIMPLEMENTED_SUBCOMMANDS=" in line: 638 | match = re.search("\((.+)\)", line) 639 | if match is not None: 640 | unimplemented = [s.strip('"') for s in match.group(1).split(" ")] 641 | 642 | with open("config") as f: 643 | for line in f.readlines(): 644 | if f"{variable}_CONFIG_OPTIONS" in line: 645 | match = re.search('"(.+)"', line) 646 | if match is not None: 647 | options = match.group(1) 648 | 649 | sponsors = [] 650 | with open("plugin.toml") as f: 651 | for line in f.readlines(): 652 | if line.startswith("sponsors"): 653 | sponsors = re.search('\[(["\w\s,_-]+)\]', line).group(1) 654 | sponsors = [s.strip('"') for s in sponsors.split(",")] 655 | 656 | text = compile( 657 | service, 658 | version, 659 | variable, 660 | alias, 661 | image, 662 | scheme, 663 | ports, 664 | sponsors, 665 | options, 666 | unimplemented, 667 | "0.19.x+", 668 | ) 669 | 670 | base_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) 671 | readme_file = os.path.join(base_path, "README.md") 672 | with open(readme_file, "w") as f: 673 | f.write(text + "\n") 674 | 675 | 676 | if __name__ == "__main__": 677 | main() 678 | -------------------------------------------------------------------------------- /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_CORE_AVAILABLE_PATH/common/functions" 5 | 6 | set -eo pipefail 7 | [[ $DOKKU_TRACE ]] && set -x 8 | 9 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/help-functions" 10 | 11 | if [[ ! -d $PLUGIN_CONFIG_ROOT ]]; then 12 | dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" 13 | fi 14 | 15 | if [[ ! -d $PLUGIN_DATA_ROOT ]]; then 16 | dokku_log_fail "$PLUGIN_SERVICE: Please run: sudo dokku plugin:install" 17 | fi 18 | 19 | fn-help "$@" 20 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | _DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 3 | export MEMCACHED_IMAGE=${MEMCACHED_IMAGE:="$(awk -F '[ :]' '{print $2}' "${_DIR}/Dockerfile")"} 4 | export MEMCACHED_IMAGE_VERSION=${MEMCACHED_IMAGE_VERSION:="$(awk -F '[ :]' '{print $3}' "${_DIR}/Dockerfile")"} 5 | export MEMCACHED_ROOT=${MEMCACHED_ROOT:="$DOKKU_LIB_ROOT/services/memcached"} 6 | export DOKKU_LIB_HOST_ROOT=${DOKKU_LIB_HOST_ROOT:=$DOKKU_LIB_ROOT} 7 | export MEMCACHED_HOST_ROOT=${MEMCACHED_HOST_ROOT:="$DOKKU_LIB_HOST_ROOT/services/memcached"} 8 | 9 | export PLUGIN_UNIMPLEMENTED_SUBCOMMANDS=("backup" "backup-auth" "backup-deauth" "backup-schedule" "backup-schedule-cat" "backup-set-encryption" "backup-unschedule" "backup-unset-encryption" "clone" "export" "import") 10 | export PLUGIN_COMMAND_PREFIX="memcached" 11 | export PLUGIN_CONFIG_ROOT=${PLUGIN_CONFIG_ROOT:="$DOKKU_LIB_ROOT/config/$PLUGIN_COMMAND_PREFIX"} 12 | export PLUGIN_DATA_ROOT=$MEMCACHED_ROOT 13 | export PLUGIN_DATA_HOST_ROOT=$MEMCACHED_HOST_ROOT 14 | export PLUGIN_DATASTORE_PORTS=(11211) 15 | export PLUGIN_DATASTORE_WAIT_PORT=11211 16 | export PLUGIN_DEFAULT_ALIAS="MEMCACHED" 17 | export PLUGIN_DISABLE_PULL=${MEMCACHED_DISABLE_PULL:=} 18 | export PLUGIN_DISABLE_PULL_VARIABLE="MEMCACHED_DISABLE_PULL" 19 | export PLUGIN_ALT_ALIAS="DOKKU_MEMCACHED" 20 | export PLUGIN_IMAGE=$MEMCACHED_IMAGE 21 | export PLUGIN_IMAGE_VERSION=$MEMCACHED_IMAGE_VERSION 22 | export PLUGIN_SCHEME="memcached" 23 | export PLUGIN_SERVICE="Memcached" 24 | export PLUGIN_VARIABLE="MEMCACHED" 25 | export PLUGIN_BASE_PATH="$PLUGIN_PATH" 26 | export PLUGIN_CONFIG_SUFFIX="config" 27 | if [[ -n $DOKKU_API_VERSION ]]; then 28 | export PLUGIN_BASE_PATH="$PLUGIN_ENABLED_PATH" 29 | fi 30 | 31 | export PLUGIN_BUSYBOX_IMAGE=${PLUGIN_BUSYBOX_IMAGE:=busybox:1.37.0-uclibc} 32 | export PLUGIN_AMBASSADOR_IMAGE=${PLUGIN_AMBASSADOR_IMAGE:=dokku/ambassador:0.8.2} 33 | export PLUGIN_S3BACKUP_IMAGE=${PLUGIN_S3BACKUP_IMAGE:=dokku/s3backup:0.18.0} 34 | export PLUGIN_WAIT_IMAGE=${PLUGIN_WAIT_IMAGE:=dokku/wait:0.9.3} 35 | 36 | export MEMCACHED_CONFIG_OPTIONS=${MEMCACHED_CONFIG_OPTIONS:=""} 37 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Extra Documentation 2 | 3 | The documentation in this folder is supplemental to using this plugin. It is injected automatically into the plugin's readme during documentation generation. 4 | 5 | -------------------------------------------------------------------------------- /functions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 6 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 7 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" 8 | source "$PLUGIN_AVAILABLE_PATH/config/functions" 9 | if [[ -f "$PLUGIN_AVAILABLE_PATH/docker-options/functions" ]]; then 10 | source "$PLUGIN_AVAILABLE_PATH/docker-options/functions" 11 | fi 12 | 13 | service_connect() { 14 | local SERVICE="$1" 15 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 16 | local ID=$(cat "$SERVICE_ROOT/ID") 17 | local IP=$(get_container_ip "$ID") 18 | 19 | telnet "$IP" 11211 20 | } 21 | 22 | service_create() { 23 | local SERVICE="$1" 24 | is_valid_service_name "$SERVICE" || dokku_log_fail "Please specify a valid name for the service. Valid characters are: [A-Za-z0-9_]+" 25 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 26 | [[ ! -d "$PLUGIN_DATA_ROOT/$SERVICE" ]] || dokku_log_fail "$PLUGIN_SERVICE service $SERVICE already exists" 27 | SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 28 | LINKS_FILE="$SERVICE_ROOT/LINKS" 29 | 30 | service_parse_args "${@:2}" 31 | 32 | if ! service_image_exists "$SERVICE"; then 33 | if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then 34 | dokku_log_warn "${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2 35 | dokku_log_warn " docker image pull ${IMAGE}" 1>&2 36 | dokku_log_warn "$PLUGIN_SERVICE service creation failed" 37 | exit 1 38 | fi 39 | "$DOCKER_BIN" image pull "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" || dokku_log_fail "$PLUGIN_SERVICE image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION pull failed" 40 | fi 41 | 42 | plugn trigger service-action pre-create "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 43 | mkdir -p "$SERVICE_ROOT" || dokku_log_fail "Unable to create service directory" 44 | mkdir -p "$SERVICE_ROOT/data" || dokku_log_fail "Unable to create service data directory" 45 | mkdir -p "$SERVICE_ROOT/$PLUGIN_CONFIG_SUFFIX" || dokku_log_fail "Unable to create service config directory" 46 | touch "$LINKS_FILE" 47 | 48 | if [[ -z "$SERVICE_MEMORY" ]]; then 49 | SERVICE_MEMORY=64 50 | fi 51 | 52 | service_commit_config "$SERVICE" 53 | write_database_name "$SERVICE" 54 | plugn trigger service-action post-create "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 55 | service_create_container "$SERVICE" 56 | plugn trigger service-action post-create-complete "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 57 | } 58 | 59 | service_create_container() { 60 | local SERVICE="$1" 61 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 62 | local SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE" 63 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 64 | local SERVICE_MEMORY="64" 65 | 66 | if [[ -f "$SERVICE_ROOT/CONFIG_OPTIONS" ]]; then 67 | export CONFIG_OPTIONS="$(cat "$SERVICE_ROOT/CONFIG_OPTIONS")" 68 | fi 69 | 70 | local network_alias="$(service_dns_hostname "$SERVICE")" 71 | 72 | rm -f "$SERVICE_ROOT/ID" 73 | declare -a DOCKER_ARGS 74 | DOCKER_ARGS=() 75 | DOCKER_ARGS+=("--cidfile=$SERVICE_ROOT/ID") 76 | DOCKER_ARGS+=("--env-file=$SERVICE_ROOT/ENV") 77 | DOCKER_ARGS+=("--hostname=$SERVICE_NAME") 78 | DOCKER_ARGS+=("--label=dokku.service=$PLUGIN_COMMAND_PREFIX") 79 | DOCKER_ARGS+=("--label=dokku=service") 80 | DOCKER_ARGS+=("--name=$SERVICE_NAME") 81 | DOCKER_ARGS+=("--restart=always") 82 | 83 | declare -a LINK_CONTAINER_DOCKER_ARGS 84 | LINK_CONTAINER_DOCKER_ARGS=() 85 | LINK_CONTAINER_DOCKER_ARGS+=("--rm") 86 | LINK_CONTAINER_DOCKER_ARGS+=("--link") 87 | LINK_CONTAINER_DOCKER_ARGS+=("$SERVICE_NAME:$network_alias") 88 | 89 | [[ -f "$SERVICE_ROOT/SERVICE_MEMORY" ]] && SERVICE_MEMORY="$(cat "$SERVICE_ROOT/SERVICE_MEMORY")" 90 | if [[ -n "$SERVICE_MEMORY" ]]; then 91 | DOCKER_ARGS+=("--memory=${SERVICE_MEMORY}m") 92 | fi 93 | 94 | [[ -f "$SERVICE_ROOT/SHM_SIZE" ]] && SERVICE_SHM_SIZE="$(cat "$SERVICE_ROOT/SHM_SIZE")" 95 | if [[ -n "$SERVICE_SHM_SIZE" ]]; then 96 | DOCKER_ARGS+=("--shm-size=${SERVICE_SHM_SIZE}") 97 | fi 98 | 99 | [[ -f "$SERVICE_ROOT/IMAGE" ]] && PLUGIN_IMAGE="$(cat "$SERVICE_ROOT/IMAGE")" 100 | [[ -f "$SERVICE_ROOT/IMAGE_VERSION" ]] && PLUGIN_IMAGE_VERSION="$(cat "$SERVICE_ROOT/IMAGE_VERSION")" 101 | 102 | local network="$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "initial-network")" 103 | if [[ -n "$network" ]]; then 104 | DOCKER_ARGS+=("--network=${network}") 105 | DOCKER_ARGS+=("--network-alias=${network_alias}") 106 | LINK_CONTAINER_DOCKER_ARGS+=("--network=${network}") 107 | fi 108 | 109 | [[ -z "$SERVICE_MEMORY" ]] && SERVICE_MEMORY="64" 110 | 111 | # shellcheck disable=SC2086 112 | suppress_output "$DOCKER_BIN" container create "${DOCKER_ARGS[@]}" "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" memcached -m "$SERVICE_MEMORY" $CONFIG_OPTIONS 113 | 114 | if [[ -n "$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-create-network")" ]]; then 115 | dokku_log_verbose_quiet "Connecting to networks after container create" 116 | while read -r line || [[ -n "$line" ]]; do 117 | dokku_log_verbose_quiet "- $line" 118 | "$DOCKER_BIN" network connect --alias "$network_alias" "$line" "$SERVICE_NAME" 119 | done < <(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-create-network" | tr "," "\n") 120 | fi 121 | suppress_output "$DOCKER_BIN" container start "$(cat "$SERVICE_ROOT/ID")" 122 | service_port_reconcile_status "$SERVICE" 123 | 124 | if [[ -n "$(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-start-network")" ]]; then 125 | dokku_log_verbose_quiet "Connecting to networks after container start" 126 | while read -r line || [[ -n "$line" ]]; do 127 | dokku_log_verbose_quiet "- $line" 128 | "$DOCKER_BIN" network connect --alias "$network_alias" "$line" "$SERVICE_NAME" 129 | done < <(fn-plugin-property-get "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "post-start-network" | tr "," "\n") 130 | fi 131 | 132 | dokku_log_verbose_quiet "Waiting for container to be ready" 133 | if ! suppress_output "$DOCKER_BIN" container run "${LINK_CONTAINER_DOCKER_ARGS[@]}" "$PLUGIN_WAIT_IMAGE" -c "$network_alias:$PLUGIN_DATASTORE_WAIT_PORT"; then 134 | dokku_log_info2_quiet "Start of $SERVICE container output" 135 | dokku_container_log_verbose_quiet "$SERVICE_NAME" 136 | dokku_log_info2_quiet "End of $SERVICE container output" 137 | return 1 138 | fi 139 | 140 | dokku_log_info2 "$PLUGIN_SERVICE container created: $SERVICE" 141 | service_info "$SERVICE" 142 | } 143 | 144 | service_export() { 145 | local SERVICE="$1" 146 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 147 | 148 | dokku_log_fail "Not yet implemented" 149 | } 150 | 151 | service_import() { 152 | local SERVICE="$1" 153 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 154 | local SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE" 155 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 156 | 157 | dokku_log_fail "Not yet implemented" 158 | } 159 | 160 | service_start() { 161 | local SERVICE="$1" 162 | local QUIET="$2" 163 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 164 | local SERVICE_NAME="$(get_service_name "$SERVICE")" 165 | local ID=$("$DOCKER_BIN" container ps -aq --no-trunc --filter "status=running" --filter "name=^/$SERVICE_NAME$") || true 166 | if [[ -n $ID ]]; then 167 | [[ -z $QUIET ]] && dokku_log_warn "Service is already started" 168 | if [[ ! -f "$SERVICE_ROOT/ID" ]] || [[ "$(cat "$SERVICE_ROOT/ID")" != "$ID" ]]; then 169 | [[ -z $QUIET ]] && dokku_log_warn "Updating local container ID" 170 | echo "$ID" >"$SERVICE_ROOT/ID" 171 | fi 172 | return 0 173 | fi 174 | 175 | dokku_log_info2_quiet "Starting container" 176 | local PREVIOUS_ID=$("$DOCKER_BIN" container ps -aq --no-trunc --filter "status=exited" --filter "name=^/$SERVICE_NAME$") || true 177 | 178 | if [[ -n $PREVIOUS_ID ]]; then 179 | "$DOCKER_BIN" container start "$PREVIOUS_ID" >/dev/null 180 | service_port_reconcile_status "$SERVICE" 181 | dokku_log_info2 "Container started" 182 | elif service_image_exists "$SERVICE"; then 183 | service_create_container "$SERVICE" 184 | else 185 | if ! service_image_exists "$SERVICE"; then 186 | [[ -f "$SERVICE_ROOT/IMAGE" ]] && PLUGIN_IMAGE="$(cat "$SERVICE_ROOT/IMAGE")" 187 | [[ -f "$SERVICE_ROOT/IMAGE_VERSION" ]] && PLUGIN_IMAGE_VERSION="$(cat "$SERVICE_ROOT/IMAGE_VERSION")" 188 | dokku_log_verbose_quiet "Missing image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION for $SERVICE" 189 | else 190 | dokku_log_verbose_quiet "Neither container nor valid configuration exists for $SERVICE" 191 | fi 192 | fi 193 | } 194 | 195 | service_url() { 196 | local SERVICE="$1" 197 | local SERVICE_DNS_HOSTNAME="$(service_dns_hostname "$SERVICE")" 198 | echo "$PLUGIN_SCHEME://$SERVICE_DNS_HOSTNAME:${PLUGIN_DATASTORE_PORTS[0]}" 199 | } 200 | -------------------------------------------------------------------------------- /help-functions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 6 | export SUBCOMMAND_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/subcommands" 7 | 8 | fn-help() { 9 | declare CMD="$1" 10 | local cmd EXIT_CODE 11 | 12 | if [[ "$CMD" == "help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]]; then 13 | fn-help-all "$@" 14 | exit 0 15 | fi 16 | 17 | pushd "$SUBCOMMAND_ROOT" >/dev/null 2>&1 18 | for cmd in *; do 19 | if [[ "$CMD" == "${PLUGIN_COMMAND_PREFIX}:$cmd" ]]; then 20 | "$SUBCOMMAND_ROOT/$cmd" "$@" 21 | EXIT_CODE="$?" 22 | exit "$EXIT_CODE" 23 | fi 24 | done 25 | popd >/dev/null 2>&1 26 | 27 | exit "$DOKKU_NOT_IMPLEMENTED_EXIT" 28 | } 29 | 30 | fn-help-all() { 31 | declare CMD="$1" SUBCOMMAND="$2" 32 | local CMD_OUTPUT BLUE BOLD FULL_OUTPUT NORMAL 33 | FULL_OUTPUT=true 34 | 35 | if [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:help" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX" ]] || [[ "$CMD" == "$PLUGIN_COMMAND_PREFIX:default" ]]; then 36 | BOLD="$(fn-help-fancy-tput bold)" 37 | NORMAL="$(fn-help-fancy-color "\033[m")" 38 | BLUE="$(fn-help-fancy-color "\033[0;34m")" 39 | CYAN="$(fn-help-fancy-color "\033[1;36m")" 40 | if [[ -n "$SUBCOMMAND" ]] && [[ "$SUBCOMMAND" != "--all" ]]; then 41 | fn-help-contents-subcommand "$SUBCOMMAND" "$FULL_OUTPUT" 42 | return "$?" 43 | fi 44 | 45 | echo -e "${BOLD}usage${NORMAL}: dokku ${PLUGIN_COMMAND_PREFIX}[:COMMAND]" 46 | echo '' 47 | echo -e "${BOLD}List your $PLUGIN_COMMAND_PREFIX services.${NORMAL}" 48 | echo '' 49 | echo -e "${BLUE}Example:${NORMAL}" 50 | echo '' 51 | echo " \$ dokku $PLUGIN_COMMAND_PREFIX:list" 52 | echo '' 53 | fn-help-list-example | column -c5 -t -s, 54 | echo '' 55 | echo -e "dokku ${BOLD}${PLUGIN_COMMAND_PREFIX}${NORMAL} commands: (get help with ${CYAN}dokku ${PLUGIN_COMMAND_PREFIX}:help SUBCOMMAND${NORMAL})" 56 | echo '' 57 | fn-help-contents | sort | column -c2 -t -s, 58 | echo '' 59 | elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then 60 | fn-help-contents 61 | else 62 | cat </dev/null 2>&1 72 | for cmd in *; do 73 | fn-help-contents-subcommand "$cmd" || true 74 | done 75 | } 76 | 77 | fn-help-contents-subcommand() { 78 | declare SUBCOMMAND="$1" FULL_OUTPUT="$2" 79 | local HELP_TMPDIR=$(mktemp -d --tmpdir) 80 | local UNCLEAN_FILE="${HELP_TMPDIR}/cmd-unclean" CLEAN_FILE="${HELP_TMPDIR}/cmd-clean" 81 | local BOLD CMD_OUTPUT CYAN EXAMPLE LIGHT_GRAY NORMAL 82 | trap 'rm -rf "$HELP_TMPDIR" > /dev/null' RETURN INT TERM EXIT 83 | 84 | rm -rf "$UNCLEAN_FILE" "$CLEAN_FILE" 85 | cat "$SUBCOMMAND_ROOT/$SUBCOMMAND" >"$UNCLEAN_FILE" 86 | 87 | fn-help-subcommand-sanitize "$UNCLEAN_FILE" "$CLEAN_FILE" 88 | if ! is_implemented_command "$SUBCOMMAND"; then 89 | return 1 90 | fi 91 | 92 | args="$(fn-help-subcommand-args "$CLEAN_FILE" "$FULL_OUTPUT")" 93 | SUBCOMMAND=":$SUBCOMMAND" 94 | [[ "$SUBCOMMAND" == ":default" ]] && SUBCOMMAND="" 95 | cmd_line="$(echo -e "${SUBCOMMAND} ${args}" | sed -e 's/[[:space:]]*$//')" 96 | desc="$(grep desc "$CLEAN_FILE" | head -1)" 97 | eval "$desc" 98 | 99 | BLUE="$(fn-help-fancy-color "\033[0;34m")" 100 | BOLD="$(fn-help-fancy-tput bold)" 101 | CYAN="$(fn-help-fancy-color "\033[1;36m")" 102 | NORMAL="$(fn-help-fancy-color "\033[m")" 103 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 104 | LIGHT_RED="$(fn-help-fancy-color "\033[1;31m")" 105 | CMD_OUTPUT="$(echo -e " ${PLUGIN_COMMAND_PREFIX}${cmd_line}, ${LIGHT_GRAY}${desc}${NORMAL}")" 106 | if [[ "$FULL_OUTPUT" != "true" ]]; then 107 | echo "$CMD_OUTPUT" 108 | return 0 109 | fi 110 | 111 | echo -e "${BOLD}usage:${NORMAL} dokku ${PLUGIN_COMMAND_PREFIX}${cmd_line}" 112 | echo '' 113 | echo -e "${BOLD}${desc}${NORMAL}" 114 | echo '' 115 | 116 | ARGS="$(fn-help-subcommand-list-args "$CLEAN_FILE")" 117 | if [[ -n "$ARGS" ]]; then 118 | echo -e "${CYAN}arguments:${NORMAL}" 119 | echo '' 120 | echo "$ARGS" | column -c2 -t -s, 121 | echo '' 122 | fi 123 | 124 | FLAGS="$(fn-help-subcommand-list-flags "$CLEAN_FILE")" 125 | if [[ -n "$FLAGS" ]]; then 126 | echo -e "${BLUE}flags:${NORMAL}" 127 | echo '' 128 | echo "$FLAGS" | column -c2 -t -s, 129 | echo '' 130 | fi 131 | 132 | EXAMPLE="$(fn-help-subcommand-example "$CLEAN_FILE")" 133 | if [[ -n "$EXAMPLE" ]]; then 134 | echo -e "${LIGHT_RED}examples:${NORMAL}" 135 | echo '' 136 | echo "$EXAMPLE" 137 | echo '' 138 | fi 139 | 140 | return 0 141 | } 142 | 143 | fn-help-fancy-tput() { 144 | declare desc="a wrapper around tput" 145 | 146 | if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" == "unknown" ]] || [[ "$TERM" == "dumb" ]]; then 147 | return 148 | fi 149 | 150 | tput "$@" 151 | } 152 | 153 | fn-help-fancy-color() { 154 | declare desc="a wrapper around colors" 155 | 156 | if [[ -n "$DOKKU_NO_COLOR" ]] || [[ "$TERM" == "unknown" ]] || [[ "$TERM" == "dumb" ]]; then 157 | return 158 | fi 159 | 160 | echo "$@" 161 | } 162 | 163 | fn-help-list-example() { 164 | # shellcheck disable=SC2034 165 | declare desc="return $PLUGIN_COMMAND_PREFIX plugin help content" 166 | cat <* ]] && line="\n ${BOLD}${line}${NORMAL}" 243 | # shellcheck disable=SC2001 244 | [[ "$line" == " "* ]] && line=" ${OTHER_GRAY}$(echo "$line" | sed -e 's/^[[:space:]]*//')${NORMAL}" 245 | echo -e "${NEWLINE}${line}" 246 | LAST_LINE="sentence" 247 | NEWLINE="\n" 248 | fi 249 | done 250 | } 251 | 252 | fn-help-subcommand-list-args() { 253 | declare FUNC_FILE="$1" 254 | local EXAMPLE LIGHT_GRAY NORMAL 255 | 256 | FLAGS=$(grep "#A" "$FUNC_FILE" | cut -d'A' -f2- | sed -e 's/^[[:space:]]*//' || true) 257 | if [[ -z "$FLAGS" ]]; then 258 | return 0 259 | fi 260 | 261 | NORMAL="$(fn-help-fancy-color "\033[m")" 262 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 263 | 264 | _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do 265 | echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" 266 | done 267 | } 268 | 269 | fn-help-subcommand-list-flags() { 270 | declare FUNC_FILE="$1" 271 | local EXAMPLE LIGHT_GRAY NORMAL 272 | 273 | FLAGS=$(grep "#F" "$FUNC_FILE" | cut -d'F' -f2- | sed -e 's/^[[:space:]]*//' || true) 274 | if [[ -z "$FLAGS" ]]; then 275 | return 0 276 | fi 277 | 278 | NORMAL="$(fn-help-fancy-color "\033[m")" 279 | LIGHT_GRAY="$(fn-help-fancy-color "\033[2;37m")" 280 | 281 | _fn-help-apply-shell-expansion "$FLAGS" | while read -r line; do 282 | echo -e "$(echo "$line" | cut -d',' -f1),${LIGHT_GRAY}$(echo "$line" | cut -d',' -f2-)${NORMAL}" 283 | done 284 | } 285 | 286 | fn-help-subcommand-sanitize() { 287 | declare FUNC_FILE="$1" OUTGOING_FUNC_FILE="$2" 288 | local FUNCTION_FOUND=false 289 | local IFS OIFS 290 | 291 | touch "$OUTGOING_FUNC_FILE" 292 | 293 | OIFS="$IFS" 294 | IFS=, 295 | while read -r p; do 296 | IFS="$OIFS" 297 | if [[ "$p" == *"-cmd \"\$@\""* ]] || [[ "$p" == "" ]]; then 298 | continue 299 | fi 300 | 301 | if [[ "$FUNCTION_FOUND" == true ]]; then 302 | echo "$p" >>"$OUTGOING_FUNC_FILE" 303 | continue 304 | fi 305 | 306 | if [[ "$p" == *"()"* ]]; then 307 | FUNCTION_FOUND=true 308 | echo "$p" >>"$OUTGOING_FUNC_FILE" 309 | continue 310 | fi 311 | done <"$FUNC_FILE" 312 | } 313 | 314 | _fn-help-apply-shell-expansion() { 315 | declare desc="expand environment variables for a shell command" 316 | declare data="$1" 317 | declare delimiter="__apply_shell_expansion_delimiter__" 318 | declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter" 319 | eval "$command" 320 | } 321 | -------------------------------------------------------------------------------- /install: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | plugin-install() { 9 | pull-docker-image() { 10 | declare IMAGE="$1" 11 | if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then 12 | echo " ! ${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2 13 | echo " ! docker image pull ${IMAGE}" 1>&2 14 | return 15 | fi 16 | if [[ "$("$DOCKER_BIN" image ls -q "${IMAGE}" 2>/dev/null)" == "" ]]; then 17 | "$DOCKER_BIN" image pull "${IMAGE}" 18 | fi 19 | } 20 | 21 | fn-plugin-property-setup "$PLUGIN_COMMAND_PREFIX" 22 | pull-docker-image "${PLUGIN_IMAGE}:${PLUGIN_IMAGE_VERSION}" 23 | pull-docker-image "$PLUGIN_BUSYBOX_IMAGE" 24 | pull-docker-image "$PLUGIN_AMBASSADOR_IMAGE" 25 | pull-docker-image "$PLUGIN_S3BACKUP_IMAGE" 26 | pull-docker-image "$PLUGIN_WAIT_IMAGE" 27 | 28 | mkdir -p "$PLUGIN_DATA_ROOT" || echo "Failed to create $PLUGIN_SERVICE data directory" 29 | chown "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "$PLUGIN_DATA_ROOT" 30 | 31 | mkdir -p "$PLUGIN_CONFIG_ROOT" || echo "Failed to create $PLUGIN_SERVICE config directory" 32 | chown "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "$PLUGIN_CONFIG_ROOT" 33 | 34 | rm -f "/etc/sudoers.d/dokku-${PLUGIN_COMMAND_PREFIX}*" 35 | _SUDOERS_FILE="/etc/sudoers.d/dokku-${PLUGIN_COMMAND_PREFIX}" 36 | 37 | touch "$_SUDOERS_FILE" 38 | cat >"$_SUDOERS_FILE" <"$SERVICE_ROOT/IMAGE" 56 | echo "${image##*:}" >"$SERVICE_ROOT/IMAGE_VERSION" 57 | fi 58 | fi 59 | 60 | chown "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "$SERVICE_ROOT/IMAGE" "$SERVICE_ROOT/IMAGE_VERSION" 61 | 62 | if [[ -f "$SERVICE_ROOT/${PLUGIN_VARIABLE}_CONFIG_OPTIONS" ]]; then 63 | mv "$SERVICE_ROOT/${PLUGIN_VARIABLE}_CONFIG_OPTIONS" "$SERVICE_ROOT/CONFIG_OPTIONS" 64 | chown "${DOKKU_SYSTEM_USER}:${DOKKU_SYSTEM_GROUP}" "$SERVICE_ROOT/CONFIG_OPTIONS" 65 | fi 66 | done 67 | } 68 | 69 | plugin-install "$@" 70 | -------------------------------------------------------------------------------- /plugin.toml: -------------------------------------------------------------------------------- 1 | [plugin] 2 | description = "dokku memcached service plugin" 3 | version = "1.36.8" 4 | [plugin.config] 5 | -------------------------------------------------------------------------------- /post-app-clone-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | plugin-post-app-clone-setup() { 9 | declare OLD_APP_NAME="$1" NEW_APP_NAME="$2" 10 | 11 | for SERVICE in $(fn-services-list false); do 12 | if in_links_file "$SERVICE" "$OLD_APP_NAME"; then 13 | add_to_links_file "$SERVICE" "$NEW_APP_NAME" 14 | fi 15 | done 16 | } 17 | 18 | plugin-post-app-clone-setup "$@" 19 | -------------------------------------------------------------------------------- /post-app-rename-setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | plugin-post-app-rename-setup() { 9 | declare OLD_APP_NAME="$1" NEW_APP_NAME="$2" 10 | 11 | for SERVICE in $(fn-services-list false); do 12 | if in_links_file "$SERVICE" "$OLD_APP_NAME"; then 13 | add_to_links_file "$SERVICE" "$NEW_APP_NAME" 14 | fi 15 | done 16 | } 17 | 18 | plugin-post-app-rename-setup "$@" 19 | -------------------------------------------------------------------------------- /pre-delete: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | APP="$1" 9 | for SERVICE in $(fn-services-list false); do 10 | [[ -n "$SERVICE" ]] || continue 11 | dokku_log_verbose_quiet "Unlinking from $SERVICE" 12 | remove_from_links_file "$(basename "$SERVICE")" "$APP" 13 | done 14 | -------------------------------------------------------------------------------- /pre-restore: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | plugin-pre-restore() { 9 | declare SCHEDULER="$1" APP="$2" 10 | local status 11 | 12 | if [[ "$SCHEDULER" != "docker-local" ]]; then 13 | return 14 | fi 15 | 16 | for SERVICE in $(fn-services-list false); do 17 | if ! in_links_file "$SERVICE" "$APP"; then 18 | continue 19 | fi 20 | 21 | status="$(service_status "$SERVICE")" 22 | if [[ "$status" == "running" ]]; then 23 | continue 24 | fi 25 | 26 | if [[ "$status" == "restarting" ]]; then 27 | dokku_log_warn "$PLUGIN_SERVICE service $SERVICE is restarting and may cause issues with linked app $APP" 28 | continue 29 | fi 30 | 31 | dokku_log_warn "$PLUGIN_SERVICE service $SERVICE is not running, issuing service start" 32 | service_start "$SERVICE" 33 | done 34 | } 35 | 36 | plugin-pre-restore "$@" 37 | -------------------------------------------------------------------------------- /pre-start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/functions" 5 | set -eo pipefail 6 | [[ $DOKKU_TRACE ]] && set -x 7 | 8 | plugin-pre-start() { 9 | declare APP="$1" 10 | local status 11 | 12 | for SERVICE in $(fn-services-list false); do 13 | if ! in_links_file "$SERVICE" "$APP"; then 14 | continue 15 | fi 16 | 17 | status="$(service_status "$SERVICE")" 18 | if [[ "$status" == "running" ]]; then 19 | continue 20 | fi 21 | 22 | if [[ "$status" == "restarting" ]]; then 23 | dokku_log_warn "$PLUGIN_SERVICE service $SERVICE is restarting and may cause issues with linked app $APP" 24 | continue 25 | fi 26 | 27 | dokku_log_warn "$PLUGIN_SERVICE service $SERVICE is not running, issuing service start" 28 | service_start "$SERVICE" 29 | done 30 | } 31 | 32 | plugin-pre-start "$@" 33 | -------------------------------------------------------------------------------- /service-list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/config" 3 | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common-functions" 4 | set -eo pipefail 5 | [[ $DOKKU_TRACE ]] && set -x 6 | 7 | plugin-service-list() { 8 | declare desc="allows listing all services for use by other dokku plugins" 9 | declare SERVICE_TYPE="$1" 10 | 11 | if [[ -n "$SERVICE_TYPE" ]] && [[ "$SERVICE_TYPE" != "$PLUGIN_COMMAND_PREFIX" ]]; then 12 | return 13 | fi 14 | 15 | for service in $(fn-services-list false); do 16 | echo "$PLUGIN_COMMAND_PREFIX:$service" 17 | done 18 | } 19 | 20 | plugin-service-list "$@" 21 | -------------------------------------------------------------------------------- /subcommands/app-links: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-app-links-cmd() { 9 | #E list all $PLUGIN_COMMAND_PREFIX services that are linked to the 'playground' app. 10 | #E dokku $PLUGIN_COMMAND_PREFIX:app-links playground 11 | #A app, app to run command against 12 | declare desc="list all $PLUGIN_SERVICE service links for a given app" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:app-links" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare APP="$1" 16 | APP=${APP:="$DOKKU_APP_NAME"} 17 | 18 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 19 | verify_app_name "$APP" 20 | service_app_links "$APP" 21 | } 22 | 23 | service-app-links-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/backup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-cmd() { 9 | #E backup the 'lollipop' service to the 'my-s3-bucket' bucket on AWS 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup lollipop my-s3-bucket --use-iam 11 | #E restore a backup file (assuming it was extracted via 'tar -xf backup.tgz') 12 | #E dokku $PLUGIN_COMMAND_PREFIX:import lollipop < backup-folder/export 13 | #F -u|--use-iam, use the IAM profile associated with the current server 14 | #A service, service to run command against 15 | #A bucket-name, name of the s3 bucket to upload backups to 16 | declare desc="create a backup of the $PLUGIN_SERVICE service to an existing s3 bucket" 17 | local cmd="$PLUGIN_COMMAND_PREFIX:backup" argv=("$@") 18 | [[ ${argv[0]} == "$cmd" ]] && shift 1 19 | declare SERVICE="$1" BUCKET_NAME="$2" USE_IAM_OPTIONAL_FLAG="$3" 20 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 21 | 22 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 23 | [[ -z "$BUCKET_NAME" ]] && dokku_log_fail "Please specify an aws bucket for the backup" 24 | verify_service_name "$SERVICE" 25 | service_backup "$SERVICE" "$BUCKET_NAME" "$USE_IAM_OPTIONAL_FLAG" 26 | } 27 | 28 | service-backup-cmd "$@" 29 | -------------------------------------------------------------------------------- /subcommands/backup-auth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-auth-cmd() { 9 | #E setup s3 backup authentication 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-auth lollipop AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY 11 | #E setup s3 backup authentication with different region 12 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-auth lollipop AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_REGION 13 | #E setup s3 backup authentication with different signature version and endpoint 14 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-auth lollipop AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_REGION AWS_SIGNATURE_VERSION ENDPOINT_URL 15 | #E more specific example for minio auth 16 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-auth lollipop MINIO_ACCESS_KEY_ID MINIO_SECRET_ACCESS_KEY us-east-1 s3v4 https://YOURMINIOSERVICE 17 | #A service, service to run command against 18 | #A access-key-id, an amazon AWS_ACCESS_KEY_ID 19 | #A aws-secret-access-key, an amazon AWS_SECRET_ACCESS_KEY 20 | #A aws-default-region, (optional) a valid amazon S3 region 21 | #A aws-signature-version, (optional) the AWS signature version to use when signing S3 requests 22 | #A endpoint-url, (optional) an aws endpoint to upload to 23 | declare desc="set up authentication for backups on the $PLUGIN_SERVICE service" 24 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-auth" argv=("$@") 25 | [[ ${argv[0]} == "$cmd" ]] && shift 1 26 | declare SERVICE="$1" AWS_ACCESS_KEY_ID="$2" AWS_SECRET_ACCESS_KEY="$3" AWS_DEFAULT_REGION="$4" AWS_SIGNATURE_VERSION="$5" ENDPOINT_URL="$6" 27 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 28 | 29 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 30 | [[ -z "$AWS_ACCESS_KEY_ID" ]] && dokku_log_fail "Please specify an aws access key id" 31 | [[ -z "$AWS_SECRET_ACCESS_KEY" ]] && dokku_log_fail "Please specify an aws secret access key" 32 | verify_service_name "$SERVICE" 33 | service_backup_auth "$SERVICE" "$AWS_ACCESS_KEY_ID" "$AWS_SECRET_ACCESS_KEY" "$AWS_DEFAULT_REGION" "$AWS_SIGNATURE_VERSION" "$ENDPOINT_URL" 34 | } 35 | 36 | service-backup-auth-cmd "$@" 37 | -------------------------------------------------------------------------------- /subcommands/backup-deauth: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-deauth-cmd() { 9 | #E remove s3 authentication 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-deauth lollipop 11 | #A service, service to run command against 12 | declare desc="remove backup authentication for the $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-deauth" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_backup_deauth "$SERVICE" 21 | } 22 | 23 | service-backup-deauth-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/backup-schedule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-schedule-cmd() { 9 | #E schedule a backup 10 | #E > 'schedule' is a crontab expression, eg. "0 3 * * *" for each day at 3am 11 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-schedule lollipop "0 3 * * *" my-s3-bucket 12 | #E schedule a backup and authenticate via iam 13 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-schedule lollipop "0 3 * * *" my-s3-bucket --use-iam 14 | #F -u|--use-iam, use the IAM profile associated with the current server 15 | #A service, service to run command against 16 | #A schedule, a cron schedule to run backups on 17 | #A bucket-name, name of the s3 bucket to upload backups to 18 | declare desc="schedule a backup of the $PLUGIN_SERVICE service" 19 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-schedule" argv=("$@") 20 | [[ ${argv[0]} == "$cmd" ]] && shift 1 21 | declare SERVICE="$1" SCHEDULE="$2" BUCKET_NAME="$3" USE_IAM_OPTIONAL_FLAG="$4" 22 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 23 | 24 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 25 | [[ -z "$SCHEDULE" ]] && dokku_log_fail "Please specify a schedule for the backup" 26 | [[ -z "$BUCKET_NAME" ]] && dokku_log_fail "Please specify an aws bucket for the backup" 27 | verify_service_name "$SERVICE" 28 | service_backup_schedule "$SERVICE" "$SCHEDULE" "$BUCKET_NAME" "$USE_IAM_OPTIONAL_FLAG" 29 | } 30 | 31 | service-backup-schedule-cmd "$@" 32 | -------------------------------------------------------------------------------- /subcommands/backup-schedule-cat: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-schedule-cat-cmd() { 9 | #E cat the contents of the configured backup cronfile for the service 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-schedule-cat lollipop 11 | #A service, service to run command against 12 | declare desc="cat the contents of the configured backup cronfile for the service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-schedule-cat" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_backup_schedule_cat "$SERVICE" 20 | } 21 | 22 | service-backup-schedule-cat-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/backup-set-encryption: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-set-encryption-cmd() { 9 | #E set the GPG-compatible passphrase for encrypting backups for backups 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-set-encryption lollipop 11 | #A service, service to run command against 12 | #A passphrase, a GPG-compatible passphrase 13 | declare desc="set encryption for all future backups of $PLUGIN_SERVICE service" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-set-encryption" argv=("$@") 15 | [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" PASSPHRASE="$2" 17 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 18 | 19 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 20 | [[ -z "$PASSPHRASE" ]] && dokku_log_fail "Please specify a GPG backup passphrase" 21 | verify_service_name "$SERVICE" 22 | service_backup_set_encryption "$SERVICE" "$PASSPHRASE" 23 | } 24 | 25 | service-backup-set-encryption-cmd "$@" 26 | -------------------------------------------------------------------------------- /subcommands/backup-set-public-key-encryption: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-set-public-key-encryption-cmd() { 9 | #E set the GPG Public Key for encrypting backups 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-set-public-key-encryption lollipop 11 | #A service, service to run command against 12 | #A public-key-id, a GPG Public Key ID (or fingerprint) to use for encryption. Must be uploaded to the GPG keyserver beforehand. 13 | declare desc="set GPG Public Key encryption for all future backups of $PLUGIN_SERVICE service" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-set-public-key-encryption" argv=("$@") 15 | [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" PUBLIC_KEY_ID="$2" 17 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 18 | 19 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 20 | [[ -z "$PUBLIC_KEY_ID" ]] && dokku_log_fail "Please specify a valid GPG Public Key ID (or fingerprint)" 21 | verify_service_name "$SERVICE" 22 | service_backup_set_public_key_encryption "$SERVICE" "$PUBLIC_KEY_ID" 23 | } 24 | 25 | service-backup-set-public-key-encryption-cmd "$@" 26 | -------------------------------------------------------------------------------- /subcommands/backup-unschedule: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-unschedule-cmd() { 9 | #E remove the scheduled backup from cron 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-unschedule lollipop 11 | #A service, service to run command against 12 | declare desc="unschedule the backup of the $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-unschedule" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_backup_unschedule "$SERVICE" 21 | } 22 | 23 | service-backup-unschedule-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/backup-unset-encryption: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-unset-encryption-cmd() { 9 | #E unset the GPG encryption passphrase for backups 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-unset-encryption lollipop 11 | #A service, service to run command against 12 | declare desc="unset encryption for future backups of the $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-unset-encryption" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_backup_unset_encryption "$SERVICE" 21 | } 22 | 23 | service-backup-unset-encryption-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/backup-unset-public-key-encryption: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-backup-unset-public-key-encryption-cmd() { 9 | #E unset the GPG Public Key encryption for backups 10 | #E dokku $PLUGIN_COMMAND_PREFIX:backup-unset-public-key-encryption lollipop 11 | #A service, service to run command against 12 | declare desc="unset GPG Public Key encryption for future backups of the $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:backup-unset-public-key-encryption" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" # TODO: [22.03.2024 by Mykola] 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_backup_unset_public_key_encryption "$SERVICE" # TODO: [22.03.2024 by Mykola] 21 | } 22 | 23 | service-backup-unset-encryption-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/clone: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-clone-cmd() { 9 | #E you can clone an existing service to a new one 10 | #E dokku $PLUGIN_COMMAND_PREFIX:clone lollipop lollipop-2 11 | #A service, service to run command against 12 | #A new-service, name of new service 13 | #F -c|--config-options "--args --go=here", extra arguments to pass to the container create command 14 | #F -C|--custom-env "USER=alpha;HOST=beta", semi-colon delimited environment variables to start the service with 15 | #F -i|--image IMAGE, the image name to start the service with 16 | #F -I|--image-version IMAGE_VERSION, the image version to start the service with 17 | #F -m|--memory MEMORY, container memory limit in megabytes (default: unlimited) 18 | #F -N|--initial-network INITIAL_NETWORK, the initial network to attach the service to 19 | #F -p|--password PASSWORD, override the user-level service password 20 | #F -P|--post-create-network NETWORKS, a comma-separated list of networks to attach the service container to after service creation 21 | #F -r|--root-password PASSWORD, override the root-level service password 22 | #F -S|--post-start-network NETWORKS, a comma-separated list of networks to attach the service container to after service start 23 | #F -s|--shm-size SHM_SIZE, override shared memory size for $PLUGIN_COMMAND_PREFIX docker container 24 | declare desc="create container then copy data from into " 25 | local cmd="$PLUGIN_COMMAND_PREFIX:clone" argv=("$@") 26 | [[ ${argv[0]} == "$cmd" ]] && shift 1 27 | declare SERVICE="$1" NEW_SERVICE="$2" CLONE_FLAGS_LIST=("${@:3}") 28 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 29 | 30 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 31 | [[ -z "$NEW_SERVICE" ]] && dokku_log_fail "Please specify a name for the new service" 32 | verify_service_name "$SERVICE" 33 | if service_exists "$NEW_SERVICE"; then 34 | dokku_log_fail "Invalid service name $NEW_SERVICE. Verify the service name is not already in use." 35 | fi 36 | 37 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 38 | local ID="$(cat "$SERVICE_ROOT/ID")" 39 | is_container_status "$ID" "Running" || dokku_log_fail "Service ${SERVICE} container is not running" 40 | 41 | PLUGIN_IMAGE=$(service_version "$SERVICE" | grep -o "^.*:" | sed -r "s/://g") 42 | PLUGIN_IMAGE_VERSION=$(service_version "$SERVICE" | grep -o ":.*$" | sed -r "s/://g") 43 | 44 | service_parse_args "${@:3}" 45 | 46 | dokku_log_info2 "Cloning $SERVICE to $NEW_SERVICE @ $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" 47 | service_create "$NEW_SERVICE" "${@:3}" 48 | dokku_log_info1 "Copying data from $SERVICE to $NEW_SERVICE" 49 | service_export "$SERVICE" | service_import "$NEW_SERVICE" >/dev/null 2>&1 || true 50 | dokku_log_info2 "Done" 51 | } 52 | 53 | service-clone-cmd "$@" 54 | -------------------------------------------------------------------------------- /subcommands/connect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-connect-cmd() { 9 | #E connect to the service via the $PLUGIN_COMMAND_PREFIX connection tool 10 | #E > NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098 11 | #E dokku $PLUGIN_COMMAND_PREFIX:connect lollipop 12 | #A service, service to run command against 13 | declare desc="connect to the service via the $PLUGIN_COMMAND_PREFIX connection tool" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:connect" argv=("$@") 15 | [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" 17 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 18 | 19 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 20 | verify_service_name "$SERVICE" 21 | service_connect "$SERVICE" 22 | } 23 | 24 | service-connect-cmd "$@" 25 | -------------------------------------------------------------------------------- /subcommands/create: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-create-cmd() { 9 | #E create a $PLUGIN_COMMAND_PREFIX service named lollipop 10 | #E dokku $PLUGIN_COMMAND_PREFIX:create lollipop 11 | #E you can also specify the image and image version to use for the service. 12 | #E it *must* be compatible with the ${PLUGIN_IMAGE} image. 13 | #E export ${PLUGIN_VARIABLE}_IMAGE="${PLUGIN_IMAGE}" 14 | #E export ${PLUGIN_VARIABLE}_IMAGE_VERSION="${PLUGIN_IMAGE_VERSION}" 15 | #E dokku $PLUGIN_COMMAND_PREFIX:create lollipop 16 | #E you can also specify custom environment variables to start 17 | #E the ${PLUGIN_COMMAND_PREFIX} service in semicolon-separated form. 18 | #E export ${PLUGIN_VARIABLE}_CUSTOM_ENV="USER=alpha;HOST=beta" 19 | #E dokku $PLUGIN_COMMAND_PREFIX:create lollipop 20 | #A service, service to run command against 21 | #F -c|--config-options "--args --go=here", extra arguments to pass to the container create command 22 | #F -C|--custom-env "USER=alpha;HOST=beta", semi-colon delimited environment variables to start the service with 23 | #F -i|--image IMAGE, the image name to start the service with 24 | #F -I|--image-version IMAGE_VERSION, the image version to start the service with 25 | #F -m|--memory MEMORY, container memory limit in megabytes (default: unlimited) 26 | #F -N|--initial-network INITIAL_NETWORK, the initial network to attach the service to 27 | #F -p|--password PASSWORD, override the user-level service password 28 | #F -P|--post-create-network NETWORKS, a comma-separated list of networks to attach the service container to after service creation 29 | #F -r|--root-password PASSWORD, override the root-level service password 30 | #F -S|--post-start-network NETWORKS, a comma-separated list of networks to attach the service container to after service start 31 | #F -s|--shm-size SHM_SIZE, override shared memory size for $PLUGIN_COMMAND_PREFIX docker container 32 | declare desc="create a $PLUGIN_SERVICE service" 33 | local cmd="$PLUGIN_COMMAND_PREFIX:create" argv=("$@") 34 | [[ ${argv[0]} == "$cmd" ]] && shift 1 35 | declare SERVICE="$1" CREATE_FLAGS_LIST=("${@:2}") 36 | 37 | service_create "$SERVICE" "${@:2}" 38 | } 39 | 40 | service-create-cmd "$@" 41 | -------------------------------------------------------------------------------- /subcommands/destroy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-destroy-cmd() { 9 | #E destroy the service, it's data, and the running container 10 | #E dokku $PLUGIN_COMMAND_PREFIX:destroy lollipop 11 | #A service, service to run command against 12 | #F -f|--force, force destroy without asking for confirmation 13 | declare desc="delete the $PLUGIN_SERVICE service/data/container if there are no links left" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:destroy" argv=("$@") 15 | [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" FORCE_FLAG="$2" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 21 | LINKS_FILE="$SERVICE_ROOT/LINKS" 22 | SERVICE_HOST_ROOT="$PLUGIN_DATA_HOST_ROOT/$SERVICE" 23 | SERVICE_NAME="$(get_service_name "$SERVICE")" 24 | 25 | [[ -s "$LINKS_FILE" ]] && dokku_log_fail "Cannot delete linked service" 26 | 27 | if [[ "$FORCE_FLAG" == "force" ]] || [[ "$FORCE_FLAG" == "-f" ]] || [[ "$FORCE_FLAG" == "--force" ]]; then 28 | DOKKU_APPS_FORCE_DELETE=1 29 | fi 30 | if [[ -z "$DOKKU_APPS_FORCE_DELETE" ]]; then 31 | dokku_log_warn "WARNING: Potentially Destructive Action" 32 | dokku_log_warn "This command will destroy $SERVICE $PLUGIN_SERVICE service." 33 | dokku_log_warn "To proceed, type \"$SERVICE\"" 34 | echo "" 35 | 36 | read -rp "> " service_name 37 | if [[ "$service_name" != "$SERVICE" ]]; then 38 | dokku_log_warn "Confirmation did not match $SERVICE. Aborted." 39 | exit 1 40 | fi 41 | fi 42 | 43 | dokku_log_info2_quiet "Deleting $SERVICE" 44 | plugn trigger service-action pre-delete "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 45 | service_backup_unschedule "$SERVICE" 46 | service_container_rm "$SERVICE" 47 | 48 | dokku_log_verbose_quiet "Removing data" 49 | "$DOCKER_BIN" container run --rm -v "$SERVICE_HOST_ROOT/data:/data" -v "$SERVICE_HOST_ROOT/$PLUGIN_CONFIG_SUFFIX:/config" "$PLUGIN_BUSYBOX_IMAGE" chmod 777 -R /config /data 50 | rm -rf "$SERVICE_ROOT" 51 | 52 | fn-plugin-property-destroy "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 53 | 54 | plugn trigger service-action post-delete "$PLUGIN_COMMAND_PREFIX" "$SERVICE" 55 | dokku_log_info2 "$PLUGIN_SERVICE container deleted: $SERVICE" 56 | } 57 | 58 | service-destroy-cmd "$@" 59 | -------------------------------------------------------------------------------- /subcommands/enter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-enter-cmd() { 9 | #E a bash prompt can be opened against a running service. 10 | #E filesystem changes will not be saved to disk. 11 | #E > NOTE: disconnecting from ssh while running this command may leave zombie processes due to moby/moby#9098 12 | #E dokku $PLUGIN_COMMAND_PREFIX:enter lollipop 13 | #E you may also run a command directly against the service. 14 | #E filesystem changes will not be saved to disk. 15 | #E dokku $PLUGIN_COMMAND_PREFIX:enter lollipop touch /tmp/test 16 | #A service, service to run command against 17 | declare desc="enter or run a command in a running $PLUGIN_SERVICE service container" 18 | local cmd="$PLUGIN_COMMAND_PREFIX:enter" argv=("$@") 19 | [[ ${argv[0]} == "$cmd" ]] && shift 1 20 | declare SERVICE="$1" 21 | 22 | verify_service_name "$SERVICE" 23 | dokku_log_info1_quiet "Filesystem changes may not persist after container restarts" 24 | service_enter "$SERVICE" "${@:2}" 25 | } 26 | 27 | service-enter-cmd "$@" 28 | -------------------------------------------------------------------------------- /subcommands/exists: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-exists-cmd() { 9 | #E here we check if the lollipop $PLUGIN_COMMAND_PREFIX service exists. 10 | #E dokku $PLUGIN_COMMAND_PREFIX:exists lollipop 11 | #A service, service to run command against 12 | declare desc="check if the $PLUGIN_SERVICE service exists" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:exists" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | dokku_log_info1 "Service $SERVICE exists" 20 | } 21 | 22 | service-exists-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/export: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-export-cmd() { 9 | #E by default, datastore output is exported to stdout 10 | #E dokku $PLUGIN_COMMAND_PREFIX:export lollipop 11 | #E you can redirect this output to a file 12 | #E dokku $PLUGIN_COMMAND_PREFIX:export lollipop > data.dump 13 | #A service, service to run command against 14 | declare desc="export a dump of the $PLUGIN_SERVICE service database" 15 | local cmd="$PLUGIN_COMMAND_PREFIX:export" argv=("$@") 16 | [[ ${argv[0]} == "$cmd" ]] && shift 1 17 | declare SERVICE="$1" 18 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 19 | 20 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 21 | verify_service_name "$SERVICE" 22 | service_export "$SERVICE" 23 | } 24 | 25 | service-export-cmd "$@" 26 | -------------------------------------------------------------------------------- /subcommands/expose: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-expose-cmd() { 9 | #E expose the service on the service's normal ports, allowing access to it from the public interface (0.0.0.0) 10 | #E dokku $PLUGIN_COMMAND_PREFIX:expose lollipop ${PLUGIN_DATASTORE_PORTS[@]} 11 | #E expose the service on the service's normal ports, with the first on a specified ip address (127.0.0.1) 12 | #E dokku $PLUGIN_COMMAND_PREFIX:expose lollipop 127.0.0.1:${PLUGIN_DATASTORE_PORTS[@]} 13 | #A service, service to run command against 14 | #A ports, a list of ports to run against 15 | declare desc="expose a $PLUGIN_SERVICE service on custom host:port if provided (random port on the 0.0.0.0 interface if otherwise unspecified)" 16 | local cmd="$PLUGIN_COMMAND_PREFIX:expose" argv=("$@") 17 | [[ ${argv[0]} == "$cmd" ]] && shift 1 18 | declare SERVICE="$1" PORTS_LIST=("${@:2}") 19 | 20 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 21 | verify_service_name "$SERVICE" 22 | service_port_expose "$SERVICE" "${@:2}" 23 | } 24 | 25 | service-expose-cmd "$@" 26 | -------------------------------------------------------------------------------- /subcommands/import: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-import-cmd() { 9 | #E import a datastore dump 10 | #E dokku $PLUGIN_COMMAND_PREFIX:import lollipop < data.dump 11 | #A service, service to run command against 12 | declare desc="import a dump into the $PLUGIN_SERVICE service database" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:import" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | is_implemented_command "$cmd" || dokku_log_fail "Not yet implemented" 17 | 18 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 19 | verify_service_name "$SERVICE" 20 | service_import "$SERVICE" 21 | } 22 | 23 | service-import-cmd "$@" 24 | -------------------------------------------------------------------------------- /subcommands/info: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-info-cmd() { 9 | #E get connection information as follows: 10 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop 11 | #E you can also retrieve a specific piece of service info via flags: 12 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --config-dir 13 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --data-dir 14 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --dsn 15 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --exposed-ports 16 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --id 17 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --internal-ip 18 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --initial-network 19 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --links 20 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --post-create-network 21 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --post-start-network 22 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --service-root 23 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --status 24 | #E dokku $PLUGIN_COMMAND_PREFIX:info lollipop --version 25 | #A service, service to run command against 26 | #F --config-dir, show the service configuration directory 27 | #F --data-dir, show the service data directory 28 | #F --dsn, show the service DSN 29 | #F --exposed-ports, show service exposed ports 30 | #F --id, show the service container id 31 | #F --internal-ip, show the service internal ip 32 | #F --initial-network, show the initial network being connected to 33 | #F --links, show the service app links 34 | #F --post-create-network, show the networks to attach to after service container creation 35 | #F --post-start-network, show the networks to attach to after service container start 36 | #F --service-root, show the service root directory 37 | #F --status, show the service running status 38 | #F --version, show the service image version 39 | declare desc="print the service information" 40 | local cmd="$PLUGIN_COMMAND_PREFIX:info" argv=("$@") 41 | [[ ${argv[0]} == "$cmd" ]] && shift 1 42 | declare SERVICE="$1" INFO_FLAG="$2" 43 | 44 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 45 | verify_service_name "$SERVICE" 46 | service_info "$SERVICE" "$INFO_FLAG" 47 | } 48 | 49 | service-info-cmd "$@" 50 | -------------------------------------------------------------------------------- /subcommands/link: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-link-cmd() { 9 | #E a $PLUGIN_COMMAND_PREFIX service can be linked to a container. 10 | #E this will use native docker links via the docker-options plugin. 11 | #E here we link it to our 'playground' app. 12 | #E > NOTE: this will restart your app 13 | #E dokku $PLUGIN_COMMAND_PREFIX:link lollipop playground 14 | #E the following environment variables will be set automatically by docker 15 | #E (not on the app itself, so they won’t be listed when calling dokku config): 16 | #E 17 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_NAME=/lollipop/DATABASE 18 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_PORT=tcp://172.17.0.1:${PLUGIN_DATASTORE_PORTS[0]} 19 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_PORT_${PLUGIN_DATASTORE_PORTS[0]}_TCP=tcp://172.17.0.1:${PLUGIN_DATASTORE_PORTS[0]} 20 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_PORT_${PLUGIN_DATASTORE_PORTS[0]}_TCP_PROTO=tcp 21 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_PORT_${PLUGIN_DATASTORE_PORTS[0]}_TCP_PORT=${PLUGIN_DATASTORE_PORTS[0]} 22 | #E DOKKU_${PLUGIN_VARIABLE}_LOLLIPOP_PORT_${PLUGIN_DATASTORE_PORTS[0]}_TCP_ADDR=172.17.0.1 23 | #E 24 | #E the following will be set on the linked application by default: 25 | #E 26 | #E ${PLUGIN_DEFAULT_ALIAS}_URL=${PLUGIN_SCHEME}://dokku-${PLUGIN_COMMAND_PREFIX}-lollipop:${PLUGIN_DATASTORE_PORTS[0]} 27 | #E 28 | #E the host exposed here only works internally in docker containers. 29 | #E if you want your container to be reachable from outside, you should 30 | #E use the 'expose' subcommand. another service can be linked to your app: 31 | #E dokku $PLUGIN_COMMAND_PREFIX:link other_service playground 32 | #E it is possible to change the protocol for ${PLUGIN_DEFAULT_ALIAS}_URL by setting the 33 | #E environment variable ${PLUGIN_VARIABLE}_DATABASE_SCHEME on the app. doing so will 34 | #E after linking will cause the plugin to think the service is not 35 | #E linked, and we advise you to unlink before proceeding. 36 | #E dokku config:set playground ${PLUGIN_VARIABLE}_DATABASE_SCHEME=${PLUGIN_SCHEME}2 37 | #E dokku $PLUGIN_COMMAND_PREFIX:link lollipop playground 38 | #E this will cause ${PLUGIN_DEFAULT_ALIAS}_URL to be set as: 39 | #E 40 | #E ${PLUGIN_SCHEME}2://dokku-${PLUGIN_COMMAND_PREFIX}-lollipop:${PLUGIN_DATASTORE_PORTS[0]} 41 | #A service, service to run command against 42 | #A app, app to run command against 43 | #F -a|--alias "BLUE_DATABASE", an alternative alias to use for linking to an app via environment variable 44 | #F -q|--querystring "pool=5", ampersand delimited querystring arguments to append to the service link 45 | #F -n|--no-restart "false", whether or not to restart the app on link (default: true) 46 | declare desc="link the $PLUGIN_SERVICE service to the app" 47 | local cmd="$PLUGIN_COMMAND_PREFIX:link" argv=("$@") 48 | [[ ${argv[0]} == "$cmd" ]] && shift 1 49 | declare SERVICE="$1" APP="$2" LINK_FLAGS_LIST=("${@:3}") 50 | APP=${APP:="$DOKKU_APP_NAME"} 51 | 52 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 53 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 54 | verify_app_name "$APP" 55 | verify_service_name "$SERVICE" 56 | 57 | service_parse_args "${@:3}" 58 | service_link "$SERVICE" "$APP" 59 | } 60 | 61 | service-link-cmd "$@" 62 | -------------------------------------------------------------------------------- /subcommands/linked: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-linked-cmd() { 9 | #E here we check if the lollipop $PLUGIN_COMMAND_PREFIX service is linked to the 'playground' app. 10 | #E dokku $PLUGIN_COMMAND_PREFIX:linked lollipop playground 11 | #A service, service to run command against 12 | #A app, app to run command against 13 | declare desc="check if the $PLUGIN_SERVICE service is linked to an app" 14 | local cmd="$PLUGIN_COMMAND_PREFIX:linked" argv=("$@") 15 | [[ ${argv[0]} == "$cmd" ]] && shift 1 16 | declare SERVICE="$1" APP="$2" 17 | APP=${APP:="$DOKKU_APP_NAME"} 18 | 19 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 20 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 21 | verify_app_name "$APP" 22 | verify_service_name "$SERVICE" 23 | service_is_linked "$SERVICE" "$APP" 24 | } 25 | 26 | service-linked-cmd "$@" 27 | -------------------------------------------------------------------------------- /subcommands/links: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-links-cmd() { 9 | #E list all apps linked to the 'lollipop' $PLUGIN_COMMAND_PREFIX service. 10 | #E dokku $PLUGIN_COMMAND_PREFIX:links lollipop 11 | #A service, service to run command against 12 | declare desc="list all apps linked to the $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:links" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 17 | local LINKS_FILE="$SERVICE_ROOT/LINKS" 18 | 19 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 20 | verify_service_name "$SERVICE" 21 | service_links "$SERVICE" 22 | } 23 | 24 | service-links-cmd "$@" 25 | -------------------------------------------------------------------------------- /subcommands/list: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-list-cmd() { 9 | #E list all services 10 | #E dokku $PLUGIN_COMMAND_PREFIX:list 11 | declare desc="list all $PLUGIN_SERVICE services" 12 | local cmd="$PLUGIN_COMMAND_PREFIX:list" argv=("$@") 13 | [[ ${argv[0]} == "$cmd" ]] && shift 1 14 | 15 | service_list 16 | } 17 | 18 | service-list-cmd "$@" 19 | -------------------------------------------------------------------------------- /subcommands/logs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-logs-cmd() { 9 | #E you can tail logs for a particular service: 10 | #E dokku $PLUGIN_COMMAND_PREFIX:logs lollipop 11 | #E by default, logs will not be tailed, but you can do this with the --tail flag: 12 | #E dokku $PLUGIN_COMMAND_PREFIX:logs lollipop --tail 13 | #E the default tail setting is to show all logs, but an initial count can also be specified 14 | #E dokku $PLUGIN_COMMAND_PREFIX:logs lollipop --tail 5 15 | #A service, service to run command against 16 | #F -t|--tail [], do not stop when end of the logs are reached and wait for additional output 17 | declare desc="print the most recent log(s) for this service" 18 | local cmd="$PLUGIN_COMMAND_PREFIX:logs" argv=("$@") 19 | [[ ${argv[0]} == "$cmd" ]] && shift 1 20 | declare SERVICE="$1" TAIL_FLAG="$2" TAIL_NUM_OPTIONAL="${3:-all}" 21 | 22 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 23 | verify_service_name "$SERVICE" 24 | service_logs "$SERVICE" "$TAIL_FLAG" "$TAIL_NUM_OPTIONAL" 25 | } 26 | 27 | service-logs-cmd "$@" 28 | -------------------------------------------------------------------------------- /subcommands/pause: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-pause-cmd() { 9 | #E pause the running container for the service 10 | #E dokku $PLUGIN_COMMAND_PREFIX:pause lollipop 11 | #A service, service to run command against 12 | declare desc="pause a running $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:pause" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_pause "$SERVICE" 20 | } 21 | 22 | service-pause-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/promote: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-promote-cmd() { 9 | #E if you have a $PLUGIN_COMMAND_PREFIX service linked to an app and try to link another $PLUGIN_COMMAND_PREFIX service 10 | #E another link environment variable will be generated automatically: 11 | #E 12 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_BLUE_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_DATASTORE_PORTS[0]}/other_service 13 | #E 14 | #E you can promote the new service to be the primary one 15 | #E > NOTE: this will restart your app 16 | #E dokku $PLUGIN_COMMAND_PREFIX:promote other_service playground 17 | #E this will replace ${PLUGIN_DEFAULT_ALIAS}_URL with the url from other_service and generate 18 | #E another environment variable to hold the previous value if necessary. 19 | #E you could end up with the following for example: 20 | #E 21 | #E ${PLUGIN_DEFAULT_ALIAS}_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_DATASTORE_PORTS[0]}/other_service 22 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_BLUE_URL=${PLUGIN_SCHEME}://other_service:ANOTHER_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-other-service:${PLUGIN_DATASTORE_PORTS[0]}/other_service 23 | #E DOKKU_${PLUGIN_DEFAULT_ALIAS}_SILVER_URL=${PLUGIN_SCHEME}://lollipop:SOME_PASSWORD@dokku-${PLUGIN_COMMAND_PREFIX}-lollipop:${PLUGIN_DATASTORE_PORTS[0]}/lollipop 24 | #A service, service to run command against 25 | #A app, app to run command against 26 | declare desc="promote service as ${PLUGIN_DEFAULT_ALIAS}_URL in " 27 | local cmd="$PLUGIN_COMMAND_PREFIX:promote" argv=("$@") 28 | [[ ${argv[0]} == "$cmd" ]] && shift 1 29 | declare SERVICE="$1" APP="$2" 30 | APP=${APP:="$DOKKU_APP_NAME"} 31 | 32 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 33 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 34 | verify_service_name "$SERVICE" 35 | verify_app_name "$APP" 36 | service_promote "$SERVICE" "$APP" 37 | } 38 | 39 | service-promote-cmd "$@" 40 | -------------------------------------------------------------------------------- /subcommands/restart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-restart-cmd() { 9 | #E restart the service 10 | #E dokku $PLUGIN_COMMAND_PREFIX:restart lollipop 11 | #A service, service to run command against 12 | declare desc="graceful shutdown and restart of the $PLUGIN_SERVICE service container" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:restart" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_pause "$SERVICE" 20 | service_start "$SERVICE" 21 | dokku_log_info1 "Please call dokku ps:restart on all linked apps" 22 | } 23 | 24 | service-restart-cmd "$@" 25 | -------------------------------------------------------------------------------- /subcommands/set: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions" 7 | source "$(cd "$(dirname "$(dirname "${BASH_SOURCE[0]}")")" && pwd)/common-functions" 8 | 9 | service-set-cmd() { 10 | #E set the network to attach after the service container is started 11 | #E dokku $PLUGIN_COMMAND_PREFIX:set lollipop post-create-network custom-network 12 | #E set multiple networks 13 | #E dokku $PLUGIN_COMMAND_PREFIX:set lollipop post-create-network custom-network,other-network 14 | #E unset the post-create-network value 15 | #E dokku $PLUGIN_COMMAND_PREFIX:set lollipop post-create-network 16 | #A service, service to run command against 17 | #A key, property name to set 18 | #A value, optional property value to set or empty to unset key 19 | declare desc="set or clear a property for a service" 20 | local cmd="$PLUGIN_COMMAND_PREFIX:set" argv=("$@") 21 | [[ ${argv[0]} == "$cmd" ]] && shift 1 22 | declare SERVICE="$1" KEY="$2" VALUE="$3" 23 | local VALID_KEYS=("initial-network" "post-create-network" "post-start-network") 24 | verify_service_name "$SERVICE" 25 | 26 | [[ -z "$KEY" ]] && dokku_log_fail "No key specified" 27 | 28 | if ! fn-in-array "$KEY" "${VALID_KEYS[@]}"; then 29 | dokku_log_fail "Invalid key specified, valid keys include: initial-network, post-create-network, post-start-network" 30 | fi 31 | 32 | if [[ -n "$VALUE" ]]; then 33 | dokku_log_info2_quiet "Setting ${KEY} to ${VALUE}" 34 | fn-plugin-property-write "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "$KEY" "$VALUE" 35 | else 36 | dokku_log_info2_quiet "Unsetting ${KEY}" 37 | if [[ "$KEY" == "rev-env-var" ]]; then 38 | fn-plugin-property-write "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "$KEY" "$VALUE" 39 | else 40 | fn-plugin-property-delete "$PLUGIN_COMMAND_PREFIX" "$SERVICE" "$KEY" 41 | fi 42 | fi 43 | } 44 | 45 | service-set-cmd "$@" 46 | -------------------------------------------------------------------------------- /subcommands/start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-start-cmd() { 9 | #E start the service 10 | #E dokku $PLUGIN_COMMAND_PREFIX:start lollipop 11 | #A service, service to run command against 12 | declare desc="start a previously stopped $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:start" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_start "$SERVICE" 20 | } 21 | 22 | service-start-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/stop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-stop-cmd() { 9 | #E stop the service and removes the running container 10 | #E dokku $PLUGIN_COMMAND_PREFIX:stop lollipop 11 | #A service, service to run command against 12 | declare desc="stop a running $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:stop" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_container_rm "$SERVICE" 20 | } 21 | 22 | service-stop-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/unexpose: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-unexpose-cmd() { 9 | #E unexpose the service, removing access to it from the public interface (0.0.0.0) 10 | #E dokku $PLUGIN_COMMAND_PREFIX:unexpose lollipop 11 | #A service, service to run command against 12 | declare desc="unexpose a previously exposed $PLUGIN_SERVICE service" 13 | local cmd="$PLUGIN_COMMAND_PREFIX:unexpose" argv=("$@") 14 | [[ ${argv[0]} == "$cmd" ]] && shift 1 15 | declare SERVICE="$1" 16 | 17 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 18 | verify_service_name "$SERVICE" 19 | service_port_unexpose "$SERVICE" 20 | } 21 | 22 | service-unexpose-cmd "$@" 23 | -------------------------------------------------------------------------------- /subcommands/unlink: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | 8 | service-unlink-cmd() { 9 | #E you can unlink a $PLUGIN_COMMAND_PREFIX service 10 | #E > NOTE: this will restart your app and unset related environment variables 11 | #E dokku $PLUGIN_COMMAND_PREFIX:unlink lollipop playground 12 | #A service, service to run command against 13 | #A app, app to run command against 14 | #F -n|--no-restart "false", whether or not to restart the app on unlink (default: true) 15 | declare desc="unlink the $PLUGIN_SERVICE service from the app" 16 | local cmd="$PLUGIN_COMMAND_PREFIX:unlink" argv=("$@") 17 | [[ ${argv[0]} == "$cmd" ]] && shift 1 18 | declare SERVICE="$1" APP="$2" 19 | APP=${APP:="$DOKKU_APP_NAME"} 20 | 21 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 22 | [[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on" 23 | verify_service_name "$SERVICE" 24 | verify_app_name "$APP" 25 | service_unlink "$SERVICE" "$APP" 26 | } 27 | 28 | service-unlink-cmd "$@" 29 | -------------------------------------------------------------------------------- /subcommands/upgrade: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 3 | set -eo pipefail 4 | [[ $DOKKU_TRACE ]] && set -x 5 | source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions" 6 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/functions" 7 | source "$PLUGIN_AVAILABLE_PATH/ps/functions" 8 | 9 | service-upgrade-cmd() { 10 | #E you can upgrade an existing service to a new image or image-version 11 | #E dokku $PLUGIN_COMMAND_PREFIX:upgrade lollipop 12 | #A service, service to run command against 13 | #F -c|--config-options "--args --go=here", extra arguments to pass to the container create command 14 | #F -C|--custom-env "USER=alpha;HOST=beta", semi-colon delimited environment variables to start the service with 15 | #F -i|--image IMAGE, the image name to start the service with 16 | #F -I|--image-version IMAGE_VERSION, the image version to start the service with 17 | #F -N|--initial-network INITIAL_NETWORK, the initial network to attach the service to 18 | #F -P|--post-create-network NETWORKS, a comma-separated list of networks to attach the service container to after service creation 19 | #F -R|--restart-apps "true", whether or not to force an app restart (default: false) 20 | #F -S|--post-start-network NETWORKS, a comma-separated list of networks to attach the service container to after service start 21 | #F -s|--shm-size SHM_SIZE, override shared memory size for $PLUGIN_COMMAND_PREFIX docker container 22 | declare desc="upgrade service to the specified versions" 23 | local cmd="$PLUGIN_COMMAND_PREFIX:upgrade" argv=("$@") 24 | [[ ${argv[0]} == "$cmd" ]] && shift 1 25 | declare SERVICE="$1" UPGRADE_FLAGS_LIST=("${@:2}") 26 | 27 | [[ -z "$SERVICE" ]] && dokku_log_fail "Please specify a valid name for the service" 28 | verify_service_name "$SERVICE" 29 | 30 | local SERVICE_ROOT="$PLUGIN_DATA_ROOT/$SERVICE" 31 | 32 | service_parse_args "${@:2}" 33 | 34 | if ! service_image_exists "$SERVICE" "$PLUGIN_IMAGE" "$PLUGIN_IMAGE_VERSION"; then 35 | if [[ "$PLUGIN_DISABLE_PULL" == "true" ]]; then 36 | dokku_log_warn "${PLUGIN_DISABLE_PULL_VARIABLE} environment variable detected. Not running pull command." 1>&2 37 | dokku_log_warn " docker image pull ${IMAGE}" 1>&2 38 | dokku_log_warn "$PLUGIN_SERVICE service $SERVICE upgrade failed" 39 | exit 1 40 | fi 41 | "$DOCKER_BIN" image pull "$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" || dokku_log_fail "$PLUGIN_SERVICE image $PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION pull failed" 42 | fi 43 | 44 | local NEW_PLUGIN_IMAGE_TAG="$PLUGIN_IMAGE:$PLUGIN_IMAGE_VERSION" 45 | if [[ "$(service_version "$SERVICE")" == "$NEW_PLUGIN_IMAGE_TAG" ]]; then 46 | dokku_log_info1 "Service $SERVICE already running $NEW_PLUGIN_IMAGE_TAG" 47 | return 48 | fi 49 | 50 | service_commit_config "$SERVICE" 51 | 52 | dokku_log_info2 "Upgrading $SERVICE to $NEW_PLUGIN_IMAGE_TAG" 53 | if [[ "$SERVICE_RESTART_APPS" == "true" ]]; then 54 | dokku_log_info2 "Stopping all linked services" 55 | for app in $(service_linked_apps "$SERVICE"); do 56 | [[ "$app" == "-" ]] && continue 57 | ps_stop "$app" 58 | done 59 | fi 60 | 61 | dokku_log_info2 "Stopping $SERVICE" 62 | service_container_rm "$SERVICE" 63 | service_start "$SERVICE" "${@:2}" 64 | 65 | if [[ "$SERVICE_RESTART_APPS" == "true" ]]; then 66 | dokku_log_info2 "Starting all linked services" 67 | for app in $(service_linked_apps "$SERVICE"); do 68 | [[ "$app" == "-" ]] && continue 69 | ps_start "$app" 70 | done 71 | fi 72 | 73 | dokku_log_info2 "Done" 74 | } 75 | 76 | service-upgrade-cmd "$@" 77 | -------------------------------------------------------------------------------- /tests/hook_pre_delete.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku apps:create my-app 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" ls 7 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app >&2 8 | } 9 | 10 | teardown() { 11 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app >&2 12 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ls 13 | dokku --force apps:destroy my-app || true 14 | } 15 | 16 | @test "($PLUGIN_COMMAND_PREFIX:hook:pre-delete) removes app from links file when destroying app" { 17 | [[ -n $(<"$PLUGIN_DATA_ROOT/ls/LINKS") ]] 18 | dokku --force apps:destroy my-app 19 | [[ -z $(<"$PLUGIN_DATA_ROOT/ls/LINKS") ]] 20 | } 21 | -------------------------------------------------------------------------------- /tests/link_networks.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" ls 6 | dokku network:create custom-network 7 | } 8 | 9 | teardown() { 10 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ls || true 11 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" lsa || true 12 | dokku network:destroy --force custom-network 13 | } 14 | 15 | @test "($PLUGIN_COMMAND_PREFIX:set) set initial-network" { 16 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls initial-network custom-network 17 | echo "output: $output" 18 | echo "status: $status" 19 | assert_success 20 | 21 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --initial-network 22 | echo "output: $output" 23 | echo "status: $status" 24 | assert_output "custom-network" 25 | assert_success 26 | 27 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 28 | echo "output: $output" 29 | echo "status: $status" 30 | assert_success 31 | assert_output_contains bridge 32 | assert_output_contains custom-network 0 33 | 34 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 35 | echo "output: $output" 36 | echo "status: $status" 37 | assert_success 38 | 39 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 40 | echo "output: $output" 41 | echo "status: $status" 42 | assert_success 43 | 44 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 45 | echo "output: $output" 46 | echo "status: $status" 47 | assert_success 48 | assert_output_contains bridge 0 49 | assert_output_contains custom-network 50 | 51 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{range $k,$alias := $v.DNSNames}}{{printf "alias:%s\n" $alias}}{{end}}{{end}}' 52 | echo "output: $output" 53 | echo "status: $status" 54 | assert_success 55 | assert_output_contains "alias:dokku.$PLUGIN_COMMAND_PREFIX.ls" 56 | assert_output_contains "alias:dokku-$PLUGIN_COMMAND_PREFIX-ls" 57 | 58 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls initial-network 59 | echo "output: $output" 60 | echo "status: $status" 61 | assert_success 62 | 63 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --initial-network 64 | echo "output: $output" 65 | echo "status: $status" 66 | assert_output "" 67 | assert_success 68 | 69 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 70 | echo "output: $output" 71 | echo "status: $status" 72 | assert_success 73 | 74 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 75 | echo "output: $output" 76 | echo "status: $status" 77 | assert_success 78 | 79 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 80 | echo "output: $output" 81 | echo "status: $status" 82 | assert_success 83 | assert_output_contains bridge 84 | assert_output_contains custom-network 0 85 | } 86 | 87 | @test "($PLUGIN_COMMAND_PREFIX:set) set post-create-network" { 88 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls post-create-network custom-network 89 | echo "output: $output" 90 | echo "status: $status" 91 | assert_success 92 | 93 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --post-create-network 94 | echo "output: $output" 95 | echo "status: $status" 96 | assert_output "custom-network" 97 | assert_success 98 | 99 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 100 | echo "output: $output" 101 | echo "status: $status" 102 | assert_success 103 | assert_output_contains bridge 104 | assert_output_contains custom-network 0 105 | 106 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 107 | echo "output: $output" 108 | echo "status: $status" 109 | assert_success 110 | 111 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 112 | echo "output: $output" 113 | echo "status: $status" 114 | assert_success 115 | 116 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 117 | echo "output: $output" 118 | echo "status: $status" 119 | assert_success 120 | assert_output_contains custom-network 121 | assert_output_contains bridge 122 | 123 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{range $k,$alias := $v.DNSNames}}{{printf "alias:%s\n" $alias}}{{end}}{{end}}' 124 | echo "output: $output" 125 | echo "status: $status" 126 | assert_success 127 | assert_output_contains "alias:dokku.$PLUGIN_COMMAND_PREFIX.ls" 128 | assert_output_contains "alias:dokku-$PLUGIN_COMMAND_PREFIX-ls" 129 | 130 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls post-create-network 131 | echo "output: $output" 132 | echo "status: $status" 133 | assert_success 134 | 135 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --post-create-network 136 | echo "output: $output" 137 | echo "status: $status" 138 | assert_output "" 139 | assert_success 140 | 141 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 142 | echo "output: $output" 143 | echo "status: $status" 144 | assert_success 145 | 146 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 147 | echo "output: $output" 148 | echo "status: $status" 149 | assert_success 150 | 151 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 152 | echo "output: $output" 153 | echo "status: $status" 154 | assert_success 155 | assert_output_contains bridge 156 | assert_output_contains custom-network 0 157 | } 158 | 159 | @test "($PLUGIN_COMMAND_PREFIX:set) set an post-start-network" { 160 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls post-start-network custom-network 161 | echo "output: $output" 162 | echo "status: $status" 163 | assert_success 164 | 165 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --post-start-network 166 | echo "output: $output" 167 | echo "status: $status" 168 | assert_output "custom-network" 169 | assert_success 170 | 171 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 172 | echo "output: $output" 173 | echo "status: $status" 174 | assert_success 175 | assert_output_contains bridge 176 | assert_output_contains custom-network 0 177 | 178 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 179 | echo "output: $output" 180 | echo "status: $status" 181 | assert_success 182 | 183 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 184 | echo "output: $output" 185 | echo "status: $status" 186 | assert_success 187 | 188 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 189 | echo "output: $output" 190 | echo "status: $status" 191 | assert_success 192 | assert_output_contains bridge 193 | assert_output_contains custom-network 194 | 195 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{range $k,$alias := $v.DNSNames}}{{printf "alias:%s\n" $alias}}{{end}}{{end}}' 196 | echo "output: $output" 197 | echo "status: $status" 198 | assert_success 199 | assert_output_contains "alias:dokku.$PLUGIN_COMMAND_PREFIX.ls" 200 | assert_output_contains "alias:dokku-$PLUGIN_COMMAND_PREFIX-ls" 201 | 202 | run dokku "$PLUGIN_COMMAND_PREFIX:set" ls post-start-network 203 | echo "output: $output" 204 | echo "status: $status" 205 | assert_success 206 | 207 | run dokku "$PLUGIN_COMMAND_PREFIX:info" ls --post-start-network 208 | echo "output: $output" 209 | echo "status: $status" 210 | assert_output "" 211 | assert_success 212 | 213 | run dokku "$PLUGIN_COMMAND_PREFIX:stop" ls 214 | echo "output: $output" 215 | echo "status: $status" 216 | assert_success 217 | 218 | run dokku "$PLUGIN_COMMAND_PREFIX:start" ls 219 | echo "output: $output" 220 | echo "status: $status" 221 | assert_success 222 | 223 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.ls -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 224 | echo "output: $output" 225 | echo "status: $status" 226 | assert_success 227 | assert_output_contains bridge 228 | assert_output_contains custom-network 0 229 | } 230 | 231 | @test "($PLUGIN_COMMAND_PREFIX:create) flags" { 232 | run dokku "$PLUGIN_COMMAND_PREFIX:create" lsa --initial-network custom-network 233 | echo "output: $output" 234 | echo "status: $status" 235 | assert_success 236 | 237 | run docker inspect "dokku.$PLUGIN_COMMAND_PREFIX.lsa" -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 238 | echo "output: $output" 239 | echo "status: $status" 240 | assert_success 241 | assert_output_contains bridge 0 242 | assert_output_contains custom-network 243 | 244 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" lsa --force 245 | echo "output: $output" 246 | echo "status: $status" 247 | assert_success 248 | 249 | run dokku "$PLUGIN_COMMAND_PREFIX:create" lsa --post-create-network custom-network 250 | echo "output: $output" 251 | echo "status: $status" 252 | assert_success 253 | 254 | run docker inspect "dokku.$PLUGIN_COMMAND_PREFIX.lsa" -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 255 | echo "output: $output" 256 | echo "status: $status" 257 | assert_success 258 | assert_output_contains bridge 259 | assert_output_contains custom-network 260 | 261 | run docker inspect dokku.$PLUGIN_COMMAND_PREFIX.lsa -f '{{range $net,$v := .NetworkSettings.Networks}}{{range $k,$alias := $v.DNSNames}}{{printf "alias:%s\n" $alias}}{{end}}{{end}}' 262 | echo "output: $output" 263 | echo "status: $status" 264 | assert_success 265 | assert_output_contains "alias:dokku.$PLUGIN_COMMAND_PREFIX.lsa" 266 | assert_output_contains "alias:dokku-$PLUGIN_COMMAND_PREFIX-lsa" 267 | 268 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" lsa --force 269 | echo "output: $output" 270 | echo "status: $status" 271 | assert_success 272 | 273 | run dokku "$PLUGIN_COMMAND_PREFIX:create" lsa --post-start-network custom-network 274 | echo "output: $output" 275 | echo "status: $status" 276 | assert_success 277 | 278 | run docker inspect "dokku.$PLUGIN_COMMAND_PREFIX.lsa" -f '{{range $net,$v := .NetworkSettings.Networks}}{{printf "%s\n" $net}}{{end}}' 279 | echo "output: $output" 280 | echo "status: $status" 281 | assert_success 282 | assert_output_contains bridge 283 | assert_output_contains custom-network 284 | 285 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" lsa --force 286 | echo "output: $output" 287 | echo "status: $status" 288 | assert_success 289 | } 290 | -------------------------------------------------------------------------------- /tests/service_connect.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:connect) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:connect" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:connect) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:connect" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:connect) success" { 23 | skip "Connect hangs indefinitely without input" 24 | run dokku "$PLUGIN_COMMAND_PREFIX:connect" l 25 | assert_success 26 | } 27 | -------------------------------------------------------------------------------- /tests/service_create.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | @test "($PLUGIN_COMMAND_PREFIX:create) success" { 5 | run dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | assert_contains "${lines[*]}" "container created: l" 7 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 8 | } 9 | 10 | @test "($PLUGIN_COMMAND_PREFIX:create) service with dashes" { 11 | run dokku "$PLUGIN_COMMAND_PREFIX:create" service-with-dashes 12 | assert_contains "${lines[*]}" "container created: service-with-dashes" 13 | assert_contains "${lines[*]}" "dokku-$PLUGIN_COMMAND_PREFIX-service-with-dashes" 14 | 15 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" service-with-dashes 16 | } 17 | 18 | @test "($PLUGIN_COMMAND_PREFIX:create) error when there are no arguments" { 19 | run dokku "$PLUGIN_COMMAND_PREFIX:create" 20 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 21 | } 22 | 23 | @test "($PLUGIN_COMMAND_PREFIX:create) error when there is an invalid name specified" { 24 | run dokku "$PLUGIN_COMMAND_PREFIX:create" d.erp 25 | assert_failure 26 | } 27 | -------------------------------------------------------------------------------- /tests/service_destroy.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | @test "($PLUGIN_COMMAND_PREFIX:destroy) success with --force" { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | run dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 7 | assert_contains "${lines[*]}" "container deleted: l" 8 | } 9 | 10 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when there are no arguments" { 11 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" 12 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 13 | } 14 | 15 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when container does not exist" { 16 | run dokku "$PLUGIN_COMMAND_PREFIX:destroy" non_existing_container 17 | assert_contains "${lines[*]}" "service non_existing_container does not exist" 18 | } 19 | 20 | @test "($PLUGIN_COMMAND_PREFIX:destroy) error when container is linked to an app" { 21 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 22 | dokku apps:create app 23 | dokku "$PLUGIN_COMMAND_PREFIX:link" l app 24 | run dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 25 | assert_contains "${lines[*]}" "Cannot delete linked service" 26 | 27 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" l app 28 | run dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 29 | assert_contains "${lines[*]}" "container deleted: l" 30 | } 31 | -------------------------------------------------------------------------------- /tests/service_expose.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" ls 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ls 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:expose) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" 14 | echo "output: $output" 15 | echo "status: $status" 16 | assert_failure 17 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 18 | } 19 | 20 | @test "($PLUGIN_COMMAND_PREFIX:expose) error when service does not exist" { 21 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" not_existing_service 22 | echo "output: $output" 23 | echo "status: $status" 24 | assert_failure 25 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 26 | } 27 | 28 | @test "($PLUGIN_COMMAND_PREFIX:expose) error when already exposed" { 29 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" ls 30 | echo "output: $output" 31 | echo "status: $status" 32 | assert_success 33 | 34 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" ls 35 | echo "output: $output" 36 | echo "status: $status" 37 | assert_failure 38 | assert_contains "${lines[*]}" "Service ls already exposed on port(s)" 39 | 40 | run sudo rm "$PLUGIN_DATA_ROOT/ls/PORT" 41 | echo "output: $output" 42 | echo "status: $status" 43 | assert_success 44 | 45 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" ls 46 | echo "output: $output" 47 | echo "status: $status" 48 | assert_success 49 | assert_contains "${lines[*]}" "Service ls has an untracked expose container, removing" 50 | } 51 | 52 | @test "($PLUGIN_COMMAND_PREFIX:expose) success when not providing custom ports" { 53 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" ls 54 | echo "output: $output" 55 | echo "status: $status" 56 | assert_success 57 | [[ "${lines[*]}" =~ exposed\ on\ port\(s\)\ \[container\-\>host\]\:\ [[:digit:]]+ ]] 58 | } 59 | 60 | @test "($PLUGIN_COMMAND_PREFIX:expose) success when providing custom ports" { 61 | run dokku "$PLUGIN_COMMAND_PREFIX:expose" ls 4242 62 | echo "output: $output" 63 | echo "status: $status" 64 | assert_success 65 | assert_contains "${lines[*]}" "exposed on port(s) [container->host]: 11211->4242" 66 | } 67 | -------------------------------------------------------------------------------- /tests/service_info.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:info) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:info" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:info) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:info" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:info) success" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l 24 | assert_contains "${lines[*]}" "memcached://dokku-memcached-l:11211" 25 | } 26 | 27 | @test "($PLUGIN_COMMAND_PREFIX:info) replaces underscores by dash in hostname" { 28 | dokku "$PLUGIN_COMMAND_PREFIX:create" test_with_underscores 29 | run dokku "$PLUGIN_COMMAND_PREFIX:info" test_with_underscores 30 | assert_contains "${lines[*]}" "memcached://dokku-memcached-test-with-underscores:11211" 31 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" test_with_underscores 32 | } 33 | 34 | @test "($PLUGIN_COMMAND_PREFIX:info) success with flag" { 35 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn 36 | assert_output "memcached://dokku-memcached-l:11211" 37 | 38 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --config-dir 39 | assert_success 40 | 41 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --data-dir 42 | assert_success 43 | 44 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --dsn 45 | assert_success 46 | 47 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --exposed-ports 48 | assert_success 49 | 50 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --id 51 | assert_success 52 | 53 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --internal-ip 54 | assert_success 55 | 56 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --links 57 | assert_success 58 | 59 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --service-root 60 | assert_success 61 | 62 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --status 63 | assert_success 64 | 65 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --version 66 | assert_success 67 | } 68 | 69 | @test "($PLUGIN_COMMAND_PREFIX:info) error when invalid flag" { 70 | run dokku "$PLUGIN_COMMAND_PREFIX:info" l --invalid-flag 71 | assert_failure 72 | } 73 | -------------------------------------------------------------------------------- /tests/service_link.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" ls 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" ms 7 | dokku apps:create my-app 8 | } 9 | 10 | teardown() { 11 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ms 12 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ls 13 | dokku --force apps:destroy my-app 14 | } 15 | 16 | @test "($PLUGIN_COMMAND_PREFIX:link) error when there are no arguments" { 17 | run dokku "$PLUGIN_COMMAND_PREFIX:link" 18 | echo "output: $output" 19 | echo "status: $status" 20 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 21 | assert_failure 22 | } 23 | 24 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the app argument is missing" { 25 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls 26 | echo "output: $output" 27 | echo "status: $status" 28 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 29 | assert_failure 30 | } 31 | 32 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the app does not exist" { 33 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls not_existing_app 34 | echo "output: $output" 35 | echo "status: $status" 36 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 37 | assert_failure 38 | } 39 | 40 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the service does not exist" { 41 | run dokku "$PLUGIN_COMMAND_PREFIX:link" not_existing_service my-app 42 | echo "output: $output" 43 | echo "status: $status" 44 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 45 | assert_failure 46 | } 47 | 48 | @test "($PLUGIN_COMMAND_PREFIX:link) error when the service is already linked to app" { 49 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 50 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 51 | echo "output: $output" 52 | echo "status: $status" 53 | assert_contains "${lines[*]}" "Already linked as MEMCACHED_URL" 54 | assert_failure 55 | 56 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 57 | } 58 | 59 | @test "($PLUGIN_COMMAND_PREFIX:link) exports MEMCACHED_URL to app" { 60 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 61 | echo "output: $output" 62 | echo "status: $status" 63 | url=$(dokku config:get my-app MEMCACHED_URL) 64 | assert_contains "$url" "dokku-memcached-ls:11211" 65 | assert_success 66 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 67 | } 68 | 69 | @test "($PLUGIN_COMMAND_PREFIX:link) generates an alternate config url when MEMCACHED_URL already in use" { 70 | dokku config:set my-app MEMCACHED_URL=host:11211 71 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 72 | run dokku config my-app 73 | assert_contains "${lines[*]}" "DOKKU_MEMCACHED_AQUA_URL" 74 | assert_success 75 | 76 | dokku "$PLUGIN_COMMAND_PREFIX:link" ms my-app 77 | run dokku config my-app 78 | assert_contains "${lines[*]}" "DOKKU_MEMCACHED_BLACK_URL" 79 | assert_success 80 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ms my-app 81 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 82 | } 83 | 84 | @test "($PLUGIN_COMMAND_PREFIX:link) links to app with docker-options" { 85 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 86 | run dokku docker-options:report my-app 87 | assert_contains "${lines[*]}" "--link dokku.memcached.ls:dokku-memcached-ls" 88 | assert_success 89 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 90 | } 91 | 92 | @test "($PLUGIN_COMMAND_PREFIX:link) uses apps MEMCACHED_DATABASE_SCHEME variable" { 93 | dokku config:set my-app MEMCACHED_DATABASE_SCHEME=memcached2 94 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 95 | url=$(dokku config:get my-app MEMCACHED_URL) 96 | assert_contains "$url" "memcached2://dokku-memcached-ls:11211" 97 | assert_success 98 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 99 | } 100 | 101 | @test "($PLUGIN_COMMAND_PREFIX:link) adds a querystring" { 102 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app --querystring "pool=5" 103 | url=$(dokku config:get my-app MEMCACHED_URL) 104 | assert_contains "$url" "?pool=5" 105 | assert_success 106 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 107 | } 108 | 109 | @test "($PLUGIN_COMMAND_PREFIX:link) uses a specified config url when alias is specified" { 110 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app --alias "ALIAS" 111 | url=$(dokku config:get my-app ALIAS_URL) 112 | assert_contains "$url" "dokku-memcached-ls:11211" 113 | assert_success 114 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 115 | } 116 | 117 | @test "($PLUGIN_COMMAND_PREFIX:link) respects --no-restart" { 118 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 119 | echo "output: $output" 120 | echo "status: $status" 121 | assert_output_contains "Skipping restart of linked app" 0 122 | assert_success 123 | 124 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 125 | echo "output: $output" 126 | echo "status: $status" 127 | assert_success 128 | 129 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app --no-restart 130 | echo "output: $output" 131 | echo "status: $status" 132 | assert_output_contains "Skipping restart of linked app" 133 | assert_success 134 | 135 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 136 | echo "output: $output" 137 | echo "status: $status" 138 | assert_success 139 | } 140 | -------------------------------------------------------------------------------- /tests/service_list.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:list) with no exposed ports, no linked apps" { 13 | run dokku --quiet "$PLUGIN_COMMAND_PREFIX:list" 14 | assert_output "l" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:list) when there are no services" { 18 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 19 | run dokku "$PLUGIN_COMMAND_PREFIX:list" 20 | assert_output "${lines[*]}" "There are no $PLUGIN_SERVICE services" 21 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 22 | } 23 | -------------------------------------------------------------------------------- /tests/service_logs.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:logs) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" 14 | echo "output: $output" 15 | echo "status: $status" 16 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 17 | assert_failure 18 | } 19 | 20 | @test "($PLUGIN_COMMAND_PREFIX:logs) error when service does not exist" { 21 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" not_existing_service 22 | echo "output: $output" 23 | echo "status: $status" 24 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 25 | assert_failure 26 | } 27 | 28 | @test "($PLUGIN_COMMAND_PREFIX:logs) success when not tailing" { 29 | skip "This may fail if there is no log output" 30 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" l 31 | echo "output: $output" 32 | echo "status: $status" 33 | assert_success 34 | } 35 | 36 | @test "($PLUGIN_COMMAND_PREFIX:logs) success when tailing" { 37 | skip "This will hang as it waits for log output" 38 | run dokku "$PLUGIN_COMMAND_PREFIX:logs" l -t 39 | echo "output: $output" 40 | echo "status: $status" 41 | assert_success 42 | } 43 | -------------------------------------------------------------------------------- /tests/service_pause.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 10 | } 11 | 12 | @test "($PLUGIN_COMMAND_PREFIX:pause) error when there are no arguments" { 13 | run dokku "$PLUGIN_COMMAND_PREFIX:pause" 14 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 15 | } 16 | 17 | @test "($PLUGIN_COMMAND_PREFIX:pause) error when service does not exist" { 18 | run dokku "$PLUGIN_COMMAND_PREFIX:pause" not_existing_service 19 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 20 | } 21 | 22 | @test "($PLUGIN_COMMAND_PREFIX:pause) success" { 23 | run dokku "$PLUGIN_COMMAND_PREFIX:pause" l 24 | assert_success 25 | } 26 | -------------------------------------------------------------------------------- /tests/service_promote.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | dokku apps:create my-app 7 | dokku "$PLUGIN_COMMAND_PREFIX:link" l my-app 8 | } 9 | 10 | teardown() { 11 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" l my-app 12 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 13 | dokku --force apps:destroy my-app 14 | } 15 | 16 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when there are no arguments" { 17 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" 18 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 19 | } 20 | 21 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the app argument is missing" { 22 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l 23 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 24 | } 25 | 26 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the app does not exist" { 27 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l not_existing_app 28 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 29 | } 30 | 31 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the service does not exist" { 32 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" not_existing_service my-app 33 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 34 | } 35 | 36 | @test "($PLUGIN_COMMAND_PREFIX:promote) error when the service is already promoted" { 37 | run dokku "$PLUGIN_COMMAND_PREFIX:promote" l my-app 38 | assert_contains "${lines[*]}" "already promoted as MEMCACHED_URL" 39 | } 40 | 41 | @test "($PLUGIN_COMMAND_PREFIX:promote) changes MEMCACHED_URL" { 42 | dokku config:set my-app "MEMCACHED_URL=memcached://host:11211" "DOKKU_MEMCACHED_BLUE_URL=memcached://dokku-memcached-l:11211" 43 | dokku "$PLUGIN_COMMAND_PREFIX:promote" l my-app 44 | url=$(dokku config:get my-app MEMCACHED_URL) 45 | assert_equal "$url" "memcached://dokku-memcached-l:11211" 46 | } 47 | 48 | @test "($PLUGIN_COMMAND_PREFIX:promote) creates new config url when needed" { 49 | dokku config:set my-app "MEMCACHED_URL=memcached://host:11211" "DOKKU_MEMCACHED_BLUE_URL=memcached://dokku-memcached-l:11211" 50 | dokku "$PLUGIN_COMMAND_PREFIX:promote" l my-app 51 | run dokku config my-app 52 | assert_contains "${lines[*]}" "DOKKU_MEMCACHED_" 53 | } 54 | @test "($PLUGIN_COMMAND_PREFIX:promote) uses MEMCACHED_DATABASE_SCHEME variable" { 55 | dokku config:set my-app "MEMCACHED_DATABASE_SCHEME=memcached2" "MEMCACHED_URL=memcached://host:11211/db" "DOKKU_MEMCACHED_BLUE_URL=memcached2://dokku-memcached-l:11211" 56 | dokku "$PLUGIN_COMMAND_PREFIX:promote" l my-app 57 | url=$(dokku config:get my-app MEMCACHED_URL) 58 | assert_contains "$url" "memcached2://dokku-memcached-l:11211" 59 | } 60 | -------------------------------------------------------------------------------- /tests/service_restart.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 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 | -------------------------------------------------------------------------------- /tests/service_start.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 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 | -------------------------------------------------------------------------------- /tests/service_stop.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 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 | -------------------------------------------------------------------------------- /tests/service_unexpose.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku "$PLUGIN_COMMAND_PREFIX:create" l 6 | } 7 | 8 | teardown() { 9 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" l 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 | -------------------------------------------------------------------------------- /tests/service_unlink.bats: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bats 2 | load test_helper 3 | 4 | setup() { 5 | dokku apps:create my-app 6 | dokku "$PLUGIN_COMMAND_PREFIX:create" ls 7 | } 8 | 9 | teardown() { 10 | dokku --force "$PLUGIN_COMMAND_PREFIX:destroy" ls 11 | dokku --force apps:destroy my-app 12 | } 13 | 14 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when there are no arguments" { 15 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" 16 | assert_contains "${lines[*]}" "Please specify a valid name for the service" 17 | } 18 | 19 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the app argument is missing" { 20 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls 21 | assert_contains "${lines[*]}" "Please specify an app to run the command on" 22 | } 23 | 24 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the app does not exist" { 25 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls not_existing_app 26 | assert_contains "${lines[*]}" "App not_existing_app does not exist" 27 | } 28 | 29 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when the service does not exist" { 30 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" not_existing_service my-app 31 | assert_contains "${lines[*]}" "service not_existing_service does not exist" 32 | } 33 | 34 | @test "($PLUGIN_COMMAND_PREFIX:unlink) error when service not linked to app" { 35 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 36 | assert_contains "${lines[*]}" "Not linked to app my-app" 37 | } 38 | 39 | @test "($PLUGIN_COMMAND_PREFIX:unlink) removes link from docker-options" { 40 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app >&2 41 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 42 | 43 | check_value="Docker options build: Docker options deploy: --restart=on-failure:10 Docker options run:" 44 | options=$(dokku --quiet docker-options:report my-app | xargs) 45 | assert_equal "$options" "$check_value" 46 | } 47 | 48 | @test "($PLUGIN_COMMAND_PREFIX:unlink) unsets config url from app" { 49 | dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app >&2 50 | dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 51 | config=$(dokku config:get my-app MEMCACHED_URL || true) 52 | assert_equal "$config" "" 53 | } 54 | 55 | @test "($PLUGIN_COMMAND_PREFIX:unlink) respects --no-restart" { 56 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 57 | echo "output: $output" 58 | echo "status: $status" 59 | assert_success 60 | 61 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app 62 | echo "output: $output" 63 | echo "status: $status" 64 | assert_output_contains "Skipping restart of linked app" 0 65 | assert_success 66 | 67 | run dokku "$PLUGIN_COMMAND_PREFIX:link" ls my-app 68 | echo "output: $output" 69 | echo "status: $status" 70 | assert_success 71 | 72 | run dokku "$PLUGIN_COMMAND_PREFIX:unlink" ls my-app --no-restart 73 | echo "output: $output" 74 | echo "status: $status" 75 | assert_output_contains "Skipping restart of linked app" 76 | assert_success 77 | } 78 | -------------------------------------------------------------------------------- /tests/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eo pipefail 3 | [[ $TRACE ]] && set -x 4 | sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 762E3157 5 | echo "deb http://nginx.org/packages/ubuntu $(lsb_release -cs) nginx" | sudo tee /etc/apt/sources.list.d/nginx.list 6 | curl -fsSL https://nginx.org/keys/nginx_signing.key | sudo apt-key add - 7 | 8 | sudo mkdir -p /etc/nginx 9 | sudo curl https://raw.githubusercontent.com/dokku/dokku/master/tests/dhparam.pem -o /etc/nginx/dhparam.pem 10 | 11 | echo "dokku dokku/skip_key_file boolean true" | sudo debconf-set-selections 12 | wget https://raw.githubusercontent.com/dokku/dokku/master/bootstrap.sh 13 | if [[ "$DOKKU_VERSION" == "master" ]]; then 14 | sudo bash bootstrap.sh 15 | else 16 | sudo DOKKU_TAG="$DOKKU_VERSION" bash bootstrap.sh 17 | fi 18 | echo "Dokku version $DOKKU_VERSION" 19 | 20 | export DOKKU_LIB_ROOT="/var/lib/dokku" 21 | export DOKKU_PLUGINS_ROOT="$DOKKU_LIB_ROOT/plugins/available" 22 | pushd "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")" >/dev/null 23 | source "config" 24 | popd >/dev/null 25 | sudo rm -rf "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX" 26 | sudo mkdir -p "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX" "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/subcommands" "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/scripts" "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/templates" 27 | sudo find ./ -maxdepth 1 -type f -exec cp '{}' "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX" \; 28 | [[ -d "./scripts" ]] && sudo find ./scripts -maxdepth 1 -type f -exec cp '{}' "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/scripts" \; 29 | [[ -d "./subcommands" ]] && sudo find ./subcommands -maxdepth 1 -type f -exec cp '{}' "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/subcommands" \; 30 | [[ -d "./templates" ]] && sudo find ./templates -maxdepth 1 -type f -exec cp '{}' "$DOKKU_PLUGINS_ROOT/$PLUGIN_COMMAND_PREFIX/templates" \; 31 | sudo mkdir -p "$PLUGIN_CONFIG_ROOT" "$PLUGIN_DATA_ROOT" 32 | sudo dokku plugin:enable "$PLUGIN_COMMAND_PREFIX" 33 | sudo dokku plugin:install 34 | -------------------------------------------------------------------------------- /tests/shellcheck-exclude: -------------------------------------------------------------------------------- 1 | # SC1090 - Can't follow non-constant source. Use a directive to specify location - https://github.com/koalaman/shellcheck/wiki/SC1090 2 | # SC1091 - Not following - 3 | # SC2034 - Variable appears unused. Verify it or export it - https://github.com/koalaman/shellcheck/wiki/SC2034 4 | # SC2155 - Declare and assign separately to avoid masking return values - https://github.com/koalaman/shellcheck/wiki/SC2155 5 | # SC2206 - Quote to prevent word splitting/globbing, or split robustly with mapfile or read -a - https://github.com/koalaman/shellcheck/wiki/SC2206 6 | # SC2207 - Prefer mapfile or read -a to split command output (or quote to avoid splitting) - https://github.com/koalaman/shellcheck/wiki/SC2207 7 | # SC2220 - Invalid flags are not handled. Add a *) case - https://github.com/koalaman/shellcheck/wiki/SC2220 8 | # SC2230 - which is non-standard. Use builtin 'command -v' instead - https://github.com/koalaman/shellcheck/wiki/SC2230 9 | -------------------------------------------------------------------------------- /tests/shellcheck-to-junit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | from __future__ import print_function 4 | import argparse 5 | import collections 6 | import datetime 7 | import re 8 | import socket 9 | import sys 10 | 11 | from xml.etree import ElementTree 12 | 13 | 14 | def CDATA(text=None): 15 | element = ElementTree.Element('![CDATA[') 16 | element.text = text 17 | return element 18 | 19 | 20 | def _serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs): 21 | 22 | if elem.tag == '![CDATA[': 23 | write("\n<{}{}]]>\n".format(elem.tag, elem.text)) 24 | if elem.tail: 25 | write(ElementTree._escape_cdata(elem.tail)) 26 | else: 27 | return ElementTree._original_serialize_xml(write, elem, qnames, namespaces,short_empty_elements, **kwargs) 28 | 29 | 30 | ElementTree._original_serialize_xml = ElementTree._serialize_xml 31 | ElementTree._serialize_xml = ElementTree._serialize['xml'] = _serialize_xml 32 | 33 | 34 | def read_in(): 35 | lines = sys.stdin.readlines() 36 | for i in range(len(lines)): 37 | lines[i] = lines[i].rstrip() 38 | return lines 39 | 40 | 41 | def process_lines(lines): 42 | files = {} 43 | current_file = None 44 | previous_line = None 45 | line_no = None 46 | new_issues = [] 47 | code = None 48 | 49 | RE_VIOLATION = re.compile(r"\^-- (SC[\w]+): (.*)") 50 | RE_VIOLATION_NEW = re.compile(r"\^[-]+\^ (SC[\w]+): (.*)") 51 | 52 | for line in lines: 53 | # start a new block 54 | if line == '': 55 | if current_file is not None: 56 | file_data = files.get(current_file, {}) 57 | files[current_file] = file_data 58 | 59 | issue_data = file_data.get(line_no, {}) 60 | issue_data['code'] = code 61 | files[current_file][line_no] = issue_data 62 | 63 | issues = issue_data.get('issues', []) 64 | issues.extend(new_issues) 65 | issue_data['issues'] = issues 66 | 67 | files[current_file][line_no] = issue_data 68 | 69 | code = None 70 | current_file = None 71 | line_no = None 72 | elif line.startswith('In ./') and not previous_line: 73 | current_file = line.split(' ')[1].replace('./', '') 74 | line_no = line.split(' ')[3] 75 | new_issues = [] 76 | code = None 77 | elif code is None and len(new_issues) == 0: 78 | code = line 79 | else: 80 | match = RE_VIOLATION.match(line.strip()) 81 | if not match: 82 | match = RE_VIOLATION_NEW.match(line.strip()) 83 | 84 | if not match: 85 | if 'https://www.shellcheck.net/wiki/SC' in line: 86 | continue 87 | if 'For more information:' == line: 88 | continue 89 | print('Error: Issue parsing line "{0}"'.format(line.strip())) 90 | else: 91 | new_issues.append({ 92 | 'shellcheck_id': match.group(1), 93 | 'message': match.group(2), 94 | 'original_message': line 95 | }) 96 | 97 | previous_line = line 98 | 99 | return files 100 | 101 | 102 | def output_junit(files, args): 103 | timestamp = datetime.datetime.now().replace(microsecond=0).isoformat() 104 | failures = 0 105 | for file, data in files.items(): 106 | for line, issue_data in data.items(): 107 | code = issue_data.get('code') 108 | for issue in issue_data.get('issues', []): 109 | failures += 1 110 | 111 | tests = 0 112 | if args.files: 113 | with open(args.files, 'r') as f: 114 | tests = len(f.readlines()) 115 | 116 | root = ElementTree.Element("testsuite", 117 | name="shellcheck", 118 | tests="{0}".format(tests), 119 | failures="{0}".format(failures), 120 | errors="0", 121 | skipped="0", 122 | timestamp=timestamp, 123 | time="0", 124 | hostname=socket.gethostname()) 125 | 126 | properties = ElementTree.SubElement(root, "properties") 127 | if args.exclude: 128 | ElementTree.SubElement(properties, 129 | "property", 130 | name="exclude", 131 | value=args.exclude) 132 | 133 | if args.files: 134 | with open(args.files, 'r') as f: 135 | lines = f.readlines() 136 | for i in range(len(lines)): 137 | file = lines[i].rstrip().replace('./', '') 138 | data = files.get(file, None) 139 | if data: 140 | for line, issue_data in data.items(): 141 | code = issue_data.get('code') 142 | for issue in issue_data.get('issues', []): 143 | testcase = ElementTree.SubElement(root, 144 | "testcase", 145 | classname=file, 146 | name=file, 147 | time="0") 148 | shellcheck_id = issue.get('shellcheck_id') 149 | message = 'line {0}: {1}'.format( 150 | line, issue.get('message')) 151 | original_message = issue.get('original_message') 152 | e = ElementTree.Element("failure", 153 | type=shellcheck_id, 154 | message=message) 155 | cdata = CDATA("\n".join([code, original_message])) 156 | e.append(cdata) 157 | testcase.append(e) 158 | ElementTree.SubElement(root, 159 | "testcase", 160 | classname=file, 161 | name=file, 162 | time="0") 163 | 164 | ElementTree.SubElement(root, "system-out") 165 | ElementTree.SubElement(root, "system-err") 166 | 167 | content = ElementTree.tostring(root, encoding='UTF-8', method='xml') 168 | if args.output: 169 | with open(args.output, 'w') as f: 170 | try: 171 | f.write(content) 172 | except TypeError: 173 | f.write(content.decode("utf-8")) 174 | 175 | 176 | def main(): 177 | parser = argparse.ArgumentParser( 178 | description='Process shellcheck output to junit.') 179 | parser.add_argument('--output', 180 | dest='output', 181 | action='store', 182 | default=None, 183 | help='file to write shellcheck output') 184 | parser.add_argument('--files', 185 | dest='files', 186 | action='store', 187 | default=None, 188 | help='a file containing a list of all files processed by shellcheck') 189 | parser.add_argument('--exclude', 190 | dest='exclude', 191 | action='store', 192 | default=None, 193 | help='a comma-separated list of rules being excluded by shellcheck') 194 | args = parser.parse_args() 195 | 196 | lines = read_in() 197 | files = process_lines(lines) 198 | files = collections.OrderedDict(sorted(files.items())) 199 | output_junit(files, args) 200 | for line in lines: 201 | print(line) 202 | 203 | 204 | if __name__ == '__main__': 205 | main() 206 | -------------------------------------------------------------------------------- /tests/test_helper.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | export DOKKU_LIB_ROOT="/var/lib/dokku" 3 | source "$(dirname "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)")/config" 4 | 5 | flunk() { 6 | { 7 | if [ "$#" -eq 0 ]; then 8 | cat - 9 | else 10 | echo "$*" 11 | fi 12 | } 13 | return 1 14 | } 15 | 16 | assert_equal() { 17 | if [ "$1" != "$2" ]; then 18 | { 19 | echo "expected: $1" 20 | echo "actual: $2" 21 | } | flunk 22 | fi 23 | } 24 | 25 | # ShellCheck doesn't know about $status from Bats 26 | # shellcheck disable=SC2154 27 | assert_exit_status() { 28 | assert_equal "$1" "$status" 29 | } 30 | 31 | # ShellCheck doesn't know about $status from Bats 32 | # shellcheck disable=SC2154 33 | # shellcheck disable=SC2120 34 | assert_success() { 35 | if [ "$status" -ne 0 ]; then 36 | flunk "command failed with exit status $status" 37 | elif [ "$#" -gt 0 ]; then 38 | assert_output "$1" 39 | fi 40 | } 41 | 42 | assert_failure() { 43 | if [[ "$status" -eq 0 ]]; then 44 | flunk "expected failed exit status" 45 | elif [[ "$#" -gt 0 ]]; then 46 | assert_output "$1" 47 | fi 48 | } 49 | 50 | assert_exists() { 51 | if [ ! -f "$1" ]; then 52 | flunk "expected file to exist: $1" 53 | fi 54 | } 55 | 56 | assert_contains() { 57 | if [[ "$1" != *"$2"* ]]; then 58 | flunk "expected $2 to be in: $1" 59 | fi 60 | } 61 | 62 | # ShellCheck doesn't know about $output from Bats 63 | # shellcheck disable=SC2154 64 | assert_output() { 65 | local expected 66 | if [ $# -eq 0 ]; then 67 | expected="$(cat -)" 68 | else 69 | expected="$1" 70 | fi 71 | assert_equal "$expected" "$output" 72 | } 73 | 74 | # ShellCheck doesn't know about $output from Bats 75 | # shellcheck disable=SC2154 76 | assert_output_contains() { 77 | local input="$output" 78 | local expected="$1" 79 | local count="${2:-1}" 80 | local found=0 81 | until [ "${input/$expected/}" = "$input" ]; do 82 | input="${input/$expected/}" 83 | found=$((found + 1)) 84 | done 85 | assert_equal "$count" "$found" 86 | } 87 | -------------------------------------------------------------------------------- /update: -------------------------------------------------------------------------------- 1 | install --------------------------------------------------------------------------------