Skip to content

Commit 95d4cfe

Browse files
authored
Refactor spinner library & hide sub steps after spinning (#21215)
* remove omitnew line * add new option to hide after spin * refactor to use new return hideAfterSpin * add new line by default only when not spinining and delegate spinner newline to spinner code * add new func for ouptputing with spinner and pass fdwriter directly to the spininer func * fix unit test * fix lint for krunkit * add comment and context * use different spinning progress bar for sub steps * make func private * making more spinning icons * integration test dont expect sub steps to be visible * fix unit test and comment why * change sub step spining icon not to be a progressbar * pass the filewriter to the spinner library for the spinning steps
1 parent 0edde17 commit 95d4cfe

File tree

8 files changed

+57
-48
lines changed

8 files changed

+57
-48
lines changed

β€Žpkg/minikube/out/out.go

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ var (
6666
// JSON is whether or not we should output stdout in JSON format. Set using SetJSON()
6767
JSON = false
6868
// spin is spinner showed at starting minikube
69-
spin = spinner.New(spinner.CharSets[style.SpinnerCharacter], 100*time.Millisecond)
69+
spin = spinner.New(spinner.CharSets[style.SpinnerCharacter], 100*time.Millisecond, spinner.WithWriter(outFile))
7070
// defaultBoxCfg is the default style config for cli box output
7171
defaultBoxCfg = box.Config{Py: 1, Px: 4, Type: "Round", Color: "Red"}
7272
)
@@ -91,7 +91,7 @@ func Step(st style.Enum, format string, a ...V) {
9191
Infof(format, a...)
9292
return
9393
}
94-
outStyled, _ := stylized(st, useColor, format, a...)
94+
outStyled, _, _ := stylized(st, useColor, format, a...)
9595
if JSON {
9696
register.PrintStep(outStyled)
9797
klog.Info(outStyled)
@@ -107,9 +107,9 @@ func Styled(st style.Enum, format string, a ...V) {
107107
Infof(format, a...)
108108
return
109109
}
110-
outStyled, useSpinner := stylized(st, useColor, format, a...)
110+
outStyled, useSpinner, hideAfterSpin := stylized(st, useColor, format, a...)
111111
if useSpinner {
112-
spinnerString(outStyled)
112+
spinnerString(outStyled, hideAfterSpin)
113113
} else {
114114
String(outStyled)
115115
}
@@ -146,13 +146,13 @@ func BoxedWithConfig(cfg box.Config, st style.Enum, title string, text string, a
146146

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

153153
// Infof is used for informational logs (options, env variables, etc)
154154
func Infof(format string, a ...V) {
155-
outStyled, _ := stylized(style.Option, useColor, format, a...)
155+
outStyled, _, _ := stylized(style.Option, useColor, format, a...)
156156
if JSON {
157157
register.PrintInfo(outStyled)
158158
}
@@ -214,6 +214,21 @@ func Output(file fdWriter, s string) {
214214
}
215215
}
216216

217+
// outputSpining writes a basic string with spinining
218+
func outputSpining(file fdWriter, s string, hideAfterSpin bool) {
219+
spin.Writer = file
220+
spin.Prefix = s
221+
if hideAfterSpin {
222+
spin.UpdateCharSet(spinner.CharSets[style.SpinnerSubStepCharacter])
223+
spin.FinalMSG = ""
224+
} else {
225+
spin.UpdateCharSet(spinner.CharSets[style.SpinnerCharacter])
226+
spin.FinalMSG = s + "\n"
227+
}
228+
spin.Start()
229+
230+
}
231+
217232
// Outputf writes a basic formatted string
218233
func Outputf(file fdWriter, format string, a ...interface{}) {
219234
_, err := fmt.Fprintf(file, format, a...)
@@ -223,7 +238,7 @@ func Outputf(file fdWriter, format string, a ...interface{}) {
223238
}
224239

225240
// spinnerString writes a basic formatted string to stdout with spinner character
226-
func spinnerString(s string) {
241+
func spinnerString(s string, hideAfterSpin bool) {
227242
// Flush log buffer so that output order makes sense
228243
klog.Flush()
229244

@@ -237,9 +252,7 @@ func spinnerString(s string) {
237252
if spin.Active() {
238253
spin.Stop()
239254
}
240-
Output(outFile, s)
241-
// Start spinning at the end of the printed line
242-
spin.Start()
255+
outputSpining(outFile, s, hideAfterSpin)
243256
}
244257

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

250263
// ErrT writes a stylized and templated error message to stderr
251264
func ErrT(st style.Enum, format string, a ...V) {
252-
errStyled, _ := stylized(st, useColor, format, a...)
265+
errStyled, _, _ := stylized(st, useColor, format, a...)
253266
Err(errStyled)
254267
}
255268

@@ -316,7 +329,7 @@ func WarningT(format string, a ...V) {
316329
if spin.Active() {
317330
spin.Stop()
318331
}
319-
st, _ := stylized(style.Warning, useColor, format, a...)
332+
st, _, _ := stylized(style.Warning, useColor, format, a...)
320333
register.PrintWarning(st)
321334
klog.Warning(st)
322335
return
@@ -343,6 +356,7 @@ func SetSilent(q bool) {
343356
// SetOutFile configures which writer standard output goes to.
344357
func SetOutFile(w fdWriter) {
345358
klog.Infof("Setting OutFile to fd %d ...", w.Fd())
359+
spin.Writer = w
346360
outFile = w
347361
useColor = wantsColor(w)
348362
}

β€Žpkg/minikube/out/out_reason.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,6 @@ func determineOutput(st style.Enum, format string, a ...V) {
106106
ErrT(st, format, a...)
107107
return
108108
}
109-
errStyled, _ := stylized(st, useColor, format, a...)
109+
errStyled, _, _ := stylized(st, useColor, format, a...)
110110
klog.Warning(errStyled)
111111
}

β€Žpkg/minikube/out/out_style.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,33 @@ func applyPrefix(prefix, format string) string {
3131
}
3232

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

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

4244
// Similar to CSS styles, if no style matches, output an unformatted string.
4345
if !ok || JSON {
44-
return format, s.Spinner
46+
return format, s.ShouldSpin, s.HideAfterSpin
4547
}
4648

4749
if !useColor {
48-
return applyPrefix(style.LowPrefix(s), format), s.Spinner
50+
return applyPrefix(style.LowPrefix(s), format), s.ShouldSpin, s.HideAfterSpin
4951
}
50-
return applyPrefix(s.Prefix, format), s.Spinner
52+
return applyPrefix(s.Prefix, format), s.ShouldSpin, s.HideAfterSpin
5153
}
5254

5355
// stylized applies formatting to the provided template
54-
func stylized(st style.Enum, useColor bool, format string, a ...V) (string, bool) {
55-
var spinner bool
56+
func stylized(st style.Enum, useColor bool, format string, a ...V) (string, bool, bool) {
57+
var shouldSpin, hideAfterSpin bool
5658
if a == nil {
5759
a = []V{}
5860
}
59-
format, spinner = applyStyle(st, useColor, format)
60-
return Fmt(format, a...), spinner
61+
format, shouldSpin, hideAfterSpin = applyStyle(st, useColor, format)
62+
return Fmt(format, a...), shouldSpin, hideAfterSpin
6163
}

β€Žpkg/minikube/out/out_style_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ func TestApplyStyle(t *testing.T) {
8383
}
8484
for _, test := range tests {
8585
t.Run(test.description, func(t *testing.T) {
86-
rawGot, _ := applyStyle(test.styleEnum, test.useColor, test.format)
86+
rawGot, _, _ := applyStyle(test.styleEnum, test.useColor, test.format)
8787
got := strings.TrimSpace(rawGot)
8888
if got != test.expected {
8989
t.Errorf("Expected '%v' but got '%v'", test.expected, got)
@@ -139,7 +139,7 @@ func TestApplyTemplateFormating(t *testing.T) {
139139
}
140140
for _, test := range tests {
141141
t.Run(test.description, func(t *testing.T) {
142-
rawGot, _ := stylized(test.styleEnum, test.useColor, test.format, test.a...)
142+
rawGot, _, _ := stylized(test.styleEnum, test.useColor, test.format, test.a...)
143143
got := strings.TrimSpace(rawGot)
144144
if got != test.expected {
145145
t.Errorf("Expected '%v' but got '%v'", test.expected, got)

β€Žpkg/minikube/out/out_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ func TestStep(t *testing.T) {
5454
{style.Fatal, "Fatal: {{.error}}", V{"error": "ugh"}, "πŸ’£ Fatal: ugh\n", "X Fatal: ugh\n"},
5555
{style.Issue, "http://i/{{.number}}", V{"number": 10000}, " β–ͺ http://i/10000\n", " - http://i/10000\n"},
5656
{style.Usage, "raw: {{.one}} {{.two}}", V{"one": "'%'", "two": "%d"}, "πŸ’‘ raw: '%' %d\n", "* raw: '%' %d\n"},
57-
{style.Running, "Installing Kubernetes version {{.version}} ...", V{"version": "v1.13"}, "πŸƒ ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n", "* ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n"},
57+
// spining steps do not support being unit tested with fake file writer, since passing the fake writer to the spininer library is not testable.
58+
{style.Provisioning, "Installing Kubernetes version {{.version}} ...", V{"version": "v1.13"}, "🌱 ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n", "* ... v1.13 ΨͺثبيΨͺ Kubernetes Ψ§Ω„Ψ₯Ψ΅Ψ―Ψ§Ψ±\n"},
5859
}
5960
for _, tc := range testCases {
6061
for _, override := range []bool{true, false} {

β€Žpkg/minikube/registry/drvs/krunkit/krunkit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func configure(cfg config.ClusterConfig, n config.Node) (interface{}, error) {
8787

8888
func status() registry.State {
8989
if runtime.GOOS != "darwin" && runtime.GOARCH != "arm64" {
90-
err := errors.New("The krunkit driver is only supported on macOS arm64 machines")
90+
err := errors.New("the krunkit driver is only supported on macOS arm64 machines")
9191
return registry.State{Error: err, Fix: "Use another driver", Doc: docURL}
9292
}
9393
if _, err := exec.LookPath("krunkit"); err != nil {

β€Žpkg/minikube/style/style.go

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,17 @@ type Options struct {
4141
Prefix string
4242
// LowPrefix is the 7-bit compatible prefix we fallback to for less-awesome terminals
4343
LowPrefix string
44-
// OmitNewline omits a newline at the end of a message.
45-
OmitNewline bool
46-
// Spinner is a character to place at ending of message
47-
Spinner bool
44+
// ShouldSpin is a character to place at ending of message
45+
ShouldSpin bool
46+
HideAfterSpin bool // Hide the prefix after spinning
4847
}
4948

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

52+
// SpinnerSubStepCharacter is Character to use for sub-steps in a spinner (it looks like a progress bar)
53+
const SpinnerSubStepCharacter = 40
54+
5355
// Config is a map of style name to style struct
5456
// For consistency, ensure that emojis added render with the same width across platforms.
5557
var Config = map[Enum]Options{
@@ -72,8 +74,8 @@ var Config = map[Enum]Options{
7274
Pause: {Prefix: "⏸️ "},
7375
Provisioning: {Prefix: "🌱 "},
7476
Ready: {Prefix: "πŸ„ "},
75-
Restarting: {Prefix: "πŸ”„ "},
76-
Running: {Prefix: "πŸƒ "},
77+
Restarting: {Prefix: "πŸ”„ ", ShouldSpin: true},
78+
Running: {Prefix: "πŸƒ ", ShouldSpin: true}, // this is used when minikube start for a second time (already started)
7779
Sparkle: {Prefix: "✨ "},
7880
Stopped: {Prefix: "πŸ›‘ "},
7981
Stopping: {Prefix: "βœ‹ "},
@@ -84,7 +86,7 @@ var Config = map[Enum]Options{
8486
URL: {Prefix: "πŸ‘‰ ", LowPrefix: LowIndent},
8587
Usage: {Prefix: "πŸ’‘ "},
8688
Waiting: {Prefix: "βŒ› "},
87-
WaitingWithSpinner: {Prefix: "βŒ› ", OmitNewline: true, Spinner: true},
89+
WaitingWithSpinner: {Prefix: "βŒ› ", ShouldSpin: true},
8890
Unsupported: {Prefix: "🚑 "},
8991
Workaround: {Prefix: "πŸ‘‰ ", LowPrefix: LowIndent},
9092

@@ -113,11 +115,11 @@ var Config = map[Enum]Options{
113115
Copying: {Prefix: "✨ "},
114116
CRIO: {Prefix: "🎁 "}, // This should be a snow-flake, but the emoji has a strange width on macOS
115117
DeletingHost: {Prefix: "πŸ”₯ "},
116-
Docker: {Prefix: "🐳 ", OmitNewline: true, Spinner: true},
118+
Docker: {Prefix: "🐳 ", ShouldSpin: true},
117119
DryRun: {Prefix: "🌡 "},
118120
Enabling: {Prefix: "πŸ”Œ "},
119121
FileDownload: {Prefix: "πŸ’Ύ "},
120-
Fileserver: {Prefix: "πŸš€ ", OmitNewline: true},
122+
Fileserver: {Prefix: "πŸš€ "},
121123
HealthCheck: {Prefix: "πŸ”Ž "},
122124
Internet: {Prefix: "🌐 "},
123125
ISODownload: {Prefix: "πŸ’Ώ "},
@@ -132,11 +134,11 @@ var Config = map[Enum]Options{
132134
Shutdown: {Prefix: "πŸ›‘ "},
133135
StartingNone: {Prefix: "🀹 "},
134136
StartingSSH: {Prefix: "πŸ”— "},
135-
StartingVM: {Prefix: "πŸ”₯ ", OmitNewline: true, Spinner: true},
136-
SubStep: {Prefix: " β–ͺ ", LowPrefix: LowIndentBullet, OmitNewline: true, Spinner: true},
137+
StartingVM: {Prefix: "πŸ”₯ ", ShouldSpin: true},
138+
SubStep: {Prefix: " β–ͺ ", LowPrefix: LowIndentBullet, ShouldSpin: true, HideAfterSpin: true},
137139
Tip: {Prefix: "πŸ’‘ "},
138140
Unmount: {Prefix: "πŸ”₯ "},
139-
VerifyingNoLine: {Prefix: "πŸ€” ", OmitNewline: true},
141+
VerifyingNoLine: {Prefix: "πŸ€” "},
140142
Verifying: {Prefix: "πŸ€” "},
141143
CNI: {Prefix: "πŸ”— "},
142144
Toolkit: {Prefix: "πŸ› οΈ "},

β€Žtest/integration/error_spam_test.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,6 @@ func TestErrorSpam(t *testing.T) {
111111
t.Logf("minikube stderr:\n%s", stderr)
112112
}
113113

114-
steps := []string{
115-
"Generating certificates and keys ...",
116-
"Booting up control plane ...",
117-
"Configuring RBAC rules ...",
118-
}
119-
for _, step := range steps {
120-
if !strings.Contains(stdout, step) {
121-
t.Errorf("missing kubeadm init sub-step %q", step)
122-
}
123-
}
124114
})
125115

126116
logTests := []struct {

0 commit comments

Comments
Β (0)