github.com/cilium/cilium@v1.16.2/pkg/hubble/filters/k8s.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 package filters 5 6 import ( 7 "context" 8 "fmt" 9 "strings" 10 11 flowpb "github.com/cilium/cilium/api/v1/flow" 12 v1 "github.com/cilium/cilium/pkg/hubble/api/v1" 13 "github.com/cilium/cilium/pkg/hubble/k8s" 14 ) 15 16 func sourcePod(ev *v1.Event) (ns, pod string) { 17 ep := ev.GetFlow().GetSource() 18 return ep.GetNamespace(), ep.GetPodName() 19 } 20 21 func destinationPod(ev *v1.Event) (ns, pod string) { 22 ep := ev.GetFlow().GetDestination() 23 return ep.GetNamespace(), ep.GetPodName() 24 } 25 26 func sourceService(ev *v1.Event) (ns, svc string) { 27 s := ev.GetFlow().GetSourceService() 28 return s.GetNamespace(), s.GetName() 29 } 30 31 func destinationService(ev *v1.Event) (ns, svc string) { 32 s := ev.GetFlow().GetDestinationService() 33 return s.GetNamespace(), s.GetName() 34 } 35 36 func filterByNamespacedName(names []string, getName func(*v1.Event) (ns, name string)) (FilterFunc, error) { 37 type nameFilter struct{ ns, prefix string } 38 nameFilters := make([]nameFilter, 0, len(names)) 39 for _, name := range names { 40 if name == "" { 41 return nil, fmt.Errorf("invalid filter, name must not be empty") 42 } 43 ns, prefix := k8s.ParseNamespaceName(name) 44 nameFilters = append(nameFilters, nameFilter{ns, prefix}) 45 } 46 47 return func(ev *v1.Event) bool { 48 eventNs, eventName := getName(ev) 49 if eventNs == "" && eventName == "" { 50 return false 51 } 52 53 for _, f := range nameFilters { 54 if (f.prefix == "" || strings.HasPrefix(eventName, f.prefix)) && (f.ns == "" || f.ns == eventNs) { 55 return true 56 } 57 } 58 59 return false 60 }, nil 61 } 62 63 // PodFilter implements filtering based on Kubernetes pod names 64 type PodFilter struct{} 65 66 // OnBuildFilter builds a Kubernetes pod name filter 67 func (p *PodFilter) OnBuildFilter(ctx context.Context, ff *flowpb.FlowFilter) ([]FilterFunc, error) { 68 var fs []FilterFunc 69 70 if ff.GetSourcePod() != nil { 71 pf, err := filterByNamespacedName(ff.GetSourcePod(), sourcePod) 72 if err != nil { 73 return nil, err 74 } 75 fs = append(fs, pf) 76 } 77 78 if ff.GetDestinationPod() != nil { 79 pf, err := filterByNamespacedName(ff.GetDestinationPod(), destinationPod) 80 if err != nil { 81 return nil, err 82 } 83 fs = append(fs, pf) 84 } 85 86 return fs, nil 87 } 88 89 // ServiceFilter implements filtering based on Kubernetes service names 90 type ServiceFilter struct{} 91 92 // OnBuildFilter builds a Kubernetes service name filter 93 func (s *ServiceFilter) OnBuildFilter(ctx context.Context, ff *flowpb.FlowFilter) ([]FilterFunc, error) { 94 var fs []FilterFunc 95 96 if ff.GetSourceService() != nil { 97 ssf, err := filterByNamespacedName(ff.GetSourceService(), sourceService) 98 if err != nil { 99 return nil, fmt.Errorf("invalid source service filter: %w", err) 100 } 101 fs = append(fs, ssf) 102 } 103 104 if ff.GetDestinationService() != nil { 105 dsf, err := filterByNamespacedName(ff.GetDestinationService(), destinationService) 106 if err != nil { 107 return nil, fmt.Errorf("invalid destination service filter: %w", err) 108 } 109 fs = append(fs, dsf) 110 } 111 112 return fs, nil 113 }