fix #612
parent
02312e1063
commit
0942ef5906
|
|
@ -21,6 +21,7 @@ As of this drop, you can now perform direct cluster nodes maintenance by leverag
|
||||||
|
|
||||||
## Resolved Bugs/Features/PRs
|
## Resolved Bugs/Features/PRs
|
||||||
|
|
||||||
|
- [Issue #612](https://github.com/derailed/k9s/issues/612)
|
||||||
- [Issue #608](https://github.com/derailed/k9s/issues/608)
|
- [Issue #608](https://github.com/derailed/k9s/issues/608)
|
||||||
- [Issue #606](https://github.com/derailed/k9s/issues/606)
|
- [Issue #606](https://github.com/derailed/k9s/issues/606)
|
||||||
- [Issue #237](https://github.com/derailed/k9s/issues/237)
|
- [Issue #237](https://github.com/derailed/k9s/issues/237)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
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()
|
meta := t.resourceMeta()
|
||||||
var (
|
var (
|
||||||
oo []runtime.Object
|
oo []runtime.Object
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,14 @@ package perf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
|
|
@ -17,8 +19,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
benchFmat = "%s_%s_%d.txt"
|
// BOZO!! Revisit bench and when we should timeout
|
||||||
k9sUA = "k9s/"
|
benchTimeout = 2 * time.Minute
|
||||||
|
benchFmat = "%s_%s_%d.txt"
|
||||||
|
k9sUA = "k9s/"
|
||||||
)
|
)
|
||||||
|
|
||||||
// K9sBenchDir directory to store K9s Benchmark files.
|
// K9sBenchDir directory to store K9s Benchmark files.
|
||||||
|
|
@ -29,6 +33,8 @@ type Benchmark struct {
|
||||||
canceled bool
|
canceled bool
|
||||||
config config.BenchConfig
|
config config.BenchConfig
|
||||||
worker *requester.Work
|
worker *requester.Work
|
||||||
|
cancelFn context.CancelFunc
|
||||||
|
mx sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBenchmark returns a new benchmark.
|
// 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 {
|
func (b *Benchmark) init(base, version string) error {
|
||||||
|
log.Debug().Msgf("BENCH-INIT")
|
||||||
req, err := http.NewRequest(b.config.HTTP.Method, base, nil)
|
req, err := http.NewRequest(b.config.HTTP.Method, base, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -51,6 +58,9 @@ func (b *Benchmark) init(base, version string) error {
|
||||||
req.SetBasicAuth(b.config.Auth.User, b.config.Auth.Password)
|
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
|
req.Header = b.config.HTTP.Headers
|
||||||
ua := req.UserAgent()
|
ua := req.UserAgent()
|
||||||
if ua == "" {
|
if ua == "" {
|
||||||
|
|
@ -80,11 +90,17 @@ func (b *Benchmark) init(base, version string) error {
|
||||||
|
|
||||||
// Cancel kills the benchmark in progress.
|
// Cancel kills the benchmark in progress.
|
||||||
func (b *Benchmark) Cancel() {
|
func (b *Benchmark) Cancel() {
|
||||||
|
b.mx.Lock()
|
||||||
|
defer b.mx.Unlock()
|
||||||
|
|
||||||
if b == nil {
|
if b == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.canceled = true
|
b.canceled = true
|
||||||
b.worker.Stop()
|
if b.cancelFn != nil {
|
||||||
|
b.cancelFn()
|
||||||
|
b.cancelFn = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Canceled checks if the benchmark was canceled.
|
// Canceled checks if the benchmark was canceled.
|
||||||
|
|
@ -94,10 +110,15 @@ func (b *Benchmark) Canceled() bool {
|
||||||
|
|
||||||
// Run starts a benchmark,
|
// Run starts a benchmark,
|
||||||
func (b *Benchmark) Run(cluster string, done func()) {
|
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)
|
buff := new(bytes.Buffer)
|
||||||
b.worker.Writer = buff
|
b.worker.Writer = buff
|
||||||
|
// this call will block until the benchmark is complete or timesout.
|
||||||
b.worker.Run()
|
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 {
|
if err := b.save(cluster, buff); err != nil {
|
||||||
log.Error().Err(err).Msg("Saving Benchmark")
|
log.Error().Err(err).Msg("Saving Benchmark")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/config"
|
"github.com/derailed/k9s/internal/config"
|
||||||
"github.com/derailed/tview"
|
"github.com/derailed/tview"
|
||||||
|
|
@ -49,6 +50,12 @@ func (l *Logo) StylesChanged(s *config.Styles) {
|
||||||
l.Reset()
|
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.
|
// Reset clears out the logo view and resets colors.
|
||||||
func (l *Logo) Reset() {
|
func (l *Logo) Reset() {
|
||||||
l.status.Clear()
|
l.status.Clear()
|
||||||
|
|
|
||||||
|
|
@ -273,7 +273,7 @@ func (t *Table) buildRow(r int, re, ore render.RowEvent, h render.Header, pads M
|
||||||
cell.SetAlign(h[c].Align)
|
cell.SetAlign(h[c].Align)
|
||||||
fgColor := color(t.GetModel().GetNamespace(), t.header, ore)
|
fgColor := color(t.GetModel().GetNamespace(), t.header, ore)
|
||||||
cell.SetTextColor(fgColor)
|
cell.SetTextColor(fgColor)
|
||||||
if marked && fgColor != render.ErrColor {
|
if marked {
|
||||||
cell.SetTextColor(t.styles.Table().MarkColor.Color())
|
cell.SetTextColor(t.styles.Table().MarkColor.Color())
|
||||||
}
|
}
|
||||||
if col == 0 {
|
if col == 0 {
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,6 @@ func (a *App) Run() error {
|
||||||
// Status reports a new app status for display.
|
// Status reports a new app status for display.
|
||||||
func (a *App) Status(l model.FlashLevel, msg string) {
|
func (a *App) Status(l model.FlashLevel, msg string) {
|
||||||
a.QueueUpdateDraw(func() {
|
a.QueueUpdateDraw(func() {
|
||||||
a.Flash().SetMessage(l, msg)
|
|
||||||
if a.showHeader {
|
if a.showHeader {
|
||||||
a.setLogo(l, msg)
|
a.setLogo(l, msg)
|
||||||
} else {
|
} 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.
|
// ClearStatus reset logo back to normal.
|
||||||
func (a *App) ClearStatus(flash bool) {
|
func (a *App) ClearStatus(flash bool) {
|
||||||
a.QueueUpdateDraw(func() {
|
a.QueueUpdateDraw(func() {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ type Browser struct {
|
||||||
|
|
||||||
// NewBrowser returns a new browser.
|
// NewBrowser returns a new browser.
|
||||||
func NewBrowser(gvr client.GVR) ResourceViewer {
|
func NewBrowser(gvr client.GVR) ResourceViewer {
|
||||||
log.Debug().Msgf("BRO %q", gvr)
|
log.Debug().Msgf("LOAD-VIEW %q", gvr)
|
||||||
return &Browser{
|
return &Browser{
|
||||||
Table: NewTable(gvr),
|
Table: NewTable(gvr),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ func (c *ClusterInfo) setDefCon(cpu, mem int) {
|
||||||
c.app.Status(flashLevel(l), fmt.Sprintf(defconFmt, flashMessage(l), "Memory"))
|
c.app.Status(flashLevel(l), fmt.Sprintf(defconFmt, flashMessage(l), "Memory"))
|
||||||
set = true
|
set = true
|
||||||
}
|
}
|
||||||
if !set {
|
if !set && !c.app.IsBenchmarking() {
|
||||||
c.app.ClearStatus(true)
|
c.app.ClearStatus(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ func NewService(gvr client.GVR) ResourceViewer {
|
||||||
|
|
||||||
func (s *Service) bindKeys(aa ui.KeyActions) {
|
func (s *Service) bindKeys(aa ui.KeyActions) {
|
||||||
aa.Add(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),
|
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) {
|
func (s *Service) getExternalPort(svc *v1.Service) (string, error) {
|
||||||
|
if svc.Spec.Type == "LoadBalancer" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
ports := render.ToPorts(svc.Spec.Ports)
|
ports := render.ToPorts(svc.Spec.Ports)
|
||||||
pp := strings.Split(ports, " ")
|
pp := strings.Split(ports, " ")
|
||||||
// Grap the first port pair for now...
|
// 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)
|
cust, err := config.NewBench(s.App().BenchFile)
|
||||||
if err != nil {
|
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]
|
cfg, ok := cust.Benchmarks.Services[path]
|
||||||
if !ok {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
cfg.Name = path
|
cfg.Name = path
|
||||||
|
|
@ -161,14 +164,14 @@ func (s *Service) benchDone() {
|
||||||
s.bench.Cancel()
|
s.bench.Cancel()
|
||||||
}
|
}
|
||||||
s.bench = nil
|
s.bench = nil
|
||||||
go benchTimedOut(s.App())
|
go clearStatus(s.App())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
func benchTimedOut(app *App) {
|
func clearStatus(app *App) {
|
||||||
<-time.After(2 * time.Second)
|
<-time.After(2 * time.Second)
|
||||||
app.QueueUpdate(func() {
|
app.QueueUpdate(func() {
|
||||||
app.ClearStatus(true)
|
app.ClearStatus(true)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue