diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 17a2c71ff1f..9119826ab38 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -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` diff --git a/Makefile b/Makefile index 06cac420a45..9b177269bbd 100644 --- a/Makefile +++ b/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 diff --git a/contrib/dokku_client.sh b/contrib/dokku_client.sh index 590d3d0dc8c..d2c7c4f047a 100755 --- a/contrib/dokku_client.sh +++ b/contrib/dokku_client.sh @@ -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 diff --git a/docs/_build/requirements.txt b/docs/_build/requirements.txt index df25e547d41..ca779377d53 100644 --- a/docs/_build/requirements.txt +++ b/docs/_build/requirements.txt @@ -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 diff --git a/docs/appendices/0.34.0-migration-guide.md b/docs/appendices/0.34.0-migration-guide.md new file mode 100644 index 00000000000..43461200f3d --- /dev/null +++ b/docs/appendices/0.34.0-migration-guide.md @@ -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 + ``` diff --git a/docs/deployment/methods/git.md b/docs/deployment/methods/git.md index 9126a3d627d..eb46b32610d 100644 --- a/docs/deployment/methods/git.md +++ b/docs/deployment/methods/git.md @@ -10,13 +10,12 @@ git:from-archive [--archive-type ARCHIVE_TYPE] [ [ ] # 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] [ ] # Updates an app's git repository with a docker image loaded from stdin -git:sync [--build] [] # Clone or fetch an app from remote git repo +git:sync [--build|build-if-changes] [] # Clone or fetch an app from remote git repo git:initialize # Initialize a git repository for an app git:public-key # Outputs the dokku public deploy key git:report [] [] # Displays a git report for one or more apps git:set () # Set or clear a git property for an app git:status # Show the working tree status for an app -git:unlock [--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] diff --git a/docs/deployment/schedulers/docker-local.md b/docs/deployment/schedulers/docker-local.md index a5f78d27957..869f937ad08 100644 --- a/docs/deployment/schedulers/docker-local.md +++ b/docs/deployment/schedulers/docker-local.md @@ -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: diff --git a/docs/deployment/schedulers/k3s.md b/docs/deployment/schedulers/k3s.md index e24a3b4db83..c357332ea6c 100644 --- a/docs/deployment/schedulers/k3s.md +++ b/docs/deployment/schedulers/k3s.md @@ -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 diff --git a/docs/getting-started/upgrading/index.md b/docs/getting-started/upgrading/index.md index a8bad588a5e..ce2b6a60cd7 100644 --- a/docs/getting-started/upgrading/index.md +++ b/docs/getting-started/upgrading/index.md @@ -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) diff --git a/docs/networking/proxies/traefik.md b/docs/networking/proxies/traefik.md index bf89e9398db..8657f3054d4 100644 --- a/docs/networking/proxies/traefik.md +++ b/docs/networking/proxies/traefik.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. diff --git a/docs/networking/proxy-management.md b/docs/networking/proxy-management.md index 470b525ec27..6b1ec7f5543 100644 --- a/docs/networking/proxy-management.md +++ b/docs/networking/proxy-management.md @@ -12,7 +12,7 @@ proxy:report [] [] # Displays a proxy report fo proxy:set [|--global] # 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 diff --git a/dokku b/dokku index 46f8d6f9297..862efa6905c 100755 --- a/dokku +++ b/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 diff --git a/plugins/00_dokku-standard/subcommands/report b/plugins/00_dokku-standard/subcommands/report index 791772fa9b4..d9ead2b2996 100755 --- a/plugins/00_dokku-standard/subcommands/report +++ b/plugins/00_dokku-standard/subcommands/report @@ -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: " diff --git a/plugins/20_events/install b/plugins/20_events/install index 9a352e198a9..ffebb1977af 100755 --- a/plugins/20_events/install +++ b/plugins/20_events/install @@ -56,16 +56,12 @@ EOF cat >"$DOKKU_LOGROTATE_FILE" </dev/null || true - endscript - create 664 syslog dokku + notifempty + copytruncate } EOF diff --git a/plugins/app-json/functions.go b/plugins/app-json/functions.go index fe24ca885b3..99527666d2c 100644 --- a/plugins/app-json/functions.go +++ b/plugins/app-json/functions.go @@ -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"}...) + _, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "ps-can-scale", + Args: []string{appName, "true"}, + StreamStdio: true, + }) + return err } - if err := common.PlugnTrigger("ps-can-scale", []string{appName, "false"}...); err != nil { + _, err = common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "ps-can-scale", + Args: []string{appName, "false"}, + StreamStdio: true, + }) + if err != nil { return err } - return common.PlugnTrigger("ps-set-scale", args...) + _, err = common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "ps-set-scale", + Args: args, + StreamStdio: true, + }) + return err } diff --git a/plugins/app-json/go.mod b/plugins/app-json/go.mod index 8ffa9aa50ce..da0eeb9ba6c 100644 --- a/plugins/app-json/go.mod +++ b/plugins/app-json/go.mod @@ -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 diff --git a/plugins/app-json/go.sum b/plugins/app-json/go.sum index 6131c142454..bc9e3044033 100644 --- a/plugins/app-json/go.sum +++ b/plugins/app-json/go.sum @@ -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= diff --git a/plugins/app-json/triggers.go b/plugins/app-json/triggers.go index 230e423c1b5..b556c0d49ff 100644 --- a/plugins/app-json/triggers.go +++ b/plugins/app-json/triggers.go @@ -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[:])) - - b, _ = common.PlugnTriggerOutput("builder-get-property", []string{appName, "build-dir"}...) - buildDir := strings.TrimSpace(string(b[:])) + results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "git-get-property", + Args: []string{appName, "source-image"}, + }) + appSourceImage := results.StdoutContents() + + 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) } diff --git a/plugins/apps/Makefile b/plugins/apps/Makefile index 8a92e94b9e7..7bf928361ce 100644 --- a/plugins/apps/Makefile +++ b/plugins/apps/Makefile @@ -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 diff --git a/plugins/apps/functions.go b/plugins/apps/functions.go index 60cfb6e4ce8..96a3e04f034 100644 --- a/plugins/apps/functions.go +++ b/plugins/apps/functions.go @@ -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) diff --git a/plugins/apps/go.mod b/plugins/apps/go.mod index f9c13adab49..a7453d6cf23 100644 --- a/plugins/apps/go.mod +++ b/plugins/apps/go.mod @@ -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 diff --git a/plugins/apps/go.sum b/plugins/apps/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/apps/go.sum +++ b/plugins/apps/go.sum @@ -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= diff --git a/plugins/apps/src/triggers/triggers.go b/plugins/apps/src/triggers/triggers.go index e79febbed5f..191ba79c3ca 100644 --- a/plugins/apps/src/triggers/triggers.go +++ b/plugins/apps/src/triggers/triggers.go @@ -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) diff --git a/plugins/apps/subcommands.go b/plugins/apps/subcommands.go index d8eef9ba271..56e6f7cc450 100644 --- a/plugins/apps/subcommands.go +++ b/plugins/apps/subcommands.go @@ -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.") diff --git a/plugins/apps/triggers.go b/plugins/apps/triggers.go index 9a82d93637a..ad16adb10c0 100644 --- a/plugins/apps/triggers.go +++ b/plugins/apps/triggers.go @@ -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) +} + +// TriggerPostCreate ensures apps have the correct data directory structure +func TriggerPostCreate(appName string) error { + return common.CreateAppDataDirectory("apps", appName) } -// TriggerPostDelete is the apps post-delete plugin trigger +// 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 } diff --git a/plugins/builder-herokuish/builder-release b/plugins/builder-herokuish/builder-release index 2522f7c556e..e8b845d3d49 100755 --- a/plugins/builder-herokuish/builder-release +++ b/plugins/builder-herokuish/builder-release @@ -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 diff --git a/plugins/builder-herokuish/dockerfiles/builder-release.Dockerfile b/plugins/builder-herokuish/dockerfiles/builder-release.Dockerfile index 9f88539df04..b6a59e63181 100644 --- a/plugins/builder-herokuish/dockerfiles/builder-release.Dockerfile +++ b/plugins/builder-herokuish/dockerfiles/builder-release.Dockerfile @@ -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 diff --git a/plugins/builder-herokuish/dockerfiles/copy-source.Dockerfile b/plugins/builder-herokuish/dockerfiles/copy-source.Dockerfile index 4769e35c60f..0bb8e9aaee7 100644 --- a/plugins/builder-herokuish/dockerfiles/copy-source.Dockerfile +++ b/plugins/builder-herokuish/dockerfiles/copy-source.Dockerfile @@ -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 \ No newline at end of file +WORKDIR /app +ENV HEROKUISH_DISABLE_CHOWN true diff --git a/plugins/builder-herokuish/dockerfiles/pre-build.Dockerfile b/plugins/builder-herokuish/dockerfiles/pre-build.Dockerfile index 943c4c1e905..a2ab687eebf 100644 --- a/plugins/builder-herokuish/dockerfiles/pre-build.Dockerfile +++ b/plugins/builder-herokuish/dockerfiles/pre-build.Dockerfile @@ -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 diff --git a/plugins/builder-herokuish/post-app-clone-setup b/plugins/builder-herokuish/post-app-clone-setup deleted file mode 100755 index 3abb1541799..00000000000 --- a/plugins/builder-herokuish/post-app-clone-setup +++ /dev/null @@ -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 "$@" diff --git a/plugins/builder-herokuish/post-app-rename-setup b/plugins/builder-herokuish/post-app-rename-setup deleted file mode 100755 index 26c5a6dbb00..00000000000 --- a/plugins/builder-herokuish/post-app-rename-setup +++ /dev/null @@ -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 "$@" diff --git a/plugins/builder/go.mod b/plugins/builder/go.mod index 66c63df6421..59d3bec3bba 100644 --- a/plugins/builder/go.mod +++ b/plugins/builder/go.mod @@ -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 diff --git a/plugins/builder/go.sum b/plugins/builder/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/builder/go.sum +++ b/plugins/builder/go.sum @@ -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= diff --git a/plugins/buildpacks/functions.go b/plugins/buildpacks/functions.go index 04f933b3d0e..f3545233e84 100644 --- a/plugins/buildpacks/functions.go +++ b/plugins/buildpacks/functions.go @@ -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-]+)$`) diff --git a/plugins/buildpacks/go.mod b/plugins/buildpacks/go.mod index cf1b1530d21..779a4a1caf4 100644 --- a/plugins/buildpacks/go.mod +++ b/plugins/buildpacks/go.mod @@ -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 diff --git a/plugins/buildpacks/go.sum b/plugins/buildpacks/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/buildpacks/go.sum +++ b/plugins/buildpacks/go.sum @@ -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= diff --git a/plugins/buildpacks/report.go b/plugins/buildpacks/report.go index 68b95aa0110..cec28af2a5c 100644 --- a/plugins/buildpacks/report.go +++ b/plugins/buildpacks/report.go @@ -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 } diff --git a/plugins/buildpacks/subcommands.go b/plugins/buildpacks/subcommands.go index 9a49ffabc98..24d3125eff9 100644 --- a/plugins/buildpacks/subcommands.go +++ b/plugins/buildpacks/subcommands.go @@ -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 } } diff --git a/plugins/buildpacks/triggers.go b/plugins/buildpacks/triggers.go index 187a0f8e156..37f1c33d755 100644 --- a/plugins/buildpacks/triggers.go +++ b/plugins/buildpacks/triggers.go @@ -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) diff --git a/plugins/common/common.go b/plugins/common/common.go index e0ffb613ea7..23e96c0f8d9 100644 --- a/plugins/common/common.go +++ b/plugins/common/common.go @@ -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" } diff --git a/plugins/common/docker.go b/plugins/common/docker.go index 3ee17915f89..e99fca6803b 100644 --- a/plugins/common/docker.go +++ b/plugins/common/docker.go @@ -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() } } diff --git a/plugins/common/exec.go b/plugins/common/exec.go index 84eaa895410..c8471cc6fb0 100644 --- a/plugins/common/exec.go +++ b/plugins/common/exec.go @@ -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() diff --git a/plugins/common/functions b/plugins/common/functions index c295ecdf126..358f8af2345 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -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 } diff --git a/plugins/common/functions.go b/plugins/common/functions.go index 185ddd9f5da..0ae83bb9e97 100644 --- a/plugins/common/functions.go +++ b/plugins/common/functions.go @@ -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 { diff --git a/plugins/common/go.mod b/plugins/common/go.mod index 9d229cd932b..5cb66aab973 100644 --- a/plugins/common/go.mod +++ b/plugins/common/go.mod @@ -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 diff --git a/plugins/common/go.sum b/plugins/common/go.sum index ea3cd3d8199..50c6f3e183f 100644 --- a/plugins/common/go.sum +++ b/plugins/common/go.sum @@ -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= diff --git a/plugins/common/subprocess.go b/plugins/common/subprocess.go index 8a6187fb96a..d47f320e32f 100644 --- a/plugins/common/subprocess.go +++ b/plugins/common/subprocess.go @@ -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") diff --git a/plugins/config/.gitignore b/plugins/config/.gitignore index b79352e779e..3b7e2f512c3 100644 --- a/plugins/config/.gitignore +++ b/plugins/config/.gitignore @@ -4,3 +4,4 @@ /triggers /config-* /config_sub +/post-* diff --git a/plugins/config/Makefile b/plugins/config/Makefile index e38a8f62de1..86ffcb36bbb 100644 --- a/plugins/config/Makefile +++ b/plugins/config/Makefile @@ -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 diff --git a/plugins/config/config.go b/plugins/config/config.go index 3bfbf59d6da..90f04039dae 100644 --- a/plugins/config/config.go +++ b/plugins/config/config.go @@ -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)) } } diff --git a/plugins/config/environment.go b/plugins/config/environment.go index 2f6ddf071f2..877939e5f74 100644 --- a/plugins/config/environment.go +++ b/plugins/config/environment.go @@ -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("", 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 diff --git a/plugins/config/go.mod b/plugins/config/go.mod index f024bb7eb75..ebafb46959a 100644 --- a/plugins/config/go.mod +++ b/plugins/config/go.mod @@ -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 diff --git a/plugins/config/go.sum b/plugins/config/go.sum index 76515bbb1c2..60dc76b24d1 100644 --- a/plugins/config/go.sum +++ b/plugins/config/go.sum @@ -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= diff --git a/plugins/config/src/triggers/triggers.go b/plugins/config/src/triggers/triggers.go index eec123a4877..1f8f58732f0 100644 --- a/plugins/config/src/triggers/triggers.go +++ b/plugins/config/src/triggers/triggers.go @@ -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) } diff --git a/plugins/config/triggers.go b/plugins/config/triggers.go index 3014f6d26c9..af96d114ca9 100644 --- a/plugins/config/triggers.go +++ b/plugins/config/triggers.go @@ -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 +} diff --git a/plugins/cron/go.mod b/plugins/cron/go.mod index 7fab44cd3aa..37acb73baa5 100644 --- a/plugins/cron/go.mod +++ b/plugins/cron/go.mod @@ -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 diff --git a/plugins/cron/go.sum b/plugins/cron/go.sum index 3dad9238068..1d1317b5fdc 100644 --- a/plugins/cron/go.sum +++ b/plugins/cron/go.sum @@ -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= diff --git a/plugins/cron/src/triggers/triggers.go b/plugins/cron/src/triggers/triggers.go index 063d35425b7..083cbb25bea 100644 --- a/plugins/cron/src/triggers/triggers.go +++ b/plugins/cron/src/triggers/triggers.go @@ -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() diff --git a/plugins/cron/subcommands.go b/plugins/cron/subcommands.go index 4a85a01e352..981f1deab99 100644 --- a/plugins/cron/subcommands.go +++ b/plugins/cron/subcommands.go @@ -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 } diff --git a/plugins/docker-options/go.mod b/plugins/docker-options/go.mod index 6bd85a92316..7b3e4273582 100644 --- a/plugins/docker-options/go.mod +++ b/plugins/docker-options/go.mod @@ -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 diff --git a/plugins/docker-options/go.sum b/plugins/docker-options/go.sum index d37bea4456c..6b2aed785da 100644 --- a/plugins/docker-options/go.sum +++ b/plugins/docker-options/go.sum @@ -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= diff --git a/plugins/docker-options/post-app-clone-setup b/plugins/docker-options/post-app-clone-setup new file mode 100755 index 00000000000..9b36b329d66 --- /dev/null +++ b/plugins/docker-options/post-app-clone-setup @@ -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 "$@" diff --git a/plugins/docker-options/post-app-rename-setup b/plugins/docker-options/post-app-rename-setup new file mode 100755 index 00000000000..0688252a692 --- /dev/null +++ b/plugins/docker-options/post-app-rename-setup @@ -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 "$@" diff --git a/plugins/domains/post-app-rename-setup b/plugins/domains/post-app-rename-setup index 7cbce6a119d..3ec256a9c99 100755 --- a/plugins/domains/post-app-rename-setup +++ b/plugins/domains/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 } diff --git a/plugins/git/git-from-directory b/plugins/git/git-from-directory index 03e7058de00..771a7bba9a0 100755 --- a/plugins/git/git-from-directory +++ b/plugins/git/git-from-directory @@ -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" diff --git a/plugins/git/help-functions b/plugins/git/help-functions index 49b34ad4107..c0fd67da876 100755 --- a/plugins/git/help-functions +++ b/plugins/git/help-functions @@ -38,7 +38,6 @@ fn-help-content() { git:public-key, Outputs the dokku public deploy key git:report [] [], Displays a git report for one or more apps git:set (), Set or clear a git property for an app - git:unlock [--force], Removes previous git clone folder for new deployment git:status , show the working tree status for an app help_content } diff --git a/plugins/git/internal-functions b/plugins/git/internal-functions index a38a41f5318..f5fb3850739 100755 --- a/plugins/git/internal-functions +++ b/plugins/git/internal-functions @@ -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 diff --git a/plugins/git/post-delete b/plugins/git/post-delete index dad74439adc..490782dd8fc 100755 --- a/plugins/git/post-delete +++ b/plugins/git/post-delete @@ -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 "$@" diff --git a/plugins/logs/go.mod b/plugins/logs/go.mod index 2b7a13f1c46..f0cee1bf470 100644 --- a/plugins/logs/go.mod +++ b/plugins/logs/go.mod @@ -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 diff --git a/plugins/logs/go.sum b/plugins/logs/go.sum index 418e80d538c..de72fbf95c3 100644 --- a/plugins/logs/go.sum +++ b/plugins/logs/go.sum @@ -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= diff --git a/plugins/logs/logs.go b/plugins/logs/logs.go index d0122957e39..6d24d8755cd 100644 --- a/plugins/logs/logs.go +++ b/plugins/logs/logs.go @@ -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 } diff --git a/plugins/logs/triggers.go b/plugins/logs/triggers.go index c0d35ea8a94..87962efb3a3 100644 --- a/plugins/logs/triggers.go +++ b/plugins/logs/triggers.go @@ -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) } diff --git a/plugins/network/go.mod b/plugins/network/go.mod index 6c4f630e55b..438ca7390dd 100644 --- a/plugins/network/go.mod +++ b/plugins/network/go.mod @@ -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 diff --git a/plugins/network/go.sum b/plugins/network/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/network/go.sum +++ b/plugins/network/go.sum @@ -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= diff --git a/plugins/network/network.go b/plugins/network/network.go index f8bf2d1dcb5..4c0254e6121 100644 --- a/plugins/network/network.go +++ b/plugins/network/network.go @@ -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()) } diff --git a/plugins/network/triggers.go b/plugins/network/triggers.go index 3f5bd99ffdf..6ad20bd0cbb 100644 --- a/plugins/network/triggers.go +++ b/plugins/network/triggers.go @@ -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()) diff --git a/plugins/nginx-vhosts/.gitignore b/plugins/nginx-vhosts/.gitignore index f0565e7afa4..ee69b93399e 100644 --- a/plugins/nginx-vhosts/.gitignore +++ b/plugins/nginx-vhosts/.gitignore @@ -1 +1,2 @@ /pagesize +/nginx-property diff --git a/plugins/nginx-vhosts/go.mod b/plugins/nginx-vhosts/go.mod index a72c65d5a2d..0db3520734f 100644 --- a/plugins/nginx-vhosts/go.mod +++ b/plugins/nginx-vhosts/go.mod @@ -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 diff --git a/plugins/nginx-vhosts/go.sum b/plugins/nginx-vhosts/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/nginx-vhosts/go.sum +++ b/plugins/nginx-vhosts/go.sum @@ -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= diff --git a/plugins/ports/functions.go b/plugins/ports/functions.go index 938cba1dee5..29ca80b0d25 100644 --- a/plugins/ports/functions.go +++ b/plugins/ports/functions.go @@ -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 diff --git a/plugins/ports/go.mod b/plugins/ports/go.mod index 6e5b795d065..6d7895562a3 100644 --- a/plugins/ports/go.mod +++ b/plugins/ports/go.mod @@ -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 diff --git a/plugins/ports/go.sum b/plugins/ports/go.sum index a2e5d436bbf..bf77a3bf13e 100644 --- a/plugins/ports/go.sum +++ b/plugins/ports/go.sum @@ -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= diff --git a/plugins/ports/subcommands.go b/plugins/ports/subcommands.go index 51f9564f8f4..6f4f3793f7f 100644 --- a/plugins/ports/subcommands.go +++ b/plugins/ports/subcommands.go @@ -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 diff --git a/plugins/proxy/go.mod b/plugins/proxy/go.mod index e44834cba23..3a6fdbf108a 100644 --- a/plugins/proxy/go.mod +++ b/plugins/proxy/go.mod @@ -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 diff --git a/plugins/proxy/go.sum b/plugins/proxy/go.sum index a2e5d436bbf..bf77a3bf13e 100644 --- a/plugins/proxy/go.sum +++ b/plugins/proxy/go.sum @@ -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= diff --git a/plugins/proxy/proxy.go b/plugins/proxy/proxy.go index 26cfee2ffb4..57a7bfba692 100644 --- a/plugins/proxy/proxy.go +++ b/plugins/proxy/proxy.go @@ -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 diff --git a/plugins/ps/functions.go b/plugins/ps/functions.go index c77475c0f77..3bb7f123515 100644 --- a/plugins/ps/functions.go +++ b/plugins/ps/functions.go @@ -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 } } diff --git a/plugins/ps/go.mod b/plugins/ps/go.mod index 3105295f4af..3ee49a0d815 100644 --- a/plugins/ps/go.mod +++ b/plugins/ps/go.mod @@ -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 diff --git a/plugins/ps/go.sum b/plugins/ps/go.sum index 5a4997fa4cf..3d4afc51399 100644 --- a/plugins/ps/go.sum +++ b/plugins/ps/go.sum @@ -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= diff --git a/plugins/ps/ps.go b/plugins/ps/ps.go index 75e6f3c931a..7e1e2f4d9d4 100644 --- a/plugins/ps/ps.go +++ b/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 { - return err - } - - if err := common.PlugnTrigger("post-stop", []string{appName}...); err != nil { + _, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "scheduler-stop", + Args: []string{scheduler, appName}, + StreamStdio: true, + }) + if err != nil { return err } - return nil + _, err = common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "post-stop", + Args: []string{appName}, + StreamStdio: true, + }) + return err } diff --git a/plugins/ps/report.go b/plugins/ps/report.go index af78b7263d5..5e0ddfe4088 100644 --- a/plugins/ps/report.go +++ b/plugins/ps/report.go @@ -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 { diff --git a/plugins/ps/subcommands.go b/plugins/ps/subcommands.go index f818d81409b..2d530240374 100644 --- a/plugins/ps/subcommands.go +++ b/plugins/ps/subcommands.go @@ -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 diff --git a/plugins/ps/triggers.go b/plugins/ps/triggers.go index c91b6c67f5c..c21e68a892b 100644 --- a/plugins/ps/triggers.go +++ b/plugins/ps/triggers.go @@ -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 == "" { diff --git a/plugins/registry/go.mod b/plugins/registry/go.mod index b67077c8c88..75c6adcc226 100644 --- a/plugins/registry/go.mod +++ b/plugins/registry/go.mod @@ -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 diff --git a/plugins/registry/go.sum b/plugins/registry/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/registry/go.sum +++ b/plugins/registry/go.sum @@ -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= diff --git a/plugins/registry/triggers.go b/plugins/registry/triggers.go index fa8cb5f0783..5579a8b7473 100644 --- a/plugins/registry/triggers.go +++ b/plugins/registry/triggers.go @@ -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 } diff --git a/plugins/repo/go.mod b/plugins/repo/go.mod index 48194e2becb..791f1e8264e 100644 --- a/plugins/repo/go.mod +++ b/plugins/repo/go.mod @@ -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 diff --git a/plugins/repo/go.sum b/plugins/repo/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/repo/go.sum +++ b/plugins/repo/go.sum @@ -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= diff --git a/plugins/resource/go.mod b/plugins/resource/go.mod index 1fb2ef53f66..3a192676615 100644 --- a/plugins/resource/go.mod +++ b/plugins/resource/go.mod @@ -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 diff --git a/plugins/resource/go.sum b/plugins/resource/go.sum index 82ead0675ea..d1dda89b5c7 100644 --- a/plugins/resource/go.sum +++ b/plugins/resource/go.sum @@ -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= diff --git a/plugins/scheduler-docker-local/bin/scheduler-deploy-process b/plugins/scheduler-docker-local/bin/scheduler-deploy-process index fce53481b0f..b84ef78273a 100755 --- a/plugins/scheduler-docker-local/bin/scheduler-deploy-process +++ b/plugins/scheduler-docker-local/bin/scheduler-deploy-process @@ -47,6 +47,33 @@ fn-scheduler-deploy-process() { fi fi + local DOCKER_ARGS + DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG" "$PROC_TYPE") + DOCKER_ARGS+=$(: | plugn trigger docker-args-process-deploy "$APP" "$IMAGE_SOURCE_TYPE" "$IMAGE_TAG" "$PROC_TYPE") + DOCKER_ARGS=" $DOCKER_ARGS " + declare -a ARG_ARRAY + eval "ARG_ARRAY=($DOCKER_ARGS)" + + local port_published=false + for arg in "${ARG_ARRAY[@]}"; do + if [[ "$arg" == "-p "* ]] || [[ "$arg" =~ "--publish "* ]] || [[ "$arg" == "-P" ]] || [[ "$arg" =~ "--publish-all"* ]]; then + port_published=true + break + fi + done + + if [[ "$port_published" == "true" ]]; then + local warned_on_publish=false + if [[ "$PROC_COUNT" -gt 1 ]]; then + warned_on_publish=true + dokku_log_warn "Deploys may fail when publishing ports and scaling to multiple containers. Consider scaling process type $PROC_TYPE to 1." + fi + if [[ "$DOKKU_CHECKS_DISABLED" != "true" ]] && [[ "$warned_on_publish" == "false" ]]; then + warned_on_publish=true + dokku_log_warn "Deploys may fail when publishing ports and enabling zero downtime. Consider disabling zero downtime for process type $PROC_TYPE." + fi + fi + PARALLEL_DEPLOY_COUNT="$(plugn trigger "app-json-process-deploy-parallelism" "$APP" "$PROC_TYPE")" DOKKU_CHECKS_DISABLED="$DOKKU_CHECKS_DISABLED" INJECT_INIT_FLAG="$INJECT_INIT_FLAG" parallel --will-cite --halt soon,fail=1 --jobs "$PARALLEL_DEPLOY_COUNT" --ungroup <"$PROCESS_TMP_FILE" diff --git a/plugins/scheduler-docker-local/functions.go b/plugins/scheduler-docker-local/functions.go index 9b9da83a39f..c9ade0be710 100644 --- a/plugins/scheduler-docker-local/functions.go +++ b/plugins/scheduler-docker-local/functions.go @@ -65,8 +65,11 @@ func generateCronEntries() ([]cron.TemplateCommand, error) { g.Go(func() error { commands := []cron.TemplateCommand{} - b, _ := common.PlugnTriggerOutput("cron-entries", "docker-local") - for _, line := range strings.Split(strings.TrimSpace(string(b[:])), "\n") { + response, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "cron-entries", + Args: []string{"docker-local"}, + }) + for _, line := range strings.Split(response.StdoutContents(), "\n") { if strings.TrimSpace(line) == "" { results <- []cron.TemplateCommand{} return nil @@ -121,7 +124,11 @@ func writeCronEntries() error { return deleteCrontab() } - mailto, _ := common.PlugnTriggerOutputAsString("cron-get-property", []string{"--global", "mailto"}...) + results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "cron-get-property", + Args: []string{"--global", "mailto"}, + }) + mailto := results.StdoutContents() data := map[string]interface{}{ "Commands": commands, diff --git a/plugins/scheduler-docker-local/go.mod b/plugins/scheduler-docker-local/go.mod index db86c77b17e..236d6dbb1a2 100644 --- a/plugins/scheduler-docker-local/go.mod +++ b/plugins/scheduler-docker-local/go.mod @@ -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/dokku/dokku/plugins/app-json v0.0.0-00010101000000-000000000000 // indirect github.com/fatih/color v1.16.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect diff --git a/plugins/scheduler-docker-local/go.sum b/plugins/scheduler-docker-local/go.sum index c231b010986..775646bc7ca 100644 --- a/plugins/scheduler-docker-local/go.sum +++ b/plugins/scheduler-docker-local/go.sum @@ -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= diff --git a/plugins/scheduler-docker-local/internal-functions b/plugins/scheduler-docker-local/internal-functions index 33f16100e9b..ebce46b95bb 100755 --- a/plugins/scheduler-docker-local/internal-functions +++ b/plugins/scheduler-docker-local/internal-functions @@ -36,7 +36,6 @@ cmd-scheduler-docker-local-report-single() { fi verify_app_name "$APP" local flag_map=( - "--scheduler-docker-local-disable-chown: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "disable-chown" "")" "--scheduler-docker-local-init-process: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "init-process" "true")" "--scheduler-docker-local-parallel-schedule-count: $(fn-plugin-property-get "scheduler-docker-local" "$APP" "parallel-schedule-count" "")" ) diff --git a/plugins/scheduler-docker-local/pre-deploy b/plugins/scheduler-docker-local/pre-deploy index 65bff7a5bca..04abd3d9205 100755 --- a/plugins/scheduler-docker-local/pre-deploy +++ b/plugins/scheduler-docker-local/pre-deploy @@ -16,52 +16,9 @@ trigger-scheduler-docker-local-pre-deploy() { return fi - scheduler-docker-local-pre-deploy-chown-app "$APP" "$IMAGE_TAG" scheduler-docker-local-pre-deploy-precheck "$APP" } -scheduler-docker-local-pre-deploy-chown-app() { - declare desc="Runs chown against the /app directory for herokuish images" - declare APP="$1" IMAGE_TAG="$2" - local DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP" - local IMAGE DISABLE_CHOWN DOCKER_ARGS DOKKU_APP_TYPE DOKKU_APP_USER APP_PATHS CONTAINER_PATHS - declare -a ARG_ARRAY - - IMAGE=$(get_app_image_name "$APP" "$IMAGE_TAG") - - DOKKU_APP_TYPE=$(config_get "$APP" DOKKU_APP_TYPE || true) - DOKKU_APP_USER=$(config_get "$APP" DOKKU_APP_USER || true) - DOKKU_APP_USER=${DOKKU_APP_USER:="herokuishuser"} - APP_PATHS=$(plugn trigger storage-list "$APP" "deploy") - - if [[ -n "$APP_PATHS" ]]; then - CONTAINER_PATHS=$(echo "$APP_PATHS" | awk -F ':' '{ print $2 }' | xargs) - DOCKER_ARGS=$(: | plugn trigger docker-args-deploy "$APP" "$IMAGE_TAG") - - filterdArgs=("--cpus" "--gpus" "--memory" "--memory-reservation" "--memory-swap" "--publish" "--publish-all" "-p" "-P" "--restart") - for filteredArg in "${filterdArgs[@]}"; do - # shellcheck disable=SC2001 - DOCKER_ARGS=$(sed -e "s/$filteredArg=[[:graph:]]\+[[:blank:]]\?//g" <<<"$DOCKER_ARGS") - - # shellcheck disable=SC2001 - DOCKER_ARGS=$(sed -e "s/$filteredArg\+[[:blank:]][[:graph:]]\+[[:blank:]]\?//g" <<<"$DOCKER_ARGS") - done - - eval "ARG_ARRAY=($DOCKER_ARGS)" - fi - - if [[ "$DOKKU_APP_TYPE" != "herokuish" ]] || [[ -z "$CONTAINER_PATHS" ]]; then - return - fi - - DISABLE_CHOWN="$(fn-plugin-property-get "scheduler-docker-local" "$APP" "disable-chown" "")" - if [[ "$DISABLE_CHOWN" == "true" ]]; then - return - fi - - "$DOCKER_BIN" container run --rm "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS "${ARG_ARRAY[@]}" $IMAGE /bin/bash -c "find $CONTAINER_PATHS -not -user $DOKKU_APP_USER -print0 | xargs -0 -r chown -R $DOKKU_APP_USER" || true -} - scheduler-docker-local-pre-deploy-precheck() { declare desc="Outputs the checks messages if necessary" declare APP="$1" diff --git a/plugins/scheduler-docker-local/subcommands/set b/plugins/scheduler-docker-local/subcommands/set index 8f223012616..eade01b3a62 100755 --- a/plugins/scheduler-docker-local/subcommands/set +++ b/plugins/scheduler-docker-local/subcommands/set @@ -9,13 +9,13 @@ cmd-scheduler-docker-local-set() { declare cmd="scheduler-docker-local:set" [[ "$1" == "$cmd" ]] && shift 1 declare APP="$1" KEY="$2" VALUE="$3" - local VALID_KEYS=("disable-chown" "init-process" "parallel-schedule-count") + local VALID_KEYS=("init-process" "parallel-schedule-count") verify_app_name "$APP" [[ -z "$KEY" ]] && dokku_log_fail "No key specified" if ! fn-in-array "$KEY" "${VALID_KEYS[@]}"; then - dokku_log_fail "Invalid key specified, valid keys include: disable-chown, init-process, parallel-schedule-count" + dokku_log_fail "Invalid key specified, valid keys include: init-process, parallel-schedule-count" fi if [[ -n "$VALUE" ]]; then diff --git a/plugins/scheduler-k3s/functions.go b/plugins/scheduler-k3s/functions.go index aad634c0eef..20eaa75120b 100644 --- a/plugins/scheduler-k3s/functions.go +++ b/plugins/scheduler-k3s/functions.go @@ -473,10 +473,11 @@ func extractStartCommand(input StartCommandInput) string { } if command == "" { - procfileStartCommand, _ := common.PlugnTriggerOutputAsString("procfile-get-command", []string{input.AppName, input.ProcessType, fmt.Sprint(input.Port)}...) - if procfileStartCommand != "" { - command = procfileStartCommand - } + results, _ := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "procfile-get-command", + Args: []string{input.AppName, input.ProcessType, fmt.Sprint(input.Port)}, + }) + command = results.StdoutContents() } return command @@ -1238,7 +1239,11 @@ func getProcessResources(appName string, processType string) (ProcessResourcesMa processResources.Limits.CPU = "" } } - nvidiaGpuLimit, err := common.PlugnTriggerOutputAsString("resource-get-property", []string{appName, processType, "limit", "nvidia-gpu"}...) + response, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "resource-get-property", + Args: []string{appName, processType, "limit", "nvidia-gpu"}, + }) + nvidiaGpuLimit := response.StdoutContents() if err == nil && nvidiaGpuLimit != "" && nvidiaGpuLimit != "0" { _, err := resource.ParseQuantity(nvidiaGpuLimit) if err != nil { diff --git a/plugins/scheduler-k3s/go.mod b/plugins/scheduler-k3s/go.mod index 62348ff5a52..4895bf9f303 100644 --- a/plugins/scheduler-k3s/go.mod +++ b/plugins/scheduler-k3s/go.mod @@ -13,6 +13,7 @@ require ( github.com/go-openapi/jsonpointer v0.20.2 github.com/go-resty/resty/v2 v2.11.0 github.com/gofrs/flock v0.8.1 + github.com/gosimple/slug v1.14.0 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/kedacore/keda/v2 v2.13.0 github.com/ryanuber/columnize v2.1.2+incompatible @@ -46,8 +47,6 @@ require ( github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chai2010/gettext-go v1.0.2 // indirect - github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect - github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 // indirect github.com/containerd/containerd v1.7.11 // indirect github.com/containerd/log v0.1.0 // indirect github.com/cyphar/filepath-securejoin v0.2.4 // indirect @@ -86,6 +85,7 @@ require ( github.com/google/uuid v1.5.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.1 // indirect + github.com/gosimple/unidecode v1.0.1 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -165,7 +165,7 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect google.golang.org/grpc v1.60.1 // indirect - google.golang.org/protobuf v1.32.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/evanphx/json-patch.v5 v5.8.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/plugins/scheduler-k3s/go.sum b/plugins/scheduler-k3s/go.sum index e613ee4759b..beac6a83559 100644 --- a/plugins/scheduler-k3s/go.sum +++ b/plugins/scheduler-k3s/go.sum @@ -51,10 +51,6 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= -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/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= @@ -195,6 +191,10 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gosimple/slug v1.14.0 h1:RtTL/71mJNDfpUbCOmnf/XFkzKRtD6wL6Uy+3akm4Es= +github.com/gosimple/slug v1.14.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= +github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= +github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= @@ -547,8 +547,8 @@ google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/plugins/scheduler-k3s/helm.go b/plugins/scheduler-k3s/helm.go index b0cc95fcb8a..098bf3ad127 100644 --- a/plugins/scheduler-k3s/helm.go +++ b/plugins/scheduler-k3s/helm.go @@ -1,6 +1,7 @@ package scheduler_k3s import ( + "bytes" "context" "errors" "fmt" @@ -291,6 +292,16 @@ func (h *HelmAgent) ListRevisions(ctx context.Context, releaseName string) ([]Re return releases, nil } +type DebugRenderer struct { +} + +func (p *DebugRenderer) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) { + for _, line := range strings.Split(renderedManifests.String(), "\n") { + common.LogWarn(line) + } + return renderedManifests, nil +} + func (h *HelmAgent) UpgradeChart(ctx context.Context, input ChartInput) error { namespace := input.Namespace if namespace == "" { @@ -311,8 +322,11 @@ func (h *HelmAgent) UpgradeChart(ctx context.Context, input ChartInput) error { client.Atomic = input.RollbackOnFailure client.ChartPathOptions = action.ChartPathOptions{} client.CleanupOnFail = true - client.DryRun = false client.MaxHistory = 10 + if os.Getenv("DOKKU_TRACE") == "1" { + client.DryRun = true + client.PostRenderer = &DebugRenderer{} + } client.Namespace = namespace client.Timeout = input.Timeout client.Wait = input.Wait diff --git a/plugins/scheduler-k3s/k8s.go b/plugins/scheduler-k3s/k8s.go index f7f13245eef..6cc5835f522 100644 --- a/plugins/scheduler-k3s/k8s.go +++ b/plugins/scheduler-k3s/k8s.go @@ -12,6 +12,7 @@ import ( autoscalingv1 "k8s.io/api/autoscaling/v1" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -229,6 +230,20 @@ func (k KubernetesClient) CreateNamespace(ctx context.Context, input CreateNames return *namespace, err } +// DeleteIngressInput contains all the information needed to delete a Kubernetes ingress +type DeleteIngressInput struct { + // Name is the Kubernetes ingress name + Name string + + // Namespace is the Kubernetes namespace + Namespace string +} + +// DeleteIngress deletes a Kubernetes ingress +func (k KubernetesClient) DeleteIngress(ctx context.Context, input DeleteIngressInput) error { + return k.Client.NetworkingV1().Ingresses(input.Namespace).Delete(ctx, input.Name, metav1.DeleteOptions{}) +} + // DeleteJobInput contains all the information needed to delete a Kubernetes job type DeleteJobInput struct { // Name is the Kubernetes job name @@ -438,6 +453,30 @@ func (k KubernetesClient) ListDeployments(ctx context.Context, input ListDeploym return deployments.Items, nil } +// ListIngressesInput contains all the information needed to list Kubernetes ingresses +type ListIngressesInput struct { + // Namespace is the Kubernetes namespace + Namespace string + + // LabelSelector is the Kubernetes label selector + LabelSelector string +} + +// ListIngresses lists Kubernetes ingresses +func (k KubernetesClient) ListIngresses(ctx context.Context, input ListIngressesInput) ([]networkingv1.Ingress, error) { + listOptions := metav1.ListOptions{LabelSelector: input.LabelSelector} + ingresses, err := k.Client.NetworkingV1().Ingresses(input.Namespace).List(ctx, listOptions) + if err != nil { + return []networkingv1.Ingress{}, err + } + + if ingresses == nil { + return []networkingv1.Ingress{}, errors.New("ingresses is nil") + } + + return ingresses.Items, nil +} + // ListNamespaces lists Kubernetes namespaces func (k KubernetesClient) ListNamespaces(ctx context.Context) ([]v1.Namespace, error) { namespaces, err := k.Client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{}) diff --git a/plugins/scheduler-k3s/portmap.go b/plugins/scheduler-k3s/portmap.go index 6e012d888d7..e25b09337a7 100644 --- a/plugins/scheduler-k3s/portmap.go +++ b/plugins/scheduler-k3s/portmap.go @@ -29,12 +29,15 @@ func getPortMaps(appName string) (map[string]PortMap, error) { portMaps := []PortMap{} allowedMappings := map[string]PortMap{} - output, err := common.PlugnTriggerOutputAsString("ports-get", []string{appName, "json"}...) + results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "ports-get", + Args: []string{appName, "json"}, + }) if err != nil { return allowedMappings, err } - err = json.Unmarshal([]byte(output), &portMaps) + err = json.Unmarshal([]byte(results.StdoutContents()), &portMaps) if err != nil { return allowedMappings, err } diff --git a/plugins/scheduler-k3s/scheduler_k3s.go b/plugins/scheduler-k3s/scheduler_k3s.go index f03bc6ffc38..d72005b2283 100644 --- a/plugins/scheduler-k3s/scheduler_k3s.go +++ b/plugins/scheduler-k3s/scheduler_k3s.go @@ -42,7 +42,7 @@ var ( } ) -const DefaultIngressClass = "traefik" +const DefaultIngressClass = "nginx" const GlobalProcessType = "--global" const KubeConfigPath = "/etc/rancher/k3s/k3s.yaml" const DefaultKubeContext = "" diff --git a/plugins/scheduler-k3s/template.go b/plugins/scheduler-k3s/template.go index d5fb94ba3f8..6622ba17b55 100644 --- a/plugins/scheduler-k3s/template.go +++ b/plugins/scheduler-k3s/template.go @@ -238,11 +238,16 @@ type ProcessLabels struct { } type ProcessWeb struct { - Domains []string `yaml:"domains,omitempty"` + Domains []ProcessDomains `yaml:"domains,omitempty"` PortMaps []ProcessPortMap `yaml:"port_maps,omitempty"` TLS ProcessTls `yaml:"tls"` } +type ProcessDomains struct { + Name string `yaml:"name"` + Slug string `yaml:"slug"` +} + type ProcessResourcesMap struct { Limits ProcessResources `yaml:"limits,omitempty"` Requests ProcessResources `yaml:"requests,omitempty"` diff --git a/plugins/scheduler-k3s/templates/chart/_helpers.tpl b/plugins/scheduler-k3s/templates/chart/_helpers.tpl index 3f340c56c1a..6fb5ee78700 100644 --- a/plugins/scheduler-k3s/templates/chart/_helpers.tpl +++ b/plugins/scheduler-k3s/templates/chart/_helpers.tpl @@ -15,3 +15,35 @@ {{- end }} {{- end }} {{- end }} + +{{- define "primary.port" -}} +{{- $found := dict -}} +{{- range $idx, $port_map := . -}} +{{- if hasPrefix "https-443-" $port_map.name -}} +{{- $found := set $found "https-443" $port_map.name -}} +{{- end -}} +{{- if hasPrefix "http-80-" $port_map.name -}} +{{- $found := set $found "http-80" $port_map.name -}} +{{- end -}} +{{- if and (eq "https" $port_map.scheme) (not (hasKey $found "https")) -}} +{{- $found := set $found "https" $port_map.name -}} +{{- end -}} +{{- if and (eq "http" $port_map.scheme) (not (hasKey $found "http")) -}} +{{- $found := set $found "http" $port_map.name -}} +{{- end -}} +{{- if not (hasKey $found "any") -}} +{{- $found := set $found "any" $port_map.name -}} +{{- end -}} +{{- end -}} +{{- if hasKey $found "https-443" -}} +{{- get $found "https-443" -}} +{{- else if hasKey $found "http-80" -}} +{{- get $found "http-80" -}} +{{- else if hasKey $found "https" -}} +{{- get $found "https" -}} +{{- else if hasKey $found "http" -}} +{{- get $found "http" -}} +{{- else if hasKey $found "any" -}} +{{- get $found "any" -}} +{{- end -}} +{{- end -}} diff --git a/plugins/scheduler-k3s/templates/chart/certificate.yaml b/plugins/scheduler-k3s/templates/chart/certificate.yaml index 1ffc42a92d2..02923002070 100644 --- a/plugins/scheduler-k3s/templates/chart/certificate.yaml +++ b/plugins/scheduler-k3s/templates/chart/certificate.yaml @@ -30,7 +30,7 @@ spec: {{ include "print.labels" (dict "config" $.Values.global "key" "secret") | indent 6 }} {{ include "print.labels" (dict "config" $config "key" "secret") | indent 6 }} dnsNames: - {{- range $config.web.domains }} - - {{ . }} + {{- range $idx, $domain := $config.web.domains }} + - {{ $domain.name }} {{- end }} {{- end }} diff --git a/plugins/scheduler-k3s/templates/chart/ingress-route.yaml b/plugins/scheduler-k3s/templates/chart/ingress-route.yaml index e61c48063fe..306e4a7a3fd 100644 --- a/plugins/scheduler-k3s/templates/chart/ingress-route.yaml +++ b/plugins/scheduler-k3s/templates/chart/ingress-route.yaml @@ -34,7 +34,7 @@ spec: routes: {{- range $ddx, $domain := $config.web.domains }} - kind: Rule - match: Host(`{{ $domain }}`) + match: Host(`{{ $domain.name }}`) {{- if $config.web.tls.enabled }} middlewares: - name: {{ $.Values.global.app_name}}-{{ $processName }}-redirect-to-https diff --git a/plugins/scheduler-k3s/templates/chart/ingress.yaml b/plugins/scheduler-k3s/templates/chart/ingress.yaml index cfbf519dff8..b0eaa6c57ce 100644 --- a/plugins/scheduler-k3s/templates/chart/ingress.yaml +++ b/plugins/scheduler-k3s/templates/chart/ingress.yaml @@ -1,20 +1,14 @@ {{- $processName := "PROCESS_NAME" }} {{- $config := index .Values.processes "PROCESS_NAME" }} {{- if and $config.web.domains (eq $.Values.global.network.ingress_class "nginx") }} -{{- $mappings := dict }} -{{- range $pdx, $port_map := $config.web.port_maps }} -{{- $mappings := set $mappings $port_map.name "true" }} -{{- end }} -{{- range $pdx, $port_map := $config.web.port_maps }} -{{- if and (eq $port_map.scheme "https") (hasKey $mappings (printf "http-80-%.0f" $port_map.container_port)) }} -{{- continue }} -{{- end }} +{{- range $pdx, $domain := $config.web.domains }} --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: dokku.com/managed: "true" + dokku.com/ingress-method: "domains" {{- if $config.web.tls.enabled }} nginx.ingress.kubernetes.io/force-ssl-redirect: "true" {{- end }} @@ -26,30 +20,28 @@ metadata: app.kubernetes.io/part-of: {{ $.Values.global.app_name }} {{ include "print.labels" (dict "config" $.Values.global "key" "ingress") | indent 4 }} {{ include "print.labels" (dict "config" $config "key" "ingress") | indent 4 }} - name: {{ $.Values.global.app_name }}-{{ $processName }}-{{ $port_map.name }} + name: {{ $.Values.global.app_name }}-{{ $processName }}-{{ $domain.slug }} namespace: {{ $.Values.global.namespace }} spec: ingressClassName: nginx {{- if $config.web.tls.enabled }} tls: - hosts: - {{- range $ddx, $domain := $config.web.domains }} - - {{ $domain | quote }} - {{- end }} + - {{ $domain.name | quote }} secretName: tls-{{ $.Values.global.app_name }}-{{ $processName }} {{- end }} rules: - {{- range $ddx, $domain := $config.web.domains }} - - host: {{ $domain | quote }} + - host: {{ $domain.name | quote }} http: paths: + {{- if $config.web.port_maps }} - backend: service: name: {{ $.Values.global.app_name }}-{{ $processName }} port: - name: {{ $port_map.name }} + name: {{ include "primary.port" $config.web.port_maps }} pathType: ImplementationSpecific path: / - {{- end }} + {{- end }} {{- end }} {{- end }} diff --git a/plugins/scheduler-k3s/triggers.go b/plugins/scheduler-k3s/triggers.go index 827380869ff..86a5cb6c652 100644 --- a/plugins/scheduler-k3s/triggers.go +++ b/plugins/scheduler-k3s/triggers.go @@ -23,6 +23,7 @@ import ( "github.com/dokku/dokku/plugins/config" "github.com/dokku/dokku/plugins/cron" "github.com/fatih/color" + "github.com/gosimple/slug" "github.com/kballard/go-shellquote" "github.com/ryanuber/columnize" corev1 "k8s.io/api/core/v1" @@ -36,7 +37,6 @@ func TriggerInstall() error { if err := common.PropertySetup("scheduler-k3s"); err != nil { return fmt.Errorf("Unable to install the scheduler-k3s plugin: %s", err.Error()) } - return nil } @@ -80,12 +80,15 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e if scheduler != "k3s" { return nil } - 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 } - processes, err := common.ParseScaleOutput(s) + processes, err := common.ParseScaleOutput(results.StdoutBytes()) if err != nil { return err } @@ -224,14 +227,21 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e domains := []string{} if _, ok := processes["web"]; ok { - err = common.PlugnTrigger("domains-vhost-enabled", []string{appName}...) + _, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "domains-vhost-enabled", + Args: []string{appName}, + StreamStdio: true, + }) if err == nil { - b, err := common.PlugnTriggerOutput("domains-list", []string{appName}...) + results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "domains-list", + Args: []string{appName}, + }) if err != nil { return fmt.Errorf("Error getting domains for deployment: %w", err) } - for _, domain := range strings.Split(string(b), "\n") { + for _, domain := range strings.Split(results.StdoutContents(), "\n") { domain = strings.TrimSpace(domain) if domain != "" { domains = append(domains, domain) @@ -385,8 +395,17 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e } if processType == "web" { + sort.Strings(domains) + domainValues := []ProcessDomains{} + for _, domain := range domains { + domainValues = append(domainValues, ProcessDomains{ + Name: domain, + Slug: slug.Make(domain), + }) + } + processValues.Web = ProcessWeb{ - Domains: domains, + Domains: domainValues, PortMaps: []ProcessPortMap{}, TLS: ProcessTls{ Enabled: tlsEnabled, @@ -435,7 +454,6 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e } sort.Sort(NameSorter(processValues.Web.PortMaps)) - sort.Strings(processValues.Web.Domains) } values.Processes[processType] = processValues @@ -587,7 +605,39 @@ func TriggerSchedulerDeploy(scheduler string, appName string, imageTag string) e return fmt.Errorf("Error parsing deploy timeout duration: %w", err) } - common.LogExclaim(fmt.Sprintf("Installing %s", appName)) + ingresses, err := clientset.ListIngresses(ctx, ListIngressesInput{ + Namespace: namespace, + LabelSelector: fmt.Sprintf("app.kubernetes.io/instance=%s-web", appName), + }) + if err != nil { + return fmt.Errorf("Error listing ingresses: %w", err) + } + + ingressesToDelete := []string{} + + for _, ingress := range ingresses { + ingressIngressMethod := ingress.Annotations["dokku.com/ingress-method"] + if ingressIngressMethod != "domains" { + ingressesToDelete = append(ingressesToDelete, ingress.Name) + } + } + + if len(ingressesToDelete) > 0 { + common.LogWarn("Manually removing non-matching ingress resources") + } + for _, ingressName := range ingressesToDelete { + common.LogVerboseQuiet(fmt.Sprintf("Removing non-matching ingress resource: %s", ingressName)) + err := clientset.DeleteIngress(ctx, DeleteIngressInput{ + Name: ingressName, + Namespace: namespace, + }) + + if err != nil { + return fmt.Errorf("Error deleting ingress: %w", err) + } + } + + common.LogInfo2(fmt.Sprintf("Installing %s", appName)) err = helmAgent.InstallOrUpgradeChart(ctx, ChartInput{ ChartPath: chartPath, Namespace: namespace, @@ -695,10 +745,21 @@ func TriggerSchedulerEnter(scheduler string, appName string, processType string, command := args if len(args) == 0 { command = []string{"/bin/bash"} - if globalShell, err := common.PlugnTriggerOutputAsString("config-get-global", []string{"DOKKU_APP_SHELL"}...); err == nil && globalShell != "" { + results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "config-get-global", + Args: []string{"DOKKU_APP_SHELL"}, + }) + globalShell := results.StdoutContents() + if err == nil && globalShell != "" { command = []string{globalShell} } - if appShell, err := common.PlugnTriggerOutputAsString("config-get", []string{appName, "DOKKU_APP_SHELL"}...); err == nil && appShell != "" { + + results, err = common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "config-get", + Args: []string{appName, "DOKKU_APP_SHELL"}, + }) + appShell := results.StdoutContents() + if err == nil && appShell != "" { command = []string{appShell} } } @@ -927,10 +988,21 @@ func TriggerSchedulerRun(scheduler string, appName string, envCount int, args [] command := args if len(args) == 0 { command = []string{"/bin/bash"} - if globalShell, err := common.PlugnTriggerOutputAsString("config-get-global", []string{"DOKKU_APP_SHELL"}...); err == nil && globalShell != "" { + results, err := common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "config-get-global", + Args: []string{"DOKKU_APP_SHELL"}, + }) + globalShell := results.StdoutContents() + if err == nil && globalShell != "" { command = []string{globalShell} } - if appShell, err := common.PlugnTriggerOutputAsString("config-get", []string{appName, "DOKKU_APP_SHELL"}...); err == nil && appShell != "" { + + results, err = common.CallPlugnTrigger(common.PlugnTriggerInput{ + Trigger: "config-get", + Args: []string{appName, "DOKKU_APP_SHELL"}, + }) + appShell := results.StdoutContents() + if err == nil && appShell != "" { command = []string{appShell} } } else if len(args) == 1 { diff --git a/plugins/scheduler/go.mod b/plugins/scheduler/go.mod index 570da73bc16..4bdadd21810 100644 --- a/plugins/scheduler/go.mod +++ b/plugins/scheduler/go.mod @@ -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 diff --git a/plugins/scheduler/go.sum b/plugins/scheduler/go.sum index a2e5d436bbf..bf77a3bf13e 100644 --- a/plugins/scheduler/go.sum +++ b/plugins/scheduler/go.sum @@ -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= diff --git a/plugins/traefik-vhosts/command-functions b/plugins/traefik-vhosts/command-functions index 68f194d5b0c..c37a19f8c64 100755 --- a/plugins/traefik-vhosts/command-functions +++ b/plugins/traefik-vhosts/command-functions @@ -44,7 +44,6 @@ cmd-traefik-report-single() { "--traefik-letsencrypt-email: $(fn-traefik-letsencrypt-email)" "--traefik-letsencrypt-server: $(fn-traefik-letsencrypt-server)" "--traefik-log-level: $(fn-traefik-log-level)" - "--traefik-priority: $(fn-traefik-priority "$APP")" ) if [[ -z "$INFO_FLAG" ]]; then diff --git a/plugins/traefik-vhosts/docker-args-process-deploy b/plugins/traefik-vhosts/docker-args-process-deploy index f9d94ffa46b..6cb1c8da4e3 100755 --- a/plugins/traefik-vhosts/docker-args-process-deploy +++ b/plugins/traefik-vhosts/docker-args-process-deploy @@ -8,7 +8,7 @@ trigger-traefik-vhosts-docker-args-process-deploy() { declare desc="nginx-vhosts core-post-deploy plugin trigger" declare trigger="docker-args-process-deploy" declare APP="$1" IMAGE_SOURCE_TYPE="$2" IMAGE_TAG="$3" PROC_TYPE="$4" CONTAINER_INDEX="$5" - local app_domains is_app_listening letsencrypt_email output proxy_container_port proxy_host_port port_map priority proxy_scheme proxy_schemes traefik_domains + local app_domains is_app_listening letsencrypt_email output proxy_container_port proxy_host_port port_map proxy_scheme proxy_schemes traefik_domains local proxy_container_http_port proxy_container_http_port_candidate proxy_host_http_port_candidate local proxy_container_https_port proxy_container_https_port_candidate proxy_host_https_port_candidate local STDIN=$(cat) @@ -87,11 +87,6 @@ trigger-traefik-vhosts-docker-args-process-deploy() { traefik_domains="${traefik_domains// /\\\`,\\\`}" fi - priority="$(fn-traefik-priority "$APP")" - if [[ -z "$priority" ]]; then - priority="$(date +%s)" - fi - output="--label traefik.enable=true" if [[ -n "$proxy_container_http_port" ]] || [[ -n "$proxy_container_http_port_candidate" ]]; then if [[ -z "$proxy_container_http_port" ]]; then @@ -102,7 +97,6 @@ trigger-traefik-vhosts-docker-args-process-deploy() { output="$output --label traefik.http.services.$APP-$PROC_TYPE-http.loadbalancer.server.port=$proxy_container_http_port" output="$output --label traefik.http.routers.$APP-$PROC_TYPE-http.entrypoints=http" - output="$output --label traefik.http.routers.$APP-$PROC_TYPE-http.priority=$priority" output="$output --label traefik.http.routers.$APP-$PROC_TYPE-http.service=$APP-$PROC_TYPE-http" if [[ -n "$traefik_domains" ]]; then output="$output --label \"traefik.http.routers.$APP-$PROC_TYPE-http.rule=Host(\\\`$traefik_domains\\\`)\"" @@ -118,7 +112,6 @@ trigger-traefik-vhosts-docker-args-process-deploy() { output="$output --label traefik.http.services.$APP-$PROC_TYPE-https.loadbalancer.server.port=$proxy_container_https_port" output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.entrypoints=https" - output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.priority=$priority" output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.service=$APP-$PROC_TYPE-https" output="$output --label traefik.http.routers.$APP-$PROC_TYPE-https.tls.certresolver=leresolver" if [[ -n "$traefik_domains" ]]; then diff --git a/plugins/traefik-vhosts/internal-functions b/plugins/traefik-vhosts/internal-functions index f2e7e4134bb..ce981215d1f 100755 --- a/plugins/traefik-vhosts/internal-functions +++ b/plugins/traefik-vhosts/internal-functions @@ -92,8 +92,3 @@ fn-traefik-log-level() { log_level="$(fn-plugin-property-get-default "traefik" "--global" "log-level" "ERROR")" echo "${log_level^^}" } - -fn-traefik-priority() { - declare APP="$1" - fn-plugin-property-get-default "traefik" "$APP" "priority" "" -} diff --git a/plugins/traefik-vhosts/subcommands/set b/plugins/traefik-vhosts/subcommands/set index 0c51777b2b0..c9a10476b4d 100755 --- a/plugins/traefik-vhosts/subcommands/set +++ b/plugins/traefik-vhosts/subcommands/set @@ -9,13 +9,13 @@ cmd-traefik-set() { declare cmd="traefik:set" [[ "$1" == "$cmd" ]] && shift 1 declare APP="$1" KEY="$2" VALUE="$3" - local VALID_KEYS=("api-enabled" "api-vhost" "dashboard-enabled" "basic-auth-username" "basic-auth-password" "image" "letsencrypt-email" "letsencrypt-server" "log-level" "priority") + local VALID_KEYS=("api-enabled" "api-vhost" "dashboard-enabled" "basic-auth-username" "basic-auth-password" "image" "letsencrypt-email" "letsencrypt-server" "log-level") local GLOBAL_KEYS=("api-enabled" "api-vhost" "dashboard"-enabled "basic-auth-username" "basic-auth-password" "image" "letsencrypt-email" "letsencrypt-server" "log-level") [[ -z "$KEY" ]] && dokku_log_fail "No key specified" if ! fn-in-array "$KEY" "${VALID_KEYS[@]}"; then - dokku_log_fail "Invalid key specified, valid keys include: api-enabled api-vhost dashboard-enabled basic-auth-username basic-auth-password image letsencrypt-email letsencrypt-server log-level priority" + dokku_log_fail "Invalid key specified, valid keys include: api-enabled api-vhost dashboard-enabled basic-auth-username basic-auth-password image letsencrypt-email letsencrypt-server log-level" fi if ! fn-in-array "$KEY" "${GLOBAL_KEYS[@]}"; then diff --git a/plugins/traefik-vhosts/templates/compose.yml.sigil b/plugins/traefik-vhosts/templates/compose.yml.sigil index 6bddb993844..d068544842a 100644 --- a/plugins/traefik-vhosts/templates/compose.yml.sigil +++ b/plugins/traefik-vhosts/templates/compose.yml.sigil @@ -12,6 +12,7 @@ services: - --entrypoints.https.address=:443 {{ end }} - --providers.docker + - --providers.docker.exposedByDefault=false - --api={{ $.TRAEFIK_API_ENABLED }} - --api.dashboard={{ $.TRAEFIK_DASHBOARD_ENABLED }} @@ -33,6 +34,7 @@ services: {{ if eq $.TRAEFIK_API_ENABLED "true" }} # Dashboard + - "traefik.enable=true" - "traefik.http.routers.api.rule=Host(`{{ $.TRAEFIK_API_VHOST }}`)" - "traefik.http.routers.api.service=api@internal" - "traefik.http.routers.api.entrypoints={{ if $.TRAEFIK_LETSENCRYPT_EMAIL }}https{{ else }}http{{ end }}" diff --git a/tests/unit/apps_1.bats b/tests/unit/apps_1.bats index 7b415606fb8..5b85ffacd12 100644 --- a/tests/unit/apps_1.bats +++ b/tests/unit/apps_1.bats @@ -178,6 +178,14 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + run /bin/bash -c "dokku config:set --no-restart $TEST_APP KEY=VALUE-$TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + run /bin/bash -c "dokku docker-options:add $TEST_APP deploy --no-healthcheck" + echo "output: $output" + echo "status: $status" + assert_success run /bin/bash -c "dokku git:set $TEST_APP deploy-branch SOME_BRANCH_NAME" echo "output: $output" echo "status: $status" @@ -194,10 +202,6 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "dokku scheduler-docker-local:set $TEST_APP disable-chown true" - echo "output: $output" - echo "status: $status" - assert_success run /bin/bash -c "dokku apps:rename $TEST_APP great-test-name" echo "output: $output" @@ -208,6 +212,16 @@ teardown() { echo "status: $status" assert_success assert_output "https://github.com/heroku/heroku-buildpack-ruby.git" + run /bin/bash -c "dokku config:get great-test-name KEY" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "VALUE-$TEST_APP" + run /bin/bash -c "dokku docker-options:report great-test-name --docker-options-deploy" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "--no-healthcheck" run /bin/bash -c "dokku git:report great-test-name --git-deploy-branch" echo "output: $output" echo "status: $status" @@ -228,11 +242,6 @@ teardown() { echo "status: $status" assert_success assert_output "100" - run /bin/bash -c "dokku scheduler-docker-local:report great-test-name --scheduler-docker-local-disable-chown" - echo "output: $output" - echo "status: $status" - assert_success - assert_output "true" run /bin/bash -c "dokku --force apps:destroy great-test-name" echo "output: $output" diff --git a/tests/unit/apps_2.bats b/tests/unit/apps_2.bats index eb7ddcbb761..a176cece0f2 100644 --- a/tests/unit/apps_2.bats +++ b/tests/unit/apps_2.bats @@ -59,10 +59,6 @@ teardown() { echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "dokku scheduler-docker-local:set $TEST_APP disable-chown true" - echo "output: $output" - echo "status: $status" - assert_success run /bin/bash -c "dokku apps:clone $TEST_APP great-test-name" echo "output: $output" @@ -103,11 +99,6 @@ teardown() { echo "status: $status" assert_success assert_output "100" - run /bin/bash -c "dokku scheduler-docker-local:report great-test-name --scheduler-docker-local-disable-chown" - echo "output: $output" - echo "status: $status" - assert_success - assert_output "true" run /bin/bash -c "dokku --force apps:destroy great-test-name" echo "output: $output" diff --git a/tests/unit/buildpacks.bats b/tests/unit/buildpacks.bats index acef7630762..e4d24fb394d 100644 --- a/tests/unit/buildpacks.bats +++ b/tests/unit/buildpacks.bats @@ -205,7 +205,7 @@ teardown() { run /bin/bash -c "dokku --quiet buildpacks:list $TEST_APP | xargs" echo "output: $output" echo "status: $status" - assert_output_contains "https://github.com/heroku/heroku-buildpack-nodejs.git https://github.com/heroku/heroku-buildpack-ruby.git" + assert_output "https://github.com/heroku/heroku-buildpack-nodejs.git https://github.com/heroku/heroku-buildpack-ruby.git" run /bin/bash -c "dokku buildpacks:remove $TEST_APP heroku/nodejs" echo "output: $output" @@ -215,7 +215,7 @@ teardown() { run /bin/bash -c "dokku --quiet buildpacks:list $TEST_APP | xargs" echo "output: $output" echo "status: $status" - assert_output_contains "https://github.com/heroku/heroku-buildpack-ruby.git" + assert_output "https://github.com/heroku/heroku-buildpack-ruby.git" run /bin/bash -c "dokku buildpacks:remove $TEST_APP heroku/php" echo "output: $output" @@ -231,6 +231,36 @@ teardown() { echo "output: $output" echo "status: $status" assert_output_not_exists + + run /bin/bash -c "dokku buildpacks:add $TEST_APP https://github.com/heroku/heroku-buildpack-nodejs.git" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku buildpacks:add $TEST_APP https://github.com/heroku/heroku-buildpack-ruby.git" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku buildpacks:add $TEST_APP https://github.com/yespark/heroku-imagemagick-buildpack" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku --quiet buildpacks:list $TEST_APP | xargs" + echo "output: $output" + echo "status: $status" + assert_output "https://github.com/heroku/heroku-buildpack-nodejs.git https://github.com/heroku/heroku-buildpack-ruby.git https://github.com/yespark/heroku-imagemagick-buildpack" + + run /bin/bash -c "dokku buildpacks:remove $TEST_APP --index 1" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku --quiet buildpacks:list $TEST_APP | xargs" + echo "output: $output" + echo "status: $status" + assert_output "https://github.com/heroku/heroku-buildpack-ruby.git https://github.com/yespark/heroku-imagemagick-buildpack" } @test "(buildpacks) buildpacks:clear" { diff --git a/tests/unit/client.bats b/tests/unit/client.bats index bfb51a64d90..0c0610ea934 100644 --- a/tests/unit/client.bats +++ b/tests/unit/client.bats @@ -6,9 +6,11 @@ setup() { global_setup export "DOKKU_HOST=${DOKKU_DOMAIN}" create_app + clone_test_plugin } teardown() { + remove_test_plugin || true destroy_app unset DOKKU_HOST global_teardown @@ -311,3 +313,22 @@ teardown() { assert_success assert_output "dokku" } + +@test "(client) test-args" { + run /bin/bash -c "dokku plugin:install $TEST_PLUGIN_GIT_REPO --name $TEST_PLUGIN_NAME" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku smoke-test-plugin:args bash -c 'echo Hello'" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "triggered smoke-test-plugin:args with args: smoke-test-plugin:args, bash, -c, echo Hello" + + run /bin/bash -c "${BATS_TEST_DIRNAME}/../../contrib/dokku_client.sh 'smoke-test-plugin:args bash -c \"echo Hello\"'" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "triggered smoke-test-plugin:args with args: smoke-test-plugin:args, bash, -c, echo Hello" +} diff --git a/tests/unit/git_3.bats b/tests/unit/git_3.bats index 1cec5559657..1361181f070 100644 --- a/tests/unit/git_3.bats +++ b/tests/unit/git_3.bats @@ -2,6 +2,12 @@ load test_helper +SMOKE_TEST_APP_1_0_0_SHA=9cf71bba639c4f1671dfd42685338b762d3354f2 +SMOKE_TEST_APP_2_0_0_SHA=5c8a5e42bbd7fae98bd657fb17f41c6019b303f9 +SMOKE_TEST_APP_ANOTHER_BRANCH_SHA=5c8a5e42bbd7fae98bd657fb17f41c6019b303f9 +SMOKE_TEST_APP_MASTER_SHA=af1b02052199b8ca8115f80ff8676a7c7744a45f +SMOKE_TEST_APP_COMMIT_SHA=5c8a5e42bbd7fae98bd657fb17f41c6019b303f9 + setup() { global_setup create_app @@ -121,6 +127,12 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" } @test "(git) git:sync new [--no-build branch]" { @@ -128,6 +140,12 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" } @test "(git) git:sync new [--no-build tag]" { @@ -135,13 +153,25 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" } @test "(git) git:sync new [--no-build commit]" { - run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git 5c8a5e42bbd7fae98bd657fb17f41c6019b303f9" + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" echo "output: $output" echo "status: $status" assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" } @test "(git) git:sync new [--build noarg]" { @@ -150,6 +180,24 @@ teardown() { echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" } @test "(git) git:sync new [--build branch]" { @@ -158,6 +206,24 @@ teardown() { echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" } @test "(git) git:sync new [--build tag]" { @@ -166,14 +232,50 @@ teardown() { echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git 1.0.0" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" } @test "(git) git:sync new [--build commit]" { - run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git 5c8a5e42bbd7fae98bd657fb17f41c6019b303f9" + run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" echo "output: $output" echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" } @test "(git) git:sync existing [errors]" { @@ -204,15 +306,28 @@ teardown() { } @test "(git) git:sync existing [--no-build noarg]" { - run /bin/bash -c "dokku --trace git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git 1.0.0" + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git 1.0.0" echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "dokku --trace git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git" + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" echo "output: $output" echo "status: $status" assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Fetching remote code for" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" } @test "(git) git:sync existing [--no-build branch]" { @@ -221,10 +336,22 @@ teardown() { echo "status: $status" assert_success + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git another-branch" echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" } @test "(git) git:sync existing [--no-build tag]" { @@ -233,10 +360,22 @@ teardown() { echo "status: $status" assert_success + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git 2.0.0" echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_2_0_0_SHA" } @test "(git) git:sync existing [--no-build commit]" { @@ -245,10 +384,22 @@ teardown() { echo "status: $status" assert_success - run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git 5c8a5e42bbd7fae98bd657fb17f41c6019b303f9" + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + + run /bin/bash -c "dokku git:sync $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" } @test "(git) git:sync existing [--build noarg]" { @@ -257,11 +408,35 @@ teardown() { echo "status: $status" assert_success + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git" echo "output: $output" echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_MASTER_SHA" } @test "(git) git:sync existing [--build branch]" { @@ -270,11 +445,35 @@ teardown() { echo "status: $status" assert_success + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_2_0_0_SHA" + run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git another-branch" echo "output: $output" echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git another-branch" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_ANOTHER_BRANCH_SHA" } @test "(git) git:sync existing [--build tag]" { @@ -283,11 +482,35 @@ teardown() { echo "status: $status" assert_success + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git 2.0.0" echo "output: $output" echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_2_0_0_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git 2.0.0" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_2_0_0_SHA" } @test "(git) git:sync existing [--build commit]" { @@ -296,11 +519,35 @@ teardown() { echo "status: $status" assert_success - run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git 5c8a5e42bbd7fae98bd657fb17f41c6019b303f9" + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_1_0_0_SHA" + + run /bin/bash -c "dokku git:sync --build $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" echo "output: $output" echo "status: $status" assert_success assert_output_contains "Application deployed" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app.git $SMOKE_TEST_APP_COMMIT_SHA" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" + + run /bin/bash -c "cat /home/dokku/$TEST_APP/refs/heads/master" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$SMOKE_TEST_APP_COMMIT_SHA" } @test "(git) git:sync private" { @@ -328,6 +575,12 @@ teardown() { echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "dokku git:sync --build-if-changes $TEST_APP https://github.com/dokku/smoke-test-app-private.git" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Skipping build as no changes were detected" } @test "(git) git:public-key" { diff --git a/tests/unit/git_6.bats b/tests/unit/git_6.bats index ab706a5753d..03c81f264e0 100644 --- a/tests/unit/git_6.bats +++ b/tests/unit/git_6.bats @@ -4,27 +4,286 @@ load test_helper setup() { global_setup + create_app touch /home/dokku/.ssh/known_hosts chown dokku:dokku /home/dokku/.ssh/known_hosts - mkdir -p "$DOKKU_LIB_ROOT/data/git/$TEST_APP" - chown dokku:dokku "$DOKKU_LIB_ROOT/data/git/$TEST_APP" } teardown() { + docker image rm linuxserver/foldingathome:7.6.21 || true + docker image rm dokku/node-js-getting-started:latest || true + docker image rm dokku-test/$TEST_APP:latest || true + docker image rm dokku-test/$TEST_APP:v2 || true + docker image rm gliderlabs/logspout:v3.2.13 || true + rm -f /tmp/image.tar /tmp/image-2.tar rm -f /home/dokku/.ssh/id_rsa.pub || true + destroy_app global_teardown } -@test "(git) git:unlock [success]" { - run /bin/bash -c "dokku git:unlock $TEST_APP --force" +@test "(git) git:load-image [normal]" { + run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" echo "output: $output" echo "status: $status" assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success +} + +@test "(git) git:load-image [normal-git-init]" { + run rm -rf "/home/dokku/$TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run mkdir "/home/dokku/$TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run chown -R dokku:dokku "/home/dokku/$TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success +} + +@test "(git) git:load-image [normal-cnb]" { + run /bin/bash -c "docker image pull dokku/node-js-getting-started:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar dokku/node-js-getting-started:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm dokku/node-js-getting-started:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku/node-js-getting-started:latest" + echo "output: $output" + echo "status: $status" + assert_success +} + +@test "(git) git:load-image [failing deploy]" { + local CUSTOM_TMP=$(mktemp -d "/tmp/${DOKKU_DOMAIN}.XXXXX") + trap 'popd &>/dev/null || true; rm -rf "$CUSTOM_TMP"' INT TERM + rmdir "$CUSTOM_TMP" && cp -r "${BATS_TEST_DIRNAME}/../../tests/apps/python" "$CUSTOM_TMP" + + run /bin/bash -c "docker image build -t dokku-test/$TEST_APP:latest -f $CUSTOM_TMP/alt.Dockerfile $CUSTOM_TMP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image build -t dokku-test/$TEST_APP:v2 --build-arg BUILD_ARG=value -f $CUSTOM_TMP/alt.Dockerfile $CUSTOM_TMP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar dokku-test/$TEST_APP:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image-2.tar dokku-test/$TEST_APP:v2" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm dokku-test/$TEST_APP:latest dokku-test/$TEST_APP:v2" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=true" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:latest" + echo "output: $output" + echo "status: $status" + assert_failure + + run /bin/bash -c "dokku config:get $TEST_APP FAIL_ON_STARTUP" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "true" + + run /bin/bash -c "dokku git:status $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output "fatal: this operation must be run in a work tree" + + run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=false" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=true" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image-2.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:v2" + echo "output: $output" + echo "status: $status" + assert_failure + + run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=false" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image-2.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:v2" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "No changes detected, skipping git commit" 0 } -@test "(git) git:unlock [missing arg]" { - run /bin/bash -c "dokku git:unlock" +@test "(git) git:load-image [onbuild]" { + local TMP=$(mktemp -d "/tmp/${DOKKU_DOMAIN}.XXXXX") + trap 'popd &>/dev/null || true; rm -rf "$TMP"' INT TERM + + run /bin/bash -c "dokku storage:mount $TEST_APP /var/run/docker.sock:/var/run/docker.sock" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image pull gliderlabs/logspout:v3.2.13" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar gliderlabs/logspout:v3.2.13" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm gliderlabs/logspout:v3.2.13" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP gliderlabs/logspout:v3.2.13" + echo "output: $output" + echo "status: $status" + assert_failure + + cat <"$TMP/build.sh" +#!/bin/sh +set -e +apk add --update go build-base git mercurial ca-certificates +cd /src +go build -ldflags "-X main.Version=\$1" -o /bin/logspout +apk del go git mercurial build-base +rm -rf /root/go /var/cache/apk/* + +# backwards compatibility +ln -fs /tmp/docker.sock /var/run/docker.sock +EOF + + cat <"$TMP/modules.go" +package main + +import ( + _ "github.com/gliderlabs/logspout/adapters/multiline" + _ "github.com/gliderlabs/logspout/adapters/raw" + _ "github.com/gliderlabs/logspout/adapters/syslog" + _ "github.com/gliderlabs/logspout/healthcheck" + _ "github.com/gliderlabs/logspout/httpstream" + _ "github.com/gliderlabs/logspout/routesapi" + _ "github.com/gliderlabs/logspout/transports/tcp" + _ "github.com/gliderlabs/logspout/transports/tls" + _ "github.com/gliderlabs/logspout/transports/udp" +) +EOF + + run sudo chown -R dokku:dokku "$TMP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image --build-dir $TMP $TEST_APP gliderlabs/logspout:v3.2.13" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP gliderlabs/logspout:v3.2.13" echo "output: $output" echo "status: $status" assert_failure } + +@test "(git) git:load-image labels correctly" { + run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "docker image inspect dokku/$TEST_APP:latest --format '{{ index .Config.Labels \"com.dokku.docker-image-labeler/alternate-tags\" }}'" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "linuxserver/foldingathome:7.6.21" +} diff --git a/tests/unit/git_7.bats b/tests/unit/git_7.bats index 03c81f264e0..be9ae88886d 100644 --- a/tests/unit/git_7.bats +++ b/tests/unit/git_7.bats @@ -2,288 +2,50 @@ load test_helper +TEST_PLUGIN_APP=smoke-test-app +TEST_PLUGIN_GIT_REPO=https://github.com/dokku/${TEST_PLUGIN_APP}.git +TEST_PLUGIN_LOCAL_REPO="$(mktemp -d)/$TEST_PLUGIN_APP" + +clone_test_app() { + git clone "$TEST_PLUGIN_GIT_REPO" "$TEST_PLUGIN_LOCAL_REPO" +} + +remove_test_app() { + rm -rf $TEST_PLUGIN_LOCAL_REPO +} + setup() { global_setup create_app - touch /home/dokku/.ssh/known_hosts - chown dokku:dokku /home/dokku/.ssh/known_hosts + clone_test_app } teardown() { - docker image rm linuxserver/foldingathome:7.6.21 || true - docker image rm dokku/node-js-getting-started:latest || true - docker image rm dokku-test/$TEST_APP:latest || true - docker image rm dokku-test/$TEST_APP:v2 || true - docker image rm gliderlabs/logspout:v3.2.13 || true - rm -f /tmp/image.tar /tmp/image-2.tar - rm -f /home/dokku/.ssh/id_rsa.pub || true + remove_test_app || true destroy_app global_teardown } -@test "(git) git:load-image [normal]" { - run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success -} - -@test "(git) git:load-image [normal-git-init]" { - run rm -rf "/home/dokku/$TEST_APP" - echo "output: $output" - echo "status: $status" - assert_success - - run mkdir "/home/dokku/$TEST_APP" - echo "output: $output" - echo "status: $status" - assert_success - - run chown -R dokku:dokku "/home/dokku/$TEST_APP" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success -} - -@test "(git) git:load-image [normal-cnb]" { - run /bin/bash -c "docker image pull dokku/node-js-getting-started:latest" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar dokku/node-js-getting-started:latest" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image rm dokku/node-js-getting-started:latest" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku/node-js-getting-started:latest" - echo "output: $output" - echo "status: $status" - assert_success -} - -@test "(git) git:load-image [failing deploy]" { - local CUSTOM_TMP=$(mktemp -d "/tmp/${DOKKU_DOMAIN}.XXXXX") - trap 'popd &>/dev/null || true; rm -rf "$CUSTOM_TMP"' INT TERM - rmdir "$CUSTOM_TMP" && cp -r "${BATS_TEST_DIRNAME}/../../tests/apps/python" "$CUSTOM_TMP" - - run /bin/bash -c "docker image build -t dokku-test/$TEST_APP:latest -f $CUSTOM_TMP/alt.Dockerfile $CUSTOM_TMP" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image build -t dokku-test/$TEST_APP:v2 --build-arg BUILD_ARG=value -f $CUSTOM_TMP/alt.Dockerfile $CUSTOM_TMP" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar dokku-test/$TEST_APP:latest" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image-2.tar dokku-test/$TEST_APP:v2" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image rm dokku-test/$TEST_APP:latest dokku-test/$TEST_APP:v2" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=true" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:latest" - echo "output: $output" - echo "status: $status" - assert_failure - - run /bin/bash -c "dokku config:get $TEST_APP FAIL_ON_STARTUP" - echo "output: $output" - echo "status: $status" - assert_success - assert_output "true" - - run /bin/bash -c "dokku git:status $TEST_APP" - echo "output: $output" - echo "status: $status" - assert_failure - assert_output "fatal: this operation must be run in a work tree" - - run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=false" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:latest" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=true" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image-2.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:v2" - echo "output: $output" - echo "status: $status" - assert_failure - - run /bin/bash -c "dokku config:set --no-restart $TEST_APP FAIL_ON_STARTUP=false" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image-2.tar | dokku git:load-image $TEST_APP dokku-test/$TEST_APP:v2" - echo "output: $output" - echo "status: $status" - assert_success - assert_output_contains "No changes detected, skipping git commit" 0 -} - -@test "(git) git:load-image [onbuild]" { - local TMP=$(mktemp -d "/tmp/${DOKKU_DOMAIN}.XXXXX") - trap 'popd &>/dev/null || true; rm -rf "$TMP"' INT TERM - - run /bin/bash -c "dokku storage:mount $TEST_APP /var/run/docker.sock:/var/run/docker.sock" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image pull gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image rm gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_failure - - cat <"$TMP/build.sh" -#!/bin/sh -set -e -apk add --update go build-base git mercurial ca-certificates -cd /src -go build -ldflags "-X main.Version=\$1" -o /bin/logspout -apk del go git mercurial build-base -rm -rf /root/go /var/cache/apk/* - -# backwards compatibility -ln -fs /tmp/docker.sock /var/run/docker.sock -EOF - - cat <"$TMP/modules.go" -package main - -import ( - _ "github.com/gliderlabs/logspout/adapters/multiline" - _ "github.com/gliderlabs/logspout/adapters/raw" - _ "github.com/gliderlabs/logspout/adapters/syslog" - _ "github.com/gliderlabs/logspout/healthcheck" - _ "github.com/gliderlabs/logspout/httpstream" - _ "github.com/gliderlabs/logspout/routesapi" - _ "github.com/gliderlabs/logspout/transports/tcp" - _ "github.com/gliderlabs/logspout/transports/tls" - _ "github.com/gliderlabs/logspout/transports/udp" -) -EOF - - run sudo chown -R dokku:dokku "$TMP" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image --build-dir $TMP $TEST_APP gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP gliderlabs/logspout:v3.2.13" - echo "output: $output" - echo "status: $status" - assert_failure -} - -@test "(git) git:load-image labels correctly" { - run /bin/bash -c "docker image pull linuxserver/foldingathome:7.6.21" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker image save -o /tmp/image.tar linuxserver/foldingathome:7.6.21" +@test "(git) push tags and branches" { + # https://github.com/dokku/dokku/issues/5188 + local GIT_REMOTE=${GIT_REMOTE:="dokku@${DOKKU_DOMAIN}:$TEST_APP"} + run git -C "$TEST_PLUGIN_LOCAL_REPO" remote add target "$GIT_REMOTE" echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "docker image rm linuxserver/foldingathome:7.6.21" + run git -C "$TEST_PLUGIN_LOCAL_REPO" push target 1.0.0:master echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "cat /tmp/image.tar | dokku git:load-image $TEST_APP linuxserver/foldingathome:7.6.21" + run git -C "$TEST_PLUGIN_LOCAL_REPO" push target 2.0.0:master -f echo "output: $output" echo "status: $status" assert_success - run /bin/bash -c "docker image inspect dokku/$TEST_APP:latest --format '{{ index .Config.Labels \"com.dokku.docker-image-labeler/alternate-tags\" }}'" + run git -C "$TEST_PLUGIN_LOCAL_REPO" push target master -f echo "output: $output" echo "status: $status" assert_success - assert_output_contains "linuxserver/foldingathome:7.6.21" } diff --git a/tests/unit/git_8.bats b/tests/unit/git_8.bats deleted file mode 100644 index be9ae88886d..00000000000 --- a/tests/unit/git_8.bats +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env bats - -load test_helper - -TEST_PLUGIN_APP=smoke-test-app -TEST_PLUGIN_GIT_REPO=https://github.com/dokku/${TEST_PLUGIN_APP}.git -TEST_PLUGIN_LOCAL_REPO="$(mktemp -d)/$TEST_PLUGIN_APP" - -clone_test_app() { - git clone "$TEST_PLUGIN_GIT_REPO" "$TEST_PLUGIN_LOCAL_REPO" -} - -remove_test_app() { - rm -rf $TEST_PLUGIN_LOCAL_REPO -} - -setup() { - global_setup - create_app - clone_test_app -} - -teardown() { - remove_test_app || true - destroy_app - global_teardown -} - -@test "(git) push tags and branches" { - # https://github.com/dokku/dokku/issues/5188 - local GIT_REMOTE=${GIT_REMOTE:="dokku@${DOKKU_DOMAIN}:$TEST_APP"} - run git -C "$TEST_PLUGIN_LOCAL_REPO" remote add target "$GIT_REMOTE" - echo "output: $output" - echo "status: $status" - assert_success - - run git -C "$TEST_PLUGIN_LOCAL_REPO" push target 1.0.0:master - echo "output: $output" - echo "status: $status" - assert_success - - run git -C "$TEST_PLUGIN_LOCAL_REPO" push target 2.0.0:master -f - echo "output: $output" - echo "status: $status" - assert_success - - run git -C "$TEST_PLUGIN_LOCAL_REPO" push target master -f - echo "output: $output" - echo "status: $status" - assert_success -} diff --git a/tests/unit/plugin.bats b/tests/unit/plugin.bats index 10761acf84f..9323bb41748 100644 --- a/tests/unit/plugin.bats +++ b/tests/unit/plugin.bats @@ -1,24 +1,12 @@ #!/usr/bin/env bats load test_helper -TEST_PLUGIN_NAME=smoke-test-plugin -TEST_PLUGIN_GIT_REPO=https://github.com/dokku/${TEST_PLUGIN_NAME}.git -TEST_PLUGIN_LOCAL_REPO="$(mktemp -d)/$TEST_PLUGIN_NAME" - -clone_test_plugin() { - git clone "$TEST_PLUGIN_GIT_REPO" "$TEST_PLUGIN_LOCAL_REPO" -} setup() { global_setup clone_test_plugin } -remove_test_plugin() { - rm -rf $PLUGIN_ENABLED_PATH/$TEST_PLUGIN_NAME $PLUGIN_AVAILABLE_PATH/$TEST_PLUGIN_NAME - rm -rf $TEST_PLUGIN_LOCAL_REPO -} - teardown() { remove_test_plugin || true global_teardown diff --git a/tests/unit/ps-general-2.bats b/tests/unit/ps-general-2.bats index 70a869e4302..379d7727d04 100644 --- a/tests/unit/ps-general-2.bats +++ b/tests/unit/ps-general-2.bats @@ -111,7 +111,7 @@ teardown() { echo "output: $output" echo "status: $status" assert_failure - assert_output_contains "Could not start due to" + assert_output_contains "Could not start due to" 2 run /bin/bash -c "dokku ps:set $TEST_APP procfile-path second.Procfile" echo "output: $output" diff --git a/tests/unit/scheduler-docker-local.bats b/tests/unit/scheduler-docker-local.bats index ba3199a3bb3..d14ea9ed415 100644 --- a/tests/unit/scheduler-docker-local.bats +++ b/tests/unit/scheduler-docker-local.bats @@ -119,3 +119,59 @@ teardown() { assert_success assert_output_contains "docker-init" 0 } + +@test "(scheduler-docker-local) publish ports" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run deploy_app + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Deploys may fail when publishing ports and scaling to multiple containers" 0 + assert_output_contains "Deploys may fail when publishing ports and enabling zero downtime" 0 + + run /bin/bash -c "dokku docker-options:add $TEST_APP deploy '--publish 5000:5000'" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:scale --skip-deploy $TEST_APP web=2" + echo "output: $output" + echo "status: $status" + assert_success + + # the expected output will be seen twice due to how parallel re-outputs stderr in its own output... + run /bin/bash -c "dokku ps:rebuild $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Deploys may fail when publishing ports and scaling to multiple containers" 2 + assert_output_contains "Deploys may fail when publishing ports and enabling zero downtime" 0 + + run /bin/bash -c "dokku ps:scale --skip-deploy $TEST_APP web=1" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:rebuild $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Deploys may fail when publishing ports and scaling to multiple containers" 0 + assert_output_contains "Deploys may fail when publishing ports and enabling zero downtime" 2 + + run /bin/bash -c "dokku checks:disable $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:rebuild $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Deploys may fail when publishing ports and scaling to multiple containers" 0 + assert_output_contains "Deploys may fail when publishing ports and enabling zero downtime" 0 +} diff --git a/tests/unit/scheduler-k3s-1.bats b/tests/unit/scheduler-k3s-1.bats index b8a62e8d876..f9fbcd45578 100644 --- a/tests/unit/scheduler-k3s-1.bats +++ b/tests/unit/scheduler-k3s-1.bats @@ -32,3 +32,33 @@ teardown_() { INGRESS_CLASS=nginx TAINT_SCHEDULING=true install_k3s } + +@test "(scheduler-k3s) deploy dockerfile exposed port" { + if [[ -z "$DOCKERHUB_USERNAME" ]] || [[ -z "$DOCKERHUB_TOKEN" ]]; then + skip "skipping due to missing docker.io credentials DOCKERHUB_USERNAME:DOCKERHUB_TOKEN" + fi + + INGRESS_CLASS=nginx install_k3s + + run /bin/bash -c "dokku apps:create $TEST_APP" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku domains:set $TEST_APP $TEST_APP.dokku.me" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku git:from-image $TEST_APP metabase/metabase:latest" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "sleep 30" + echo "output: $output" + echo "status: $status" + assert_success + + assert_http_localhost_response_contains "http" "$TEST_APP.dokku.me" "80" "" "Metabase" +} diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index 831f94aa95d..cb5af752b1f 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -15,6 +15,9 @@ UUID=$(uuidgen) TEST_APP="rdmtestapp-${UUID}" TEST_NETWORK="test-network-${UUID}" SKIPPED_TEST_ERR_MSG="previous test failed! skipping remaining tests..." +TEST_PLUGIN_NAME=smoke-test-plugin +TEST_PLUGIN_GIT_REPO=https://github.com/dokku/${TEST_PLUGIN_NAME}.git +TEST_PLUGIN_LOCAL_REPO="$(mktemp -d)/$TEST_PLUGIN_NAME" # global setup() and teardown() # skips remaining tests on first failure @@ -45,6 +48,15 @@ cleanup_containers() { fi } +clone_test_plugin() { + git clone "$TEST_PLUGIN_GIT_REPO" "$TEST_PLUGIN_LOCAL_REPO" +} + +remove_test_plugin() { + rm -rf "${PLUGIN_ENABLED_PATH:?}/$TEST_PLUGIN_NAME" "${PLUGIN_AVAILABLE_PATH:?}/$TEST_PLUGIN_NAME" + rm -rf "$TEST_PLUGIN_LOCAL_REPO" +} + # test functions flunk() { { @@ -238,6 +250,22 @@ assert_http_localhost_response() { fi } +assert_http_localhost_response_contains() { + local scheme="$1" domain="$2" port="${3:-80}" path="${4:-}" content="${5:-}" status_code="${6:-200}" + run curl --connect-to "$domain:$port:localhost:$port" -kSso /dev/null -w "%{http_code}" "$scheme://$domain:$port$path" + echo "curl: curl --connect-to $domain:$port:localhost:$port -kSso /dev/null -w %{http_code} $scheme://$domain:$port$path" + echo "output: $output" + echo "status: $status" + assert_output "$status_code" + + if [[ -n "$content" ]]; then + run curl --connect-to "$domain:$port:localhost:$port" -kSs "$scheme://$domain:$port$path" + echo "output: $output" + echo "status: $status" + assert_output_contains "$content" + fi +} + assert_ssl_domain() { local domain=$1 assert_app_domain "${domain}" diff --git a/tests/unit/traefik.bats b/tests/unit/traefik.bats index 835b974cda1..efebbedcd4d 100644 --- a/tests/unit/traefik.bats +++ b/tests/unit/traefik.bats @@ -140,34 +140,6 @@ teardown() { assert_success } -@test "(traefik) traefik:set priority" { - run /bin/bash -c "dokku proxy:set $TEST_APP traefik" - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "dokku traefik:set $TEST_APP priority 12345" - echo "output: $output" - echo "status: $status" - assert_success - - run deploy_app - echo "output: $output" - echo "status: $status" - assert_success - - run /bin/bash -c "docker inspect $TEST_APP.web.1 --format '{{ index .Config.Labels \"traefik.http.services.$TEST_APP-web-http.loadbalancer.server.port\" }}'" - echo "output: $output" - echo "status: $status" - assert_output "5000" - - run /bin/bash -c "docker inspect $TEST_APP.web.1 --format '{{ index .Config.Labels \"traefik.http.routers.$TEST_APP-web-http.priority\" }}'" - echo "output: $output" - echo "status: $status" - assert_success - assert_output "12345" -} - @test "(traefik) ssl" { run /bin/bash -c "dokku builder-herokuish:set $TEST_APP allowed true" echo "output: $output"