diff --git a/plugins/logs/.gitignore b/plugins/logs/.gitignore new file mode 100644 index 000000000..0f6770b1e --- /dev/null +++ b/plugins/logs/.gitignore @@ -0,0 +1,2 @@ +/commands +/subcommands/* diff --git a/plugins/logs/Makefile b/plugins/logs/Makefile new file mode 100644 index 000000000..abb84bed4 --- /dev/null +++ b/plugins/logs/Makefile @@ -0,0 +1,5 @@ +SUBCOMMANDS = subcommands/failed +BUILD = commands subcommands +PLUGIN_NAME = logs + +include ../../common.mk diff --git a/plugins/logs/commands b/plugins/logs/commands deleted file mode 100755 index 816849610..000000000 --- a/plugins/logs/commands +++ /dev/null @@ -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 diff --git a/plugins/logs/go.mod b/plugins/logs/go.mod new file mode 100644 index 000000000..9c7166d02 --- /dev/null +++ b/plugins/logs/go.mod @@ -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 diff --git a/plugins/logs/help-functions b/plugins/logs/help-functions deleted file mode 100755 index be7dd3b33..000000000 --- a/plugins/logs/help-functions +++ /dev/null @@ -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 < [-h] [-t] [-n num] [-q] [-p process], Display recent log output - logs:failed , Show the last logs for an application -help_content -} diff --git a/plugins/logs/internal-functions b/plugins/logs/internal-functions deleted file mode 100755 index dbefa3041..000000000 --- a/plugins/logs/internal-functions +++ /dev/null @@ -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 " - 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" -} diff --git a/plugins/logs/src/commands/commands.go b/plugins/logs/src/commands/commands.go new file mode 100644 index 000000000..e4f13c6ca --- /dev/null +++ b/plugins/logs/src/commands/commands.go @@ -0,0 +1,70 @@ +package main + +import ( + "flag" + "fmt" + "github.com/dokku/dokku/plugins/common" + "github.com/dokku/dokku/plugins/logs" + "os" + "strconv" +) + +const ( + helpHeader = `Usage: dokku network[:COMMAND] + +Manage network settings for an app + +Additional commands:` + + helpContent = ` + logs [-h] [-t] [-n num] [-q] [-p process] , Display recent log output + logs:failed [], 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) + help := args.Bool("h", false, "-h: print help for the command") + var num int64 + args.Int64Var(&num, "n", 0, "-n: the number of lines to display") + args.Int64Var(&num, "num", 0, "--num: the number of lines to display") + var ps string + args.StringVar(&ps, "p", "", "-p: only display logs from the given process") + args.StringVar(&ps, "ps", "", "--p: only display logs from the given process") + var tail bool + args.BoolVar(&tail, "t", true, "-t: continually stream logs") + args.BoolVar(&tail, "tail", true, "--tail: continually stream logs") + var quiet bool + 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() + 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) +} diff --git a/plugins/logs/src/subcommands/subcommands.go b/plugins/logs/src/subcommands/subcommands.go new file mode 100644 index 000000000..065ea8816 --- /dev/null +++ b/plugins/logs/src/subcommands/subcommands.go @@ -0,0 +1,31 @@ +package main + +import ( + "flag" + "fmt" + "github.com/dokku/dokku/plugins/common" + "github.com/dokku/dokku/plugins/logs" + "os" + "strings" +) + +// 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) + args.Parse(os.Args[2:]) + appName := args.Arg(0) + err = logs.CommandFailed(appName) + default: + common.LogFail(fmt.Sprintf("Invalid plugin subcommand call: %s", subcommand)) + } + + if err != nil { + common.LogFail(err.Error()) + } +} diff --git a/plugins/logs/subcommands.go b/plugins/logs/subcommands.go new file mode 100644 index 000000000..f0bed7404 --- /dev/null +++ b/plugins/logs/subcommands.go @@ -0,0 +1,53 @@ +package logs + +import ( + "errors" + "fmt" + "github.com/dokku/dokku/plugins/common" + "strconv" +) + +// 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) error { + if appName == "" { + apps, err := common.DokkuApps() + if err != nil { + return err + } + for _, appName := range apps { + _ = failedSingle(appName) + } + return nil + } + return failedSingle(appName) +} + +func failedSingle(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 +} diff --git a/plugins/logs/subcommands/default b/plugins/logs/subcommands/default deleted file mode 100755 index 9cf68f1cc..000000000 --- a/plugins/logs/subcommands/default +++ /dev/null @@ -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 "$@" diff --git a/plugins/logs/subcommands/failed b/plugins/logs/subcommands/failed deleted file mode 100755 index f2c2339b9..000000000 --- a/plugins/logs/subcommands/failed +++ /dev/null @@ -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 "$@"