parent
4c222f80ed
commit
ba84183034
|
|
@ -1,6 +1,7 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -97,7 +98,7 @@ func (a *APIClient) CanI(ns, gvr string, verbs []string) (bool, error) {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
if !resp.Status.Allowed {
|
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
|
return true, nil
|
||||||
|
|
|
||||||
|
|
@ -29,13 +29,13 @@ func (a *Alias) Clear() {
|
||||||
|
|
||||||
// Ensure makes sure alias are loaded.
|
// Ensure makes sure alias are loaded.
|
||||||
func (a *Alias) Ensure() (config.Alias, error) {
|
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 {
|
if err := LoadResources(a.factory); err != nil {
|
||||||
return config.Alias{}, err
|
return config.Alias{}, err
|
||||||
}
|
}
|
||||||
return a.Alias, a.load()
|
return a.Alias, a.load()
|
||||||
}
|
|
||||||
return a.Alias, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Alias) load() error {
|
func (a *Alias) load() error {
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,10 @@ func LoadResources(f Factory) error {
|
||||||
}
|
}
|
||||||
loadNonResource(resMetas)
|
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!
|
// BOZO!! Need contermeasure for direct commands!
|
||||||
|
|
@ -172,7 +175,7 @@ func loadPreferred(f Factory, m ResourceMetas) error {
|
||||||
}
|
}
|
||||||
rr, err := discovery.ServerPreferredResources()
|
rr, err := discovery.ServerPreferredResources()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
log.Warn().Err(err).Msgf("Failed to load preferred resources")
|
||||||
}
|
}
|
||||||
for _, r := range rr {
|
for _, r := range rr {
|
||||||
for _, res := range r.APIResources {
|
for _, res := range r.APIResources {
|
||||||
|
|
@ -188,11 +191,13 @@ func loadPreferred(f Factory, m ResourceMetas) error {
|
||||||
func loadCRDs(f Factory, m ResourceMetas) error {
|
func loadCRDs(f Factory, m ResourceMetas) error {
|
||||||
log.Debug().Msgf("Loading CRDs...")
|
log.Debug().Msgf("Loading CRDs...")
|
||||||
const crdGVR = "apiextensions.k8s.io/v1beta1/customresourcedefinitions"
|
const crdGVR = "apiextensions.k8s.io/v1beta1/customresourcedefinitions"
|
||||||
_ = f.ForResource("", crdGVR)
|
_, err := f.CanForResource("", crdGVR, "list")
|
||||||
f.WaitForCacheSync()
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
oo, err := f.List(crdGVR, "", labels.Everything())
|
oo, err := f.List(crdGVR, "", labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msgf("Fail CRDs load")
|
log.Warn().Err(err).Msgf("Fail CRDs load")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Debug().Msgf(">>> CRDS count %d", len(oo))
|
log.Debug().Msgf(">>> CRDS count %d", len(oo))
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,9 @@ type Factory interface {
|
||||||
// ForResource fetch an informer for a given resource.
|
// ForResource fetch an informer for a given resource.
|
||||||
ForResource(ns, gvr string) informers.GenericInformer
|
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 synchronize the cache.
|
||||||
WaitForCacheSync()
|
WaitForCacheSync()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ type CustomResourceDefinition struct {
|
||||||
func (c *CustomResourceDefinition) List(ctx context.Context) ([]runtime.Object, error) {
|
func (c *CustomResourceDefinition) List(ctx context.Context) ([]runtime.Object, error) {
|
||||||
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
|
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
|
||||||
lsel := labels.Everything()
|
lsel := labels.Everything()
|
||||||
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
|
if sel, e := labels.ConvertSelectorToLabelsMap(strLabel); ok && e == nil {
|
||||||
lsel = sel.AsSelector()
|
lsel = sel.AsSelector()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,10 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal"
|
"github.com/derailed/k9s/internal"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
@ -14,33 +16,32 @@ type HorizontalPodAutoscaler struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// List returns a collection of nodes.
|
// 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)
|
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
|
||||||
lsel := labels.Everything()
|
lsel := labels.Everything()
|
||||||
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
|
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
|
||||||
lsel = sel.AsSelector()
|
lsel = sel.AsSelector()
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr := "autoscaling/v2beta2/horizontalpodautoscalers"
|
gvrs := []string{
|
||||||
ooV2b2, err := c.factory.List(gvr, c.namespace, lsel)
|
"autoscaling/v2beta2/horizontalpodautoscalers",
|
||||||
if err != nil {
|
"autoscaling/v2beta1/horizontalpodautoscalers",
|
||||||
return nil, err
|
"autoscaling/v1/horizontalpodautoscalers",
|
||||||
}
|
|
||||||
if len(ooV2b2) > 0 {
|
|
||||||
return ooV2b2, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gvr = "autoscaling/v2beta1/horizontalpodautoscalers"
|
for _, gvr := range gvrs {
|
||||||
ooV2b1, err := c.factory.List(gvr, c.namespace, lsel)
|
oo, err := h.list(gvr, lsel)
|
||||||
if err != nil {
|
if err == nil && len(oo) > 0 {
|
||||||
return nil, err
|
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"
|
return []runtime.Object{}, nil
|
||||||
oo, err := c.factory.List(gvr, c.namespace, lsel)
|
}
|
||||||
|
|
||||||
|
func (h *HorizontalPodAutoscaler) list(gvr string, sel labels.Selector) ([]runtime.Object, error) {
|
||||||
|
oo, err := h.factory.List(gvr, h.namespace, sel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,9 @@ func (p *Policy) fetchRoleBindingSubjects(kind, name string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Policy) fetchClusterRoles() ([]rbacv1.ClusterRole, 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -189,7 +191,9 @@ func (p *Policy) fetchClusterRoles() ([]rbacv1.ClusterRole, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Policy) fetchRoles() ([]rbacv1.Role, 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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal"
|
"github.com/derailed/k9s/internal"
|
||||||
"github.com/derailed/k9s/internal/render"
|
"github.com/derailed/k9s/internal/render"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
@ -22,11 +23,13 @@ func (r *Resource) Init(ns, gvr string, f Factory) {
|
||||||
|
|
||||||
// List returns a collection of nodes.
|
// List returns a collection of nodes.
|
||||||
func (r *Resource) List(ctx context.Context) ([]runtime.Object, error) {
|
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)
|
strLabel, ok := ctx.Value(internal.KeyLabels).(string)
|
||||||
lsel := labels.Everything()
|
lsel := labels.Everything()
|
||||||
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
|
if sel, err := labels.ConvertSelectorToLabelsMap(strLabel); ok && err == nil {
|
||||||
lsel = sel.AsSelector()
|
lsel = sel.AsSelector()
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.factory.List(r.gvr, r.namespace, lsel)
|
return r.factory.List(r.gvr, r.namespace, lsel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
refreshRate = 2 * time.Second
|
refreshRate = 1 * time.Second
|
||||||
noDataCount = 2
|
noDataCount = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -115,6 +115,7 @@ func (t *Table) refresh(ctx context.Context) {
|
||||||
if err := t.reconcile(ctx); err != nil {
|
if err := t.reconcile(ctx); err != nil {
|
||||||
log.Error().Err(err).Msg("Reconcile failed")
|
log.Error().Err(err).Msg("Reconcile failed")
|
||||||
t.fireTableLoadFailed(err)
|
t.fireTableLoadFailed(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
t.fireTableChanged(*t.data)
|
t.fireTableChanged(*t.data)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
benchFmat = "%s_%s_%d.txt"
|
benchFmat = "%s_%s_%d.txt"
|
||||||
k9sUA = "k9s/0.0.7"
|
k9sUA = "k9s/"
|
||||||
)
|
)
|
||||||
|
|
||||||
// K9sBenchDir directory to store K9s Benchmark files.
|
// K9sBenchDir directory to store K9s Benchmark files.
|
||||||
|
|
@ -32,15 +32,15 @@ type Benchmark struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBenchmark returns a new benchmark.
|
// 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}
|
b := Benchmark{config: cfg}
|
||||||
if err := b.init(base); err != nil {
|
if err := b.init(base, version); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &b, nil
|
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)
|
req, err := http.NewRequest(b.config.HTTP.Method, base, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -58,6 +58,7 @@ func (b *Benchmark) init(base string) error {
|
||||||
} else {
|
} else {
|
||||||
ua += " " + k9sUA
|
ua += " " + k9sUA
|
||||||
}
|
}
|
||||||
|
ua += version
|
||||||
if req.Header == nil {
|
if req.Header == nil {
|
||||||
req.Header = make(http.Header)
|
req.Header = make(http.Header)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
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)
|
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)
|
r.ID, ok = row.Cells[0].(string)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("expecting row id to be a string but got %#v", row.Cells[0])
|
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)
|
rns, err := extractNamespace(row.Object.Raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
r.Fields[index] = rns
|
|
||||||
r.ID = FQN(rns, r.ID)
|
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 {
|
for _, c := range row.Cells {
|
||||||
r.Fields[index] = fmt.Sprintf("%v", c)
|
r.Fields = append(r.Fields, fmt.Sprintf("%v", c))
|
||||||
index++
|
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("GENERIC %#v", r)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ func TestGenericRender(t *testing.T) {
|
||||||
row := makeGeneric().Rows[0]
|
row := makeGeneric().Rows[0]
|
||||||
assert.Nil(t, g.Render(&row, "blee", &r))
|
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)
|
assert.Equal(t, render.Fields{"a", "b", "c"}, r.Fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -306,9 +306,11 @@ func (a *App) Status(l ui.FlashLevel, msg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearStatus reset log back to normal.
|
// ClearStatus reset log back to normal.
|
||||||
func (a *App) ClearStatus() {
|
func (a *App) ClearStatus(flash bool) {
|
||||||
a.Logo().Reset()
|
a.Logo().Reset()
|
||||||
|
if flash {
|
||||||
a.Flash().Clear()
|
a.Flash().Clear()
|
||||||
|
}
|
||||||
a.Draw()
|
a.Draw()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/derailed/k9s/internal/render"
|
"github.com/derailed/k9s/internal/render"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
"github.com/derailed/k9s/internal/ui/dialog"
|
"github.com/derailed/k9s/internal/ui/dialog"
|
||||||
|
"github.com/derailed/k9s/internal/watch"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
|
@ -133,7 +134,7 @@ func (b *Browser) Aliases() []string {
|
||||||
func (b *Browser) TableLoadFailed(err error) {
|
func (b *Browser) TableLoadFailed(err error) {
|
||||||
b.app.QueueUpdateDraw(func() {
|
b.app.QueueUpdateDraw(func() {
|
||||||
b.app.Flash().Err(err)
|
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.app.QueueUpdateDraw(func() {
|
||||||
b.refreshActions()
|
b.refreshActions()
|
||||||
b.Update(data)
|
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
|
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.app.switchNS(ns)
|
||||||
b.setNamespace(ns)
|
b.setNamespace(ns)
|
||||||
b.app.Flash().Infof("Viewing namespace `%s`...", ns)
|
b.app.Flash().Infof("Viewing namespace `%s`...", ns)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,11 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"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.
|
// Command represents a user command.
|
||||||
type Command struct {
|
type Command struct {
|
||||||
|
|
@ -38,6 +42,37 @@ func (c *Command) Init() error {
|
||||||
return nil
|
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.
|
// Reset resets Command and reload aliases.
|
||||||
func (c *Command) Reset() error {
|
func (c *Command) Reset() error {
|
||||||
c.alias.Clear()
|
c.alias.Clear()
|
||||||
|
|
@ -52,8 +87,6 @@ func (c *Command) defaultCmd() error {
|
||||||
return c.run(c.app.Config.ActiveView(), true)
|
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 {
|
func (c *Command) specialCmd(cmd string) bool {
|
||||||
cmds := strings.Split(cmd, " ")
|
cmds := strings.Split(cmd, " ")
|
||||||
switch cmds[0] {
|
switch cmds[0] {
|
||||||
|
|
@ -96,37 +129,6 @@ func (c *Command) viewMetaFor(cmd string) (string, *MetaViewer, error) {
|
||||||
return gvr, &v, nil
|
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 {
|
func (c *Command) componentFor(gvr string, v *MetaViewer) ResourceViewer {
|
||||||
var view ResourceViewer
|
var view ResourceViewer
|
||||||
if v.viewerFn != nil {
|
if v.viewerFn != nil {
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,7 @@ func (v *Help) showGeneral() model.MenuHints {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Mnemonic: "Ctrl-r",
|
Mnemonic: "Ctrl-r",
|
||||||
Description: "Refresh",
|
Description: "Reload",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Mnemonic: "Ctrl-u",
|
Mnemonic: "Ctrl-u",
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,6 @@ func toYAML(o runtime.Object) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func showPodsWithLabels(app *App, path string, sel map[string]string) {
|
func showPodsWithLabels(app *App, path string, sel map[string]string) {
|
||||||
log.Debug().Msgf("SHOWING POD FOR %#v", sel)
|
|
||||||
var labels []string
|
var labels []string
|
||||||
for k, v := range sel {
|
for k, v := range sel {
|
||||||
labels = append(labels, fmt.Sprintf("%s=%s", k, v))
|
labels = append(labels, fmt.Sprintf("%s=%s", k, v))
|
||||||
|
|
|
||||||
|
|
@ -131,12 +131,8 @@ func (l *Log) bindKeys() {
|
||||||
tcell.KeyEscape: ui.NewKeyAction("Back", l.app.PrevCmd, true),
|
tcell.KeyEscape: ui.NewKeyAction("Back", l.app.PrevCmd, true),
|
||||||
ui.KeyC: ui.NewKeyAction("Clear", l.clearCmd, true),
|
ui.KeyC: ui.NewKeyAction("Clear", l.clearCmd, true),
|
||||||
ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true),
|
ui.KeyS: ui.NewKeyAction("Toggle AutoScroll", l.toggleAutoScrollCmd, true),
|
||||||
ui.KeyG: ui.NewKeyAction("Top", l.topCmd, false),
|
ui.KeyF: ui.NewKeyAction("FullScreen", l.fullScreenCmd, true),
|
||||||
ui.KeyShiftF: ui.NewKeyAction("FullScreen", l.fullScreenCmd, true),
|
|
||||||
ui.KeyW: ui.NewKeyAction("Toggle Wrap", l.textWrapCmd, 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),
|
tcell.KeyCtrlS: ui.NewKeyAction("Save", l.SaveCmd, true),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -306,32 +302,6 @@ func saveData(cluster, name, data string) (string, error) {
|
||||||
return path, nil
|
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 {
|
func (l *Log) clearCmd(*tcell.EventKey) *tcell.EventKey {
|
||||||
l.app.Flash().Info("Clearing logs...")
|
l.app.Flash().Info("Clearing logs...")
|
||||||
l.logs.Clear()
|
l.logs.Clear()
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ func TestLogFlush(t *testing.T) {
|
||||||
assert.Equal(t, " Autoscroll: Off FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
|
assert.Equal(t, " Autoscroll: Off FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
|
||||||
v.toggleAutoScrollCmd(nil)
|
v.toggleAutoScrollCmd(nil)
|
||||||
assert.Equal(t, " Autoscroll: On FullScreen: Off Wrap: Off ", v.Indicator().GetText(true))
|
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) {
|
func TestLogViewSave(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@ package view
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
|
"github.com/derailed/k9s/internal/render"
|
||||||
"github.com/derailed/k9s/internal/ui"
|
"github.com/derailed/k9s/internal/ui"
|
||||||
|
"github.com/derailed/k9s/internal/watch"
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
@ -55,6 +57,15 @@ func isResourcePath(p string) bool {
|
||||||
|
|
||||||
func (l *LogsExtender) showLogs(path string, prev bool) {
|
func (l *LogsExtender) showLogs(path string, prev bool) {
|
||||||
log.Debug().Msgf("SHOWING LOGS path %q", path)
|
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 := ""
|
co := ""
|
||||||
if l.containerFn != nil {
|
if l.containerFn != nil {
|
||||||
co = l.containerFn()
|
co = l.containerFn()
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,8 @@ func (p *PortForward) portForwardContext(ctx context.Context) context.Context {
|
||||||
func (p *PortForward) bindKeys(aa ui.KeyActions) {
|
func (p *PortForward) bindKeys(aa ui.KeyActions) {
|
||||||
aa.Add(ui.KeyActions{
|
aa.Add(ui.KeyActions{
|
||||||
tcell.KeyEnter: ui.NewKeyAction("Benchmarks", p.showBenchCmd, true),
|
tcell.KeyEnter: ui.NewKeyAction("Benchmarks", p.showBenchCmd, true),
|
||||||
tcell.KeyCtrlB: ui.NewKeyAction("Bench", p.benchCmd, true),
|
ui.KeyB: ui.NewKeyAction("Bench", p.benchCmd, true),
|
||||||
tcell.KeyCtrlK: ui.NewKeyAction("Bench Stop", p.benchStopCmd, true),
|
ui.KeyK: ui.NewKeyAction("Bench Stop", p.benchStopCmd, true),
|
||||||
tcell.KeyCtrlD: ui.NewKeyAction("Delete", p.deleteCmd, true),
|
tcell.KeyCtrlD: ui.NewKeyAction("Delete", p.deleteCmd, true),
|
||||||
ui.KeyShiftP: ui.NewKeyAction("Sort Ports", p.GetTable().SortColCmd(2, true), false),
|
ui.KeyShiftP: ui.NewKeyAction("Sort Ports", p.GetTable().SortColCmd(2, true), false),
|
||||||
ui.KeyShiftU: ui.NewKeyAction("Sort URL", p.GetTable().SortColCmd(4, 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.App().Status(ui.FlashErr, "Benchmark Camceled!")
|
||||||
p.bench.Cancel()
|
p.bench.Cancel()
|
||||||
}
|
}
|
||||||
p.App().ClearStatus()
|
p.App().ClearStatus(true)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -95,9 +95,9 @@ func (p *PortForward) benchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
|
|
||||||
base := ui.TrimCell(p.GetTable().SelectTable, r, 4)
|
base := ui.TrimCell(p.GetTable().SelectTable, r, 4)
|
||||||
var err error
|
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().Flash().Errf("Bench failed %v", err)
|
||||||
p.App().ClearStatus()
|
p.App().ClearStatus(false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +121,7 @@ func (p *PortForward) runBenchmark() {
|
||||||
p.bench = nil
|
p.bench = nil
|
||||||
go func() {
|
go func() {
|
||||||
<-time.After(2 * time.Second)
|
<-time.After(2 * time.Second)
|
||||||
p.App().QueueUpdate(func() { p.App().ClearStatus() })
|
p.App().QueueUpdate(func() { p.App().ClearStatus(true) })
|
||||||
}()
|
}()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -32,19 +32,19 @@ func NewReplicaSet(gvr client.GVR) ResourceViewer {
|
||||||
r := ReplicaSet{
|
r := ReplicaSet{
|
||||||
ResourceViewer: NewBrowser(gvr),
|
ResourceViewer: NewBrowser(gvr),
|
||||||
}
|
}
|
||||||
r.bindKeys()
|
r.SetBindKeysFn(r.bindKeys)
|
||||||
r.GetTable().SetEnterFn(r.showPods)
|
r.GetTable().SetEnterFn(r.showPods)
|
||||||
r.GetTable().SetColorerFn(render.ReplicaSet{}.ColorerFunc())
|
r.GetTable().SetColorerFn(render.ReplicaSet{}.ColorerFunc())
|
||||||
|
|
||||||
return &r
|
return &r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReplicaSet) bindKeys() {
|
func (r *ReplicaSet) bindKeys(aa ui.KeyActions) {
|
||||||
r.Actions().Add(ui.KeyActions{
|
aa.Add(ui.KeyActions{
|
||||||
ui.KeyShiftD: ui.NewKeyAction("Sort Desired", r.GetTable().SortColCmd(1, true), false),
|
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.KeyShiftC: ui.NewKeyAction("Sort Current", r.GetTable().SortColCmd(2, true), false),
|
||||||
ui.KeyShiftR: ui.NewKeyAction("Sort Ready", r.GetTable().SortColCmd(3, 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),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,17 +40,26 @@ func (s *StatefulSet) bindKeys(aa ui.KeyActions) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *StatefulSet) showPods(app *App, _, gvr, path string) {
|
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 {
|
if err != nil {
|
||||||
app.Flash().Err(err)
|
app.Flash().Err(err)
|
||||||
return
|
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
|
var sts appsv1.StatefulSet
|
||||||
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &sts)
|
err = runtime.DefaultUnstructuredConverter.FromUnstructured(o.(*unstructured.Unstructured).Object, &sts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Flash().Err(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
showPodsFromSelector(app, strings.Replace(path, "/", "::", 1), sts.Spec.Selector)
|
return &sts, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,13 @@ 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", s.benchCmd, true),
|
ui.KeyB: ui.NewKeyAction("Bench", s.benchCmd, true),
|
||||||
tcell.KeyCtrlK: ui.NewKeyAction("Bench Stop", s.benchStopCmd, true),
|
ui.KeyK: ui.NewKeyAction("Bench Stop", s.benchStopCmd, true),
|
||||||
ui.KeyShiftT: ui.NewKeyAction("Sort Type", s.GetTable().SortColCmd(1, true), false),
|
ui.KeyShiftT: ui.NewKeyAction("Sort Type", s.GetTable().SortColCmd(1, true), false),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) showPods(app *App, ns, gvr, path string) {
|
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())
|
o, err := app.factory.Get(gvr, path, labels.Everything())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
app.Flash().Err(err)
|
app.Flash().Err(err)
|
||||||
|
|
@ -61,7 +60,7 @@ func (s *Service) showPods(app *App, ns, gvr, path string) {
|
||||||
return
|
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 {
|
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.App().Status(ui.FlashErr, "Benchmark Canceled!")
|
||||||
s.bench.Cancel()
|
s.bench.Cancel()
|
||||||
}
|
}
|
||||||
s.App().ClearStatus()
|
s.App().ClearStatus(true)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +135,7 @@ func (s *Service) benchCmd(evt *tcell.EventKey) *tcell.EventKey {
|
||||||
}
|
}
|
||||||
if err := s.runBenchmark(port, cfg); err != nil {
|
if err := s.runBenchmark(port, cfg); err != nil {
|
||||||
s.App().Flash().Errf("Benchmark failed %v", err)
|
s.App().Flash().Errf("Benchmark failed %v", err)
|
||||||
s.App().ClearStatus()
|
s.App().ClearStatus(false)
|
||||||
s.bench = nil
|
s.bench = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -151,7 +150,7 @@ func (s *Service) runBenchmark(port string, cfg config.BenchConfig) error {
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
base := "http://" + cfg.HTTP.Host + ":" + port + cfg.HTTP.Path
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,6 +178,6 @@ func (s *Service) benchDone() {
|
||||||
func benchTimedOut(app *App) {
|
func benchTimedOut(app *App) {
|
||||||
<-time.After(2 * time.Second)
|
<-time.After(2 * time.Second)
|
||||||
app.QueueUpdate(func() {
|
app.QueueUpdate(func() {
|
||||||
app.ClearStatus()
|
app.ClearStatus(true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ const (
|
||||||
clusterScope = "-"
|
clusterScope = "-"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ReadVerbs = []string{"get", "list", "watch"}
|
||||||
|
|
||||||
// Factory tracks various resource informers.
|
// Factory tracks various resource informers.
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
factories map[string]di.DynamicSharedInformerFactory
|
factories map[string]di.DynamicSharedInformerFactory
|
||||||
|
|
@ -37,6 +39,7 @@ func NewFactory(client client.Connection) *Factory {
|
||||||
|
|
||||||
// Start initializes the informers until caller cancels the context.
|
// Start initializes the informers until caller cancels the context.
|
||||||
func (f *Factory) Start(ns string) {
|
func (f *Factory) Start(ns string) {
|
||||||
|
log.Debug().Msgf("Starting factory in ns `%q", ns)
|
||||||
f.stopChan = make(chan struct{})
|
f.stopChan = make(chan struct{})
|
||||||
for ns, fac := range f.factories {
|
for ns, fac := range f.factories {
|
||||||
log.Debug().Msgf("Starting factory in ns %q", ns)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("LISTING %q:%q", ns, gvr)
|
||||||
if ns == clusterScope {
|
if ns == clusterScope {
|
||||||
return inf.Lister().List(sel)
|
return inf.Lister().List(sel)
|
||||||
}
|
}
|
||||||
|
|
||||||
return inf.Lister().ByNamespace(ns).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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
log.Debug().Msgf("GETTING %q:%q", ns, gvr)
|
||||||
|
|
||||||
if ns == clusterScope {
|
if ns == clusterScope {
|
||||||
return inf.Lister().Get(n)
|
return inf.Lister().Get(n)
|
||||||
}
|
}
|
||||||
|
|
@ -117,8 +122,7 @@ func (f *Factory) isClusterWide() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Factory) preload(_ string) {
|
func (f *Factory) preload(_ string) {
|
||||||
verbs := []string{"get", "list", "watch"}
|
_, _ = f.CanForResource("", "apiextensions.k8s.io/v1beta1/customresourcedefinitions", ReadVerbs...)
|
||||||
_, _ = f.CanForResource("", "apiextensions.k8s.io/v1beta1/customresourcedefinitions", verbs...)
|
|
||||||
// BOZO!!
|
// BOZO!!
|
||||||
// _, _ = f.CanForResource(ns, "v1/pods", verbs...)
|
// _, _ = f.CanForResource(ns, "v1/pods", verbs...)
|
||||||
// _, _ = f.CanForResource(clusterScope, "rbac.authorization.k8s.io/v1/clusterroles", 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 {
|
func (f *Factory) ensureFactory(ns string) di.DynamicSharedInformerFactory {
|
||||||
if f.isClusterWide() {
|
|
||||||
ns = allNamespaces
|
|
||||||
}
|
|
||||||
if fac, ok := f.factories[ns]; ok {
|
if fac, ok := f.factories[ns]; ok {
|
||||||
return fac
|
return fac
|
||||||
}
|
}
|
||||||
|
|
@ -173,12 +174,9 @@ func (f *Factory) AddForwarder(pf Forwarder) {
|
||||||
|
|
||||||
// DeleteForwarder deletes portforward for a given container.
|
// DeleteForwarder deletes portforward for a given container.
|
||||||
func (f *Factory) DeleteForwarder(path string) {
|
func (f *Factory) DeleteForwarder(path string) {
|
||||||
fwd, ok := f.forwarders[path]
|
f.forwarders.Dump()
|
||||||
if !ok {
|
count := f.forwarders.Kill(path)
|
||||||
return
|
log.Warn().Msgf("Deleted (%d) portforward for %q", count, path)
|
||||||
}
|
|
||||||
fwd.Stop()
|
|
||||||
delete(f.forwarders, path)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forwarders returns all portforwards.
|
// Forwarders returns all portforwards.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue