github.com/cilium/cilium@v1.16.2/pkg/hubble/filters/k8s_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  package filters
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  
    10  	flowpb "github.com/cilium/cilium/api/v1/flow"
    11  	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
    12  )
    13  
    14  func TestPodFilter(t *testing.T) {
    15  	type args struct {
    16  		f  []*flowpb.FlowFilter
    17  		ev []*v1.Event
    18  	}
    19  	tests := []struct {
    20  		name    string
    21  		args    args
    22  		wantErr bool
    23  		want    []bool
    24  	}{
    25  		{
    26  			name: "source pod",
    27  			args: args{
    28  				f: []*flowpb.FlowFilter{
    29  					{SourcePod: []string{"xwing", "default/tiefighter"}},
    30  				},
    31  				ev: []*v1.Event{
    32  					{Event: &flowpb.Flow{Source: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"}}},
    33  					{Event: &flowpb.Flow{Source: &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"}}},
    34  					{Event: &flowpb.Flow{Source: &flowpb.Endpoint{Namespace: "kube-system", PodName: "xwing"}}},
    35  					{Event: &flowpb.Flow{Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"}}},
    36  				},
    37  			},
    38  			want: []bool{
    39  				true,
    40  				true,
    41  				false,
    42  				false,
    43  			},
    44  		},
    45  		{
    46  			name: "destination pod",
    47  			args: args{
    48  				f: []*flowpb.FlowFilter{
    49  					{DestinationPod: []string{"xwing", "default/tiefighter"}},
    50  				},
    51  				ev: []*v1.Event{
    52  					{Event: &flowpb.Flow{Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"}}},
    53  					{Event: &flowpb.Flow{Destination: &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"}}},
    54  					{Event: &flowpb.Flow{Destination: &flowpb.Endpoint{Namespace: "kube-system", PodName: "xwing"}}},
    55  					{Event: &flowpb.Flow{Source: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"}}},
    56  				},
    57  			},
    58  			want: []bool{
    59  				true,
    60  				true,
    61  				false,
    62  				false,
    63  			},
    64  		},
    65  		{
    66  			name: "source and destination pod",
    67  			args: args{
    68  				f: []*flowpb.FlowFilter{
    69  					{
    70  						SourcePod:      []string{"xwing", "tiefighter"},
    71  						DestinationPod: []string{"deathstar"},
    72  					},
    73  				},
    74  				ev: []*v1.Event{
    75  					{Event: &flowpb.Flow{
    76  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
    77  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
    78  					}},
    79  					{Event: &flowpb.Flow{
    80  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
    81  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
    82  					}},
    83  					{Event: &flowpb.Flow{
    84  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
    85  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
    86  					}},
    87  					{Event: &flowpb.Flow{
    88  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
    89  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
    90  					}},
    91  				},
    92  			},
    93  			want: []bool{
    94  				true,
    95  				true,
    96  				false,
    97  				false,
    98  			},
    99  		},
   100  		{
   101  			name: "source or destination pod",
   102  			args: args{
   103  				f: []*flowpb.FlowFilter{
   104  					{SourcePod: []string{"xwing"}},
   105  					{DestinationPod: []string{"deathstar"}},
   106  				},
   107  				ev: []*v1.Event{
   108  					{Event: &flowpb.Flow{
   109  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   110  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
   111  					}},
   112  					{Event: &flowpb.Flow{
   113  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   114  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
   115  					}},
   116  					{Event: &flowpb.Flow{
   117  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "deathstar"},
   118  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   119  					}},
   120  					{Event: &flowpb.Flow{
   121  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   122  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   123  					}},
   124  				},
   125  			},
   126  			want: []bool{
   127  				true,
   128  				true,
   129  				false,
   130  				false,
   131  			},
   132  		},
   133  		{
   134  			name: "namespace filter",
   135  			args: args{
   136  				f: []*flowpb.FlowFilter{
   137  					{SourcePod: []string{"kube-system/"}},
   138  					{DestinationPod: []string{"kube-system/"}},
   139  				},
   140  				ev: []*v1.Event{
   141  					{Event: &flowpb.Flow{
   142  						Source:      &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   143  						Destination: &flowpb.Endpoint{Namespace: "kube-system", PodName: "kube-proxy"},
   144  					}},
   145  					{Event: &flowpb.Flow{
   146  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   147  						Destination: &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   148  					}},
   149  					{Event: &flowpb.Flow{
   150  						Source:      &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   151  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   152  					}},
   153  					{Event: &flowpb.Flow{
   154  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   155  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   156  					}},
   157  				},
   158  			},
   159  			want: []bool{
   160  				true,
   161  				true,
   162  				true,
   163  				false,
   164  			},
   165  		},
   166  		{
   167  			name: "prefix filter",
   168  			args: args{
   169  				f: []*flowpb.FlowFilter{
   170  					{SourcePod: []string{"xwing", "kube-system/coredns-"}},
   171  				},
   172  				ev: []*v1.Event{
   173  					{Event: &flowpb.Flow{
   174  						Source: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   175  					}},
   176  					{Event: &flowpb.Flow{
   177  						Source: &flowpb.Endpoint{Namespace: "default", PodName: "xwing-t-65b"},
   178  					}},
   179  					{Event: &flowpb.Flow{
   180  						Source: &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns-12345"},
   181  					}},
   182  					{Event: &flowpb.Flow{
   183  						Source: &flowpb.Endpoint{Namespace: "kube-system", PodName: "-coredns-12345"},
   184  					}},
   185  					{Event: &flowpb.Flow{
   186  						Source: &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   187  					}},
   188  				},
   189  			},
   190  			want: []bool{
   191  				true,
   192  				true,
   193  				true,
   194  				false,
   195  				false,
   196  			},
   197  		},
   198  		{
   199  			name: "invalid data",
   200  			args: args{
   201  				f: []*flowpb.FlowFilter{
   202  					{SourcePod: []string{"xwing"}},
   203  				},
   204  				ev: []*v1.Event{
   205  					nil,
   206  					{},
   207  					{Event: &flowpb.Flow{}},
   208  					{Event: &flowpb.Flow{Source: &flowpb.Endpoint{Namespace: "", PodName: "xwing"}}},
   209  				},
   210  			},
   211  			want: []bool{
   212  				false,
   213  				false,
   214  				false,
   215  				false,
   216  			},
   217  		},
   218  		{
   219  			name: "invalid source pod filter",
   220  			args: args{
   221  				f: []*flowpb.FlowFilter{
   222  					{SourcePod: []string{""}},
   223  				},
   224  			},
   225  			wantErr: true,
   226  		},
   227  		{
   228  			name: "invalid destination pod filter",
   229  			args: args{
   230  				f: []*flowpb.FlowFilter{
   231  					{DestinationPod: []string{""}},
   232  				},
   233  			},
   234  			wantErr: true,
   235  		},
   236  		{
   237  			name: "all namespaces",
   238  			args: args{
   239  				f: []*flowpb.FlowFilter{
   240  					{SourcePod: []string{"/xwing"}},
   241  					{DestinationPod: []string{"/xwing"}},
   242  				},
   243  				ev: []*v1.Event{
   244  					{Event: &flowpb.Flow{
   245  						Source:      &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   246  						Destination: &flowpb.Endpoint{Namespace: "kube-system", PodName: "kube-proxy"},
   247  					}},
   248  					{Event: &flowpb.Flow{
   249  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   250  						Destination: &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   251  					}},
   252  					{Event: &flowpb.Flow{
   253  						Source:      &flowpb.Endpoint{Namespace: "kube-system", PodName: "coredns"},
   254  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   255  					}},
   256  					{Event: &flowpb.Flow{
   257  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   258  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "xwing"},
   259  					}},
   260  					{Event: &flowpb.Flow{
   261  						Source:      &flowpb.Endpoint{Namespace: "hoth", PodName: "tiefighter"},
   262  						Destination: &flowpb.Endpoint{Namespace: "endor", PodName: "xwing"},
   263  					}},
   264  					{Event: &flowpb.Flow{
   265  						Source:      &flowpb.Endpoint{Namespace: "default", PodName: "tiefighter"},
   266  						Destination: &flowpb.Endpoint{Namespace: "default", PodName: "ywing"},
   267  					}},
   268  				},
   269  			},
   270  			want: []bool{
   271  				false,
   272  				false,
   273  				true,
   274  				true,
   275  				true,
   276  				false,
   277  			},
   278  		},
   279  	}
   280  	for _, tt := range tests {
   281  		t.Run(tt.name, func(t *testing.T) {
   282  			fl, err := BuildFilterList(context.Background(), tt.args.f, []OnBuildFilter{&PodFilter{}})
   283  			if (err != nil) != tt.wantErr {
   284  				t.Errorf("BuildFilterList(context.Background(), ) error = %v, wantErr %v", err, tt.wantErr)
   285  				return
   286  			}
   287  			for i, ev := range tt.args.ev {
   288  				if filterResult := fl.MatchOne(ev); filterResult != tt.want[i] {
   289  					t.Errorf("\"%s\" filterResult %d = %v, want %v", tt.name, i, filterResult, tt.want[i])
   290  				}
   291  			}
   292  		})
   293  	}
   294  }
   295  
   296  func TestServiceFilter(t *testing.T) {
   297  	type args struct {
   298  		f  []*flowpb.FlowFilter
   299  		ev []*v1.Event
   300  	}
   301  	tests := []struct {
   302  		name    string
   303  		args    args
   304  		wantErr bool
   305  		want    []bool
   306  	}{
   307  		{
   308  			name: "source service",
   309  			args: args{
   310  				f: []*flowpb.FlowFilter{
   311  					{SourceService: []string{"deathstar", "kube-system/kube-dns"}},
   312  				},
   313  				ev: []*v1.Event{
   314  					{Event: &flowpb.Flow{SourceService: &flowpb.Service{Namespace: "default", Name: "xwing"}}},
   315  					{Event: &flowpb.Flow{SourceService: &flowpb.Service{Namespace: "default", Name: "deathstar"}}},
   316  					{Event: &flowpb.Flow{SourceService: &flowpb.Service{Namespace: "kube-system", Name: "kube-dns"}}},
   317  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "kube-system", Name: "deathstar"}}},
   318  				},
   319  			},
   320  			want: []bool{
   321  				false,
   322  				true,
   323  				true,
   324  				false,
   325  			},
   326  		},
   327  		{
   328  			name: "destination service",
   329  			args: args{
   330  				f: []*flowpb.FlowFilter{
   331  					{DestinationService: []string{"default/", "kube-system/kube-"}},
   332  				},
   333  				ev: []*v1.Event{
   334  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "default", Name: "xwing"}}},
   335  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "default", Name: "deathstar"}}},
   336  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "kube-system", Name: "kube-dns"}}},
   337  					{Event: &flowpb.Flow{SourceService: &flowpb.Service{Namespace: "kube-system", Name: "deathstar"}}},
   338  				},
   339  			},
   340  			want: []bool{
   341  				true,
   342  				true,
   343  				true,
   344  				false,
   345  			},
   346  		},
   347  		{
   348  			name: "any namespace",
   349  			args: args{
   350  				f: []*flowpb.FlowFilter{
   351  					{DestinationService: []string{"/kube-"}},
   352  				},
   353  				ev: []*v1.Event{
   354  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "default", Name: "xwing"}}},
   355  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "default", Name: "deathstar"}}},
   356  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "kube-system", Name: "kube-dns"}}},
   357  					{Event: &flowpb.Flow{SourceService: &flowpb.Service{Namespace: "kube-system", Name: "deathstar"}}},
   358  					{Event: &flowpb.Flow{DestinationService: &flowpb.Service{Namespace: "monitoring", Name: "kube-prometheus"}}},
   359  				},
   360  			},
   361  			want: []bool{
   362  				false,
   363  				false,
   364  				true,
   365  				false,
   366  				true,
   367  			},
   368  		},
   369  	}
   370  	for _, tt := range tests {
   371  		t.Run(tt.name, func(t *testing.T) {
   372  			fl, err := BuildFilterList(context.Background(), tt.args.f, []OnBuildFilter{&ServiceFilter{}})
   373  			if (err != nil) != tt.wantErr {
   374  				t.Errorf("BuildFilterList(context.Background(), ) error = %v, wantErr %v", err, tt.wantErr)
   375  				return
   376  			}
   377  			for i, ev := range tt.args.ev {
   378  				if filterResult := fl.MatchOne(ev); filterResult != tt.want[i] {
   379  					t.Errorf("\"%s\" filterResult %d = %v, want %v", tt.name, i, filterResult, tt.want[i])
   380  				}
   381  			}
   382  		})
   383  	}
   384  }