diff --git a/pkg/addons/addons.go b/pkg/addons/addons.go index 29dc6d2a4068..b1ce70bd3199 100644 --- a/pkg/addons/addons.go +++ b/pkg/addons/addons.go @@ -199,7 +199,7 @@ https://github.com/kubernetes/minikube/issues/7332`, out.V{"driver_name": cc.Dri return errors.Wrap(err, "registry port") } if enable { - out.Boxed(style.Tip, `Registry addon with {{.driver}} driver uses port {{.port}} please use that instead of default port 5000`, out.V{"driver": cc.Driver, "port": port}) + out.Boxed(`Registry addon with {{.driver}} driver uses port {{.port}} please use that instead of default port 5000`, out.V{"driver": cc.Driver, "port": port}) } out.Styled(style.Documentation, `For more information see: https://minikube.sigs.k8s.io/docs/drivers/{{.driver}}`, out.V{"driver": cc.Driver}) } diff --git a/pkg/minikube/out/out.go b/pkg/minikube/out/out.go index 6e3ec67415c8..d32f08f53177 100644 --- a/pkg/minikube/out/out.go +++ b/pkg/minikube/out/out.go @@ -23,7 +23,9 @@ import ( "html" "html/template" "io" + "io/ioutil" "os" + "path/filepath" "strconv" "strings" "time" @@ -33,6 +35,7 @@ import ( isatty "github.com/mattn/go-isatty" "k8s.io/klog/v2" + "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out/register" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/translate" @@ -111,17 +114,14 @@ func Styled(st style.Enum, format string, a ...V) { } // Boxed writes a stylized and templated message in a box to stdout -func Boxed(st style.Enum, format string, a ...V) { +func Boxed(format string, a ...V) { str := Sprintf(style.None, format, a...) str = strings.TrimSpace(str) - box := box.New(box.Config{Type: "Round"}) + box := box.New(box.Config{Py: 1, Px: 4, Type: "Round"}) if useColor { box.Config.Color = "Red" } - txt := strings.Split(box.String("", str), "\n") - Styled(style.Indent, txt[0]) - Styled(st, txt[1]) - Styled(style.Indent, txt[2]) + box.Println("", str) } // Sprintf is used for returning the string (doesn't write anything) @@ -333,7 +333,7 @@ func wantsColor(w fdWriter) bool { // LogEntries outputs an error along with any important log entries. func LogEntries(msg string, err error, entries map[string][]string) { - DisplayError(msg, err) + displayError(msg, err) for name, lines := range entries { Step(style.Failure, "Problems detected in {{.entry}}:", V{"entry": name}) @@ -346,8 +346,8 @@ func LogEntries(msg string, err error, entries map[string][]string) { } } -// DisplayError prints the error and displays the standard minikube error messaging -func DisplayError(msg string, err error) { +// displayError prints the error and displays the standard minikube error messaging +func displayError(msg string, err error) { klog.Warningf(fmt.Sprintf("%s: %v", msg, err)) if JSON { FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err}) @@ -357,8 +357,52 @@ func DisplayError(msg string, err error) { ErrT(style.Empty, "") FatalT("{{.msg}}: {{.err}}", V{"msg": translate.T(msg), "err": err}) ErrT(style.Empty, "") - ErrT(style.Sad, "minikube is exiting due to an error. If the above message is not useful, open an issue:") - ErrT(style.URL, "https://github.com/kubernetes/minikube/issues/new/choose") + displayGitHubIssueMessage() +} + +func latestLogFilePath() (string, error) { + if len(os.Args) < 2 { + return "", fmt.Errorf("unable to detect command") + } + cmd := os.Args[1] + if cmd == "start" { + return localpath.LastStartLog(), nil + } + + tmpdir := os.TempDir() + files, err := ioutil.ReadDir(tmpdir) + if err != nil { + return "", fmt.Errorf("failed to get list of files in tempdir: %v", err) + } + var lastModName string + var lastModTime time.Time + for _, file := range files { + if !strings.Contains(file.Name(), "minikube_") { + continue + } + if !lastModTime.IsZero() && lastModTime.After(file.ModTime()) { + continue + } + lastModName = file.Name() + lastModTime = file.ModTime() + } + fullPath := filepath.Join(tmpdir, lastModName) + + return fullPath, nil +} + +func displayGitHubIssueMessage() { + logPath, err := latestLogFilePath() + if err != nil { + klog.Warningf("failed to diplay GitHub issue message: %v", err) + } + + msg := Sprintf(style.Sad, "If the above advice does not help, please let us know:") + msg += Sprintf(style.URL, "https://github.com/kubernetes/minikube/issues/new/choose\n") + msg += Sprintf(style.Empty, "Please attach the following file to the GitHub issue:") + msg += Sprintf(style.Empty, "- {{.logPath}}", V{"logPath": logPath}) + + Boxed(msg) } // applyTmpl applies formatting diff --git a/pkg/minikube/out/out_reason.go b/pkg/minikube/out/out_reason.go index 3907e2107e20..7b750ddfca17 100644 --- a/pkg/minikube/out/out_reason.go +++ b/pkg/minikube/out/out_reason.go @@ -113,8 +113,7 @@ func displayText(k reason.Kind, format string, a ...V) { if k.NewIssueLink { ErrT(style.Empty, "") - ErrT(style.Sad, "If the above advice does not help, please let us know: ") - ErrT(style.URL, "https://github.com/kubernetes/minikube/issues/new/choose") + displayGitHubIssueMessage() } Ln("") } diff --git a/pkg/minikube/out/out_test.go b/pkg/minikube/out/out_test.go index 9094be289c72..593222350aa7 100644 --- a/pkg/minikube/out/out_test.go +++ b/pkg/minikube/out/out_test.go @@ -19,9 +19,11 @@ package out import ( "fmt" "os" + "path/filepath" "strconv" "testing" + "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/style" "k8s.io/minikube/pkg/minikube/tests" "k8s.io/minikube/pkg/minikube/translate" @@ -114,3 +116,49 @@ func TestErr(t *testing.T) { t.Errorf("Err() = %q, want %q", got, want) } } + +func createLogFile() (string, error) { + td := os.TempDir() + name := filepath.Join(td, "minikube_test_test_test.log") + f, err := os.Create(name) + if err != nil { + return "", fmt.Errorf("failed to create log file: %v", err) + } + + return f.Name(), nil +} + +func TestLatestLogPath(t *testing.T) { + filename, err := createLogFile() + if err != nil { + t.Fatal(err) + } + defer os.Remove(filename) + + testCases := []struct { + args []string + want string + }{ + { + []string{"minikube", "start"}, + localpath.LastStartLog(), + }, + { + []string{"minikube", "status"}, + filename, + }, + } + + for _, tt := range testCases { + oldArgs := os.Args + defer func() { os.Args = oldArgs }() + os.Args = tt.args + got, err := latestLogFilePath() + if err != nil { + t.Fatalf("os.Args = %s; latestLogFilePath() failed with error = %v", tt.args, err) + } + if got != tt.want { + t.Errorf("os.Args = %s; latestLogFilePath() = %q; wanted %q", tt.args, got, tt.want) + } + } +}