fix: correctly handle is-deployed check
Previously, checking if an app was deployed actually checked if there were any running processes. This is not only incorrect, but also fails to take into account applications that do not have running processes and are only used for one-off commands. This fix migrates apps to the new "deployed" property which is set in core-post-deploy. The result is a slightly faster "deployed" check that is correct and allows non-scaled apps to actually work. Closes #4398
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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=
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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=
|
||||
|
||||
34
plugins/common/src/common/common.go
Normal file
34
plugins/common/src/common/common.go
Normal file
@@ -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())
|
||||
}
|
||||
}
|
||||
35
plugins/common/src/triggers/triggers.go
Normal file
35
plugins/common/src/triggers/triggers.go
Normal file
@@ -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())
|
||||
}
|
||||
}
|
||||
39
plugins/common/triggers.go
Normal file
39
plugins/common/triggers.go
Normal file
@@ -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)
|
||||
}
|
||||
1
tests/apps/python-console-only/Procfile
Normal file
1
tests/apps/python-console-only/Procfile
Normal file
@@ -0,0 +1 @@
|
||||
console: python3 console.py
|
||||
1
tests/apps/python-console-only/console.py
Normal file
1
tests/apps/python-console-only/console.py
Normal file
@@ -0,0 +1 @@
|
||||
print("Hello world!")
|
||||
0
tests/apps/python-console-only/null
Normal file
0
tests/apps/python-console-only/null
Normal file
@@ -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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user