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  }