diff --git a/docs/development/plugin-triggers.md b/docs/development/plugin-triggers.md index 37acb4e32..61d05c603 100644 --- a/docs/development/plugin-triggers.md +++ b/docs/development/plugin-triggers.md @@ -1947,25 +1947,6 @@ DOKKU_SCHEDULER="$1"; APP="$2"; # TODO ``` -### `scheduler-is-deployed` - -> Warning: The scheduler plugin trigger apis are under development and may change -> between minor releases until the 1.0 release. - -- Description: Allows you to check if an app has been deployed -- Invoked by: `dokku ps:rebuild` -- Arguments: `$DOKKU_SCHEDULER $APP` -- Example: - -```shell -#!/usr/bin/env bash - -set -eo pipefail; [[ $DOKKU_TRACE ]] && set -x -DOKKU_SCHEDULER="$1"; APP="$2"; - -# TODO -``` - ### `scheduler-logs` > Warning: The scheduler plugin trigger apis are under development and may change diff --git a/plugins/app-json/go.sum b/plugins/app-json/go.sum index 3599be52d..9fdb858d0 100644 --- a/plugins/app-json/go.sum +++ b/plugins/app-json/go.sum @@ -6,5 +6,6 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3 h1:utdYOikI1XjNtTFGCwSM6OmFJblU4ld4gACoJsbadJg= github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/plugins/common/Makefile b/plugins/common/Makefile index 81bfdd798..e3823d2da 100644 --- a/plugins/common/Makefile +++ b/plugins/common/Makefile @@ -1,10 +1,17 @@ -BUILD = prop +TRIGGERS = triggers/core-post-deploy triggers/install triggers/post-delete +BUILD = prop common triggers PLUGIN_NAME = common clean-prop: rm -rf prop +clean-common: + rm -rf common + prop: clean-prop **/**/prop.go go build -ldflags="-s -w" $(GO_ARGS) -o prop src/prop/prop.go +common: clean-common **/**/common.go + go build -ldflags="-s -w" $(GO_ARGS) -o common src/common/common.go + include ../../common.mk diff --git a/plugins/common/common.go b/plugins/common/common.go index a4b1be044..59c009e42 100644 --- a/plugins/common/common.go +++ b/plugins/common/common.go @@ -20,6 +20,16 @@ import ( type errfunc func() error +var ( + // DefaultProperties is a map of all valid common properties with corresponding default property values + DefaultProperties = map[string]string{ + "deployed": "false", + } + + // GlobalProperties is a map of all valid global common properties + GlobalProperties = map[string]bool{} +) + // AppRoot returns the app root path func AppRoot(appName string) string { dokkuRoot := MustGetEnv("DOKKU_ROOT") @@ -279,9 +289,19 @@ func GetAppImageName(appName, imageTag, imageRepo string) (imageName string) { // IsDeployed returns true if given app has a running container func IsDeployed(appName string) bool { - scheduler := GetAppScheduler(appName) - _, err := PlugnTriggerOutput("scheduler-is-deployed", []string{scheduler, appName}...) - return err == nil + deployed := PropertyGetDefault("common", appName, "deployed", "") + if deployed == "" { + deployed = "false" + scheduler := GetAppScheduler(appName) + _, err := PlugnTriggerOutput("scheduler-is-deployed", []string{scheduler, appName}...) + if err == nil { + deployed = "true" + } + + CommandPropertySet("common", appName, "deployed", deployed, DefaultProperties, GlobalProperties) + } + + return deployed == "true" } // MustGetEnv returns env variable or fails if it's not set diff --git a/plugins/common/functions b/plugins/common/functions index 93002186a..b5838af23 100755 --- a/plugins/common/functions +++ b/plugins/common/functions @@ -577,10 +577,8 @@ get_app_running_container_types() { is_deployed() { declare desc="return 0 if given app has a running container" local APP="$1" - source "$PLUGIN_AVAILABLE_PATH/config/functions" - local DOKKU_SCHEDULER=$(get_app_scheduler "$APP") - plugn trigger scheduler-is-deployed "$DOKKU_SCHEDULER" "$APP" + "$PLUGIN_CORE_AVAILABLE_PATH/common/common" --quiet is-deployed "$APP" } is_container_running() { diff --git a/plugins/common/go.mod b/plugins/common/go.mod index 6fb4e0764..8fc5569f7 100644 --- a/plugins/common/go.mod +++ b/plugins/common/go.mod @@ -6,5 +6,6 @@ require ( github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3 + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sync v0.0.0-20201207232520-09787c993a3a ) diff --git a/plugins/common/go.sum b/plugins/common/go.sum index aa1fb3e7e..58c904707 100644 --- a/plugins/common/go.sum +++ b/plugins/common/go.sum @@ -4,5 +4,7 @@ github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4qu github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27/go.mod h1:VQx0hjo2oUeQkQUET7wRwradO6f+fN5jzXgB/zROxxE= github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3 h1:utdYOikI1XjNtTFGCwSM6OmFJblU4ld4gACoJsbadJg= github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/plugins/common/src/common/common.go b/plugins/common/src/common/common.go new file mode 100644 index 000000000..1562b1b2e --- /dev/null +++ b/plugins/common/src/common/common.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "os" + + "github.com/dokku/dokku/plugins/common" + flag "github.com/spf13/pflag" +) + +func main() { + quiet := flag.Bool("quiet", false, "--quiet: set DOKKU_QUIET_OUTPUT=1") + flag.Parse() + cmd := flag.Arg(0) + + if *quiet { + os.Setenv("DOKKU_QUIET_OUTPUT", "1") + } + + var err error + switch cmd { + case "is-deployed": + appName := flag.Arg(1) + if !common.IsDeployed(appName) { + err = fmt.Errorf("App %v not deployed", appName) + } + default: + err = fmt.Errorf("Invalid common command call: %v", cmd) + } + + if err != nil { + common.LogFailQuiet(err.Error()) + } +} diff --git a/plugins/common/src/triggers/triggers.go b/plugins/common/src/triggers/triggers.go new file mode 100644 index 000000000..e5b342297 --- /dev/null +++ b/plugins/common/src/triggers/triggers.go @@ -0,0 +1,35 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + + "github.com/dokku/dokku/plugins/common" +) + +// main entrypoint to all triggers +func main() { + parts := strings.Split(os.Args[0], "/") + trigger := parts[len(parts)-1] + flag.Parse() + + var err error + switch trigger { + case "core-post-deploy": + appName := flag.Arg(0) + err = common.TriggerCorePostDeploy(appName) + case "install": + err = common.TriggerInstall() + case "post-delete": + appName := flag.Arg(0) + err = common.TriggerPostDelete(appName) + default: + common.LogFail(fmt.Sprintf("Invalid plugin trigger call: %s", trigger)) + } + + if err != nil { + common.LogFail(err.Error()) + } +} diff --git a/plugins/common/triggers.go b/plugins/common/triggers.go new file mode 100644 index 000000000..b20c655b3 --- /dev/null +++ b/plugins/common/triggers.go @@ -0,0 +1,39 @@ +package common + +import ( + "fmt" + "os" +) + +// TriggerCorePostDeploy associates the container with a specified network +func TriggerCorePostDeploy(appName string) error { + quiet := os.Getenv("DOKKU_QUIET_OUTPUT") + os.Setenv("DOKKU_QUIET_OUTPUT", "1") + CommandPropertySet("common", appName, "deployed", "true", DefaultProperties, GlobalProperties) + os.Setenv("DOKKU_QUIET_OUTPUT", quiet) + return nil +} + +// TriggerInstall runs the install step for the common plugin +func TriggerInstall() error { + if err := PropertySetup("common"); err != nil { + return fmt.Errorf("Unable to install the common plugin: %s", err.Error()) + } + + apps, err := DokkuApps() + if err != nil { + return nil + } + + // migrate all is-deployed values from trigger to property + for _, appName := range apps { + IsDeployed(appName) + } + + return nil +} + +// TriggerPostDelete destroys the common property for a given app container +func TriggerPostDelete(appName string) error { + return PropertyDestroy("common", appName) +} diff --git a/tests/apps/python-console-only/Procfile b/tests/apps/python-console-only/Procfile new file mode 100644 index 000000000..81a711088 --- /dev/null +++ b/tests/apps/python-console-only/Procfile @@ -0,0 +1 @@ +console: python3 console.py diff --git a/tests/apps/python-console-only/console.py b/tests/apps/python-console-only/console.py new file mode 100644 index 000000000..f1a18139c --- /dev/null +++ b/tests/apps/python-console-only/console.py @@ -0,0 +1 @@ +print("Hello world!") diff --git a/tests/apps/python-console-only/null b/tests/apps/python-console-only/null new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/ps-general.bats b/tests/unit/ps-general.bats index 6c570e0ac..ebe719428 100644 --- a/tests/unit/ps-general.bats +++ b/tests/unit/ps-general.bats @@ -151,3 +151,50 @@ EOF echo "status: $status" assert_success } + +@test "(ps:scale) console-only app" { + run /bin/bash -c "dokku ps:scale $TEST_APP web=0 console=0" + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:report $TEST_APP --deployed" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "false" + + run deploy_app python-console-only + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku ps:report $TEST_APP --deployed" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "true" + + run /bin/bash -c "dokku --rm run $TEST_APP console" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Hello world!" + + run /bin/bash -c "dokku --rm run $TEST_APP printenv FOO" + echo "output: $output" + echo "status: $status" + assert_failure + + run /bin/bash -c "dokku --rm config:set $TEST_APP FOO=bar" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Releasing $TEST_APP" + + run /bin/bash -c "dokku --rm run $TEST_APP printenv FOO" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "bar" +}