From 28c9f42a259b810508e81a3ca2d9ea8c1f9d2e10 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Tue, 29 Dec 2020 23:56:10 -0500 Subject: [PATCH] refactor: parallelize report commands This will make reports a bit faster to run, and is safe to do as reports should not change app state. --- plugins/apps/{apps.go => report.go} | 31 +++++-- .../buildpacks/{buildpacks.go => report.go} | 19 ++-- plugins/common/parallel.go | 24 +++++ plugins/network/network.go | 18 ---- plugins/network/report.go | 42 +++++++++ plugins/proxy/proxy.go | 27 ------ plugins/proxy/report.go | 47 ++++++++++ plugins/ps/ps.go | 59 ------------ plugins/ps/report.go | 90 +++++++++++++++++++ 9 files changed, 237 insertions(+), 120 deletions(-) rename plugins/apps/{apps.go => report.go} (63%) rename plugins/buildpacks/{buildpacks.go => report.go} (72%) create mode 100644 plugins/network/report.go create mode 100644 plugins/proxy/report.go create mode 100644 plugins/ps/report.go diff --git a/plugins/apps/apps.go b/plugins/apps/report.go similarity index 63% rename from plugins/apps/apps.go rename to plugins/apps/report.go index 28b0c96ef..ae0a9ba6c 100644 --- a/plugins/apps/apps.go +++ b/plugins/apps/report.go @@ -12,23 +12,36 @@ func ReportSingleApp(appName, infoFlag string) error { return err } + flags := map[string]common.ReportFunc{ + "--app-dir": reportDir, + "--app-deploy-source": reportDeploySource, + "--app-locked": reportLocked, + } + + trimPrefix := false + uppercaseFirstCharacter := true + infoFlags := common.CollectReport(appName, flags) + return common.ReportSingleApp("app", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) +} + +func reportDir(appName string) string { + return common.AppRoot(appName) +} + +func reportDeploySource(appName string) string { deploySource := "" if b, err := common.PlugnTriggerSetup("deploy-source", []string{appName}...).SetInput("").Output(); err != nil { deploySource = strings.TrimSpace(string(b[:])) } + return deploySource +} + +func reportLocked(appName string) string { locked := "false" if appIsLocked(appName) { locked = "true" } - infoFlags := map[string]string{ - "--app-dir": common.AppRoot(appName), - "--app-deploy-source": deploySource, - "--app-locked": locked, - } - - trimPrefix := false - uppercaseFirstCharacter := true - return common.ReportSingleApp("app", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return locked } diff --git a/plugins/buildpacks/buildpacks.go b/plugins/buildpacks/report.go similarity index 72% rename from plugins/buildpacks/buildpacks.go rename to plugins/buildpacks/report.go index b8e5e76c2..b1e593a2b 100644 --- a/plugins/buildpacks/buildpacks.go +++ b/plugins/buildpacks/report.go @@ -12,16 +12,21 @@ func ReportSingleApp(appName, infoFlag string) error { return err } - buildpacks, err := common.PropertyListGet("buildpacks", appName, "buildpacks") - if err != nil { - return err - } - - infoFlags := map[string]string{ - "--buildpacks-list": strings.Join(buildpacks, ","), + flags := map[string]common.ReportFunc{ + "--buildpacks-list": reportList, } trimPrefix := false uppercaseFirstCharacter := true + infoFlags := common.CollectReport(appName, flags) return common.ReportSingleApp("buildpacks", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) } + +func reportList(appName string) string { + buildpacks, err := common.PropertyListGet("buildpacks", appName, "buildpacks") + if err != nil { + return "" + } + + return strings.Join(buildpacks, ",") +} diff --git a/plugins/common/parallel.go b/plugins/common/parallel.go index 7ac6e66bc..3258ed56d 100644 --- a/plugins/common/parallel.go +++ b/plugins/common/parallel.go @@ -132,3 +132,27 @@ func createParallelWorkerPool(jobs chan string, results chan parallelCommandResu wg.Wait() close(results) } + +type ReportFunc func(string) string + +func CollectReport(appName string, flags map[string]ReportFunc) map[string]string { + var sm sync.Map + var wg sync.WaitGroup + for flag, fn := range flags { + wg.Add(1) + go func(flag string, fn ReportFunc) { + defer wg.Done() + s := fn(appName) + sm.Store(flag, s) + }(flag, fn) + } + wg.Wait() + + infoFlags := map[string]string{} + sm.Range(func(key interface{}, value interface{}) bool { + infoFlags[key.(string)] = value.(string) + return true + }) + + return infoFlags +} diff --git a/plugins/network/network.go b/plugins/network/network.go index 9f141d53b..e2f36ac47 100644 --- a/plugins/network/network.go +++ b/plugins/network/network.go @@ -206,21 +206,3 @@ func ClearNetworkConfig(appName string) bool { } return success } - -// ReportSingleApp is an internal function that displays the app report for one or more apps -func ReportSingleApp(appName, infoFlag string) error { - if err := common.VerifyAppName(appName); err != nil { - return err - } - - infoFlags := map[string]string{ - "--network-bind-all-interfaces": common.PropertyGet("network", appName, "bind-all-interfaces"), - "--network-attach-post-create": common.PropertyGet("network", appName, "attach-post-create"), - "--network-attach-post-deploy": common.PropertyGet("network", appName, "attach-post-deploy"), - "--network-web-listeners": strings.Join(GetListeners(appName, "web"), " "), - } - - trimPrefix := false - uppercaseFirstCharacter := true - return common.ReportSingleApp("network", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) -} diff --git a/plugins/network/report.go b/plugins/network/report.go new file mode 100644 index 000000000..a3bccdb02 --- /dev/null +++ b/plugins/network/report.go @@ -0,0 +1,42 @@ +package network + +import ( + "strings" + + "github.com/dokku/dokku/plugins/common" +) + +// ReportSingleApp is an internal function that displays the app report for one or more apps +func ReportSingleApp(appName, infoFlag string) error { + if err := common.VerifyAppName(appName); err != nil { + return err + } + + flags := map[string]common.ReportFunc{ + "--network-bind-all-interfaces": reportBindAllInterfaces, + "--network-attach-post-create": reportAttachPostCreate, + "--network-attach-post-deploy": reportAttachPostDeploy, + "--network-web-listeners": reportWebListeners, + } + + trimPrefix := false + uppercaseFirstCharacter := true + infoFlags := common.CollectReport(appName, flags) + return common.ReportSingleApp("network", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) +} + +func reportBindAllInterfaces(appName string) string { + return common.PropertyGet("network", appName, "bind-all-interfaces") +} + +func reportAttachPostCreate(appName string) string { + return common.PropertyGet("network", appName, "attach-post-create") +} + +func reportAttachPostDeploy(appName string) string { + return common.PropertyGet("network", appName, "attach-post-deploy") +} + +func reportWebListeners(appName string) string { + return strings.Join(GetListeners(appName, "web"), " ") +} diff --git a/plugins/proxy/proxy.go b/plugins/proxy/proxy.go index 3da647658..cec4abce5 100644 --- a/plugins/proxy/proxy.go +++ b/plugins/proxy/proxy.go @@ -43,33 +43,6 @@ func IsAppProxyEnabled(appName string) bool { return proxyEnabled } -// ReportSingleApp is an internal function that displays the app report for one or more apps -func ReportSingleApp(appName string, infoFlag string) error { - if err := common.VerifyAppName(appName); err != nil { - return err - } - - proxyEnabled := "false" - if IsAppProxyEnabled(appName) { - proxyEnabled = "true" - } - - var proxyPortMap []string - for _, portMap := range getProxyPortMap(appName) { - proxyPortMap = append(proxyPortMap, portMap.String()) - } - - infoFlags := map[string]string{ - "--proxy-enabled": proxyEnabled, - "--proxy-type": getAppProxyType(appName), - "--proxy-port-map": strings.Join(proxyPortMap, " "), - } - - trimPrefix := false - uppercaseFirstCharacter := true - return common.ReportSingleApp("proxy", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) -} - func addProxyPorts(appName string, proxyPortMap []PortMap) error { allPortMaps := getProxyPortMap(appName) allPortMaps = append(allPortMaps, proxyPortMap...) diff --git a/plugins/proxy/report.go b/plugins/proxy/report.go new file mode 100644 index 000000000..0791eb273 --- /dev/null +++ b/plugins/proxy/report.go @@ -0,0 +1,47 @@ +package proxy + +import ( + "strings" + + "github.com/dokku/dokku/plugins/common" +) + +// ReportSingleApp is an internal function that displays the app report for one or more apps +func ReportSingleApp(appName string, infoFlag string) error { + if err := common.VerifyAppName(appName); err != nil { + return err + } + + flags := map[string]common.ReportFunc{ + "--proxy-enabled": reportEnabled, + "--proxy-type": reportType, + "--proxy-port-map": reportPortMap, + } + + trimPrefix := false + uppercaseFirstCharacter := true + infoFlags := common.CollectReport(appName, flags) + return common.ReportSingleApp("proxy", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) +} + +func reportEnabled(appName string) string { + proxyEnabled := "false" + if IsAppProxyEnabled(appName) { + proxyEnabled = "true" + } + + return proxyEnabled +} + +func reportType(appName string) string { + return getAppProxyType(appName) +} + +func reportPortMap(appName string) string { + var proxyPortMap []string + for _, portMap := range getProxyPortMap(appName) { + proxyPortMap = append(proxyPortMap, portMap.String()) + } + + return strings.Join(proxyPortMap, " ") +} diff --git a/plugins/ps/ps.go b/plugins/ps/ps.go index a82ca6a1a..84fc40996 100644 --- a/plugins/ps/ps.go +++ b/plugins/ps/ps.go @@ -2,7 +2,6 @@ package ps import ( "fmt" - "strconv" "strings" "github.com/dokku/dokku/plugins/common" @@ -24,64 +23,6 @@ func Rebuild(appName string) error { return common.PlugnTrigger("receive-app", []string{appName}...) } -// ReportSingleApp is an internal function that displays the ps report for one or more apps -func ReportSingleApp(appName, infoFlag string) error { - if err := common.VerifyAppName(appName); err != nil { - return err - } - - policy, _ := getRestartPolicy(appName) - if policy == "" { - policy = DefaultProperties["restart-policy"] - } - - canScale := "false" - if canScaleApp(appName) { - canScale = "true" - } - - deployed := "false" - if common.IsDeployed(appName) { - deployed = "true" - } - - runningState := getRunningState(appName) - - count, err := getProcessCount(appName) - if err != nil { - count = -1 - } - - b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_RESTORE"}...) - restore := strings.TrimSpace(string(b[:])) - if restore == "0" { - restore = "false" - } else { - restore = "true" - } - - infoFlags := map[string]string{ - "--deployed": deployed, - "--processes": strconv.Itoa(count), - "--ps-can-scale": canScale, - "--ps-restart-policy": policy, - "--restore": restore, - "--running": runningState, - } - - scheduler := common.GetAppScheduler(appName) - if scheduler == "docker-local" { - processStatus := getProcessStatus(appName) - for process, value := range processStatus { - infoFlags[fmt.Sprintf("--status-%s", process)] = value - } - } - - trimPrefix := false - uppercaseFirstCharacter := true - return common.ReportSingleApp("ps", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) -} - // Restart restarts the app func Restart(appName string) error { if !common.IsDeployed(appName) { diff --git a/plugins/ps/report.go b/plugins/ps/report.go new file mode 100644 index 000000000..34bd36f47 --- /dev/null +++ b/plugins/ps/report.go @@ -0,0 +1,90 @@ +package ps + +import ( + "fmt" + "strconv" + "strings" + + "github.com/dokku/dokku/plugins/common" +) + +// ReportSingleApp is an internal function that displays the ps report for one or more apps +func ReportSingleApp(appName, infoFlag string) error { + if err := common.VerifyAppName(appName); err != nil { + return err + } + + flags := map[string]common.ReportFunc{ + "--deployed": reportDeployed, + "--processes": reportProcesses, + "--ps-can-scale": reportCanScale, + "--ps-restart-policy": reportRestartPolicy, + "--restore": reportRestore, + "--running": reportRunningState, + } + + infoFlags := common.CollectReport(appName, flags) + scheduler := common.GetAppScheduler(appName) + if scheduler == "docker-local" { + processStatus := getProcessStatus(appName) + for process, value := range processStatus { + infoFlags[fmt.Sprintf("--status-%s", process)] = value + } + } + + trimPrefix := false + uppercaseFirstCharacter := true + return common.ReportSingleApp("ps", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) +} + +func reportCanScale(appName string) string { + canScale := "false" + if canScaleApp(appName) { + canScale = "true" + } + + return canScale +} + +func reportDeployed(appName string) string { + deployed := "false" + if common.IsDeployed(appName) { + deployed = "true" + } + + return deployed +} + +func reportProcesses(appName string) string { + count, err := getProcessCount(appName) + if err != nil { + count = -1 + } + + return strconv.Itoa(count) +} + +func reportRestartPolicy(appName string) string { + policy, _ := getRestartPolicy(appName) + if policy == "" { + policy = DefaultProperties["restart-policy"] + } + + return policy +} + +func reportRestore(appName string) string { + b, _ := common.PlugnTriggerOutput("config-get", []string{appName, "DOKKU_APP_RESTORE"}...) + restore := strings.TrimSpace(string(b[:])) + if restore == "0" { + restore = "false" + } else { + restore = "true" + } + + return restore +} + +func reportRunningState(appName string) string { + return getRunningState(appName) +}