k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/cmd/kube-proxy/app/server_linux_test.go (about) 1 //go:build linux 2 // +build linux 3 4 /* 5 Copyright 2018 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package app 21 22 import ( 23 "fmt" 24 "net" 25 "os" 26 "path/filepath" 27 "reflect" 28 goruntime "runtime" 29 "strings" 30 "testing" 31 "time" 32 33 "github.com/spf13/pflag" 34 35 v1 "k8s.io/api/core/v1" 36 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 37 "k8s.io/apimachinery/pkg/runtime" 38 "k8s.io/apimachinery/pkg/watch" 39 clientsetfake "k8s.io/client-go/kubernetes/fake" 40 clientgotesting "k8s.io/client-go/testing" 41 proxyconfigapi "k8s.io/kubernetes/pkg/proxy/apis/config" 42 proxyutil "k8s.io/kubernetes/pkg/proxy/util" 43 "k8s.io/kubernetes/test/utils/ktesting" 44 netutils "k8s.io/utils/net" 45 "k8s.io/utils/ptr" 46 ) 47 48 func Test_platformApplyDefaults(t *testing.T) { 49 testCases := []struct { 50 name string 51 mode proxyconfigapi.ProxyMode 52 expectedMode proxyconfigapi.ProxyMode 53 detectLocal proxyconfigapi.LocalMode 54 expectedDetectLocal proxyconfigapi.LocalMode 55 }{ 56 { 57 name: "defaults", 58 mode: "", 59 expectedMode: proxyconfigapi.ProxyModeIPTables, 60 detectLocal: "", 61 expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, 62 }, 63 { 64 name: "explicit", 65 mode: proxyconfigapi.ProxyModeIPTables, 66 expectedMode: proxyconfigapi.ProxyModeIPTables, 67 detectLocal: proxyconfigapi.LocalModeClusterCIDR, 68 expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, 69 }, 70 { 71 name: "override mode", 72 mode: "ipvs", 73 expectedMode: proxyconfigapi.ProxyModeIPVS, 74 detectLocal: "", 75 expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, 76 }, 77 { 78 name: "override detect-local", 79 mode: "", 80 expectedMode: proxyconfigapi.ProxyModeIPTables, 81 detectLocal: "NodeCIDR", 82 expectedDetectLocal: proxyconfigapi.LocalModeNodeCIDR, 83 }, 84 { 85 name: "override both", 86 mode: "ipvs", 87 expectedMode: proxyconfigapi.ProxyModeIPVS, 88 detectLocal: "NodeCIDR", 89 expectedDetectLocal: proxyconfigapi.LocalModeNodeCIDR, 90 }, 91 } 92 for _, tc := range testCases { 93 t.Run(tc.name, func(t *testing.T) { 94 options := NewOptions() 95 config := &proxyconfigapi.KubeProxyConfiguration{ 96 Mode: tc.mode, 97 DetectLocalMode: tc.detectLocal, 98 } 99 100 options.platformApplyDefaults(config) 101 if config.Mode != tc.expectedMode { 102 t.Fatalf("expected mode: %s, but got: %s", tc.expectedMode, config.Mode) 103 } 104 if config.DetectLocalMode != tc.expectedDetectLocal { 105 t.Fatalf("expected detect-local: %s, but got: %s", tc.expectedDetectLocal, config.DetectLocalMode) 106 } 107 }) 108 } 109 } 110 111 func Test_getLocalDetectors(t *testing.T) { 112 cases := []struct { 113 name string 114 config *proxyconfigapi.KubeProxyConfiguration 115 primaryIPFamily v1.IPFamily 116 nodePodCIDRs []string 117 expected map[v1.IPFamily]proxyutil.LocalTrafficDetector 118 }{ 119 // LocalModeClusterCIDR 120 { 121 name: "LocalModeClusterCIDR, single-stack IPv4 cluster", 122 config: &proxyconfigapi.KubeProxyConfiguration{ 123 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 124 ClusterCIDR: "10.0.0.0/14", 125 }, 126 primaryIPFamily: v1.IPv4Protocol, 127 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 128 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), 129 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 130 }, 131 }, 132 { 133 name: "LocalModeClusterCIDR, single-stack IPv6 cluster", 134 config: &proxyconfigapi.KubeProxyConfiguration{ 135 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 136 ClusterCIDR: "2002:0:0:1234::/64", 137 }, 138 primaryIPFamily: v1.IPv6Protocol, 139 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 140 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 141 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), 142 }, 143 }, 144 { 145 name: "LocalModeClusterCIDR, single-stack IPv6 cluster with single-stack IPv4 config", 146 config: &proxyconfigapi.KubeProxyConfiguration{ 147 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 148 ClusterCIDR: "10.0.0.0/14", 149 }, 150 primaryIPFamily: v1.IPv6Protocol, 151 // This will output a warning that there is no IPv6 CIDR but it 152 // will still use the provided IPv4 CIDR for IPv4. 153 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 154 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), 155 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 156 }, 157 }, 158 { 159 name: "LocalModeClusterCIDR, single-stack IPv4 cluster with single-stack IPv6 config", 160 config: &proxyconfigapi.KubeProxyConfiguration{ 161 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 162 ClusterCIDR: "2002:0:0:1234::/64", 163 }, 164 primaryIPFamily: v1.IPv4Protocol, 165 // This will output a warning that there is no IPv4 CIDR but it 166 // will still use the provided IPv6 CIDR for IPv6. 167 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 168 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 169 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), 170 }, 171 }, 172 { 173 name: "LocalModeClusterCIDR, dual-stack IPv4-primary cluster", 174 config: &proxyconfigapi.KubeProxyConfiguration{ 175 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 176 ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", 177 }, 178 primaryIPFamily: v1.IPv4Protocol, 179 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 180 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), 181 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), 182 }, 183 }, 184 { 185 name: "LocalModeClusterCIDR, dual-stack IPv6-primary cluster", 186 config: &proxyconfigapi.KubeProxyConfiguration{ 187 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 188 ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", 189 }, 190 primaryIPFamily: v1.IPv6Protocol, 191 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 192 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), 193 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), 194 }, 195 }, 196 { 197 name: "LocalModeClusterCIDR, IPv4-primary kube-proxy / IPv6-primary config", 198 config: &proxyconfigapi.KubeProxyConfiguration{ 199 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 200 ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", 201 }, 202 primaryIPFamily: v1.IPv4Protocol, 203 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 204 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"), 205 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"), 206 }, 207 }, 208 { 209 name: "LocalModeClusterCIDR, no ClusterCIDR", 210 config: &proxyconfigapi.KubeProxyConfiguration{ 211 DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR, 212 ClusterCIDR: "", 213 }, 214 primaryIPFamily: v1.IPv4Protocol, 215 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 216 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 217 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 218 }, 219 }, 220 // LocalModeNodeCIDR 221 { 222 name: "LocalModeNodeCIDR, single-stack IPv4 cluster", 223 config: &proxyconfigapi.KubeProxyConfiguration{ 224 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 225 ClusterCIDR: "10.0.0.0/14", 226 }, 227 primaryIPFamily: v1.IPv4Protocol, 228 nodePodCIDRs: []string{"10.0.0.0/24"}, 229 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 230 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), 231 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 232 }, 233 }, 234 { 235 name: "LocalModeNodeCIDR, single-stack IPv6 cluster", 236 config: &proxyconfigapi.KubeProxyConfiguration{ 237 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 238 ClusterCIDR: "2002:0:0:1234::/64", 239 }, 240 primaryIPFamily: v1.IPv6Protocol, 241 nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, 242 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 243 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 244 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), 245 }, 246 }, 247 { 248 name: "LocalModeNodeCIDR, single-stack IPv6 cluster with single-stack IPv4 config", 249 config: &proxyconfigapi.KubeProxyConfiguration{ 250 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 251 ClusterCIDR: "10.0.0.0/14", 252 }, 253 primaryIPFamily: v1.IPv6Protocol, 254 nodePodCIDRs: []string{"10.0.0.0/24"}, 255 // This will output a warning that there is no IPv6 CIDR but it 256 // will still use the provided IPv4 CIDR for IPv4. 257 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 258 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), 259 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 260 }, 261 }, 262 { 263 name: "LocalModeNodeCIDR, single-stack IPv4 cluster with single-stack IPv6 config", 264 config: &proxyconfigapi.KubeProxyConfiguration{ 265 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 266 ClusterCIDR: "2002:0:0:1234::/64", 267 }, 268 primaryIPFamily: v1.IPv4Protocol, 269 nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"}, 270 // This will output a warning that there is no IPv4 CIDR but it 271 // will still use the provided IPv6 CIDR for IPv6. 272 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 273 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 274 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), 275 }, 276 }, 277 { 278 name: "LocalModeNodeCIDR, dual-stack IPv4-primary cluster", 279 config: &proxyconfigapi.KubeProxyConfiguration{ 280 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 281 ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", 282 }, 283 primaryIPFamily: v1.IPv4Protocol, 284 nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, 285 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 286 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), 287 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), 288 }, 289 }, 290 { 291 name: "LocalModeNodeCIDR, dual-stack IPv6-primary cluster", 292 config: &proxyconfigapi.KubeProxyConfiguration{ 293 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 294 ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14", 295 }, 296 primaryIPFamily: v1.IPv6Protocol, 297 nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96", "10.0.0.0/24"}, 298 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 299 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), 300 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), 301 }, 302 }, 303 { 304 name: "LocalModeNodeCIDR, IPv6-primary kube-proxy / IPv4-primary config", 305 config: &proxyconfigapi.KubeProxyConfiguration{ 306 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 307 ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64", 308 }, 309 primaryIPFamily: v1.IPv6Protocol, 310 nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"}, 311 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 312 v1.IPv4Protocol: proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"), 313 v1.IPv6Protocol: proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"), 314 }, 315 }, 316 { 317 name: "LocalModeNodeCIDR, no PodCIDRs", 318 config: &proxyconfigapi.KubeProxyConfiguration{ 319 DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR, 320 ClusterCIDR: "", 321 }, 322 primaryIPFamily: v1.IPv4Protocol, 323 nodePodCIDRs: []string{}, 324 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 325 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 326 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 327 }, 328 }, 329 // unknown mode 330 { 331 name: "unknown LocalMode", 332 config: &proxyconfigapi.KubeProxyConfiguration{ 333 DetectLocalMode: proxyconfigapi.LocalMode("abcd"), 334 ClusterCIDR: "10.0.0.0/14", 335 }, 336 primaryIPFamily: v1.IPv4Protocol, 337 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 338 v1.IPv4Protocol: proxyutil.NewNoOpLocalDetector(), 339 v1.IPv6Protocol: proxyutil.NewNoOpLocalDetector(), 340 }, 341 }, 342 // LocalModeBridgeInterface 343 { 344 name: "LocalModeBridgeInterface", 345 config: &proxyconfigapi.KubeProxyConfiguration{ 346 DetectLocalMode: proxyconfigapi.LocalModeBridgeInterface, 347 DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, 348 }, 349 primaryIPFamily: v1.IPv4Protocol, 350 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 351 v1.IPv4Protocol: proxyutil.NewDetectLocalByBridgeInterface("eth"), 352 v1.IPv6Protocol: proxyutil.NewDetectLocalByBridgeInterface("eth"), 353 }, 354 }, 355 { 356 name: "LocalModeBridgeInterface, strange bridge name", 357 config: &proxyconfigapi.KubeProxyConfiguration{ 358 DetectLocalMode: proxyconfigapi.LocalModeBridgeInterface, 359 DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "1234567890123456789"}, 360 }, 361 primaryIPFamily: v1.IPv4Protocol, 362 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 363 v1.IPv4Protocol: proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789"), 364 v1.IPv6Protocol: proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789"), 365 }, 366 }, 367 // LocalModeInterfaceNamePrefix 368 { 369 name: "LocalModeInterfaceNamePrefix", 370 config: &proxyconfigapi.KubeProxyConfiguration{ 371 DetectLocalMode: proxyconfigapi.LocalModeInterfaceNamePrefix, 372 DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"}, 373 }, 374 primaryIPFamily: v1.IPv4Protocol, 375 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 376 v1.IPv4Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("eth"), 377 v1.IPv6Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("eth"), 378 }, 379 }, 380 { 381 name: "LocalModeInterfaceNamePrefix, strange interface name", 382 config: &proxyconfigapi.KubeProxyConfiguration{ 383 DetectLocalMode: proxyconfigapi.LocalModeInterfaceNamePrefix, 384 DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "1234567890123456789"}, 385 }, 386 primaryIPFamily: v1.IPv4Protocol, 387 expected: map[v1.IPFamily]proxyutil.LocalTrafficDetector{ 388 v1.IPv4Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789"), 389 v1.IPv6Protocol: proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789"), 390 }, 391 }, 392 } 393 for _, c := range cases { 394 t.Run(c.name, func(t *testing.T) { 395 logger, _ := ktesting.NewTestContext(t) 396 r := getLocalDetectors(logger, c.primaryIPFamily, c.config, c.nodePodCIDRs) 397 if !reflect.DeepEqual(r, c.expected) { 398 t.Errorf("Unexpected detect-local implementation, expected: %q, got: %q", c.expected, r) 399 } 400 }) 401 } 402 } 403 404 func makeNodeWithPodCIDRs(cidrs ...string) *v1.Node { 405 if len(cidrs) == 0 { 406 return &v1.Node{} 407 } 408 return &v1.Node{ 409 Spec: v1.NodeSpec{ 410 PodCIDR: cidrs[0], 411 PodCIDRs: cidrs, 412 }, 413 } 414 } 415 416 func TestConfigChange(t *testing.T) { 417 setUp := func() (*os.File, string, error) { 418 tempDir, err := os.MkdirTemp("", "kubeproxy-config-change") 419 if err != nil { 420 return nil, "", fmt.Errorf("unable to create temporary directory: %v", err) 421 } 422 fullPath := filepath.Join(tempDir, "kube-proxy-config") 423 file, err := os.Create(fullPath) 424 if err != nil { 425 return nil, "", fmt.Errorf("unexpected error when creating temp file: %v", err) 426 } 427 428 _, err = file.WriteString(`apiVersion: kubeproxy.config.k8s.io/v1alpha1 429 bindAddress: 0.0.0.0 430 bindAddressHardFail: false 431 clientConnection: 432 acceptContentTypes: "" 433 burst: 10 434 contentType: application/vnd.kubernetes.protobuf 435 kubeconfig: /var/lib/kube-proxy/kubeconfig.conf 436 qps: 5 437 clusterCIDR: 10.244.0.0/16 438 configSyncPeriod: 15m0s 439 conntrack: 440 maxPerCore: 32768 441 min: 131072 442 tcpCloseWaitTimeout: 1h0m0s 443 tcpEstablishedTimeout: 24h0m0s 444 enableProfiling: false 445 healthzBindAddress: 0.0.0.0:10256 446 hostnameOverride: "" 447 iptables: 448 masqueradeAll: false 449 masqueradeBit: 14 450 minSyncPeriod: 0s 451 syncPeriod: 30s 452 ipvs: 453 excludeCIDRs: null 454 minSyncPeriod: 0s 455 scheduler: "" 456 syncPeriod: 30s 457 kind: KubeProxyConfiguration 458 metricsBindAddress: 127.0.0.1:10249 459 mode: "" 460 nodePortAddresses: null 461 oomScoreAdj: -999 462 portRange: "" 463 detectLocalMode: "BridgeInterface"`) 464 if err != nil { 465 return nil, "", fmt.Errorf("unexpected error when writing content to temp kube-proxy config file: %v", err) 466 } 467 468 return file, tempDir, nil 469 } 470 471 tearDown := func(file *os.File, tempDir string) { 472 file.Close() 473 os.RemoveAll(tempDir) 474 } 475 476 testCases := []struct { 477 name string 478 proxyServer proxyRun 479 append bool 480 expectedErr string 481 }{ 482 { 483 name: "update config file", 484 proxyServer: new(fakeProxyServerLongRun), 485 append: true, 486 expectedErr: "content of the proxy server's configuration file was updated", 487 }, 488 { 489 name: "fake error", 490 proxyServer: new(fakeProxyServerError), 491 expectedErr: "mocking error from ProxyServer.Run()", 492 }, 493 } 494 495 for _, tc := range testCases { 496 _, ctx := ktesting.NewTestContext(t) 497 file, tempDir, err := setUp() 498 if err != nil { 499 t.Fatalf("unexpected error when setting up environment: %v", err) 500 } 501 502 opt := NewOptions() 503 opt.ConfigFile = file.Name() 504 err = opt.Complete(new(pflag.FlagSet)) 505 if err != nil { 506 t.Fatal(err) 507 } 508 opt.proxyServer = tc.proxyServer 509 510 errCh := make(chan error, 1) 511 go func() { 512 errCh <- opt.runLoop(ctx) 513 }() 514 515 if tc.append { 516 file.WriteString("append fake content") 517 } 518 519 select { 520 case err := <-errCh: 521 if err != nil { 522 if !strings.Contains(err.Error(), tc.expectedErr) { 523 t.Errorf("[%s] Expected error containing %v, got %v", tc.name, tc.expectedErr, err) 524 } 525 } 526 case <-time.After(10 * time.Second): 527 t.Errorf("[%s] Timeout: unable to get any events or internal timeout.", tc.name) 528 } 529 tearDown(file, tempDir) 530 } 531 } 532 533 func Test_waitForPodCIDR(t *testing.T) { 534 _, ctx := ktesting.NewTestContext(t) 535 expected := []string{"192.168.0.0/24", "fd00:1:2::/64"} 536 nodeName := "test-node" 537 oldNode := &v1.Node{ 538 ObjectMeta: metav1.ObjectMeta{ 539 Name: nodeName, 540 ResourceVersion: "1000", 541 }, 542 Spec: v1.NodeSpec{ 543 PodCIDR: "10.0.0.0/24", 544 PodCIDRs: []string{"10.0.0.0/24", "2001:db2:1/64"}, 545 }, 546 } 547 node := &v1.Node{ 548 ObjectMeta: metav1.ObjectMeta{ 549 Name: nodeName, 550 ResourceVersion: "1", 551 }, 552 } 553 updatedNode := node.DeepCopy() 554 updatedNode.Spec.PodCIDRs = expected 555 updatedNode.Spec.PodCIDR = expected[0] 556 557 // start with the new node 558 client := clientsetfake.NewSimpleClientset() 559 client.AddReactor("list", "nodes", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { 560 obj := &v1.NodeList{} 561 return true, obj, nil 562 }) 563 fakeWatch := watch.NewFake() 564 client.PrependWatchReactor("nodes", clientgotesting.DefaultWatchReactor(fakeWatch, nil)) 565 566 go func() { 567 fakeWatch.Add(node) 568 // receive a delete event for the old node 569 fakeWatch.Delete(oldNode) 570 // set the PodCIDRs on the new node 571 fakeWatch.Modify(updatedNode) 572 }() 573 got, err := waitForPodCIDR(ctx, client, node.Name) 574 if err != nil { 575 t.Errorf("waitForPodCIDR() unexpected error %v", err) 576 return 577 } 578 if !reflect.DeepEqual(got.Spec.PodCIDRs, expected) { 579 t.Errorf("waitForPodCIDR() got %v expected to be %v ", got.Spec.PodCIDRs, expected) 580 } 581 } 582 583 func TestGetConntrackMax(t *testing.T) { 584 ncores := goruntime.NumCPU() 585 testCases := []struct { 586 min int32 587 maxPerCore int32 588 expected int 589 err string 590 }{ 591 { 592 expected: 0, 593 }, 594 { 595 maxPerCore: 67890, // use this if Max is 0 596 min: 1, // avoid 0 default 597 expected: 67890 * ncores, 598 }, 599 { 600 maxPerCore: 1, // ensure that Min is considered 601 min: 123456, 602 expected: 123456, 603 }, 604 { 605 maxPerCore: 0, // leave system setting 606 min: 123456, 607 expected: 0, 608 }, 609 } 610 611 for i, tc := range testCases { 612 cfg := proxyconfigapi.KubeProxyConntrackConfiguration{ 613 Min: ptr.To(tc.min), 614 MaxPerCore: ptr.To(tc.maxPerCore), 615 } 616 _, ctx := ktesting.NewTestContext(t) 617 x, e := getConntrackMax(ctx, cfg) 618 if e != nil { 619 if tc.err == "" { 620 t.Errorf("[%d] unexpected error: %v", i, e) 621 } else if !strings.Contains(e.Error(), tc.err) { 622 t.Errorf("[%d] expected an error containing %q: %v", i, tc.err, e) 623 } 624 } else if x != tc.expected { 625 t.Errorf("[%d] expected %d, got %d", i, tc.expected, x) 626 } 627 } 628 } 629 630 func TestProxyServer_platformSetup(t *testing.T) { 631 tests := []struct { 632 name string 633 node *v1.Node 634 config *proxyconfigapi.KubeProxyConfiguration 635 wantPodCIDRs []string 636 }{ 637 { 638 name: "LocalModeNodeCIDR store the node PodCIDRs obtained", 639 node: makeNodeWithPodCIDRs("10.0.0.0/24"), 640 config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR}, 641 wantPodCIDRs: []string{"10.0.0.0/24"}, 642 }, 643 { 644 name: "LocalModeNodeCIDR store the node PodCIDRs obtained dual stack", 645 node: makeNodeWithPodCIDRs("10.0.0.0/24", "2001:db2:1/64"), 646 config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR}, 647 wantPodCIDRs: []string{"10.0.0.0/24", "2001:db2:1/64"}, 648 }, 649 { 650 name: "LocalModeClusterCIDR does not get the node PodCIDRs", 651 node: makeNodeWithPodCIDRs("10.0.0.0/24", "2001:db2:1/64"), 652 config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR}, 653 }, 654 } 655 for _, tt := range tests { 656 t.Run(tt.name, func(t *testing.T) { 657 _, ctx := ktesting.NewTestContext(t) 658 client := clientsetfake.NewSimpleClientset(tt.node) 659 s := &ProxyServer{ 660 Config: tt.config, 661 Client: client, 662 Hostname: "nodename", 663 NodeIPs: map[v1.IPFamily]net.IP{ 664 v1.IPv4Protocol: netutils.ParseIPSloppy("127.0.0.1"), 665 v1.IPv6Protocol: net.IPv6zero, 666 }, 667 } 668 err := s.platformSetup(ctx) 669 if err != nil { 670 t.Errorf("ProxyServer.createProxier() error = %v", err) 671 return 672 } 673 if !reflect.DeepEqual(s.podCIDRs, tt.wantPodCIDRs) { 674 t.Errorf("Expected PodCIDRs %v got %v", tt.wantPodCIDRs, s.podCIDRs) 675 } 676 677 }) 678 } 679 }