diff --git a/.circleci/config.yml b/.circleci/config.yml index 41fe25837..7638102fa 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,6 +6,12 @@ jobs: parallelism: 4 steps: - checkout + - run: | + make ci-dependencies + - run: | + ./tests/ci/setup.sh + - run: | + echo 'export DOKKU_SKIP_CLEANUP=true' | sudo tee /home/dokku/.dokkurc/dokku_skip_cleanup - run: | if [[ "$(lsb_release -rs)" == "14.04" ]]; then # dokku.me now resolves to 10.0.0.2. add 10.0.0.2/24 to eth0 @@ -14,15 +20,9 @@ jobs: # dokku.me now resolves to 10.0.0.2. add 10.0.0.2/24 to ens4 sudo ip a a 10.0.0.2/24 broadcast 10.0.0.255 dev ens4 fi - - run: | - make ci-dependencies - - run: | - ./tests/ci/setup.sh - - run: | - echo 'export DOKKU_SKIP_CLEANUP=true' | sudo tee /home/dokku/.dokkurc/dokku_skip_cleanup - run: | case $CIRCLE_NODE_INDEX in - 0) sudo -E make -e lint go-tests ci-go-coverage ;; + 0) sudo -E make -e lint-ci go-tests ci-go-coverage ;; 1) sudo -E make -e deploy-test-checks-root deploy-test-config ;; 2) sudo -E make -e deploy-test-multi ;; 3) sudo -E make -e deploy-test-go-fail-predeploy deploy-test-go-fail-postdeploy ;; @@ -31,6 +31,11 @@ jobs: shell: /bin/bash command: sudo -E make -e test-ci no_output_timeout: 60m + - run: | + if [ "${CIRCLE_NODE_INDEX}" == "0" ]; then + ./tests/ci/setup.sh docker + DOKKU_SSH_PORT=3022 sudo -E make -e test-ci-docker + fi - store_artifacts: path: ./coverage.out - store_artifacts: diff --git a/.dockerignore b/.dockerignore index 84200e4bd..977ed7878 100644 --- a/.dockerignore +++ b/.dockerignore @@ -6,6 +6,7 @@ contrib build docs tests +!build/dokku.deb !contrib/dokku-installer.py !contrib/dokku-update !contrib/bash-completion diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..3dc52667a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,52 @@ +FROM phusion/baseimage:0.11 + +CMD ["/sbin/my_init"] + +ARG DOKKU_TAG=0.17.7 +ARG DOKKU_GID=200 +ARG DOKKU_UID=200 +ARG DOKKU_HOSTNAME=dokku.invalid +ARG DOKKU_SKIP_KEY_FILE=true +ARG DOKKU_VHOST_ENABLE=false +ARG DOKKU_WEB_CONFIG=false + +COPY ./build/dokku.deb /tmp/dokku.deb + +RUN addgroup --gid $DOKKU_GID dokku \ + && adduser --uid $DOKKU_UID --gid $DOKKU_GID --disabled-password --gecos "" "dokku" + +RUN echo "dokku dokku/hostname string $DOKKU_HOSTNAME" | debconf-set-selections \ + && echo "dokku dokku/skip_key_file boolean $DOKKU_SKIP_KEY_FILE" | debconf-set-selections \ + && echo "dokku dokku/vhost_enable boolean $DOKKU_VHOST_ENABLE" | debconf-set-selections \ + && echo "dokku dokku/web_config boolean $DOKKU_WEB_CONFIG" | debconf-set-selections \ + && curl -sSL https://packagecloud.io/dokku/dokku/gpgkey | apt-key add - \ + && echo "deb https://packagecloud.io/dokku/dokku/ubuntu/ bionic main" | tee /etc/apt/sources.list.d/dokku.list \ + && apt-get update -qq \ + && apt-get install --no-install-recommends --only-upgrade -y -qq openssl openssh-server \ + && apt --no-install-recommends -qq -y install rsync /tmp/dokku.deb \ + && apt-get purge -y -q syslog-ng-core \ + && apt-get autoremove -y -q \ + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* + +WORKDIR /tmp + +COPY ./docker . + +RUN \ + rsync -a /tmp/ / \ + && rm -rf /tmp/* \ + && rm /etc/runit/runsvdir/default/sshd/down \ + && chown -R dokku:dokku /home/dokku/ \ + && mkdir -p /skel/etc /skel/home /skel/var/lib/dokku /var/log/services \ + && mv /etc/ssh /skel/etc/ssh \ + && mv /home/dokku /skel/home/dokku \ + && mv /var/lib/dokku/config /skel/var/lib/dokku/config \ + && mv /var/lib/dokku/data /skel/var/lib/dokku/data \ + && ln -sf /mnt/dokku/etc/ssh /etc/ssh \ + && ln -sf /mnt/dokku/home/dokku /home/dokku \ + && ln -sf /mnt/dokku/var/lib/dokku/config /var/lib/dokku/config \ + && ln -sf /mnt/dokku/var/lib/dokku/data /var/lib/dokku/data \ + && mv /etc/my_init.d/00_regen_ssh_host_keys.sh /etc/my_init.d/15_regen_ssh_host_keys \ + && rm /etc/nginx/sites-enabled/default /usr/share/nginx/html/index.html /etc/my_init.d/10_syslog-ng.init \ + && sed -i '/imklog/d' /etc/rsyslog.conf \ + && rm /var/log/btmp /var/log/wtmp /var/log/*log /var/log/apt/* /var/log/dokku/* /var/log/nginx/* diff --git a/contrib/dokku-docker-bin.sh b/contrib/dokku-docker-bin.sh new file mode 100755 index 000000000..3bc362322 --- /dev/null +++ b/contrib/dokku-docker-bin.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $DOKKU_TRACE ]] && set -x && DOKKU_DOCKER_ENV="--env DOKKU_TRACE=on" +DOKKU_DOCKER_CONTAINER_NAME=${DOKKU_DOCKER_CONTAINER_NAME:=dokku} + +# TODO: handle cases where we need a tty +# shellcheck disable=SC2086 +docker exec $DOKKU_DOCKER_ENV -i "$DOKKU_DOCKER_CONTAINER_NAME" dokku "$@" diff --git a/contrib/release-dokku b/contrib/release-dokku index f88f01a92..f56d4e564 100755 --- a/contrib/release-dokku +++ b/contrib/release-dokku @@ -206,13 +206,15 @@ fn-repo-update() { fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" contrib/dokku-installer.py fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" debian/control + fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" Dockerfile fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/advanced-usage/plugin-management.md fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/assets/favicons/browserconfig.xml fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/assets/favicons/manifest.json fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/assets/style.css fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/development/release-process.md - fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/home.html + fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/getting-started/install/docker.md fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/getting-started/installation.md + fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/home.html fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/template.html fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" README.md @@ -317,6 +319,13 @@ fn-require-bin() { fi } +fn-build-docker-image() { + declare desc="Builds the dokku docker image and tags it with the given version" + declare VERSION="$1" + docker build -t "dokku/dokku:$VERSION" . + docker push "dokku/dokku:$VERSION" +} + main() { declare RELEASE="$1" local CURRENT_VERSION NEXT_VERSION IS_RELEASE @@ -358,12 +367,14 @@ main() { if [[ "$RELEASE" != "build" ]]; then fn-publish-package "$IS_RELEASE" "deb" "build/dokku_${NEXT_VERSION}_amd64.deb" || log-fail "Error publishing deb package" fn-publish-package "$IS_RELEASE" "rpm" "build/dokku-${NEXT_VERSION}-1.x86_64.rpm" || log-fail "Error publishing rpm package" + fn-build-docker-image "$NEXT_VERSION" || log-fail "Error building docker image" fn-repo-push-tags "$IS_RELEASE" fi if [[ "$IS_RELEASE" != "true" ]]; then git reset -q HEAD plugins/*/plugin.toml git checkout -- plugins/*/plugin.toml + cp "build/dokku_${NEXT_VERSION}_amd64.deb" build/dokku.deb fi echo "build/dokku_${NEXT_VERSION}_amd64.deb" >build/deb-filename diff --git a/debian/postinst b/debian/postinst index 789cbb50a..0cc555dda 100755 --- a/debian/postinst +++ b/debian/postinst @@ -33,11 +33,14 @@ case "$1" in configure) mandb [ ! -x /usr/bin/docker.io ] || ln -sf /usr/bin/docker.io /usr/local/bin/docker - modprobe aufs || echo "WARNING: Restart server to finish installing dokku!" + if [[ -f /sbin/modprobe ]]; then + modprobe aufs || echo "WARNING: Restart server to finish installing dokku!" + fi call-sshcommand create dokku /usr/bin/dokku egrep -i "^docker" /etc/group || groupadd docker usermod -aG docker dokku + mkdir -p ${DOKKU_ROOT}/.dokkurc echo "Setting up storage directories" mkdir -p ${DOKKU_LIB_ROOT}/data ${DOKKU_LIB_ROOT}/data/storage diff --git a/docker/etc/cron.d/dokku-retire b/docker/etc/cron.d/dokku-retire new file mode 100644 index 000000000..ff81b231b --- /dev/null +++ b/docker/etc/cron.d/dokku-retire @@ -0,0 +1,4 @@ +PATH=/usr/local/bin:/usr/bin:/bin +SHELL=/bin/bash + +*/5 * * * * root /usr/bin/dokku ps:retire >> /var/log/dokku/retire.log 2>&1 diff --git a/docker/etc/logrotate.d/services b/docker/etc/logrotate.d/services new file mode 100644 index 000000000..f64cc3925 --- /dev/null +++ b/docker/etc/logrotate.d/services @@ -0,0 +1,9 @@ +/var/log/services/* { + daily + missingok + rotate 7 + compress + delaycompress + notifempty + copytruncate +} diff --git a/docker/etc/my_init.d/10_dokku_init b/docker/etc/my_init.d/10_dokku_init new file mode 100755 index 000000000..7caff134b --- /dev/null +++ b/docker/etc/my_init.d/10_dokku_init @@ -0,0 +1,62 @@ +#!/bin/bash +set -eo pipefail + +log-info() { + declare desc="Log info formatter" + echo " $*" 1>&2 +} + +log-fail() { + declare desc="Log fail formatter" + echo "! $*" 1>&2 + exit 1 +} + +main() { + if [[ ! -d /mnt/dokku ]]; then + log-info "Creating missing /mnt/dokku" + mkdir -p /mnt/dokku + fi + + directories=("/etc/ssh" "/home/dokku" "/var/lib/dokku/config" "/var/lib/dokku/data") + for dir in "${directories[@]}"; do + if [[ ! -e "$dir" ]]; then + log-info "Copying ${dir} skel into place" + mkdir -p "/mnt/dokku${dir}" + rsync -a "/skel${dir}/" "${dir}/" || log-fail "Unable to copy ${dir} skel into place" + fi + + # chown mount directories to "dokku:dokku" + if [[ "$dir" != "/etc/ssh" ]]; then + find "$dir" -print0 | xargs -0 chown -h dokku:dokku + fi + done + + if [[ -f /mnt/dokku/plugin-list ]]; then + while read line; do + dokku plugin:install "$(echo "$line" | awk '{print $2}')" "$(echo "$line" | cut -d':' -f1)" + done "/home/dokku/.dokkurc/DOCKER_BIN" + fi + + if [[ ! -f /mnt/dokku/etc/nginx/dhparam.pem ]]; then + mkdir -p /mnt/dokku/etc/nginx + openssl dhparam -out /mnt/dokku/etc/nginx/dhparam.pem 2048 + fi + + cp -f /mnt/dokku/etc/nginx/dhparam.pem /etc/nginx/dhparam.pem + chown root:root /etc/nginx/dhparam.pem + chown root:root /etc/nginx/conf.d +} + +main "$@" diff --git a/docker/etc/runit/runsvdir/default/dokku-restore/finish b/docker/etc/runit/runsvdir/default/dokku-restore/finish new file mode 100755 index 000000000..ea80c20c0 --- /dev/null +++ b/docker/etc/runit/runsvdir/default/dokku-restore/finish @@ -0,0 +1,15 @@ +#!/bin/bash + +exec >>/var/log/services/dokku-restore +exec 2>&1 + +if [[ "$1" -ne 0 ]]; then + echo "Error restoring dokku apps! Retrying in 30 seconds..." + exec sleep 30 + exit 0 +fi + +echo "Done restoring dokku apps." +exec sleep infinity + +exit 0 diff --git a/docker/etc/runit/runsvdir/default/dokku-restore/run b/docker/etc/runit/runsvdir/default/dokku-restore/run new file mode 100755 index 000000000..4287517ac --- /dev/null +++ b/docker/etc/runit/runsvdir/default/dokku-restore/run @@ -0,0 +1,9 @@ +#!/bin/bash + +exec >>/var/log/services/dokku-restore +exec 2>&1 + +echo "Running dokku-restore" +cd /tmp || exit 1 + +exec dokku ps:restore diff --git a/docker/etc/runit/runsvdir/default/nginx/run b/docker/etc/runit/runsvdir/default/nginx/run new file mode 100755 index 000000000..3328faaaf --- /dev/null +++ b/docker/etc/runit/runsvdir/default/nginx/run @@ -0,0 +1,7 @@ +#!/bin/bash + +exec >>/var/log/services/nginx +exec 2>&1 + +echo "Running nginx" +exec /usr/sbin/nginx -c /etc/nginx/nginx.conf -g "daemon off;" diff --git a/docker/etc/runit/runsvdir/default/rsyslog/run b/docker/etc/runit/runsvdir/default/rsyslog/run new file mode 100755 index 000000000..9a84a59ed --- /dev/null +++ b/docker/etc/runit/runsvdir/default/rsyslog/run @@ -0,0 +1,7 @@ +#!/bin/bash + +exec >>/var/log/services/rsyslog +exec 2>&1 + +echo "Running rsyslog" +exec /usr/sbin/rsyslogd -n diff --git a/docker/etc/sudoers.d/dokku-docker b/docker/etc/sudoers.d/dokku-docker new file mode 100644 index 000000000..ea099f997 --- /dev/null +++ b/docker/etc/sudoers.d/dokku-docker @@ -0,0 +1 @@ +dokku ALL=NOPASSWD:SETENV:/usr/bin/docker diff --git a/docker/usr/local/bin/docker b/docker/usr/local/bin/docker new file mode 100755 index 000000000..dcebde400 --- /dev/null +++ b/docker/usr/local/bin/docker @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -eo pipefail +[[ $TRACE ]] && set -x + +main() { + declare desc="re-runs docker commands as sudo" + local DOCKER_BIN="" + if [[ -x "/usr/bin/docker" ]]; then + DOCKER_BIN="/usr/bin/docker" + fi + + if [[ -z "$DOCKER_BIN" ]]; then + echo "! No docker binary found" 1>&2 + exit 1 + fi + + sudo -E "$DOCKER_BIN" "$@" +} + +main "$@" diff --git a/docs/getting-started/install/azure.md b/docs/getting-started/install/azure.md index 6d61ddda9..a9beb19c5 100644 --- a/docs/getting-started/install/azure.md +++ b/docs/getting-started/install/azure.md @@ -1,4 +1,4 @@ -# Microsoft Azure +# Microsoft Azure Installation Notes 1. If you don't already have one [generate an SSH key pair](https://help.github.com/articles/generating-ssh-keys/). diff --git a/docs/getting-started/install/digitalocean.md b/docs/getting-started/install/digitalocean.md index 2d9462413..caf2a717b 100644 --- a/docs/getting-started/install/digitalocean.md +++ b/docs/getting-started/install/digitalocean.md @@ -1,4 +1,4 @@ -# DigitalOcean Droplet +# DigitalOcean Droplet Installation Notes [DigitalOcean](https://www.digitalocean.com/products/compute/) offers a pre-installed Dokku image. You can run this image on any sized Droplet, although larger Droplets will allow you to run larger applications. diff --git a/docs/getting-started/install/docker.md b/docs/getting-started/install/docker.md new file mode 100644 index 000000000..cb03f5622 --- /dev/null +++ b/docs/getting-started/install/docker.md @@ -0,0 +1,54 @@ +# Docker Installation Notes + +Pull the dokku/dokku image: + +```shell +docker pull dokku/dokku:v0.17.7 +``` + +Next, run the image. + +```shell +docker run \ + --env DOKKU_HOSTNAME=dokku.me \ + --name dokku \ + --publish 3022:22 \ + --publish 8080:80 \ + --publish 8443:443 \ + --volume /var/lib/dokku:/mnt/dokku \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + dokku/dokku:v0.17.7 +``` + +Dokku is run with the following options: + +- The global hostname is set to `dokku.me` on boot. +- The container name is dokku. +- Container SSH port 22 is exposed on the host as 3022. +- Container HTTP port 80 is exposed on the host as 8080. +- Container HTTPS port 443 is exposed on the host as 8443. +- Data within the container is stored on the host within the `/var/lib/dokku` directory. +- The docker socket is mounted into container + +Application repositories, plugin config, and plugin data is persisted to disk within the specified host directory for `/var/lib/dokku`. + +To install custom plugins, create a `plugin-list` file in the host's `/var/lib/dokku` directory. The plugins listed herein will be automatically installed by Dokku on container boot. This file should be the following format: + +```yaml +plugin_name: repository_url +``` + +An example for installing the postgres and redis plugins follows: + +```yaml +postgres: https://github.com/dokku/dokku-postgres.git +redis: https://github.com/dokku/dokku-redis.git +``` + +To initialize ssh-keys within the container, use `docker exec` to enter the container and run the appropriate ssh-keys commands. + +```shell +docker exec -it dokku bash +``` + +Please see the [user management documentation](/docs/deployment/user-management.md) for more information. diff --git a/docs/getting-started/install/dreamhost.md b/docs/getting-started/install/dreamhost.md index 0f4d005f2..a664d94f5 100644 --- a/docs/getting-started/install/dreamhost.md +++ b/docs/getting-started/install/dreamhost.md @@ -1,4 +1,4 @@ -# Install Dokku on DreamHost Cloud Server with cloud-init +# DreamHost Cloud Server Installation Notes Cloud-init script can be used to automate installation of Dokku on Dreamhost (or any other OpenStack-compatible cloud with minimal diff --git a/docs/getting-started/install/vagrant.md b/docs/getting-started/install/vagrant.md index 3ea1e9f72..5b8055ed6 100644 --- a/docs/getting-started/install/vagrant.md +++ b/docs/getting-started/install/vagrant.md @@ -1,4 +1,4 @@ -# Install Dokku using Vagrant +# Vagrant Installation Notes 1. Download and install [VirtualBox](https://www.virtualbox.org/wiki/Downloads). diff --git a/plugins/scheduler-docker-local/check-deploy b/plugins/scheduler-docker-local/check-deploy index 148c427f7..f3d8a96f8 100755 --- a/plugins/scheduler-docker-local/check-deploy +++ b/plugins/scheduler-docker-local/check-deploy @@ -87,7 +87,7 @@ scheduler-docker-local-check-deploy() { local CHECK_DEPLOY_TMP_WORK_DIR=$(mktemp -d "/tmp/dokku-${FUNCNAME[0]}.XXXX") "$DOCKER_BIN" cp "$DOKKU_APP_CONTAINER_ID:/app/CHECKS" "$CHECK_DEPLOY_TMP_WORK_DIR" 2>/dev/null || true - local FILENAME=${CHECK_DEPLOY_TMP_WORK_DIR}/CHECKS + local CHECKS_FILENAME=${CHECK_DEPLOY_TMP_WORK_DIR}/CHECKS checks_check_deploy_cleanup() { declare desc="cleans up CHECK_DEPLOY_TMP_WORK_DIR and print container output" @@ -101,7 +101,7 @@ scheduler-docker-local-check-deploy() { } trap "checks_check_deploy_cleanup $DOKKU_APP_CONTAINER_ID" RETURN INT TERM EXIT - if [[ ! -s "${CHECK_DEPLOY_TMP_WORK_DIR}/CHECKS" ]] || [[ "$DOKKU_APP_CONTAINER_TYPE" != "web" ]]; then + if [[ ! -s "${CHECKS_FILENAME}" ]] || [[ "$DOKKU_APP_CONTAINER_TYPE" != "web" ]]; then # We allow custom check for web instances only if [[ "$DOKKU_APP_CONTAINER_TYPE" == "web" ]]; then dokku_log_verbose "For more efficient zero downtime deployments, create a file CHECKS." @@ -131,12 +131,18 @@ scheduler-docker-local-check-deploy() { fi # ensure CHECKS file has trailing newline - if [[ "$(tail -c1 "$FILENAME")" != "" ]]; then - echo "" >>"$FILENAME" + if [[ "$(tail -c1 "$CHECKS_FILENAME")" != "" ]]; then + # workaround for CHECKS file when owner is root. seems to only happen when running inside docker + if [[ "$(stat -c %u "$CHECKS_FILENAME")" == "0" ]]; then + local NEW_CHECKS_FILENAME=${CHECK_DEPLOY_TMP_WORK_DIR}/$(mktemp dokku-${FUNCNAME[0]}-CHECKS.XXXX) + cat ${CHECKS_FILENAME} >${NEW_CHECKS_FILENAME} + CHECKS_FILENAME=$NEW_CHECKS_FILENAME + fi + echo "" >>"$CHECKS_FILENAME" fi # Reads name/value pairs, sets the WAIT and TIMEOUT variables - exec <"$FILENAME" + exec <"$CHECKS_FILENAME" local line local NAME local VALUE @@ -173,7 +179,7 @@ scheduler-docker-local-check-deploy() { local CURL_OPTIONS+=" -H X-Forwarded-Proto:https" fi - exec <"$FILENAME" + exec <"$CHECKS_FILENAME" local CHECK_URL local EXPECTED while read -r CHECK_URL EXPECTED; do diff --git a/rpm/dokku.postinst b/rpm/dokku.postinst index 4658c75b1..182e645c0 100644 --- a/rpm/dokku.postinst +++ b/rpm/dokku.postinst @@ -9,6 +9,7 @@ setup-user() { touch "$DOKKU_ROOT/.ssh/authorized_keys" chown -R dokku:dokku "$DOKKU_ROOT/.ssh" usermod -aG docker dokku + mkdir -p "$DOKKU_ROOT/.dokkurc" } setup-storage() { diff --git a/tests.mk b/tests.mk index c42dc22b3..c3dfc5fbd 100644 --- a/tests.mk +++ b/tests.mk @@ -1,4 +1,5 @@ SYSTEM := $(shell sh -c 'uname -s 2>/dev/null') +DOKKU_SSH_PORT ?= 22 bats: ifeq ($(SYSTEM),Darwin) @@ -42,13 +43,12 @@ else endif endif -ci-dependencies: bats shellcheck shfmt xmlstarlet +ci-dependencies: bats shellcheck xmlstarlet setup-deploy-tests: - mkdir -p /home/dokku ifdef ENABLE_DOKKU_TRACE - echo "-----> Enabling tracing" - echo "export DOKKU_TRACE=1" >> /home/dokku/dokkurc + echo "-----> Enable dokku trace" + dokku trace:on endif @echo "Setting dokku.me in /etc/hosts" sudo /bin/bash -c "[[ `ping -c1 dokku.me >/dev/null 2>&1; echo $$?` -eq 0 ]] || echo \"127.0.0.1 dokku.me *.dokku.me www.test.app.dokku.me\" >> /etc/hosts" @@ -61,11 +61,14 @@ endif @echo "-----> Setting up ssh config..." ifneq ($(shell ls /root/.ssh/config >/dev/null 2>&1 ; echo $$?),0) - echo "Host dokku.me \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config + echo "Host dokku.me \\r\\n Port $(DOKKU_SSH_PORT) \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config echo "Host 127.0.0.1 \\r\\n Port 22333 \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config else ifeq ($(shell grep dokku.me /root/.ssh/config),) - echo "Host dokku.me \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config + echo "Host dokku.me \\r\\n Port $(DOKKU_SSH_PORT) \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config echo "Host 127.0.0.1 \\r\\n Port 22333 \\r\\n RequestTTY yes \\r\\n IdentityFile /root/.ssh/dokku_test_rsa" >> /root/.ssh/config +else + sed --in-place 's/Port 22 \r/Port $(DOKKU_SSH_PORT) \r/g' /root/.ssh/config + cat /root/.ssh/config endif ifneq ($(wildcard /etc/ssh/sshd_config),) @@ -80,30 +83,46 @@ endif sudo sshcommand acl-remove dokku test cat /root/.ssh/dokku_test_rsa.pub | sudo sshcommand acl-add dokku test - @echo "-----> Intitial SSH connection to populate known_hosts..." - ssh -o StrictHostKeyChecking=no dokku@dokku.me help >/dev/null - ssh -o StrictHostKeyChecking=no dokku@127.0.0.1 help >/dev/null - ifeq ($(shell grep dokku.me /home/dokku/VHOST 2>/dev/null),) @echo "-----> Setting default VHOST to dokku.me..." echo "dokku.me" > /home/dokku/VHOST endif +ifeq ($(DOKKU_SSH_PORT), 22) + $(MAKE) prime-ssh-known-hosts +endif + +setup-docker-deploy-tests: setup-deploy-tests +ifdef ENABLE_DOKKU_TRACE + echo "-----> Enable dokku trace" + docker exec -ti dokku bash -c "dokku trace:on" +endif + docker exec -ti dokku bash -c "sshcommand acl-remove dokku test" + docker exec -ti dokku bash -c "echo `cat /root/.ssh/dokku_test_rsa.pub` | sshcommand acl-add dokku test" + $(MAKE) prime-ssh-known-hosts + +prime-ssh-known-hosts: + @echo "-----> Intitial SSH connection to populate known_hosts..." + ssh -o StrictHostKeyChecking=no dokku@dokku.me help >/dev/null + ssh -o StrictHostKeyChecking=no dokku@127.0.0.1 help >/dev/null lint-setup: @mkdir -p test-results/shellcheck tmp/shellcheck @find . -not -path '*/\.*' -not -path './debian/*' -type f | xargs file | grep text | awk -F ':' '{ print $$1 }' | xargs head -n1 | egrep -B1 "bash" | grep "==>" | awk '{ print $$2 }' > tmp/shellcheck/test-files @cat tests/shellcheck-exclude | sed -n -e '/^# SC/p' | cut -d' ' -f2 | paste -d, -s > tmp/shellcheck/exclude -lint: lint-setup - # verifying via shfmt - # shfmt -l -bn -ci -i 2 -d . - @shfmt -l -bn -ci -i 2 -d . - +lint-ci: lint-setup # these are disabled due to their expansive existence in the codebase. we should clean it up though @cat tests/shellcheck-exclude | sed -n -e '/^# SC/p' @echo linting... @cat tmp/shellcheck/test-files | xargs shellcheck -e $(shell cat tmp/shellcheck/exclude) | tests/shellcheck-to-junit --output test-results/shellcheck/results.xml --files tmp/shellcheck/test-files --exclude $(shell cat tmp/shellcheck/exclude) +lint-shfmt: shfmt + # verifying via shfmt + # shfmt -l -bn -ci -i 2 -d . + @shfmt -l -bn -ci -i 2 -d . + +lint: lint-shfmt lint-ci + ci-go-coverage: docker run --rm -ti \ -e DOKKU_ROOT=/home/dokku \ @@ -242,3 +261,5 @@ test-ci: @mkdir -p test-results/bats @cd tests/unit && echo "executing tests: $(shell cd tests/unit ; circleci tests glob *.bats | circleci tests split --split-by=timings --timings-type=classname | xargs)" cd tests/unit && bats --formatter bats-format-junit -e -T -o ../../test-results/bats $(shell cd tests/unit ; circleci tests glob *.bats | circleci tests split --split-by=timings --timings-type=classname | xargs) + +test-ci-docker: setup-docker-deploy-tests deploy-test-checks-root deploy-test-config deploy-test-multi deploy-test-go-fail-predeploy deploy-test-go-fail-postdeploy diff --git a/tests/ci/setup.sh b/tests/ci/setup.sh index 190f2812e..b5e8e5099 100755 --- a/tests/ci/setup.sh +++ b/tests/ci/setup.sh @@ -4,6 +4,8 @@ set -eo pipefail readonly ROOT_DIR="$(cd "$(dirname "$(dirname "$(dirname "${BASH_SOURCE[0]}")")")" && pwd)" install_dependencies() { + echo "=====> install_dependencies on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + mkdir -p "$ROOT_DIR/build/" HEROKUISH_VERSION=$(grep HEROKUISH_VERSION "${ROOT_DIR}/deb.mk" | head -n1 | cut -d' ' -f3) HEROKUISH_PACKAGE_NAME="herokuish_${HEROKUISH_VERSION}_amd64.deb" @@ -30,20 +32,27 @@ install_dependencies() { sudo apt-get -qq -y install cgroupfs-mount nginx sudo cp "${ROOT_DIR}/tests/dhparam.pem" /etc/nginx/dhparam.pem - sudo dpkg -i "${ROOT_DIR}/build/$HEROKUISH_PACKAGE_NAME" - sudo dpkg -i "${ROOT_DIR}/build/$PLUGN_PACKAGE_NAME" - sudo dpkg -i "${ROOT_DIR}/build/$SSHCOMMAND_PACKAGE_NAME" - sudo dpkg -i "${ROOT_DIR}/build/$SIGIL_PACKAGE_NAME" - sudo dpkg -i "${ROOT_DIR}/build/$PROCFILE_UTIL_PACKAGE_NAME" + sudo dpkg -i "${ROOT_DIR}/build/$HEROKUISH_PACKAGE_NAME" \ + "${ROOT_DIR}/build/$PLUGN_PACKAGE_NAME" \ + "${ROOT_DIR}/build/$SSHCOMMAND_PACKAGE_NAME" \ + "${ROOT_DIR}/build/$SIGIL_PACKAGE_NAME" \ + "${ROOT_DIR}/build/$PROCFILE_UTIL_PACKAGE_NAME" +} + +build_dokku() { + echo "=====> build_dokku on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + "${ROOT_DIR}/contrib/release-dokku" build } install_dokku() { + echo "=====> install_dokku on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + if [[ "$FROM_SOURCE" == "true" ]]; then sudo -E CI=true make -e install return fi - "${ROOT_DIR}/contrib/release-dokku" build + build_dokku echo "dokku dokku/hostname string dokku.me" | sudo debconf-set-selections echo "dokku dokku/key_file string /root/.ssh/id_rsa.pub" | sudo debconf-set-selections @@ -54,6 +63,45 @@ install_dokku() { sudo dpkg -i "$(cat "${ROOT_DIR}/build/deb-filename")" } +build_dokku_docker_image() { + echo "=====> build_dokku_docker_image on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + docker build -t dokku/dokku:test . +} + +run_dokku_container() { + echo "=====> run_dokku_container on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + docker run -d \ + --env DOKKU_HOSTNAME=dokku.me \ + --name dokku \ + --publish 3022:22 \ + --publish 80:80 \ + --publish 443:443 \ + --volume /var/lib/dokku:/mnt/dokku \ + --volume /var/run/docker.sock:/var/run/docker.sock \ + dokku/dokku:test + + check_container +} + +check_container() { + echo "=====> check_container on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" + local is_up + local cnt=0 + while true; do + echo "$(date) [count: $cnt]: waiting for dokku startup" + is_up=$( + docker exec -ti dokku ps -ef | grep "/usr/sbin/sshd -D" >/dev/null 2>&1 + echo $? + ) + if [[ $is_up -eq 0 ]]; then + echo "" && docker logs dokku + break + fi + sleep 2 + cnt=$((cnt + 1)) + done +} + # shellcheck disable=SC2120 setup_circle() { echo "=====> setup_circle on CIRCLE_NODE_INDEX: $CIRCLE_NODE_INDEX" @@ -66,8 +114,6 @@ setup_circle() { install_dokku sudo -E make -e setup-deploy-tests - bash --version - docker version lsb_release -a # setup .dokkurc sudo -E mkdir -p /home/dokku/.dokkurc @@ -77,6 +123,16 @@ setup_circle() { sudo docker pull node:4 } -# shellcheck disable=SC2119 -setup_circle -exit $? +case "$1" in + docker) + sudo /etc/init.d/nginx stop + build_dokku_docker_image + run_dokku_container + ;; + *) + # shellcheck disable=SC2119 + setup_circle + exit $? + ;; +esac +