Merge pull request #4160 from nerg4l/go-logs-plugin
Rewrite logs plugin in Go
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
# 0.22.0 Migration Guide
|
# 0.22.0 Migration Guide
|
||||||
|
|
||||||
|
## Deprecations
|
||||||
|
|
||||||
|
- Calling `logs:failed` without either a `<name>` or the `--all` flag is deprecated.
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
- Underscores are no longer valid characters in app names. Please rename applications before upgrading.
|
- Underscores are no longer valid characters in app names. Please rename applications before upgrading.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
logs <app> [-h] [-t] [-n num] [-q] [-p process] # Display recent log output
|
logs <app> [-h] [-t] [-n num] [-q] [-p process] # Display recent log output
|
||||||
logs:failed [<app>] # Shows the last failed deploy logs
|
logs:failed [--parallel count] [--all|<app>] # Shows the last failed deploy logs
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
@@ -46,8 +46,8 @@ You can retrieve these logs by using the `logs:failed` command
|
|||||||
dokku logs:failed node-js-app
|
dokku logs:failed node-js-app
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also retrieve the failed logs for each app:
|
You may also fetch all failed app logs by using the `--all` flag.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
dokku logs:failed node-js-app
|
dokku logs:failed --all
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -43,13 +43,14 @@ func RunCommandAgainstAllApps(command ParallelCommand, commandName string, paral
|
|||||||
}
|
}
|
||||||
|
|
||||||
if runInSerial {
|
if runInSerial {
|
||||||
return runCommandAgainstAllAppsSerially(command, commandName)
|
return RunCommandAgainstAllAppsSerially(command, commandName)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runCommandAgainstAllAppsInParallel(command, commandName, parallelCount)
|
return RunCommandAgainstAllAppsInParallel(command, commandName, parallelCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommandAgainstAllAppsInParallel(command ParallelCommand, commandName string, parallelCount int) error {
|
// RunCommandAgainstAllAppsInParallel runs a given ParallelCommand against all apps in parallel
|
||||||
|
func RunCommandAgainstAllAppsInParallel(command ParallelCommand, commandName string, parallelCount int) error {
|
||||||
apps, err := DokkuApps()
|
apps, err := DokkuApps()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogWarn(err.Error())
|
LogWarn(err.Error())
|
||||||
@@ -68,7 +69,8 @@ func runCommandAgainstAllAppsInParallel(command ParallelCommand, commandName str
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCommandAgainstAllAppsSerially(command ParallelCommand, commandName string) error {
|
// RunCommandAgainstAllAppsSerially runs a given ParallelCommand against all apps serially
|
||||||
|
func RunCommandAgainstAllAppsSerially(command ParallelCommand, commandName string) error {
|
||||||
apps, err := DokkuApps()
|
apps, err := DokkuApps()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogWarn(err.Error())
|
LogWarn(err.Error())
|
||||||
|
|||||||
2
plugins/logs/.gitignore
vendored
Normal file
2
plugins/logs/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/commands
|
||||||
|
/subcommands/*
|
||||||
5
plugins/logs/Makefile
Normal file
5
plugins/logs/Makefile
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
SUBCOMMANDS = subcommands/failed
|
||||||
|
BUILD = commands subcommands
|
||||||
|
PLUGIN_NAME = logs
|
||||||
|
|
||||||
|
include ../../common.mk
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
[[ " help logs:help " == *" $1 "* ]] || exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
|
||||||
source "$PLUGIN_AVAILABLE_PATH/logs/help-functions"
|
|
||||||
set -eo pipefail
|
|
||||||
[[ $DOKKU_TRACE ]] && set -x
|
|
||||||
|
|
||||||
case "$1" in
|
|
||||||
help | logs:help)
|
|
||||||
cmd-logs-help "$@"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
exit "$DOKKU_NOT_IMPLEMENTED_EXIT"
|
|
||||||
;;
|
|
||||||
|
|
||||||
esac
|
|
||||||
11
plugins/logs/go.mod
Normal file
11
plugins/logs/go.mod
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
module github.com/dokku/dokku/plugins/logs
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27
|
||||||
|
github.com/dokku/dokku/plugins/common v0.0.0-00010101000000-000000000000
|
||||||
|
github.com/ryanuber/columnize v1.1.2-0.20190319233515-9e6335e58db3 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
|
replace github.com/dokku/dokku/plugins/common => ../common
|
||||||
6
plugins/logs/go.sum
Normal file
6
plugins/logs/go.sum
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q=
|
||||||
|
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
|
||||||
|
github.com/codeskyblue/go-sh v0.0.0-20190412065543-76bd3d59ff27 h1:HHUr4P/aKh4quafGxDT9LDasjGdlGkzLbfmmrlng3kA=
|
||||||
|
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=
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eo pipefail
|
|
||||||
[[ $DOKKU_TRACE ]] && set -x
|
|
||||||
|
|
||||||
cmd-logs-help() {
|
|
||||||
declare desc="help command"
|
|
||||||
declare CMD="$1"
|
|
||||||
local plugin_name="logs"
|
|
||||||
local plugin_description="Manage log integration for an app"
|
|
||||||
|
|
||||||
if [[ "$CMD" == "$plugin_name:help" ]]; then
|
|
||||||
echo -e "Usage: dokku $plugin_name[:COMMAND]"
|
|
||||||
echo ''
|
|
||||||
echo "$plugin_description"
|
|
||||||
echo ''
|
|
||||||
echo 'Additional commands:'
|
|
||||||
fn-help-content | sort | column -c2 -t -s,
|
|
||||||
elif [[ $(ps -o command= $PPID) == *"--all"* ]]; then
|
|
||||||
fn-help-content
|
|
||||||
else
|
|
||||||
cat <<help_desc
|
|
||||||
$plugin_name, $plugin_description
|
|
||||||
help_desc
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fn-help-content() {
|
|
||||||
declare desc="return help content"
|
|
||||||
cat <<help_content
|
|
||||||
logs <app> [-h] [-t] [-n num] [-q] [-p process], Display recent log output
|
|
||||||
logs:failed <app>, Show the last logs for an application
|
|
||||||
help_content
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eo pipefail
|
|
||||||
[[ $DOKKU_TRACE ]] && set -x
|
|
||||||
|
|
||||||
fn-logs-usage() {
|
|
||||||
declare desc="logs specific usage"
|
|
||||||
echo "Usage: dokku logs <app>"
|
|
||||||
echo " display recent log output"
|
|
||||||
echo ""
|
|
||||||
echo " -n, --num NUM # the number of lines to display"
|
|
||||||
echo " -p, --ps PS # only display logs from the given process"
|
|
||||||
echo " -t, --tail # continually stream logs"
|
|
||||||
echo " -q, --quiet # display raw logs without colors, time and names"
|
|
||||||
}
|
|
||||||
17
plugins/logs/logs.go
Normal file
17
plugins/logs/logs.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetFailedLogs outputs failed deploy logs for a given app
|
||||||
|
func GetFailedLogs(appName string) error {
|
||||||
|
common.LogInfo2Quiet(fmt.Sprintf("%s failed deploy logs", appName))
|
||||||
|
s := common.GetAppScheduler(appName)
|
||||||
|
if err := common.PlugnTrigger("scheduler-logs-failed", s, appName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
82
plugins/logs/src/commands/commands.go
Normal file
82
plugins/logs/src/commands/commands.go
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
"github.com/dokku/dokku/plugins/logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
helpHeader = `Usage: dokku logs[:COMMAND]
|
||||||
|
|
||||||
|
Manage log integration for an app
|
||||||
|
|
||||||
|
Additional commands:`
|
||||||
|
|
||||||
|
helpContent = `
|
||||||
|
logs [-h] [-t] [-n num] [-q] [-p process] <app>, Display recent log output
|
||||||
|
logs:failed [<app>], Shows the last failed deploy logs
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Usage = usage
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
cmd := flag.Arg(0)
|
||||||
|
switch cmd {
|
||||||
|
case "logs":
|
||||||
|
args := flag.NewFlagSet("logs", flag.ExitOnError)
|
||||||
|
var num int64
|
||||||
|
var ps string
|
||||||
|
var tail bool
|
||||||
|
var quiet bool
|
||||||
|
help := args.Bool("h", false, "-h: print help for the command")
|
||||||
|
args.Int64Var(&num, "n", 0, "-n: the number of lines to display")
|
||||||
|
args.Int64Var(&num, "num", 0, "--num: the number of lines to display")
|
||||||
|
args.StringVar(&ps, "p", "", "-p: only display logs from the given process")
|
||||||
|
args.StringVar(&ps, "ps", "", "--p: only display logs from the given process")
|
||||||
|
args.BoolVar(&tail, "t", true, "-t: continually stream logs")
|
||||||
|
args.BoolVar(&tail, "tail", true, "--tail: continually stream logs")
|
||||||
|
args.BoolVar(&quiet, "q", true, "-q: display raw logs without colors, time and names")
|
||||||
|
args.BoolVar(&quiet, "quiet", true, "--quiet: display raw logs without colors, time and names")
|
||||||
|
args.Parse(flag.Args()[1:])
|
||||||
|
if *help {
|
||||||
|
usage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
appName := args.Arg(0)
|
||||||
|
err := logs.CommandDefault(appName, num, ps, tail, quiet)
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
case "logs:help":
|
||||||
|
usage()
|
||||||
|
case "help":
|
||||||
|
command := common.NewShellCmd(fmt.Sprintf("ps -o command= %d", os.Getppid()))
|
||||||
|
command.ShowOutput = false
|
||||||
|
output, err := command.Output()
|
||||||
|
|
||||||
|
if err == nil && strings.Contains(string(output), "--all") {
|
||||||
|
fmt.Println(helpContent)
|
||||||
|
} else {
|
||||||
|
fmt.Print("\n logs, Manage log integration for an app\n")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
dokkuNotImplementExitCode, err := strconv.Atoi(os.Getenv("DOKKU_NOT_IMPLEMENTED_EXIT"))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("failed to retrieve DOKKU_NOT_IMPLEMENTED_EXIT environment variable")
|
||||||
|
dokkuNotImplementExitCode = 10
|
||||||
|
}
|
||||||
|
os.Exit(dokkuNotImplementExitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func usage() {
|
||||||
|
common.CommandUsage(helpHeader, helpContent)
|
||||||
|
}
|
||||||
33
plugins/logs/src/subcommands/subcommands.go
Normal file
33
plugins/logs/src/subcommands/subcommands.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
"github.com/dokku/dokku/plugins/logs"
|
||||||
|
)
|
||||||
|
|
||||||
|
// main entrypoint to all subcommands
|
||||||
|
func main() {
|
||||||
|
parts := strings.Split(os.Args[0], "/")
|
||||||
|
subcommand := parts[len(parts)-1]
|
||||||
|
|
||||||
|
var err error
|
||||||
|
switch subcommand {
|
||||||
|
case "failed":
|
||||||
|
args := flag.NewFlagSet("logs:failed", flag.ExitOnError)
|
||||||
|
allApps := args.Bool("all", false, "--all: restore all apps")
|
||||||
|
args.Parse(os.Args[2:])
|
||||||
|
appName := args.Arg(0)
|
||||||
|
err = logs.CommandFailed(appName, *allApps)
|
||||||
|
default:
|
||||||
|
common.LogFail(fmt.Sprintf("Invalid plugin subcommand call: %s", subcommand))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
common.LogFail(err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
51
plugins/logs/subcommands.go
Normal file
51
plugins/logs/subcommands.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package logs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/dokku/dokku/plugins/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CommandDefault displays recent log output
|
||||||
|
func CommandDefault(appName string, num int64, process string, tail, quiet bool) error {
|
||||||
|
if appName == "" {
|
||||||
|
return errors.New("Please specify an app to run the command on")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := common.VerifyAppName(appName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !common.IsDeployed(appName) {
|
||||||
|
return fmt.Errorf("App %s has not been deployed", appName)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := common.GetAppScheduler(appName)
|
||||||
|
t := strconv.FormatBool(tail)
|
||||||
|
q := strconv.FormatBool(quiet)
|
||||||
|
n := strconv.FormatInt(num, 10)
|
||||||
|
if err := common.PlugnTrigger("scheduler-logs", []string{s, appName, process, t, q, n}...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CommandFailed shows the last failed deploy logs
|
||||||
|
func CommandFailed(appName string, allApps bool) error {
|
||||||
|
if allApps {
|
||||||
|
return common.RunCommandAgainstAllAppsSerially(GetFailedLogs, "logs:failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if appName == "" {
|
||||||
|
common.LogWarn("Deprecated: Restore specified without app, assuming --all")
|
||||||
|
return common.RunCommandAgainstAllAppsSerially(GetFailedLogs, "logs:failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := common.VerifyAppName(appName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetFailedLogs(appName)
|
||||||
|
}
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
set -eo pipefail
|
|
||||||
[[ $DOKKU_TRACE ]] && set -x
|
|
||||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
||||||
source "$PLUGIN_AVAILABLE_PATH/logs/internal-functions"
|
|
||||||
|
|
||||||
cmd-logs-default() {
|
|
||||||
declare desc="display recent log output"
|
|
||||||
declare cmd="logs"
|
|
||||||
[[ "$1" == "$cmd" ]] && shift 1
|
|
||||||
declare APP="$1"
|
|
||||||
|
|
||||||
[[ -z "$APP" ]] && dokku_log_fail "Please specify an app to run the command on"
|
|
||||||
verify_app_name "$APP"
|
|
||||||
|
|
||||||
! (is_deployed "$APP") && dokku_log_fail "App $APP has not been deployed"
|
|
||||||
|
|
||||||
shift 1
|
|
||||||
local TEMP=$(getopt -o htqn:p: --long help,tail,quiet,num:,ps: -n 'dokku logs' -- "$@")
|
|
||||||
local EXIT_CODE="$?"
|
|
||||||
if [[ "$EXIT_CODE" != 0 ]]; then
|
|
||||||
fn-logs-usage >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
eval set -- "$TEMP"
|
|
||||||
|
|
||||||
local NUM="100"
|
|
||||||
while true; do
|
|
||||||
case "$1" in
|
|
||||||
-t | --tail)
|
|
||||||
local TAIL=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-n | --num)
|
|
||||||
local NUM="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
-p | --ps)
|
|
||||||
local PROCESS_TYPE="$2"
|
|
||||||
shift 2
|
|
||||||
;;
|
|
||||||
-q | --quiet)
|
|
||||||
local PRETTY_PRINT=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*) dokku_log_fail "Internal error" ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
DOKKU_SCHEDULER=$(get_app_scheduler "$APP")
|
|
||||||
plugn trigger scheduler-logs "$DOKKU_SCHEDULER" "$APP" "$PROCESS_TYPE" "$TAIL" "$PRETTY_PRINT" "$NUM"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd-logs-default "$@"
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
|
|
||||||
source "$PLUGIN_AVAILABLE_PATH/apps/functions"
|
|
||||||
source "$PLUGIN_AVAILABLE_PATH/config/functions"
|
|
||||||
set -eo pipefail
|
|
||||||
[[ $DOKKU_TRACE ]] && set -x
|
|
||||||
|
|
||||||
cmd-logs-failed() {
|
|
||||||
declare desc="shows the last failed deploy logs"
|
|
||||||
declare cmd="logs:failed"
|
|
||||||
[[ "$1" == "$cmd" ]] && shift 1
|
|
||||||
declare APP="$1"
|
|
||||||
local DOKKU_SCHEDULER
|
|
||||||
|
|
||||||
if [[ -z "$APP" ]]; then
|
|
||||||
local INSTALLED_APPS=$(dokku_apps)
|
|
||||||
for app in $INSTALLED_APPS; do
|
|
||||||
fn-logs-failed-single "$app" | tee || true
|
|
||||||
done
|
|
||||||
else
|
|
||||||
fn-logs-failed-single "$APP"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
fn-logs-failed-single() {
|
|
||||||
declare desc="shows the last failed deploy logs for an app"
|
|
||||||
declare APP="$1"
|
|
||||||
local DOKKU_SCHEDULER
|
|
||||||
|
|
||||||
dokku_log_info2_quiet "${APP} failed deploy logs"
|
|
||||||
DOKKU_SCHEDULER=$(get_app_scheduler "$APP")
|
|
||||||
plugn trigger scheduler-logs-failed "$DOKKU_SCHEDULER" "$APP"
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd-logs-failed "$@"
|
|
||||||
Reference in New Issue
Block a user