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  }