From ad732bd42bd898f2d1da378c4dd0e9ae1492ed62 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Wed, 4 Oct 2017 00:48:02 -0400 Subject: [PATCH] feat: add network:report command --- docs/networking/network.md | 39 +++++++++++ plugins/common/common.go | 9 +++ plugins/common/log.go | 2 +- plugins/network/Makefile | 5 +- plugins/network/network.go | 18 +++++ plugins/network/src/commands/commands.go | 1 + .../network/src/subcommands/report/report.go | 67 +++++++++++++++++++ .../network-get-listeners.go | 17 +---- 8 files changed, 141 insertions(+), 17 deletions(-) create mode 100644 plugins/network/src/subcommands/report/report.go diff --git a/docs/networking/network.md b/docs/networking/network.md index a1fea00ed..810b39ecc 100644 --- a/docs/networking/network.md +++ b/docs/networking/network.md @@ -3,6 +3,7 @@ > New as of 0.11.0 ``` +network:report [] [] # Displays a network report for one or more apps network:rebuild # Rebuilds network settings for an app network:rebuildall # Rebuild network settings for all apps network:set () # Set or clear a network property for an app @@ -83,3 +84,41 @@ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES d6499edb0edb dokku/node-js-app:latest "/bin/bash -c '/star About a minute ago Up About a minute 0.0.0.0:49153->5000/tcp node-js-app.web.1 ``` + +### Displaying network reports about an app + +You can get a report about the app's network status using the `network:report` command: + +```shell +dokku network:report +``` + +``` +=====> node-js-app network information + Network bind all interfaces: false + Network listeners: 172.17.0.1:5000 +=====> python-sample network information + Network bind all interfaces: false + Network listeners: 172.17.0.2:5000 +=====> ruby-sample network information + Network bind all interfaces: true + Network listeners: +``` + +You can run the command for a specific app also. + +```shell +dokku network:report node-js-app +``` + +``` +=====> node-js-app network information + Network bind all interfaces: false + Network listeners: 172.17.0.1:5000 +``` + +You can pass flags which will output only the value of the specific information you want. For example: + +```shell +dokku network:report node-js-app --network-bind-all-interfaces +``` diff --git a/plugins/common/common.go b/plugins/common/common.go index fcaceadaa..d8faf3510 100644 --- a/plugins/common/common.go +++ b/plugins/common/common.go @@ -8,6 +8,7 @@ import ( "os/exec" "regexp" "strings" + "unicode" sh "github.com/codeskyblue/go-sh" ) @@ -311,6 +312,14 @@ func ToBool(s string) bool { return s == "true" } +// UcFirst uppercases the first character in a string +func UcFirst(str string) string { + for i, v := range str { + return string(unicode.ToUpper(v)) + str[i+1:] + } + return "" +} + // VerifyAppName verifies app name format and app existence" func VerifyAppName(appName string) (err error) { if appName == "" { diff --git a/plugins/common/log.go b/plugins/common/log.go index f91ee0c69..dd3992e83 100644 --- a/plugins/common/log.go +++ b/plugins/common/log.go @@ -31,7 +31,7 @@ func LogInfo2(text string) { // LogInfo2Quiet is the info2 header formatter (with quiet option) func LogInfo2Quiet(text string) { - if os.Getenv("DOKKU_QUIET_OUTPUT") != "" { + if os.Getenv("DOKKU_QUIET_OUTPUT") == "" { LogInfo2(text) } } diff --git a/plugins/network/Makefile b/plugins/network/Makefile index c435e1d26..c3017156f 100644 --- a/plugins/network/Makefile +++ b/plugins/network/Makefile @@ -8,7 +8,7 @@ build-in-docker: clean bash -c "make build" || exit $$? build: commands subcommands triggers -subcommands: subcommands/rebuild subcommands/rebuildall subcommands/set +subcommands: subcommands/rebuild subcommands/rebuildall subcommands/report subcommands/set triggers: install network-build-config network-compute-ports network-config-exists network-get-ipaddr network-get-listeners network-get-port network-get-property network-write-ipaddr network-write-port post-create post-delete commands: **/**/commands.go go build -a -o commands src/commands/commands.go @@ -19,6 +19,9 @@ subcommands/rebuild: **/**/**/rebuild.go subcommands/rebuildall: **/**/**/rebuildall.go go build -a -o subcommands/rebuildall src/subcommands/rebuildall/rebuildall.go +subcommands/report: **/**/**/report.go + go build -a -o subcommands/report src/subcommands/report/report.go + subcommands/set: **/**/**/set.go go build -a -o subcommands/set src/subcommands/set/set.go diff --git a/plugins/network/network.go b/plugins/network/network.go index c5e117c54..08a8d21e1 100644 --- a/plugins/network/network.go +++ b/plugins/network/network.go @@ -2,6 +2,7 @@ package network import ( "fmt" + "path/filepath" "strconv" "strings" @@ -148,6 +149,23 @@ func GetDefaultValue(property string) (value string) { return } +// GetListeners returns a string array of app listeners +func GetListeners(appName string) []string { + dokkuRoot := common.MustGetEnv("DOKKU_ROOT") + appRoot := strings.Join([]string{dokkuRoot, appName}, "/") + + files, _ := filepath.Glob(appRoot + "/IP.web.*") + + var listeners []string + for _, ipfile := range files { + portfile := strings.Replace(ipfile, "/IP.web.", "/PORT.web.", 1) + ipAddress := common.ReadFirstLine(ipfile) + port := common.ReadFirstLine(portfile) + listeners = append(listeners, fmt.Sprintf("%s:%s", ipAddress, port)) + } + return listeners +} + // HasNetworkConfig returns whether the network configuration for a given app exists func HasNetworkConfig(appName string) bool { appRoot := strings.Join([]string{common.MustGetEnv("DOKKU_ROOT"), appName}, "/") diff --git a/plugins/network/src/commands/commands.go b/plugins/network/src/commands/commands.go index 308fab652..61ec0efba 100644 --- a/plugins/network/src/commands/commands.go +++ b/plugins/network/src/commands/commands.go @@ -18,6 +18,7 @@ Manages network settings for an app Additional commands:` helpContent = ` + network:report [] [], Displays a network report for one or more apps network:rebuild , Rebuilds network settings for an app network:rebuildall, Rebuild network settings for all apps network:set (), Set or clear a network property for an app diff --git a/plugins/network/src/subcommands/report/report.go b/plugins/network/src/subcommands/report/report.go new file mode 100644 index 000000000..382245cb8 --- /dev/null +++ b/plugins/network/src/subcommands/report/report.go @@ -0,0 +1,67 @@ +package main + +import ( + "flag" + "fmt" + "os" + "reflect" + "strings" + + "github.com/dokku/dokku/plugins/common" + "github.com/dokku/dokku/plugins/network" +) + +func reportSingleApp(appName, infoFlag string) { + infoFlags := map[string]string{ + "--network-bind-all-interfaces": common.PropertyGet("network", appName, "bind-all-interfaces"), + "--network-listeners": strings.Join(network.GetListeners(appName), " "), + } + + if len(infoFlag) == 0 { + common.LogInfo2Quiet(fmt.Sprintf("%s network information", appName)) + for k, v := range infoFlags { + key := common.UcFirst(strings.Replace(strings.TrimPrefix(k, "--"), "-", " ", -1)) + common.LogVerbose(fmt.Sprintf("%s: %s", key, v)) + } + return + } + + for k, v := range infoFlags { + if infoFlag == k { + fmt.Fprintln(os.Stdout, v) + return + } + } + + keys := reflect.ValueOf(infoFlags).MapKeys() + strkeys := make([]string, len(keys)) + for i := 0; i < len(keys); i++ { + strkeys[i] = keys[i].String() + } + common.LogFail(fmt.Sprintf("Invalid flag passed, valid flags: %s", strings.Join(strkeys, ", "))) +} + +// set or clear a network property for an app +func main() { + flag.Parse() + appName := flag.Arg(1) + infoFlag := flag.Arg(2) + + if strings.HasPrefix(appName, "--") { + infoFlag = appName + appName = "" + } + + if len(appName) == 0 { + apps, err := common.DokkuApps() + if err != nil { + return + } + for _, appName := range apps { + reportSingleApp(appName, infoFlag) + } + return + } + + reportSingleApp(appName, infoFlag) +} diff --git a/plugins/network/src/triggers/network-get-listeners/network-get-listeners.go b/plugins/network/src/triggers/network-get-listeners/network-get-listeners.go index 6ef0508aa..9c999fe4e 100644 --- a/plugins/network/src/triggers/network-get-listeners/network-get-listeners.go +++ b/plugins/network/src/triggers/network-get-listeners/network-get-listeners.go @@ -4,10 +4,9 @@ import ( "flag" "fmt" "os" - "path/filepath" "strings" - "github.com/dokku/dokku/plugins/common" + "github.com/dokku/dokku/plugins/network" ) // returns the listeners (host:port combinations) for a given app container @@ -15,18 +14,6 @@ func main() { flag.Parse() appName := flag.Arg(0) - dokkuRoot := common.MustGetEnv("DOKKU_ROOT") - appRoot := strings.Join([]string{dokkuRoot, appName}, "/") - - files, _ := filepath.Glob(appRoot + "/IP.web.*") - - var listeners []string - for _, ipfile := range files { - portfile := strings.Replace(ipfile, "/IP.web.", "/PORT.web.", 1) - ipAddress := common.ReadFirstLine(ipfile) - port := common.ReadFirstLine(portfile) - listeners = append(listeners, fmt.Sprintf("%s:%s", ipAddress, port)) - } - + listeners := network.GetListeners(appName) fmt.Fprint(os.Stdout, strings.Join(listeners, " ")) }