2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
PACKER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Get changed files in the docs folder
|
||||
id: changed-files-specific
|
||||
uses: tj-actions/changed-files@v42.1.0
|
||||
uses: tj-actions/changed-files@v43.0.0
|
||||
with:
|
||||
files: contrib/images/digitalocean/**
|
||||
- name: Run `packer validate`
|
||||
|
||||
7
Makefile
7
Makefile
@@ -75,9 +75,12 @@ go-clean:
|
||||
fi ;\
|
||||
done
|
||||
|
||||
copyfiles:
|
||||
$(MAKE) go-build || exit 1
|
||||
copydokku:
|
||||
cp dokku /usr/local/bin/dokku
|
||||
chmod 0755 /usr/local/bin/dokku
|
||||
|
||||
copyfiles: copydokku
|
||||
$(MAKE) go-build || exit 1
|
||||
mkdir -p ${CORE_PLUGINS_PATH} ${PLUGINS_PATH}
|
||||
rm -rf ${CORE_PLUGINS_PATH}/*
|
||||
test -d ${CORE_PLUGINS_PATH}/enabled || PLUGIN_PATH=${CORE_PLUGINS_PATH} plugn init
|
||||
|
||||
@@ -188,9 +188,14 @@ main() {
|
||||
[[ " storage:ensure-directory " == *" $CMD "* ]] && unset APP
|
||||
[[ "$CMD" =~ events*|plugin*|ssh-keys* ]] && unset APP
|
||||
[[ -n "$APP_ARG" ]] && [[ "$APP_ARG" == "--global" ]] && unset APP
|
||||
[[ -n "$@" ]] && [[ -n "$APP" ]] && app_arg="--app $APP"
|
||||
if [[ -n "$@" ]] && [[ -n "$APP" ]]; then
|
||||
set -- "$APP" "$@"
|
||||
set -- "--app" "$@"
|
||||
fi
|
||||
# echo "ssh -o LogLevel=QUIET -p $DOKKU_PORT -t dokku@$DOKKU_REMOTE_HOST -- $app_arg $@"
|
||||
ssh -o LogLevel=QUIET -p $DOKKU_PORT -t dokku@$DOKKU_REMOTE_HOST -- $app_arg $@ || {
|
||||
local ssh_args=("-o" "LogLevel=QUIET" "-p" "$DOKKU_PORT" "-t" "dokku@$DOKKU_REMOTE_HOST" "--")
|
||||
ssh_args+=("$@")
|
||||
ssh "${ssh_args[@]}" || {
|
||||
ssh_exit_code="$?"
|
||||
echo " ! Failed to execute dokku command over ssh: exit code $?" 1>&2
|
||||
echo " ! If there was no output from Dokku, ensure your configured SSH Key can connect to the remote server" 1>&2
|
||||
|
||||
4
docs/_build/requirements.txt
vendored
4
docs/_build/requirements.txt
vendored
@@ -3,7 +3,7 @@ click==8.1.7
|
||||
ghp-import==2.1.0
|
||||
importlib-metadata==7.0.2
|
||||
Jinja2==3.1.3
|
||||
Markdown>=3.2.1,<3.6
|
||||
Markdown>=3.2.1,<3.7
|
||||
MarkupSafe==2.1.5
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.5.3
|
||||
@@ -20,4 +20,4 @@ pyyaml_env_tag==0.1
|
||||
six==1.16.0
|
||||
soupsieve==2.5
|
||||
watchdog==4.0.0
|
||||
zipp==3.17.0
|
||||
zipp==3.18.1
|
||||
|
||||
14
docs/appendices/0.34.0-migration-guide.md
Normal file
14
docs/appendices/0.34.0-migration-guide.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# 0.34.0 Migration Guide
|
||||
|
||||
## Removals
|
||||
|
||||
- The `disable-chown` property of the `scheduler-docker-local` plugin has been removed. Mounted paths will no longer have file permissions changed during the pre-deploy phase. Files baked into the container image for herokuish builds will always be owned by the correct user.
|
||||
- The `git:unlock` command has been removed. It was previously used to "unlock" a temporary directory that already existed. The directory the `git:unlock` command used to cleanup is now properly removed on exit of the `git:from-image` command.
|
||||
|
||||
## Changes
|
||||
|
||||
- The k3s scheduler now defaults to nginx as it's default proxy implementation. The traefik proxy implementation is still available, though users will need to set the global `ingress-class` k3s property to `traefik` via the following command:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:set --global ingress-class traefik
|
||||
```
|
||||
@@ -10,13 +10,12 @@ git:from-archive [--archive-type ARCHIVE_TYPE] <app> <archive-url> [<git-usernam
|
||||
git:from-image [--build-dir DIRECTORY] <app> <docker-image> [<git-username> <git-email>] # Updates an app's git repository with a given docker image
|
||||
git:generate-deploy-key # Generates a deploy ssh key
|
||||
git:load-image [--build-dir DIRECTORY] <app> <docker-image> [<git-username> <git-email>] # Updates an app's git repository with a docker image loaded from stdin
|
||||
git:sync [--build] <app> <repository> [<git-ref>] # Clone or fetch an app from remote git repo
|
||||
git:sync [--build|build-if-changes] <app> <repository> [<git-ref>] # Clone or fetch an app from remote git repo
|
||||
git:initialize <app> # Initialize a git repository for an app
|
||||
git:public-key # Outputs the dokku public deploy key
|
||||
git:report [<app>] [<flag>] # Displays a git report for one or more apps
|
||||
git:set <app> <key> (<value>) # Set or clear a git property for an app
|
||||
git:status <app> # Show the working tree status for an app
|
||||
git:unlock <app> [--force] # Removes previous git clone folder for new deployment
|
||||
```
|
||||
|
||||
Git-based deployment has been the traditional method of deploying applications in Dokku. As of v0.12.0, Dokku introduces a few ways to customize the experience of deploying via `git push`. A Git-based deployment currently supports building applications via:
|
||||
@@ -158,6 +157,12 @@ By default, this command does not trigger an application build. To do so during
|
||||
dokku git:sync --build node-js-app https://github.com/heroku/node-js-getting-started.git
|
||||
```
|
||||
|
||||
When running `git:sync` without a reference, it may be useful to only build when there are changes. To do so, specify the `--build-if-changes` flag.
|
||||
|
||||
```shell
|
||||
dokku git:sync --build-if-changes node-js-app https://github.com/heroku/node-js-getting-started.git
|
||||
```
|
||||
|
||||
### Initializing from private repositories
|
||||
|
||||
> [!IMPORTANT]
|
||||
|
||||
@@ -32,20 +32,6 @@ dokku scheduler:set node-js-app selected
|
||||
|
||||
Many builders only produce amd64-compatible images. The docker-local scheduler will automatically detect these and run them via the `--platform=linux/amd64` on arm64 deploy targets.
|
||||
|
||||
### Disabling chown of persistent storage
|
||||
|
||||
The `scheduler-docker-local` plugin will ensure your storage mounts are owned by either `herokuishuser` or the overridden value you have set in `DOKKU_APP_USER`. You may disable this by running the following `scheduler-docker-local:set` command for your application:
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set node-js-app disable-chown true
|
||||
```
|
||||
|
||||
Once set, you may re-enable it by setting a blank value for `disable-chown`:
|
||||
|
||||
```shell
|
||||
dokku scheduler-docker-local:set node-js-app disable-chown
|
||||
```
|
||||
|
||||
### Disabling the init process
|
||||
|
||||
The `scheduler-docker-local` injects an init process by default via the `--init`. For some apps - such as those where the built docker image uses S6 as the init - this may be undesirable and cause issues with process starts. You may disable this by running the following `scheduler-docker-local:set` command for your application:
|
||||
|
||||
@@ -58,12 +58,12 @@ By default, Dokku will attempt to auto-detect the IP address of the server. In c
|
||||
dokku scheduler-k3s:initialize --server-ip 192.168.20.15
|
||||
```
|
||||
|
||||
Dokku's k3s integration natively uses `Traefik` as it's ingress load balancer via [Traefik's CRDs](https://doc.traefik.io/traefik/providers/kubernetes-crd/), but a cluster can be set to use `nginx` via the [ingress-nginx](https://github.com/kubernetes/ingress-nginx) project. Switching to nginx will result in any `nginx` plugin settings being respected, either by turning them into annotations or creating a custom server snippet.
|
||||
Dokku's k3s integration natively uses `nginx` as it's ingress load balancer via [ingress-nginx](https://github.com/kubernetes/ingress-nginx). Properties set by the `nginx` plugin will be respected, either by turning them into annotations or creating a custom server/location snippet that the `ingress-nginx` project can use.
|
||||
|
||||
To change the ingress, set the `--ingress-class` flag:
|
||||
Dokku can also use Traefik on cluster initialization via the [Traefik's CRDs](https://doc.traefik.io/traefik/providers/kubernetes-crd/). To change the ingress, set the `--ingress-class` flag:
|
||||
|
||||
```shell
|
||||
dokku scheduler-k3s:initialize --ingress-class nginx
|
||||
dokku scheduler-k3s:initialize --ingress-class traefik
|
||||
```
|
||||
|
||||
### Adding nodes to the cluster
|
||||
|
||||
@@ -18,6 +18,7 @@ Docker releases updates periodically to their engine. We recommend reading their
|
||||
|
||||
Before upgrading, check the migration guides to get comfortable with new features and prepare your deployment to be upgraded.
|
||||
|
||||
- [Upgrading to 0.34](/docs/appendices/0.34.0-migration-guide.md)
|
||||
- [Upgrading to 0.33](/docs/appendices/0.33.0-migration-guide.md)
|
||||
- [Upgrading to 0.32](/docs/appendices/0.32.0-migration-guide.md)
|
||||
- [Upgrading to 0.31](/docs/appendices/0.31.0-migration-guide.md)
|
||||
|
||||
@@ -116,16 +116,6 @@ dokku traefik:set --global log-level DEBUG
|
||||
|
||||
After modifying, the Traefik container will need to be restarted.
|
||||
|
||||
### Setting rule priority
|
||||
|
||||
By default, app deployments will result in the newer traefik rules using a higher priority in order to have any newer rules respected by Traefik. Rule priorities will always increase according to the current unix timestamp. The priority may be fixed by setting the app-level `priority` property:
|
||||
|
||||
```shell
|
||||
dokku traefik:set node-js-app priority 12345
|
||||
```
|
||||
|
||||
After modifying, the app container will need to be recreated via a `ps:rebuild` or an app deployment.
|
||||
|
||||
### SSL Configuration
|
||||
|
||||
The traefik plugin only supports automatic ssl certificates from it's letsencrypt integration. Managed certificates provided by the `certs` plugin are ignored.
|
||||
|
||||
@@ -12,7 +12,7 @@ proxy:report [<app>] [<flag>] # Displays a proxy report fo
|
||||
proxy:set [<app>|--global] <proxy-type> # Set proxy type for app
|
||||
```
|
||||
|
||||
In Dokku 0.5.0, port proxying was decoupled from the `nginx-vhosts` plugin into the proxy plugin. Dokku 0.6.0 introduced the ability to map host ports to specific container ports. In the future this will allow other proxy software - such as HAProxy or Caddy - to be used in place of nginx.
|
||||
In Dokku 0.5.0, port proxying was decoupled from the `nginx-vhosts` plugin into the proxy plugin. Dokku 0.6.0 introduced the ability to map host ports to specific container ports. This allows other proxy software - such as HAProxy or Caddy - to be used in place of nginx.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
19
dokku
19
dokku
@@ -55,7 +55,7 @@ export DOKKU_SYSTEM_USER=${DOKKU_SYSTEM_USER:="dokku"}
|
||||
export DOKKU_API_VERSION=1
|
||||
export DOKKU_NOT_IMPLEMENTED_EXIT=10
|
||||
export DOKKU_VALID_EXIT=0
|
||||
export DOKKU_PID="$BASHPID"
|
||||
export DOKKU_PID="${DOKKU_PID:=$$}"
|
||||
|
||||
export DOKKU_LOGS_DIR=${DOKKU_LOGS_DIR:="/var/log/dokku"}
|
||||
export DOKKU_LOGS_HOST_DIR=${DOKKU_LOGS_HOST_DIR:=$DOKKU_LOGS_DIR}
|
||||
@@ -88,8 +88,8 @@ fi
|
||||
! has_tty && DOKKU_QUIET_OUTPUT=1
|
||||
|
||||
if [[ $(id -un) != "dokku" ]]; then
|
||||
unset TMP TMPDIR TEMP TEMPDIR
|
||||
if [[ ! $1 =~ plugin:* ]] && [[ $1 != "ssh-keys:add" ]] && [[ $1 != "ssh-keys:remove" ]] && [[ $1 != "scheduler-k3s:initialize" ]] && [[ $1 != "scheduler-k3s:uninstall" ]]; then
|
||||
unset DOKKU_PID TMP TMPDIR TEMP TEMPDIR
|
||||
export SSH_USER=$(id -un)
|
||||
sudo -u dokku -E -H "$0" "$@"
|
||||
exit $?
|
||||
@@ -106,15 +106,20 @@ fi
|
||||
|
||||
if [[ -n "$SSH_ORIGINAL_COMMAND" ]]; then
|
||||
export -n SSH_ORIGINAL_COMMAND
|
||||
if [[ $1 =~ config-* ]] || [[ $1 =~ docker-options* ]]; then
|
||||
xargs $0 <<<$SSH_ORIGINAL_COMMAND
|
||||
exit $?
|
||||
else
|
||||
exit_code=0
|
||||
if [[ $1 =~ git-* ]] || [[ $1 =~ git:* ]]; then
|
||||
set -f
|
||||
$0 $SSH_ORIGINAL_COMMAND
|
||||
exit_code=$?
|
||||
set +f
|
||||
else
|
||||
readarray -t -O "${#ssh_arg_array[@]}" ssh_arg_array < <(printf '%s' "$SSH_ORIGINAL_COMMAND" | xargs -n 1)
|
||||
set -f
|
||||
$0 "${ssh_arg_array[@]}"
|
||||
exit_code=$?
|
||||
set +f
|
||||
exit $?
|
||||
fi
|
||||
exit $exit_code
|
||||
fi
|
||||
|
||||
if ! dokku_auth "$@"; then
|
||||
|
||||
@@ -17,6 +17,10 @@ cmd-report() {
|
||||
dokku_log_info1 "uname: $(uname -a)"
|
||||
dokku_log_info1 "memory: "
|
||||
free -m | sed "s/^/ /"
|
||||
dokku_log_info1 "disk utilization: "
|
||||
df -h --type btrfs --type ext4 --type ext3 --type ext2 --type vfat --type iso9660 | sed "s/^/ /"
|
||||
dokku_log_info1 "disk inode utilization: "
|
||||
df -hi --type btrfs --type ext4 --type ext3 --type ext2 --type vfat --type iso9660 | sed "s/^/ /"
|
||||
dokku_log_info1 "docker version: "
|
||||
"$DOCKER_BIN" version | sed "s/^/ /"
|
||||
dokku_log_info1 "docker daemon info: "
|
||||
|
||||
@@ -56,16 +56,12 @@ EOF
|
||||
cat >"$DOKKU_LOGROTATE_FILE" <<EOF
|
||||
$DOKKU_LOGS_DIR/*.log {
|
||||
daily
|
||||
rotate 7
|
||||
missingok
|
||||
notifempty
|
||||
su syslog dokku
|
||||
rotate 7
|
||||
compress
|
||||
delaycompress
|
||||
postrotate
|
||||
reload rsyslog &>/dev/null || true
|
||||
endscript
|
||||
create 664 syslog dokku
|
||||
notifempty
|
||||
copytruncate
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
@@ -102,8 +102,11 @@ func getPhaseScript(appName string, phase string) (string, error) {
|
||||
func getReleaseCommand(appName string, image string) string {
|
||||
processType := "release"
|
||||
port := "5000"
|
||||
b, _ := common.PlugnTriggerOutput("procfile-get-command", []string{appName, processType, port}...)
|
||||
return strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "procfile-get-command",
|
||||
Args: []string{appName, processType, port},
|
||||
})
|
||||
return results.StdoutContents()
|
||||
}
|
||||
|
||||
func getDokkuAppShell(appName string) string {
|
||||
@@ -114,13 +117,19 @@ func getDokkuAppShell(appName string) string {
|
||||
ctx := context.Background()
|
||||
errs, ctx := errgroup.WithContext(ctx)
|
||||
errs.Go(func() error {
|
||||
b, _ := common.PlugnTriggerOutput("config-get-global", []string{"DOKKU_APP_SHELL"}...)
|
||||
globalShell = strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTriggerWithContext(ctx, common.PlugnTriggerInput{
|
||||
Trigger: "config-get-global",
|
||||
Args: []string{"DOKKU_APP_SHELL"},
|
||||
})
|
||||
globalShell = results.StdoutContents()
|
||||
return nil
|
||||
})
|
||||
errs.Go(func() error {
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_SHELL"}...)
|
||||
appShell = strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTriggerWithContext(ctx, common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_APP_SHELL"},
|
||||
})
|
||||
appShell = results.StdoutContents()
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -204,8 +213,13 @@ func executeScript(appName string, image string, imageTag string, phase string)
|
||||
}
|
||||
|
||||
var dockerArgs []string
|
||||
if b, err := common.PlugnTriggerSetup("docker-args-deploy", []string{appName, imageTag}...).SetInput("").Output(); err == nil {
|
||||
words, err := shellquote.Split(strings.TrimSpace(string(b[:])))
|
||||
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "docker-args-deploy",
|
||||
Args: []string{appName, imageTag},
|
||||
Stdin: strings.NewReader(""),
|
||||
})
|
||||
if err == nil {
|
||||
words, err := shellquote.Split(results.StdoutContents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -213,8 +227,13 @@ func executeScript(appName string, image string, imageTag string, phase string)
|
||||
dockerArgs = append(dockerArgs, words...)
|
||||
}
|
||||
|
||||
if b, err := common.PlugnTriggerSetup("docker-args-process-deploy", []string{appName, imageSourceType, imageTag}...).SetInput("").Output(); err == nil {
|
||||
words, err := shellquote.Split(strings.TrimSpace(string(b[:])))
|
||||
results, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "docker-args-process-deploy",
|
||||
Args: []string{appName, imageSourceType, imageTag},
|
||||
Stdin: strings.NewReader(""),
|
||||
})
|
||||
if err == nil {
|
||||
words, err := shellquote.Split(results.StdoutContents())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -398,12 +417,15 @@ func createdContainerID(appName string, dockerArgs []string, image string, comma
|
||||
arguments = append(arguments, image)
|
||||
arguments = append(arguments, command...)
|
||||
|
||||
b, err := common.PlugnTriggerOutput("config-export", []string{appName, "false", "true", "json"}...)
|
||||
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-export",
|
||||
Args: []string{appName, "false", "true", "json"},
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var env map[string]string
|
||||
if err := json.Unmarshal(b, &env); err != nil {
|
||||
if err := json.Unmarshal(results.StdoutBytes(), &env); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -420,7 +442,11 @@ func createdContainerID(appName string, dockerArgs []string, image string, comma
|
||||
}
|
||||
|
||||
containerID := result.StdoutContents()
|
||||
err = common.PlugnTrigger("post-container-create", []string{"app", containerID, appName, phase}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-container-create",
|
||||
Args: []string{"app", containerID, appName, phase},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return containerID, err
|
||||
}
|
||||
|
||||
@@ -440,12 +466,27 @@ func setScale(appName string, image string) error {
|
||||
}
|
||||
|
||||
if len(args) == 3 {
|
||||
return common.PlugnTrigger("ps-can-scale", []string{appName, "true"}...)
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("ps-can-scale", []string{appName, "false"}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "ps-can-scale",
|
||||
Args: []string{appName, "true"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("ps-set-scale", args...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "ps-can-scale",
|
||||
Args: []string{appName, "false"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "ps-set-scale",
|
||||
Args: args,
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
||||
@@ -101,11 +101,17 @@ func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
|
||||
}
|
||||
|
||||
processSpecificAppJSON := fmt.Sprintf("%s.%s", existingAppJSON, os.Getenv("DOKKU_PID"))
|
||||
b, _ := common.PlugnTriggerOutput("git-get-property", []string{appName, "source-image"}...)
|
||||
appSourceImage := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "git-get-property",
|
||||
Args: []string{appName, "source-image"},
|
||||
})
|
||||
appSourceImage := results.StdoutContents()
|
||||
|
||||
b, _ = common.PlugnTriggerOutput("builder-get-property", []string{appName, "build-dir"}...)
|
||||
buildDir := strings.TrimSpace(string(b[:]))
|
||||
results, _ = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "builder-get-property",
|
||||
Args: []string{appName, "build-dir"},
|
||||
})
|
||||
buildDir := results.StdoutContents()
|
||||
|
||||
repoDefaultAppJSONPath := path.Join(sourceWorkDir, "app.json")
|
||||
if appSourceImage == "" {
|
||||
@@ -179,7 +185,7 @@ func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
||||
return common.CloneAppData("app-json", oldAppName, newAppName)
|
||||
}
|
||||
|
||||
// TriggerPostCreate ensures apps the correct data directory structure
|
||||
// TriggerPostCreate ensures apps have the correct data directory structure
|
||||
func TriggerPostCreate(appName string) error {
|
||||
return common.CreateAppDataDirectory("app-json", appName)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
SUBCOMMANDS = subcommands/clone subcommands/create subcommands/destroy subcommands/exists subcommands/list subcommands/lock subcommands/locked subcommands/rename subcommands/report subcommands/unlock
|
||||
TRIGGERS = triggers/app-create triggers/app-destroy triggers/app-exists triggers/app-maybe-create triggers/deploy-source-set triggers/install triggers/post-app-clone-setup triggers/post-app-rename-setup triggers/post-delete triggers/report
|
||||
TRIGGERS = triggers/app-create triggers/app-destroy triggers/app-exists triggers/app-maybe-create triggers/deploy-source-set triggers/install triggers/post-app-clone-setup triggers/post-app-rename triggers/post-app-rename-setup triggers/post-create triggers/post-delete triggers/report
|
||||
BUILD = commands subcommands triggers
|
||||
PLUGIN_NAME = apps
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
@@ -17,8 +16,8 @@ func appExists(appName string) error {
|
||||
|
||||
// checks if an app is locked
|
||||
func appIsLocked(appName string) bool {
|
||||
lockfilePath := fmt.Sprintf("%v/.deploy.lock", common.AppRoot(appName))
|
||||
_, err := os.Stat(lockfilePath)
|
||||
lockPath := getLockPath(appName)
|
||||
_, err := os.Stat(lockPath)
|
||||
return !os.IsNotExist(err)
|
||||
}
|
||||
|
||||
@@ -39,11 +38,12 @@ func createApp(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-create", []string{appName}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-create",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// destroys an app
|
||||
@@ -57,19 +57,41 @@ func destroyApp(appName string) error {
|
||||
common.LogInfo1(fmt.Sprintf("Destroying %s (including all add-ons)", appName))
|
||||
|
||||
imageTag, _ := common.GetRunningImageTag(appName, "")
|
||||
if err := common.PlugnTrigger("pre-delete", []string{appName, imageTag}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "pre-delete",
|
||||
Args: []string{appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
removeContainers := "true"
|
||||
if err := common.PlugnTrigger("scheduler-stop", []string{scheduler, appName, removeContainers}...); err != nil {
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-stop",
|
||||
Args: []string{scheduler, appName, removeContainers},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := common.PlugnTrigger("scheduler-post-delete", []string{scheduler, appName, imageTag}...); err != nil {
|
||||
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-post-delete",
|
||||
Args: []string{scheduler, appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := common.PlugnTrigger("post-delete", []string{appName, imageTag}...); err != nil {
|
||||
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-delete",
|
||||
Args: []string{appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -77,7 +99,12 @@ func destroyApp(appName string) error {
|
||||
common.DockerCleanup(appName, forceCleanup)
|
||||
|
||||
common.LogInfo1("Retiring old containers and images")
|
||||
if err := common.PlugnTrigger("scheduler-retire", []string{scheduler, appName}...); err != nil {
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-retire",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -94,14 +121,22 @@ func destroyApp(appName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// returns the lock path
|
||||
func getLockPath(appName string) string {
|
||||
return fmt.Sprintf("%v/.deploy.lock", common.GetAppDataDirectory("apps", appName))
|
||||
}
|
||||
|
||||
// creates an app if allowed
|
||||
func maybeCreateApp(appName string) error {
|
||||
if err := appExists(appName); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
b, _ := common.PlugnTriggerOutput("config-get-global", []string{"DOKKU_DISABLE_APP_AUTOCREATION"}...)
|
||||
disableAutocreate := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get-global",
|
||||
Args: []string{"DOKKU_DISABLE_APP_AUTOCREATION"},
|
||||
})
|
||||
disableAutocreate := results.StdoutContents()
|
||||
if disableAutocreate == "true" {
|
||||
common.LogWarn("App auto-creation disabled.")
|
||||
return fmt.Errorf("Re-enable app auto-creation or create an app with 'dokku apps:create %s'", appName)
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -41,10 +41,17 @@ func main() {
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = apps.TriggerPostAppCloneSetup(oldAppName, newAppName)
|
||||
case "post-app-rename":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = apps.TriggerPostAppRename(oldAppName, newAppName)
|
||||
case "post-app-rename-setup":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = apps.TriggerPostAppRenameSetup(oldAppName, newAppName)
|
||||
case "post-create":
|
||||
appName := flag.Arg(0)
|
||||
err = apps.TriggerPostCreate(appName)
|
||||
case "post-delete":
|
||||
appName := flag.Arg(0)
|
||||
err = apps.TriggerPostDelete(appName)
|
||||
|
||||
@@ -40,7 +40,12 @@ func CommandClone(oldAppName string, newAppName string, skipDeploy bool, ignoreE
|
||||
return err
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-app-clone-setup", []string{oldAppName, newAppName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-app-clone-setup",
|
||||
Args: []string{oldAppName, newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -48,15 +53,21 @@ func CommandClone(oldAppName string, newAppName string, skipDeploy bool, ignoreE
|
||||
os.Setenv("SKIP_REBUILD", "true")
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("git-has-code", []string{newAppName}...); err != nil {
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "git-has-code",
|
||||
Args: []string{newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
os.Setenv("SKIP_REBUILD", "true")
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-app-clone", []string{oldAppName, newAppName}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-app-clone",
|
||||
Args: []string{oldAppName, newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandCreate creates app via command line
|
||||
@@ -108,8 +119,8 @@ func CommandLock(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
lockfilePath := fmt.Sprintf("%v/.deploy.lock", common.AppRoot(appName))
|
||||
if _, err := os.Create(lockfilePath); err != nil {
|
||||
lockPath := getLockPath(appName)
|
||||
if _, err := os.Create(lockPath); err != nil {
|
||||
return errors.New("Unable to create deploy lock")
|
||||
}
|
||||
|
||||
@@ -158,7 +169,12 @@ func CommandRename(oldAppName string, newAppName string, skipDeploy bool) error
|
||||
return err
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-app-rename-setup", []string{oldAppName, newAppName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-app-rename-setup",
|
||||
Args: []string{oldAppName, newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -171,15 +187,21 @@ func CommandRename(oldAppName string, newAppName string, skipDeploy bool) error
|
||||
os.Setenv("SKIP_REBUILD", "true")
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("git-has-code", []string{newAppName}...); err != nil {
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "git-has-code",
|
||||
Args: []string{newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
os.Setenv("SKIP_REBUILD", "true")
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-app-rename", []string{oldAppName, newAppName}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-app-rename",
|
||||
Args: []string{oldAppName, newAppName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandReport displays an app report for one or more apps
|
||||
@@ -206,7 +228,7 @@ func CommandUnlock(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
lockfilePath := fmt.Sprintf("%v/.deploy.lock", common.AppRoot(appName))
|
||||
lockfilePath := getLockPath(appName)
|
||||
if _, err := os.Stat(lockfilePath); !os.IsNotExist(err) {
|
||||
common.LogWarn("A deploy may be in progress.")
|
||||
common.LogWarn("Removing the app lock will not stop in progress deploys.")
|
||||
|
||||
@@ -43,6 +43,10 @@ func TriggerInstall() error {
|
||||
return fmt.Errorf("Unable to install the apps plugin: %s", err.Error())
|
||||
}
|
||||
|
||||
if err := common.SetupAppData("apps"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
apps, err := common.UnfilteredDokkuApps()
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -79,7 +83,12 @@ func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return common.CloneAppData("apps", oldAppName, newAppName)
|
||||
}
|
||||
|
||||
// TriggerPostAppRename removes the old app data
|
||||
func TriggerPostAppRename(oldAppName string, newAppName string) error {
|
||||
return common.MigrateAppDataDirectory("apps", oldAppName, newAppName)
|
||||
}
|
||||
|
||||
// TriggerPostAppRenameSetup renames apps files
|
||||
@@ -92,14 +101,22 @@ func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return common.CloneAppData("apps", oldAppName, newAppName)
|
||||
}
|
||||
|
||||
// TriggerPostDelete is the apps post-delete plugin trigger
|
||||
// TriggerPostCreate ensures apps have the correct data directory structure
|
||||
func TriggerPostCreate(appName string) error {
|
||||
return common.CreateAppDataDirectory("apps", appName)
|
||||
}
|
||||
|
||||
// TriggerPostDelete destroys the apps data for a given app container
|
||||
func TriggerPostDelete(appName string) error {
|
||||
if err := common.PropertyDestroy("apps", appName); err != nil {
|
||||
common.LogWarn(err.Error())
|
||||
dataErr := common.RemoveAppDataDirectory("apps", appName)
|
||||
propertyErr := common.PropertyDestroy("apps", appName)
|
||||
|
||||
if dataErr != nil {
|
||||
return dataErr
|
||||
}
|
||||
|
||||
return nil
|
||||
return propertyErr
|
||||
}
|
||||
|
||||
@@ -33,7 +33,10 @@ trigger-builder-herokuish-builder-release() {
|
||||
DOCKER_BUILD_ARGS+=("--platform=linux/amd64")
|
||||
fi
|
||||
|
||||
if ! suppress_output "$DOCKER_BIN" image build "${DOCKER_BUILD_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -f "$PLUGIN_AVAILABLE_PATH/builder-herokuish/dockerfiles/builder-release.Dockerfile" --build-arg APP_IMAGE="$IMAGE" -t "$IMAGE" "$TMP_WORK_DIR"; then
|
||||
DOKKU_APP_USER=$(config_get "$APP" DOKKU_APP_USER || true)
|
||||
DOKKU_APP_USER=${DOKKU_APP_USER:="herokuishuser"}
|
||||
|
||||
if ! suppress_output "$DOCKER_BIN" image build "${DOCKER_BUILD_ARGS[@]}" $DOKKU_GLOBAL_BUILD_ARGS -f "$PLUGIN_AVAILABLE_PATH/builder-herokuish/dockerfiles/builder-release.Dockerfile" --build-arg APP_IMAGE="$IMAGE" --build-arg DOKKU_APP_USER=$DOKKU_APP_USER -t "$IMAGE" "$TMP_WORK_DIR"; then
|
||||
dokku_log_warn "Failure injecting environment variables"
|
||||
return 1
|
||||
fi
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
ARG APP_IMAGE
|
||||
FROM $APP_IMAGE
|
||||
|
||||
COPY 00-global-env.sh 01-app-env.sh /app/.profile.d/
|
||||
ARG DOKKU_APP_USER herokuishuser
|
||||
COPY --chown=$DOKKU_APP_USER 00-global-env.sh 01-app-env.sh /app/.profile.d/
|
||||
RUN chown -R "$DOKKU_APP_USER:$DOKKU_APP_USER" /app
|
||||
USER $DOKKU_APP_USER
|
||||
ENV HEROKUISH_SETUIDGUID false
|
||||
|
||||
@@ -4,4 +4,5 @@ FROM $APP_IMAGE
|
||||
ARG DOKKU_APP_USER herokuishuser
|
||||
RUN USER=$DOKKU_APP_USER /exec true
|
||||
COPY --chown=$DOKKU_APP_USER . /app
|
||||
WORKDIR /app
|
||||
WORKDIR /app
|
||||
ENV HEROKUISH_DISABLE_CHOWN true
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
ARG APP_IMAGE
|
||||
FROM $APP_IMAGE
|
||||
|
||||
COPY .env.d /tmp/env
|
||||
COPY .env /app/.env
|
||||
COPY --chown=$DOKKU_APP_USER .env.d /tmp/env
|
||||
COPY --chown=$DOKKU_APP_USER .env /app/.env
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
|
||||
|
||||
trigger-builder-herokuish-post-app-clone-setup() {
|
||||
declare desc="builder-herokuish post-app-clone-setup plugin trigger"
|
||||
declare trigger="post-app-clone-setup"
|
||||
declare OLD_APP="$1" NEW_APP="$2"
|
||||
|
||||
local NEW_CACHE_DIR="$DOKKU_ROOT/$NEW_APP/cache"
|
||||
local NEW_CACHE_HOST_DIR="$DOKKU_HOST_ROOT/$NEW_APP/cache"
|
||||
|
||||
pushd "$DOKKU_ROOT/$OLD_APP/." >/dev/null
|
||||
find ./* \( -name ".cache" -o -name "cache" \) -prune -o -print | cpio -pdmu --quiet "$DOKKU_ROOT/$NEW_APP"
|
||||
popd &>/dev/null || pushd "/tmp" >/dev/null
|
||||
|
||||
if [[ -d "$NEW_CACHE_DIR" ]] && ! rmdir "$NEW_CACHE_DIR"; then
|
||||
local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$NEW_APP"
|
||||
"$DOCKER_BIN" container run "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS --rm --volume "$NEW_CACHE_HOST_DIR:/cache" "dokku/$OLD_APP" chmod 777 -R /cache
|
||||
fi
|
||||
rm -rf "$NEW_CACHE_DIR"
|
||||
}
|
||||
|
||||
trigger-builder-herokuish-post-app-clone-setup "$@"
|
||||
@@ -1,26 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/property-functions"
|
||||
|
||||
trigger-builder-herokuish-post-app-clone-setup() {
|
||||
declare desc="builder-herokuish post-app-clone-setup plugin trigger"
|
||||
declare trigger="post-app-clone-setup"
|
||||
declare OLD_APP="$1" NEW_APP="$2"
|
||||
|
||||
local OLD_CACHE_DIR="$DOKKU_ROOT/$OLD_APP/cache"
|
||||
local OLD_CACHE_HOST_DIR="$DOKKU_HOST_ROOT/$OLD_APP/cache"
|
||||
|
||||
if [[ -d "$OLD_CACHE_DIR" ]] && ! rmdir "$OLD_CACHE_DIR" &>/dev/null; then
|
||||
local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$NEW_APP"
|
||||
"$DOCKER_BIN" container run "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS --rm --volume "$OLD_CACHE_HOST_DIR:/cache" "dokku/$OLD_APP" chmod 777 -R /cache
|
||||
fi
|
||||
rm -rf "$OLD_CACHE_DIR"
|
||||
|
||||
pushd "$DOKKU_ROOT/$OLD_APP/." >/dev/null
|
||||
find ./* \( -name ".cache" -o -name "cache" \) -prune -o -print | cpio -pdmu --quiet "$DOKKU_ROOT/$NEW_APP"
|
||||
popd &>/dev/null || pushd "/tmp" >/dev/null
|
||||
}
|
||||
|
||||
trigger-builder-herokuish-post-app-clone-setup "$@"
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -44,7 +44,7 @@ func rewriteBuildpacksFile(sourceWorkDir string) error {
|
||||
|
||||
func validBuildpackURL(buildpack string) (string, error) {
|
||||
if buildpack == "" {
|
||||
return buildpack, errors.New("Must specify a buildpack to add")
|
||||
return buildpack, errors.New("Must specify a buildpack url or reference")
|
||||
}
|
||||
|
||||
reHerokuValue := regexp.MustCompile(`(?m)^([\w-]+\/[\w-]+)$`)
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -40,8 +40,11 @@ func reportComputedStack(appName string) string {
|
||||
return stack
|
||||
}
|
||||
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_IMAGE"}...)
|
||||
if dokkuImage := strings.TrimSpace(string(b[:])); dokkuImage != "" {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_IMAGE"},
|
||||
})
|
||||
if dokkuImage := results.StdoutContents(); dokkuImage != "" {
|
||||
common.LogWarn("Deprecated: use buildpacks:set-property instead of specifying DOKKU_IMAGE environment variable")
|
||||
return dokkuImage
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ func CommandRemove(appName string, buildpack string, index int) (err error) {
|
||||
}
|
||||
|
||||
buildpack, err = validBuildpackURL(buildpack)
|
||||
if err != nil {
|
||||
if index == 0 && err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -149,7 +149,12 @@ func CommandSetProperty(appName string, property string, value string) error {
|
||||
common.CommandPropertySet("buildpacks", appName, property, value, DefaultProperties, GlobalProperties)
|
||||
if property == "stack" && oldStack != value {
|
||||
if appName != "--global" {
|
||||
return common.PlugnTrigger("post-stack-set", []string{appName, value}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-stack-set",
|
||||
Args: []string{appName, value},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
apps, err := common.DokkuApps()
|
||||
@@ -157,7 +162,12 @@ func CommandSetProperty(appName string, property string, value string) error {
|
||||
return err
|
||||
}
|
||||
for _, app := range apps {
|
||||
if err := common.PlugnTrigger("post-stack-set", []string{app, value}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-stack-set",
|
||||
Args: []string{app, value},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
@@ -22,8 +21,11 @@ func TriggerBuildpackStackName(appName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_IMAGE"}...)
|
||||
dokkuImage := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_IMAGE"},
|
||||
})
|
||||
dokkuImage := results.StdoutContents()
|
||||
if dokkuImage != "" {
|
||||
common.LogWarn("Deprecated: use buildpacks:set-property instead of specifying DOKKU_IMAGE environment variable")
|
||||
fmt.Println(dokkuImage)
|
||||
|
||||
@@ -124,8 +124,11 @@ func GetAppScheduler(appName string) string {
|
||||
}
|
||||
|
||||
func getAppScheduler(appName string) string {
|
||||
b, _ := PlugnTriggerOutput("scheduler-detect", []string{appName}...)
|
||||
value := strings.TrimSpace(string(b[:]))
|
||||
results, _ := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "scheduler-detect",
|
||||
Args: []string{appName},
|
||||
})
|
||||
value := results.StdoutContents()
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
@@ -134,8 +137,11 @@ func getAppScheduler(appName string) string {
|
||||
|
||||
// GetGlobalScheduler fetchs the global scheduler
|
||||
func GetGlobalScheduler() string {
|
||||
b, _ := PlugnTriggerOutput("scheduler-detect", []string{"--global"}...)
|
||||
value := strings.TrimSpace(string(b[:]))
|
||||
results, _ := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "scheduler-detect",
|
||||
Args: []string{"--global"},
|
||||
})
|
||||
value := results.StdoutContents()
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
@@ -152,24 +158,34 @@ func GetDeployingAppImageName(appName, imageTag, imageRepo string) (string, erro
|
||||
ctx := context.Background()
|
||||
errs, ctx := errgroup.WithContext(ctx)
|
||||
errs.Go(func() error {
|
||||
b, err := PlugnTriggerOutput("deployed-app-repository", []string{appName}...)
|
||||
results, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "deployed-app-repository",
|
||||
Args: []string{appName},
|
||||
})
|
||||
if err == nil {
|
||||
imageRemoteRepository = strings.TrimSpace(string(b[:]))
|
||||
imageRemoteRepository = results.StdoutContents()
|
||||
}
|
||||
return err
|
||||
})
|
||||
errs.Go(func() error {
|
||||
b, err := PlugnTriggerOutput("deployed-app-image-tag", []string{appName}...)
|
||||
results, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "deployed-app-image-tag",
|
||||
Args: []string{appName},
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
newImageTag = strings.TrimSpace(string(b[:]))
|
||||
newImageTag = results.StdoutContents()
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
errs.Go(func() error {
|
||||
b, err := PlugnTriggerOutput("deployed-app-image-repo", []string{appName}...)
|
||||
results, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "deployed-app-image-repo",
|
||||
Args: []string{appName},
|
||||
})
|
||||
if err == nil {
|
||||
newImageRepo = strings.TrimSpace(string(b[:]))
|
||||
newImageRepo = results.StdoutContents()
|
||||
}
|
||||
return err
|
||||
})
|
||||
@@ -251,11 +267,14 @@ func GetAppRunningContainerIDs(appName string, containerType string) ([]string,
|
||||
|
||||
// GetRunningImageTag retrieves current deployed image tag for a given app
|
||||
func GetRunningImageTag(appName string, imageTag string) (string, error) {
|
||||
b, err := PlugnTriggerOutput("deployed-app-image-tag", []string{appName}...)
|
||||
results, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "deployed-app-image-tag",
|
||||
Args: []string{appName},
|
||||
})
|
||||
if err != nil {
|
||||
return imageTag, err
|
||||
}
|
||||
newImageTag := strings.TrimSpace(string(b[:]))
|
||||
newImageTag := results.StdoutContents()
|
||||
if newImageTag != "" {
|
||||
imageTag = newImageTag
|
||||
}
|
||||
@@ -326,7 +345,10 @@ func IsDeployed(appName string) bool {
|
||||
if deployed == "" {
|
||||
deployed = "false"
|
||||
scheduler := GetAppScheduler(appName)
|
||||
_, err := PlugnTriggerOutput("scheduler-is-deployed", []string{scheduler, appName}...)
|
||||
_, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "scheduler-is-deployed",
|
||||
Args: []string{scheduler, appName},
|
||||
})
|
||||
if err == nil {
|
||||
deployed = "true"
|
||||
}
|
||||
|
||||
@@ -182,9 +182,11 @@ func DockerCleanup(appName string, forceCleanup bool) error {
|
||||
triggerArgs = []string{"DOKKU_SKIP_CLEANUP"}
|
||||
}
|
||||
|
||||
b, _ := PlugnTriggerOutput(triggerName, triggerArgs...)
|
||||
output := strings.TrimSpace(string(b[:]))
|
||||
if output == "true" {
|
||||
results, _ := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: triggerName,
|
||||
Args: triggerArgs,
|
||||
})
|
||||
if results.StdoutContents() == "true" {
|
||||
skipCleanup = true
|
||||
}
|
||||
}
|
||||
@@ -309,9 +311,12 @@ func IsImageHerokuishBased(image string, appName string) bool {
|
||||
|
||||
dokkuAppUser := ""
|
||||
if len(appName) != 0 {
|
||||
b, err := PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_USER"}...)
|
||||
results, err := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_APP_USER"},
|
||||
})
|
||||
if err == nil {
|
||||
dokkuAppUser = strings.TrimSpace(string(b))
|
||||
dokkuAppUser = results.StdoutContents()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,16 @@ func (ecr ExecCommandResponse) StderrContents() string {
|
||||
return strings.TrimSpace(ecr.Stderr)
|
||||
}
|
||||
|
||||
// StderrBytes returns the trimmed stderr of the command as bytes
|
||||
func (ecr ExecCommandResponse) StderrBytes() []byte {
|
||||
return []byte(ecr.StderrContents())
|
||||
}
|
||||
|
||||
// StdoutBytes returns the trimmed stdout of the command as bytes
|
||||
func (ecr ExecCommandResponse) StdoutBytes() []byte {
|
||||
return []byte(ecr.StdoutContents())
|
||||
}
|
||||
|
||||
// CallExecCommand executes a command on the local host
|
||||
func CallExecCommand(input ExecCommandInput) (ExecCommandResponse, error) {
|
||||
ctx := context.Background()
|
||||
|
||||
@@ -944,7 +944,7 @@ acquire_app_deploy_lock() {
|
||||
declare desc="acquire advisory lock for use in deploys"
|
||||
local APP="$1"
|
||||
local LOCK_TYPE="${2:-waiting}"
|
||||
local APP_DEPLOY_LOCK_FILE="$DOKKU_ROOT/$APP/.deploy.lock"
|
||||
local APP_DEPLOY_LOCK_FILE="$DOKKU_LIB_ROOT/data/apps/$APP/.deploy.lock"
|
||||
local LOCK_WAITING_MSG="$APP currently has a deploy lock in place. Waiting..."
|
||||
local LOCK_FAILED_MSG="$APP currently has a deploy lock in place. Exiting..."
|
||||
|
||||
@@ -954,7 +954,7 @@ acquire_app_deploy_lock() {
|
||||
release_app_deploy_lock() {
|
||||
declare desc="release advisory lock used in deploys"
|
||||
local APP="$1"
|
||||
local APP_DEPLOY_LOCK_FILE="$DOKKU_ROOT/$APP/.deploy.lock"
|
||||
local APP_DEPLOY_LOCK_FILE="$DOKKU_LIB_ROOT/data/apps/$APP/.deploy.lock"
|
||||
|
||||
release_advisory_lock "$APP_DEPLOY_LOCK_FILE"
|
||||
}
|
||||
@@ -983,6 +983,7 @@ acquire_advisory_lock() {
|
||||
dokku_log_fail "Run 'apps:unlock' to release the existing deploy lock"
|
||||
fi
|
||||
fi
|
||||
echo "$DOKKU_PID" >"$LOCK_FILE"
|
||||
}
|
||||
|
||||
release_advisory_lock() {
|
||||
@@ -997,13 +998,14 @@ suppress_output() {
|
||||
declare desc="suppress all output from a given command unless there is an error"
|
||||
local TMP_COMMAND_OUTPUT
|
||||
TMP_COMMAND_OUTPUT=$(mktemp "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
|
||||
trap "rm -rf '$TMP_COMMAND_OUTPUT' >/dev/null" RETURN
|
||||
|
||||
"$@" >"$TMP_COMMAND_OUTPUT" 2>&1 || {
|
||||
local exit_code="$?"
|
||||
cat "$TMP_COMMAND_OUTPUT"
|
||||
rm -rf "$TMP_COMMAND_OUTPUT" >/dev/null
|
||||
return "$exit_code"
|
||||
}
|
||||
rm -rf "$TMP_COMMAND_OUTPUT" >/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,11 @@ func filterApps(apps []string) ([]string, error) {
|
||||
}
|
||||
|
||||
args := append([]string{sshUser, sshName}, apps...)
|
||||
b, _ := PlugnTriggerOutput("user-auth-app", args...)
|
||||
filteredApps := strings.Split(strings.TrimSpace(string(b[:])), "\n")
|
||||
results, _ := CallPlugnTrigger(PlugnTriggerInput{
|
||||
Trigger: "user-auth-app",
|
||||
Args: args,
|
||||
})
|
||||
filteredApps := strings.Split(results.StdoutContents(), "\n")
|
||||
filteredApps = removeEmptyEntries(filteredApps)
|
||||
|
||||
if len(filteredApps) == 0 {
|
||||
|
||||
@@ -4,7 +4,6 @@ go 1.21
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/melbahja/goph v1.4.0
|
||||
@@ -17,7 +16,6 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -1,158 +1,10 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"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
|
||||
ExitError *exec.ExitError
|
||||
}
|
||||
|
||||
// NewShellCmd returns a new ShellCmd struct
|
||||
//
|
||||
// Deprecated: use CallExecCommand instead
|
||||
func NewShellCmd(command string) *ShellCmd {
|
||||
items := strings.Split(command, " ")
|
||||
cmd := items[0]
|
||||
args := items[1:]
|
||||
return NewShellCmdWithArgs(cmd, args...)
|
||||
}
|
||||
|
||||
// NewShellCmdWithArgs returns a new ShellCmd struct
|
||||
//
|
||||
// Deprecated: use CallExecCommand instead
|
||||
func NewShellCmdWithArgs(cmd string, args ...string) *ShellCmd {
|
||||
commandString := strings.Join(append([]string{cmd}, args...), " ")
|
||||
|
||||
return &ShellCmd{
|
||||
Command: exec.Command(cmd, args...),
|
||||
CommandString: commandString,
|
||||
Args: args,
|
||||
ShowOutput: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *ShellCmd) setup() {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// Execute is a lightweight wrapper around exec.Command
|
||||
func (sc *ShellCmd) Execute() bool {
|
||||
sc.setup()
|
||||
|
||||
if err := sc.Command.Run(); err != nil {
|
||||
exitError, ok := err.(*exec.ExitError)
|
||||
if ok {
|
||||
sc.ExitError = exitError
|
||||
}
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Start is a wrapper around exec.Command.Start()
|
||||
func (sc *ShellCmd) Start() error {
|
||||
sc.setup()
|
||||
|
||||
return sc.Command.Start()
|
||||
}
|
||||
|
||||
// Output is a lightweight wrapper around exec.Command.Output()
|
||||
func (sc *ShellCmd) Output() ([]byte, error) {
|
||||
sc.setup()
|
||||
return sc.Command.Output()
|
||||
}
|
||||
|
||||
// CombinedOutput is a lightweight wrapper around exec.Command.CombinedOutput()
|
||||
func (sc *ShellCmd) CombinedOutput() ([]byte, error) {
|
||||
sc.setup()
|
||||
return sc.Command.CombinedOutput()
|
||||
}
|
||||
|
||||
// PlugnTrigger fire the given plugn trigger with the given args
|
||||
//
|
||||
// Deprecated: use CallPlugnTrigger instead
|
||||
func PlugnTrigger(triggerName string, args ...string) error {
|
||||
LogDebug(fmt.Sprintf("plugn trigger %s %v", triggerName, args))
|
||||
return PlugnTriggerSetup(triggerName, args...).Run()
|
||||
}
|
||||
|
||||
// PlugnTriggerOutput fire the given plugn trigger with the given args
|
||||
//
|
||||
// Deprecated: use CallPlugnTrigger with CaptureOutput=true instead
|
||||
func PlugnTriggerOutput(triggerName string, args ...string) ([]byte, error) {
|
||||
LogDebug(fmt.Sprintf("plugn trigger %s %v", triggerName, args))
|
||||
rE, wE, _ := os.Pipe()
|
||||
rO, wO, _ := os.Pipe()
|
||||
session := PlugnTriggerSetup(triggerName, args...)
|
||||
session.Stderr = wE
|
||||
session.Stdout = wO
|
||||
err := session.Run()
|
||||
wE.Close()
|
||||
wO.Close()
|
||||
|
||||
readStderr, _ := io.ReadAll(rE)
|
||||
readStdout, _ := io.ReadAll(rO)
|
||||
|
||||
stderr := string(readStderr[:])
|
||||
if err != nil {
|
||||
err = fmt.Errorf(stderr)
|
||||
}
|
||||
|
||||
if os.Getenv("DOKKU_TRACE") == "1" {
|
||||
for _, line := range strings.Split(stderr, "\n") {
|
||||
LogDebug(fmt.Sprintf("plugn trigger %s stderr: %s", triggerName, line))
|
||||
}
|
||||
for _, line := range strings.Split(string(readStdout[:]), "\n") {
|
||||
LogDebug(fmt.Sprintf("plugn trigger %s stdout: %s", triggerName, line))
|
||||
}
|
||||
}
|
||||
|
||||
return readStdout, err
|
||||
}
|
||||
|
||||
// PlugnTriggerOutputAsString fires the given plugn trigger with the given args and returns the string contents instead of bytes
|
||||
//
|
||||
// Deprecated: use CallPlugnTrigger with CaptureOutput=true instead
|
||||
func PlugnTriggerOutputAsString(triggerName string, args ...string) (string, error) {
|
||||
b, err := PlugnTriggerOutput(triggerName, args...)
|
||||
return strings.TrimSpace(string(b[:])), err
|
||||
}
|
||||
|
||||
// PlugnTriggerSetup sets up a plugn trigger call
|
||||
//
|
||||
// Deprecated: use CallPlugnTrigger instead
|
||||
func PlugnTriggerSetup(triggerName string, args ...string) *sh.Session {
|
||||
shellArgs := make([]interface{}, len(args)+2)
|
||||
shellArgs[0] = "trigger"
|
||||
shellArgs[1] = triggerName
|
||||
for i, arg := range args {
|
||||
shellArgs[i+2] = arg
|
||||
}
|
||||
return sh.Command("plugn", shellArgs...)
|
||||
}
|
||||
|
||||
// PlugnTriggerExists returns whether a plugin trigger exists (ignoring the existence of any within the 20_events plugin)
|
||||
func PlugnTriggerExists(triggerName string) bool {
|
||||
pluginPath := MustGetEnv("PLUGIN_PATH")
|
||||
|
||||
1
plugins/config/.gitignore
vendored
1
plugins/config/.gitignore
vendored
@@ -4,3 +4,4 @@
|
||||
/triggers
|
||||
/config-*
|
||||
/config_sub
|
||||
/post-*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
GOARCH ?= amd64
|
||||
SUBCOMMANDS = subcommands/bundle subcommands/clear subcommands/export subcommands/get subcommands/keys subcommands/show subcommands/set subcommands/unset
|
||||
TRIGGERS = triggers/config-export triggers/config-get triggers/config-get-global
|
||||
TRIGGERS = triggers/config-export triggers/config-get triggers/config-get-global triggers/post-app-clone-setup triggers/post-app-rename-setup
|
||||
BUILD = commands config_sub subcommands triggers
|
||||
PLUGIN_NAME = config
|
||||
|
||||
|
||||
@@ -129,14 +129,24 @@ func UnsetAll(appName string, restart bool) (err error) {
|
||||
|
||||
func triggerRestart(appName string) {
|
||||
common.LogInfo1(fmt.Sprintf("Restarting app %s", appName))
|
||||
if err := common.PlugnTrigger("release-and-deploy", appName); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "release-and-deploy",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
common.LogWarn(fmt.Sprintf("Failure while restarting app: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
func triggerUpdate(appName string, operation string, args []string) {
|
||||
args = append([]string{appName, operation}, args...)
|
||||
if err := common.PlugnTrigger("post-config-update", args...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-config-update",
|
||||
Args: args,
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
common.LogWarn(fmt.Sprintf("Failure while triggering post-config-update: %s", err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
"github.com/ryanuber/columnize"
|
||||
)
|
||||
|
||||
//ExportFormat types of possible exports
|
||||
// ExportFormat types of possible exports
|
||||
type ExportFormat int
|
||||
|
||||
const (
|
||||
@@ -40,14 +40,14 @@ const (
|
||||
ExportFormatPackArgKeys
|
||||
)
|
||||
|
||||
//Env is a representation for global or app environment
|
||||
// Env is a representation for global or app environment
|
||||
type Env struct {
|
||||
name string
|
||||
filename string
|
||||
env map[string]string
|
||||
}
|
||||
|
||||
//newEnvFromString creates an env from the given ENVFILE contents representation
|
||||
// newEnvFromString creates an env from the given ENVFILE contents representation
|
||||
func newEnvFromString(rep string) (env *Env, err error) {
|
||||
envMap, err := godotenv.Unmarshal(rep)
|
||||
env = &Env{
|
||||
@@ -58,7 +58,7 @@ func newEnvFromString(rep string) (env *Env, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//LoadAppEnv loads an environment for the given app
|
||||
// LoadAppEnv loads an environment for the given app
|
||||
func LoadAppEnv(appName string) (env *Env, err error) {
|
||||
appfile, err := getAppFile(appName)
|
||||
if err != nil {
|
||||
@@ -67,7 +67,7 @@ func LoadAppEnv(appName string) (env *Env, err error) {
|
||||
return loadFromFile(appName, appfile)
|
||||
}
|
||||
|
||||
//LoadMergedAppEnv loads an app environment merged with the global environment
|
||||
// LoadMergedAppEnv loads an app environment merged with the global environment
|
||||
func LoadMergedAppEnv(appName string) (env *Env, err error) {
|
||||
env, err = LoadAppEnv(appName)
|
||||
if err != nil {
|
||||
@@ -83,7 +83,7 @@ func LoadMergedAppEnv(appName string) (env *Env, err error) {
|
||||
return global, err
|
||||
}
|
||||
|
||||
//LoadGlobalEnv loads the global environment
|
||||
// LoadGlobalEnv loads the global environment
|
||||
func LoadGlobalEnv() (*Env, error) {
|
||||
return loadFromFile("<global>", getGlobalFile())
|
||||
}
|
||||
@@ -93,13 +93,13 @@ func (e *Env) Filename() string {
|
||||
return e.filename
|
||||
}
|
||||
|
||||
//Get an environment variable
|
||||
// Get an environment variable
|
||||
func (e *Env) Get(key string) (value string, ok bool) {
|
||||
value, ok = e.env[key]
|
||||
return
|
||||
}
|
||||
|
||||
//GetDefault an environment variable or a default if it doesn't exist
|
||||
// GetDefault an environment variable or a default if it doesn't exist
|
||||
func (e *Env) GetDefault(key string, defaultValue string) string {
|
||||
v, ok := e.env[key]
|
||||
if !ok {
|
||||
@@ -108,8 +108,8 @@ func (e *Env) GetDefault(key string, defaultValue string) string {
|
||||
return v
|
||||
}
|
||||
|
||||
//GetBoolDefault gets the bool value of the given key with the given default
|
||||
//right now that is evaluated as `value != "0"`
|
||||
// GetBoolDefault gets the bool value of the given key with the given default
|
||||
// right now that is evaluated as `value != "0"`
|
||||
func (e *Env) GetBoolDefault(key string, defaultValue bool) bool {
|
||||
v, ok := e.Get(key)
|
||||
if !ok {
|
||||
@@ -118,17 +118,17 @@ func (e *Env) GetBoolDefault(key string, defaultValue bool) bool {
|
||||
return v != "0"
|
||||
}
|
||||
|
||||
//Set an environment variable
|
||||
// Set an environment variable
|
||||
func (e *Env) Set(key string, value string) {
|
||||
e.env[key] = value
|
||||
}
|
||||
|
||||
//Unset an environment variable
|
||||
// Unset an environment variable
|
||||
func (e *Env) Unset(key string) {
|
||||
delete(e.env, key)
|
||||
}
|
||||
|
||||
//Keys gets the keys in this environment
|
||||
// Keys gets the keys in this environment
|
||||
func (e *Env) Keys() (keys []string) {
|
||||
keys = make([]string, 0, len(e.env))
|
||||
for k := range e.env {
|
||||
@@ -138,12 +138,12 @@ func (e *Env) Keys() (keys []string) {
|
||||
return
|
||||
}
|
||||
|
||||
//Len returns the number of items in this environment
|
||||
// Len returns the number of items in this environment
|
||||
func (e *Env) Len() int {
|
||||
return len(e.env)
|
||||
}
|
||||
|
||||
//Map returns the Env as a map
|
||||
// Map returns the Env as a map
|
||||
func (e *Env) Map() map[string]string {
|
||||
return e.env
|
||||
}
|
||||
@@ -152,14 +152,14 @@ func (e *Env) String() string {
|
||||
return e.EnvfileString()
|
||||
}
|
||||
|
||||
//Merge merges the given environment on top of the receiver
|
||||
// Merge merges the given environment on top of the receiver
|
||||
func (e *Env) Merge(other *Env) {
|
||||
for _, k := range other.Keys() {
|
||||
e.Set(k, other.GetDefault(k, ""))
|
||||
}
|
||||
}
|
||||
|
||||
//Write an Env back to the file it was read from as an exportfile
|
||||
// Write an Env back to the file it was read from as an exportfile
|
||||
func (e *Env) Write() error {
|
||||
if e.filename == "" {
|
||||
return errors.New("this Env was created unbound to a file")
|
||||
@@ -167,7 +167,7 @@ func (e *Env) Write() error {
|
||||
return godotenv.Write(e.Map(), e.filename)
|
||||
}
|
||||
|
||||
//Export the Env in the given format
|
||||
// Export the Env in the given format
|
||||
func (e *Env) Export(format ExportFormat) string {
|
||||
switch format {
|
||||
case ExportFormatExports:
|
||||
@@ -194,23 +194,23 @@ func (e *Env) Export(format ExportFormat) string {
|
||||
}
|
||||
}
|
||||
|
||||
//EnvfileString returns the contents of this Env in dotenv format
|
||||
// EnvfileString returns the contents of this Env in dotenv format
|
||||
func (e *Env) EnvfileString() string {
|
||||
rep, _ := godotenv.Marshal(e.Map())
|
||||
return rep
|
||||
}
|
||||
|
||||
//ExportfileString returns the contents of this Env as bash exports
|
||||
// ExportfileString returns the contents of this Env as bash exports
|
||||
func (e *Env) ExportfileString() string {
|
||||
return e.stringWithPrefixAndSeparator("export ", "\n")
|
||||
}
|
||||
|
||||
//DockerArgsString gets the contents of this Env in the form -env=KEY=VALUE --env...
|
||||
// DockerArgsString gets the contents of this Env in the form -env=KEY=VALUE --env...
|
||||
func (e *Env) DockerArgsString() string {
|
||||
return e.stringWithPrefixAndSeparator("--env=", " ")
|
||||
}
|
||||
|
||||
//DockerArgsKeysString gets the contents of this Env in the form -env=KEY --env...
|
||||
// DockerArgsKeysString gets the contents of this Env in the form -env=KEY --env...
|
||||
func (e *Env) DockerArgsKeysString() string {
|
||||
keys := e.Keys()
|
||||
entries := make([]string, len(keys))
|
||||
@@ -220,7 +220,7 @@ func (e *Env) DockerArgsKeysString() string {
|
||||
return strings.Join(entries, " ")
|
||||
}
|
||||
|
||||
//JSONString returns the contents of this Env as a key/value json object
|
||||
// JSONString returns the contents of this Env as a key/value json object
|
||||
func (e *Env) JSONString() string {
|
||||
data, err := json.Marshal(e.Map())
|
||||
if err != nil {
|
||||
@@ -230,7 +230,7 @@ func (e *Env) JSONString() string {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
//JSONListString returns the contents of this Env as a json list of objects containing the name and the value of the env var
|
||||
// JSONListString returns the contents of this Env as a json list of objects containing the name and the value of the env var
|
||||
func (e *Env) JSONListString() string {
|
||||
var list []map[string]string
|
||||
for _, key := range e.Keys() {
|
||||
@@ -249,7 +249,7 @@ func (e *Env) JSONListString() string {
|
||||
return string(data)
|
||||
}
|
||||
|
||||
//PackArgKeysAsString gets the contents of this Env in the form -env KEY --env...
|
||||
// PackArgKeysAsString gets the contents of this Env in the form -env KEY --env...
|
||||
func (e *Env) PackArgKeysAsString() string {
|
||||
keys := e.Keys()
|
||||
entries := make([]string, len(keys))
|
||||
@@ -259,13 +259,13 @@ func (e *Env) PackArgKeysAsString() string {
|
||||
return strings.Join(entries, " ")
|
||||
}
|
||||
|
||||
//ShellString gets the contents of this Env in the form "KEY='value' KEY2='value'"
|
||||
// ShellString gets the contents of this Env in the form "KEY='value' KEY2='value'"
|
||||
// for passing the environment in the shell
|
||||
func (e *Env) ShellString() string {
|
||||
return e.stringWithPrefixAndSeparator("", " ")
|
||||
}
|
||||
|
||||
//ExportBundle writes a tarfile of the environment to the given io.Writer.
|
||||
// ExportBundle writes a tarfile of the environment to the given io.Writer.
|
||||
// for every environment variable there is a file with the variable's key
|
||||
// with its content set to the variable's value
|
||||
func (e *Env) ExportBundle(dest io.Writer) error {
|
||||
@@ -287,7 +287,7 @@ func (e *Env) ExportBundle(dest io.Writer) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//stringWithPrefixAndSeparator makes a string of the environment
|
||||
// stringWithPrefixAndSeparator makes a string of the environment
|
||||
// with the given prefix and separator for each entry
|
||||
func (e *Env) stringWithPrefixAndSeparator(prefix string, separator string) string {
|
||||
keys := e.Keys()
|
||||
@@ -299,12 +299,12 @@ func (e *Env) stringWithPrefixAndSeparator(prefix string, separator string) stri
|
||||
return strings.Join(entries, separator)
|
||||
}
|
||||
|
||||
//singleQuoteEscape escapes the value as if it were shell-quoted in single quotes
|
||||
// singleQuoteEscape escapes the value as if it were shell-quoted in single quotes
|
||||
func singleQuoteEscape(value string) string { // so that 'esc'aped' -> 'esc'\''aped'
|
||||
return strings.Replace(value, "'", "'\\''", -1)
|
||||
}
|
||||
|
||||
//prettyPrintEnvEntries in columns
|
||||
// prettyPrintEnvEntries in columns
|
||||
func prettyPrintEnvEntries(prefix string, entries map[string]string) string {
|
||||
colConfig := columnize.DefaultConfig()
|
||||
colConfig.Prefix = prefix
|
||||
|
||||
@@ -12,8 +12,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -36,6 +36,14 @@ func main() {
|
||||
case "config-get-global":
|
||||
key := flag.Arg(0)
|
||||
err = config.TriggerConfigGetGlobal(key)
|
||||
case "post-app-clone-setup":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = config.TriggerPostAppCloneSetup(oldAppName, newAppName)
|
||||
case "post-app-rename-setup":
|
||||
oldAppName := flag.Arg(0)
|
||||
newAppName := flag.Arg(1)
|
||||
err = config.TriggerPostAppRenameSetup(oldAppName, newAppName)
|
||||
default:
|
||||
err = fmt.Errorf("Invalid plugin trigger call: %s", trigger)
|
||||
}
|
||||
|
||||
@@ -44,3 +44,43 @@ func TriggerConfigGetGlobal(key string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostAppCloneSetup creates new buildpacks files
|
||||
func TriggerPostAppCloneSetup(oldAppName string, newAppName string) error {
|
||||
oldEnv, err := LoadAppEnv(oldAppName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to load old environment: %s", err.Error())
|
||||
}
|
||||
|
||||
newEnv, err := LoadAppEnv(newAppName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to load new environment: %s", err.Error())
|
||||
}
|
||||
|
||||
newEnv.Merge(oldEnv)
|
||||
if err := newEnv.Write(); err != nil {
|
||||
return fmt.Errorf("Unable to write new environment: %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostAppRenameSetup renames buildpacks files
|
||||
func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
||||
oldEnv, err := LoadAppEnv(oldAppName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to load old environment: %s", err.Error())
|
||||
}
|
||||
|
||||
newEnv, err := LoadAppEnv(newAppName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Unable to load new environment: %s", err.Error())
|
||||
}
|
||||
|
||||
newEnv.Merge(oldEnv)
|
||||
if err := newEnv.Write(); err != nil {
|
||||
return fmt.Errorf("Unable to write new environment: %s", err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
func main() {
|
||||
parts := strings.Split(os.Args[0], "/")
|
||||
trigger := parts[len(parts)-1]
|
||||
global := flag.Bool("global", false, "--global: Whether global or app-specific")
|
||||
flag.Parse()
|
||||
|
||||
var err error
|
||||
@@ -21,6 +22,10 @@ func main() {
|
||||
case "cron-get-property":
|
||||
appName := flag.Arg(0)
|
||||
property := flag.Arg(1)
|
||||
if *global {
|
||||
appName = "--global"
|
||||
property = flag.Arg(0)
|
||||
}
|
||||
err = cron.TriggerCronGetProperty(appName, property)
|
||||
case "install":
|
||||
err = cron.TriggerInstall()
|
||||
|
||||
@@ -110,7 +110,12 @@ func CommandRun(appName string, cronID string, detached bool) error {
|
||||
os.Setenv("DOKKU_RM_CONTAINER", "1")
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
args := append([]string{scheduler, appName, "0", "--"}, fields...)
|
||||
return common.PlugnTrigger("scheduler-run", args...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-run",
|
||||
Args: args,
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandSet set or clear a cron property for an app
|
||||
@@ -120,5 +125,9 @@ func CommandSet(appName string, property string, value string) error {
|
||||
}
|
||||
|
||||
common.CommandPropertySet("cron", appName, property, value, DefaultProperties, GlobalProperties)
|
||||
return common.PlugnTrigger("cron-write")
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "cron-write",
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ require github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
20
plugins/docker-options/post-app-clone-setup
Executable file
20
plugins/docker-options/post-app-clone-setup
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_AVAILABLE_PATH/docker-options/functions"
|
||||
|
||||
trigger-docker-options-post-app-clone-setup() {
|
||||
declare desc="copies docker options over"
|
||||
declare trigger="post-app-clone-setup"
|
||||
declare OLD_APP="$1" NEW_APP="$2"
|
||||
|
||||
declare -a phases
|
||||
phases=("build" "deploy" "run")
|
||||
for phase in "${phases[@]}"; do
|
||||
if [[ -f "$(fn-get-phase-file-path "$OLD_APP" "$phase")" ]]; then
|
||||
cp "$(fn-get-phase-file-path "$OLD_APP" "$phase")" "$(fn-get-phase-file-path "$NEW_APP" "$phase")"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
trigger-docker-options-post-app-clone-setup "$@"
|
||||
20
plugins/docker-options/post-app-rename-setup
Executable file
20
plugins/docker-options/post-app-rename-setup
Executable file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
[[ $DOKKU_TRACE ]] && set -x
|
||||
source "$PLUGIN_AVAILABLE_PATH/docker-options/functions"
|
||||
|
||||
trigger-docker-options-post-app-rename-setup() {
|
||||
declare desc="copies docker options over"
|
||||
declare trigger="post-app-rename-setup"
|
||||
declare OLD_APP="$1" NEW_APP="$2"
|
||||
|
||||
declare -a phases
|
||||
phases=("build" "deploy" "run")
|
||||
for phase in "${phases[@]}"; do
|
||||
if [[ -f "$(fn-get-phase-file-path "$OLD_APP" "$phase")" ]]; then
|
||||
cp "$(fn-get-phase-file-path "$OLD_APP" "$phase")" "$(fn-get-phase-file-path "$NEW_APP" "$phase")"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
trigger-docker-options-post-app-rename-setup "$@"
|
||||
@@ -7,9 +7,9 @@ trigger-domains-post-app-rename-setup() {
|
||||
declare trigger="post-app-rename-setup"
|
||||
declare OLD_APP="$1" NEW_APP="$2"
|
||||
|
||||
if [[ -f "$DOKKU_ROOT/$NEW_APP/VHOST" ]]; then
|
||||
if [[ -f "$DOKKU_ROOT/$OLD_APP/VHOST" ]]; then
|
||||
while read -r VHOST || [[ -n "$VHOST" ]]; do
|
||||
sed -i -e "s/$OLD_APP.$VHOST/$NEW_APP.$VHOST/g" "$DOKKU_ROOT/$NEW_APP/VHOST"
|
||||
sed -e "s/$OLD_APP.$VHOST/$NEW_APP.$VHOST/g" "$DOKKU_ROOT/$OLD_APP/VHOST" >"$DOKKU_ROOT/$NEW_APP/VHOST"
|
||||
done <"$DOKKU_ROOT/VHOST"
|
||||
fi
|
||||
}
|
||||
|
||||
@@ -17,10 +17,9 @@ trigger-git-git-from-directory() {
|
||||
local TMP_WORK_DIR_2=$(mktemp -d "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
|
||||
trap "rm -rf '$TMP_WORK_DIR' '$TMP_WORK_DIR_2' >/dev/null" RETURN INT TERM EXIT
|
||||
|
||||
local has_code=true
|
||||
local git_objects="$(fn-git-cmd "$APP_ROOT" count-objects 2>/dev/null || true)"
|
||||
if [[ -z "$git_objects" ]] || [[ "$git_objects" == "0 objects, 0 kilobytes" ]]; then
|
||||
local has_code=false
|
||||
local has_code=false
|
||||
if fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" >/dev/null 2>&1; then
|
||||
has_code=true
|
||||
fi
|
||||
|
||||
dokku_log_info1 "Updating git repository with specified build context"
|
||||
|
||||
@@ -38,7 +38,6 @@ fn-help-content() {
|
||||
git:public-key, Outputs the dokku public deploy key
|
||||
git:report [<app>] [<flag>], Displays a git report for one or more apps
|
||||
git:set <app> <property> (<value>), Set or clear a git property for an app
|
||||
git:unlock <app> [--force], Removes previous git clone folder for new deployment
|
||||
git:status <app>, show the working tree status for an app
|
||||
help_content
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ cmd-git-sync() {
|
||||
local cmd="git:sync"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP GIT_REMOTE GIT_REF FLAG
|
||||
local CURRENT_REF DOKKU_DEPLOY_BRANCH SHOULD_BUILD UPDATED_REF
|
||||
|
||||
ARGS=()
|
||||
for arg in "$@"; do
|
||||
@@ -187,6 +188,11 @@ cmd-git-sync() {
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$arg" == "--build-if-changes" ]]; then
|
||||
FLAG="--build-if-changes"
|
||||
continue
|
||||
fi
|
||||
|
||||
ARGS+=("$arg")
|
||||
done
|
||||
|
||||
@@ -196,32 +202,37 @@ cmd-git-sync() {
|
||||
|
||||
verify_app_name "$APP"
|
||||
|
||||
if [[ -d "$DOKKU_LIB_ROOT/data/git/$APP" ]]; then
|
||||
if has_tty eq 0; then
|
||||
cmd-git-unlock "$APP"
|
||||
if [[ -d "$DOKKU_LIB_ROOT/data/git/$APP" ]]; then
|
||||
dokku_log_fail "Failed to delete existing clone folder"
|
||||
exit 15
|
||||
fi
|
||||
else
|
||||
dokku_log_fail "Run 'git:unlock' to remove the existing temporary clone"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "$GIT_REMOTE" ]]; then
|
||||
dokku_log_fail "Missing GIT_REMOTE parameter"
|
||||
return
|
||||
fi
|
||||
|
||||
local APP_ROOT="$DOKKU_ROOT/$APP"
|
||||
if [[ "$(fn-git-cmd "$APP_ROOT" count-objects)" == "0 objects, 0 kilobytes" ]]; then
|
||||
DOKKU_DEPLOY_BRANCH="$(fn-git-deploy-branch "$APP")"
|
||||
CURRENT_REF="$(fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" 2>/dev/null || true)"
|
||||
|
||||
if ! fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" >/dev/null 2>&1; then
|
||||
dokku_log_info1_quiet "Cloning $APP from $GIT_REMOTE#$GIT_REF"
|
||||
fn-git-clone "$APP" "$GIT_REMOTE" "$GIT_REF"
|
||||
else
|
||||
dokku_log_verbose "Fetching remote code for $APP from $GIT_REMOTE#$GIT_REF"
|
||||
fn-git-fetch "$APP" "$GIT_REMOTE" "$GIT_REF"
|
||||
fi
|
||||
|
||||
UPDATED_REF="$(fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" 2>/dev/null || true)"
|
||||
local SHOULD_BUILD=false
|
||||
if [[ "$FLAG" == "--build" ]]; then
|
||||
SHOULD_BUILD=true
|
||||
elif [[ "$FLAG" == "--build-if-changes" ]]; then
|
||||
if [[ "$CURRENT_REF" == "$UPDATED_REF" ]]; then
|
||||
dokku_log_verbose "Skipping build as no changes were detected"
|
||||
return
|
||||
fi
|
||||
|
||||
SHOULD_BUILD=true
|
||||
fi
|
||||
|
||||
if [[ "$SHOULD_BUILD" == "true" ]]; then
|
||||
if [[ -n "$GIT_REF" ]]; then
|
||||
GIT_REF="$(fn-git-cmd "$APP_ROOT" rev-parse "$GIT_REF")"
|
||||
plugn trigger receive-app "$APP" "$GIT_REF"
|
||||
@@ -232,40 +243,6 @@ cmd-git-sync() {
|
||||
fi
|
||||
}
|
||||
|
||||
cmd-git-unlock() {
|
||||
declare desc="removes the clone folder for an app"
|
||||
local cmd="git:unlock"
|
||||
[[ "$1" == "$cmd" ]] && shift 1
|
||||
declare APP="$1" FLAG
|
||||
|
||||
for arg in "$@"; do
|
||||
if [[ "$arg" == "--force" ]]; then
|
||||
FLAG="--force"
|
||||
continue
|
||||
fi
|
||||
|
||||
ARGS+=("$arg")
|
||||
done
|
||||
|
||||
local APP_CLONE_ROOT="$DOKKU_LIB_ROOT/data/git/$APP"
|
||||
|
||||
if [[ -d "$APP_CLONE_ROOT" ]]; then
|
||||
if [[ "$FLAG" == "--force" ]]; then
|
||||
fn-git-remove-clone-folder "$APP_CLONE_ROOT"
|
||||
else
|
||||
read -rp "Are you sure that want to delete clone folder (y/n)?" choice
|
||||
case "$choice" in
|
||||
y | Y)
|
||||
fn-git-remove-clone-folder "$APP_CLONE_ROOT"
|
||||
;;
|
||||
n | N) echo "no" ;;
|
||||
*) echo "please answer with yes or no" ;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
dokku_log_info1 "No clone folder exists app already unlocked"
|
||||
fi
|
||||
}
|
||||
cmd-git-public-key() {
|
||||
declare desc="outputs the dokku public deploy key"
|
||||
local cmd="git:public-key"
|
||||
@@ -396,11 +373,11 @@ EOF
|
||||
fn-git-clone() {
|
||||
declare desc="creates an app from remote git repo"
|
||||
declare APP="$1" GIT_REMOTE="$2" GIT_REF="$3"
|
||||
local APP_CLONE_ROOT="$DOKKU_LIB_ROOT/data/git/$APP"
|
||||
local APP_ROOT="$DOKKU_ROOT/$APP"
|
||||
[[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on"
|
||||
|
||||
if [[ "$(fn-git-cmd "$APP_ROOT" count-objects)" != "0 objects, 0 kilobytes" ]]; then
|
||||
local DOKKU_DEPLOY_BRANCH="$(fn-git-deploy-branch "$APP")"
|
||||
if fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" >/dev/null 2>&1; then
|
||||
dokku_log_fail "The clone subcommand can only be executed for new applications"
|
||||
fi
|
||||
|
||||
@@ -408,20 +385,24 @@ fn-git-clone() {
|
||||
GIT_REF="$(fn-git-deploy-branch "$APP")"
|
||||
fi
|
||||
|
||||
trap "rm -rf '$APP_CLONE_ROOT' > /dev/null" RETURN INT TERM EXIT
|
||||
local TMP_IS_REF_DIR=$(mktemp -d "/tmp/dokku-ref-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
|
||||
trap "rm -rf '$TMP_IS_REF_DIR' >/dev/null" RETURN INT TERM EXIT
|
||||
|
||||
is_ref=true
|
||||
if GIT_TERMINAL_PROMPT=0 git clone --depth 1 -n --branch "$GIT_REF" "$GIT_REMOTE" "$APP_CLONE_ROOT" 2>/dev/null; then
|
||||
if GIT_TERMINAL_PROMPT=0 git clone --depth 1 -n --branch "$GIT_REF" "$GIT_REMOTE" "$TMP_IS_REF_DIR" 2>/dev/null; then
|
||||
is_ref=false
|
||||
fi
|
||||
rm -rf "$APP_CLONE_ROOT"
|
||||
rm -rf "$TMP_IS_REF_DIR"
|
||||
|
||||
local TMP_CLONE_DIR=$(mktemp -d "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
|
||||
trap "rm -rf '$TMP_CLONE_DIR' >/dev/null" RETURN INT TERM EXIT
|
||||
|
||||
if [[ "$is_ref" == "true" ]]; then
|
||||
GIT_TERMINAL_PROMPT=0 suppress_output git clone -n "$GIT_REMOTE" "$APP_CLONE_ROOT"
|
||||
fn-git-cmd "$APP_CLONE_ROOT" checkout -qq "$GIT_REF"
|
||||
GIT_TERMINAL_PROMPT=0 suppress_output git clone -n "$GIT_REMOTE" "$TMP_CLONE_DIR"
|
||||
fn-git-cmd "$TMP_CLONE_DIR" checkout -qq "$GIT_REF"
|
||||
else
|
||||
GIT_TERMINAL_PROMPT=0 suppress_output git clone -n --branch "$GIT_REF" "$GIT_REMOTE" "$APP_CLONE_ROOT"
|
||||
if fn-git-cmd "$APP_CLONE_ROOT" show-ref --verify "refs/heads/$GIT_REF" &>/dev/null; then
|
||||
GIT_TERMINAL_PROMPT=0 suppress_output git clone -n --branch "$GIT_REF" "$GIT_REMOTE" "$TMP_CLONE_DIR"
|
||||
if fn-git-cmd "$TMP_CLONE_DIR" show-ref --verify "refs/heads/$GIT_REF" &>/dev/null; then
|
||||
dokku_log_verbose "Detected branch, setting deploy-branch to $GIT_REF"
|
||||
fn-plugin-property-write "git" "$APP" "deploy-branch" "$GIT_REF"
|
||||
fi
|
||||
@@ -430,13 +411,13 @@ fn-git-clone() {
|
||||
DOKKU_DEPLOY_BRANCH="$(fn-git-deploy-branch "$APP")"
|
||||
if [[ "$GIT_REF" != "$DOKKU_DEPLOY_BRANCH" ]]; then
|
||||
if [[ "$is_ref" == "true" ]]; then
|
||||
fn-git-cmd "$APP_CLONE_ROOT" branch -qq -D "$DOKKU_DEPLOY_BRANCH" 2>/dev/null || true
|
||||
fn-git-cmd "$TMP_CLONE_DIR" branch -qq -D "$DOKKU_DEPLOY_BRANCH" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
fn-git-cmd "$APP_CLONE_ROOT" checkout -qq -b "$DOKKU_DEPLOY_BRANCH"
|
||||
fn-git-cmd "$TMP_CLONE_DIR" checkout -qq -b "$DOKKU_DEPLOY_BRANCH"
|
||||
fi
|
||||
|
||||
rsync -a "$APP_CLONE_ROOT/.git/" "$APP_ROOT"
|
||||
rsync -a "$TMP_CLONE_DIR/.git/" "$APP_ROOT"
|
||||
fn-git-create-hook "$APP"
|
||||
fn-git-cmd "$APP_ROOT" config --add core.bare true
|
||||
}
|
||||
@@ -458,7 +439,8 @@ fn-git-fetch() {
|
||||
local DOKKU_DEPLOY_BRANCH
|
||||
local APP_ROOT="$DOKKU_ROOT/$APP"
|
||||
|
||||
if [[ "$(fn-git-cmd "$APP_ROOT" count-objects)" == "0 objects, 0 kilobytes" ]]; then
|
||||
local DOKKU_DEPLOY_BRANCH="$(fn-git-deploy-branch "$APP")"
|
||||
if ! fn-git-cmd "$APP_ROOT" rev-parse "$DOKKU_DEPLOY_BRANCH" >/dev/null 2>&1; then
|
||||
dokku_log_fail "The fetch subcommand can only be executed for existing applications"
|
||||
fi
|
||||
|
||||
|
||||
@@ -7,8 +7,10 @@ trigger-git-post-delete() {
|
||||
declare desc="destroys the git properties for a given app"
|
||||
declare trigger="post-delete"
|
||||
declare APP="$1"
|
||||
local APP_CLONE_ROOT="$DOKKU_LIB_ROOT/data/git/$APP"
|
||||
|
||||
fn-plugin-property-destroy "git" "$APP"
|
||||
rm -rf "$APP_CLONE_ROOT"
|
||||
}
|
||||
|
||||
trigger-git-post-delete "$@"
|
||||
|
||||
@@ -11,8 +11,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -40,9 +40,11 @@ var templates embed.FS
|
||||
// GetFailedLogs outputs failed deploy logs for a given app
|
||||
func GetFailedLogs(appName string) error {
|
||||
common.LogInfo2Quiet(fmt.Sprintf("%s failed deploy logs", appName))
|
||||
s := common.GetAppScheduler(appName)
|
||||
if err := common.PlugnTrigger("scheduler-logs-failed", s, appName); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-logs-failed",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ func TriggerPostAppRenameSetup(oldAppName string, newAppName string) error {
|
||||
return common.CloneAppData("logs", oldAppName, newAppName)
|
||||
}
|
||||
|
||||
// TriggerPostCreate ensures apps the correct data directory structure
|
||||
// TriggerPostCreate ensures apps have the correct data directory structure
|
||||
func TriggerPostCreate(appName string) error {
|
||||
return common.CreateAppDataDirectory("logs", appName)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -43,12 +43,15 @@ func BuildConfig(appName string) error {
|
||||
}
|
||||
|
||||
appRoot := common.AppRoot(appName)
|
||||
s, err := common.PlugnTriggerOutput("ps-current-scale", []string{appName}...)
|
||||
results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "ps-current-scale",
|
||||
Args: []string{appName},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
scale, err := common.ParseScaleOutput(s)
|
||||
scale, err := common.ParseScaleOutput(results.StdoutBytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -78,7 +81,10 @@ func BuildConfig(appName string) error {
|
||||
ipAddress := GetContainerIpaddress(appName, processType, containerID)
|
||||
if ipAddress != "" {
|
||||
args := []string{appName, processType, containerIndexString, ipAddress}
|
||||
_, err := common.PlugnTriggerOutput("network-write-ipaddr", args...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "network-write-ipaddr",
|
||||
Args: args,
|
||||
})
|
||||
if err != nil {
|
||||
common.LogWarn(err.Error())
|
||||
}
|
||||
|
||||
@@ -40,7 +40,12 @@ func TriggerInstall() error {
|
||||
if common.PropertyExists("network", appName, "bind-all-interfaces") {
|
||||
continue
|
||||
}
|
||||
if err := common.PlugnTrigger("proxy-is-enabled", []string{appName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-is-enabled",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
common.LogVerboseQuiet("Setting network property 'bind-all-interfaces' to false")
|
||||
if err := common.PropertyWrite("network", appName, "bind-all-interfaces", "false"); err != nil {
|
||||
common.LogWarn(err.Error())
|
||||
|
||||
1
plugins/nginx-vhosts/.gitignore
vendored
1
plugins/nginx-vhosts/.gitignore
vendored
@@ -1 +1,2 @@
|
||||
/pagesize
|
||||
/nginx-property
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -33,13 +33,19 @@ func clearPorts(appName string) error {
|
||||
|
||||
// doesCertExist checks if a cert exists for an app
|
||||
func doesCertExist(appName string) bool {
|
||||
certsExists, _ := common.PlugnTriggerOutputAsString("certs-exists", []string{appName}...)
|
||||
if certsExists == "true" {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "certs-exists",
|
||||
Args: []string{appName},
|
||||
})
|
||||
if results.StdoutContents() == "true" {
|
||||
return true
|
||||
}
|
||||
|
||||
certsForce, _ := common.PlugnTriggerOutputAsString("certs-force", []string{appName}...)
|
||||
return certsForce == "true"
|
||||
results, _ = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "certs-force",
|
||||
Args: []string{appName},
|
||||
})
|
||||
return results.StdoutContents() == "true"
|
||||
}
|
||||
|
||||
// filterAppPortMaps filters the port mappings for an app
|
||||
@@ -156,8 +162,11 @@ func getDetectedPortMaps(appName string) []PortMap {
|
||||
// getGlobalProxyPort gets the global proxy port
|
||||
func getGlobalProxyPort() int {
|
||||
port := 0
|
||||
b, _ := common.PlugnTriggerOutput("config-get-global", []string{"DOKKU_PROXY_PORT"}...)
|
||||
if intVar, err := strconv.Atoi(strings.TrimSpace(string(b[:]))); err == nil {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get-global",
|
||||
Args: []string{"DOKKU_PROXY_PORT"},
|
||||
})
|
||||
if intVar, err := strconv.Atoi(results.StdoutContents()); err == nil {
|
||||
port = intVar
|
||||
}
|
||||
|
||||
@@ -167,8 +176,11 @@ func getGlobalProxyPort() int {
|
||||
// getGlobalProxySSLPort gets the global proxy ssl port
|
||||
func getGlobalProxySSLPort() int {
|
||||
port := 0
|
||||
b, _ := common.PlugnTriggerOutput("config-get-global", []string{"DOKKU_PROXY_SSL_PORT"}...)
|
||||
if intVar, err := strconv.Atoi(strings.TrimSpace(string(b[:]))); err == nil {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get-global",
|
||||
Args: []string{"DOKKU_PROXY_SSL_PORT"},
|
||||
})
|
||||
if intVar, err := strconv.Atoi(results.StdoutContents()); err == nil {
|
||||
port = intVar
|
||||
}
|
||||
|
||||
@@ -189,8 +201,11 @@ func getPortMaps(appName string) []PortMap {
|
||||
// getProxyPort gets the proxy port for an app
|
||||
func getProxyPort(appName string) int {
|
||||
port := 0
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_PROXY_PORT"}...)
|
||||
if intVar, err := strconv.Atoi(strings.TrimSpace(string(b[:]))); err == nil {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_PROXY_PORT"},
|
||||
})
|
||||
if intVar, err := strconv.Atoi(results.StdoutContents()); err == nil {
|
||||
port = intVar
|
||||
}
|
||||
|
||||
@@ -200,8 +215,11 @@ func getProxyPort(appName string) int {
|
||||
// getProxySSLPort gets the proxy ssl port for an app
|
||||
func getProxySSLPort(appName string) int {
|
||||
port := 0
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_PROXY_SSL_PORT"}...)
|
||||
if intVar, err := strconv.Atoi(strings.TrimSpace(string(b[:]))); err == nil {
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_PROXY_SSL_PORT"},
|
||||
})
|
||||
if intVar, err := strconv.Atoi(results.StdoutContents()); err == nil {
|
||||
port = intVar
|
||||
}
|
||||
|
||||
@@ -268,10 +286,12 @@ func inRange(value int, min int, max int) bool {
|
||||
|
||||
// isAppVhostEnabled checks if the app vhost is enabled
|
||||
func isAppVhostEnabled(appName string) bool {
|
||||
if err := common.PlugnTrigger("domains-vhost-enabled", []string{appName}...); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "domains-vhost-enabled",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// listAppPortMaps lists the port mappings for an app
|
||||
|
||||
@@ -11,8 +11,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -46,7 +46,12 @@ func CommandAdd(appName string, portMapStrings []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "add"}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-proxy-ports-update",
|
||||
Args: []string{appName, "add"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandClear clears all port mappings for an app
|
||||
@@ -59,7 +64,12 @@ func CommandClear(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "clear"}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-proxy-ports-update",
|
||||
Args: []string{appName, "clear"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandRemove removes specific port mappings from an app
|
||||
@@ -81,7 +91,12 @@ func CommandRemove(appName string, portMapStrings []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "remove"}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-proxy-ports-update",
|
||||
Args: []string{appName, "remove"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandSet sets port mappings for an app
|
||||
@@ -107,7 +122,12 @@ func CommandSet(appName string, portMapStrings []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("post-proxy-ports-update", []string{appName, "set"}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-proxy-ports-update",
|
||||
Args: []string{appName, "set"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandReport displays a ports report for one or more apps
|
||||
|
||||
@@ -10,8 +10,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -11,12 +11,22 @@ const RunInSerial = 0
|
||||
|
||||
// BuildConfig rebuilds the proxy config for the specified app
|
||||
func BuildConfig(appName string) error {
|
||||
return common.PlugnTrigger("proxy-build-config", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-build-config",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// ClearConfig clears the proxy config for the specified app
|
||||
func ClearConfig(appName string) error {
|
||||
return common.PlugnTrigger("proxy-clear-config", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-clear-config",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Disable disables proxy implementations for the specified app
|
||||
@@ -35,7 +45,12 @@ func Disable(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("proxy-disable", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-disable",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Enable enables proxy implementations for the specified app
|
||||
@@ -50,8 +65,12 @@ func Enable(appName string) error {
|
||||
if err := config.UnsetMany(appName, keys, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("proxy-enable", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-enable",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// IsAppProxyEnabled returns true if proxy is enabled; otherwise return false
|
||||
|
||||
@@ -69,15 +69,21 @@ func getRestartPolicy(appName string) (string, error) {
|
||||
|
||||
func getProcessCount(appName string) (int, error) {
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
b, _ := common.PlugnTriggerOutput("scheduler-app-status", []string{scheduler, appName}...)
|
||||
count := strings.Split(strings.TrimSpace(string(b[:])), " ")[0]
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-app-status",
|
||||
Args: []string{scheduler, appName},
|
||||
})
|
||||
count := strings.Split(results.StdoutContents(), " ")[0]
|
||||
return strconv.Atoi(count)
|
||||
}
|
||||
|
||||
func getRunningState(appName string) string {
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
b, _ := common.PlugnTriggerOutput("scheduler-app-status", []string{scheduler, appName}...)
|
||||
return strings.Split(strings.TrimSpace(string(b[:])), " ")[1]
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-app-status",
|
||||
Args: []string{scheduler, appName},
|
||||
})
|
||||
return strings.Split(results.StdoutContents(), " ")[1]
|
||||
}
|
||||
|
||||
func hasProcfile(appName string) bool {
|
||||
@@ -204,7 +210,12 @@ func getFormations(appName string) (FormationSlice, error) {
|
||||
}
|
||||
|
||||
func restorePrep() error {
|
||||
if err := common.PlugnTrigger("proxy-clear-config", []string{"--all"}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-clear-config",
|
||||
Args: []string{"--all"},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error clearing proxy config: %s", err)
|
||||
}
|
||||
|
||||
@@ -260,7 +271,12 @@ func scaleSet(appName string, skipDeploy bool, clearExisting bool, processTuples
|
||||
}
|
||||
|
||||
for _, formation := range formations {
|
||||
if err := common.PlugnTrigger("deploy", []string{appName, imageTag, formation.ProcessType}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "deploy",
|
||||
Args: []string{appName, imageTag, formation.ProcessType},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
100
plugins/ps/ps.go
100
plugins/ps/ps.go
@@ -2,7 +2,6 @@ package ps
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
@@ -69,7 +68,12 @@ func (d FormationSlice) Less(i, j int) bool {
|
||||
|
||||
// Rebuild rebuilds app from base image
|
||||
func Rebuild(appName string) error {
|
||||
return common.PlugnTrigger("receive-app", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "receive-app",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Restart restarts the app
|
||||
@@ -86,10 +90,20 @@ func Restart(appName string) error {
|
||||
|
||||
if imageTag == "" {
|
||||
common.LogWarn("No deployed-image-tag property saved, falling back to full release-and-deploy")
|
||||
return common.PlugnTrigger("release-and-deploy", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "release-and-deploy",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("deploy", []string{appName, imageTag}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "deploy",
|
||||
Args: []string{appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// RestartProcess restarts a process type within an app
|
||||
@@ -106,21 +120,41 @@ func RestartProcess(appName string, processName string) error {
|
||||
|
||||
if imageTag == "" {
|
||||
common.LogWarn("No deployed-image-tag property saved, falling back to full release-and-deploy")
|
||||
return common.PlugnTrigger("release-and-deploy", []string{appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "release-and-deploy",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
return common.PlugnTrigger("deploy", []string{appName, imageTag, processName}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "deploy",
|
||||
Args: []string{appName, imageTag, processName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Restore ensures an app that should be running is running on boot
|
||||
func Restore(appName string) error {
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
if err := common.PlugnTrigger("scheduler-pre-restore", []string{scheduler, appName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-pre-restore",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error running scheduler-pre-restore: %s", err)
|
||||
}
|
||||
|
||||
common.LogInfo1("Clearing potentially invalid proxy configuration")
|
||||
if err := common.PlugnTrigger("proxy-clear-config", []string{appName}...); err != nil {
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-clear-config",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
common.LogWarn(fmt.Sprintf("Error clearing proxy config: %s", err))
|
||||
}
|
||||
|
||||
@@ -129,8 +163,11 @@ func Restore(appName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_RESTORE"}...)
|
||||
restore := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_APP_RESTORE"},
|
||||
})
|
||||
restore := results.StdoutContents()
|
||||
if restore == "0" {
|
||||
common.LogWarn(fmt.Sprintf("Skipping ps:restore for %s as DOKKU_APP_RESTORE=%s", appName, restore))
|
||||
return nil
|
||||
@@ -149,7 +186,12 @@ func Start(appName string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("pre-start", []string{appName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "pre-start",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failure in pre-start hook: %s", err)
|
||||
}
|
||||
|
||||
@@ -162,18 +204,24 @@ func Start(appName string) error {
|
||||
}
|
||||
|
||||
if runningState != "true" {
|
||||
if err := common.PlugnTrigger("release-and-deploy", []string{appName, imageTag}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "release-and-deploy",
|
||||
Args: []string{appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
common.LogWarn(fmt.Sprintf("App %s already running", appName))
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("proxy-build-config", []string{appName}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "proxy-build-config",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// Stop stops the app
|
||||
@@ -186,13 +234,19 @@ func Stop(appName string) error {
|
||||
common.LogInfo1Quiet(fmt.Sprintf("Stopping %s", appName))
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
|
||||
if err := common.PlugnTrigger("scheduler-stop", []string{scheduler, appName}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-stop",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := common.PlugnTrigger("post-stop", []string{appName}...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "post-stop",
|
||||
Args: []string{appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -129,8 +129,11 @@ func reportRestartPolicy(appName string) string {
|
||||
}
|
||||
|
||||
func reportRestore(appName string) string {
|
||||
b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_RESTORE"}...)
|
||||
restore := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "config-get",
|
||||
Args: []string{appName, "DOKKU_APP_RESTORE"},
|
||||
})
|
||||
restore := results.StdoutContents()
|
||||
if restore == "0" {
|
||||
restore = "false"
|
||||
} else {
|
||||
|
||||
@@ -18,7 +18,12 @@ func CommandInspect(appName string) error {
|
||||
}
|
||||
|
||||
scheduler := common.GetAppScheduler(appName)
|
||||
return common.PlugnTrigger("scheduler-inspect", []string{scheduler, appName}...)
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-inspect",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandRebuild rebuilds an app from source
|
||||
@@ -74,7 +79,11 @@ func CommandRestart(appName string, processName string, allApps bool, parallelCo
|
||||
|
||||
// CommandRestore starts previously running apps e.g. after reboot
|
||||
func CommandRestore(appName string, allApps bool, parallelCount int) error {
|
||||
if err := common.PlugnTrigger("pre-restore", []string{}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "pre-restore",
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error running pre-restore: %s", err)
|
||||
}
|
||||
|
||||
@@ -124,7 +133,12 @@ func CommandRetire(appName string) error {
|
||||
}
|
||||
|
||||
common.LogInfo1("Retiring old containers and images")
|
||||
return common.PlugnTrigger("scheduler-retire", []string{scheduler, appName}...)
|
||||
_, err = common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "scheduler-retire",
|
||||
Args: []string{scheduler, appName},
|
||||
StreamStdio: true,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// CommandScale gets or sets how many instances of a given process to run
|
||||
|
||||
@@ -72,8 +72,11 @@ func TriggerCorePostExtract(appName string, sourceWorkDir string) error {
|
||||
}
|
||||
|
||||
processSpecificProcfile := fmt.Sprintf("%s.%s", existingProcfile, os.Getenv("DOKKU_PID"))
|
||||
b, _ := common.PlugnTriggerOutput("git-get-property", []string{appName, "source-image"}...)
|
||||
appSourceImage := strings.TrimSpace(string(b[:]))
|
||||
results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "git-get-property",
|
||||
Args: []string{appName, "source-image"},
|
||||
})
|
||||
appSourceImage := results.StdoutContents()
|
||||
|
||||
repoDefaultProcfilePath := path.Join(sourceWorkDir, "Procfile")
|
||||
if appSourceImage == "" {
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -90,7 +90,12 @@ func TriggerPostDelete(appName string) error {
|
||||
func TriggerPostReleaseBuilder(appName string, image string) error {
|
||||
parts := strings.Split(image, ":")
|
||||
imageTag := parts[len(parts)-1]
|
||||
if err := common.PlugnTrigger("pre-deploy", []string{appName, imageTag}...); err != nil {
|
||||
_, err := common.CallPlugnTrigger(common.PlugnTriggerInput{
|
||||
Trigger: "pre-deploy",
|
||||
Args: []string{appName, imageTag},
|
||||
StreamStdio: true,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
@@ -9,8 +9,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 // indirect
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
github.com/alexellis/go-execute/v2 v2.2.1 h1:4Ye3jiCKQarstODOEmqDSRCqxMHLkC92Bhse743RdOI=
|
||||
github.com/alexellis/go-execute/v2 v2.2.1/go.mod h1:FMdRnUTiFAmYXcv23txrp3VYZfLo24nMpiIneWgKHTQ=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user