120 lines
2.8 KiB
Go
120 lines
2.8 KiB
Go
package watch
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/derailed/k9s/internal/k8s"
|
|
"github.com/rs/zerolog/log"
|
|
"k8s.io/apimachinery/pkg/watch"
|
|
"k8s.io/client-go/tools/cache"
|
|
)
|
|
|
|
type (
|
|
// Row represents a collection of string fields.
|
|
Row []string
|
|
|
|
// RowEvent represents a call for action after a resource reconciliation.
|
|
// Tracks whether a resource got added, deleted or updated.
|
|
RowEvent struct {
|
|
Action watch.EventType
|
|
Fields Row
|
|
Deltas Row
|
|
}
|
|
|
|
// RowEvents tracks resource update events.
|
|
RowEvents map[string]*RowEvent
|
|
|
|
// TableData tracks a K8s resource for tabular display.
|
|
TableData struct {
|
|
Header Row
|
|
Rows RowEvents
|
|
Namespace string
|
|
}
|
|
)
|
|
|
|
// TableListenerFn represents a table data listener.
|
|
type TableListenerFn func(TableData)
|
|
|
|
// CallbackInformer an informer that allows listeners registration.
|
|
type CallbackInformer interface {
|
|
cache.SharedIndexInformer
|
|
Get(fqn string) (interface{}, error)
|
|
List(ns string) (k8s.Collection, error)
|
|
SetListener(ns string, cb TableListenerFn)
|
|
UnsetListener(ns string)
|
|
}
|
|
|
|
// Meta represents a collection of cluster wide watchers.
|
|
type Meta struct {
|
|
informers map[string]CallbackInformer
|
|
client k8s.Connection
|
|
podInformer *Pod
|
|
listenerFn TableListenerFn
|
|
}
|
|
|
|
// NewMeta creates a new cluster resource informer
|
|
func NewMeta(client k8s.Connection, ns string) *Meta {
|
|
m := Meta{client: client, informers: map[string]CallbackInformer{}}
|
|
m.init(ns)
|
|
|
|
return &m
|
|
}
|
|
|
|
func (m *Meta) init(ns string) {
|
|
po := NewPod(m.client, ns)
|
|
m.informers = map[string]CallbackInformer{
|
|
NodeIndex: NewNode(m.client),
|
|
NodeMXIndex: NewNodeMetrics(m.client),
|
|
PodIndex: po,
|
|
PodMXIndex: NewPodMetrics(m.client, ns),
|
|
ContainerIndex: NewContainer(po),
|
|
}
|
|
}
|
|
|
|
// List items from store.
|
|
func (m *Meta) List(res, ns string) (k8s.Collection, error) {
|
|
if m == nil {
|
|
return nil, fmt.Errorf("No meta exists")
|
|
}
|
|
if i, ok := m.informers[res]; ok {
|
|
return i.List(ns)
|
|
}
|
|
|
|
return nil, fmt.Errorf("No informer found for resource %s", res)
|
|
}
|
|
|
|
// RegisterListener register table data listeners.
|
|
func (m *Meta) RegisterListener(res, ns string, cb TableListenerFn) {
|
|
if informer, ok := m.informers[res]; ok {
|
|
informer.SetListener(ns, cb)
|
|
} else {
|
|
log.Error().Msgf("No informer for %q:%s", ns, res)
|
|
}
|
|
}
|
|
|
|
// UnregisterListener register table data listeners.
|
|
func (m *Meta) UnregisterListener(ns string) {
|
|
for _, i := range m.informers {
|
|
i.UnsetListener(ns)
|
|
}
|
|
}
|
|
|
|
// Get a resource by name.
|
|
func (m Meta) Get(res, fqn string) (interface{}, error) {
|
|
if informer, ok := m.informers[res]; ok {
|
|
return informer.Get(fqn)
|
|
}
|
|
|
|
return nil, errors.New("Unable to local resource")
|
|
}
|
|
|
|
// Run starts watching cluster resources.
|
|
func (m *Meta) Run(closeCh <-chan struct{}) {
|
|
for i := range m.informers {
|
|
go func(informer CallbackInformer, c <-chan struct{}) {
|
|
informer.Run(c)
|
|
}(m.informers[i], closeCh)
|
|
}
|
|
}
|