Merge pull request #4301 from dokku/4299-vector-fixes
Ensure vector container starts correctly
This commit is contained in:
@@ -4,8 +4,8 @@
|
||||
logs <app> [-h] [-t] [-n num] [-q] [-p process] # Display recent log output
|
||||
logs:failed [--all|<app>] # Shows the last failed deploy logs
|
||||
logs:report [<app>] [<flag>] # Displays a logs report for one or more apps
|
||||
logs:set [--global|<app>] <key> <value> # Set or clear a logs property for an app
|
||||
logs:vector-logs # Tail the logs of the vector container
|
||||
logs:set [--global|<app>] <key> <value> # Set or clear a logs property for an app
|
||||
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
|
||||
```
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ 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() {
|
||||
return errors.New("Unable to start vector container")
|
||||
@@ -151,11 +152,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{},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -25,8 +25,8 @@ Additional commands:`
|
||||
logs [-h] [-t|--tail] [-n|--num num] [-q|--quiet] [-p|--ps process] <app>, Display recent log output
|
||||
logs:failed [--all|<app>], Shows the last failed deploy logs
|
||||
logs:report [<app>] [<flag>], Displays a logs report for one or more apps
|
||||
logs:set <app> <key> <value>, Set or clear a logs property for an app
|
||||
logs:vector-logs, Tail the logs of the vector container
|
||||
logs:set [--global|<app>] <key> <value>, Set or clear a logs property for an app
|
||||
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
|
||||
`
|
||||
|
||||
@@ -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)
|
||||
@@ -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")
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
@@ -84,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")
|
||||
}
|
||||
@@ -93,8 +94,8 @@ func CommandVectorLogs() error {
|
||||
return errors.New("Vector container is not running")
|
||||
}
|
||||
|
||||
common.LogInfo1Quiet("Tailing vector container logs")
|
||||
common.LogVerboseQuietContainerLogsTail(vectorContainerName)
|
||||
common.LogInfo1Quiet("Vector container logs")
|
||||
common.LogVerboseQuietContainerLogsTail(vectorContainerName, lines, tail)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
234
tests/unit/logs.bats
Normal file
234
tests/unit/logs.bats
Normal file
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env bats
|
||||
|
||||
load test_helper
|
||||
|
||||
setup() {
|
||||
global_setup
|
||||
}
|
||||
|
||||
teardown() {
|
||||
destroy_app
|
||||
global_teardown
|
||||
}
|
||||
|
||||
@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"
|
||||
}
|
||||
|
||||
@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"
|
||||
}
|
||||
@@ -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[@]}"
|
||||
|
||||
Reference in New Issue
Block a user