github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/monitor/internal/kubernetes/cache.go (about)

     1  // +build !windows
     2  
     3  package kubernetesmonitor
     4  
     5  import (
     6  	"sync"
     7  
     8  	"go.aporeto.io/trireme-lib/policy"
     9  )
    10  
    11  // puidCacheEntry is a Kubernetes entry based on Docker as a key.
    12  // This entry keeps track of the DockerMonitor properties that cannot be queried later on (such as the runtime)
    13  type puidCacheEntry struct {
    14  	// podID is the reference to the Kubernetes pod that this container refers to
    15  	kubeIdentifier string
    16  
    17  	// The latest reference to the runtime as received from DockerMonitor
    18  	dockerRuntime policy.RuntimeReader
    19  
    20  	// The latest reference to the runtime as received from DockerMonitor
    21  	kubernetesRuntime policy.RuntimeReader
    22  }
    23  
    24  // podCacheEntry is a Kubernetes entry based on a Pod as Key. The main goal here is to keep a mapping to all
    25  // existing Dockers PUIDs implementing this pod (as there might be multiple)
    26  type podCacheEntry struct {
    27  	// puIDs us a map containing a link to all the containers currently known to be part of that pod.
    28  	puIDs map[string]bool
    29  }
    30  
    31  // Cache is a cache implementation specific to KubernetesMonitor.
    32  // puidCache is centered on Docker and podCache is centered on Kubernetes
    33  type cache struct {
    34  	// popuidCache keeps a mapping between a PUID and the corresponding puidCacheEntry.
    35  	puidCache map[string]*puidCacheEntry
    36  
    37  	// podCache keeps a mapping between a POD/Namespace name and the corresponding podCacheEntry.
    38  	podCache map[string]*podCacheEntry
    39  
    40  	// Lock for the whole cache
    41  	sync.RWMutex
    42  }
    43  
    44  // NewCache initialize a cache
    45  func newCache() *cache {
    46  	return &cache{
    47  		puidCache: map[string]*puidCacheEntry{},
    48  		podCache:  map[string]*podCacheEntry{},
    49  	}
    50  }
    51  
    52  func kubePodIdentifier(podName string, podNamespace string) string {
    53  	return podNamespace + "/" + podName
    54  }
    55  
    56  // updatePUIDCache updates the cache with an entry coming from a container perspective
    57  func (c *cache) updatePUIDCache(podNamespace string, podName string, puID string, dockerRuntime policy.RuntimeReader, kubernetesRuntime policy.RuntimeReader) {
    58  	if podNamespace == "" || podName == "" || puID == "" {
    59  		return
    60  	}
    61  
    62  	c.Lock()
    63  	defer c.Unlock()
    64  
    65  	kubeIdentifier := kubePodIdentifier(podName, podNamespace)
    66  
    67  	puidEntry, ok := c.puidCache[puID]
    68  	if !ok {
    69  		puidEntry = &puidCacheEntry{}
    70  		c.puidCache[puID] = puidEntry
    71  	}
    72  	puidEntry.kubeIdentifier = kubeIdentifier
    73  	puidEntry.dockerRuntime = dockerRuntime
    74  	puidEntry.kubernetesRuntime = kubernetesRuntime
    75  
    76  	podEntry, ok := c.podCache[kubeIdentifier]
    77  	if !ok {
    78  		podEntry = &podCacheEntry{}
    79  		podEntry.puIDs = map[string]bool{}
    80  		c.podCache[kubeIdentifier] = podEntry
    81  	}
    82  	podEntry.puIDs[puID] = true
    83  
    84  }
    85  
    86  // deletePUIDCache deletes puid corresponding entries from the cache.
    87  func (c *cache) deletePUIDCache(puID string) {
    88  	c.Lock()
    89  	defer c.Unlock()
    90  
    91  	// Remove from pod cache.
    92  	puidEntry, ok := c.puidCache[puID]
    93  	if !ok {
    94  		return
    95  	}
    96  	kubeIdentifier := puidEntry.kubeIdentifier
    97  
    98  	podEntry, ok := c.podCache[kubeIdentifier]
    99  	if !ok {
   100  		return
   101  	}
   102  
   103  	delete(podEntry.puIDs, puID)
   104  
   105  	// if no more containers in the pod, delete the podEntry.
   106  	if len(podEntry.puIDs) == 0 {
   107  		delete(c.podCache, kubeIdentifier)
   108  	}
   109  
   110  	// delete entry in puidcache
   111  	delete(c.puidCache, puID)
   112  }
   113  
   114  // getOrCreatePodFromCache locks the cache in order to return the pod cache entry if found, or create it if not found
   115  func (c *cache) getPUIDsbyPod(podNamespace string, podName string) []string {
   116  	c.RLock()
   117  	defer c.RUnlock()
   118  
   119  	kubeIdentifier := kubePodIdentifier(podName, podNamespace)
   120  	podEntry, ok := c.podCache[kubeIdentifier]
   121  	if !ok {
   122  		return []string{}
   123  	}
   124  
   125  	return keysFromMap(podEntry.puIDs)
   126  }
   127  
   128  // getRuntimeByPUID locks the cache in order to return the pod cache entry if found, or create it if not found
   129  func (c *cache) getDockerRuntimeByPUID(puid string) policy.RuntimeReader {
   130  	c.RLock()
   131  	defer c.RUnlock()
   132  
   133  	puidEntry, ok := c.puidCache[puid]
   134  	if !ok {
   135  		return nil
   136  	}
   137  
   138  	return puidEntry.dockerRuntime
   139  }
   140  
   141  // getRuntimeByPUID locks the cache in order to return the pod cache entry if found, or create it if not found
   142  func (c *cache) getKubernetesRuntimeByPUID(puid string) policy.RuntimeReader {
   143  	c.RLock()
   144  	defer c.RUnlock()
   145  
   146  	puidEntry, ok := c.puidCache[puid]
   147  	if !ok {
   148  		return nil
   149  	}
   150  
   151  	return puidEntry.kubernetesRuntime
   152  }
   153  
   154  // deletePodEntry locks the cache in order to deletes pod cache entry.
   155  func (c *cache) deletePodEntry(podNamespace string, podName string) {
   156  	c.Lock()
   157  	defer c.Unlock()
   158  
   159  	kubeIdentifier := kubePodIdentifier(podName, podNamespace)
   160  
   161  	delete(c.podCache, kubeIdentifier)
   162  }
   163  
   164  // deletePUID locks the cache in order to delete the puid from puidcache.
   165  func (c *cache) deletePUIDEntry(puid string) {
   166  	c.Lock()
   167  	defer c.Unlock()
   168  
   169  	delete(c.puidCache, puid)
   170  }
   171  
   172  func keysFromMap(m map[string]bool) []string {
   173  	keys := make([]string, len(m))
   174  
   175  	i := 0
   176  	for k := range m {
   177  		keys[i] = k
   178  		i++
   179  	}
   180  
   181  	return keys
   182  }