diff --git a/change_logs/release_v0.17.6.md b/change_logs/release_v0.17.6.md index e6957fd7..1f600419 100644 --- a/change_logs/release_v0.17.6.md +++ b/change_logs/release_v0.17.6.md @@ -21,6 +21,7 @@ As of this drop, you can now perform direct cluster nodes maintenance by leverag ## Resolved Bugs/Features/PRs +- [Issue #612](https://github.com/derailed/k9s/issues/612) - [Issue #608](https://github.com/derailed/k9s/issues/608) - [Issue #606](https://github.com/derailed/k9s/issues/606) - [Issue #237](https://github.com/derailed/k9s/issues/237) diff --git a/internal/model/table.go b/internal/model/table.go index 3d06edc3..d6f72ad5 100644 --- a/internal/model/table.go +++ b/internal/model/table.go @@ -224,10 +224,6 @@ func (t *Table) list(ctx context.Context, a dao.Accessor) ([]runtime.Object, err } func (t *Table) reconcile(ctx context.Context) error { - defer func(ti time.Time) { - log.Debug().Msgf("Elapsed %v %v", t.gvr, time.Since(ti)) - }(time.Now()) - meta := t.resourceMeta() var ( oo []runtime.Object diff --git a/internal/perf/benchmark.go b/internal/perf/benchmark.go index cbb669b8..ea4a1249 100644 --- a/internal/perf/benchmark.go +++ b/internal/perf/benchmark.go @@ -2,12 +2,14 @@ package perf import ( "bytes" + "context" "fmt" "io" "io/ioutil" "net/http" "os" "path/filepath" + "sync" "time" "github.com/derailed/k9s/internal/client" @@ -17,8 +19,10 @@ import ( ) const ( - benchFmat = "%s_%s_%d.txt" - k9sUA = "k9s/" + // BOZO!! Revisit bench and when we should timeout + benchTimeout = 2 * time.Minute + benchFmat = "%s_%s_%d.txt" + k9sUA = "k9s/" ) // K9sBenchDir directory to store K9s Benchmark files. @@ -29,6 +33,8 @@ type Benchmark struct { canceled bool config config.BenchConfig worker *requester.Work + cancelFn context.CancelFunc + mx sync.RWMutex } // NewBenchmark returns a new benchmark. @@ -41,6 +47,7 @@ func NewBenchmark(base, version string, cfg config.BenchConfig) (*Benchmark, err } func (b *Benchmark) init(base, version string) error { + log.Debug().Msgf("BENCH-INIT") req, err := http.NewRequest(b.config.HTTP.Method, base, nil) if err != nil { return err @@ -51,6 +58,9 @@ func (b *Benchmark) init(base, version string) error { req.SetBasicAuth(b.config.Auth.User, b.config.Auth.Password) } + var ctx context.Context + ctx, b.cancelFn = context.WithTimeout(context.Background(), benchTimeout) + req = req.WithContext(ctx) req.Header = b.config.HTTP.Headers ua := req.UserAgent() if ua == "" { @@ -80,11 +90,17 @@ func (b *Benchmark) init(base, version string) error { // Cancel kills the benchmark in progress. func (b *Benchmark) Cancel() { + b.mx.Lock() + defer b.mx.Unlock() + if b == nil { return } b.canceled = true - b.worker.Stop() + if b.cancelFn != nil { + b.cancelFn() + b.cancelFn = nil + } } // Canceled checks if the benchmark was canceled. @@ -94,10 +110,15 @@ func (b *Benchmark) Canceled() bool { // Run starts a benchmark, func (b *Benchmark) Run(cluster string, done func()) { + log.Debug().Msgf("Running benchmark on cluster %s", cluster) + log.Debug().Msgf("BENCH-CFG %#v", b.worker) buff := new(bytes.Buffer) b.worker.Writer = buff + // this call will block until the benchmark is complete or timesout. b.worker.Run() - if !b.canceled { + b.worker.Stop() + log.Debug().Msgf("YO!! %t %s", b.canceled, buff) + if len(buff.Bytes()) > 0 { if err := b.save(cluster, buff); err != nil { log.Error().Err(err).Msg("Saving Benchmark") } diff --git a/internal/ui/logo.go b/internal/ui/logo.go index f29b58c4..80c63199 100644 --- a/internal/ui/logo.go +++ b/internal/ui/logo.go @@ -2,6 +2,7 @@ package ui import ( "fmt" + "strings" "github.com/derailed/k9s/internal/config" "github.com/derailed/tview" @@ -49,6 +50,12 @@ func (l *Logo) StylesChanged(s *config.Styles) { l.Reset() } +// IsBenchmarking checks if benchmarking is active or not. +func (l *Logo) IsBenchmarking() bool { + txt := l.Status().GetText(true) + return strings.Contains(txt, "Bench") +} + // Reset clears out the logo view and resets colors. func (l *Logo) Reset() { l.status.Clear() diff --git a/internal/ui/table.go b/internal/ui/table.go index 7fd4901a..eae9122f 100644 --- a/internal/ui/table.go +++ b/internal/ui/table.go @@ -273,7 +273,7 @@ func (t *Table) buildRow(r int, re, ore render.RowEvent, h render.Header, pads M cell.SetAlign(h[c].Align) fgColor := color(t.GetModel().GetNamespace(), t.header, ore) cell.SetTextColor(fgColor) - if marked && fgColor != render.ErrColor { + if marked { cell.SetTextColor(t.styles.Table().MarkColor.Color()) } if col == 0 { diff --git a/internal/view/app.go b/internal/view/app.go index 215752ae..f0bd449a 100644 --- a/internal/view/app.go +++ b/internal/view/app.go @@ -342,7 +342,6 @@ func (a *App) Run() error { // Status reports a new app status for display. func (a *App) Status(l model.FlashLevel, msg string) { a.QueueUpdateDraw(func() { - a.Flash().SetMessage(l, msg) if a.showHeader { a.setLogo(l, msg) } else { @@ -351,6 +350,11 @@ func (a *App) Status(l model.FlashLevel, msg string) { }) } +// IsBenchmarking check if benchmarks are active. +func (a *App) IsBenchmarking() bool { + return a.Logo().IsBenchmarking() +} + // ClearStatus reset logo back to normal. func (a *App) ClearStatus(flash bool) { a.QueueUpdateDraw(func() { diff --git a/internal/view/browser.go b/internal/view/browser.go index eaf0e797..2284e9dc 100644 --- a/internal/view/browser.go +++ b/internal/view/browser.go @@ -32,7 +32,7 @@ type Browser struct { // NewBrowser returns a new browser. func NewBrowser(gvr client.GVR) ResourceViewer { - log.Debug().Msgf("BRO %q", gvr) + log.Debug().Msgf("LOAD-VIEW %q", gvr) return &Browser{ Table: NewTable(gvr), } diff --git a/internal/view/cluster_info.go b/internal/view/cluster_info.go index 552d6338..cedf58b8 100644 --- a/internal/view/cluster_info.go +++ b/internal/view/cluster_info.go @@ -115,7 +115,7 @@ func (c *ClusterInfo) setDefCon(cpu, mem int) { c.app.Status(flashLevel(l), fmt.Sprintf(defconFmt, flashMessage(l), "Memory")) set = true } - if !set { + if !set && !c.app.IsBenchmarking() { c.app.ClearStatus(true) } } diff --git a/internal/view/svc.go b/internal/view/svc.go index 6f7d9509..6af77dac 100644 --- a/internal/view/svc.go +++ b/internal/view/svc.go @@ -45,7 +45,7 @@ func NewService(gvr client.GVR) ResourceViewer { func (s *Service) bindKeys(aa ui.KeyActions) { aa.Add(ui.KeyActions{ - tcell.KeyCtrlB: ui.NewKeyAction("Bench Run/Stop", s.toggleBenchCmd, true), + tcell.KeyCtrlL: ui.NewKeyAction("Bench Run/Stop", s.toggleBenchCmd, true), ui.KeyShiftT: ui.NewKeyAction("Sort Type", s.GetTable().SortColCmd("TYPE", true), false), }) } @@ -71,6 +71,9 @@ func (s *Service) checkSvc(svc *v1.Service) error { } func (s *Service) getExternalPort(svc *v1.Service) (string, error) { + if svc.Spec.Type == "LoadBalancer" { + return "", nil + } ports := render.ToPorts(svc.Spec.Ports) pp := strings.Split(ports, " ") // Grap the first port pair for now... @@ -98,12 +101,12 @@ func (s *Service) toggleBenchCmd(evt *tcell.EventKey) *tcell.EventKey { cust, err := config.NewBench(s.App().BenchFile) if err != nil { - log.Debug().Msgf("No custom benchmark config file found") + log.Debug().Msgf("No bench config file found %s", s.App().BenchFile) } cfg, ok := cust.Benchmarks.Services[path] if !ok { - s.App().Flash().Errf("No bench config found for service %s", path) + s.App().Flash().Errf("No bench config found for service %s in %s", path, s.App().BenchFile) return nil } cfg.Name = path @@ -161,14 +164,14 @@ func (s *Service) benchDone() { s.bench.Cancel() } s.bench = nil - go benchTimedOut(s.App()) + go clearStatus(s.App()) }) } // ---------------------------------------------------------------------------- // Helpers... -func benchTimedOut(app *App) { +func clearStatus(app *App) { <-time.After(2 * time.Second) app.QueueUpdate(func() { app.ClearStatus(true)