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 }