github.com/cilium/cilium@v1.16.2/pkg/hubble/observer/namespace_manager.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 package observer 5 6 import ( 7 "context" 8 "sort" 9 10 observerpb "github.com/cilium/cilium/api/v1/observer" 11 "github.com/cilium/cilium/pkg/lock" 12 "github.com/cilium/cilium/pkg/time" 13 ) 14 15 var _ NamespaceManager = &namespaceManager{} 16 17 const ( 18 checkNamespaceAgeFrequency = 5 * time.Minute 19 namespaceTTL = time.Hour 20 ) 21 22 type NamespaceManager interface { 23 GetNamespaces() []*observerpb.Namespace 24 AddNamespace(*observerpb.Namespace) 25 } 26 27 type namespaceRecord struct { 28 namespace *observerpb.Namespace 29 added time.Time 30 } 31 32 type namespaceManager struct { 33 mu lock.RWMutex 34 namespaces map[string]namespaceRecord 35 nowFunc func() time.Time 36 } 37 38 func NewNamespaceManager() *namespaceManager { 39 return &namespaceManager{ 40 namespaces: make(map[string]namespaceRecord), 41 nowFunc: time.Now, 42 } 43 } 44 45 func (m *namespaceManager) Run(ctx context.Context) { 46 ticker := time.NewTicker(checkNamespaceAgeFrequency) 47 defer ticker.Stop() 48 for { 49 select { 50 case <-ctx.Done(): 51 return 52 case <-ticker.C: 53 // periodically remove any namespaces which haven't been seen in flows 54 // for the last hour 55 m.cleanupNamespaces() 56 } 57 } 58 } 59 60 func (m *namespaceManager) cleanupNamespaces() { 61 m.mu.Lock() 62 for key, record := range m.namespaces { 63 if record.added.Add(namespaceTTL).Before(m.nowFunc()) { 64 delete(m.namespaces, key) 65 } 66 } 67 m.mu.Unlock() 68 } 69 70 func (m *namespaceManager) GetNamespaces() []*observerpb.Namespace { 71 m.mu.RLock() 72 namespaces := make([]*observerpb.Namespace, 0, len(m.namespaces)) 73 for _, ns := range m.namespaces { 74 namespaces = append(namespaces, ns.namespace) 75 } 76 m.mu.RUnlock() 77 78 sort.Slice(namespaces, func(i, j int) bool { 79 a := namespaces[i] 80 b := namespaces[j] 81 if a.Cluster != b.Cluster { 82 return a.Cluster < b.Cluster 83 } 84 return a.Namespace < b.Namespace 85 }) 86 return namespaces 87 } 88 89 func (m *namespaceManager) AddNamespace(ns *observerpb.Namespace) { 90 m.mu.Lock() 91 defer m.mu.Unlock() 92 93 key := ns.GetCluster() + "/" + ns.GetNamespace() 94 m.namespaces[key] = namespaceRecord{namespace: ns, added: m.nowFunc()} 95 }