checkpoint
parent
355f4ce396
commit
98b07e6961
|
|
@ -14,3 +14,4 @@ gen.sh
|
||||||
*.log
|
*.log
|
||||||
*~
|
*~
|
||||||
faas
|
faas
|
||||||
|
demos
|
||||||
|
|
@ -210,9 +210,9 @@ func newStyle() Style {
|
||||||
|
|
||||||
func newCharts() Charts {
|
func newCharts() Charts {
|
||||||
return Charts{
|
return Charts{
|
||||||
BgColor: "#111111",
|
BgColor: "default",
|
||||||
DialBgColor: "#111111",
|
DialBgColor: "default",
|
||||||
ChartBgColor: "#111111",
|
ChartBgColor: "default",
|
||||||
DefaultDialColors: Colors{Color("palegreen"), Color("orangered")},
|
DefaultDialColors: Colors{Color("palegreen"), Color("orangered")},
|
||||||
DefaultChartColors: Colors{Color("palegreen"), Color("orangered")},
|
DefaultChartColors: Colors{Color("palegreen"), Color("orangered")},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultRefreshRate = 5 * time.Second
|
||||||
|
|
||||||
// PulseListener represents a health model listener.
|
// PulseListener represents a health model listener.
|
||||||
type PulseListener interface {
|
type PulseListener interface {
|
||||||
// PulseChanged notifies the model data changed.
|
// PulseChanged notifies the model data changed.
|
||||||
|
|
@ -29,14 +31,14 @@ type Pulse struct {
|
||||||
inUpdate int32
|
inUpdate int32
|
||||||
listeners []PulseListener
|
listeners []PulseListener
|
||||||
refreshRate time.Duration
|
refreshRate time.Duration
|
||||||
health *Health
|
health *PulseHealth
|
||||||
data health.Checks
|
data health.Checks
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPulse(gvr string) *Pulse {
|
func NewPulse(gvr string) *Pulse {
|
||||||
return &Pulse{
|
return &Pulse{
|
||||||
gvr: gvr,
|
gvr: gvr,
|
||||||
refreshRate: 2 * time.Second,
|
refreshRate: defaultRefreshRate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +50,7 @@ func (p *Pulse) Watch(ctx context.Context) {
|
||||||
func (p *Pulse) updater(ctx context.Context) {
|
func (p *Pulse) updater(ctx context.Context) {
|
||||||
defer log.Debug().Msgf("Pulse canceled -- %q", p.gvr)
|
defer log.Debug().Msgf("Pulse canceled -- %q", p.gvr)
|
||||||
|
|
||||||
rate := initTreeRefreshRate
|
rate := initRefreshRate
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
|
|
@ -88,7 +90,7 @@ func (p *Pulse) list(ctx context.Context) ([]runtime.Object, error) {
|
||||||
return nil, fmt.Errorf("expected Factory in context but got %T", ctx.Value(internal.KeyFactory))
|
return nil, fmt.Errorf("expected Factory in context but got %T", ctx.Value(internal.KeyFactory))
|
||||||
}
|
}
|
||||||
if p.health == nil {
|
if p.health == nil {
|
||||||
p.health = NewHealth(f)
|
p.health = NewPulseHealth(f)
|
||||||
}
|
}
|
||||||
ctx = context.WithValue(ctx, internal.KeyFields, "")
|
ctx = context.WithValue(ctx, internal.KeyFields, "")
|
||||||
ctx = context.WithValue(ctx, internal.KeyWithMetrics, false)
|
ctx = context.WithValue(ctx, internal.KeyWithMetrics, false)
|
||||||
|
|
|
||||||
|
|
@ -14,19 +14,19 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Health struct {
|
type PulseHealth struct {
|
||||||
factory dao.Factory
|
factory dao.Factory
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHealth(f dao.Factory) *Health {
|
func NewPulseHealth(f dao.Factory) *PulseHealth {
|
||||||
return &Health{
|
return &PulseHealth{
|
||||||
factory: f,
|
factory: f,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Health) List(ctx context.Context, ns string) ([]runtime.Object, error) {
|
func (h *PulseHealth) List(ctx context.Context, ns string) ([]runtime.Object, error) {
|
||||||
defer func(t time.Time) {
|
defer func(t time.Time) {
|
||||||
log.Debug().Msgf("HealthCheck %v", time.Since(t))
|
log.Debug().Msgf("PulseHealthCheck %v", time.Since(t))
|
||||||
}(time.Now())
|
}(time.Now())
|
||||||
|
|
||||||
gvrs := []string{
|
gvrs := []string{
|
||||||
|
|
@ -60,7 +60,7 @@ func (h *Health) List(ctx context.Context, ns string) ([]runtime.Object, error)
|
||||||
return hh, nil
|
return hh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Health) checkMetrics() (health.Checks, error) {
|
func (h *PulseHealth) checkMetrics() (health.Checks, error) {
|
||||||
dial := client.DialMetrics(h.factory.Client())
|
dial := client.DialMetrics(h.factory.Client())
|
||||||
nmx, err := dial.FetchNodesMetrics()
|
nmx, err := dial.FetchNodesMetrics()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -81,11 +81,7 @@ func (h *Health) checkMetrics() (health.Checks, error) {
|
||||||
return health.Checks{c1, c2}, nil
|
return health.Checks{c1, c2}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Health) check(ctx context.Context, ns, gvr string) (*health.Check, error) {
|
func (h *PulseHealth) check(ctx context.Context, ns, gvr string) (*health.Check, error) {
|
||||||
defer func(t time.Time) {
|
|
||||||
log.Debug().Msgf(" CHECK %s - %v", gvr, time.Since(t))
|
|
||||||
}(time.Now())
|
|
||||||
|
|
||||||
meta, ok := Registry[gvr]
|
meta, ok := Registry[gvr]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("No meta for %q", gvr)
|
return nil, fmt.Errorf("No meta for %q", gvr)
|
||||||
|
|
@ -31,7 +31,7 @@ func NewComponent(id string) *Component {
|
||||||
return &Component{
|
return &Component{
|
||||||
Box: tview.NewBox(),
|
Box: tview.NewBox(),
|
||||||
id: id,
|
id: id,
|
||||||
noColor: tcell.ColorBlack,
|
noColor: tcell.ColorDefault,
|
||||||
seriesColors: []tcell.Color{tview.Styles.PrimaryTextColor, tview.Styles.FocusColor},
|
seriesColors: []tcell.Color{tview.Styles.PrimaryTextColor, tview.Styles.FocusColor},
|
||||||
dimmed: tcell.StyleDefault.Background(tview.Styles.PrimitiveBackgroundColor).Foreground(tcell.ColorGray).Dim(true),
|
dimmed: tcell.StyleDefault.Background(tview.Styles.PrimitiveBackgroundColor).Foreground(tcell.ColorGray).Dim(true),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ func TestDial(t *testing.T) {
|
||||||
|
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
const hChar, vChar = '⠶', '⠿'
|
const hChar, vChar = '▤', '▥'
|
||||||
|
|
||||||
var numbers = []tchart.Matrix{
|
var numbers = []tchart.Matrix{
|
||||||
[][]rune{
|
[][]rune{
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,9 @@ func (g *Gauge) drawNum(sc tcell.Screen, ok bool, o image.Point, n int, dn delta
|
||||||
}
|
}
|
||||||
|
|
||||||
dm, sig := NewDotMatrix(5, 3), n == 0
|
dm, sig := NewDotMatrix(5, 3), n == 0
|
||||||
|
if n == 0 {
|
||||||
|
style = g.dimmed
|
||||||
|
}
|
||||||
for i := 0; i < len(ns); i++ {
|
for i := 0; i < len(ns); i++ {
|
||||||
if ns[i] == '0' && !sig {
|
if ns[i] == '0' && !sig {
|
||||||
g.drawDial(sc, dm.Print(int(ns[i]-48)), o, g.dimmed)
|
g.drawDial(sc, dm.Print(int(ns[i]-48)), o, g.dimmed)
|
||||||
|
|
@ -102,7 +105,7 @@ func (g *Gauge) Draw(sc tcell.Screen) {
|
||||||
if g.HasFocus() {
|
if g.HasFocus() {
|
||||||
legend = "[:aqua]" + g.legend + "[::]"
|
legend = "[:aqua]" + g.legend + "[::]"
|
||||||
}
|
}
|
||||||
tview.Print(sc, legend, rect.Min.X, rect.Max.Y-1, rect.Dx(), tview.AlignCenter, tcell.ColorWhite)
|
tview.Print(sc, legend, rect.Min.X, rect.Max.Y, rect.Dx(), tview.AlignCenter, tcell.ColorWhite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,6 @@ type SparkLine struct {
|
||||||
*Component
|
*Component
|
||||||
|
|
||||||
data []Metric
|
data []Metric
|
||||||
lastWidth int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSparkLine returns a new graph.
|
// NewSparkLine returns a new graph.
|
||||||
|
|
@ -75,24 +74,24 @@ func (s *SparkLine) Draw(screen tcell.Screen) {
|
||||||
}
|
}
|
||||||
|
|
||||||
rect := s.asRect()
|
rect := s.asRect()
|
||||||
s.lastWidth = rect.Dx()
|
|
||||||
s.cutSet(rect.Dx())
|
s.cutSet(rect.Dx())
|
||||||
max := s.computeMax()
|
max := s.computeMax()
|
||||||
|
|
||||||
cX := rect.Min.X + 1
|
cX, idx := rect.Min.X+1, 0
|
||||||
if len(s.data) < rect.Dx() {
|
if len(s.data)*2 < rect.Dx() {
|
||||||
cX = rect.Max.X - len(s.data)
|
cX = rect.Max.X - len(s.data)*2
|
||||||
|
} else {
|
||||||
|
idx = len(s.data) - rect.Dx()/2
|
||||||
}
|
}
|
||||||
|
|
||||||
scale := float64(len(sparks)) * float64((rect.Dy() - pad)) / float64(max)
|
scale := float64(len(sparks)) * float64((rect.Dy() - pad)) / float64(max)
|
||||||
|
|
||||||
c1, c2 := s.colorForSeries()
|
c1, c2 := s.colorForSeries()
|
||||||
for _, d := range s.data {
|
for _, d := range s.data[idx:] {
|
||||||
b := toBlocks(d, scale)
|
b := toBlocks(d, scale)
|
||||||
cY := rect.Max.Y - pad
|
cY := rect.Max.Y - pad
|
||||||
cY = s.drawBlock(screen, cX, cY, b.oks, c1)
|
s.drawBlock(screen, cX, cY, b.oks, c1)
|
||||||
s.drawBlock(screen, cX, cY, b.errs, c2)
|
s.drawBlock(screen, cX, cY, b.errs, c2)
|
||||||
cX++
|
cX += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
if rect.Dx() > 0 && rect.Dy() > 0 && s.legend != "" {
|
if rect.Dx() > 0 && rect.Dy() > 0 && s.legend != "" {
|
||||||
|
|
@ -100,11 +99,11 @@ func (s *SparkLine) Draw(screen tcell.Screen) {
|
||||||
if s.HasFocus() {
|
if s.HasFocus() {
|
||||||
legend = "[:aqua:]" + s.legend + "[::]"
|
legend = "[:aqua:]" + s.legend + "[::]"
|
||||||
}
|
}
|
||||||
tview.Print(screen, legend, rect.Min.X, rect.Max.Y-1, rect.Dx(), tview.AlignCenter, tcell.ColorWhite)
|
tview.Print(screen, legend, rect.Min.X, rect.Max.Y, rect.Dx(), tview.AlignCenter, tcell.ColorWhite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SparkLine) drawBlock(screen tcell.Screen, x, y int, b block, c tcell.Color) int {
|
func (s *SparkLine) drawBlock(screen tcell.Screen, x, y int, b block, c tcell.Color) {
|
||||||
style := tcell.StyleDefault.Foreground(c).Background(s.bgColor)
|
style := tcell.StyleDefault.Foreground(c).Background(s.bgColor)
|
||||||
|
|
||||||
for i := 0; i < b.full; i++ {
|
for i := 0; i < b.full; i++ {
|
||||||
|
|
@ -114,48 +113,46 @@ func (s *SparkLine) drawBlock(screen tcell.Screen, x, y int, b block, c tcell.Co
|
||||||
if b.partial != 0 {
|
if b.partial != 0 {
|
||||||
screen.SetContent(x, y, b.partial, nil, style)
|
screen.SetContent(x, y, b.partial, nil, style)
|
||||||
}
|
}
|
||||||
|
|
||||||
return y
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SparkLine) cutSet(w int) {
|
func (s *SparkLine) cutSet(width int) {
|
||||||
if w <= 0 || len(s.data) == 0 {
|
if width <= 0 || len(s.data) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if w < len(s.data) {
|
if len(s.data) >= width*2 {
|
||||||
s.data = s.data[len(s.data)-w:]
|
s.data = s.data[len(s.data)-width:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SparkLine) computeMax() int {
|
func (s *SparkLine) computeMax() int {
|
||||||
var max int
|
var max int
|
||||||
for _, d := range s.data {
|
for _, d := range s.data {
|
||||||
sum := d.Sum()
|
if max < d.OK {
|
||||||
if sum > max {
|
max = d.OK
|
||||||
max = sum
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return max
|
return max
|
||||||
}
|
}
|
||||||
|
|
||||||
func toBlocks(value Metric, scale float64) blocks {
|
func toBlocks(m Metric, scale float64) blocks {
|
||||||
if value.Sum() <= 0 {
|
if m.Sum() <= 0 {
|
||||||
return blocks{}
|
return blocks{}
|
||||||
}
|
}
|
||||||
|
return blocks{oks: makeBlocks(m.OK, false, scale), errs: makeBlocks(m.Fault, true, scale)}
|
||||||
oks := int(math.Floor(float64(value.OK) * scale))
|
}
|
||||||
part, okB := oks%len(sparks), block{full: oks / len(sparks)}
|
|
||||||
if part > 0 {
|
func makeBlocks(v int, isErr bool, scale float64) block {
|
||||||
okB.partial = sparks[part-1]
|
scaled := int(math.Round(float64(v) * scale))
|
||||||
}
|
part, b := scaled%len(sparks), block{full: scaled / len(sparks)}
|
||||||
|
// Err might get scaled way down if so nudge.
|
||||||
errs := int(math.Round(float64(value.Fault) * scale))
|
if v > 0 && isErr && scaled == 0 {
|
||||||
part, errB := errs%len(sparks), block{full: errs / len(sparks)}
|
part = 1
|
||||||
if part > 0 {
|
}
|
||||||
errB.partial = sparks[part-1]
|
if part > 0 {
|
||||||
}
|
b.partial = sparks[part-1]
|
||||||
|
}
|
||||||
return blocks{oks: okB, errs: errB}
|
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func NewFlash(app *App) *Flash {
|
||||||
TextView: tview.NewTextView(),
|
TextView: tview.NewTextView(),
|
||||||
}
|
}
|
||||||
f.SetTextColor(tcell.ColorAqua)
|
f.SetTextColor(tcell.ColorAqua)
|
||||||
f.SetTextAlign(tview.AlignLeft)
|
f.SetTextAlign(tview.AlignCenter)
|
||||||
f.SetBorderPadding(0, 0, 1, 1)
|
f.SetBorderPadding(0, 0, 1, 1)
|
||||||
f.app.Styles.AddListener(&f)
|
f.app.Styles.AddListener(&f)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ func NewLogo(styles *config.Styles) *Logo {
|
||||||
}
|
}
|
||||||
l.SetDirection(tview.FlexRow)
|
l.SetDirection(tview.FlexRow)
|
||||||
l.AddItem(l.logo, 0, 6, false)
|
l.AddItem(l.logo, 0, 6, false)
|
||||||
l.AddItem(l.status, 0, 1, false)
|
l.AddItem(l.status, 1, 0, false)
|
||||||
l.refreshLogo(styles.Body().LogoColor)
|
l.refreshLogo(styles.Body().LogoColor)
|
||||||
l.SetBackgroundColor(styles.BgColor())
|
l.SetBackgroundColor(styles.BgColor())
|
||||||
styles.AddListener(&l)
|
styles.AddListener(&l)
|
||||||
|
|
|
||||||
|
|
@ -68,14 +68,14 @@ func hotKeyActions(r Runner, aa ui.KeyActions) {
|
||||||
}
|
}
|
||||||
aa[key] = ui.NewSharedKeyAction(
|
aa[key] = ui.NewSharedKeyAction(
|
||||||
hk.Description,
|
hk.Description,
|
||||||
gotoCmd(r, hk.Command),
|
gotoCmd(r, "", hk.Command),
|
||||||
false)
|
false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func gotoCmd(r Runner, cmd string) ui.ActionHandler {
|
func gotoCmd(r Runner, cmd, path string) ui.ActionHandler {
|
||||||
return func(evt *tcell.EventKey) *tcell.EventKey {
|
return func(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if err := r.App().gotoResource(cmd, true); err != nil {
|
if err := r.App().gotoResource(cmd, path, true); err != nil {
|
||||||
r.App().Flash().Err(err)
|
r.App().Flash().Err(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (a *Alias) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if r != 0 {
|
if r != 0 {
|
||||||
s := ui.TrimCell(a.GetTable().SelectTable, r, 1)
|
s := ui.TrimCell(a.GetTable().SelectTable, r, 1)
|
||||||
tokens := strings.Split(s, ",")
|
tokens := strings.Split(s, ",")
|
||||||
if err := a.App().gotoResource(tokens[0], true); err != nil {
|
if err := a.App().gotoResource(tokens[0], "", true); err != nil {
|
||||||
a.App().Flash().Err(err)
|
a.App().Flash().Err(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -104,8 +104,8 @@ func (a *App) Init(version string, rate int) error {
|
||||||
main := tview.NewFlex().SetDirection(tview.FlexRow)
|
main := tview.NewFlex().SetDirection(tview.FlexRow)
|
||||||
main.AddItem(a.statusIndicator(), 1, 1, false)
|
main.AddItem(a.statusIndicator(), 1, 1, false)
|
||||||
main.AddItem(a.Content, 0, 10, true)
|
main.AddItem(a.Content, 0, 10, true)
|
||||||
main.AddItem(a.Crumbs(), 2, 1, false)
|
main.AddItem(a.Crumbs(), 1, 1, false)
|
||||||
main.AddItem(flash, 2, 1, false)
|
main.AddItem(flash, 1, 1, false)
|
||||||
|
|
||||||
a.Main.AddPage("main", main, true, false)
|
a.Main.AddPage("main", main, true, false)
|
||||||
a.Main.AddPage("splash", ui.NewSplash(a.Styles, version), true, true)
|
a.Main.AddPage("splash", ui.NewSplash(a.Styles, version), true, true)
|
||||||
|
|
@ -136,7 +136,7 @@ func (a *App) toggleHeader(flag bool) {
|
||||||
}
|
}
|
||||||
if a.showHeader {
|
if a.showHeader {
|
||||||
flex.RemoveItemAtIndex(0)
|
flex.RemoveItemAtIndex(0)
|
||||||
flex.AddItemAtIndex(0, a.buildHeader(), 7, 1, false)
|
flex.AddItemAtIndex(0, a.buildHeader(), 8, 1, false)
|
||||||
} else {
|
} else {
|
||||||
flex.RemoveItemAtIndex(0)
|
flex.RemoveItemAtIndex(0)
|
||||||
flex.AddItemAtIndex(0, a.statusIndicator(), 1, 1, false)
|
flex.AddItemAtIndex(0, a.statusIndicator(), 1, 1, false)
|
||||||
|
|
@ -271,7 +271,7 @@ func (a *App) switchCtx(name string, loadPods bool) error {
|
||||||
}
|
}
|
||||||
a.Flash().Infof("Switching context to %s", name)
|
a.Flash().Infof("Switching context to %s", name)
|
||||||
a.ReloadStyles(name)
|
a.ReloadStyles(name)
|
||||||
if err := a.gotoResource("pods", true); loadPods && err != nil {
|
if err := a.gotoResource("pods", "", true); loadPods && err != nil {
|
||||||
a.Flash().Err(err)
|
a.Flash().Err(err)
|
||||||
}
|
}
|
||||||
a.clusterModel.Reset(a.factory)
|
a.clusterModel.Reset(a.factory)
|
||||||
|
|
@ -382,7 +382,7 @@ func (a *App) toggleHeaderCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
func (a *App) gotoCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
|
if a.CmdBuff().IsActive() && !a.CmdBuff().Empty() {
|
||||||
if err := a.gotoResource(a.GetCmd(), true); err != nil {
|
if err := a.gotoResource(a.GetCmd(), "", true); err != nil {
|
||||||
log.Error().Err(err).Msgf("Goto resource for %q failed", a.GetCmd())
|
log.Error().Err(err).Msgf("Goto resource for %q failed", a.GetCmd())
|
||||||
a.Flash().Err(err)
|
a.Flash().Err(err)
|
||||||
}
|
}
|
||||||
|
|
@ -431,8 +431,8 @@ func (a *App) viewResource(gvr, path string, clearStack bool) error {
|
||||||
return a.command.run(gvr, path, clearStack)
|
return a.command.run(gvr, path, clearStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) gotoResource(cmd string, clearStack bool) error {
|
func (a *App) gotoResource(cmd, path string, clearStack bool) error {
|
||||||
return a.command.run(cmd, "", clearStack)
|
return a.command.run(cmd, path, clearStack)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) inject(c model.Component) error {
|
func (a *App) inject(c model.Component) error {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ func NewClusterInfo(app *App) *ClusterInfo {
|
||||||
|
|
||||||
// Init initializes the view.
|
// Init initializes the view.
|
||||||
func (c *ClusterInfo) Init() {
|
func (c *ClusterInfo) Init() {
|
||||||
|
c.SetBorderPadding(0, 0, 1, 0)
|
||||||
c.app.Styles.AddListener(c)
|
c.app.Styles.AddListener(c)
|
||||||
c.layout()
|
c.layout()
|
||||||
c.StylesChanged(c.app.Styles)
|
c.StylesChanged(c.app.Styles)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ func (n *Namespace) bindKeys(aa ui.KeyActions) {
|
||||||
|
|
||||||
func (n *Namespace) switchNs(app *App, model ui.Tabular, gvr, path string) {
|
func (n *Namespace) switchNs(app *App, model ui.Tabular, gvr, path string) {
|
||||||
n.useNamespace(path)
|
n.useNamespace(path)
|
||||||
if err := app.gotoResource("pods", true); err != nil {
|
if err := app.gotoResource("pods", "", true); err != nil {
|
||||||
app.Flash().Err(err)
|
app.Flash().Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ func ShowPortForwards(v ResourceViewer, path string, ports []string, okFn PortFo
|
||||||
SetFieldTextColor(styles.K9s.Info.SectionColor.Color())
|
SetFieldTextColor(styles.K9s.Info.SectionColor.Color())
|
||||||
|
|
||||||
p1, p2, address := ports[0], extractPort(ports[0]), "localhost"
|
p1, p2, address := ports[0], extractPort(ports[0]), "localhost"
|
||||||
f.AddInputField("Container Port:", p1, 20, nil, func(p string) {
|
f.AddInputField("Container Port:", p1, 30, nil, func(p string) {
|
||||||
p1 = p
|
p1 = p
|
||||||
})
|
})
|
||||||
f.AddInputField("Local Port:", p2, 20, nil, func(p string) {
|
f.AddInputField("Local Port:", p2, 30, nil, func(p string) {
|
||||||
p2 = p
|
p2 = p
|
||||||
})
|
})
|
||||||
f.AddInputField("Address:", address, 20, nil, func(h string) {
|
f.AddInputField("Address:", address, 30, nil, func(h string) {
|
||||||
address = h
|
address = h
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
@ -48,22 +48,24 @@ func ShowPortForwards(v ResourceViewer, path string, ports []string, okFn PortFo
|
||||||
okFn(v, path, extractContainer(p1), tunnel)
|
okFn(v, path, extractContainer(p1), tunnel)
|
||||||
})
|
})
|
||||||
f.AddButton("Cancel", func() {
|
f.AddButton("Cancel", func() {
|
||||||
DismissPortForwards(pages)
|
DismissPortForwards(v.App(), pages)
|
||||||
})
|
})
|
||||||
|
|
||||||
modal := tview.NewModalForm(fmt.Sprintf("<PortForward on %s>", path), f)
|
modal := tview.NewModalForm(fmt.Sprintf("<PortForward on %s>", path), f)
|
||||||
modal.SetText("Exposed Ports: " + strings.Join(ports, ","))
|
modal.SetText("Exposed Ports: " + strings.Join(ports, ","))
|
||||||
modal.SetDoneFunc(func(_ int, b string) {
|
modal.SetDoneFunc(func(_ int, b string) {
|
||||||
DismissPortForwards(pages)
|
DismissPortForwards(v.App(), pages)
|
||||||
})
|
})
|
||||||
|
|
||||||
pages.AddPage(portForwardKey, modal, false, false)
|
pages.AddPage(portForwardKey, modal, false, true)
|
||||||
pages.ShowPage(portForwardKey)
|
pages.ShowPage(portForwardKey)
|
||||||
|
v.App().SetFocus(pages.GetPrimitive(portForwardKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DismissPortForwards dismiss the port forward dialog.
|
// DismissPortForwards dismiss the port forward dialog.
|
||||||
func DismissPortForwards(p *ui.Pages) {
|
func DismissPortForwards(app *App, p *ui.Pages) {
|
||||||
p.RemovePage(portForwardKey)
|
p.RemovePage(portForwardKey)
|
||||||
|
app.SetFocus(p.CurrentPage().Item)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ func runForward(v ResourceViewer, pf watch.Forwarder, f *portforward.PortForward
|
||||||
|
|
||||||
v.App().QueueUpdateDraw(func() {
|
v.App().QueueUpdateDraw(func() {
|
||||||
v.App().Flash().Infof("PortForward activated %s:%s", pf.Path(), pf.Ports()[0])
|
v.App().Flash().Infof("PortForward activated %s:%s", pf.Path(), pf.Ports()[0])
|
||||||
DismissPortForwards(v.App().Content.Pages)
|
DismissPortForwards(v.App(), v.App().Content.Pages)
|
||||||
})
|
})
|
||||||
|
|
||||||
pf.SetActive(true)
|
pf.SetActive(true)
|
||||||
|
|
@ -124,7 +124,6 @@ func showFwdDialog(v ResourceViewer, path string, cb PortForwardFunc) error {
|
||||||
ports = append(ports, client.FQN(co, p.Name)+":"+strconv.Itoa(int(p.ContainerPort)))
|
ports = append(ports, client.FQN(co, p.Name)+":"+strconv.Itoa(int(p.ContainerPort)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ports) == 0 {
|
if len(ports) == 0 {
|
||||||
return fmt.Errorf("no tcp ports found on %s", path)
|
return fmt.Errorf("no tcp ports found on %s", path)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,15 +141,19 @@ func (p *Pulse) PulseChanged(c *health.Check) {
|
||||||
v.SetLegend(fmt.Sprintf(" %s - %dMi", strings.Title(gvr.R()), c.Tally(health.OK)))
|
v.SetLegend(fmt.Sprintf(" %s - %dMi", strings.Title(gvr.R()), c.Tally(health.OK)))
|
||||||
default:
|
default:
|
||||||
nn := v.GetSeriesColorNames()
|
nn := v.GetSeriesColorNames()
|
||||||
v.SetLegend(fmt.Sprintf(" %s(%d:[%s::]%d:[%s::b]%d[-::])",
|
if c.Tally(health.OK) == 0 {
|
||||||
|
nn[0] = "gray"
|
||||||
|
}
|
||||||
|
if c.Tally(health.Toast) == 0 {
|
||||||
|
nn[1] = "gray"
|
||||||
|
}
|
||||||
|
v.SetLegend(fmt.Sprintf(" %s - [%s::]%d/[%s::b]%d[-::]",
|
||||||
strings.Title(gvr.R()),
|
strings.Title(gvr.R()),
|
||||||
c.Tally(health.Corpus),
|
|
||||||
nn[0],
|
nn[0],
|
||||||
c.Tally(health.OK),
|
c.Tally(health.OK),
|
||||||
nn[1],
|
nn[1],
|
||||||
c.Tally(health.Toast),
|
c.Tally(health.Toast),
|
||||||
),
|
))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
v.Add(tchart.Metric{OK: c.Tally(health.OK), Fault: c.Tally(health.Toast)})
|
v.Add(tchart.Metric{OK: c.Tally(health.OK), Fault: c.Tally(health.Toast)})
|
||||||
}
|
}
|
||||||
|
|
@ -173,12 +177,10 @@ func (p *Pulse) bindKeys() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pulse) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
func (p *Pulse) keyboard(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
log.Debug().Msgf("Pulse GOT EVENT %#v", evt)
|
|
||||||
key := evt.Key()
|
key := evt.Key()
|
||||||
if key == tcell.KeyRune {
|
if key == tcell.KeyRune {
|
||||||
key = tcell.Key(evt.Rune())
|
key = tcell.Key(evt.Rune())
|
||||||
}
|
}
|
||||||
|
|
||||||
if a, ok := p.actions[key]; ok {
|
if a, ok := p.actions[key]; ok {
|
||||||
return a.Action(evt)
|
return a.Action(evt)
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +277,7 @@ func (p *Pulse) enterCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
log.Debug().Msgf("Selected %s", s.ID())
|
log.Debug().Msgf("Selected %s", s.ID())
|
||||||
gvr := client.NewGVR(s.ID())
|
gvr := client.NewGVR(s.ID())
|
||||||
if err := p.App().gotoResource(gvr.R(), false); err != nil {
|
if err := p.App().gotoResource(gvr.R(), "", false); err != nil {
|
||||||
p.App().Flash().Err(err)
|
p.App().Flash().Err(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ func extViewers(vv MetaViewers) {
|
||||||
func showCRD(app *App, _ ui.Tabular, _, path string) {
|
func showCRD(app *App, _ ui.Tabular, _, path string) {
|
||||||
_, crdGVR := client.Namespaced(path)
|
_, crdGVR := client.Namespaced(path)
|
||||||
tokens := strings.Split(crdGVR, ".")
|
tokens := strings.Split(crdGVR, ".")
|
||||||
if err := app.gotoResource(tokens[0], false); err != nil {
|
if err := app.gotoResource(tokens[0], "", false); err != nil {
|
||||||
app.Flash().Err(err)
|
app.Flash().Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue