bug fixes + possible resolve on #456, #452

mine
derailed 2020-01-01 00:00:31 -07:00
parent 4c222f80ed
commit ba84183034
25 changed files with 172 additions and 160 deletions

View File

@ -1,6 +1,7 @@
package client
import (
"fmt"
"path/filepath"
"sync"
"time"
@ -97,7 +98,7 @@ func (a *APIClient) CanI(ns, gvr string, verbs []string) (bool, error) {
return false, err
}
if !resp.Status.Allowed {
return false, err
return false, fmt.Errorf("%s access denied for current user on %q:%s", v, ns, gvr)
}
}
return true, nil

View File

@ -29,13 +29,13 @@ func (a *Alias) Clear() {
// Ensure makes sure alias are loaded.
func (a *Alias) Ensure() (config.Alias, error) {
if len(a.Alias) == 0 {
// if len(a.Alias) > 0 {
// return a.Alias, nil
// }
if err := LoadResources(a.factory); err != nil {
return config.Alias{}, err
}
return a.Alias, a.load()
}
return a.Alias, nil
}
func (a *Alias) load() error {

View File

@ -94,7 +94,10 @@ func LoadResources(f Factory) error {
}
loadNonResource(resMetas)
return loadCRDs(f, resMetas)
if err := loadCRDs(f, resMetas); err != nil {
log.Warn().Err(err).Msgf("CRDs load failed!")
}
return nil
}
// BOZO!! Need contermeasure for direct commands!
@ -172,7 +175,7 @@ func loadPreferred(f Factory, m ResourceMetas) error {
}
rr, err := discovery.ServerPreferredResources()
if err != nil {
return err
log.Warn().Err(err).Msgf("Failed to load preferred resources")
}
for _, r := range rr {
for _, res := range r.APIResources {
@ -188,11 +191,13 @@ func loadPreferred(f Factory, m ResourceMetas) error {
func loadCRDs(f Factory, m ResourceMetas) error {
log.Debug().Msgf("Loading CRDs...")
const crdGVR = "apiextensions.k8s.io/v1beta1/customresourcedefinitions"
_ = f.ForResource("", crdGVR)
f.WaitForCacheSync()
_, err := f.CanForResource("", crdGVR, "list")
if err != nil {
return err
}
oo, err := f.List(crdGVR, "", labels.Everything())
if err != nil {
log.Error().Err(err).Msgf("Fail CRDs load")
log.Warn().Err(err).Msgf("Fail CRDs load")
return nil
}
log.Debug().Msgf(">>> CRDS count %d", len(oo))

View File

@ -26,6 +26,9 @@ type Factory interface {
// ForResource fetch an informer for a given resource.
ForResource(ns, gvr string) informers.GenericInformer
// CanForResource fetch an informer for a given resource if authorized
CanForResource(ns, gvr string, verbs ...string) (informers.GenericInformer, error)
// WaitForCacheSync synchronize the cache.
WaitForCacheSync()

View File

@ -17,7 +17,7 @@ type CustomResourceDefinition struct {
func (c *CustomResourceDefinition) List(ctx context.Context) ([]runtime.Object, error) {
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
lsel := labels.Everything()
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
if sel, e := labels.ConvertSelectorToLabelsMap(strLabel); ok && e == nil {
lsel = sel.AsSelector()
}

View File

@ -2,8 +2,10 @@ package model
import (
"context"
"fmt"
"github.com/derailed/k9s/internal"
"github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
)
@ -14,33 +16,32 @@ type HorizontalPodAutoscaler struct {
}
// List returns a collection of nodes.
func (c *HorizontalPodAutoscaler) List(ctx context.Context) ([]runtime.Object, error) {
func (h *HorizontalPodAutoscaler) List(ctx context.Context) ([]runtime.Object, error) {
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
lsel := labels.Everything()
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
lsel = sel.AsSelector()
}
gvr := "autoscaling/v2beta2/horizontalpodautoscalers"
ooV2b2, err := c.factory.List(gvr, c.namespace, lsel)
if err != nil {
return nil, err
}
if len(ooV2b2) > 0 {
return ooV2b2, nil
gvrs := []string{
"autoscaling/v2beta2/horizontalpodautoscalers",
"autoscaling/v2beta1/horizontalpodautoscalers",
"autoscaling/v1/horizontalpodautoscalers",
}
gvr = "autoscaling/v2beta1/horizontalpodautoscalers"
ooV2b1, err := c.factory.List(gvr, c.namespace, lsel)
if err != nil {
return nil, err
for _, gvr := range gvrs {
oo, err := h.list(gvr, lsel)
if err == nil && len(oo) > 0 {
return oo, nil
}
if len(ooV2b1) > 0 {
return ooV2b1, nil
}
log.Error().Err(fmt.Errorf("No results for any known HPA versions"))
gvr = "autoscaling/v1/horizontalpodautoscalers"
oo, err := c.factory.List(gvr, c.namespace, lsel)
return []runtime.Object{}, nil
}
func (h *HorizontalPodAutoscaler) list(gvr string, sel labels.Selector) ([]runtime.Object, error) {
oo, err := h.factory.List(gvr, h.namespace, sel)
if err != nil {
return nil, err
}

View File

@ -171,7 +171,9 @@ func (p *Policy) fetchRoleBindingSubjects(kind, name string) ([]string, error) {
}
func (p *Policy) fetchClusterRoles() ([]rbacv1.ClusterRole, error) {
oo, err := p.factory.List("rbac.authorization.k8s.io/v1/clusterroles", render.ClusterScope, labels.Everything())
const gvr = "rbac.authorization.k8s.io/v1/clusterroles"
oo, err := p.factory.List(gvr, render.ClusterScope, labels.Everything())
if err != nil {
return nil, err
}
@ -189,7 +191,9 @@ func (p *Policy) fetchClusterRoles() ([]rbacv1.ClusterRole, error) {
}
func (p *Policy) fetchRoles() ([]rbacv1.Role, error) {
oo, err := p.factory.List("rbac.authorization.k8s.io/v1/roles", render.AllNamespaces, labels.Everything())
const gvr = "rbac.authorization.k8s.io/v1/roles"
oo, err := p.factory.List(gvr, render.AllNamespaces, labels.Everything())
if err != nil {
return nil, err
}

View File

@ -5,6 +5,7 @@ import (
"github.com/derailed/k9s/internal"
"github.com/derailed/k9s/internal/render"
"github.com/rs/zerolog/log"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
)
@ -22,11 +23,13 @@ func (r *Resource) Init(ns, gvr string, f Factory) {
// List returns a collection of nodes.
func (r *Resource) List(ctx context.Context) ([]runtime.Object, error) {
log.Debug().Msgf("MODELLIST %q:%q", r.namespace, r.gvr)
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
lsel := labels.Everything()
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
lsel = sel.AsSelector()
}
return r.factory.List(r.gvr, r.namespace, lsel)
}

View File

@ -13,7 +13,7 @@ import (
)
const (
refreshRate = 2 * time.Second
refreshRate = 1 * time.Second
noDataCount = 2
)
@ -115,6 +115,7 @@ func (t *Table) refresh(ctx context.Context) {
if err := t.reconcile(ctx); err != nil {
log.Error().Err(err).Msg("Reconcile failed")
t.fireTableLoadFailed(err)
return
}
t.fireTableChanged(*t.data)
}

View File

@ -18,7 +18,7 @@ import (
const (
benchFmat = "%s_%s_%d.txt"
k9sUA = "k9s/0.0.7"
k9sUA = "k9s/"
)
// K9sBenchDir directory to store K9s Benchmark files.
@ -32,15 +32,15 @@ type Benchmark struct {
}
// NewBenchmark returns a new benchmark.
func NewBenchmark(base string, cfg config.BenchConfig) (*Benchmark, error) {
func NewBenchmark(base, version string, cfg config.BenchConfig) (*Benchmark, error) {
b := Benchmark{config: cfg}
if err := b.init(base); err != nil {
if err := b.init(base, version); err != nil {
return nil, err
}
return &b, nil
}
func (b *Benchmark) init(base string) error {
func (b *Benchmark) init(base, version string) error {
req, err := http.NewRequest(b.config.HTTP.Method, base, nil)
if err != nil {
return err
@ -58,6 +58,7 @@ func (b *Benchmark) init(base string) error {
} else {
ua += " " + k9sUA
}
ua += version
if req.Header == nil {
req.Header = make(http.Header)
}

View File

@ -6,6 +6,7 @@ import (
"fmt"
"strings"
"github.com/rs/zerolog/log"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
)
@ -48,30 +49,25 @@ func (g *Generic) Render(o interface{}, ns string, r *Row) error {
return fmt.Errorf("expecting a TableRow but got %T", o)
}
count := len(row.Cells)
if ns == AllNamespaces {
count++
}
r.ID, ok = row.Cells[0].(string)
if !ok {
return fmt.Errorf("expecting row id to be a string but got %#v", row.Cells[0])
}
r.Fields = make(Fields, count)
var index int
if ns == AllNamespaces {
rns, err := extractNamespace(row.Object.Raw)
if err != nil {
return err
}
r.Fields[index] = rns
r.ID = FQN(rns, r.ID)
index++
r.Fields = make(Fields, 0, len(g.Header(ns)))
if isAllNamespace(ns) {
r.Fields = append(r.Fields, rns)
}
for _, c := range row.Cells {
r.Fields[index] = fmt.Sprintf("%v", c)
index++
r.Fields = append(r.Fields, fmt.Sprintf("%v", c))
}
log.Debug().Msgf("GENERIC %#v", r)
return nil
}

View File

@ -16,7 +16,7 @@ func TestGenericRender(t *testing.T) {
row := makeGeneric().Rows[0]
assert.Nil(t, g.Render(&row, "blee", &r))
assert.Equal(t, "a", r.ID)
assert.Equal(t, "blee/a", r.ID)
assert.Equal(t, render.Fields{"a", "b", "c"}, r.Fields)
}

View File

@ -306,9 +306,11 @@ func (a *App) Status(l ui.FlashLevel, msg string) {
}
// ClearStatus reset log back to normal.
func (a *App) ClearStatus() {
func (a *App) ClearStatus(flash bool) {
a.Logo().Reset()
if flash {
a.Flash().Clear()
}
a.Draw()
}

View File

@ -13,6 +13,7 @@ import (
"github.com/derailed/k9s/internal/render"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/k9s/internal/ui/dialog"
"github.com/derailed/k9s/internal/watch"
"github.com/gdamore/tcell"
"github.com/rs/zerolog/log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -133,7 +134,7 @@ func (b *Browser) Aliases() []string {
func (b *Browser) TableLoadFailed(err error) {
b.app.QueueUpdateDraw(func() {
b.app.Flash().Err(err)
b.App().ClearStatus()
b.App().ClearStatus(false)
})
}
@ -142,7 +143,7 @@ func (b *Browser) TableDataChanged(data render.TableData) {
b.app.QueueUpdateDraw(func() {
b.refreshActions()
b.Update(data)
b.App().ClearStatus()
b.App().ClearStatus(false)
})
}
@ -273,6 +274,12 @@ func (b *Browser) switchNamespaceCmd(evt *tcell.EventKey) *tcell.EventKey {
ns = render.NamespaceAll
}
auth, err := b.App().factory.Client().CanI(ns, b.GVR(), watch.ReadVerbs)
if !auth {
b.App().Flash().Err(err)
return nil
}
b.app.switchNS(ns)
b.setNamespace(ns)
b.app.Flash().Infof("Viewing namespace `%s`...", ns)

View File

@ -11,7 +11,11 @@ import (
"github.com/rs/zerolog/log"
)
var customViewers MetaViewers
var (
customViewers MetaViewers
canRX = regexp.MustCompile(`\Acan\s([u|g|s]):([\w-:]+)\b`)
)
// Command represents a user command.
type Command struct {
@ -38,6 +42,37 @@ func (c *Command) Init() error {
return nil
}
// Exec the Command by showing associated display.
func (c *Command) run(cmd string, clearStack bool) error {
if c.specialCmd(cmd) {
return nil
}
cmds := strings.Split(cmd, " ")
gvr, v, err := c.viewMetaFor(cmds[0])
if err != nil {
return err
}
switch cmds[0] {
case "ctx", "context", "contexts":
if len(cmds) == 2 && c.app.switchCtx(cmds[1], true) != nil {
return fmt.Errorf("context switch failed!")
}
view := c.componentFor(gvr, v)
return c.exec(gvr, view, clearStack)
default:
// checks if Command includes a namespace
ns := c.app.Config.ActiveNamespace()
if len(cmds) == 2 {
ns = cmds[1]
}
if !c.app.switchNS(ns) {
return fmt.Errorf("namespace switch failed for ns %q", ns)
}
return c.exec(gvr, c.componentFor(gvr, v), clearStack)
}
}
// Reset resets Command and reload aliases.
func (c *Command) Reset() error {
c.alias.Clear()
@ -52,8 +87,6 @@ func (c *Command) defaultCmd() error {
return c.run(c.app.Config.ActiveView(), true)
}
var canRX = regexp.MustCompile(`\Acan\s([u|g|s]):([\w-:]+)\b`)
func (c *Command) specialCmd(cmd string) bool {
cmds := strings.Split(cmd, " ")
switch cmds[0] {
@ -96,37 +129,6 @@ func (c *Command) viewMetaFor(cmd string) (string, *MetaViewer, error) {
return gvr, &v, nil
}
// Exec the Command by showing associated display.
func (c *Command) run(cmd string, clearStack bool) error {
if c.specialCmd(cmd) {
return nil
}
cmds := strings.Split(cmd, " ")
gvr, v, err := c.viewMetaFor(cmds[0])
if err != nil {
return err
}
switch cmds[0] {
case "ctx", "context", "contexts":
if len(cmds) == 2 && c.app.switchCtx(cmds[1], true) != nil {
return fmt.Errorf("context switch failed!")
}
view := c.componentFor(gvr, v)
return c.exec(gvr, view, clearStack)
default:
// checks if Command includes a namespace
ns := c.app.Config.ActiveNamespace()
if len(cmds) == 2 {
ns = cmds[1]
}
if !c.app.switchNS(ns) {
return fmt.Errorf("namespace switch failed for ns %q", ns)
}
return c.exec(gvr, c.componentFor(gvr, v), clearStack)
}
}
func (c *Command) componentFor(gvr string, v *MetaViewer) ResourceViewer {
var view ResourceViewer
if v.viewerFn != nil {

View File

@ -188,7 +188,7 @@ func (v *Help) showGeneral() model.MenuHints {
},
{
Mnemonic: "Ctrl-r",
Description: "Refresh",
Description: "Reload",
},
{
Mnemonic: "Ctrl-u",

View File

@ -89,7 +89,6 @@ func toYAML(o runtime.Object) (string, error) {
}
func showPodsWithLabels(app *App, path string, sel map[string]string) {
log.Debug().Msgf("SHOWING POD FOR %#v", sel)
var labels []string
for k, v := range sel {
labels = append(labels, fmt.Sprintf("%s=%s", k, v))

View File

@ -131,12 +131,8 @@ func (l *Log) bindKeys() {
tcell.KeyEscape: ui.NewKeyAction("Back", l.app.PrevCmd, true),
ui.KeyC: ui.NewKeyAction("Clear", l.clearCmd, true),
ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true),
ui.KeyG: ui.NewKeyAction("Top", l.topCmd, false),
ui.KeyShiftF: ui.NewKeyAction("FullScreen", l.fullScreenCmd, true),
ui.KeyF: ui.NewKeyAction("FullScreen", l.fullScreenCmd, true),
ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.textWrapCmd, true),
ui.KeyShiftG: ui.NewKeyAction("Bottom", l.bottomCmd, false),
ui.KeyF: ui.NewKeyAction("Up", l.pageUpCmd, false),
ui.KeyB: ui.NewKeyAction("Down", l.pageDownCmd, false),
tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true),
})
}
@ -306,32 +302,6 @@ func saveData(cluster, name, data string) (string, error) {
return path, nil
}
func (l *Log) topCmd(evt *tcell.EventKey) *tcell.EventKey {
l.app.Flash().Info("Top of logs...")
l.logs.ScrollToBeginning()
return nil
}
func (l *Log) bottomCmd(*tcell.EventKey) *tcell.EventKey {
l.app.Flash().Info("Bottom of logs...")
l.logs.ScrollToEnd()
return nil
}
func (l *Log) pageUpCmd(*tcell.EventKey) *tcell.EventKey {
if l.logs.PageUp() {
l.app.Flash().Info("Reached Top ...")
}
return nil
}
func (l *Log) pageDownCmd(*tcell.EventKey) *tcell.EventKey {
if l.logs.PageDown() {
l.app.Flash().Info("Reached Bottom ...")
}
return nil
}
func (l *Log) clearCmd(*tcell.EventKey) *tcell.EventKey {
l.app.Flash().Info("Clearing logs...")
l.logs.Clear()

View File

@ -37,7 +37,7 @@ func TestLogFlush(t *testing.T) {
assert.Equal(t, " Autoscroll: Off FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
v.toggleAutoScrollCmd(nil)
assert.Equal(t, " Autoscroll: On FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
assert.Equal(t, 10, len(v.Hints()))
assert.Equal(t, 6, len(v.Hints()))
}
func TestLogViewSave(t *testing.T) {

View File

@ -2,7 +2,9 @@ package view
import (
"github.com/derailed/k9s/internal/client"
"github.com/derailed/k9s/internal/render"
"github.com/derailed/k9s/internal/ui"
"github.com/derailed/k9s/internal/watch"
"github.com/gdamore/tcell"
"github.com/rs/zerolog/log"
)
@ -55,6 +57,15 @@ func isResourcePath(p string) bool {
func (l *LogsExtender) showLogs(path string, prev bool) {
log.Debug().Msgf("SHOWING LOGS path %q", path)
// Need to load and wait for pods
ns, _ := render.Namespaced(path)
_, err := l.App().factory.CanForResource(ns, "v1/pods", watch.ReadVerbs...)
if err != nil {
l.App().Flash().Err(err)
return
}
l.App().factory.WaitForCacheSync()
co := ""
if l.containerFn != nil {
co = l.containerFn()

View File

@ -48,8 +48,8 @@ func (p *PortForward) portForwardContext(ctx context.Context) context.Context {
func (p *PortForward) bindKeys(aa ui.KeyActions) {
aa.Add(ui.KeyActions{
tcell.KeyEnter: ui.NewKeyAction("Benchmarks", p.showBenchCmd, true),
tcell.KeyCtrlB: ui.NewKeyAction("Bench", p.benchCmd, true),
tcell.KeyCtrlK: ui.NewKeyAction("Bench Stop", p.benchStopCmd, true),
ui.KeyB: ui.NewKeyAction("Bench", p.benchCmd, true),
ui.KeyK: ui.NewKeyAction("Bench Stop", p.benchStopCmd, true),
tcell.KeyCtrlD: ui.NewKeyAction("Delete", p.deleteCmd, true),
ui.KeyShiftP: ui.NewKeyAction("Sort Ports", p.GetTable().SortColCmd(2, true), false),
ui.KeyShiftU: ui.NewKeyAction("Sort URL", p.GetTable().SortColCmd(4, true), false),
@ -70,7 +70,7 @@ func (p *PortForward) benchStopCmd(evt *tcell.EventKey) *tcell.EventKey {
p.App().Status(ui.FlashErr, "Benchmark Camceled!")
p.bench.Cancel()
}
p.App().ClearStatus()
p.App().ClearStatus(true)
return nil
}
@ -95,9 +95,9 @@ func (p *PortForward) benchCmd(evt *tcell.EventKey) *tcell.EventKey {
base := ui.TrimCell(p.GetTable().SelectTable, r, 4)
var err error
if p.bench, err = perf.NewBenchmark(base, cfg); err != nil {
if p.bench, err = perf.NewBenchmark(base, p.App().version, cfg); err != nil {
p.App().Flash().Errf("Bench failed %v", err)
p.App().ClearStatus()
p.App().ClearStatus(false)
return nil
}
@ -121,7 +121,7 @@ func (p *PortForward) runBenchmark() {
p.bench = nil
go func() {
<-time.After(2 * time.Second)
p.App().QueueUpdate(func() { p.App().ClearStatus() })
p.App().QueueUpdate(func() { p.App().ClearStatus(true) })
}()
})
})

View File

@ -32,19 +32,19 @@ func NewReplicaSet(gvr client.GVR) ResourceViewer {
r := ReplicaSet{
ResourceViewer: NewBrowser(gvr),
}
r.bindKeys()
r.SetBindKeysFn(r.bindKeys)
r.GetTable().SetEnterFn(r.showPods)
r.GetTable().SetColorerFn(render.ReplicaSet{}.ColorerFunc())
return &r
}
func (r *ReplicaSet) bindKeys() {
r.Actions().Add(ui.KeyActions{
func (r *ReplicaSet) bindKeys(aa ui.KeyActions) {
aa.Add(ui.KeyActions{
ui.KeyShiftD: ui.NewKeyAction("Sort Desired", r.GetTable().SortColCmd(1, true), false),
ui.KeyShiftC: ui.NewKeyAction("Sort Current", r.GetTable().SortColCmd(2, true), false),
ui.KeyShiftR: ui.NewKeyAction("Sort Ready", r.GetTable().SortColCmd(3, true), false),
tcell.KeyCtrlB: ui.NewKeyAction("Rollback", r.rollbackCmd, true),
tcell.KeyCtrlL: ui.NewKeyAction("Rollback", r.rollbackCmd, true),
})
}

View File

@ -40,17 +40,26 @@ func (s *StatefulSet) bindKeys(aa ui.KeyActions) {
}
func (s *StatefulSet) showPods(app *App, _, gvr, path string) {
o, err := app.factory.Get(s.GVR(), path, labels.Everything())
sts, err := s.sts(path)
if err != nil {
app.Flash().Err(err)
return
}
showPodsFromSelector(app, strings.Replace(path, "/", "::", 1), sts.Spec.Selector)
}
func (s *StatefulSet) sts(path string) (*appsv1.StatefulSet, error) {
o, err := s.App().factory.Get(s.GVR(), path, labels.Everything())
if err != nil {
return nil, err
}
var sts appsv1.StatefulSet
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &sts)
if err != nil {
app.Flash().Err(err)
return nil, err
}
showPodsFromSelector(app, strings.Replace(path, "/", "::", 1), sts.Spec.Selector)
return &sts, nil
}

View File

@ -40,14 +40,13 @@ func NewService(gvr client.GVR) ResourceViewer {
func (s *Service) bindKeys(aa ui.KeyActions) {
aa.Add(ui.KeyActions{
tcell.KeyCtrlB: ui.NewKeyAction("Bench", s.benchCmd, true),
tcell.KeyCtrlK: ui.NewKeyAction("Bench Stop", s.benchStopCmd, true),
ui.KeyB: ui.NewKeyAction("Bench", s.benchCmd, true),
ui.KeyK: ui.NewKeyAction("Bench Stop", s.benchStopCmd, true),
ui.KeyShiftT: ui.NewKeyAction("Sort Type", s.GetTable().SortColCmd(1, true), false),
})
}
func (s *Service) showPods(app *App, ns, gvr, path string) {
log.Debug().Msgf("SVC SHOW PODS %q", path)
o, err := app.factory.Get(gvr, path, labels.Everything())
if err != nil {
app.Flash().Err(err)
@ -61,7 +60,7 @@ func (s *Service) showPods(app *App, ns, gvr, path string) {
return
}
showPodsWithLabels(app, path, svc.Spec.Selector)
showPodsWithLabels(app, strings.Replace(path, "/", "::", 1), svc.Spec.Selector)
}
func (s *Service) benchStopCmd(evt *tcell.EventKey) *tcell.EventKey {
@ -70,7 +69,7 @@ func (s *Service) benchStopCmd(evt *tcell.EventKey) *tcell.EventKey {
s.App().Status(ui.FlashErr, "Benchmark Canceled!")
s.bench.Cancel()
}
s.App().ClearStatus()
s.App().ClearStatus(true)
return nil
}
@ -136,7 +135,7 @@ func (s *Service) benchCmd(evt *tcell.EventKey) *tcell.EventKey {
}
if err := s.runBenchmark(port, cfg); err != nil {
s.App().Flash().Errf("Benchmark failed %v", err)
s.App().ClearStatus()
s.App().ClearStatus(false)
s.bench = nil
}
@ -151,7 +150,7 @@ func (s *Service) runBenchmark(port string, cfg config.BenchConfig) error {
var err error
base := "http://" + cfg.HTTP.Host + ":" + port + cfg.HTTP.Path
if s.bench, err = perf.NewBenchmark(base, cfg); err != nil {
if s.bench, err = perf.NewBenchmark(base, s.App().version, cfg); err != nil {
return err
}
@ -179,6 +178,6 @@ func (s *Service) benchDone() {
func benchTimedOut(app *App) {
<-time.After(2 * time.Second)
app.QueueUpdate(func() {
app.ClearStatus()
app.ClearStatus(true)
})
}

View File

@ -18,6 +18,8 @@ const (
clusterScope = "-"
)
var ReadVerbs = []string{"get", "list", "watch"}
// Factory tracks various resource informers.
type Factory struct {
factories map[string]di.DynamicSharedInformerFactory
@ -37,6 +39,7 @@ func NewFactory(client client.Connection) *Factory {
// Start initializes the informers until caller cancels the context.
func (f *Factory) Start(ns string) {
log.Debug().Msgf("Starting factory in ns `%q", ns)
f.stopChan = make(chan struct{})
for ns, fac := range f.factories {
log.Debug().Msgf("Starting factory in ns %q", ns)
@ -62,10 +65,10 @@ func (f *Factory) List(gvr, ns string, sel labels.Selector) ([]runtime.Object, e
if err != nil {
return nil, err
}
log.Debug().Msgf("LISTING %q:%q", ns, gvr)
if ns == clusterScope {
return inf.Lister().List(sel)
}
return inf.Lister().ByNamespace(ns).List(sel)
}
@ -76,6 +79,8 @@ func (f *Factory) Get(gvr, path string, sel labels.Selector) (runtime.Object, er
if err != nil {
return nil, err
}
log.Debug().Msgf("GETTING %q:%q", ns, gvr)
if ns == clusterScope {
return inf.Lister().Get(n)
}
@ -117,8 +122,7 @@ func (f *Factory) isClusterWide() bool {
}
func (f *Factory) preload(_ string) {
verbs := []string{"get", "list", "watch"}
_, _ = f.CanForResource("", "apiextensions.k8s.io/v1beta1/customresourcedefinitions", verbs...)
_, _ = f.CanForResource("", "apiextensions.k8s.io/v1beta1/customresourcedefinitions", ReadVerbs...)
// BOZO!!
// _, _ = f.CanForResource(ns, "v1/pods", verbs...)
// _, _ = f.CanForResource(clusterScope, "rbac.authorization.k8s.io/v1/clusterroles", verbs...)
@ -148,9 +152,6 @@ func (f *Factory) ForResource(ns, gvr string) informers.GenericInformer {
}
func (f *Factory) ensureFactory(ns string) di.DynamicSharedInformerFactory {
if f.isClusterWide() {
ns = allNamespaces
}
if fac, ok := f.factories[ns]; ok {
return fac
}
@ -173,12 +174,9 @@ func (f *Factory) AddForwarder(pf Forwarder) {
// DeleteForwarder deletes portforward for a given container.
func (f *Factory) DeleteForwarder(path string) {
fwd, ok := f.forwarders[path]
if !ok {
return
}
fwd.Stop()
delete(f.forwarders, path)
f.forwarders.Dump()
count := f.forwarders.Kill(path)
log.Warn().Msgf("Deleted (%d) portforward for %q", count, path)
}
// Forwarders returns all portforwards.