From 2d841f47eba2f7d9ec220f9358b5a142402fb2e9 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Wed, 6 Jan 2021 22:45:47 -0500 Subject: [PATCH 01/12] fix: handle case where there are no apps --- plugins/logs/functions.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index 2587d3341..eba6b20af 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -151,11 +151,7 @@ func valueToConfig(appName string, value string) (vectorSink, error) { } func writeVectorConfig() error { - apps, err := common.DokkuApps() - if err != nil { - return err - } - + apps, _ := common.DokkuApps() data := vectorConfig{ Sources: map[string]vectorSource{}, Sinks: map[string]vectorSink{}, From 714b27f8a416dc1e3b70675f2d915f1f1f32d8e6 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 00:08:05 -0500 Subject: [PATCH 02/12] chore: quiet output of starting container We check if the container is running later, so there isn't a need for us to see the containerID here --- plugins/logs/functions.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index eba6b20af..3e02fff8a 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -75,6 +75,7 @@ func startVectorContainer(vectorImage string) error { "--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + ":/var/logs/dokku/apps", vectorImage, "--config", "/etc/vector/vector.json", "--watch-config"}, " ")) + cmd.ShowOutput = false if !cmd.Execute() { return errors.New("Unable to start vector container") From 441f7ab22afd4f24dc643f0cb334f14e571c3672 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 00:12:23 -0500 Subject: [PATCH 03/12] fix: pass 1 to --watch-config flag Apparently this needs a value... --- plugins/logs/functions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/logs/functions.go b/plugins/logs/functions.go index 3e02fff8a..ab616fe26 100644 --- a/plugins/logs/functions.go +++ b/plugins/logs/functions.go @@ -74,7 +74,7 @@ func startVectorContainer(vectorImage string) error { "--volume", "/var/run/docker.sock:/var/run/docker.sock", "--volume", common.MustGetEnv("DOKKU_LOGS_HOST_DIR") + ":/var/logs/dokku/apps", vectorImage, - "--config", "/etc/vector/vector.json", "--watch-config"}, " ")) + "--config", "/etc/vector/vector.json", "--watch-config", "1"}, " ")) cmd.ShowOutput = false if !cmd.Execute() { From 4bbee232d8974189e4302e218f2ab93b2a8b1747 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 00:12:44 -0500 Subject: [PATCH 04/12] fix: handle error cases in starting a new vector container --- plugins/common/docker.go | 13 +++++++++++++ plugins/logs/subcommands.go | 28 +++++++++++++++++++--------- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/plugins/common/docker.go b/plugins/common/docker.go index 492e754c6..42fe0cb93 100644 --- a/plugins/common/docker.go +++ b/plugins/common/docker.go @@ -7,6 +7,7 @@ import ( "io/ioutil" "os" "strings" + "time" "github.com/codeskyblue/go-sh" ) @@ -45,6 +46,18 @@ func ContainerExists(containerID string) bool { return true } +// ContainerWaitTilReady will wait timeout seconds and then check if a container is running +// returning an error if it is not running at the end of the timeout +func ContainerWaitTilReady(containerID string, timeout time.Duration) error { + time.Sleep(timeout) + + if !ContainerIsRunning(containerID) { + return fmt.Errorf("Container %s is not running", containerID) + } + + return nil +} + // CopyFromImage copies a file from named image to destination func CopyFromImage(appName string, image string, source string, destination string) error { if !VerifyImage(image) { diff --git a/plugins/logs/subcommands.go b/plugins/logs/subcommands.go index 06b25aaf8..483d1baeb 100644 --- a/plugins/logs/subcommands.go +++ b/plugins/logs/subcommands.go @@ -5,6 +5,7 @@ import ( "fmt" "path/filepath" "strconv" + "time" "github.com/dokku/dokku/plugins/common" ) @@ -108,19 +109,28 @@ func CommandVectorStart(vectorImage string) error { return err } - if !common.ContainerExists(vectorContainerName) { - return startVectorContainer(vectorImage) + if common.ContainerExists(vectorContainerName) { + if common.ContainerIsRunning(vectorContainerName) { + common.LogVerbose("Vector container is running") + return nil + } + + common.LogVerbose("Starting vector container") + if !common.ContainerStart(vectorContainerName) { + return errors.New("Unable to start vector container") + } + } else { + if err := startVectorContainer(vectorImage); err != nil { + return err + } } - if common.ContainerIsRunning(vectorContainerName) { - common.LogVerbose("Container already running") - return nil - } - - if !common.ContainerStart(vectorContainerName) { - return errors.New("Unable to start vector container") + common.LogVerbose("Waiting for 10 seconds") + if err := common.ContainerWaitTilReady(vectorContainerName, 10*time.Second); err != nil { + return errors.New("Vector container did not start properly, run logs:vector-logs for more details") } + common.LogVerbose("Vector container is running") return nil } From 2eae6c25af1e27af4fa01ddd47b7b31576987f48 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 00:14:43 -0500 Subject: [PATCH 05/12] tests: add test for logs:help --- tests/unit/logs.bats | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/unit/logs.bats diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats new file mode 100644 index 000000000..44eaef40a --- /dev/null +++ b/tests/unit/logs.bats @@ -0,0 +1,19 @@ +#!/usr/bin/env bats + +load test_helper + +setup() { + global_setup +} + +teardown() { + destroy_app + global_teardown +} + +@test "(network) logs:help" { + run /bin/bash -c "dokku logs:help" + echo "output: $output" + echo "status: $status" + assert_output_contains "Manage log integration for an app" +} From 081a44755ed903400fbf026c27dd21197b21d034 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:07:20 -0500 Subject: [PATCH 06/12] docs: fix examples to use correct property key --- docs/deployment/logs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 7c1a392a8..276e84319 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -101,7 +101,7 @@ The `vector` container will be stopped and removed from the system. If the conta #### Configuring a log sink -Vector uses the concept of log "sinks" to send logs to a given endpoint. Log sinks may be configured globally or on a per-app basis by specifying a `sink` in DSN form with the `logs:set` command. Specifying a sink value will reload any running vector container. +Vector uses the concept of log "sinks" to send logs to a given endpoint. Log sinks may be configured globally or on a per-app basis by specifying a `vector-sink` in DSN form with the `logs:set` command. Specifying a sink value will reload any running vector container. ```shell # setting the sink value in quotes is encouraged to avoid @@ -112,7 +112,7 @@ dokku logs:set node-js-app sink "console://?encoding[codec]=json" A sink may be removed by setting an empty value, which will also reload the running vector container. ```shell -dokku logs:set node-js-app sink +dokku logs:set node-js-app vector-sink ``` Only one sink may be specified on a per-app basis at a given time. @@ -120,13 +120,13 @@ Only one sink may be specified on a per-app basis at a given time. Log sinks can also be specified globally by specifying the `--global` flag to `logs:set` with no app name specified: ```shell -dokku logs:set --global sink "console://?encoding[codec]=json" +dokku logs:set --global vector-sink "console://?encoding[codec]=json" ``` As with app-specific sink settings, the global value may also be cleared by setting no value. ```shell -dokku logs:set --global sink +dokku logs:set --global vector-sink ``` ##### Log Sink DSN Format From 666bb9dfee2cd3cab0e68aa101933e42cb143baf Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:12:50 -0500 Subject: [PATCH 07/12] fix: unscope err for report subcommands --- plugins/apps/src/subcommands/subcommands.go | 4 ++-- plugins/buildpacks/src/subcommands/subcommands.go | 4 ++-- plugins/logs/src/subcommands/subcommands.go | 4 ++-- plugins/network/src/subcommands/subcommands.go | 4 ++-- plugins/proxy/src/subcommands/subcommands.go | 4 ++-- plugins/ps/src/subcommands/subcommands.go | 4 ++-- plugins/resource/src/subcommands/subcommands.go | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/apps/src/subcommands/subcommands.go b/plugins/apps/src/subcommands/subcommands.go index 0f146428e..66943d125 100644 --- a/plugins/apps/src/subcommands/subcommands.go +++ b/plugins/apps/src/subcommands/subcommands.go @@ -65,8 +65,8 @@ func main() { err = apps.CommandRename(oldAppName, newAppName, *skipDeploy) case "report": args := flag.NewFlagSet("apps:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("apps", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("apps", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = apps.CommandReport(appName, infoFlag) diff --git a/plugins/buildpacks/src/subcommands/subcommands.go b/plugins/buildpacks/src/subcommands/subcommands.go index 375b8794e..7bf7a2303 100644 --- a/plugins/buildpacks/src/subcommands/subcommands.go +++ b/plugins/buildpacks/src/subcommands/subcommands.go @@ -44,8 +44,8 @@ func main() { err = buildpacks.CommandRemove(appName, buildpack, *index) case "report": args := flag.NewFlagSet("buildpacks:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("buildpacks", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("buildpacks", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = buildpacks.CommandReport(appName, infoFlag) diff --git a/plugins/logs/src/subcommands/subcommands.go b/plugins/logs/src/subcommands/subcommands.go index b10ce4912..d94322bc0 100644 --- a/plugins/logs/src/subcommands/subcommands.go +++ b/plugins/logs/src/subcommands/subcommands.go @@ -26,8 +26,8 @@ func main() { err = logs.CommandFailed(appName, *allApps) case "report": args := flag.NewFlagSet("logs:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("logs", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("logs", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = logs.CommandReport(appName, infoFlag) diff --git a/plugins/network/src/subcommands/subcommands.go b/plugins/network/src/subcommands/subcommands.go index b5f1a5cc7..1842692e2 100644 --- a/plugins/network/src/subcommands/subcommands.go +++ b/plugins/network/src/subcommands/subcommands.go @@ -53,8 +53,8 @@ func main() { err = network.CommandRebuildall() case "report": args := flag.NewFlagSet("network:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("network", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("network", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = network.CommandReport(appName, infoFlag) diff --git a/plugins/proxy/src/subcommands/subcommands.go b/plugins/proxy/src/subcommands/subcommands.go index 7765b0375..5df47134c 100644 --- a/plugins/proxy/src/subcommands/subcommands.go +++ b/plugins/proxy/src/subcommands/subcommands.go @@ -64,8 +64,8 @@ func main() { err = proxy.CommandPortsSet(appName, portMaps) case "report": args := flag.NewFlagSet("proxy:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("proxy", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("proxy", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = proxy.CommandReport(appName, infoFlag) diff --git a/plugins/ps/src/subcommands/subcommands.go b/plugins/ps/src/subcommands/subcommands.go index d19c51173..41aae7d35 100644 --- a/plugins/ps/src/subcommands/subcommands.go +++ b/plugins/ps/src/subcommands/subcommands.go @@ -32,8 +32,8 @@ func main() { err = ps.CommandRebuild(appName, *allApps, *parallelCount) case "report": args := flag.NewFlagSet("ps:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("ps", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("ps", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = ps.CommandReport(appName, infoFlag) diff --git a/plugins/resource/src/subcommands/subcommands.go b/plugins/resource/src/subcommands/subcommands.go index c0808d06b..8d079e329 100644 --- a/plugins/resource/src/subcommands/subcommands.go +++ b/plugins/resource/src/subcommands/subcommands.go @@ -50,8 +50,8 @@ func main() { err = resource.CommandLimitClear(appName, *processType) case "report": args := flag.NewFlagSet("resource:report", flag.ExitOnError) - osArgs, infoFlag, err := common.ParseReportArgs("resource", os.Args[2:]) - if err == nil { + osArgs, infoFlag, flagErr := common.ParseReportArgs("resource", os.Args[2:]) + if flagErr == nil { args.Parse(osArgs) appName := args.Arg(0) err = resource.CommandReport(appName, infoFlag) From d70a9be97e85a269cfebc04ae1930770cc931a19 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:34:05 -0500 Subject: [PATCH 08/12] fix: correct issue where all flags were not shown if an invalid flag was specified --- plugins/apps/report.go | 7 ++++++- plugins/buildpacks/report.go | 7 ++++++- plugins/common/common.go | 23 ++++++++++++----------- plugins/logs/report.go | 7 ++++++- plugins/network/report.go | 7 ++++++- plugins/proxy/report.go | 7 ++++++- plugins/ps/report.go | 7 ++++++- plugins/resource/resource.go | 11 ++++++++--- 8 files changed, 56 insertions(+), 20 deletions(-) diff --git a/plugins/apps/report.go b/plugins/apps/report.go index d74d9ce51..491a45d6c 100644 --- a/plugins/apps/report.go +++ b/plugins/apps/report.go @@ -18,10 +18,15 @@ func ReportSingleApp(appName, infoFlag string) error { "--app-locked": reportLocked, } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("app", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("app", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func reportDir(appName string) string { diff --git a/plugins/buildpacks/report.go b/plugins/buildpacks/report.go index b255095f2..e67bdd72b 100644 --- a/plugins/buildpacks/report.go +++ b/plugins/buildpacks/report.go @@ -16,10 +16,15 @@ func ReportSingleApp(appName, infoFlag string) error { "--buildpacks-list": reportList, } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("buildpacks", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("buildpacks", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func reportList(appName string) string { diff --git a/plugins/common/common.go b/plugins/common/common.go index 6472b7d9e..7ec38493b 100644 --- a/plugins/common/common.go +++ b/plugins/common/common.go @@ -7,7 +7,6 @@ import ( "io/ioutil" "os" "path/filepath" - "reflect" "regexp" "sort" "strconv" @@ -324,7 +323,7 @@ func ParseReportArgs(pluginName string, arguments []string) ([]string, string, e } // ReportSingleApp is an internal function that displays a report for an app -func ReportSingleApp(reportType string, appName string, infoFlag string, infoFlags map[string]string, trimPrefix bool, uppercaseFirstCharacter bool) error { +func ReportSingleApp(reportType string, appName string, infoFlag string, infoFlags map[string]string, infoFlagKeys []string, trimPrefix bool, uppercaseFirstCharacter bool) error { flags := []string{} for key := range infoFlags { flags = append(flags, key) @@ -334,7 +333,11 @@ func ReportSingleApp(reportType string, appName string, infoFlag string, infoFla if len(infoFlag) == 0 { LogInfo2Quiet(fmt.Sprintf("%s %v information", appName, reportType)) for _, k := range flags { - v := infoFlags[k] + v, ok := infoFlags[k] + if !ok { + continue + } + prefix := "--" if trimPrefix { prefix = fmt.Sprintf("--%v-", reportType) @@ -353,19 +356,17 @@ func ReportSingleApp(reportType string, appName string, infoFlag string, infoFla for _, k := range flags { if infoFlag == k { - v := infoFlags[k] + v, ok := infoFlags[k] + if !ok { + continue + } fmt.Println(v) return nil } } - keys := reflect.ValueOf(infoFlags).MapKeys() - strkeys := make([]string, len(keys)) - for i := 0; i < len(keys); i++ { - strkeys[i] = keys[i].String() - } - - return fmt.Errorf("Invalid flag passed, valid flags: %s", strings.Join(strkeys, ", ")) + sort.Strings(infoFlagKeys) + return fmt.Errorf("Invalid flag passed, valid flags: %s", strings.Join(infoFlagKeys, ", ")) } // RightPad right-pads the string with pad up to len runes diff --git a/plugins/logs/report.go b/plugins/logs/report.go index 1234e6e55..3e8a95aa9 100644 --- a/plugins/logs/report.go +++ b/plugins/logs/report.go @@ -15,10 +15,15 @@ func ReportSingleApp(appName, infoFlag string) error { "--logs-global-vector-sink": reportGlobalVectorSink, } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("logs", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("logs", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func reportVectorSink(appName string) string { diff --git a/plugins/network/report.go b/plugins/network/report.go index ff9fcfdda..a1cc197b4 100644 --- a/plugins/network/report.go +++ b/plugins/network/report.go @@ -19,10 +19,15 @@ func ReportSingleApp(appName, infoFlag string) error { "--network-web-listeners": reportWebListeners, } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("network", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("network", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func reportBindAllInterfaces(appName string) string { diff --git a/plugins/proxy/report.go b/plugins/proxy/report.go index f32365ab1..01f181307 100644 --- a/plugins/proxy/report.go +++ b/plugins/proxy/report.go @@ -18,10 +18,15 @@ func ReportSingleApp(appName string, infoFlag string) error { "--proxy-port-map": reportPortMap, } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("proxy", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("proxy", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func reportEnabled(appName string) string { diff --git a/plugins/ps/report.go b/plugins/ps/report.go index 838eaee49..46656697c 100644 --- a/plugins/ps/report.go +++ b/plugins/ps/report.go @@ -28,10 +28,15 @@ func ReportSingleApp(appName, infoFlag string) error { flags[flag] = fn } + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) + } + trimPrefix := false uppercaseFirstCharacter := true infoFlags := common.CollectReport(appName, infoFlag, flags) - return common.ReportSingleApp("ps", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("ps", appName, infoFlag, infoFlags, flagKeys, trimPrefix, uppercaseFirstCharacter) } func addStatusFlags(appName string, infoFlag string) map[string]common.ReportFunc { diff --git a/plugins/resource/resource.go b/plugins/resource/resource.go index 7d0ea4c4c..7f09e973f 100644 --- a/plugins/resource/resource.go +++ b/plugins/resource/resource.go @@ -28,15 +28,20 @@ func ReportSingleApp(appName, infoFlag string) error { return nil } - infoFlags := map[string]string{} + flags := map[string]string{} for key, value := range resources { flag := fmt.Sprintf("--resource-%v", key) - infoFlags[flag] = value + flags[flag] = value + } + + flagKeys := []string{} + for flagKey := range flags { + flagKeys = append(flagKeys, flagKey) } trimPrefix := true uppercaseFirstCharacter := false - return common.ReportSingleApp("resource", appName, infoFlag, infoFlags, trimPrefix, uppercaseFirstCharacter) + return common.ReportSingleApp("resource", appName, infoFlag, flags, flagKeys, trimPrefix, uppercaseFirstCharacter) } // GetResourceValue fetches a single value for a given app/process/request/key combination From f16a211b4875d843970a3cd968d63bcc245043a8 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:34:19 -0500 Subject: [PATCH 09/12] feat: add more tests for the logs plugin --- tests/unit/logs.bats | 175 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 174 insertions(+), 1 deletion(-) diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats index 44eaef40a..76bb061d1 100644 --- a/tests/unit/logs.bats +++ b/tests/unit/logs.bats @@ -11,9 +11,182 @@ teardown() { global_teardown } -@test "(network) logs:help" { +@test "(logs) logs:help" { run /bin/bash -c "dokku logs:help" echo "output: $output" echo "status: $status" assert_output_contains "Manage log integration for an app" } + +@test "(logs) logs:report" { + run /bin/bash -c "dokku logs:report" + echo "output: $output" + echo "status: $status" + assert_output_contains "You haven't deployed any applications yet" + + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:report 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$TEST_APP logs information" +} + +@test "(logs) logs:report app" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:report $TEST_APP 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$TEST_APP logs information" + + run /bin/bash -c "dokku logs:report $TEST_APP --invalid-flag 2>&1" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "$TEST_APP logs information" 0 + assert_output_contains "Invalid flag passed, valid flags: --logs-global-vector-sink, --logs-vector-sink" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$TEST_APP logs information" 0 + assert_output_contains "Invalid flag passed" 0 + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-global-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "$TEST_APP logs information" 0 + assert_output_contains "Invalid flag passed" 0 +} + +@test "(logs) logs:set [error]" { + run /bin/bash -c "dokku logs:set 2>&1" + echo "output: $output" + echo "status: $status" + assert_failure + + assert_output_contains "Please specify an app to run the command on" + run /bin/bash -c "dokku logs:set ${TEST_APP}-non-existent" 2>&1 + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "App $TEST_APP-non-existent does not exist" + + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:set $TEST_APP" 2>&1 + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "No property specified" + + run /bin/bash -c "dokku logs:set $TEST_APP invalid" 2>&1 + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Invalid property specified, valid properties include: vector-sink" + + run /bin/bash -c "dokku logs:set $TEST_APP invalid value" 2>&1 + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Invalid property specified, valid properties include: vector-sink" +} + +@test "(logs) logs:set app" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_not_exists + + run /bin/bash -c "dokku logs:set $TEST_APP vector-sink" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Unsetting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_not_exists + + run /bin/bash -c "dokku logs:set $TEST_APP vector-sink console://?encoding[codec]=json" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Setting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "console://?encoding[codec]=json" +} +@test "(logs) logs:set global" { + run create_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-global-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_not_exists + + run /bin/bash -c "dokku logs:set --global vector-sink" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Unsetting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-global-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_not_exists + + run /bin/bash -c "dokku logs:set --global vector-sink console://?encoding[codec]=json" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Setting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" + + run /bin/bash -c "dokku logs:report $TEST_APP --logs-global-vector-sink 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "console://?encoding[codec]=json" + + run /bin/bash -c "dokku logs:set --global vector-sink" 2>&1 + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Unsetting vector-sink" + assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" +} From b186d9d66c21f956a77949494d45aa889d07b415 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:42:51 -0500 Subject: [PATCH 10/12] docs: fix help output --- docs/deployment/logs.md | 2 +- plugins/logs/src/commands/commands.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 276e84319..938a1029d 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -4,7 +4,7 @@ logs [-h] [-t] [-n num] [-q] [-p process] # Display recent log output logs:failed [--all|] # Shows the last failed deploy logs logs:report [] [] # Displays a logs report for one or more apps -logs:set [--global|] # Set or clear a logs property for an app +logs:set [--global|] # Set or clear a logs property for an app logs:vector-logs # Tail the logs of the vector container logs:vector-start # Start the vector logging container logs:vector-stop # Stop the vector logging container diff --git a/plugins/logs/src/commands/commands.go b/plugins/logs/src/commands/commands.go index dd6e72e45..c9c4e4fd3 100644 --- a/plugins/logs/src/commands/commands.go +++ b/plugins/logs/src/commands/commands.go @@ -25,7 +25,7 @@ Additional commands:` logs [-h] [-t|--tail] [-n|--num num] [-q|--quiet] [-p|--ps process] , Display recent log output logs:failed [--all|], Shows the last failed deploy logs logs:report [] [], Displays a logs report for one or more apps - logs:set , Set or clear a logs property for an app + logs:set [--global|] , Set or clear a logs property for an app logs:vector-logs, Tail the logs of the vector container logs:vector-start, Start the vector logging container logs:vector-stop, Stop the vector logging container From eda71e3ffe4738511fe7958ebad3a1652ec652e1 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:43:55 -0500 Subject: [PATCH 11/12] feat: mirror log tailing support for logs:vector-logs command --- docs/deployment/logs.md | 2 +- plugins/common/log.go | 14 +++++++++++--- plugins/logs/src/commands/commands.go | 2 +- plugins/logs/src/subcommands/subcommands.go | 4 +++- plugins/logs/subcommands.go | 4 ++-- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/docs/deployment/logs.md b/docs/deployment/logs.md index 938a1029d..2e242c689 100644 --- a/docs/deployment/logs.md +++ b/docs/deployment/logs.md @@ -5,7 +5,7 @@ logs [-h] [-t] [-n num] [-q] [-p process] # Display recent log output logs:failed [--all|] # Shows the last failed deploy logs logs:report [] [] # Displays a logs report for one or more apps logs:set [--global|] # Set or clear a logs property for an app -logs:vector-logs # Tail the logs of the vector container +logs:vector-logs [--num num] [--tail] # Display vector log output logs:vector-start # Start the vector logging container logs:vector-stop # Stop the vector logging container ``` diff --git a/plugins/common/log.go b/plugins/common/log.go index 1a64ca241..6b9e053e2 100644 --- a/plugins/common/log.go +++ b/plugins/common/log.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "os" + "strconv" "strings" ) @@ -95,8 +96,15 @@ func LogVerboseQuietContainerLogs(containerID string) { } // LogVerboseQuietContainerLogsTail is the verbose log formatter for container logs with tail mode enabled -func LogVerboseQuietContainerLogsTail(containerID string) { - sc := NewShellCmdWithArgs(DockerBin(), "container", "logs", containerID, "--follow", "--tail", "10") +func LogVerboseQuietContainerLogsTail(containerID string, lines int, tail bool) { + args := []string{"container", "logs", containerID} + if lines > 0 { + args = append(args, "--tail", strconv.Itoa(lines)) + } + if tail { + args = append(args, "--follow") + } + sc := NewShellCmdWithArgs(DockerBin(), args...) stdout, _ := sc.Command.StdoutPipe() sc.Command.Start() @@ -104,7 +112,7 @@ func LogVerboseQuietContainerLogsTail(containerID string) { scanner.Split(bufio.ScanLines) for scanner.Scan() { m := scanner.Text() - fmt.Println(m) + LogVerboseQuiet(m) } sc.Command.Wait() } diff --git a/plugins/logs/src/commands/commands.go b/plugins/logs/src/commands/commands.go index c9c4e4fd3..c4fcc3a93 100644 --- a/plugins/logs/src/commands/commands.go +++ b/plugins/logs/src/commands/commands.go @@ -26,7 +26,7 @@ Additional commands:` logs:failed [--all|], Shows the last failed deploy logs logs:report [] [], Displays a logs report for one or more apps logs:set [--global|] , Set or clear a logs property for an app - logs:vector-logs, Tail the logs of the vector container + logs:vector-logs [--num num] [--tail], Display vector log output logs:vector-start, Start the vector logging container logs:vector-stop, Stop the vector logging container ` diff --git a/plugins/logs/src/subcommands/subcommands.go b/plugins/logs/src/subcommands/subcommands.go index d94322bc0..875dc2d67 100644 --- a/plugins/logs/src/subcommands/subcommands.go +++ b/plugins/logs/src/subcommands/subcommands.go @@ -47,8 +47,10 @@ func main() { err = logs.CommandSet(appName, property, value) case "vector-logs": args := flag.NewFlagSet("logs:vector-logs", flag.ExitOnError) + num := args.Int("num", 100, "the number of lines to display") + tail := args.Bool("tail", false, "continually stream logs") args.Parse(os.Args[2:]) - err = logs.CommandVectorLogs() + err = logs.CommandVectorLogs(*num, *tail) case "vector-start": args := flag.NewFlagSet("logs:vector-start", flag.ExitOnError) vectorImage := args.String("vector-image", logs.VectorImage, "--vector-image: the name of the docker image to run for vector") diff --git a/plugins/logs/subcommands.go b/plugins/logs/subcommands.go index 483d1baeb..25e1191ef 100644 --- a/plugins/logs/subcommands.go +++ b/plugins/logs/subcommands.go @@ -85,7 +85,7 @@ func CommandSet(appName string, property string, value string) error { } // CommandVectorLogs tails the log output for the vector container -func CommandVectorLogs() error { +func CommandVectorLogs(lines int, tail bool) error { if !common.ContainerExists(vectorContainerName) { return errors.New("Vector container does not exist") } @@ -95,7 +95,7 @@ func CommandVectorLogs() error { } common.LogInfo1Quiet("Tailing vector container logs") - common.LogVerboseQuietContainerLogsTail(vectorContainerName) + common.LogVerboseQuietContainerLogsTail(vectorContainerName, lines, tail) return nil } From a57680fbbfdda1646d019aa3dd16dd2643097830 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Thu, 7 Jan 2021 01:54:04 -0500 Subject: [PATCH 12/12] feat: test vector commands --- plugins/logs/subcommands.go | 2 +- tests/unit/logs.bats | 42 +++++++++++++++++++++++++++++++++++++ tests/unit/test_helper.bash | 8 +++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/plugins/logs/subcommands.go b/plugins/logs/subcommands.go index 25e1191ef..d9c8ce572 100644 --- a/plugins/logs/subcommands.go +++ b/plugins/logs/subcommands.go @@ -94,7 +94,7 @@ func CommandVectorLogs(lines int, tail bool) error { return errors.New("Vector container is not running") } - common.LogInfo1Quiet("Tailing vector container logs") + common.LogInfo1Quiet("Vector container logs") common.LogVerboseQuietContainerLogsTail(vectorContainerName, lines, tail) return nil diff --git a/tests/unit/logs.bats b/tests/unit/logs.bats index 76bb061d1..0e86f5f3a 100644 --- a/tests/unit/logs.bats +++ b/tests/unit/logs.bats @@ -190,3 +190,45 @@ teardown() { assert_output_contains "Unsetting vector-sink" assert_output_contains "Writing updated vector config to /var/lib/dokku/data/logs/vector.json" } + +@test "(logs) logs:vector" { + run /bin/bash -c "dokku logs:vector-logs 2>&1" + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains "Vector container does not exist" + + run /bin/bash -c "dokku logs:vector-start 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Vector container is running" + + run /bin/bash -c "dokku logs:vector-logs 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Vector container logs" + + run /bin/bash -c "dokku logs:vector-logs --num 10 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Vector container logs" + assert_output_contains "vector:" 10 + assert_line_count 11 + + run /bin/bash -c "dokku logs:vector-logs --num 5 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "Vector container logs" + assert_output_contains "vector:" 5 + assert_line_count 6 + + run /bin/bash -c "dokku logs:vector-stop 2>&1" + echo "output: $output" + echo "status: $status" + assert_success + assert_output_contains "StoppingĀ and removing vector container" +} diff --git a/tests/unit/test_helper.bash b/tests/unit/test_helper.bash index cebb96fce..353772f39 100644 --- a/tests/unit/test_helper.bash +++ b/tests/unit/test_helper.bash @@ -163,6 +163,14 @@ assert_line() { fi } +# ShellCheck doesn't know about $lines from Bats +# shellcheck disable=SC2154 +assert_line_count() { + declare EXPECTED="$1" + local num_lines="${#lines[@]}" + assert_equal "$EXPECTED" "$num_lines" +} + refute_line() { if [[ "$1" -ge 0 ]] 2>/dev/null; then local num_lines="${#lines[@]}"