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 }