Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cb8b108db | ||
|
|
9aef43d5a0 | ||
|
|
8dadc4cf50 | ||
|
|
45518fce6c | ||
|
|
b21f4b6470 | ||
|
|
c52f60f9d7 | ||
|
|
c815d732eb | ||
|
|
18849c085a | ||
|
|
cb62958095 | ||
|
|
4fcfad5df5 | ||
|
|
5101096518 | ||
|
|
afef3b94d5 | ||
|
|
73a84f90c5 | ||
|
|
918bc9efe8 | ||
|
|
98619733b2 | ||
|
|
2fb712c3a2 | ||
|
|
0fa6503034 | ||
|
|
fab97a377f | ||
|
|
811bf2f9c4 | ||
|
|
20497dabb4 | ||
|
|
0b430af077 | ||
|
|
e42e7c3694 | ||
|
|
eeef120433 | ||
|
|
8950571acb | ||
|
|
a72a82e29b | ||
|
|
b6adc23bdd | ||
|
|
8677aadad7 | ||
|
|
a4b8e59c3f | ||
|
|
3a5d0716d4 | ||
|
|
b54a5b3f67 | ||
|
|
5b33bd5eda | ||
|
|
6d55dd8884 | ||
|
|
0fae350256 | ||
|
|
90015ab594 | ||
|
|
28281ae4d4 | ||
|
|
4723b27f2c | ||
|
|
de338f4da5 | ||
|
|
d52eac7b35 | ||
|
|
4d01e677ee | ||
|
|
33daa88197 | ||
|
|
607a3d88ae | ||
|
|
be082e2fe0 | ||
|
|
27bd578405 | ||
|
|
0962ebeadb | ||
|
|
95d9ca8945 | ||
|
|
e71cd7a939 | ||
|
|
4bf301c913 | ||
|
|
0ea9e398bb | ||
|
|
2a6ea5d979 | ||
|
|
b8cde503c2 | ||
|
|
89c8e1c6a5 | ||
|
|
6c66e9850c | ||
|
|
fbcc8d8d6c | ||
|
|
e2bbdc968d | ||
|
|
ed7d5623ad | ||
|
|
217e491e59 | ||
|
|
101414dcd3 | ||
|
|
edda1e6567 | ||
|
|
dd7439095a | ||
|
|
9e3ae9c37c | ||
|
|
b1bd2c17a0 | ||
|
|
a939296981 | ||
|
|
23cfccf424 | ||
|
|
eae2876187 | ||
|
|
8730bbf0a9 | ||
|
|
1f5e5e5c14 | ||
|
|
e8b6e33934 | ||
|
|
9ee6c7aab6 | ||
|
|
22a8b914d2 | ||
|
|
dfab96c72e | ||
|
|
7c8fba8fc1 | ||
|
|
85f4023965 | ||
|
|
e9ee47a7c7 | ||
|
|
a7c6127f2b | ||
|
|
4e6a699140 | ||
|
|
f71644faf6 | ||
|
|
9a6306c53b | ||
|
|
83d98fb6fb | ||
|
|
c501574753 | ||
|
|
f0efdd2ed4 | ||
|
|
177b45c49b | ||
|
|
fc31b28ab6 | ||
|
|
e61475c7ea | ||
|
|
c92c0fce37 | ||
|
|
1a0c308b65 | ||
|
|
dffbad49b4 | ||
|
|
b6dffaabee | ||
|
|
8d83803763 | ||
|
|
85e5bd7c86 | ||
|
|
7ba063c6bb |
@@ -14,3 +14,8 @@ indent_size = 4
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
[*.go]
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
71
HISTORY.md
71
HISTORY.md
@@ -1,5 +1,72 @@
|
||||
# History
|
||||
|
||||
## 0.9.4
|
||||
|
||||
### Documentation
|
||||
|
||||
- #2710: @josegonzalez Quiet output for git-related commands
|
||||
|
||||
## 0.9.3
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #2706: @josegonzalez fix: ensure nginx conf.d directory exists when running nginx install hook
|
||||
- #2701: @scjody Set SSH_USER for root commands
|
||||
|
||||
### New Features
|
||||
|
||||
- #2708: @josegonzalez Document that we will not do buildpack support in the issue tracker
|
||||
|
||||
### Documentation
|
||||
|
||||
- #2709: @michaelshobbs increase CURL_TIMEOUT and CURL_CONNECT_TIMEOUT defaults
|
||||
- #2699: @mbreit Add support for git >= 2.11
|
||||
|
||||
## 0.9.2
|
||||
|
||||
### New Features
|
||||
|
||||
- #2698: @josegonzalez docs: Document that we only care about specific sections
|
||||
- #2697: @callahad Restore installer note regarding AUFS on Linode
|
||||
- #2694: @scjody Add documentation note re: git-pre-pull vs. auth
|
||||
|
||||
### Documentation
|
||||
|
||||
- #2695: @michaelshobbs add tests for pre/post deploy tasks
|
||||
|
||||
## 0.9.1
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #2693: @josegonzalez fix: explicitly chown data and data/storage directories
|
||||
|
||||
## 0.9.0
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- #2691: @josegonzalez Fix package building when golang binaries are available
|
||||
- #2671: @znz Fix variable name
|
||||
- #2672: @callahad Fix logrotate on Debian
|
||||
- #2666: @josegonzalez Use correct flag for build arguments when installing herokuish
|
||||
- #2664: @pvalentim Fix remote name when using --remote option with apps:create
|
||||
|
||||
### New Features
|
||||
|
||||
- #2689: @mbreit Add dokku-monit to community plugin list
|
||||
- #2683: @josegonzalez Ensure we have an example for adding keys as another user
|
||||
- #2682: @josegonzalez Clarify supported stanzas in app.json
|
||||
- #2679: @callahad Remove unnecessary Linode-specific instructions
|
||||
- #2670: @znz Remove duplicated `(i.e. `
|
||||
|
||||
### Documentation
|
||||
|
||||
- #2685: @josegonzalez Pass shellcheck on os x
|
||||
- #2677: @callahad Prefer HTTP2 to SPDY in nginx-vhosts
|
||||
- #2673: @michaelshobbs Update to herokuish 0.3.27
|
||||
- #2674: @michaelshobbs Update sshcommand to 0.7.0
|
||||
- #2654: @ebeigarts Enable nginx and docker on system startup when using bootstrap.sh on CentOS
|
||||
- #2546: @michaelshobbs Convert repo plugin to golang
|
||||
|
||||
## 0.8.2
|
||||
|
||||
### New Features
|
||||
@@ -1091,7 +1158,7 @@ Thanks to the *many* contributors for making this release our best release so fa
|
||||
- #1473: @josegonzalez Handle crashing containers by using restart=on-failure policy
|
||||
- #1476: @michaelshobbs Support static nginx port when deploying without an application VHOST
|
||||
- #1476: nginx proxy without VHOST
|
||||
- #1477: @arthurschreiber Support removing config variables that contain `\n`.
|
||||
- #1477: @arthurschreiber Support removing config variables containing newlines.
|
||||
|
||||
### Documentation
|
||||
|
||||
@@ -1237,7 +1304,7 @@ This release pegs Dokku to Docker 1.6.2. Docker 1.7.0 introduced changes in `doc
|
||||
|
||||
### New Features
|
||||
|
||||
- #1245: @arthurschreiber Support config variables containing `\n`
|
||||
- #1245: @arthurschreiber Support config variables containing newlines
|
||||
- #1257: @josegonzalez Split nginx ssl logs by $APP
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
> If you need help figuring out how to use a specific buildpack, or are having issues using multiple buildpacks, please see our [irc or slack channels](http://dokku.viewdocs.io/dokku/getting-started/where-to-get-help/#the-irc-and-slack-channels). Issues pertaining to buildpacks may be closed and locked.
|
||||
|
||||
Description of problem:
|
||||
|
||||
|
||||
|
||||
28
Makefile
28
Makefile
@@ -8,6 +8,7 @@ PREBUILT_STACK_URL ?= gliderlabs/herokuish:latest
|
||||
DOKKU_LIB_ROOT ?= /var/lib/dokku
|
||||
PLUGINS_PATH ?= ${DOKKU_LIB_ROOT}/plugins
|
||||
CORE_PLUGINS_PATH ?= ${DOKKU_LIB_ROOT}/core-plugins
|
||||
PLUGIN_MAKE_TARGET ?= build-in-docker
|
||||
|
||||
# If the first argument is "vagrant-dokku"...
|
||||
ifeq (vagrant-dokku,$(firstword $(MAKECMDGOALS)))
|
||||
@@ -23,7 +24,9 @@ else
|
||||
BUILD_STACK_TARGETS = build-in-docker
|
||||
endif
|
||||
|
||||
.PHONY: all apt-update install version copyfiles man-db plugins dependencies sshcommand plugn docker aufs stack count dokku-installer vagrant-acl-add vagrant-dokku
|
||||
include common.mk
|
||||
|
||||
.PHONY: all apt-update install version copyfiles man-db plugins dependencies sshcommand plugn docker aufs stack count dokku-installer vagrant-acl-add vagrant-dokku go-build
|
||||
|
||||
include tests.mk
|
||||
include deb.mk
|
||||
@@ -50,7 +53,24 @@ package_cloud:
|
||||
packer:
|
||||
packer build contrib/packer.json
|
||||
|
||||
go-build:
|
||||
basedir=$(PWD); \
|
||||
for dir in plugins/*; do \
|
||||
if [ -e $$dir/Makefile ]; then \
|
||||
$(MAKE) -e -C $$dir $(PLUGIN_MAKE_TARGET) || exit $$? ;\
|
||||
fi ;\
|
||||
done
|
||||
|
||||
go-clean:
|
||||
basedir=$(PWD); \
|
||||
for dir in plugins/*; do \
|
||||
if [ -e $$dir/Makefile ]; then \
|
||||
$(MAKE) -e -C $$dir clean ;\
|
||||
fi ;\
|
||||
done
|
||||
|
||||
copyfiles:
|
||||
$(MAKE) go-build || exit 1
|
||||
cp dokku /usr/local/bin/dokku
|
||||
mkdir -p ${CORE_PLUGINS_PATH} ${PLUGINS_PATH}
|
||||
rm -rf ${CORE_PLUGINS_PATH}/*
|
||||
@@ -62,11 +82,15 @@ copyfiles:
|
||||
rm -rf ${CORE_PLUGINS_PATH}/$$plugin && \
|
||||
rm -rf ${PLUGINS_PATH}/$$plugin && \
|
||||
cp -R plugins/$$plugin ${CORE_PLUGINS_PATH}/available && \
|
||||
rm -rf ${CORE_PLUGINS_PATH}/available/$$plugin/src && \
|
||||
ln -s ${CORE_PLUGINS_PATH}/available/$$plugin ${PLUGINS_PATH}/available; \
|
||||
find /var/lib/dokku/ -xtype l -delete;\
|
||||
PLUGIN_PATH=${CORE_PLUGINS_PATH} plugn enable $$plugin ;\
|
||||
PLUGIN_PATH=${PLUGINS_PATH} plugn enable $$plugin ;\
|
||||
done
|
||||
done
|
||||
ifndef SKIP_GO_CLEAN
|
||||
$(MAKE) go-clean
|
||||
endif
|
||||
chown dokku:dokku -R ${PLUGINS_PATH} ${CORE_PLUGINS_PATH} || true
|
||||
$(MAKE) addman
|
||||
|
||||
|
||||
@@ -99,8 +99,8 @@ A fresh VM running any of the following operating systems:
|
||||
To install the latest stable release, run the following commands as a user who has access to `sudo`:
|
||||
|
||||
```shell
|
||||
wget https://raw.githubusercontent.com/dokku/dokku/v0.8.2/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.8.2 bash bootstrap.sh
|
||||
wget https://raw.githubusercontent.com/dokku/dokku/v0.9.4/bootstrap.sh
|
||||
sudo DOKKU_TAG=v0.9.4 bash bootstrap.sh
|
||||
```
|
||||
|
||||
You can then proceed to the ip address or domain name associated with your server to complete the web-based installation.
|
||||
|
||||
@@ -118,8 +118,8 @@ install-dokku-from-deb-package() {
|
||||
|
||||
echo "--> Installing docker"
|
||||
if uname -r | grep -q linode; then
|
||||
echo "--> NOTE: Using Linode? Docker might complain about missing AUFS support."
|
||||
echo " See http://dokku.viewdocs.io/dokku/getting-started/install/linode/"
|
||||
echo "--> NOTE: Using Linode? Docker may complain about missing AUFS support."
|
||||
echo " You can safely ignore this warning."
|
||||
echo " Installation will continue in 10 seconds."
|
||||
sleep 10
|
||||
fi
|
||||
@@ -167,6 +167,10 @@ install-dokku-from-rpm-package() {
|
||||
yum -y install herokuish dokku
|
||||
fi
|
||||
|
||||
echo "--> Enabling docker and nginx on system startup"
|
||||
systemctl enable docker
|
||||
systemctl enable nginx
|
||||
|
||||
echo "--> Starting nginx"
|
||||
systemctl start nginx
|
||||
}
|
||||
|
||||
4
common.mk
Normal file
4
common.mk
Normal file
@@ -0,0 +1,4 @@
|
||||
GO_REPO_ROOT := /go/src/github.com/dokku/dokku
|
||||
BUILD_IMAGE := golang:1.7.5
|
||||
|
||||
.PHONY: build-in-docker build clean src-clean
|
||||
@@ -1,34 +0,0 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get -y install gcc git build-essential wget ruby-dev ruby1.9.1 lintian rpm help2man man-db
|
||||
|
||||
RUN command -v fpm > /dev/null || sudo gem install fpm --no-ri --no-rdoc
|
||||
|
||||
WORKDIR /dokku
|
||||
|
||||
COPY Makefile /dokku/
|
||||
|
||||
COPY *.mk /dokku/
|
||||
|
||||
RUN make deb-setup rpm-setup
|
||||
|
||||
COPY . /dokku
|
||||
|
||||
RUN make sshcommand plugn version copyfiles
|
||||
|
||||
ARG DOKKU_VERSION=master
|
||||
ENV DOKKU_VERSION ${DOKKU_VERSION}
|
||||
|
||||
ARG DOKKU_GIT_REV
|
||||
ENV DOKKU_GIT_REV ${DOKKU_GIT_REV}
|
||||
|
||||
ARG IS_RELEASE=false
|
||||
ENV IS_RELEASE ${IS_RELEASE}
|
||||
|
||||
RUN make rpm-herokuish rpm-dokku rpm-plugn rpm-sshcommand rpm-sigil
|
||||
|
||||
RUN mkdir -p /data && cp /tmp/*.rpm /data && ls /data/
|
||||
@@ -1,34 +0,0 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update
|
||||
|
||||
RUN apt-get -y install gcc git build-essential wget ruby-dev ruby1.9.1 lintian rpm help2man man-db
|
||||
|
||||
RUN command -v fpm > /dev/null || sudo gem install fpm --no-ri --no-rdoc
|
||||
|
||||
WORKDIR /dokku
|
||||
|
||||
COPY Makefile /dokku/
|
||||
|
||||
COPY *.mk /dokku/
|
||||
|
||||
RUN make deb-setup rpm-setup
|
||||
|
||||
COPY . /dokku
|
||||
|
||||
RUN make sshcommand plugn version copyfiles
|
||||
|
||||
ARG DOKKU_VERSION=master
|
||||
ENV DOKKU_VERSION ${DOKKU_VERSION}
|
||||
|
||||
ARG DOKKU_GIT_REV
|
||||
ENV DOKKU_GIT_REV ${DOKKU_GIT_REV}
|
||||
|
||||
ARG IS_RELEASE=false
|
||||
ENV IS_RELEASE ${IS_RELEASE}
|
||||
|
||||
RUN make deb-herokuish deb-dokku deb-plugn deb-sshcommand deb-sigil
|
||||
|
||||
RUN mkdir -p /data && cp /tmp/*.deb /data && ls /data/
|
||||
44
contrib/build.Dockerfile
Normal file
44
contrib/build.Dockerfile
Normal file
@@ -0,0 +1,44 @@
|
||||
FROM ubuntu:14.04
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt-get update
|
||||
RUN apt-get -y install gcc git build-essential wget ruby-dev ruby1.9.1 lintian rpm help2man man-db
|
||||
RUN command -v fpm > /dev/null || sudo gem install fpm --no-ri --no-rdoc
|
||||
|
||||
ARG GOLANG_VERSION
|
||||
|
||||
RUN wget -qO /tmp/go${GOLANG_VERSION}.linux-amd64.tar.gz https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-amd64.tar.gz \
|
||||
&& tar -C /usr/local -xzf /tmp/go${GOLANG_VERSION}.linux-amd64.tar.gz
|
||||
|
||||
ARG WORKDIR=/go/src/github.com/dokku/dokku
|
||||
|
||||
WORKDIR ${WORKDIR}
|
||||
|
||||
COPY Makefile ${WORKDIR}/
|
||||
COPY *.mk ${WORKDIR}/
|
||||
|
||||
RUN make deb-setup rpm-setup sshcommand plugn
|
||||
|
||||
COPY . ${WORKDIR}
|
||||
|
||||
ARG PLUGIN_MAKE_TARGET
|
||||
ARG DOKKU_VERSION=master
|
||||
ARG DOKKU_GIT_REV
|
||||
ARG IS_RELEASE=false
|
||||
|
||||
RUN PATH=$PATH:/usr/local/go/bin GOPATH=/go \
|
||||
PLUGIN_MAKE_TARGET=${PLUGIN_MAKE_TARGET} \
|
||||
DOKKU_VERSION=${DOKKU_VERSION} \
|
||||
DOKKU_GIT_REV=${DOKKU_GIT_REV} \
|
||||
IS_RELEASE=${IS_RELEASE} \
|
||||
SKIP_GO_CLEAN=true \
|
||||
make version copyfiles \
|
||||
&& rm -rf plugins/common/*.go plugins/common/glide* plugins/common/vendor/ \
|
||||
&& make deb-herokuish deb-dokku deb-plugn deb-sshcommand deb-sigil \
|
||||
rpm-herokuish rpm-dokku rpm-plugn rpm-sshcommand rpm-sigil
|
||||
|
||||
RUN mkdir -p /data \
|
||||
&& cp /tmp/*.deb /data \
|
||||
&& cp /tmp/*.rpm /data \
|
||||
&& ls -lha /data/
|
||||
@@ -10,7 +10,7 @@ import subprocess
|
||||
import sys
|
||||
import threading
|
||||
|
||||
VERSION = 'v0.8.2'
|
||||
VERSION = 'v0.9.4'
|
||||
|
||||
hostname = ''
|
||||
try:
|
||||
|
||||
@@ -56,7 +56,7 @@ fn-dokku-host() {
|
||||
if [[ -z "$DOKKU_HOST" ]]; then
|
||||
fn-client-help-msg
|
||||
fi
|
||||
|
||||
|
||||
echo "$DOKKU_HOST"
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ main() {
|
||||
else
|
||||
APP="$APP_ARG"
|
||||
fi
|
||||
if git remote add dokku "dokku@$DOKKU_REMOTE_HOST:$APP"; then
|
||||
if git remote add "$DOKKU_GIT_REMOTE" "dokku@$DOKKU_REMOTE_HOST:$APP"; then
|
||||
echo "-----> Dokku remote added at ${DOKKU_REMOTE_HOST} called ${DOKKU_GIT_REMOTE}"
|
||||
echo "-----> Application name is ${APP}"
|
||||
else
|
||||
|
||||
313
contrib/release
Executable file
313
contrib/release
Executable file
@@ -0,0 +1,313 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $TRACE ]] && set -x
|
||||
|
||||
readonly ROOT_DIR="$(cd "$(dirname "$(dirname "${BASH_SOURCE[0]}")")" && pwd)"
|
||||
readonly TMP_WORK_DIR="$(mktemp -d "/tmp/dokku-release.XXXX")"
|
||||
readonly DOKKU_GIT_REV="$(git rev-parse HEAD)"
|
||||
|
||||
trap 'rm -rf "$TMP_WORK_DIR" > /dev/null' RETURN INT TERM EXIT
|
||||
|
||||
log-info() {
|
||||
# shellcheck disable=SC2034
|
||||
declare desc="Log info formatter"
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
log-error() {
|
||||
# shellcheck disable=SC2034
|
||||
declare desc="Log error formatter"
|
||||
echo "! $*" 1>&2
|
||||
}
|
||||
|
||||
log-fail() {
|
||||
# shellcheck disable=SC2034
|
||||
declare desc="Log fail formatter"
|
||||
log-error "$*"
|
||||
exit -1
|
||||
}
|
||||
|
||||
fn-build-dokku() {
|
||||
declare desc="Builds dokku packages within a docker container"
|
||||
declare IS_RELEASE="$1" DOKKU_VERSION="$2"
|
||||
local NAME GOLANG_VERSION
|
||||
|
||||
if [[ -z "$DOKKU_VERSION" ]]; then
|
||||
log-error "Invalid deb file specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
NAME="dokku:build"
|
||||
[[ "$IS_RELEASE" == "true" ]] && NAME="dokku:build-release"
|
||||
[[ -n "$DOKKU_VERSION" ]] || DOKKU_VERSION="master"
|
||||
|
||||
pushd "$ROOT_DIR" >/dev/null
|
||||
GOLANG_VERSION="$(grep BUILD_IMAGE common.mk | cut -d' ' -f3 | cut -d':' -f2)"
|
||||
docker build \
|
||||
--build-arg DOKKU_VERSION="$DOKKU_VERSION" \
|
||||
--build-arg DOKKU_GIT_REV="$DOKKU_GIT_REV" \
|
||||
--build-arg IS_RELEASE="$IS_RELEASE" \
|
||||
--build-arg PLUGIN_MAKE_TARGET="build" \
|
||||
--build-arg GOLANG_VERSION="$GOLANG_VERSION" \
|
||||
-f "contrib/build.Dockerfile" \
|
||||
-t "$NAME" .
|
||||
}
|
||||
|
||||
fn-extract-package() {
|
||||
declare desc="Extract packages from a docker container to the root directory"
|
||||
declare IS_RELEASE="$1" PACKAGE_NAME="$2"
|
||||
local NAME
|
||||
|
||||
if [[ -z "$PACKAGE_NAME" ]]; then
|
||||
log-error "Invalid deb file specified"
|
||||
return 1
|
||||
fi
|
||||
|
||||
NAME="dokku:build"
|
||||
[[ "$IS_RELEASE" == "true" ]] && NAME="dokku:build-release"
|
||||
|
||||
log-info "(extract-package) writing ${PACKAGE_NAME} to correct path"
|
||||
docker run --rm --entrypoint cat "$NAME" "/data/${PACKAGE_NAME}" > "${ROOT_DIR}/${PACKAGE_NAME}"
|
||||
}
|
||||
|
||||
fn-in-array() {
|
||||
declare desc="return true if value ($1) is in list (all other arguments)"
|
||||
|
||||
local e
|
||||
for e in "${@:2}"; do
|
||||
[[ "$e" == "$1" ]] && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
fn-is-release() {
|
||||
declare desc="Checks if a given run is a release run"
|
||||
declare RELEASE="$1"
|
||||
local IS_RELEASE=false
|
||||
if [[ "$RELEASE" == "major" ]] || [[ "$RELEASE" == "minor" ]] || [[ "$RELEASE" == "patch" ]]; then
|
||||
IS_RELEASE=true
|
||||
fi
|
||||
|
||||
echo "$IS_RELEASE"
|
||||
}
|
||||
|
||||
fn-version-current() {
|
||||
declare desc="Retrieves the current version of dokku"
|
||||
pushd "$ROOT_DIR" >/dev/null
|
||||
grep Version debian/control | cut -d' ' -f2
|
||||
}
|
||||
|
||||
fn-version-next() {
|
||||
declare desc="Calculates the next version name of dokku"
|
||||
declare CURRENT_VERSION="$1" RELEASE="$2"
|
||||
local major minor patch short_object
|
||||
|
||||
major=$(echo "$CURRENT_VERSION" | awk '{split($0,a,"."); print a[1]}')
|
||||
minor=$(echo "$CURRENT_VERSION" | awk '{split($0,a,"."); print a[2]}')
|
||||
patch=$(echo "$CURRENT_VERSION" | awk '{split($0,a,"."); print a[3]}')
|
||||
|
||||
if [[ "$RELEASE" == "major" ]]; then
|
||||
major=$((major + 1))
|
||||
minor="0"
|
||||
patch="0"
|
||||
elif [[ "$RELEASE" == "minor" ]]; then
|
||||
minor=$((minor + 1))
|
||||
patch="0"
|
||||
elif [[ "$RELEASE" == "patch" ]]; then
|
||||
patch=$((patch + 1))
|
||||
else
|
||||
short_object=$(git log --oneline | tail -n 1 | cut -d' ' -f1)
|
||||
echo "${CURRENT_VERSION}build+$(echo "$DOKKU_GIT_REV" | cut -c1-${#short_object})"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo "${major}.${minor}.${patch}"
|
||||
}
|
||||
|
||||
fn-publish-package() {
|
||||
declare desc="Publishes a package to packagecloud"
|
||||
declare IS_RELEASE="$1" RELEASE_TYPE="$2" PACKAGE_NAME="$3"
|
||||
local REPOSITORY=dokku/dokku-betafish DIST=ubuntu/trusty
|
||||
|
||||
[[ "$IS_RELEASE" == "true" ]] && REPOSITORY=dokku/dokku
|
||||
[[ "$RELEASE_TYPE" == "rpm" ]] && DIST=el/7
|
||||
log-info "(release-dokku) pushing ${RELEASE_TYPE} to packagecloud.com/${REPOSITORY}/${DIST}"
|
||||
package_cloud push "${REPOSITORY}/${DIST}" "$PACKAGE_NAME"
|
||||
}
|
||||
|
||||
fn-replace-version() {
|
||||
declare desc="Replaces the version within a file"
|
||||
local CURRENT_VERSION="$1"
|
||||
local NEXT_VERSION="$2"
|
||||
local FILENAME="$3"
|
||||
sed -i.bak "s/${CURRENT_VERSION//./\.}/$NEXT_VERSION/g" "$FILENAME" && rm "$FILENAME.bak"
|
||||
git add "$FILENAME"
|
||||
}
|
||||
|
||||
fn-repo-merged-requests() {
|
||||
declare desc="Retrieves all pull request ids since a given release of dokku"
|
||||
declare TAG="$1"
|
||||
git log "v${TAG}..HEAD" --oneline | grep "Merge pull request" | cut -d' ' -f 5 | cut -d '#' -f2
|
||||
}
|
||||
|
||||
fn-repo-push-tags() {
|
||||
declare desc="Pushes tags and the repository to github"
|
||||
declare IS_RELEASE="$1"
|
||||
|
||||
if [[ "$IS_RELEASE" == "false" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
pushd "$ROOT_DIR" >/dev/null
|
||||
git push --tags origin master
|
||||
}
|
||||
|
||||
fn-repo-update() {
|
||||
declare desc="Updates files within the repository for a given release"
|
||||
declare IS_RELEASE="$1" CURRENT_VERSION="$2" NEXT_VERSION="$3"
|
||||
|
||||
log-info "(release-dokku) Replacing ${CURRENT_VERSION} with ${NEXT_VERSION}"
|
||||
for f in plugins/*/plugin.toml; do
|
||||
fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" "$f"
|
||||
done
|
||||
|
||||
if [[ "$IS_RELEASE" == "false" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
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" 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/installation.md
|
||||
fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/template.html
|
||||
fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" README.md
|
||||
|
||||
if [[ "$RELEASE" == 'patch' ]]; then
|
||||
fn-replace-version "$CURRENT_VERSION" "$NEXT_VERSION" docs/assets/versions.json
|
||||
else
|
||||
versions=$(python -c 'import json,sys;d=json.load(sys.stdin);d["max-versions"].append("'"${NEXT_VERSION}"'"); print json.dumps(d, indent=2, sort_keys=True)' <docs/assets/versions.json)
|
||||
echo "$versions" >docs/assets/versions.json
|
||||
git add docs/assets/versions.json
|
||||
fi
|
||||
|
||||
if [[ "$IS_RELEASE" == "false" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
log-info "(release-dokku) Adding HISTORY.md, committing and tagging"
|
||||
fn-repo-update-history-and-commit "$CURRENT_VERSION" "$NEXT_VERSION"
|
||||
git tag "v${NEXT_VERSION}"
|
||||
}
|
||||
|
||||
fn-repo-update-history-and-commit() {
|
||||
declare desc="Updates the history file and commits the changes"
|
||||
declare CURRENT_VERSION="$1" NEXT_VERSION="$2"
|
||||
local PULL_REQUEST_ID TITLE AUTHOR TYPE CHANGELOG_TEXT
|
||||
local COMMIT_MESSAGE HISTORY HISTORY_CONTENTS HISTORY_DOCUMENTATION HISTORY_ENHANCEMENT HISTORY_BUG ISSUE_FILE
|
||||
|
||||
pushd "$ROOT_DIR" >/dev/null
|
||||
|
||||
mkdir -p /tmp/github-data
|
||||
|
||||
for PULL_REQUEST_ID in $(fn-repo-merged-requests "$CURRENT_VERSION"); do
|
||||
ISSUE_FILE="/tmp/github-data/${PULL_REQUEST_ID}.json"
|
||||
if [[ ! -f "$ISSUE_FILE" ]]; then
|
||||
curl -sS "https://api.github.com/repos/dokku/dokku/issues/${PULL_REQUEST_ID}" >"$ISSUE_FILE"
|
||||
fi
|
||||
|
||||
TITLE="$(jq -r '.title' "$ISSUE_FILE")"
|
||||
AUTHOR="$(jq -r '.user.login' "$ISSUE_FILE")"
|
||||
TYPE="$(jq -r '.labels[] | select( .name | contains("type") ) | .name' "$ISSUE_FILE" | cut -d' ' -f2)"
|
||||
CHANGELOG_TEXT="- #${PULL_REQUEST_ID}: @${AUTHOR} ${TITLE}"
|
||||
|
||||
if [[ "$TYPE" == "bug" ]]; then
|
||||
HISTORY_BUG="${HISTORY_BUG}"$'\n'"$CHANGELOG_TEXT"
|
||||
elif [[ "$TYPE" == "documentation" ]]; then
|
||||
HISTORY_DOCUMENTATION="${HISTORY_DOCUMENTATION}"$'\n'"$CHANGELOG_TEXT"
|
||||
elif [[ "$TYPE" == "enhancement" ]]; then
|
||||
HISTORY_ENHANCEMENT="${HISTORY_ENHANCEMENT}"$'\n'"$CHANGELOG_TEXT"
|
||||
fi
|
||||
done
|
||||
|
||||
HISTORY="# History"
|
||||
HISTORY="${HISTORY}"$'\n\n'"## ${NEXT_VERSION}"
|
||||
|
||||
if [[ "$HISTORY_BUG" ]]; then
|
||||
HISTORY="${HISTORY}"$'\n\n'"### Bug Fixes"
|
||||
HISTORY="${HISTORY}"$'\n'"$HISTORY_BUG"
|
||||
fi
|
||||
|
||||
if [[ "$HISTORY_DOCUMENTATION" ]]; then
|
||||
HISTORY="${HISTORY}"$'\n\n'"### New Features"
|
||||
HISTORY="${HISTORY}"$'\n'"$HISTORY_DOCUMENTATION"
|
||||
fi
|
||||
|
||||
if [[ "$HISTORY_ENHANCEMENT" ]]; then
|
||||
HISTORY="${HISTORY}"$'\n\n'"### Documentation"
|
||||
HISTORY="${HISTORY}"$'\n'"$HISTORY_ENHANCEMENT"
|
||||
fi
|
||||
|
||||
sed -i.bak '1d' HISTORY.md && rm HISTORY.md.bak
|
||||
HISTORY_CONTENTS="$(cat HISTORY.md)"
|
||||
echo -e "$HISTORY\n$HISTORY_CONTENTS" >HISTORY.md
|
||||
git add HISTORY.md
|
||||
|
||||
COMMIT_MESSAGE="Release ${NEXT_VERSION}"$'\n\n'"${HISTORY}"
|
||||
git commit -m "${COMMIT_MESSAGE}"
|
||||
}
|
||||
|
||||
fn-require-bin() {
|
||||
declare desc="Checks that a binary exists"
|
||||
declare BINARY="$1"
|
||||
if ! command -v "$BINARY" &>/dev/null; then
|
||||
log-fail "Missing ${BINARY}, please install it"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
declare RELEASE="$1"
|
||||
local CURRENT_VERSION NEXT_VERSION IS_RELEASE major minor patch versions
|
||||
local VALID_RELEASE_LEVELS=("major" "minor" "patch" "betafish")
|
||||
|
||||
if [[ "$RELEASE" == '--trace' ]]; then
|
||||
shift 1
|
||||
RELEASE="$1"
|
||||
TRACE=1 && set -x
|
||||
fi
|
||||
|
||||
if [[ -z "$RELEASE" ]]; then
|
||||
log-fail "Argument 1 must be one of [major, minor, patch, betafish], none given"
|
||||
fi
|
||||
|
||||
if ! fn-in-array "$RELEASE" "${VALID_RELEASE_LEVELS[@]}"; then
|
||||
log-fail "Argument 1 must be one of [major, minor, patch, betafish], '${RELEASE}' given"
|
||||
fi
|
||||
|
||||
fn-require-bin "docker"
|
||||
fn-require-bin "git"
|
||||
fn-require-bin "package_cloud"
|
||||
[[ -n "$PACKAGECLOUD_API_TOKEN" ]] || log-fail "Missing PACKAGECLOUD_API_TOKEN environment variable"
|
||||
|
||||
CURRENT_VERSION="$(fn-version-current)"
|
||||
NEXT_VERSION="$(fn-version-next "$CURRENT_VERSION" "$RELEASE")"
|
||||
IS_RELEASE="$(fn-is-release "$RELEASE")"
|
||||
|
||||
fn-repo-update "$IS_RELEASE" "$CURRENT_VERSION" "$NEXT_VERSION"
|
||||
|
||||
fn-build-dokku "$IS_RELEASE" "$NEXT_VERSION"
|
||||
|
||||
fn-extract-package "$IS_RELEASE" "dokku_${NEXT_VERSION}_amd64.deb"
|
||||
fn-extract-package "$IS_RELEASE" "dokku-${NEXT_VERSION}-1.x86_64.rpm"
|
||||
|
||||
fn-publish-package "$IS_RELEASE" "deb" "dokku_${NEXT_VERSION}_amd64.deb"
|
||||
fn-publish-package "$IS_RELEASE" "rpm" "dokku-${NEXT_VERSION}-1.x86_64.rpm"
|
||||
|
||||
fn-repo-push-tags "$IS_RELEASE"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
22
deb.mk
22
deb.mk
@@ -1,6 +1,6 @@
|
||||
HEROKUISH_DESCRIPTION = 'Herokuish uses Docker and Buildpacks to build applications like Heroku'
|
||||
HEROKUISH_REPO_NAME ?= gliderlabs/herokuish
|
||||
HEROKUISH_VERSION ?= 0.3.26
|
||||
HEROKUISH_VERSION ?= 0.3.27
|
||||
HEROKUISH_ARCHITECTURE = amd64
|
||||
HEROKUISH_PACKAGE_NAME = herokuish_$(HEROKUISH_VERSION)_$(HEROKUISH_ARCHITECTURE).deb
|
||||
|
||||
@@ -26,7 +26,7 @@ Simplifies running a single command over SSH, and
|
||||
manages authorized keys (ACL) and users in order to do so.
|
||||
endef
|
||||
SSHCOMMAND_REPO_NAME ?= dokku/sshcommand
|
||||
SSHCOMMAND_VERSION ?= 0.6.0
|
||||
SSHCOMMAND_VERSION ?= 0.7.0
|
||||
SSHCOMMAND_ARCHITECTURE = amd64
|
||||
SSHCOMMAND_PACKAGE_NAME = sshcommand_$(SSHCOMMAND_VERSION)_$(SSHCOMMAND_ARCHITECTURE).deb
|
||||
SSHCOMMAND_URL ?= https://raw.githubusercontent.com/dokku/sshcommand/v$(SSHCOMMAND_VERSION)/sshcommand
|
||||
@@ -92,8 +92,8 @@ deb-herokuish:
|
||||
@echo " sudo docker rmi gliderlabs/herokuish" >> /tmp/tmp/post-install
|
||||
@echo "fi" >> /tmp/tmp/post-install
|
||||
@echo "echo 'Importing herokuish into docker (around 5 minutes)'" >> /tmp/tmp/post-install
|
||||
@echo 'if [[ ! -z $${http_proxy+x} ]]; then BUILDARGS="--build-args http_proxy=$$http_proxy"; fi' >> /tmp/tmp/post-install
|
||||
@echo 'if [[ ! -z $${https_proxy+x} ]]; then BUILDARGS="$$BUILDARGS --build-args https_proxy=$$https_proxy"; fi' >> /tmp/tmp/post-install
|
||||
@echo 'if [[ ! -z $${http_proxy+x} ]]; then BUILDARGS="--build-arg http_proxy=$$http_proxy"; fi' >> /tmp/tmp/post-install
|
||||
@echo 'if [[ ! -z $${https_proxy+x} ]]; then BUILDARGS="$$BUILDARGS --build-arg https_proxy=$$https_proxy"; fi' >> /tmp/tmp/post-install
|
||||
@echo 'if [[ ! -z $${BUILDARGS+x} ]]; then echo Adding proxy settings to docker build: $$BUILDARGS; fi' >> /tmp/tmp/post-install
|
||||
@echo 'sudo docker build $$BUILDARGS -t gliderlabs/herokuish /var/lib/herokuish 1> /dev/null' >> /tmp/tmp/post-install
|
||||
|
||||
@@ -124,8 +124,12 @@ deb-dokku:
|
||||
cp dokku /tmp/build/usr/bin
|
||||
cp LICENSE /tmp/build/usr/share/doc/dokku/copyright
|
||||
find . -name ".DS_Store" -depth -exec rm {} \;
|
||||
$(MAKE) go-build
|
||||
cp common.mk /tmp/build/var/lib/dokku/core-plugins/common.mk
|
||||
cp -r plugins/* /tmp/build/var/lib/dokku/core-plugins/available
|
||||
find plugins/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | while read plugin; do cd /tmp/build/var/lib/dokku/core-plugins/available/$$plugin && if [ -e Makefile ]; then $(MAKE) src-clean; fi; done
|
||||
find plugins/ -mindepth 1 -maxdepth 1 -type d -printf '%f\n' | while read plugin; do touch /tmp/build/var/lib/dokku/core-plugins/available/$$plugin/.core; done
|
||||
rm /tmp/build/var/lib/dokku/core-plugins/common.mk
|
||||
$(MAKE) help2man
|
||||
$(MAKE) addman
|
||||
cp /usr/local/share/man/man1/dokku.1 /tmp/build/usr/share/man/man1/dokku.1
|
||||
@@ -140,16 +144,16 @@ endif
|
||||
ifneq (,$(findstring false,$(IS_RELEASE)))
|
||||
sed -i.bak -e "s/^/`date +%s`:/" /tmp/build/var/lib/dokku/STABLE_VERSION && rm /tmp/build/var/lib/dokku/STABLE_VERSION.bak
|
||||
endif
|
||||
rm /tmp/build/DEBIAN/lintian-overrides
|
||||
mv debian/lintian-overrides /tmp/build/usr/share/lintian/overrides/dokku
|
||||
rm -f /tmp/build/DEBIAN/lintian-overrides
|
||||
cp debian/lintian-overrides /tmp/build/usr/share/lintian/overrides/dokku
|
||||
ifdef DOKKU_GIT_REV
|
||||
echo "$(DOKKU_GIT_REV)" > /tmp/build/var/lib/dokku/GIT_REV
|
||||
else
|
||||
git rev-parse HEAD > /tmp/build/var/lib/dokku/GIT_REV
|
||||
endif
|
||||
sed -i "s/^Version: .*/Version: `cat /tmp/build/var/lib/dokku/STABLE_VERSION`/g" /tmp/build/DEBIAN/control
|
||||
dpkg-deb --build /tmp/build "/tmp/dokku_`cat /tmp/build/var/lib/dokku/STABLE_VERSION`_$(DOKKU_ARCHITECTURE).deb"
|
||||
lintian "/tmp/dokku_`cat /tmp/build/var/lib/dokku/STABLE_VERSION`_$(DOKKU_ARCHITECTURE).deb"
|
||||
sed -i.bak "s/^Version: .*/Version: `cat /tmp/build/var/lib/dokku/STABLE_VERSION`/g" /tmp/build/DEBIAN/control && rm /tmp/build/DEBIAN/control.bak
|
||||
dpkg-deb --build /tmp/build "/tmp/dokku_`cat /tmp/build/var/lib/dokku/VERSION`_$(DOKKU_ARCHITECTURE).deb"
|
||||
lintian "/tmp/dokku_`cat /tmp/build/var/lib/dokku/VERSION`_$(DOKKU_ARCHITECTURE).deb"
|
||||
|
||||
deb-plugn:
|
||||
rm -rf /tmp/tmp /tmp/build $(PLUGN_PACKAGE_NAME)
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -1,5 +1,5 @@
|
||||
Package: dokku
|
||||
Version: 0.8.2
|
||||
Version: 0.9.4
|
||||
Section: web
|
||||
Priority: optional
|
||||
Architecture: amd64
|
||||
|
||||
2
debian/lintian-overrides
vendored
2
debian/lintian-overrides
vendored
@@ -1,3 +1,5 @@
|
||||
dokku: command-with-path-in-maintainer-script postinst:16 /usr/bin/sshcommand
|
||||
dokku: maintainer-script-calls-systemctl postinst:87
|
||||
dokku: changelog-file-missing-in-native-package
|
||||
dokku: statically-linked-binary
|
||||
dokku: unstripped-binary-or-object
|
||||
|
||||
2
debian/postinst
vendored
2
debian/postinst
vendored
@@ -35,7 +35,7 @@ case "$1" in
|
||||
|
||||
echo "Setting up storage directories"
|
||||
mkdir -p ${DOKKU_LIB_ROOT}/data ${DOKKU_LIB_ROOT}/data/storage
|
||||
chown dokku:dokku -R ${DOKKU_LIB_ROOT}/data
|
||||
chown dokku:dokku ${DOKKU_LIB_ROOT}/data ${DOKKU_LIB_ROOT}/data/storage
|
||||
|
||||
echo "Setting up plugin directories"
|
||||
# should be replaced by `plugn init`
|
||||
|
||||
@@ -20,40 +20,15 @@ For dockerfile apps, place `app.json` in the configured `WORKDIR` directory; oth
|
||||
|
||||
### Example app.json
|
||||
|
||||
> NOTE: Only the `scripts.dokku.predeploy` and `scripts.dokku.postdeploy` tasks are supported by Dokku at this time. All other fields will be ignored and can be omitted.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "barebones nodejs",
|
||||
"description": "A barebones Node.js app using Express 4.",
|
||||
"keywords": [
|
||||
"nodejs",
|
||||
"express"
|
||||
],
|
||||
"repository": "https://github.com/michaelshobbs/node-js-sample",
|
||||
"scripts": {
|
||||
"dokku": {
|
||||
"predeploy": "touch /app/predeploy.test",
|
||||
"postdeploy": "curl https://some.external.api.service.com/deployment?state=success"
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"SECRET_TOKEN": {
|
||||
"description": "A secret key for verifying the integrity of signed cookies.",
|
||||
"value": "secret"
|
||||
},
|
||||
"WEB_CONCURRENCY": {
|
||||
"description": "The number of processes to run.",
|
||||
"generator": "echo 5"
|
||||
}
|
||||
},
|
||||
"image": "gliderlabs/herokuish",
|
||||
"addons": [
|
||||
"dokku-postgres",
|
||||
"dokku-redis"
|
||||
],
|
||||
"buildpacks": [
|
||||
{
|
||||
"url": "https://github.com/heroku/heroku-buildpack-nodejs"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -31,30 +31,30 @@ dokku plugin
|
||||
|
||||
```
|
||||
plugn: dev
|
||||
00_dokku-standard 0.8.2 enabled dokku core standard plugin
|
||||
20_events 0.8.2 enabled dokku core events logging plugin
|
||||
apps 0.8.2 enabled dokku core apps plugin
|
||||
build-env 0.8.2 enabled dokku core build-env plugin
|
||||
certs 0.8.2 enabled dokku core certificate management plugin
|
||||
checks 0.8.2 enabled dokku core checks plugin
|
||||
common 0.8.2 enabled dokku core common plugin
|
||||
config 0.8.2 enabled dokku core config plugin
|
||||
docker-options 0.8.2 enabled dokku core docker-options plugin
|
||||
domains 0.8.2 enabled dokku core domains plugin
|
||||
enter 0.8.2 enabled dokku core enter plugin
|
||||
git 0.8.2 enabled dokku core git plugin
|
||||
logs 0.8.2 enabled dokku core logs plugin
|
||||
named-containers 0.8.2 enabled dokku core named containers plugin
|
||||
nginx-vhosts 0.8.2 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.8.2 enabled dokku core plugin plugin
|
||||
proxy 0.8.2 enabled dokku core proxy plugin
|
||||
ps 0.8.2 enabled dokku core ps plugin
|
||||
repo 0.8.2 enabled dokku core repo plugin
|
||||
shell 0.8.2 enabled dokku core shell plugin
|
||||
ssh-keys 0.8.2 enabled dokku core ssh-keys plugin
|
||||
storage 0.8.2 enabled dokku core storage plugin
|
||||
tags 0.8.2 enabled dokku core tags plugin
|
||||
tar 0.8.2 enabled dokku core tar plugin
|
||||
00_dokku-standard 0.9.4 enabled dokku core standard plugin
|
||||
20_events 0.9.4 enabled dokku core events logging plugin
|
||||
apps 0.9.4 enabled dokku core apps plugin
|
||||
build-env 0.9.4 enabled dokku core build-env plugin
|
||||
certs 0.9.4 enabled dokku core certificate management plugin
|
||||
checks 0.9.4 enabled dokku core checks plugin
|
||||
common 0.9.4 enabled dokku core common plugin
|
||||
config 0.9.4 enabled dokku core config plugin
|
||||
docker-options 0.9.4 enabled dokku core docker-options plugin
|
||||
domains 0.9.4 enabled dokku core domains plugin
|
||||
enter 0.9.4 enabled dokku core enter plugin
|
||||
git 0.9.4 enabled dokku core git plugin
|
||||
logs 0.9.4 enabled dokku core logs plugin
|
||||
named-containers 0.9.4 enabled dokku core named containers plugin
|
||||
nginx-vhosts 0.9.4 enabled dokku core nginx-vhosts plugin
|
||||
plugin 0.9.4 enabled dokku core plugin plugin
|
||||
proxy 0.9.4 enabled dokku core proxy plugin
|
||||
ps 0.9.4 enabled dokku core ps plugin
|
||||
repo 0.9.4 enabled dokku core repo plugin
|
||||
shell 0.9.4 enabled dokku core shell plugin
|
||||
ssh-keys 0.9.4 enabled dokku core ssh-keys plugin
|
||||
storage 0.9.4 enabled dokku core storage plugin
|
||||
tags 0.9.4 enabled dokku core tags plugin
|
||||
tar 0.9.4 enabled dokku core tar plugin
|
||||
```
|
||||
|
||||
Installing a plugin is easy as well using the `plugin:install` command. This command will also trigger the `install` pluginhook on all existing plugins.
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-310x150.png"/>
|
||||
<square70x70logo src="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-70x70.png"/>
|
||||
<square150x150logo src="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-150x150.png"/>
|
||||
<square310x310logo src="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-310x310.png"/>
|
||||
<wide310x150logo src="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-310x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
|
||||
@@ -2,37 +2,37 @@
|
||||
"name": "Dokku",
|
||||
"icons": [
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-36x36.png",
|
||||
"sizes": "36x36",
|
||||
"type": "image\/png",
|
||||
"density": "0.75"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-48x48.png",
|
||||
"sizes": "48x48",
|
||||
"type": "image\/png",
|
||||
"density": "1.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image\/png",
|
||||
"density": "1.5"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image\/png",
|
||||
"density": "2.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image\/png",
|
||||
"density": "3.0"
|
||||
},
|
||||
{
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.8.2\/docs\/assets\/favicons\/android-chrome-192x192.png",
|
||||
"src": "https:\/\/cdn.rawgit.com\/progrium\/dokku\/v0.9.4\/docs\/assets\/favicons\/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image\/png",
|
||||
"density": "4.0"
|
||||
|
||||
@@ -35,13 +35,13 @@ h1 {
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.header .navbar-brand a {
|
||||
background-image: url(https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/dokku.png);
|
||||
background-image: url(https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/dokku.png);
|
||||
text-indent: 40px;
|
||||
}
|
||||
.blurb {
|
||||
color: #424242;
|
||||
background-color: #ededed;
|
||||
background-image: url(https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/gplaypattern.png);
|
||||
background-image: url(https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/gplaypattern.png);
|
||||
padding: 45px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"0.5.8",
|
||||
"0.6.5",
|
||||
"0.7.2",
|
||||
"0.8.2"
|
||||
"0.8.2",
|
||||
"0.9.4"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ Note: The following plugins have been supplied by our community and may not have
|
||||
[luxifer]: https://github.com/luxifer
|
||||
[Maciej Łebkowski]: https://github.com/mlebkowski
|
||||
[matto1990]: https://github.com/matto1990
|
||||
[mbreit]: https://github.com/mbreit
|
||||
[mbriskar]: https://github.com/mbriskar
|
||||
[michaelshobbs]: https://github.com/michaelshobbs
|
||||
[mikecsh]: https://github.com/mikecsh
|
||||
@@ -180,6 +181,7 @@ Note: The following plugins have been supplied by our community and may not have
|
||||
| [Haproxy tcp load balancer](https://github.com/256dpi/dokku-haproxy) | [256dpi][] | 0.4.0+ |
|
||||
| [Hostname](https://github.com/michaelshobbs/dokku-hostname) | [michaelshobbs][] | 0.4.0+ |
|
||||
| [HTTP Auth Secure Apps](https://github.com/matto1990/dokku-secure-apps) | [matto1990][] | 0.4.0+ |
|
||||
| [Monit (Health Checks)](https://github.com/mbreit/dokku-monit) | [mbreit][] | 0.8.0+ |
|
||||
| [Nuke Containers](https://github.com/josegonzalez/dokku-nuke) | [josegonzalez][] | 0.4.0+ |
|
||||
| [Open App Ports](https://github.com/josegonzalez/dokku-ports) | [josegonzalez][] | 0.3.x |
|
||||
| [Proctype Filter](https://github.com/michaelshobbs/dokku-proctype-filter) | [michaelshobbs][] | 0.4.0+ |
|
||||
|
||||
@@ -56,6 +56,13 @@ Admin users and root can also add keys remotely:
|
||||
cat ~/.ssh/id_rsa.pub | ssh dokku@dokku.me ssh-keys:add KEY_NAME
|
||||
```
|
||||
|
||||
If you are using an ssh user other than `dokku`, then you'll also need to specify the `dokku` bin:
|
||||
|
||||
```shell
|
||||
cat ~/.ssh/id_rsa.pub | ssh root@dokku.me dokku ssh-keys:add KEY_NAME
|
||||
```
|
||||
|
||||
|
||||
Finally, if you are using the vagrant installation, you can also use the `make vagrant-acl-add` target to add your public key to Dokku (it will use your host username as the `USER`):
|
||||
|
||||
```shell
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Plugin Creation
|
||||
|
||||
Plugins can simply be implementations of [triggers](/dokku/development/plugin-triggers) or they may implement a command structure of their own. Dokku has no restrictions on the language in which a plugin is implemented, it only cares that the plugin implements the appropriate [commands](/dokku/development/plugin-creation#command-api) or [triggers](/dokku/development/plugin-triggers) API. NOTE: all files that implement the triggers or commands API must be executable.
|
||||
|
||||
If you create your own plugin:
|
||||
|
||||
1. Take a look at the plugins shipped with Dokku and hack away!
|
||||
@@ -9,6 +11,23 @@ If you create your own plugin:
|
||||
5. Subscribe to the [dokku development blog](http://progrium.com) to be notified about API changes and releases
|
||||
|
||||
|
||||
### Compilable Plugins (i.e. golang, java(?), c, etc.)
|
||||
The plugin developer is required to implement the `install` trigger such that it will output your built executable(s) in the correct directory structure to implement the plugin's desired command and/or trigger API. See [smoke-test-plugin](https://github.com/dokku/smoke-test-plugin) for an example.
|
||||
|
||||
|
||||
### Command API
|
||||
There are 3 main implementation points: `commands`, `subcommands/default`, and `subcommands/<command-name>`
|
||||
|
||||
#### commands
|
||||
Primarily used to supply the plugin's usage/help output. (i.e. [plugin help](https://github.com/dokku/dokku/tree/master/plugins/plugin/commands))
|
||||
|
||||
#### subcommands/default
|
||||
Implements the plugin's default command behavior. (i.e. [`dokku plugin`](https://github.com/dokku/dokku/tree/master/plugins/plugin/subcommands/default))
|
||||
|
||||
#### subcommands/<command-name>
|
||||
Implements the additional command interface and will translate to `dokku plugin:cmd` on the command line. (i.e. [`dokku plugin:install`](https://github.com/dokku/dokku/tree/master/plugins/plugin/subcommands/install))
|
||||
|
||||
|
||||
### Sample plugin
|
||||
The below plugin is a dummy `dokku hello` plugin.
|
||||
|
||||
|
||||
@@ -321,6 +321,10 @@ set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
# TODO
|
||||
```
|
||||
|
||||
> WARNING: The `git-pre-pull` trigger should _not_ be used for authentication
|
||||
since it does not get called for commands that use `git-upload-archive` such
|
||||
as `git archive`. Instead, use the [`user-auth`](#user-auth) trigger.
|
||||
|
||||
### `install`
|
||||
|
||||
- Description: Used to setup any files/configuration for a plugin.
|
||||
|
||||
@@ -67,7 +67,7 @@ The workflow looks like this:
|
||||
```shell
|
||||
# having dokku-arch in ../dokku-arch
|
||||
vagrant up build-arch
|
||||
# wait for "==> build-arch: ==> Finished making: dokku 0.8.2-2 (Mon Feb 22 23:20:37 CET 2016)"
|
||||
# wait for "==> build-arch: ==> Finished making: dokku 0.9.4-2 (Mon Feb 22 23:20:37 CET 2016)"
|
||||
cd ../dokku-arch
|
||||
git add PKGBUILD .SRCINFO
|
||||
git commit -m 'Update to dokku 0.9.9'
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# Installing on Linode
|
||||
|
||||
## Enable AUFS Storage Driver
|
||||
|
||||
When installing Dokku on a newly-created Linode server, you'll likely see an error during Docker installation:
|
||||
|
||||
> Warning: current kernel is not supported by the linux-image-extra-virtual package. We have no AUFS support. Consider installing the packages linux-image-virtual kernel and linux-image-extra-virtual for AUFS support.
|
||||
|
||||
After 10 seconds, the installation will continue as normal.
|
||||
|
||||
This warning is the result of Linode using its own kernel, which does not support AUFS, instead of using the kernel supplied by Debian/Ubuntu. If you ignore the warning, Docker will fall back to using the DeviceMapper storage backend and Dokku will work normally. However, AUFS is better tested and will perform better.
|
||||
|
||||
To avoid this error message and use AUFS, follow the steps below to select the GRUB 2 kernel.
|
||||
|
||||
|
||||
### Select the GRUB 2 kernel instead of the default Linode kernel:
|
||||
|
||||
1. Login to your [Linode Manager](http://manager.linode.com), open the `Dashboard` associated with your new server.
|
||||
2. Click `Edit` for the `Configuration Profile`. You should now be on the `Edit Configuration Profile` page.
|
||||
3. Scroll down to `Boot Settings` > `Kernel menu`. Change the "Kernel" option to "GRUB 2" and save your changes.
|
||||
4. If you have already pushed the `Boot` button and your server is running, you will need to reboot it before continuing. Otherwise, you can now push the `Boot` button to start your server and proceed with the normal Dokku installation.
|
||||
|
||||
Once your server comes back online, you'll be running Ubuntu's default kernel. You can now follow Dokku's [normal installation instructions](/dokku/getting-started/installation/) and `bootstrap.sh` will take care of everything else.
|
||||
|
||||
|
||||
### Verify that you are using AUFS:
|
||||
|
||||
Once you have fully installed Dokku and rebooted your server, you can verify that AUFS is being used with the terminal command: `docker info`. If AUFS is being used, you should see `Storage Driver: aufs` in the output.
|
||||
@@ -7,16 +7,21 @@
|
||||
Dokku defaults to being installed via RPM package on CentOS 7. While certain hosts may require extra work to get running, you may optionally wish to automate the installation of Dokku without the use of our `bootstrap.sh` bash script. The following are the steps run by said script:
|
||||
|
||||
```shell
|
||||
# install docker
|
||||
# Install docker
|
||||
curl -fsSL https://get.docker.com/ | sh
|
||||
|
||||
# install epel for nginx packages to be available
|
||||
# Install epel for nginx packages to be available
|
||||
sudo yum install -y epel-release
|
||||
|
||||
# install dokku
|
||||
# Install dokku
|
||||
curl -s https://packagecloud.io/install/repositories/dokku/dokku/script.rpm.sh | sudo bash
|
||||
sudo yum install -y herokuish dokku
|
||||
sudo dokku plugin:install-dependencies --core
|
||||
systemctl start nginx
|
||||
|
||||
# Enable docker and nginx on system startup
|
||||
systemctl enable docker
|
||||
systemctl enable nginx
|
||||
```
|
||||
|
||||
The [devicemapper](https://docs.docker.com/engine/userguide/storagedriver/device-mapper-driver/) is the default Docker storage driver on CentOS 7 and defaults to a configuration mode known as `loop-lvm`. This mode is designed to work out-of-the-box with no additional configuration. However, production deployments should not run under `loop-lvm` mode. The preferred configuration for production deployments is [`direct-lvm`](https://docs.docker.com/engine/userguide/storagedriver/device-mapper-driver/#/configure-direct-lvm-mode-for-production).
|
||||
|
||||
@@ -21,8 +21,8 @@ To install the latest stable version of dokku, you can run the following shell c
|
||||
|
||||
```shell
|
||||
# for debian systems, installs Dokku via apt-get
|
||||
wget https://raw.githubusercontent.com/dokku/dokku/v0.8.2/bootstrap.sh;
|
||||
sudo DOKKU_TAG=v0.8.2 bash bootstrap.sh
|
||||
wget https://raw.githubusercontent.com/dokku/dokku/v0.9.4/bootstrap.sh;
|
||||
sudo DOKKU_TAG=v0.9.4 bash bootstrap.sh
|
||||
```
|
||||
|
||||
The installation process takes about 5-10 minutes, depending upon internet connection speed.
|
||||
@@ -44,7 +44,6 @@ For various reasons, certain hosting providers may have other steps that should
|
||||
|
||||
- [Digital Ocean Installation Notes](/dokku/getting-started/install/digitalocean)
|
||||
- [DreamHost Cloud Installation Notes](/dokku/getting-started/install/dreamhost/)
|
||||
- [Linode Installation Notes](/dokku/getting-started/install/linode/)
|
||||
- [Microsoft Azure Installation Notes](/dokku/getting-started/install/azure/)
|
||||
|
||||
As well, you may wish to customize your installation in some other fashion. or experiment with vagrant. The guides below should get you started:
|
||||
|
||||
@@ -10,30 +10,30 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700" rel="stylesheet" type="text/css">
|
||||
<title>Dokku - The smallest PaaS implementation you've ever seen</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Dokku">
|
||||
<meta name="application-name" content="Dokku">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/style.css" rel="stylesheet">
|
||||
<!-- <link href="/dokku/docs/assets/style.css" rel="stylesheet"> -->
|
||||
<style>
|
||||
</style>
|
||||
@@ -98,12 +98,12 @@
|
||||
<p class="line">
|
||||
<span class="path"></span>
|
||||
<span class="prompt">$</span>
|
||||
<span class="command">wget https://raw.githubusercontent.com/dokku/dokku/v0.8.2/bootstrap.sh</span>
|
||||
<span class="command">wget https://raw.githubusercontent.com/dokku/dokku/v0.9.4/bootstrap.sh</span>
|
||||
</p>
|
||||
<p class="line">
|
||||
<span class="path"></span>
|
||||
<span class="prompt">$</span>
|
||||
<span class="command">sudo DOKKU_TAG=v0.8.2 bash bootstrap.sh</span>
|
||||
<span class="command">sudo DOKKU_TAG=v0.9.4 bash bootstrap.sh</span>
|
||||
</p>
|
||||
<p class="line">
|
||||
<span class="output"> # go to your server's IP and follow the web installer</span>
|
||||
@@ -173,7 +173,7 @@
|
||||
</div>
|
||||
|
||||
<div class="alternate-instructions">
|
||||
<p>Hate <code>curl | bash</code>? See our official <a href="https://github.com/Azure/azure-quickstart-templates/tree/master/dokku-vm" target="_blank">Azure</a>, <a href="https://www.digitalocean.com/features/one-click-apps/dokku/" target="_blank">DigitalOcean</a>, <a href="/{{NAME}}~{{REF}}/getting-started/install/dreamhost/">DreamHost Cloud</a>, and <a href="/{{NAME}}~{{REF}}/getting-started/install/linode/" target="_blank">Linode</a> instructions.<p>
|
||||
<p>Hate <code>curl | bash</code>? See our official <a href="https://github.com/Azure/azure-quickstart-templates/tree/master/dokku-vm" target="_blank">Azure</a>, <a href="https://www.digitalocean.com/features/one-click-apps/dokku/" target="_blank">DigitalOcean</a>, and <a href="/{{NAME}}~{{REF}}/getting-started/install/dreamhost/">DreamHost Cloud</a> instructions.<p>
|
||||
<p>Still no love? <a href="https://github.com/dokku/dokku/blob/master/CONTRIBUTING.md" target="_blank">Contributions welcome</a>!</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,26 +9,26 @@
|
||||
<meta name="author" content="">
|
||||
<title>Dokku - The smallest PaaS implementation you've ever seen</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/favicon.ico">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/apple-touch-icon-180x180.png">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-32x32.png" sizes="32x32">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/android-chrome-192x192.png" sizes="192x192">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-96x96.png" sizes="96x96">
|
||||
<link rel="icon" type="image/png" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon-16x16.png" sizes="16x16">
|
||||
<link rel="manifest" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/manifest.json">
|
||||
<link rel="shortcut icon" href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/favicon.ico">
|
||||
<meta name="apple-mobile-web-app-title" content="Dokku">
|
||||
<meta name="application-name" content="Dokku">
|
||||
<meta name="msapplication-TileColor" content="#da532c">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="msapplication-TileImage" content="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/mstile-144x144.png">
|
||||
<meta name="msapplication-config" content="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/favicons/browserconfig.xml">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
|
||||
<script>
|
||||
@@ -42,7 +42,7 @@
|
||||
</script>
|
||||
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="https://cdn.rawgit.com/dokku/dokku/v0.8.2/docs/assets/style.css" rel="stylesheet">
|
||||
<link href="https://cdn.rawgit.com/dokku/dokku/v0.9.4/docs/assets/style.css" rel="stylesheet">
|
||||
<!-- <link href="/dokku/docs/assets/style.css" rel="stylesheet"> -->
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<style>
|
||||
|
||||
8
dokku
8
dokku
@@ -56,8 +56,12 @@ if [[ $(id -un) != "dokku" ]] && [[ ! $1 =~ plugin:* ]] && [[ ! $1 == "ssh-keys:
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ $(id -un) != "root" && $1 =~ ^plugin:.* && $1 != "plugin:help" && $1 != "plugin:list" ]] || [[ $(id -un) != "root" && $1 == "ssh-keys:add" ]]; then
|
||||
dokku_log_fail "This command must be run as root"
|
||||
if [[ $1 =~ ^plugin:.* && $1 != "plugin:help" && $1 != "plugin:list" ]] || [[ $1 == "ssh-keys:add" ]]; then
|
||||
if [[ $(id -un) != "root" ]]; then
|
||||
dokku_log_fail "This command must be run as root"
|
||||
else
|
||||
export SSH_USER=root
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$SSH_ORIGINAL_COMMAND" ]]; then
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core standard plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -10,6 +10,7 @@ flag_rsyslog_needs_restart=n
|
||||
|
||||
# This can be done unconditionally as mkdir -p
|
||||
# exits gracefully if the path already exists
|
||||
# shellcheck disable=SC2174
|
||||
mkdir -m 775 -p "$DOKKU_LOGS_DIR"
|
||||
case "$DOKKU_DISTRO" in
|
||||
arch|debian|centos)
|
||||
@@ -59,7 +60,7 @@ $DOKKU_LOGS_DIR/*.log {
|
||||
EOF
|
||||
|
||||
if [[ "$DOKKU_DISTRO" = "debian" ]]; then
|
||||
sed -i '/\s*su syslog dokku/d; s/\(create [0-7][0-7][0-7]\) syslog dokku/\1 root dokku/g' $DOKKU_LOGROTATE_FILE
|
||||
sed -i 's/ syslog dokku$/root dokku/g' $DOKKU_LOGROTATE_FILE
|
||||
fi
|
||||
|
||||
flag_rsyslog_needs_restart=y
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core events logging plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core apps plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core build-env plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -9,8 +9,8 @@ build_env_pre_build_buildpack() {
|
||||
local APP="$1"; local IMAGE=$(get_app_image_name "$APP"); local BUILD_ENV=""
|
||||
verify_app_name "$APP"
|
||||
|
||||
[[ -z $(config_get --global CURL_CONNECT_TIMEOUT) ]] && config_set --global CURL_CONNECT_TIMEOUT=5
|
||||
[[ -z $(config_get --global CURL_TIMEOUT) ]] && config_set --global CURL_TIMEOUT=30
|
||||
[[ -z $(config_get --global CURL_CONNECT_TIMEOUT) ]] && config_set --global CURL_CONNECT_TIMEOUT=90
|
||||
[[ -z $(config_get --global CURL_TIMEOUT) ]] && config_set --global CURL_TIMEOUT=60
|
||||
|
||||
if [[ -n $(config_export global) ]]; then
|
||||
local BUILD_ENV+=$'\n'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core certificate management plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -74,7 +74,7 @@ checks_check_deploy() {
|
||||
# after successfully copying the file. Thus, we suppress stderr.
|
||||
# ref: https://github.com/dotcloud/docker/issues/3986
|
||||
local CHECK_DEPLOY_TMP_WORK_DIR=$(mktemp -d /tmp/dokku_CHECKS.XXXXX)
|
||||
docker cp $DOKKU_APP_CONTAINER_ID:/app/CHECKS "$CHECK_DEPLOY_TMP_WORK_DIR" 2> /dev/null || true
|
||||
docker cp "$DOKKU_APP_CONTAINER_ID:/app/CHECKS" "$CHECK_DEPLOY_TMP_WORK_DIR" 2> /dev/null || true
|
||||
|
||||
local FILENAME=${CHECK_DEPLOY_TMP_WORK_DIR}/CHECKS
|
||||
|
||||
@@ -107,8 +107,8 @@ checks_check_deploy() {
|
||||
dokku_log_info1 "Waiting for $DOKKU_DEFAULT_CHECKS_WAIT seconds ..."
|
||||
sleep "$DOKKU_DEFAULT_CHECKS_WAIT"
|
||||
|
||||
! (is_container_running $DOKKU_APP_CONTAINER_ID) && dokku_log_fail "App container failed to start!!"
|
||||
local container_restarts=$(docker inspect -f "{{ .RestartCount }}" $DOKKU_APP_CONTAINER_ID)
|
||||
! (is_container_running "$DOKKU_APP_CONTAINER_ID") && dokku_log_fail "App container failed to start!!"
|
||||
local container_restarts="$(docker inspect -f "{{ .RestartCount }}" "$DOKKU_APP_CONTAINER_ID")"
|
||||
if [[ $container_restarts -ne 0 ]]; then
|
||||
docker stop "$DOKKU_APP_CONTAINER_ID" || true
|
||||
dokku_log_fail "App container failed to start!!"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core checks plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
141
plugins/common/common.go
Normal file
141
plugins/common/common.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
sh "github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
// ShellCmd represents a shell command to be run for dokku
|
||||
type ShellCmd struct {
|
||||
Env map[string]string
|
||||
Command *exec.Cmd
|
||||
CommandString string
|
||||
Args []string
|
||||
ShowOutput bool
|
||||
}
|
||||
|
||||
// NewShellCmd returns a new ShellCmd struct
|
||||
func NewShellCmd(command string) *ShellCmd {
|
||||
items := strings.Split(command, " ")
|
||||
cmd := items[0]
|
||||
args := items[1:]
|
||||
return &ShellCmd{
|
||||
Command: exec.Command(cmd, args...),
|
||||
CommandString: command,
|
||||
Args: args,
|
||||
ShowOutput: true,
|
||||
}
|
||||
}
|
||||
|
||||
// Execute is a lightweight wrapper around exec.Command
|
||||
func (sc *ShellCmd) Execute() bool {
|
||||
env := os.Environ()
|
||||
for k, v := range sc.Env {
|
||||
env = append(env, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
sc.Command.Env = env
|
||||
if sc.ShowOutput {
|
||||
sc.Command.Stdout = os.Stdout
|
||||
sc.Command.Stderr = os.Stderr
|
||||
}
|
||||
err := sc.Command.Run()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// VerifyAppName verifies app name format and app existence"
|
||||
func VerifyAppName(appName string) (err error) {
|
||||
dokkuRoot := MustGetEnv("DOKKU_ROOT")
|
||||
appRoot := strings.Join([]string{dokkuRoot, appName}, "/")
|
||||
_, err = os.Stat(appRoot)
|
||||
if os.IsNotExist(err) {
|
||||
return fmt.Errorf("App %s does not exist: %v\n", appName, err)
|
||||
}
|
||||
r, _ := regexp.Compile("^[a-z].*")
|
||||
if !r.MatchString(appName) {
|
||||
return fmt.Errorf("App name (%s) must begin with lowercase alphanumeric character\n", appName)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// MustGetEnv returns env variable or fails if it's not set
|
||||
func MustGetEnv(key string) string {
|
||||
value := os.Getenv(key)
|
||||
if value == "" {
|
||||
LogFail(fmt.Sprintf("%s not set!", key))
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// LogFail is the failure log formatter
|
||||
// prints text to stderr and exits with status 1
|
||||
func LogFail(text string) {
|
||||
fmt.Fprintln(os.Stderr, fmt.Sprintf("FAILED: %s", text))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// GetDeployingAppImageName returns deploying image identifier for a given app, tag tuple. validate if tag is presented
|
||||
func GetDeployingAppImageName(appName, imageTag, imageRepo string) (imageName string) {
|
||||
if appName == "" {
|
||||
LogFail("(GetDeployingAppImageName) APP must not be empty")
|
||||
}
|
||||
|
||||
b, err := sh.Command("plugn", "trigger", "deployed-app-repository", appName).Output()
|
||||
if err != nil {
|
||||
LogFail(err.Error())
|
||||
}
|
||||
imageRemoteRepository := string(b[:])
|
||||
|
||||
b, err = sh.Command("plugn", "trigger", "deployed-app-image-tag", appName).Output()
|
||||
if err != nil {
|
||||
LogFail(err.Error())
|
||||
}
|
||||
newImageTag := string(b[:])
|
||||
|
||||
b, err = sh.Command("plugn", "trigger", "deployed-app-image-repo", appName).Output()
|
||||
if err != nil {
|
||||
LogFail(err.Error())
|
||||
}
|
||||
newImageRepo := string(b[:])
|
||||
|
||||
if newImageRepo != "" {
|
||||
imageRepo = newImageRepo
|
||||
}
|
||||
if newImageTag != "" {
|
||||
imageTag = newImageTag
|
||||
}
|
||||
if imageRepo == "" {
|
||||
imageRepo = GetAppImageRepo(appName)
|
||||
}
|
||||
if imageTag == "" {
|
||||
imageTag = "latest"
|
||||
}
|
||||
|
||||
imageName = fmt.Sprintf("%s%s:%s", imageRemoteRepository, imageRepo, imageTag)
|
||||
if !VerifyImage(imageName) {
|
||||
LogFail(fmt.Sprintf("app image (%s) not found", imageName))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetAppImageRepo is the central definition of a dokku image repo pattern
|
||||
func GetAppImageRepo(appName string) string {
|
||||
return strings.Join([]string{"dokku", appName}, "/")
|
||||
}
|
||||
|
||||
// VerifyImage returns true if docker image exists in local repo
|
||||
func VerifyImage(image string) bool {
|
||||
imageCmd := NewShellCmd(strings.Join([]string{"docker inspect", image}, " "))
|
||||
imageCmd.ShowOutput = false
|
||||
if imageCmd.Execute() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
38
plugins/common/common_test.go
Normal file
38
plugins/common/common_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestGetEnv(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
Expect(MustGetEnv("DOKKU_ROOT")).To(Equal("/home/dokku"))
|
||||
}
|
||||
|
||||
func TestGetAppImageRepo(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
Expect(GetAppImageRepo("testapp")).To(Equal("dokku/testapp"))
|
||||
}
|
||||
|
||||
func TestVerifyImageInvalid(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
Expect(VerifyImage("testapp")).To(Equal(false))
|
||||
}
|
||||
|
||||
func TestVerifyAppNameInvalid(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
err := VerifyAppName("1994testApp")
|
||||
Expect(err).To(HaveOccurred())
|
||||
}
|
||||
|
||||
func TestVerifyAppName(t *testing.T) {
|
||||
RegisterTestingT(t)
|
||||
dir := "/home/dokku/testApp"
|
||||
os.MkdirAll(dir, 0644)
|
||||
err := VerifyAppName("testApp")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
os.RemoveAll(dir)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ verify_app_name() {
|
||||
local APP="$1"
|
||||
[[ ! -n "$APP" ]] && dokku_log_fail "(verify_app_name) APP must not be null"
|
||||
if [[ ! "$APP" =~ ^[a-z].* && ! "$APP" =~ ^[0-9].* ]]; then
|
||||
[[ -d "$DOKKU_ROOT/$APP" ]] && rm -rf "$DOKKU_ROOT/$APP"
|
||||
[[ -d "$DOKKU_ROOT/$APP" ]] && rm -rf "${DOKKU_ROOT:?}/$APP"
|
||||
dokku_log_fail "App name must begin with lowercase alphanumeric character"
|
||||
fi
|
||||
[[ ! -d "$DOKKU_ROOT/$APP" ]] && dokku_log_fail "App $APP does not exist"
|
||||
@@ -211,7 +211,7 @@ get_running_image_tag() {
|
||||
verify_app_name "$APP"
|
||||
|
||||
local CIDS=( $(get_app_container_ids "$APP") )
|
||||
local RUNNING_IMAGE_TAG=$(docker inspect -f '{{ .Config.Image }}' ${CIDS[0]} 2>/dev/null | awk -F: '{ print $2 }' || echo '')
|
||||
local RUNNING_IMAGE_TAG=$(docker inspect -f '{{ .Config.Image }}' "${CIDS[0]}" 2>/dev/null | awk -F: '{ print $2 }' || echo '')
|
||||
echo "$RUNNING_IMAGE_TAG"
|
||||
}
|
||||
|
||||
@@ -331,10 +331,11 @@ get_app_container_ids() {
|
||||
get_app_running_container_ids() {
|
||||
declare desc="return list of running docker container ids for given app and optional container_type"
|
||||
local APP="$1" CONTAINER_TYPE="$2"
|
||||
local CIDS
|
||||
verify_app_name "$APP"
|
||||
|
||||
! (is_deployed "$APP") && dokku_log_fail "App $APP has not been deployed"
|
||||
local CIDS=$(get_app_container_ids "$APP" "$CONTAINER_TYPE")
|
||||
CIDS=$(get_app_container_ids "$APP" "$CONTAINER_TYPE")
|
||||
|
||||
for CID in $CIDS; do
|
||||
local APP_CONTAINER_STATUS=$(docker inspect -f '{{.State.Running}}' "$CID" 2>/dev/null || true)
|
||||
@@ -367,7 +368,7 @@ get_cmd_from_procfile() {
|
||||
|
||||
if [[ -f $DOKKU_PROCFILE ]]; then
|
||||
local line; local name; local command
|
||||
while read line || [[ -n "$line" ]]; do
|
||||
while read -r line || [[ -n "$line" ]]; do
|
||||
if [[ -z "$line" ]] || [[ "$line" == "#"* ]]; then
|
||||
continue
|
||||
fi
|
||||
@@ -702,6 +703,8 @@ release_and_deploy() {
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
|
||||
local APP="$1"; local IMAGE_TAG="$2"; local IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG")
|
||||
local DOKKU_DOCKERFILE_PORTS
|
||||
|
||||
verify_app_name "$APP"
|
||||
|
||||
if verify_image "$IMAGE"; then
|
||||
@@ -709,7 +712,7 @@ release_and_deploy() {
|
||||
local IMAGE_SOURCE_TYPE="herokuish"
|
||||
else
|
||||
local IMAGE_SOURCE_TYPE="dockerfile"
|
||||
local DOKKU_DOCKERFILE_PORTS=$(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true)
|
||||
DOKKU_DOCKERFILE_PORTS=$(config_get "$APP" DOKKU_DOCKERFILE_PORTS || true)
|
||||
if [[ -z "$DOKKU_DOCKERFILE_PORTS" ]]; then
|
||||
local DOCKER_IMAGE_PORTS=$(get_exposed_ports_from_image "$IMAGE")
|
||||
[[ -n "$DOCKER_IMAGE_PORTS" ]] && config_set --no-restart "$APP" DOKKU_DOCKERFILE_PORTS="$DOCKER_IMAGE_PORTS"
|
||||
|
||||
8
plugins/common/glide.lock
generated
Normal file
8
plugins/common/glide.lock
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
hash: e438ca8cf1bdca3e9c984bb1ee70c0d58be9da52cbe13a079a7c6cbc14210a37
|
||||
updated: 2017-01-03T17:17:27.973373328-08:00
|
||||
imports:
|
||||
- name: github.com/codegangsta/inject
|
||||
version: 33e0aa1cb7c019ccc3fbe049a8262a6403d30504
|
||||
- name: github.com/codeskyblue/go-sh
|
||||
version: ceb46ec4630a726eeed51d0a70066c9e1102c48f
|
||||
testImports: []
|
||||
3
plugins/common/glide.yaml
Normal file
3
plugins/common/glide.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
package: .
|
||||
import:
|
||||
- package: github.com/codeskyblue/go-sh
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core common plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
2
plugins/common/vendor/github.com/codegangsta/inject/.gitignore
generated
vendored
Normal file
2
plugins/common/vendor/github.com/codegangsta/inject/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
inject
|
||||
inject.test
|
||||
20
plugins/common/vendor/github.com/codegangsta/inject/LICENSE
generated
vendored
Normal file
20
plugins/common/vendor/github.com/codegangsta/inject/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Jeremy Saenz
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
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.
|
||||
92
plugins/common/vendor/github.com/codegangsta/inject/README.md
generated
vendored
Normal file
92
plugins/common/vendor/github.com/codegangsta/inject/README.md
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
# inject
|
||||
--
|
||||
import "github.com/codegangsta/inject"
|
||||
|
||||
Package inject provides utilities for mapping and injecting dependencies in
|
||||
various ways.
|
||||
|
||||
Language Translations:
|
||||
* [简体中文](translations/README_zh_cn.md)
|
||||
|
||||
## Usage
|
||||
|
||||
#### func InterfaceOf
|
||||
|
||||
```go
|
||||
func InterfaceOf(value interface{}) reflect.Type
|
||||
```
|
||||
InterfaceOf dereferences a pointer to an Interface type. It panics if value is
|
||||
not an pointer to an interface.
|
||||
|
||||
#### type Applicator
|
||||
|
||||
```go
|
||||
type Applicator interface {
|
||||
// Maps dependencies in the Type map to each field in the struct
|
||||
// that is tagged with 'inject'. Returns an error if the injection
|
||||
// fails.
|
||||
Apply(interface{}) error
|
||||
}
|
||||
```
|
||||
|
||||
Applicator represents an interface for mapping dependencies to a struct.
|
||||
|
||||
#### type Injector
|
||||
|
||||
```go
|
||||
type Injector interface {
|
||||
Applicator
|
||||
Invoker
|
||||
TypeMapper
|
||||
// SetParent sets the parent of the injector. If the injector cannot find a
|
||||
// dependency in its Type map it will check its parent before returning an
|
||||
// error.
|
||||
SetParent(Injector)
|
||||
}
|
||||
```
|
||||
|
||||
Injector represents an interface for mapping and injecting dependencies into
|
||||
structs and function arguments.
|
||||
|
||||
#### func New
|
||||
|
||||
```go
|
||||
func New() Injector
|
||||
```
|
||||
New returns a new Injector.
|
||||
|
||||
#### type Invoker
|
||||
|
||||
```go
|
||||
type Invoker interface {
|
||||
// Invoke attempts to call the interface{} provided as a function,
|
||||
// providing dependencies for function arguments based on Type. Returns
|
||||
// a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
Invoke(interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
```
|
||||
|
||||
Invoker represents an interface for calling functions via reflection.
|
||||
|
||||
#### type TypeMapper
|
||||
|
||||
```go
|
||||
type TypeMapper interface {
|
||||
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
|
||||
Map(interface{}) TypeMapper
|
||||
// Maps the interface{} value based on the pointer of an Interface provided.
|
||||
// This is really only useful for mapping a value as an interface, as interfaces
|
||||
// cannot at this time be referenced directly without a pointer.
|
||||
MapTo(interface{}, interface{}) TypeMapper
|
||||
// Provides a possibility to directly insert a mapping based on type and value.
|
||||
// This makes it possible to directly map type arguments not possible to instantiate
|
||||
// with reflect like unidirectional channels.
|
||||
Set(reflect.Type, reflect.Value) TypeMapper
|
||||
// Returns the Value that is mapped to the current type. Returns a zeroed Value if
|
||||
// the Type has not been mapped.
|
||||
Get(reflect.Type) reflect.Value
|
||||
}
|
||||
```
|
||||
|
||||
TypeMapper represents an interface for mapping interface{} values based on type.
|
||||
187
plugins/common/vendor/github.com/codegangsta/inject/inject.go
generated
vendored
Normal file
187
plugins/common/vendor/github.com/codegangsta/inject/inject.go
generated
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
// Package inject provides utilities for mapping and injecting dependencies in various ways.
|
||||
package inject
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Injector represents an interface for mapping and injecting dependencies into structs
|
||||
// and function arguments.
|
||||
type Injector interface {
|
||||
Applicator
|
||||
Invoker
|
||||
TypeMapper
|
||||
// SetParent sets the parent of the injector. If the injector cannot find a
|
||||
// dependency in its Type map it will check its parent before returning an
|
||||
// error.
|
||||
SetParent(Injector)
|
||||
}
|
||||
|
||||
// Applicator represents an interface for mapping dependencies to a struct.
|
||||
type Applicator interface {
|
||||
// Maps dependencies in the Type map to each field in the struct
|
||||
// that is tagged with 'inject'. Returns an error if the injection
|
||||
// fails.
|
||||
Apply(interface{}) error
|
||||
}
|
||||
|
||||
// Invoker represents an interface for calling functions via reflection.
|
||||
type Invoker interface {
|
||||
// Invoke attempts to call the interface{} provided as a function,
|
||||
// providing dependencies for function arguments based on Type. Returns
|
||||
// a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
Invoke(interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
|
||||
// TypeMapper represents an interface for mapping interface{} values based on type.
|
||||
type TypeMapper interface {
|
||||
// Maps the interface{} value based on its immediate type from reflect.TypeOf.
|
||||
Map(interface{}) TypeMapper
|
||||
// Maps the interface{} value based on the pointer of an Interface provided.
|
||||
// This is really only useful for mapping a value as an interface, as interfaces
|
||||
// cannot at this time be referenced directly without a pointer.
|
||||
MapTo(interface{}, interface{}) TypeMapper
|
||||
// Provides a possibility to directly insert a mapping based on type and value.
|
||||
// This makes it possible to directly map type arguments not possible to instantiate
|
||||
// with reflect like unidirectional channels.
|
||||
Set(reflect.Type, reflect.Value) TypeMapper
|
||||
// Returns the Value that is mapped to the current type. Returns a zeroed Value if
|
||||
// the Type has not been mapped.
|
||||
Get(reflect.Type) reflect.Value
|
||||
}
|
||||
|
||||
type injector struct {
|
||||
values map[reflect.Type]reflect.Value
|
||||
parent Injector
|
||||
}
|
||||
|
||||
// InterfaceOf dereferences a pointer to an Interface type.
|
||||
// It panics if value is not an pointer to an interface.
|
||||
func InterfaceOf(value interface{}) reflect.Type {
|
||||
t := reflect.TypeOf(value)
|
||||
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
if t.Kind() != reflect.Interface {
|
||||
panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// New returns a new Injector.
|
||||
func New() Injector {
|
||||
return &injector{
|
||||
values: make(map[reflect.Type]reflect.Value),
|
||||
}
|
||||
}
|
||||
|
||||
// Invoke attempts to call the interface{} provided as a function,
|
||||
// providing dependencies for function arguments based on Type.
|
||||
// Returns a slice of reflect.Value representing the returned values of the function.
|
||||
// Returns an error if the injection fails.
|
||||
// It panics if f is not a function
|
||||
func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
|
||||
t := reflect.TypeOf(f)
|
||||
|
||||
var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
|
||||
for i := 0; i < t.NumIn(); i++ {
|
||||
argType := t.In(i)
|
||||
val := inj.Get(argType)
|
||||
if !val.IsValid() {
|
||||
return nil, fmt.Errorf("Value not found for type %v", argType)
|
||||
}
|
||||
|
||||
in[i] = val
|
||||
}
|
||||
|
||||
return reflect.ValueOf(f).Call(in), nil
|
||||
}
|
||||
|
||||
// Maps dependencies in the Type map to each field in the struct
|
||||
// that is tagged with 'inject'.
|
||||
// Returns an error if the injection fails.
|
||||
func (inj *injector) Apply(val interface{}) error {
|
||||
v := reflect.ValueOf(val)
|
||||
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil // Should not panic here ?
|
||||
}
|
||||
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
f := v.Field(i)
|
||||
structField := t.Field(i)
|
||||
if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
|
||||
ft := f.Type()
|
||||
v := inj.Get(ft)
|
||||
if !v.IsValid() {
|
||||
return fmt.Errorf("Value not found for type %v", ft)
|
||||
}
|
||||
|
||||
f.Set(v)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
|
||||
// It returns the TypeMapper registered in.
|
||||
func (i *injector) Map(val interface{}) TypeMapper {
|
||||
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
|
||||
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
|
||||
return i
|
||||
}
|
||||
|
||||
// Maps the given reflect.Type to the given reflect.Value and returns
|
||||
// the Typemapper the mapping has been registered in.
|
||||
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
|
||||
i.values[typ] = val
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *injector) Get(t reflect.Type) reflect.Value {
|
||||
val := i.values[t]
|
||||
|
||||
if val.IsValid() {
|
||||
return val
|
||||
}
|
||||
|
||||
// no concrete types found, try to find implementors
|
||||
// if t is an interface
|
||||
if t.Kind() == reflect.Interface {
|
||||
for k, v := range i.values {
|
||||
if k.Implements(t) {
|
||||
val = v
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Still no type found, try to look it up on the parent
|
||||
if !val.IsValid() && i.parent != nil {
|
||||
val = i.parent.Get(t)
|
||||
}
|
||||
|
||||
return val
|
||||
|
||||
}
|
||||
|
||||
func (i *injector) SetParent(parent Injector) {
|
||||
i.parent = parent
|
||||
}
|
||||
159
plugins/common/vendor/github.com/codegangsta/inject/inject_test.go
generated
vendored
Normal file
159
plugins/common/vendor/github.com/codegangsta/inject/inject_test.go
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
package inject_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/codegangsta/inject"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type SpecialString interface {
|
||||
}
|
||||
|
||||
type TestStruct struct {
|
||||
Dep1 string `inject:"t" json:"-"`
|
||||
Dep2 SpecialString `inject`
|
||||
Dep3 string
|
||||
}
|
||||
|
||||
type Greeter struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func (g *Greeter) String() string {
|
||||
return "Hello, My name is" + g.Name
|
||||
}
|
||||
|
||||
/* Test Helpers */
|
||||
func expect(t *testing.T, a interface{}, b interface{}) {
|
||||
if a != b {
|
||||
t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func refute(t *testing.T, a interface{}, b interface{}) {
|
||||
if a == b {
|
||||
t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a))
|
||||
}
|
||||
}
|
||||
|
||||
func Test_InjectorInvoke(t *testing.T) {
|
||||
injector := inject.New()
|
||||
expect(t, injector == nil, false)
|
||||
|
||||
dep := "some dependency"
|
||||
injector.Map(dep)
|
||||
dep2 := "another dep"
|
||||
injector.MapTo(dep2, (*SpecialString)(nil))
|
||||
dep3 := make(chan *SpecialString)
|
||||
dep4 := make(chan *SpecialString)
|
||||
typRecv := reflect.ChanOf(reflect.RecvDir, reflect.TypeOf(dep3).Elem())
|
||||
typSend := reflect.ChanOf(reflect.SendDir, reflect.TypeOf(dep4).Elem())
|
||||
injector.Set(typRecv, reflect.ValueOf(dep3))
|
||||
injector.Set(typSend, reflect.ValueOf(dep4))
|
||||
|
||||
_, err := injector.Invoke(func(d1 string, d2 SpecialString, d3 <-chan *SpecialString, d4 chan<- *SpecialString) {
|
||||
expect(t, d1, dep)
|
||||
expect(t, d2, dep2)
|
||||
expect(t, reflect.TypeOf(d3).Elem(), reflect.TypeOf(dep3).Elem())
|
||||
expect(t, reflect.TypeOf(d4).Elem(), reflect.TypeOf(dep4).Elem())
|
||||
expect(t, reflect.TypeOf(d3).ChanDir(), reflect.RecvDir)
|
||||
expect(t, reflect.TypeOf(d4).ChanDir(), reflect.SendDir)
|
||||
})
|
||||
|
||||
expect(t, err, nil)
|
||||
}
|
||||
|
||||
func Test_InjectorInvokeReturnValues(t *testing.T) {
|
||||
injector := inject.New()
|
||||
expect(t, injector == nil, false)
|
||||
|
||||
dep := "some dependency"
|
||||
injector.Map(dep)
|
||||
dep2 := "another dep"
|
||||
injector.MapTo(dep2, (*SpecialString)(nil))
|
||||
|
||||
result, err := injector.Invoke(func(d1 string, d2 SpecialString) string {
|
||||
expect(t, d1, dep)
|
||||
expect(t, d2, dep2)
|
||||
return "Hello world"
|
||||
})
|
||||
|
||||
expect(t, result[0].String(), "Hello world")
|
||||
expect(t, err, nil)
|
||||
}
|
||||
|
||||
func Test_InjectorApply(t *testing.T) {
|
||||
injector := inject.New()
|
||||
|
||||
injector.Map("a dep").MapTo("another dep", (*SpecialString)(nil))
|
||||
|
||||
s := TestStruct{}
|
||||
err := injector.Apply(&s)
|
||||
expect(t, err, nil)
|
||||
|
||||
expect(t, s.Dep1, "a dep")
|
||||
expect(t, s.Dep2, "another dep")
|
||||
expect(t, s.Dep3, "")
|
||||
}
|
||||
|
||||
func Test_InterfaceOf(t *testing.T) {
|
||||
iType := inject.InterfaceOf((*SpecialString)(nil))
|
||||
expect(t, iType.Kind(), reflect.Interface)
|
||||
|
||||
iType = inject.InterfaceOf((**SpecialString)(nil))
|
||||
expect(t, iType.Kind(), reflect.Interface)
|
||||
|
||||
// Expecting nil
|
||||
defer func() {
|
||||
rec := recover()
|
||||
refute(t, rec, nil)
|
||||
}()
|
||||
iType = inject.InterfaceOf((*testing.T)(nil))
|
||||
}
|
||||
|
||||
func Test_InjectorSet(t *testing.T) {
|
||||
injector := inject.New()
|
||||
typ := reflect.TypeOf("string")
|
||||
typSend := reflect.ChanOf(reflect.SendDir, typ)
|
||||
typRecv := reflect.ChanOf(reflect.RecvDir, typ)
|
||||
|
||||
// instantiating unidirectional channels is not possible using reflect
|
||||
// http://golang.org/src/pkg/reflect/value.go?s=60463:60504#L2064
|
||||
chanRecv := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, typ), 0)
|
||||
chanSend := reflect.MakeChan(reflect.ChanOf(reflect.BothDir, typ), 0)
|
||||
|
||||
injector.Set(typSend, chanSend)
|
||||
injector.Set(typRecv, chanRecv)
|
||||
|
||||
expect(t, injector.Get(typSend).IsValid(), true)
|
||||
expect(t, injector.Get(typRecv).IsValid(), true)
|
||||
expect(t, injector.Get(chanSend.Type()).IsValid(), false)
|
||||
}
|
||||
|
||||
func Test_InjectorGet(t *testing.T) {
|
||||
injector := inject.New()
|
||||
|
||||
injector.Map("some dependency")
|
||||
|
||||
expect(t, injector.Get(reflect.TypeOf("string")).IsValid(), true)
|
||||
expect(t, injector.Get(reflect.TypeOf(11)).IsValid(), false)
|
||||
}
|
||||
|
||||
func Test_InjectorSetParent(t *testing.T) {
|
||||
injector := inject.New()
|
||||
injector.MapTo("another dep", (*SpecialString)(nil))
|
||||
|
||||
injector2 := inject.New()
|
||||
injector2.SetParent(injector)
|
||||
|
||||
expect(t, injector2.Get(inject.InterfaceOf((*SpecialString)(nil))).IsValid(), true)
|
||||
}
|
||||
|
||||
func TestInjectImplementors(t *testing.T) {
|
||||
injector := inject.New()
|
||||
g := &Greeter{"Jeremy"}
|
||||
injector.Map(g)
|
||||
|
||||
expect(t, injector.Get(inject.InterfaceOf((*fmt.Stringer)(nil))).IsValid(), true)
|
||||
}
|
||||
85
plugins/common/vendor/github.com/codegangsta/inject/translations/README_zh_cn.md
generated
vendored
Normal file
85
plugins/common/vendor/github.com/codegangsta/inject/translations/README_zh_cn.md
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
# inject
|
||||
--
|
||||
import "github.com/codegangsta/inject"
|
||||
|
||||
inject包提供了多种对实体的映射和依赖注入方式。
|
||||
|
||||
## 用法
|
||||
|
||||
#### func InterfaceOf
|
||||
|
||||
```go
|
||||
func InterfaceOf(value interface{}) reflect.Type
|
||||
```
|
||||
函数InterfaceOf返回指向接口类型的指针。如果传入的value值不是指向接口的指针,将抛出一个panic异常。
|
||||
|
||||
#### type Applicator
|
||||
|
||||
```go
|
||||
type Applicator interface {
|
||||
// 在Type map中维持对结构体中每个域的引用并用'inject'来标记
|
||||
// 如果注入失败将会返回一个error.
|
||||
Apply(interface{}) error
|
||||
}
|
||||
```
|
||||
|
||||
Applicator接口表示到结构体的依赖映射关系。
|
||||
|
||||
#### type Injector
|
||||
|
||||
```go
|
||||
type Injector interface {
|
||||
Applicator
|
||||
Invoker
|
||||
TypeMapper
|
||||
// SetParent用来设置父injector. 如果在当前injector的Type map中找不到依赖,
|
||||
// 将会继续从它的父injector中找,直到返回error.
|
||||
SetParent(Injector)
|
||||
}
|
||||
```
|
||||
|
||||
Injector接口表示对结构体、函数参数的映射和依赖注入。
|
||||
|
||||
#### func New
|
||||
|
||||
```go
|
||||
func New() Injector
|
||||
```
|
||||
New创建并返回一个Injector.
|
||||
|
||||
#### type Invoker
|
||||
|
||||
```go
|
||||
type Invoker interface {
|
||||
// Invoke尝试将interface{}作为一个函数来调用,并基于Type为函数提供参数。
|
||||
// 它将返回reflect.Value的切片,其中存放原函数的返回值。
|
||||
// 如果注入失败则返回error.
|
||||
Invoke(interface{}) ([]reflect.Value, error)
|
||||
}
|
||||
```
|
||||
|
||||
Invoker接口表示通过反射进行函数调用。
|
||||
|
||||
#### type TypeMapper
|
||||
|
||||
```go
|
||||
type TypeMapper interface {
|
||||
// 基于调用reflect.TypeOf得到的类型映射interface{}的值。
|
||||
Map(interface{}) TypeMapper
|
||||
// 基于提供的接口的指针映射interface{}的值。
|
||||
// 该函数仅用来将一个值映射为接口,因为接口无法不通过指针而直接引用到。
|
||||
MapTo(interface{}, interface{}) TypeMapper
|
||||
// 为直接插入基于类型和值的map提供一种可能性。
|
||||
// 它使得这一类直接映射成为可能:无法通过反射直接实例化的类型参数,如单向管道。
|
||||
Set(reflect.Type, reflect.Value) TypeMapper
|
||||
// 返回映射到当前类型的Value. 如果Type没被映射,将返回对应的零值。
|
||||
Get(reflect.Type) reflect.Value
|
||||
}
|
||||
```
|
||||
|
||||
TypeMapper接口用来表示基于类型到接口值的映射。
|
||||
|
||||
|
||||
## 译者
|
||||
|
||||
张强 (qqbunny@yeah.net)
|
||||
3
plugins/common/vendor/github.com/codegangsta/inject/update_readme.sh
generated
vendored
Normal file
3
plugins/common/vendor/github.com/codegangsta/inject/update_readme.sh
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
go get github.com/robertkrimen/godocdown/godocdown
|
||||
godocdown > README.md
|
||||
202
plugins/common/vendor/github.com/codeskyblue/go-sh/LICENSE
generated
vendored
Normal file
202
plugins/common/vendor/github.com/codeskyblue/go-sh/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
69
plugins/common/vendor/github.com/codeskyblue/go-sh/OLD_README.md
generated
vendored
Normal file
69
plugins/common/vendor/github.com/codeskyblue/go-sh/OLD_README.md
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
## OLD README
|
||||
First give you a full example, I will explain every command below.
|
||||
|
||||
session := sh.NewSession()
|
||||
session.Env["PATH"] = "/usr/bin:/bin"
|
||||
session.Stdout = os.Stdout
|
||||
session.Stderr = os.Stderr
|
||||
session.Alias("ll", "ls", "-l")
|
||||
session.ShowCMD = true // enable for debug
|
||||
var err error
|
||||
err = session.Call("ll", "/")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ret, err := session.Capture("pwd", sh.Dir("/home")) # wraper of session.Call
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
# ret is "/home\n"
|
||||
fmt.Println(ret)
|
||||
|
||||
create a new Session
|
||||
|
||||
session := sh.NewSession()
|
||||
|
||||
use alias like this
|
||||
|
||||
session.Alias("ll", "ls", "-l") # like alias ll='ls -l'
|
||||
|
||||
set current env like this
|
||||
|
||||
session.Env["BUILD_ID"] = "123" # like export BUILD_ID=123
|
||||
|
||||
set current directory
|
||||
|
||||
session.Set(sh.Dir("/")) # like cd /
|
||||
|
||||
pipe is also supported
|
||||
|
||||
session.Command("echo", "hello\tworld").Command("cut", "-f2")
|
||||
// output should be "world"
|
||||
session.Run()
|
||||
|
||||
test, the build in command support
|
||||
|
||||
session.Test("d", "dir") // test dir
|
||||
session.Test("f", "file) // test regular file
|
||||
|
||||
with `Alias Env Set Call Capture Command` a shell scripts can be easily converted into golang program. below is a shell script.
|
||||
|
||||
#!/bin/bash -
|
||||
#
|
||||
export PATH=/usr/bin:/bin
|
||||
alias ll='ls -l'
|
||||
cd /usr
|
||||
if test -d "local"
|
||||
then
|
||||
ll local | awk '{print $1, $NF}'
|
||||
fi
|
||||
|
||||
convert to golang, will be
|
||||
|
||||
s := sh.NewSession()
|
||||
s.Env["PATH"] = "/usr/bin:/bin"
|
||||
s.Set(sh.Dir("/usr"))
|
||||
s.Alias("ll", "ls", "-l")
|
||||
if s.Test("d", "local") {
|
||||
s.Command("ll", "local").Command("awk", "{print $1, $NF}").Run()
|
||||
}
|
||||
85
plugins/common/vendor/github.com/codeskyblue/go-sh/README.md
generated
vendored
Normal file
85
plugins/common/vendor/github.com/codeskyblue/go-sh/README.md
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
## go-sh
|
||||
[](https://app.wercker.com/project/bykey/009acbd4f00ccc6de7e2554e12a50d84)
|
||||
[](http://gowalker.org/github.com/codeskyblue/go-sh)
|
||||
|
||||
*If you depend on the old api, see tag: v.0.1*
|
||||
|
||||
install: `go get github.com/codeskyblue/go-sh`
|
||||
|
||||
Pipe Example:
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/codeskyblue/go-sh"
|
||||
|
||||
func main() {
|
||||
sh.Command("echo", "hello\tworld").Command("cut", "-f2").Run()
|
||||
}
|
||||
|
||||
Because I like os/exec, `go-sh` is very much modelled after it. However, `go-sh` provides a better experience.
|
||||
|
||||
These are some of its features:
|
||||
|
||||
* keep the variable environment (e.g. export)
|
||||
* alias support (e.g. alias in shell)
|
||||
* remember current dir
|
||||
* pipe command
|
||||
* shell build-in commands echo & test
|
||||
* timeout support
|
||||
|
||||
Examples are important:
|
||||
|
||||
sh: echo hello
|
||||
go: sh.Command("echo", "hello").Run()
|
||||
|
||||
sh: export BUILD_ID=123
|
||||
go: s = sh.NewSession().SetEnv("BUILD_ID", "123")
|
||||
|
||||
sh: alias ll='ls -l'
|
||||
go: s = sh.NewSession().Alias('ll', 'ls', '-l')
|
||||
|
||||
sh: (cd /; pwd)
|
||||
go: sh.Command("pwd", sh.Dir("/")).Run()
|
||||
|
||||
sh: test -d data || mkdir data
|
||||
go: if ! sh.Test("dir", "data") { sh.Command("mkdir", "data").Run() }
|
||||
|
||||
sh: cat first second | awk '{print $1}'
|
||||
go: sh.Command("cat", "first", "second").Command("awk", "{print $1}").Run()
|
||||
|
||||
sh: count=$(echo "one two three" | wc -w)
|
||||
go: count, err := sh.Echo("one two three").Command("wc", "-w").Output()
|
||||
|
||||
sh(in ubuntu): timeout 1s sleep 3
|
||||
go: c := sh.Command("sleep", "3"); c.Start(); c.WaitTimeout(time.Second) # default SIGKILL
|
||||
go: out, err := sh.Command("sleep", "3").SetTimeout(time.Second).Output() # set session timeout and get output)
|
||||
|
||||
sh: echo hello | cat
|
||||
go: out, err := sh.Command("cat").SetInput("hello").Output()
|
||||
|
||||
sh: cat # read from stdin
|
||||
go: out, err := sh.Command("cat").SetStdin(os.Stdin).Output()
|
||||
|
||||
If you need to keep env and dir, it is better to create a session
|
||||
|
||||
session := sh.NewSession()
|
||||
session.SetEnv("BUILD_ID", "123")
|
||||
session.SetDir("/")
|
||||
# then call cmd
|
||||
session.Command("echo", "hello").Run()
|
||||
# set ShowCMD to true for easily debug
|
||||
session.ShowCMD = true
|
||||
|
||||
for more information, it better to see docs.
|
||||
[](http://gowalker.org/github.com/codeskyblue/go-sh)
|
||||
|
||||
### contribute
|
||||
If you love this project, starring it will encourage the coder. Pull requests are welcome.
|
||||
|
||||
support the author: [alipay](https://me.alipay.com/goskyblue)
|
||||
|
||||
### thanks
|
||||
this project is based on <http://github.com/codegangsta/inject>. thanks for the author.
|
||||
|
||||
# the reason to use Go shell
|
||||
Sometimes we need to write shell scripts, but shell scripts are not good at working cross platform, Go, on the other hand, is good at that. Is there a good way to use Go to write shell like scripts? Using go-sh we can do this now.
|
||||
41
plugins/common/vendor/github.com/codeskyblue/go-sh/example/example1.go
generated
vendored
Normal file
41
plugins/common/vendor/github.com/codeskyblue/go-sh/example/example1.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
func main() {
|
||||
sh.Command("echo", "hello").Run()
|
||||
out, err := sh.Command("echo", "hello").Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println("output is", string(out))
|
||||
|
||||
var a int
|
||||
sh.Command("echo", "2").UnmarshalJSON(&a)
|
||||
fmt.Println("a =", a)
|
||||
|
||||
s := sh.NewSession()
|
||||
s.Alias("hi", "echo", "hi")
|
||||
s.Command("hi", "boy").Run()
|
||||
|
||||
fmt.Print("pwd = ")
|
||||
s.Command("pwd", sh.Dir("/")).Run()
|
||||
|
||||
if !sh.Test("dir", "data") {
|
||||
sh.Command("echo", "mkdir", "data").Run()
|
||||
}
|
||||
|
||||
sh.Command("echo", "hello", "world").
|
||||
Command("awk", `{print "second arg is "$2}`).Run()
|
||||
s.ShowCMD = true
|
||||
s.Command("echo", "hello", "world").
|
||||
Command("awk", `{print "second arg is "$2}`).Run()
|
||||
|
||||
s.SetEnv("BUILD_ID", "123").Command("bash", "-c", "echo $BUILD_ID").Run()
|
||||
s.Command("bash", "-c", "echo current shell is $SHELL").Run()
|
||||
}
|
||||
7
plugins/common/vendor/github.com/codeskyblue/go-sh/example/less/less.go
generated
vendored
Normal file
7
plugins/common/vendor/github.com/codeskyblue/go-sh/example/less/less.go
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
import "github.com/codeskyblue/go-sh"
|
||||
|
||||
func main() {
|
||||
sh.Command("less", "less.go").Run()
|
||||
}
|
||||
17
plugins/common/vendor/github.com/codeskyblue/go-sh/example/tail/tailf.go
generated
vendored
Normal file
17
plugins/common/vendor/github.com/codeskyblue/go-sh/example/tail/tailf.go
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
"github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if flag.NArg() != 1 {
|
||||
fmt.Println("Usage: PROGRAM <file>")
|
||||
return
|
||||
}
|
||||
sh.Command("tail", "-f", flag.Arg(0)).Run()
|
||||
}
|
||||
23
plugins/common/vendor/github.com/codeskyblue/go-sh/example/timeout/timeout.go
generated
vendored
Normal file
23
plugins/common/vendor/github.com/codeskyblue/go-sh/example/timeout/timeout.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
sh "github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
func main() {
|
||||
c := sh.Command("sleep", "3")
|
||||
c.Start()
|
||||
err := c.WaitTimeout(time.Second * 1)
|
||||
if err != nil {
|
||||
fmt.Printf("timeout should happend: %v\n", err)
|
||||
}
|
||||
// timeout should be a session
|
||||
out, err := sh.Command("sleep", "2").SetTimeout(time.Second).Output()
|
||||
fmt.Printf("output:(%s), err(%v)\n", string(out), err)
|
||||
|
||||
out, err = sh.Command("echo", "hello").SetTimeout(time.Second).Output()
|
||||
fmt.Printf("output:(%s), err(%v)\n", string(out), err)
|
||||
}
|
||||
28
plugins/common/vendor/github.com/codeskyblue/go-sh/example_test.go
generated
vendored
Normal file
28
plugins/common/vendor/github.com/codeskyblue/go-sh/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
package sh_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
func ExampleCommand() {
|
||||
out, err := sh.Command("echo", "hello").Output()
|
||||
fmt.Println(string(out), err)
|
||||
}
|
||||
|
||||
func ExampleCommandPipe() {
|
||||
out, err := sh.Command("echo", "-n", "hi").Command("wc", "-c").Output()
|
||||
fmt.Println(string(out), err)
|
||||
}
|
||||
|
||||
func ExampleCommandSetDir() {
|
||||
out, err := sh.Command("pwd", sh.Dir("/")).Output()
|
||||
fmt.Println(string(out), err)
|
||||
}
|
||||
|
||||
func ExampleTest() {
|
||||
if sh.Test("dir", "mydir") {
|
||||
fmt.Println("mydir exists")
|
||||
}
|
||||
}
|
||||
148
plugins/common/vendor/github.com/codeskyblue/go-sh/pipe.go
generated
vendored
Normal file
148
plugins/common/vendor/github.com/codeskyblue/go-sh/pipe.go
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
var ErrExecTimeout = errors.New("execute timeout")
|
||||
|
||||
// unmarshal shell output to decode json
|
||||
func (s *Session) UnmarshalJSON(data interface{}) (err error) {
|
||||
bufrw := bytes.NewBuffer(nil)
|
||||
s.Stdout = bufrw
|
||||
if err = s.Run(); err != nil {
|
||||
return
|
||||
}
|
||||
return json.NewDecoder(bufrw).Decode(data)
|
||||
}
|
||||
|
||||
// unmarshal command output into xml
|
||||
func (s *Session) UnmarshalXML(data interface{}) (err error) {
|
||||
bufrw := bytes.NewBuffer(nil)
|
||||
s.Stdout = bufrw
|
||||
if err = s.Run(); err != nil {
|
||||
return
|
||||
}
|
||||
return xml.NewDecoder(bufrw).Decode(data)
|
||||
}
|
||||
|
||||
// start command
|
||||
func (s *Session) Start() (err error) {
|
||||
s.started = true
|
||||
var rd *io.PipeReader
|
||||
var wr *io.PipeWriter
|
||||
var length = len(s.cmds)
|
||||
if s.ShowCMD {
|
||||
var cmds = make([]string, 0, 4)
|
||||
for _, cmd := range s.cmds {
|
||||
cmds = append(cmds, strings.Join(cmd.Args, " "))
|
||||
}
|
||||
s.writePrompt(strings.Join(cmds, " | "))
|
||||
}
|
||||
for index, cmd := range s.cmds {
|
||||
if index == 0 {
|
||||
cmd.Stdin = s.Stdin
|
||||
} else {
|
||||
cmd.Stdin = rd
|
||||
}
|
||||
if index != length {
|
||||
rd, wr = io.Pipe() // create pipe
|
||||
cmd.Stdout = wr
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
if index == length-1 {
|
||||
cmd.Stdout = s.Stdout
|
||||
cmd.Stderr = s.Stderr
|
||||
}
|
||||
err = cmd.Start()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Should be call after Start()
|
||||
// only catch the last command error
|
||||
func (s *Session) Wait() (err error) {
|
||||
for _, cmd := range s.cmds {
|
||||
err = cmd.Wait()
|
||||
wr, ok := cmd.Stdout.(*io.PipeWriter)
|
||||
if ok {
|
||||
wr.Close()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Session) Kill(sig os.Signal) {
|
||||
for _, cmd := range s.cmds {
|
||||
if cmd.Process != nil {
|
||||
cmd.Process.Signal(sig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Session) WaitTimeout(timeout time.Duration) (err error) {
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
s.Kill(syscall.SIGKILL)
|
||||
return ErrExecTimeout
|
||||
case err = <-Go(s.Wait):
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
func Go(f func() error) chan error {
|
||||
ch := make(chan error)
|
||||
go func() {
|
||||
ch <- f()
|
||||
}()
|
||||
return ch
|
||||
}
|
||||
|
||||
func (s *Session) Run() (err error) {
|
||||
if err = s.Start(); err != nil {
|
||||
return
|
||||
}
|
||||
if s.timeout != time.Duration(0) {
|
||||
return s.WaitTimeout(s.timeout)
|
||||
}
|
||||
return s.Wait()
|
||||
}
|
||||
|
||||
func (s *Session) Output() (out []byte, err error) {
|
||||
oldout := s.Stdout
|
||||
defer func() {
|
||||
s.Stdout = oldout
|
||||
}()
|
||||
stdout := bytes.NewBuffer(nil)
|
||||
s.Stdout = stdout
|
||||
err = s.Run()
|
||||
out = stdout.Bytes()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Session) CombinedOutput() (out []byte, err error) {
|
||||
oldout := s.Stdout
|
||||
olderr := s.Stderr
|
||||
defer func() {
|
||||
s.Stdout = oldout
|
||||
s.Stderr = olderr
|
||||
}()
|
||||
stdout := bytes.NewBuffer(nil)
|
||||
s.Stdout = stdout
|
||||
s.Stderr = stdout
|
||||
|
||||
err = s.Run()
|
||||
out = stdout.Bytes()
|
||||
return
|
||||
}
|
||||
126
plugins/common/vendor/github.com/codeskyblue/go-sh/pipe_test.go
generated
vendored
Normal file
126
plugins/common/vendor/github.com/codeskyblue/go-sh/pipe_test.go
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestUnmarshalJSON(t *testing.T) {
|
||||
var a int
|
||||
s := NewSession()
|
||||
s.ShowCMD = true
|
||||
err := s.Command("echo", []string{"1"}).UnmarshalJSON(&a)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if a != 1 {
|
||||
t.Errorf("expect a tobe 1, but got %d", a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalXML(t *testing.T) {
|
||||
s := NewSession()
|
||||
xmlSample := `<?xml version="1.0" encoding="utf-8"?>
|
||||
<server version="1" />`
|
||||
type server struct {
|
||||
XMLName xml.Name `xml:"server"`
|
||||
Version string `xml:"version,attr"`
|
||||
}
|
||||
data := &server{}
|
||||
s.Command("echo", xmlSample).UnmarshalXML(data)
|
||||
if data.Version != "1" {
|
||||
t.Error(data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPipe(t *testing.T) {
|
||||
s := NewSession()
|
||||
s.ShowCMD = true
|
||||
s.Call("echo", "hello")
|
||||
err := s.Command("echo", "hi").Command("cat", "-n").Start()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = s.Wait()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
out, err := s.Command("echo", []string{"hello"}).Output()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(out) != "hello\n" {
|
||||
t.Error("capture wrong output:", out)
|
||||
}
|
||||
s.Command("echo", []string{"hello\tworld"}).Command("cut", []string{"-f2"}).Run()
|
||||
}
|
||||
|
||||
func TestPipeCommand(t *testing.T) {
|
||||
c1 := exec.Command("echo", "good")
|
||||
rd, wr := io.Pipe()
|
||||
c1.Stdout = wr
|
||||
c2 := exec.Command("cat", "-n")
|
||||
c2.Stdout = os.Stdout
|
||||
c2.Stdin = rd
|
||||
c1.Start()
|
||||
c2.Start()
|
||||
|
||||
c1.Wait()
|
||||
wc, ok := c1.Stdout.(io.WriteCloser)
|
||||
if ok {
|
||||
wc.Close()
|
||||
}
|
||||
c2.Wait()
|
||||
}
|
||||
|
||||
func TestPipeInput(t *testing.T) {
|
||||
s := NewSession()
|
||||
s.ShowCMD = true
|
||||
s.SetInput("first line\nsecond line\n")
|
||||
out, err := s.Command("grep", "second").Output()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(out) != "second line\n" {
|
||||
t.Error("capture wrong output:", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimeout(t *testing.T) {
|
||||
s := NewSession()
|
||||
err := s.Command("sleep", "2").Start()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = s.WaitTimeout(time.Second)
|
||||
if err != ErrExecTimeout {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetTimeout(t *testing.T) {
|
||||
s := NewSession()
|
||||
s.SetTimeout(time.Second)
|
||||
defer s.SetTimeout(0)
|
||||
err := s.Command("sleep", "2").Run()
|
||||
if err != ErrExecTimeout {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCombinedOutput(t *testing.T) {
|
||||
s := NewSession()
|
||||
bytes, err := s.Command("sh", "-c", "echo stderr >&2 ; echo stdout").CombinedOutput()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
stringOutput := string(bytes)
|
||||
if !(strings.Contains(stringOutput, "stdout") && strings.Contains(stringOutput, "stderr")) {
|
||||
t.Errorf("expect output from both output streams, got '%s'", strings.TrimSpace(stringOutput))
|
||||
}
|
||||
}
|
||||
200
plugins/common/vendor/github.com/codeskyblue/go-sh/sh.go
generated
vendored
Normal file
200
plugins/common/vendor/github.com/codeskyblue/go-sh/sh.go
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
Package go-sh is intented to make shell call with golang more easily.
|
||||
Some usage is more similar to os/exec, eg: Run(), Output(), Command(name, args...)
|
||||
|
||||
But with these similar function, pipe is added in and this package also got shell-session support.
|
||||
|
||||
Why I love golang so much, because the usage of golang is simple, but the power is unlimited. I want to make this pakcage got the sample style like golang.
|
||||
|
||||
// just like os/exec
|
||||
sh.Command("echo", "hello").Run()
|
||||
|
||||
// support pipe
|
||||
sh.Command("echo", "hello").Command("wc", "-c").Run()
|
||||
|
||||
// create a session to store dir and env
|
||||
sh.NewSession().SetDir("/").Command("pwd")
|
||||
|
||||
// shell buildin command - "test"
|
||||
sh.Test("dir", "mydir")
|
||||
|
||||
// like shell call: (cd /; pwd)
|
||||
sh.Command("pwd", sh.Dir("/")) same with sh.Command(sh.Dir("/"), "pwd")
|
||||
|
||||
// output to json and xml easily
|
||||
v := map[string] int {}
|
||||
err = sh.Command("echo", `{"number": 1}`).UnmarshalJSON(&v)
|
||||
*/
|
||||
package sh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/inject"
|
||||
)
|
||||
|
||||
type Dir string
|
||||
|
||||
type Session struct {
|
||||
inj inject.Injector
|
||||
alias map[string][]string
|
||||
cmds []*exec.Cmd
|
||||
dir Dir
|
||||
started bool
|
||||
Env map[string]string
|
||||
Stdin io.Reader
|
||||
Stdout io.Writer
|
||||
Stderr io.Writer
|
||||
ShowCMD bool // enable for debug
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (s *Session) writePrompt(args ...interface{}) {
|
||||
var ps1 = fmt.Sprintf("[golang-sh]$")
|
||||
args = append([]interface{}{ps1}, args...)
|
||||
fmt.Fprintln(s.Stderr, args...)
|
||||
}
|
||||
|
||||
func NewSession() *Session {
|
||||
env := make(map[string]string)
|
||||
for _, key := range []string{"PATH"} {
|
||||
env[key] = os.Getenv(key)
|
||||
}
|
||||
s := &Session{
|
||||
inj: inject.New(),
|
||||
alias: make(map[string][]string),
|
||||
dir: Dir(""),
|
||||
Stdin: strings.NewReader(""),
|
||||
Stdout: os.Stdout,
|
||||
Stderr: os.Stderr,
|
||||
Env: env,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func InteractiveSession() *Session {
|
||||
s := NewSession()
|
||||
s.SetStdin(os.Stdin)
|
||||
return s
|
||||
}
|
||||
|
||||
func Command(name string, a ...interface{}) *Session {
|
||||
s := NewSession()
|
||||
return s.Command(name, a...)
|
||||
}
|
||||
|
||||
func Echo(in string) *Session {
|
||||
s := NewSession()
|
||||
return s.SetInput(in)
|
||||
}
|
||||
|
||||
func (s *Session) Alias(alias, cmd string, args ...string) {
|
||||
v := []string{cmd}
|
||||
v = append(v, args...)
|
||||
s.alias[alias] = v
|
||||
}
|
||||
|
||||
func (s *Session) Command(name string, a ...interface{}) *Session {
|
||||
var args = make([]string, 0)
|
||||
var sType = reflect.TypeOf("")
|
||||
|
||||
// init cmd, args, dir, envs
|
||||
// if not init, program may panic
|
||||
s.inj.Map(name).Map(args).Map(s.dir).Map(map[string]string{})
|
||||
for _, v := range a {
|
||||
switch reflect.TypeOf(v) {
|
||||
case sType:
|
||||
args = append(args, v.(string))
|
||||
default:
|
||||
s.inj.Map(v)
|
||||
}
|
||||
}
|
||||
if len(args) != 0 {
|
||||
s.inj.Map(args)
|
||||
}
|
||||
s.inj.Invoke(s.appendCmd)
|
||||
return s
|
||||
}
|
||||
|
||||
// combine Command and Run
|
||||
func (s *Session) Call(name string, a ...interface{}) error {
|
||||
return s.Command(name, a...).Run()
|
||||
}
|
||||
|
||||
/*
|
||||
func (s *Session) Exec(cmd string, args ...string) error {
|
||||
return s.Call(cmd, args)
|
||||
}
|
||||
*/
|
||||
|
||||
func (s *Session) SetEnv(key, value string) *Session {
|
||||
s.Env[key] = value
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) SetDir(dir string) *Session {
|
||||
s.dir = Dir(dir)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) SetInput(in string) *Session {
|
||||
s.Stdin = strings.NewReader(in)
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) SetStdin(r io.Reader) *Session {
|
||||
s.Stdin = r
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Session) SetTimeout(d time.Duration) *Session {
|
||||
s.timeout = d
|
||||
return s
|
||||
}
|
||||
|
||||
func newEnviron(env map[string]string, inherit bool) []string { //map[string]string {
|
||||
environ := make([]string, 0, len(env))
|
||||
if inherit {
|
||||
for _, line := range os.Environ() {
|
||||
for k, _ := range env {
|
||||
if strings.HasPrefix(line, k+"=") {
|
||||
goto CONTINUE
|
||||
}
|
||||
}
|
||||
environ = append(environ, line)
|
||||
CONTINUE:
|
||||
}
|
||||
}
|
||||
for k, v := range env {
|
||||
environ = append(environ, k+"="+v)
|
||||
}
|
||||
return environ
|
||||
}
|
||||
|
||||
func (s *Session) appendCmd(cmd string, args []string, cwd Dir, env map[string]string) {
|
||||
if s.started {
|
||||
s.started = false
|
||||
s.cmds = make([]*exec.Cmd, 0)
|
||||
}
|
||||
for k, v := range s.Env {
|
||||
if _, ok := env[k]; !ok {
|
||||
env[k] = v
|
||||
}
|
||||
}
|
||||
environ := newEnviron(s.Env, true) // true: inherit sys-env
|
||||
v, ok := s.alias[cmd]
|
||||
if ok {
|
||||
cmd = v[0]
|
||||
args = append(v[1:], args...)
|
||||
}
|
||||
c := exec.Command(cmd, args...)
|
||||
c.Env = environ
|
||||
c.Dir = string(cwd)
|
||||
s.cmds = append(s.cmds, c)
|
||||
}
|
||||
106
plugins/common/vendor/github.com/codeskyblue/go-sh/sh_test.go
generated
vendored
Normal file
106
plugins/common/vendor/github.com/codeskyblue/go-sh/sh_test.go
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAlias(t *testing.T) {
|
||||
s := NewSession()
|
||||
s.Alias("gr", "echo", "hi")
|
||||
out, err := s.Command("gr", "sky").Output()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(out) != "hi sky\n" {
|
||||
t.Errorf("expect 'hi sky' but got:%s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleSession_Command() {
|
||||
s := NewSession()
|
||||
out, err := s.Command("echo", "hello").Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
// Output: hello
|
||||
}
|
||||
|
||||
func ExampleSession_Command_pipe() {
|
||||
s := NewSession()
|
||||
out, err := s.Command("echo", "hello", "world").Command("awk", "{print $2}").Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
// Output: world
|
||||
}
|
||||
|
||||
func ExampleSession_Alias() {
|
||||
s := NewSession()
|
||||
s.Alias("alias_echo_hello", "echo", "hello")
|
||||
out, err := s.Command("alias_echo_hello", "world").Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
// Output: hello world
|
||||
}
|
||||
|
||||
func TestEcho(t *testing.T) {
|
||||
out, err := Echo("one two three").Command("wc", "-w").Output()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if strings.TrimSpace(string(out)) != "3" {
|
||||
t.Errorf("expect '3' but got:%s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSession(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Log("ignore test on windows")
|
||||
return
|
||||
}
|
||||
session := NewSession()
|
||||
session.ShowCMD = true
|
||||
err := session.Call("pwd")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
out, err := session.SetDir("/").Command("pwd").Output()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if string(out) != "/\n" {
|
||||
t.Errorf("expect /, but got %s", string(out))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#!/bin/bash -
|
||||
#
|
||||
export PATH=/usr/bin:/bin
|
||||
alias ll='ls -l'
|
||||
cd /usr
|
||||
if test -d "local"
|
||||
then
|
||||
ll local | awk '{print $1, $NF}' | grep bin
|
||||
fi
|
||||
*/
|
||||
func Example(t *testing.T) {
|
||||
s := NewSession()
|
||||
//s.ShowCMD = true
|
||||
s.Env["PATH"] = "/usr/bin:/bin"
|
||||
s.SetDir("/bin")
|
||||
s.Alias("ll", "ls", "-l")
|
||||
|
||||
if s.Test("d", "local") {
|
||||
//s.Command("ll", []string{"local"}).Command("awk", []string{"{print $1, $NF}"}).Command("grep", []string{"bin"}).Run()
|
||||
s.Command("ll", "local").Command("awk", "{print $1, $NF}").Command("grep", "bin").Run()
|
||||
}
|
||||
}
|
||||
64
plugins/common/vendor/github.com/codeskyblue/go-sh/test.go
generated
vendored
Normal file
64
plugins/common/vendor/github.com/codeskyblue/go-sh/test.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
package sh
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func filetest(name string, modemask os.FileMode) (match bool, err error) {
|
||||
fi, err := os.Stat(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
match = (fi.Mode() & modemask) == modemask
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Session) pwd() string {
|
||||
dir := string(s.dir)
|
||||
if dir == "" {
|
||||
dir, _ = os.Getwd()
|
||||
}
|
||||
return dir
|
||||
}
|
||||
|
||||
func (s *Session) abspath(name string) string {
|
||||
if filepath.IsAbs(name) {
|
||||
return name
|
||||
}
|
||||
return filepath.Join(s.pwd(), name)
|
||||
}
|
||||
|
||||
func init() {
|
||||
//log.SetFlags(log.Lshortfile | log.LstdFlags)
|
||||
}
|
||||
|
||||
// expression can be dir, file, link
|
||||
func (s *Session) Test(expression string, argument string) bool {
|
||||
var err error
|
||||
var fi os.FileInfo
|
||||
fi, err = os.Lstat(s.abspath(argument))
|
||||
switch expression {
|
||||
case "d", "dir":
|
||||
return err == nil && fi.IsDir()
|
||||
case "f", "file":
|
||||
return err == nil && fi.Mode().IsRegular()
|
||||
case "x", "executable":
|
||||
/*
|
||||
fmt.Println(expression, argument)
|
||||
if err == nil {
|
||||
fmt.Println(fi.Mode())
|
||||
}
|
||||
*/
|
||||
return err == nil && fi.Mode()&os.FileMode(0100) != 0
|
||||
case "L", "link":
|
||||
return err == nil && fi.Mode()&os.ModeSymlink != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// expression can be d,dir, f,file, link
|
||||
func Test(exp string, arg string) bool {
|
||||
s := NewSession()
|
||||
return s.Test(exp, arg)
|
||||
}
|
||||
58
plugins/common/vendor/github.com/codeskyblue/go-sh/test_test.go
generated
vendored
Normal file
58
plugins/common/vendor/github.com/codeskyblue/go-sh/test_test.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package sh_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/codeskyblue/go-sh"
|
||||
)
|
||||
|
||||
var s = sh.NewSession()
|
||||
|
||||
type T struct{ *testing.T }
|
||||
|
||||
func NewT(t *testing.T) *T {
|
||||
return &T{t}
|
||||
}
|
||||
|
||||
func (t *T) checkTest(exp string, arg string, result bool) {
|
||||
r := s.Test(exp, arg)
|
||||
if r != result {
|
||||
t.Errorf("test -%s %s, %v != %v", exp, arg, r, result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTest(i *testing.T) {
|
||||
t := NewT(i)
|
||||
t.checkTest("d", "../go-sh", true)
|
||||
t.checkTest("d", "./yymm", false)
|
||||
|
||||
// file test
|
||||
t.checkTest("f", "testdata/hello.txt", true)
|
||||
t.checkTest("f", "testdata/xxxxx", false)
|
||||
t.checkTest("f", "testdata/yymm", false)
|
||||
|
||||
// link test
|
||||
t.checkTest("link", "testdata/linkfile", true)
|
||||
t.checkTest("link", "testdata/xxxxxlinkfile", false)
|
||||
t.checkTest("link", "testdata/hello.txt", false)
|
||||
|
||||
// executable test
|
||||
t.checkTest("x", "testdata/executable", true)
|
||||
t.checkTest("x", "testdata/xxxxx", false)
|
||||
t.checkTest("x", "testdata/hello.txt", false)
|
||||
}
|
||||
|
||||
func ExampleShellTest(t *testing.T) {
|
||||
// test -L
|
||||
sh.Test("link", "testdata/linkfile")
|
||||
sh.Test("L", "testdata/linkfile")
|
||||
// test -f
|
||||
sh.Test("file", "testdata/file")
|
||||
sh.Test("f", "testdata/file")
|
||||
// test -x
|
||||
sh.Test("executable", "testdata/binfile")
|
||||
sh.Test("x", "testdata/binfile")
|
||||
// test -d
|
||||
sh.Test("dir", "testdata/dir")
|
||||
sh.Test("d", "testdata/dir")
|
||||
}
|
||||
0
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/executable
generated
vendored
Executable file
0
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/executable
generated
vendored
Executable file
0
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/hello.txt
generated
vendored
Normal file
0
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/hello.txt
generated
vendored
Normal file
1
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/linkfile
generated
vendored
Symbolic link
1
plugins/common/vendor/github.com/codeskyblue/go-sh/testdata/linkfile
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
hello.txt
|
||||
28
plugins/common/vendor/github.com/codeskyblue/go-sh/wercker.yml
generated
vendored
Normal file
28
plugins/common/vendor/github.com/codeskyblue/go-sh/wercker.yml
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
box: wercker/golang
|
||||
# Build definition
|
||||
build:
|
||||
# The steps that will be executed on build
|
||||
steps:
|
||||
# Sets the go workspace and places you package
|
||||
# at the right place in the workspace tree
|
||||
- setup-go-workspace
|
||||
|
||||
# Gets the dependencies
|
||||
- script:
|
||||
name: go get
|
||||
code: |
|
||||
cd $WERCKER_SOURCE_DIR
|
||||
go version
|
||||
go get -t .
|
||||
|
||||
# Build the project
|
||||
- script:
|
||||
name: go build
|
||||
code: |
|
||||
go build .
|
||||
|
||||
# Test the project
|
||||
- script:
|
||||
name: go test
|
||||
code: |
|
||||
go test -v ./...
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core config plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core docker-options plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -10,6 +10,7 @@ docker_options_remove_cmd() {
|
||||
verify_app_name "$2" && local APP="$2"
|
||||
read -ra passed_phases <<< "$(get_phases "$3")"
|
||||
shift 3 # everything else passed is the docker option
|
||||
# shellcheck disable=SC2154
|
||||
[[ -z ${passed_docker_option="$@"} ]] && dokku_log_fail "Please specify docker options to add to the phase"
|
||||
remove_passed_docker_option passed_phases[@] "${passed_docker_option[@]}"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core domains plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core enter plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -12,7 +12,7 @@ enter_default_cmd() {
|
||||
if [[ -z "$3" ]]; then
|
||||
if [[ ${#AVAILABLE_CONTAINER_TYPES[@]} -gt 1 ]]; then
|
||||
dokku_log_warn "No container type specified."
|
||||
dokku_log_fail "Available types for app ($APP): ${AVAILABLE_CONTAINER_TYPES[@]}"
|
||||
dokku_log_fail "Available types for app ($APP): ${AVAILABLE_CONTAINER_TYPES[*]}"
|
||||
else
|
||||
CONTAINER_TYPE="${AVAILABLE_CONTAINER_TYPES[0]}"
|
||||
fi
|
||||
@@ -22,11 +22,11 @@ enter_default_cmd() {
|
||||
local DOKKU_APP_CIDS=( $(get_app_container_ids "$APP") )
|
||||
if [[ ! -n "$4" ]]; then
|
||||
dokku_log_warn "No container id specified."
|
||||
dokku_log_fail "Available ids for app ($APP): ${DOKKU_APP_CIDS[@]}"
|
||||
dokku_log_fail "Available ids for app ($APP): ${DOKKU_APP_CIDS[*]}"
|
||||
fi
|
||||
if ! (printf -- '%s\n' "${DOKKU_APP_CIDS[@]}" | grep -q -e "^$4"); then
|
||||
dokku_log_warn "Invalid container id for app"
|
||||
dokku_log_fail "Available ids for app ($APP): ${DOKKU_APP_CIDS[@]}"
|
||||
dokku_log_fail "Available ids for app ($APP): ${DOKKU_APP_CIDS[*]}"
|
||||
fi
|
||||
local ID=$(printf -- '%s\n' "${DOKKU_APP_CIDS[@]}" | grep -e "^$4")
|
||||
shift 4
|
||||
@@ -35,7 +35,7 @@ enter_default_cmd() {
|
||||
local ID=${DOKKU_APP_CIDS[0]}
|
||||
if [[ ! -n $ID ]]; then
|
||||
dokku_log_warn "No containers found for type '$CONTAINER_TYPE'"
|
||||
dokku_log_fail "Available types for app ($APP): ${AVAILABLE_CONTAINER_TYPES[@]}"
|
||||
dokku_log_fail "Available types for app ($APP): ${AVAILABLE_CONTAINER_TYPES[*]}"
|
||||
fi
|
||||
if [[ $3 ]]; then
|
||||
shift 3
|
||||
|
||||
@@ -4,6 +4,23 @@ source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/apps/functions"
|
||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
||||
|
||||
use_git_worktree() {
|
||||
declare desc="detects whether to use git worktree"
|
||||
local GIT_VERSION MAJOR_VERSION MINOR_VERSION
|
||||
|
||||
GIT_VERSION=$(git --version | awk '{split($0,a," "); print a[3]}')
|
||||
MAJOR_VERSION=$(echo "$GIT_VERSION" | awk '{split($0,a,"."); print a[1]}')
|
||||
MINOR_VERSION=$(echo "$GIT_VERSION" | awk '{split($0,a,"."); print a[2]}')
|
||||
|
||||
if [[ "$MAJOR_VERSION" -ge "3" ]]; then
|
||||
return 0
|
||||
elif [[ "$MAJOR_VERSION" -eq "2" ]] && [[ "$MINOR_VERSION" -ge "11" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
git_build_app_repo() {
|
||||
declare desc="builds local git app repo for app"
|
||||
verify_app_name "$1"
|
||||
@@ -13,26 +30,37 @@ git_build_app_repo() {
|
||||
local GIT_BUILD_APP_REPO_TMP_WORK_DIR=$(mktemp -d "/tmp/dokku_git.XXXX")
|
||||
trap 'rm -rf "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null' RETURN INT TERM EXIT
|
||||
|
||||
# git clone - this method creates a new git repository and adds the primary
|
||||
# repo as a remote, then does a fetch depth=1 to avoid cloning
|
||||
# the entire repo
|
||||
local TMP_TAG="dokku/$REV"
|
||||
chmod 755 "$GIT_BUILD_APP_REPO_TMP_WORK_DIR"
|
||||
unset GIT_DIR GIT_WORK_TREE
|
||||
pushd "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null
|
||||
[[ ! -d "$DOKKU_ROOT/$APP" ]] && apps_create "$APP"
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag "$TMP_TAG" "$REV" &> /dev/null
|
||||
git init &> /dev/null
|
||||
git config advice.detachedHead false
|
||||
git remote add origin "$DOKKU_ROOT/$APP" &> /dev/null
|
||||
git fetch --depth=1 origin "refs/tags/$TMP_TAG" &> /dev/null
|
||||
git reset --hard FETCH_HEAD &> /dev/null
|
||||
suppress_output git submodule update --init --recursive
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true
|
||||
find -name .git -prune -exec rm -rf {} \; > /dev/null
|
||||
|
||||
plugn trigger post-extract "$APP" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV"
|
||||
if use_git_worktree; then
|
||||
# git worktree - this method uses git worktree which was introduced in git 2.5
|
||||
git worktree add "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" > /dev/null
|
||||
pushd "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null
|
||||
else
|
||||
# git clone - this method creates a new git repository and adds the primary
|
||||
# repo as a remote, then does a fetch depth=1 to avoid cloning
|
||||
# the entire repo.
|
||||
# Not working for git >= 2.11.0 due to changes introduced
|
||||
# in this merge:
|
||||
# https://github.com/git/git/commit/25ab004c53cdcfea485e5bf437aeaa74df47196d
|
||||
pushd "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" > /dev/null
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag "$TMP_TAG" "$REV" &> /dev/null
|
||||
git init &> /dev/null
|
||||
git config advice.detachedHead false
|
||||
git remote add origin "$DOKKU_ROOT/$APP" &> /dev/null
|
||||
git fetch --depth=1 origin "refs/tags/$TMP_TAG" &> /dev/null
|
||||
git reset --hard FETCH_HEAD &> /dev/null
|
||||
GIT_DIR="$DOKKU_ROOT/$APP" git tag -d "$TMP_TAG" &> /dev/null || true
|
||||
fi
|
||||
|
||||
suppress_output git submodule update --init --recursive
|
||||
find . -name .git -prune -exec rm -rf {} \; > /dev/null
|
||||
|
||||
plugn trigger post-extract "$APP" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV" | sed -u "s/^/"$'\e[1G'"/"
|
||||
|
||||
if [[ -f Dockerfile ]] && [[ "$([[ -f .env ]] && grep -q BUILDPACK_URL .env; echo $?)" != "0" ]] && [[ ! -f ".buildpacks" ]] && [[ -z $(config_get "$APP" BUILDPACK_URL || true) ]]; then
|
||||
plugn trigger pre-receive-app "$APP" "dockerfile" "$GIT_BUILD_APP_REPO_TMP_WORK_DIR" "$REV"
|
||||
@@ -79,7 +107,7 @@ git_hook_cmd() {
|
||||
local APP="$2"
|
||||
local DOKKU_DEPLOY_BRANCH="$(git_deploy_branch "$APP")"
|
||||
|
||||
if ! git check-ref-format --branch "$DOKKU_DEPLOY_BRANCH" 2> /dev/null; then
|
||||
if ! git check-ref-format --branch "$DOKKU_DEPLOY_BRANCH" > /dev/null 2>&1; then
|
||||
echo $'\e[1G\e[K'"-----> WARNING: Invalid branch name '$DOKKU_DEPLOY_BRANCH' specified via DOKKU_DEPLOY_BRANCH."
|
||||
echo $'\e[1G\e[K'"-----> For more details, please see the man page for 'git-check-ref-format.'"
|
||||
return
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core git plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core logs plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -17,7 +17,8 @@ logs_default_cmd() {
|
||||
|
||||
shift 2;
|
||||
local TEMP=$(getopt -o htqn:p: --long help,tail,quiet,num:,ps: -n 'dokku logs' -- "$@")
|
||||
if [[ $? != 0 ]]; then usage >&2 ; exit 1 ; fi
|
||||
local EXIT_CODE="$?"
|
||||
if [[ "$EXIT_CODE" != 0 ]]; then usage >&2 ; exit 1 ; fi
|
||||
eval set -- "$TEMP"
|
||||
|
||||
local DOKKU_LOGS_LINE_NUMBERS="100"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core named containers plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -28,6 +28,8 @@ chmod 0440 /etc/sudoers.d/dokku-nginx
|
||||
|
||||
# if dokku.conf has not been created, create it
|
||||
if [[ ! -f /etc/nginx/conf.d/dokku.conf ]]; then
|
||||
mkdir -p /etc/nginx/conf.d
|
||||
chown root:root /etc/nginx/conf.d
|
||||
cat<<EOF > /etc/nginx/conf.d/dokku.conf
|
||||
include $DOKKU_ROOT/*/nginx.conf;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core nginx-vhosts plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -38,8 +38,8 @@ server {
|
||||
}
|
||||
{{ else if eq $scheme "https"}}
|
||||
server {
|
||||
listen [::]:{{ $listen_port }} ssl {{ if eq $.SPDY_SUPPORTED "true" }}spdy{{ else if eq $.HTTP2_SUPPORTED "true" }}http2{{ end }};
|
||||
listen {{ $listen_port }} ssl {{ if eq $.SPDY_SUPPORTED "true" }}spdy{{ else if eq $.HTTP2_SUPPORTED "true" }}http2{{ end }};
|
||||
listen [::]:{{ $listen_port }} ssl {{ if eq $.HTTP2_SUPPORTED "true" }}http2{{ else if eq $.SPDY_SUPPORTED "true" }}spdy{{ end }};
|
||||
listen {{ $listen_port }} ssl {{ if eq $.HTTP2_SUPPORTED "true" }}http2{{ else if eq $.SPDY_SUPPORTED "true" }}spdy{{ end }};
|
||||
{{ if $.SSL_SERVER_NAME }}server_name {{ $.SSL_SERVER_NAME }}; {{ end }}
|
||||
{{ if $.NOSSL_SERVER_NAME }}server_name {{ $.NOSSL_SERVER_NAME }}; {{ end }}
|
||||
access_log /var/log/nginx/{{ $.APP }}-access.log;
|
||||
@@ -50,7 +50,7 @@ server {
|
||||
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
|
||||
|
||||
keepalive_timeout 70;
|
||||
{{ if eq $.SPDY_SUPPORTED "true" }}add_header Alternate-Protocol {{ $.NGINX_SSL_PORT }}:npn-spdy/2;{{ end }}
|
||||
{{ if and (eq $.SPDY_SUPPORTED "true") (ne $.HTTP2_SUPPORTED "true") }}add_header Alternate-Protocol {{ $.NGINX_SSL_PORT }}:npn-spdy/2;{{ end }}
|
||||
|
||||
location / {
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core plugin plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core proxy plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
@@ -77,9 +77,9 @@ set_scale() {
|
||||
for procscale in "${SCALE_SETTINGS[@]}"; do
|
||||
local PROC_NAME=${procscale%%=*}
|
||||
local PROC_COUNT=${procscale#*=}
|
||||
is_number $PROC_COUNT || dokku_log_fail "ps:scale $PROC_COUNT is not a number"
|
||||
is_number "$PROC_COUNT" || dokku_log_fail "ps:scale $PROC_COUNT is not a number"
|
||||
dokku_log_info1_quiet "Scaling $APP:$PROC_NAME to $PROC_COUNT"
|
||||
if (egrep -q ^${PROC_NAME}= "$DOKKU_SCALE_FILE" > /dev/null 2>&1); then
|
||||
if (egrep -q "^${PROC_NAME}=" "$DOKKU_SCALE_FILE" > /dev/null 2>&1); then
|
||||
sed --in-place "s:^${PROC_NAME}=.*:$PROC_NAME=$PROC_COUNT:g" "$DOKKU_SCALE_FILE"
|
||||
else
|
||||
echo "$PROC_NAME=$PROC_COUNT" >> "$DOKKU_SCALE_FILE"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core ps plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
2
plugins/repo/.gitignore
vendored
Normal file
2
plugins/repo/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/commands
|
||||
/subcommands/*
|
||||
26
plugins/repo/Makefile
Normal file
26
plugins/repo/Makefile
Normal file
@@ -0,0 +1,26 @@
|
||||
include ../../common.mk
|
||||
|
||||
build-in-docker: clean
|
||||
docker run --rm \
|
||||
-v $$PWD/../..:$(GO_REPO_ROOT) \
|
||||
-w $(GO_REPO_ROOT)/plugins/repo \
|
||||
$(BUILD_IMAGE) \
|
||||
bash -c "make build" || exit $$?
|
||||
|
||||
build: commands subcommands
|
||||
subcommands: subcommands/gc subcommands/purge-cache
|
||||
|
||||
commands: **/**/commands.go
|
||||
go build -a -o commands src/commands/commands.go
|
||||
|
||||
subcommands/gc: **/**/**/gc.go
|
||||
go build -a -o subcommands/gc src/subcommands/gc/gc.go
|
||||
|
||||
subcommands/purge-cache: **/**/**/purge-cache.go
|
||||
go build -a -o subcommands/purge-cache src/subcommands/purge-cache/purge-cache.go
|
||||
|
||||
clean:
|
||||
rm -rf commands subcommands
|
||||
|
||||
src-clean:
|
||||
rm -rf .gitignore src vendor Makefile
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
[[ " help repo:help " == *" $1 "* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
||||
source "$PLUGIN_AVAILABLE_PATH/repo/internal-functions"
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
case "$1" in
|
||||
help | repo:help)
|
||||
repo_help_cmd "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
||||
;;
|
||||
|
||||
esac
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x
|
||||
|
||||
repo_help_content_func () {
|
||||
declare desc="return repo plugin help content"
|
||||
cat<<help_content
|
||||
repo:gc <app>, Runs 'git gc --aggressive' against the application's repo
|
||||
repo:purge-cache <app>, Deletes the contents of the build cache stored in the repository
|
||||
help_content
|
||||
}
|
||||
|
||||
repo_help_cmd() {
|
||||
if [[ $1 = "repo:help" ]] ; then
|
||||
echo -e 'Usage: dokku repo[:COMMAND]'
|
||||
echo ''
|
||||
echo "Runs commands that interact with the app's repo"
|
||||
echo ''
|
||||
echo 'Additional commands:'
|
||||
repo_help_content_func | sort | column -c2 -t -s,
|
||||
elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then
|
||||
repo_help_content_func
|
||||
else
|
||||
cat<<help_desc
|
||||
repo, Runs commands that interact with the app's repo
|
||||
help_desc
|
||||
fi
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
[plugin]
|
||||
description = "dokku core repo plugin"
|
||||
version = "0.8.2"
|
||||
version = "0.9.4"
|
||||
[plugin.config]
|
||||
|
||||
54
plugins/repo/src/commands/commands.go
Normal file
54
plugins/repo/src/commands/commands.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
columnize "github.com/ryanuber/columnize"
|
||||
)
|
||||
|
||||
const (
|
||||
helpHeader = `Usage: dokku repo[:COMMAND]
|
||||
|
||||
Runs commands that interact with the app's repo
|
||||
|
||||
Additional commands:`
|
||||
|
||||
helpContent = `
|
||||
repo:gc <app>, Runs 'git gc --aggressive' against the application's repo
|
||||
repo:purge-cache <app>, Deletes the contents of the build cache stored in the repository
|
||||
`
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
cmd := flag.Arg(0)
|
||||
switch cmd {
|
||||
case "repo:help":
|
||||
usage()
|
||||
case "help":
|
||||
fmt.Print(helpContent)
|
||||
default:
|
||||
dokkuNotImplementExitCode, err := strconv.Atoi(os.Getenv("DOKKU_NOT_IMPLEMENTED_EXIT"))
|
||||
if err != nil {
|
||||
fmt.Println("failed to retrieve DOKKU_NOT_IMPLEMENTED_EXIT environment variable")
|
||||
dokkuNotImplementExitCode = 10
|
||||
}
|
||||
os.Exit(dokkuNotImplementExitCode)
|
||||
}
|
||||
}
|
||||
|
||||
func usage() {
|
||||
config := columnize.DefaultConfig()
|
||||
config.Delim = ","
|
||||
config.Prefix = "\t"
|
||||
config.Empty = ""
|
||||
content := strings.Split(helpContent, "\n")[1:]
|
||||
fmt.Println(helpHeader)
|
||||
fmt.Println(columnize.Format(content, config))
|
||||
}
|
||||
6
plugins/repo/src/glide.lock
generated
Normal file
6
plugins/repo/src/glide.lock
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
hash: 1ddab5de41d1514c2722bd7e24758ad4b60bf6956eb5b9b925fa071a1427f149
|
||||
updated: 2017-01-03T17:16:50.97156327-08:00
|
||||
imports:
|
||||
- name: github.com/ryanuber/columnize
|
||||
version: 0fbbb3f0e3fbdc5bae7c6cd5f6c1887ebfb76360
|
||||
testImports: []
|
||||
3
plugins/repo/src/glide.yaml
Normal file
3
plugins/repo/src/glide.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
package: .
|
||||
import:
|
||||
- package: github.com/ryanuber/columnize
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user