fix navigator
parent
8192e1f6ad
commit
a839b7f84a
|
|
@ -48,7 +48,7 @@ func (n *Namespace) Validate(c Connection, ks KubeSettings) {
|
|||
|
||||
// SetActive set the active namespace.
|
||||
func (n *Namespace) SetActive(ns string, ks KubeSettings) error {
|
||||
log.Debug().Msgf("Setting active ns %s", ns)
|
||||
log.Debug().Msgf("Setting active ns %q", ns)
|
||||
n.Active = ns
|
||||
if ns != "" {
|
||||
n.addFavNS(ns)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,16 @@ func (b *base) SetLabelSelector(s string) {
|
|||
b.labelSelector = s
|
||||
}
|
||||
|
||||
// GetFieldSelector returns field selector.
|
||||
func (b *base) GetFieldSelector() string {
|
||||
return b.fieldSelector
|
||||
}
|
||||
|
||||
// GetLabelSelector returns label selector.
|
||||
func (b *base) GetLabelSelector() string {
|
||||
return b.labelSelector
|
||||
}
|
||||
|
||||
func (b *base) HasSelectors() bool {
|
||||
return b.labelSelector != "" || b.fieldSelector != ""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ type (
|
|||
Delete(ns string, name string) error
|
||||
SetLabelSelector(string)
|
||||
SetFieldSelector(string)
|
||||
GetLabelSelector() string
|
||||
GetFieldSelector() string
|
||||
HasSelectors() bool
|
||||
}
|
||||
|
||||
|
|
@ -70,6 +72,16 @@ func (b *Base) SetLabelSelector(s string) {
|
|||
b.Resource.SetLabelSelector(s)
|
||||
}
|
||||
|
||||
// GetFieldSelector returns field selector.
|
||||
func (b *Base) GetFieldSelector() string {
|
||||
return b.Resource.GetFieldSelector()
|
||||
}
|
||||
|
||||
// GetLabelSelector returns label selector.
|
||||
func (b *Base) GetLabelSelector() string {
|
||||
return b.Resource.GetLabelSelector()
|
||||
}
|
||||
|
||||
// Name returns the resource namespaced name.
|
||||
func (b *Base) Name() string {
|
||||
return b.path
|
||||
|
|
|
|||
|
|
@ -108,6 +108,8 @@ type (
|
|||
Header(ns string) Row
|
||||
SetFieldSelector(string)
|
||||
SetLabelSelector(string)
|
||||
GetFieldSelector() string
|
||||
GetLabelSelector() string
|
||||
HasSelectors() bool
|
||||
}
|
||||
|
||||
|
|
@ -232,12 +234,16 @@ func metaFQN(m metav1.ObjectMeta) string {
|
|||
}
|
||||
|
||||
func (l *list) fetchFromStore(m *wa.Meta, ns string) (Columnars, error) {
|
||||
rr, err := m.List(l.name, ns)
|
||||
rr, err := m.List(l.name, ns, metav1.ListOptions{
|
||||
FieldSelector: l.resource.GetFieldSelector(),
|
||||
LabelSelector: l.resource.GetLabelSelector(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
items := make(Columnars, 0, len(rr))
|
||||
opts := metav1.GetOptions{}
|
||||
for _, r := range rr {
|
||||
var (
|
||||
fqn string
|
||||
|
|
@ -247,7 +253,7 @@ func (l *list) fetchFromStore(m *wa.Meta, ns string) (Columnars, error) {
|
|||
case *v1.Node:
|
||||
fqn = metaFQN(o.ObjectMeta)
|
||||
res = l.resource.New(r)
|
||||
nmx, err := m.Get(wa.NodeMXIndex, fqn)
|
||||
nmx, err := m.Get(wa.NodeMXIndex, fqn, opts)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("NodeMetrics")
|
||||
}
|
||||
|
|
@ -257,7 +263,7 @@ func (l *list) fetchFromStore(m *wa.Meta, ns string) (Columnars, error) {
|
|||
case *v1.Pod:
|
||||
fqn = metaFQN(o.ObjectMeta)
|
||||
res = l.resource.New(r)
|
||||
pmx, err := m.Get(wa.PodMXIndex, fqn)
|
||||
pmx, err := m.Get(wa.PodMXIndex, fqn, opts)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("PodMetrics")
|
||||
}
|
||||
|
|
@ -267,7 +273,7 @@ func (l *list) fetchFromStore(m *wa.Meta, ns string) (Columnars, error) {
|
|||
case v1.Container:
|
||||
fqn = ns
|
||||
res = l.resource.New(r)
|
||||
pmx, err := m.Get(wa.PodMXIndex, fqn)
|
||||
pmx, err := m.Get(wa.PodMXIndex, fqn, opts)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("PodMetrics")
|
||||
}
|
||||
|
|
@ -294,7 +300,6 @@ func (l *list) Reconcile(m *wa.Meta, path *string) error {
|
|||
if rr, err := l.fetchFromStore(m, ns); err == nil {
|
||||
items = rr
|
||||
} else {
|
||||
log.Debug().Msg("Standard load")
|
||||
items, err = l.resource.List(l.namespace)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -52,6 +52,36 @@ func (mock *MockCruder) Get(_param0 string, _param1 string) (interface{}, error)
|
|||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockCruder) GetFieldSelector() string {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockCruder().")
|
||||
}
|
||||
params := []pegomock.Param{}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("GetFieldSelector", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
|
||||
var ret0 string
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(string)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockCruder) GetLabelSelector() string {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockCruder().")
|
||||
}
|
||||
params := []pegomock.Param{}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("GetLabelSelector", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
|
||||
var ret0 string
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(string)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockCruder) HasSelectors() bool {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockCruder().")
|
||||
|
|
@ -201,6 +231,40 @@ func (c *Cruder_Get_OngoingVerification) GetAllCapturedArguments() (_param0 []st
|
|||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierCruder) GetFieldSelector() *Cruder_GetFieldSelector_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetFieldSelector", params, verifier.timeout)
|
||||
return &Cruder_GetFieldSelector_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type Cruder_GetFieldSelector_OngoingVerification struct {
|
||||
mock *MockCruder
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *Cruder_GetFieldSelector_OngoingVerification) GetCapturedArguments() {
|
||||
}
|
||||
|
||||
func (c *Cruder_GetFieldSelector_OngoingVerification) GetAllCapturedArguments() {
|
||||
}
|
||||
|
||||
func (verifier *VerifierCruder) GetLabelSelector() *Cruder_GetLabelSelector_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetLabelSelector", params, verifier.timeout)
|
||||
return &Cruder_GetLabelSelector_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type Cruder_GetLabelSelector_OngoingVerification struct {
|
||||
mock *MockCruder
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *Cruder_GetLabelSelector_OngoingVerification) GetCapturedArguments() {
|
||||
}
|
||||
|
||||
func (c *Cruder_GetLabelSelector_OngoingVerification) GetAllCapturedArguments() {
|
||||
}
|
||||
|
||||
func (verifier *VerifierCruder) HasSelectors() *Cruder_HasSelectors_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "HasSelectors", params, verifier.timeout)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,36 @@ func (mock *MockSwitchableCruder) Get(_param0 string, _param1 string) (interface
|
|||
return ret0, ret1
|
||||
}
|
||||
|
||||
func (mock *MockSwitchableCruder) GetFieldSelector() string {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockSwitchableCruder().")
|
||||
}
|
||||
params := []pegomock.Param{}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("GetFieldSelector", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
|
||||
var ret0 string
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(string)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockSwitchableCruder) GetLabelSelector() string {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockSwitchableCruder().")
|
||||
}
|
||||
params := []pegomock.Param{}
|
||||
result := pegomock.GetGenericMockFrom(mock).Invoke("GetLabelSelector", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem()})
|
||||
var ret0 string
|
||||
if len(result) != 0 {
|
||||
if result[0] != nil {
|
||||
ret0 = result[0].(string)
|
||||
}
|
||||
}
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (mock *MockSwitchableCruder) HasSelectors() bool {
|
||||
if mock == nil {
|
||||
panic("mock must not be nil. Use myMock := NewMockSwitchableCruder().")
|
||||
|
|
@ -231,6 +261,40 @@ func (c *SwitchableCruder_Get_OngoingVerification) GetAllCapturedArguments() (_p
|
|||
return
|
||||
}
|
||||
|
||||
func (verifier *VerifierSwitchableCruder) GetFieldSelector() *SwitchableCruder_GetFieldSelector_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetFieldSelector", params, verifier.timeout)
|
||||
return &SwitchableCruder_GetFieldSelector_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type SwitchableCruder_GetFieldSelector_OngoingVerification struct {
|
||||
mock *MockSwitchableCruder
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *SwitchableCruder_GetFieldSelector_OngoingVerification) GetCapturedArguments() {
|
||||
}
|
||||
|
||||
func (c *SwitchableCruder_GetFieldSelector_OngoingVerification) GetAllCapturedArguments() {
|
||||
}
|
||||
|
||||
func (verifier *VerifierSwitchableCruder) GetLabelSelector() *SwitchableCruder_GetLabelSelector_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "GetLabelSelector", params, verifier.timeout)
|
||||
return &SwitchableCruder_GetLabelSelector_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
|
||||
}
|
||||
|
||||
type SwitchableCruder_GetLabelSelector_OngoingVerification struct {
|
||||
mock *MockSwitchableCruder
|
||||
methodInvocations []pegomock.MethodInvocation
|
||||
}
|
||||
|
||||
func (c *SwitchableCruder_GetLabelSelector_OngoingVerification) GetCapturedArguments() {
|
||||
}
|
||||
|
||||
func (c *SwitchableCruder_GetLabelSelector_OngoingVerification) GetAllCapturedArguments() {
|
||||
}
|
||||
|
||||
func (verifier *VerifierSwitchableCruder) HasSelectors() *SwitchableCruder_HasSelectors_OngoingVerification {
|
||||
params := []pegomock.Param{}
|
||||
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "HasSelectors", params, verifier.timeout)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/derailed/tview"
|
||||
"github.com/gdamore/tcell"
|
||||
"github.com/rs/zerolog/log"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type clusterInfoView struct {
|
||||
|
|
@ -103,12 +104,12 @@ func (v *clusterInfoView) refresh() {
|
|||
v.GetCell(row, 1).SetText(cluster.Version())
|
||||
row++
|
||||
|
||||
nos, err := v.app.informer.List(watch.NodeIndex, "")
|
||||
nos, err := v.app.informer.List(watch.NodeIndex, "", metav1.ListOptions{})
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("List nodes")
|
||||
return
|
||||
}
|
||||
nmx, err := v.app.informer.List(watch.NodeMXIndex, "")
|
||||
nmx, err := v.app.informer.List(watch.NodeMXIndex, "", metav1.ListOptions{})
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Msg("List node metrics")
|
||||
return
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ func (v *deployView) showPodsCmd(evt *tcell.EventKey) *tcell.EventKey {
|
|||
v.app.flash(flashErr, err.Error())
|
||||
return evt
|
||||
}
|
||||
showPods(v.app, "", "Deployment", v.selectedItem, sel.String(), "", v.backCmd)
|
||||
showPods(v.app, ns, "Deployment", v.selectedItem, sel.String(), "", v.backCmd)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,6 @@ func showPods(app *appView, ns, res, selected, labelSel, fieldSel string, b acti
|
|||
aa[tcell.KeyEsc] = newKeyAction("Back", b, true)
|
||||
})
|
||||
// Reset active namespace to all.
|
||||
app.config.SetActiveNamespace("")
|
||||
app.config.SetActiveNamespace(ns)
|
||||
app.inject(pv)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/gdamore/tcell"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const containerFmt = "[fg:bg:b]%s([hilite:bg:b]%s[fg:bg:-])"
|
||||
|
|
@ -52,10 +53,7 @@ func (v *podView) listContainers(app *appView, _, res, sel string) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Debug().Msgf("Selected %s", sel)
|
||||
// ns, n := namespaced(sel)
|
||||
po, err := v.app.informer.Get(watch.PodIndex, sel)
|
||||
// po, err := app.conn().DialOrDie().CoreV1().Pods(ns).Get(n, metav1.GetOptions{})
|
||||
po, err := v.app.informer.Get(watch.PodIndex, sel, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msgf("Unable to retrieve pod %s", sel)
|
||||
app.flash(flashErr, err.Error())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/derailed/k9s/internal/k8s"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -31,7 +32,7 @@ func (c *Container) StartWatching(stopCh <-chan struct{}) {}
|
|||
func (c *Container) Run(closeCh <-chan struct{}) {}
|
||||
|
||||
// Get retrieves a given container from store.
|
||||
func (c *Container) Get(fqn string) (interface{}, error) {
|
||||
func (c *Container) Get(fqn string, opts metav1.GetOptions) (interface{}, error) {
|
||||
o, ok, err := c.GetStore().GetByKey(fqn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -47,7 +48,7 @@ func (c *Container) Get(fqn string) (interface{}, error) {
|
|||
}
|
||||
|
||||
// List retrieves a given containers from store.
|
||||
func (c *Container) List(fqn string) k8s.Collection {
|
||||
func (c *Container) List(fqn string, opts metav1.ListOptions) k8s.Collection {
|
||||
o, ok, err := c.GetStore().GetByKey(fqn)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("Pod<container>")
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
// "github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -12,7 +13,7 @@ func TestContainerGet(t *testing.T) {
|
|||
|
||||
c := NewContainer(NewPod(cmo, ""))
|
||||
|
||||
o, err := c.Get("fred")
|
||||
o, err := c.Get("fred", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "not found")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
@ -22,7 +23,7 @@ func TestContainerList(t *testing.T) {
|
|||
|
||||
c := NewContainer(NewPod(cmo, ""))
|
||||
|
||||
o := c.List("fred")
|
||||
o := c.List("fred", metav1.ListOptions{})
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/derailed/k9s/internal/k8s"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
|
@ -37,8 +38,8 @@ type TableListenerFn func(TableData)
|
|||
// StoreInformer an informer that allows listeners registration.
|
||||
type StoreInformer interface {
|
||||
cache.SharedIndexInformer
|
||||
Get(fqn string) (interface{}, error)
|
||||
List(ns string) k8s.Collection
|
||||
Get(fqn string, opts metav1.GetOptions) (interface{}, error)
|
||||
List(ns string, opts metav1.ListOptions) k8s.Collection
|
||||
}
|
||||
|
||||
// Meta represents a collection of cluster wide watchers.
|
||||
|
|
@ -72,21 +73,21 @@ func (m *Meta) init(ns string) {
|
|||
}
|
||||
|
||||
// List items from store.
|
||||
func (m *Meta) List(res, ns string) (k8s.Collection, error) {
|
||||
func (m *Meta) List(res, ns string, opts metav1.ListOptions) (k8s.Collection, error) {
|
||||
if m == nil {
|
||||
return nil, fmt.Errorf("No meta exists")
|
||||
}
|
||||
if i, ok := m.informers[res]; ok {
|
||||
return i.List(ns), nil
|
||||
return i.List(ns, opts), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("No informer found for resource %s", res)
|
||||
}
|
||||
|
||||
// Get a resource by name.
|
||||
func (m Meta) Get(res, fqn string) (interface{}, error) {
|
||||
func (m Meta) Get(res, fqn string, opts metav1.GetOptions) (interface{}, error) {
|
||||
if informer, ok := m.informers[res]; ok {
|
||||
return informer.Get(fqn)
|
||||
return informer.Get(fqn, opts)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("No informer found for resource %s", res)
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestMetaList(t *testing.T) {
|
||||
cmo := NewMockConnection()
|
||||
m := NewMeta(cmo, "")
|
||||
|
||||
o, err := m.List(PodIndex, "fred")
|
||||
o, err := m.List(PodIndex, "fred", metav1.ListOptions{})
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, len(o) == 0)
|
||||
}
|
||||
|
|
@ -19,7 +20,7 @@ func TestMetaListNoRes(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
m := NewMeta(cmo, "")
|
||||
|
||||
o, err := m.List("dp", "fred")
|
||||
o, err := m.List("dp", "fred", metav1.ListOptions{})
|
||||
assert.ErrorContains(t, err, "No informer found")
|
||||
assert.Assert(t, len(o) == 0)
|
||||
}
|
||||
|
|
@ -28,7 +29,7 @@ func TestMetaGet(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
m := NewMeta(cmo, "")
|
||||
|
||||
o, err := m.Get(PodIndex, "fred")
|
||||
o, err := m.Get(PodIndex, "fred", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "Pod fred not found")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
@ -37,7 +38,7 @@ func TestMetaGetNoRes(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
m := NewMeta(cmo, "")
|
||||
|
||||
o, err := m.Get("rs", "fred")
|
||||
o, err := m.Get("rs", "fred", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "No informer found")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/derailed/k9s/internal/k8s"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
wv1 "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
|
@ -27,7 +28,7 @@ func NewNode(c k8s.Connection) *Node {
|
|||
}
|
||||
|
||||
// List all nodes.
|
||||
func (n *Node) List(_ string) k8s.Collection {
|
||||
func (n *Node) List(_ string, opts metav1.ListOptions) k8s.Collection {
|
||||
var res k8s.Collection
|
||||
for _, o := range n.GetStore().List() {
|
||||
res = append(res, o)
|
||||
|
|
@ -37,7 +38,7 @@ func (n *Node) List(_ string) k8s.Collection {
|
|||
}
|
||||
|
||||
// Get retrieves a given node from store.
|
||||
func (n *Node) Get(fqn string) (interface{}, error) {
|
||||
func (n *Node) Get(fqn string, opts metav1.GetOptions) (interface{}, error) {
|
||||
o, ok, err := n.GetStore().GetByKey(fqn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -36,12 +36,12 @@ func NewNodeMetrics(c k8s.Connection) *NodeMetrics {
|
|||
}
|
||||
|
||||
// List node metrics from store.
|
||||
func (p *NodeMetrics) List(string) k8s.Collection {
|
||||
func (p *NodeMetrics) List(_ string, opts metav1.ListOptions) k8s.Collection {
|
||||
return p.GetStore().List()
|
||||
}
|
||||
|
||||
// Get node metrics from store.
|
||||
func (p *NodeMetrics) Get(MetaFQN string) (interface{}, error) {
|
||||
func (p *NodeMetrics) Get(MetaFQN string, opts metav1.GetOptions) (interface{}, error) {
|
||||
o, ok, err := p.GetStore().GetByKey(MetaFQN)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestNodeMXList(t *testing.T) {
|
||||
cmo := NewMockConnection()
|
||||
no := NewNodeMetrics(cmo)
|
||||
|
||||
o := no.List("")
|
||||
o := no.List("", metav1.ListOptions{})
|
||||
assert.Assert(t, len(o) == 0)
|
||||
}
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ func TestNodeMXGet(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
no := NewNodeMetrics(cmo)
|
||||
|
||||
o, err := no.Get("")
|
||||
o, err := no.Get("", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "No node metrics")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestNodeList(t *testing.T) {
|
||||
cmo := NewMockConnection()
|
||||
no := NewNode(cmo)
|
||||
|
||||
o := no.List("")
|
||||
o := no.List("", metav1.ListOptions{})
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
||||
|
|
@ -18,7 +19,7 @@ func TestNodeGet(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
no := NewNode(cmo)
|
||||
|
||||
o, err := no.Get("")
|
||||
o, err := no.Get("", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "not found")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,12 @@ package watch
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/derailed/k9s/internal/k8s"
|
||||
"github.com/rs/zerolog/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
wv1 "k8s.io/client-go/informers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
|
@ -30,20 +33,48 @@ func NewPod(c Connection, ns string) *Pod {
|
|||
}
|
||||
}
|
||||
|
||||
func toSelector(s string) map[string]string {
|
||||
var m map[string]string
|
||||
ls, err := metav1.ParseToLabelSelector(s)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("StringToSel")
|
||||
return m
|
||||
}
|
||||
mSel, err := metav1.LabelSelectorAsMap(ls)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Msg("SelToMap")
|
||||
return m
|
||||
}
|
||||
|
||||
return mSel
|
||||
}
|
||||
|
||||
// List all pods from store in the given namespace.
|
||||
func (p *Pod) List(ns string) k8s.Collection {
|
||||
func (p *Pod) List(ns string, opts metav1.ListOptions) k8s.Collection {
|
||||
var res k8s.Collection
|
||||
var nodeSelector bool
|
||||
if strings.Contains(opts.FieldSelector, "spec.nodeName") {
|
||||
nodeSelector = true
|
||||
}
|
||||
for _, o := range p.GetStore().List() {
|
||||
pod := o.(*v1.Pod)
|
||||
if ns == "" || pod.Namespace == ns {
|
||||
res = append(res, pod)
|
||||
if ns != "" && pod.Namespace != ns {
|
||||
continue
|
||||
}
|
||||
if nodeSelector {
|
||||
if !matchesNode(pod.Spec.NodeName, toSelector(opts.FieldSelector)) {
|
||||
continue
|
||||
}
|
||||
} else if !matchesLabels(pod.ObjectMeta.Labels, toSelector(opts.LabelSelector)) {
|
||||
continue
|
||||
}
|
||||
res = append(res, pod)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Get retrieves a given pod from store.
|
||||
func (p *Pod) Get(fqn string) (interface{}, error) {
|
||||
func (p *Pod) Get(fqn string, opts metav1.GetOptions) (interface{}, error) {
|
||||
o, ok, err := p.GetStore().GetByKey(fqn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -54,3 +85,24 @@ func (p *Pod) Get(fqn string) (interface{}, error) {
|
|||
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func matchesLabels(labels, selector map[string]string) bool {
|
||||
if len(selector) == 0 {
|
||||
return true
|
||||
}
|
||||
for k, v := range selector {
|
||||
la, ok := labels[k]
|
||||
if !ok || la != v {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func matchesNode(name string, selector map[string]string) bool {
|
||||
if len(selector) == 0 {
|
||||
return true
|
||||
}
|
||||
return selector["spec.nodeName"] == name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func NewPodMetrics(c k8s.Connection, ns string) *PodMetrics {
|
|||
}
|
||||
|
||||
// List pod metrics from store.
|
||||
func (p *PodMetrics) List(ns string) k8s.Collection {
|
||||
func (p *PodMetrics) List(ns string, opts metav1.ListOptions) k8s.Collection {
|
||||
var res k8s.Collection
|
||||
for _, o := range p.GetStore().List() {
|
||||
mx := o.(*mv1beta1.PodMetrics)
|
||||
|
|
@ -52,7 +52,7 @@ func (p *PodMetrics) List(ns string) k8s.Collection {
|
|||
}
|
||||
|
||||
// Get pod metrics from store.
|
||||
func (p *PodMetrics) Get(fqn string) (interface{}, error) {
|
||||
func (p *PodMetrics) Get(fqn string, opts metav1.GetOptions) (interface{}, error) {
|
||||
o, ok, err := p.GetStore().GetByKey(fqn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/rs/zerolog"
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
)
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ func TestPodMXList(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
no := NewPodMetrics(cmo, "")
|
||||
|
||||
o := no.List("")
|
||||
o := no.List("", metav1.ListOptions{})
|
||||
assert.Assert(t, len(o) == 0)
|
||||
}
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ func TestPodMXGet(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
no := NewPodMetrics(cmo, "")
|
||||
|
||||
o, err := no.Get("")
|
||||
o, err := no.Get("", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "No pod metrics")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@ import (
|
|||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestPodList(t *testing.T) {
|
||||
cmo := NewMockConnection()
|
||||
no := NewPod(cmo, "")
|
||||
|
||||
o := no.List("")
|
||||
o := no.List("", metav1.ListOptions{})
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
||||
|
|
@ -18,63 +19,7 @@ func TestPodGet(t *testing.T) {
|
|||
cmo := NewMockConnection()
|
||||
no := NewPod(cmo, "")
|
||||
|
||||
o, err := no.Get("")
|
||||
o, err := no.Get("", metav1.GetOptions{})
|
||||
assert.ErrorContains(t, err, "not found")
|
||||
assert.Assert(t, o == nil)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Helpers...
|
||||
|
||||
// func makePod() *v1.Pod {
|
||||
// var i int32 = 1
|
||||
// var t = v1.HostPathDirectory
|
||||
// return &v1.Pod{
|
||||
// ObjectMeta: metav1.ObjectMeta{
|
||||
// Namespace: "blee",
|
||||
// Name: "fred",
|
||||
// Labels: map[string]string{"blee": "duh"},
|
||||
// CreationTimestamp: metav1.Time{Time: testTime()},
|
||||
// },
|
||||
// Spec: v1.PodSpec{
|
||||
// Priority: &i,
|
||||
// PriorityClassName: "bozo",
|
||||
// Containers: []v1.Container{
|
||||
// {
|
||||
// Name: "fred",
|
||||
// Image: "blee",
|
||||
// Env: []v1.EnvVar{
|
||||
// {
|
||||
// Name: "fred",
|
||||
// Value: "1",
|
||||
// ValueFrom: &v1.EnvVarSource{
|
||||
// ConfigMapKeyRef: &v1.ConfigMapKeySelector{Key: "blee"},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// Volumes: []v1.Volume{
|
||||
// {
|
||||
// Name: "fred",
|
||||
// VolumeSource: v1.VolumeSource{
|
||||
// HostPath: &v1.HostPathVolumeSource{
|
||||
// Path: "/blee",
|
||||
// Type: &t,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// Status: v1.PodStatus{
|
||||
// Phase: "Running",
|
||||
// ContainerStatuses: []v1.ContainerStatus{
|
||||
// {
|
||||
// Name: "fred",
|
||||
// State: v1.ContainerState{Running: &v1.ContainerStateRunning{}},
|
||||
// RestartCount: 0,
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
|
|
|
|||
Loading…
Reference in New Issue