Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 26 additions & 12 deletions pkg/minikube/out/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ var (
// JSON is whether or not we should output stdout in JSON format. Set using SetJSON()
JSON = false
// spin is spinner showed at starting minikube
spin = spinner.New(spinner.CharSets[style.SpinnerCharacter], 100*time.Millisecond)
spin = spinner.New(spinner.CharSets[style.SpinnerCharacter], 100*time.Millisecond, spinner.WithWriter(outFile))
// defaultBoxCfg is the default style config for cli box output
defaultBoxCfg = box.Config{Py: 1, Px: 4, Type: "Round", Color: "Red"}
)
Expand All @@ -91,7 +91,7 @@ func Step(st style.Enum, format string, a ...V) {
Infof(format, a...)
return
}
outStyled, _ := stylized(st, useColor, format, a...)
outStyled, _, _ := stylized(st, useColor, format, a...)
if JSON {
register.PrintStep(outStyled)
klog.Info(outStyled)
Expand All @@ -107,9 +107,9 @@ func Styled(st style.Enum, format string, a ...V) {
Infof(format, a...)
return
}
outStyled, useSpinner := stylized(st, useColor, format, a...)
outStyled, useSpinner, hideAfterSpin := stylized(st, useColor, format, a...)
if useSpinner {
spinnerString(outStyled)
spinnerString(outStyled, hideAfterSpin)
} else {
String(outStyled)
}
Expand Down Expand Up @@ -146,13 +146,13 @@ func BoxedWithConfig(cfg box.Config, st style.Enum, title string, text string, a

// Sprintf is used for returning the string (doesn't write anything)
func Sprintf(st style.Enum, format string, a ...V) string {
outStyled, _ := stylized(st, useColor, format, a...)
outStyled, _, _ := stylized(st, useColor, format, a...)
return outStyled
}

// Infof is used for informational logs (options, env variables, etc)
func Infof(format string, a ...V) {
outStyled, _ := stylized(style.Option, useColor, format, a...)
outStyled, _, _ := stylized(style.Option, useColor, format, a...)
if JSON {
register.PrintInfo(outStyled)
}
Expand Down Expand Up @@ -214,6 +214,21 @@ func Output(file fdWriter, s string) {
}
}

// outputSpining writes a basic string with spinining
func outputSpining(file fdWriter, s string, hideAfterSpin bool) {
spin.Writer = file
spin.Prefix = s
if hideAfterSpin {
spin.UpdateCharSet(spinner.CharSets[style.SpinnerSubStepCharacter])
spin.FinalMSG = ""
} else {
spin.UpdateCharSet(spinner.CharSets[style.SpinnerCharacter])
spin.FinalMSG = s + "\n"
}
spin.Start()

}

// Outputf writes a basic formatted string
func Outputf(file fdWriter, format string, a ...interface{}) {
_, err := fmt.Fprintf(file, format, a...)
Expand All @@ -223,7 +238,7 @@ func Outputf(file fdWriter, format string, a ...interface{}) {
}

// spinnerString writes a basic formatted string to stdout with spinner character
func spinnerString(s string) {
func spinnerString(s string, hideAfterSpin bool) {
// Flush log buffer so that output order makes sense
klog.Flush()

Expand All @@ -237,9 +252,7 @@ func spinnerString(s string) {
if spin.Active() {
spin.Stop()
}
Output(outFile, s)
// Start spinning at the end of the printed line
spin.Start()
outputSpining(outFile, s, hideAfterSpin)
}

// Ln writes a basic formatted string with a newline to stdout
Expand All @@ -249,7 +262,7 @@ func Ln(format string, a ...interface{}) {

// ErrT writes a stylized and templated error message to stderr
func ErrT(st style.Enum, format string, a ...V) {
errStyled, _ := stylized(st, useColor, format, a...)
errStyled, _, _ := stylized(st, useColor, format, a...)
Err(errStyled)
}

Expand Down Expand Up @@ -316,7 +329,7 @@ func WarningT(format string, a ...V) {
if spin.Active() {
spin.Stop()
}
st, _ := stylized(style.Warning, useColor, format, a...)
st, _, _ := stylized(style.Warning, useColor, format, a...)
register.PrintWarning(st)
klog.Warning(st)
return
Expand All @@ -343,6 +356,7 @@ func SetSilent(q bool) {
// SetOutFile configures which writer standard output goes to.
func SetOutFile(w fdWriter) {
klog.Infof("Setting OutFile to fd %d ...", w.Fd())
spin.Writer = w
outFile = w
useColor = wantsColor(w)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/out/out_reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,6 @@ func determineOutput(st style.Enum, format string, a ...V) {
ErrT(st, format, a...)
return
}
errStyled, _ := stylized(st, useColor, format, a...)
errStyled, _, _ := stylized(st, useColor, format, a...)
klog.Warning(errStyled)
}
20 changes: 11 additions & 9 deletions pkg/minikube/out/out_style.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,31 +31,33 @@ func applyPrefix(prefix, format string) string {
}

// applyStyle translates the given string if necessary then adds any appropriate style prefix.
func applyStyle(st style.Enum, useColor bool, format string) (string, bool) {
func applyStyle(st style.Enum, useColor bool, format string) (string, bool, bool) {
format = translate.T(format)

s, ok := style.Config[st]
if !s.OmitNewline {
// becaue of https://github.com/kubernetes/minikube/issues/21148
// will handle making new lines with spinner library itself
if !s.ShouldSpin {
format += "\n"
}

// Similar to CSS styles, if no style matches, output an unformatted string.
if !ok || JSON {
return format, s.Spinner
return format, s.ShouldSpin, s.HideAfterSpin
}

if !useColor {
return applyPrefix(style.LowPrefix(s), format), s.Spinner
return applyPrefix(style.LowPrefix(s), format), s.ShouldSpin, s.HideAfterSpin
}
return applyPrefix(s.Prefix, format), s.Spinner
return applyPrefix(s.Prefix, format), s.ShouldSpin, s.HideAfterSpin
}

// stylized applies formatting to the provided template
func stylized(st style.Enum, useColor bool, format string, a ...V) (string, bool) {
var spinner bool
func stylized(st style.Enum, useColor bool, format string, a ...V) (string, bool, bool) {
var shouldSpin, hideAfterSpin bool
if a == nil {
a = []V{}
}
format, spinner = applyStyle(st, useColor, format)
return Fmt(format, a...), spinner
format, shouldSpin, hideAfterSpin = applyStyle(st, useColor, format)
return Fmt(format, a...), shouldSpin, hideAfterSpin
}
4 changes: 2 additions & 2 deletions pkg/minikube/out/out_style_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestApplyStyle(t *testing.T) {
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
rawGot, _ := applyStyle(test.styleEnum, test.useColor, test.format)
rawGot, _, _ := applyStyle(test.styleEnum, test.useColor, test.format)
got := strings.TrimSpace(rawGot)
if got != test.expected {
t.Errorf("Expected '%v' but got '%v'", test.expected, got)
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestApplyTemplateFormating(t *testing.T) {
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
rawGot, _ := stylized(test.styleEnum, test.useColor, test.format, test.a...)
rawGot, _, _ := stylized(test.styleEnum, test.useColor, test.format, test.a...)
got := strings.TrimSpace(rawGot)
if got != test.expected {
t.Errorf("Expected '%v' but got '%v'", test.expected, got)
Expand Down
3 changes: 2 additions & 1 deletion pkg/minikube/out/out_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ func TestStep(t *testing.T) {
{style.Fatal, "Fatal: {{.error}}", V{"error": "ugh"}, "πŸ’£ Fatal: ugh\n", "X Fatal: ugh\n"},
{style.Issue, "http://i/{{.number}}", V{"number": 10000}, " β–ͺ http://i/10000\n", " - http://i/10000\n"},
{style.Usage, "raw: {{.one}} {{.two}}", V{"one": "'%'", "two": "%d"}, "πŸ’‘ raw: '%' %d\n", "* raw: '%' %d\n"},
{style.Running, "Installing Kubernetes version {{.version}} ...", V{"version": "v1.13"}, "πŸƒ ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n", "* ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n"},
// spining steps do not support being unit tested with fake file writer, since passing the fake writer to the spininer library is not testable.
{style.Provisioning, "Installing Kubernetes version {{.version}} ...", V{"version": "v1.13"}, "🌱 ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n", "* ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n"},
}
for _, tc := range testCases {
for _, override := range []bool{true, false} {
Expand Down
2 changes: 1 addition & 1 deletion pkg/minikube/registry/drvs/krunkit/krunkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) {

func status() registry.State {
if runtime.GOOS != "darwin" && runtime.GOARCH != "arm64" {
err := errors.New("The krunkit driver is only supported on macOS arm64 machines")
err := errors.New("the krunkit driver is only supported on macOS arm64 machines")
return registry.State{Error: err, Fix: "Use another driver", Doc: docURL}
}
if _, err := exec.LookPath("krunkit"); err != nil {
Expand Down
26 changes: 14 additions & 12 deletions pkg/minikube/style/style.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,17 @@ type Options struct {
Prefix string
// LowPrefix is the 7-bit compatible prefix we fallback to for less-awesome terminals
LowPrefix string
// OmitNewline omits a newline at the end of a message.
OmitNewline bool
// Spinner is a character to place at ending of message
Spinner bool
// ShouldSpin is a character to place at ending of message
ShouldSpin bool
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Inconsistent field alignment: ShouldSpin has extra spacing while HideAfterSpin doesn't. Consider aligning the fields consistently for better readability.

Suggested change
ShouldSpin bool
ShouldSpin bool

Copilot uses AI. Check for mistakes.
HideAfterSpin bool // Hide the prefix after spinning
}

// SpinnerCharacter is which of the spinner.CharSets to use
const SpinnerCharacter = 9

// SpinnerSubStepCharacter is Character to use for sub-steps in a spinner (it looks like a progress bar)
Copy link

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The constant SpinnerSubStepCharacter = 40 lacks explanation of what character index 40 represents or why it was chosen. Consider adding a comment explaining what this character looks like or referencing the character set documentation.

Suggested change
// SpinnerSubStepCharacter is Character to use for sub-steps in a spinner (it looks like a progress bar)
// SpinnerSubStepCharacter is the index of the character to use for sub-steps in a spinner (it looks like a progress bar).
// Index 40 in spinner.CharSets corresponds to the 'β–ˆ' (full block) character, which visually represents progress.
// See: https://github.com/briandowns/spinner/blob/master/spinner.go#L50 for the character set details.

Copilot uses AI. Check for mistakes.
const SpinnerSubStepCharacter = 40

// Config is a map of style name to style struct
// For consistency, ensure that emojis added render with the same width across platforms.
var Config = map[Enum]Options{
Expand All @@ -72,8 +74,8 @@ var Config = map[Enum]Options{
Pause: {Prefix: "⏸️ "},
Provisioning: {Prefix: "🌱 "},
Ready: {Prefix: "πŸ„ "},
Restarting: {Prefix: "πŸ”„ "},
Running: {Prefix: "πŸƒ "},
Restarting: {Prefix: "πŸ”„ ", ShouldSpin: true},
Running: {Prefix: "πŸƒ ", ShouldSpin: true}, // this is used when minikube start for a second time (already started)
Sparkle: {Prefix: "✨ "},
Stopped: {Prefix: "πŸ›‘ "},
Stopping: {Prefix: "βœ‹ "},
Expand All @@ -84,7 +86,7 @@ var Config = map[Enum]Options{
URL: {Prefix: "πŸ‘‰ ", LowPrefix: LowIndent},
Usage: {Prefix: "πŸ’‘ "},
Waiting: {Prefix: "βŒ› "},
WaitingWithSpinner: {Prefix: "βŒ› ", OmitNewline: true, Spinner: true},
WaitingWithSpinner: {Prefix: "βŒ› ", ShouldSpin: true},
Unsupported: {Prefix: "🚑 "},
Workaround: {Prefix: "πŸ‘‰ ", LowPrefix: LowIndent},

Expand Down Expand Up @@ -113,11 +115,11 @@ var Config = map[Enum]Options{
Copying: {Prefix: "✨ "},
CRIO: {Prefix: "🎁 "}, // This should be a snow-flake, but the emoji has a strange width on macOS
DeletingHost: {Prefix: "πŸ”₯ "},
Docker: {Prefix: "🐳 ", OmitNewline: true, Spinner: true},
Docker: {Prefix: "🐳 ", ShouldSpin: true},
DryRun: {Prefix: "🌡 "},
Enabling: {Prefix: "πŸ”Œ "},
FileDownload: {Prefix: "πŸ’Ύ "},
Fileserver: {Prefix: "πŸš€ ", OmitNewline: true},
Fileserver: {Prefix: "πŸš€ "},
HealthCheck: {Prefix: "πŸ”Ž "},
Internet: {Prefix: "🌐 "},
ISODownload: {Prefix: "πŸ’Ώ "},
Expand All @@ -132,11 +134,11 @@ var Config = map[Enum]Options{
Shutdown: {Prefix: "πŸ›‘ "},
StartingNone: {Prefix: "🀹 "},
StartingSSH: {Prefix: "πŸ”— "},
StartingVM: {Prefix: "πŸ”₯ ", OmitNewline: true, Spinner: true},
SubStep: {Prefix: " β–ͺ ", LowPrefix: LowIndentBullet, OmitNewline: true, Spinner: true},
StartingVM: {Prefix: "πŸ”₯ ", ShouldSpin: true},
SubStep: {Prefix: " β–ͺ ", LowPrefix: LowIndentBullet, ShouldSpin: true, HideAfterSpin: true},
Tip: {Prefix: "πŸ’‘ "},
Unmount: {Prefix: "πŸ”₯ "},
VerifyingNoLine: {Prefix: "πŸ€” ", OmitNewline: true},
VerifyingNoLine: {Prefix: "πŸ€” "},
Verifying: {Prefix: "πŸ€” "},
CNI: {Prefix: "πŸ”— "},
Toolkit: {Prefix: "πŸ› οΈ "},
Expand Down
10 changes: 0 additions & 10 deletions test/integration/error_spam_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,6 @@ func TestErrorSpam(t *testing.T) {
t.Logf("minikube stderr:\n%s", stderr)
}

steps := []string{
"Generating certificates and keys ...",
"Booting up control plane ...",
"Configuring RBAC rules ...",
}
for _, step := range steps {
if !strings.Contains(stdout, step) {
t.Errorf("missing kubeadm init sub-step %q", step)
}
}
})

logTests := []struct {
Expand Down
Loading