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