109 lines
2.2 KiB
Go
109 lines
2.2 KiB
Go
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"
|
|
)
|
|
|
|
const (
|
|
// PodIndex marker for stored pods.
|
|
PodIndex string = "po"
|
|
podCols = 11
|
|
)
|
|
|
|
// Connection represents an client api server connection.
|
|
type Connection k8s.Connection
|
|
|
|
// Pod tracks pod activities.
|
|
type Pod struct {
|
|
cache.SharedIndexInformer
|
|
}
|
|
|
|
// NewPod returns a new pod.
|
|
func NewPod(c Connection, ns string) *Pod {
|
|
return &Pod{
|
|
SharedIndexInformer: wv1.NewPodInformer(c.DialOrDie(), ns, 0, cache.Indexers{}),
|
|
}
|
|
}
|
|
|
|
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, 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 {
|
|
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, opts metav1.GetOptions) (interface{}, error) {
|
|
o, ok, err := p.GetStore().GetByKey(fqn)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !ok {
|
|
return nil, fmt.Errorf("Pod %s not found", fqn)
|
|
}
|
|
|
|
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
|
|
}
|