github.com/Azure/aad-pod-identity@v1.8.17/pkg/pod/pod.go (about)

     1  package pod
     2  
     3  import (
     4  	"strings"
     5  	"time"
     6  
     7  	aadpodid "github.com/Azure/aad-pod-identity/pkg/apis/aadpodidentity"
     8  	"github.com/Azure/aad-pod-identity/pkg/stats"
     9  
    10  	v1 "k8s.io/api/core/v1"
    11  	"k8s.io/apimachinery/pkg/labels"
    12  	"k8s.io/apimachinery/pkg/selection"
    13  	"k8s.io/client-go/informers"
    14  	informersv1 "k8s.io/client-go/informers/core/v1"
    15  	"k8s.io/client-go/tools/cache"
    16  	"k8s.io/klog/v2"
    17  )
    18  
    19  // Client represents new pod client
    20  type Client struct {
    21  	PodWatcher informersv1.PodInformer
    22  }
    23  
    24  // ClientInt represents pod client interface
    25  type ClientInt interface {
    26  	GetPods() (pods []*v1.Pod, err error)
    27  	Start(exit <-chan struct{})
    28  }
    29  
    30  // NewPodClient returns new pod client
    31  func NewPodClient(i informers.SharedInformerFactory, eventCh chan aadpodid.EventType) ClientInt {
    32  	podInformer := i.Core().V1().Pods()
    33  	addPodHandler(podInformer, eventCh)
    34  
    35  	return &Client{
    36  		PodWatcher: podInformer,
    37  	}
    38  }
    39  
    40  func addPodHandler(i informersv1.PodInformer, eventCh chan aadpodid.EventType) {
    41  	i.Informer().AddEventHandler(
    42  		cache.ResourceEventHandlerFuncs{
    43  			AddFunc: func(obj interface{}) {
    44  				klog.V(6).Infof("pod created")
    45  				eventCh <- aadpodid.PodCreated
    46  			},
    47  			DeleteFunc: func(obj interface{}) {
    48  				klog.V(6).Infof("pod deleted")
    49  				eventCh <- aadpodid.PodDeleted
    50  			},
    51  			UpdateFunc: func(oldObj, newObj interface{}) {
    52  				// We are only interested in updates to pod if the node or label changes.
    53  				// Having this check will ensure that mic sync loop does not do extra work
    54  				// for every pod update.
    55  				oldPod, newPod := oldObj.(*v1.Pod), newObj.(*v1.Pod)
    56  				if oldPod.Spec.NodeName != newPod.Spec.NodeName || oldPod.ObjectMeta.Labels[aadpodid.CRDLabelKey] != newPod.ObjectMeta.Labels[aadpodid.CRDLabelKey] {
    57  					klog.V(6).Infof("pod updated")
    58  					eventCh <- aadpodid.PodUpdated
    59  				}
    60  			},
    61  		},
    62  	)
    63  }
    64  
    65  func (c *Client) syncCache(exit <-chan struct{}) {
    66  	cacheSyncStarted := time.Now()
    67  	klog.V(6).Infof("wait for cache to sync")
    68  	if !cache.WaitForCacheSync(exit, c.PodWatcher.Informer().HasSynced) {
    69  		klog.Error("wait for pod cache sync failed")
    70  		return
    71  	}
    72  	klog.Infof("pod cache synchronized. Took %s", time.Since(cacheSyncStarted).String())
    73  }
    74  
    75  // Start starts watching for any pod-related changes.
    76  func (c *Client) Start(exit <-chan struct{}) {
    77  	go c.PodWatcher.Informer().Run(exit)
    78  	c.syncCache(exit)
    79  	klog.Info("pod watcher started !!")
    80  }
    81  
    82  // GetPods returns list of all pods
    83  func (c *Client) GetPods() ([]*v1.Pod, error) {
    84  	begin := time.Now()
    85  	crdReq, err := labels.NewRequirement(aadpodid.CRDLabelKey, selection.Exists, nil)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	crdSelector := labels.NewSelector().Add(*crdReq)
    90  	listPods, err := c.PodWatcher.Lister().List(crdSelector)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	stats.Put(stats.PodList, time.Since(begin))
    95  	return listPods, nil
    96  }
    97  
    98  // IsPodExcepted returns true if pod label is part of exception crd
    99  func IsPodExcepted(podLabels map[string]string, exceptionList []aadpodid.AzurePodIdentityException) bool {
   100  	return len(exceptionList) > 0 && labelInExceptionList(podLabels, exceptionList)
   101  }
   102  
   103  // labelInExceptionList checks if the labels defined in azurepodidentityexception match label defined in pods
   104  func labelInExceptionList(podLabels map[string]string, exceptionList []aadpodid.AzurePodIdentityException) bool {
   105  	for _, exception := range exceptionList {
   106  		for exceptionLabelKey, exceptionLabelValue := range exception.Spec.PodLabels {
   107  			if val, ok := podLabels[exceptionLabelKey]; ok {
   108  				if strings.EqualFold(val, exceptionLabelValue) {
   109  					return true
   110  				}
   111  			}
   112  		}
   113  	}
   114  	return false
   115  }