//go:build linux // +build linux /* Copyright 2018 The Kubernetes Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package app import ( "fmt" "net" "os" "path/filepath" "reflect" goruntime "runtime" "strings" "testing" "time" "github.com/spf13/pflag" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" clientsetfake "k8s.io/client-go/kubernetes/fake" clientgotesting "k8s.io/client-go/testing" proxyconfigapi "k8s.io/kubernetes/pkg/proxy/apis/config" proxyutiliptables "k8s.io/kubernetes/pkg/proxy/util/iptables" netutils "k8s.io/utils/net" "k8s.io/utils/ptr" ) func Test_platformApplyDefaults(t *testing.T) { testCases := []struct { name string mode proxyconfigapi.ProxyMode expectedMode proxyconfigapi.ProxyMode detectLocal proxyconfigapi.LocalMode expectedDetectLocal proxyconfigapi.LocalMode }{ { name: "defaults", mode: "", expectedMode: proxyconfigapi.ProxyModeIPTables, detectLocal: "", expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, }, { name: "explicit", mode: proxyconfigapi.ProxyModeIPTables, expectedMode: proxyconfigapi.ProxyModeIPTables, detectLocal: proxyconfigapi.LocalModeClusterCIDR, expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, }, { name: "override mode", mode: "ipvs", expectedMode: proxyconfigapi.ProxyModeIPVS, detectLocal: "", expectedDetectLocal: proxyconfigapi.LocalModeClusterCIDR, }, { name: "override detect-local", mode: "", expectedMode: proxyconfigapi.ProxyModeIPTables, detectLocal: "NodeCIDR", expectedDetectLocal: proxyconfigapi.LocalModeNodeCIDR, }, { name: "override both", mode: "ipvs", expectedMode: proxyconfigapi.ProxyModeIPVS, detectLocal: "NodeCIDR", expectedDetectLocal: proxyconfigapi.LocalModeNodeCIDR, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { options := NewOptions() config := &proxyconfigapi.KubeProxyConfiguration{ Mode: tc.mode, DetectLocalMode: tc.detectLocal, } options.platformApplyDefaults(config) if config.Mode != tc.expectedMode { t.Fatalf("expected mode: %s, but got: %s", tc.expectedMode, config.Mode) } if config.DetectLocalMode != tc.expectedDetectLocal { t.Fatalf("expected detect-local: %s, but got: %s", tc.expectedDetectLocal, config.DetectLocalMode) } }) } } func Test_getLocalDetector(t *testing.T) { cases := []struct { name string mode proxyconfigapi.LocalMode config *proxyconfigapi.KubeProxyConfiguration family v1.IPFamily expected proxyutiliptables.LocalTrafficDetector nodePodCIDRs []string errExpected bool }{ // LocalModeClusterCIDR { name: "LocalModeClusterCIDR, IPv4 cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/14")), errExpected: false, }, { name: "LocalModeClusterCIDR, IPv6 cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, family: v1.IPv6Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/64")), errExpected: false, }, { name: "LocalModeClusterCIDR, IPv6 cluster with IPv6 config", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, family: v1.IPv6Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), errExpected: false, }, { name: "LocalModeClusterCIDR, IPv4 cluster with IPv6 config", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, family: v1.IPv4Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), errExpected: false, }, { name: "LocalModeClusterCIDR, IPv4 kube-proxy in dual-stack IPv6-primary cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64,10.0.0.0/14"}, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/14")), errExpected: false, }, { name: "LocalModeClusterCIDR, no ClusterCIDR", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, family: v1.IPv4Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), errExpected: false, }, // LocalModeNodeCIDR { name: "LocalModeNodeCIDR, IPv4 cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/24")), nodePodCIDRs: []string{"10.0.0.0/24"}, errExpected: false, }, { name: "LocalModeNodeCIDR, IPv6 cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, family: v1.IPv6Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/96")), nodePodCIDRs: []string{"2002::1234:abcd:ffff:c0a8:101/96"}, errExpected: false, }, { name: "LocalModeNodeCIDR, IPv6 cluster with IPv4 config", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, family: v1.IPv6Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), nodePodCIDRs: []string{"10.0.0.0/24"}, errExpected: false, }, { name: "LocalModeNodeCIDR, IPv4 cluster with IPv6 config", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, family: v1.IPv4Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), nodePodCIDRs: []string{"2002::1234:abcd:ffff:c0a8:101/96"}, errExpected: false, }, { name: "LocalModeNodeCIDR, IPv6 kube-proxy in dual-stack IPv4-primary cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002::1234:abcd:ffff:c0a8:101/64"}, family: v1.IPv6Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/96")), nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:c0a8:101/96"}, errExpected: false, }, { name: "LocalModeNodeCIDR, no PodCIDRs", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, family: v1.IPv4Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), nodePodCIDRs: []string{}, errExpected: false, }, // unknown mode { name: "unknown LocalMode", mode: proxyconfigapi.LocalMode("abcd"), config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, family: v1.IPv4Protocol, expected: proxyutiliptables.NewNoOpLocalDetector(), errExpected: false, }, // LocalModeBridgeInterface { name: "LocalModeBrideInterface", mode: proxyconfigapi.LocalModeBridgeInterface, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, }, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByBridgeInterface("eth")), errExpected: false, }, { name: "LocalModeBridgeInterface, strange bridge name", mode: proxyconfigapi.LocalModeBridgeInterface, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "1234567890123456789"}, }, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByBridgeInterface("1234567890123456789")), errExpected: false, }, // LocalModeInterfaceNamePrefix { name: "LocalModeInterfaceNamePrefix", mode: proxyconfigapi.LocalModeInterfaceNamePrefix, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"}, }, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("eth")), errExpected: false, }, { name: "LocalModeInterfaceNamePrefix, strange interface name", mode: proxyconfigapi.LocalModeInterfaceNamePrefix, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "1234567890123456789"}, }, family: v1.IPv4Protocol, expected: resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("1234567890123456789")), errExpected: false, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { r, err := getLocalDetector(c.family, c.mode, c.config, c.nodePodCIDRs) if c.errExpected { if err == nil { t.Errorf("Expected error, but succeeded with %v", r) } return } if err != nil { t.Errorf("Error resolving detect-local: %v", err) return } if !reflect.DeepEqual(r, c.expected) { t.Errorf("Unexpected detect-local implementation, expected: %q, got: %q", c.expected, r) } }) } } func Test_getDualStackLocalDetectorTuple(t *testing.T) { cases := []struct { name string mode proxyconfigapi.LocalMode config *proxyconfigapi.KubeProxyConfiguration expected [2]proxyutiliptables.LocalTrafficDetector nodePodCIDRs []string errExpected bool }{ // LocalModeClusterCIDR { name: "LocalModeClusterCIDR, dual-stack IPv4-primary cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002::1234:abcd:ffff:c0a8:101/64"}, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/14"))( proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/64")), errExpected: false, }, { name: "LocalModeClusterCIDR, dual-stack IPv6-primary cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64,10.0.0.0/14"}, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/14"))( proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/64")), errExpected: false, }, { name: "LocalModeClusterCIDR, single-stack IPv4 cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, expected: [2]proxyutiliptables.LocalTrafficDetector{ resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/14")), proxyutiliptables.NewNoOpLocalDetector()}, errExpected: false, }, { name: "LocalModeClusterCIDR, single-stack IPv6 cluster", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, expected: [2]proxyutiliptables.LocalTrafficDetector{ proxyutiliptables.NewNoOpLocalDetector(), resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/64"))}, errExpected: false, }, { name: "LocalModeClusterCIDR, no ClusterCIDR", mode: proxyconfigapi.LocalModeClusterCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, expected: [2]proxyutiliptables.LocalTrafficDetector{proxyutiliptables.NewNoOpLocalDetector(), proxyutiliptables.NewNoOpLocalDetector()}, errExpected: false, }, // LocalModeNodeCIDR { name: "LocalModeNodeCIDR, dual-stack IPv4-primary cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002::1234:abcd:ffff:c0a8:101/64"}, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/24"))( proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/96")), nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:c0a8:101/96"}, errExpected: false, }, { name: "LocalModeNodeCIDR, dual-stack IPv6-primary cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64,10.0.0.0/14"}, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/24"))( proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/96")), nodePodCIDRs: []string{"2002::1234:abcd:ffff:c0a8:101/96", "10.0.0.0/24"}, errExpected: false, }, { name: "LocalModeNodeCIDR, single-stack IPv4 cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"}, expected: [2]proxyutiliptables.LocalTrafficDetector{ resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("10.0.0.0/24")), proxyutiliptables.NewNoOpLocalDetector()}, nodePodCIDRs: []string{"10.0.0.0/24"}, errExpected: false, }, { name: "LocalModeNodeCIDR, single-stack IPv6 cluster", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002::1234:abcd:ffff:c0a8:101/64"}, expected: [2]proxyutiliptables.LocalTrafficDetector{ proxyutiliptables.NewNoOpLocalDetector(), resolveLocalDetector(t)(proxyutiliptables.NewDetectLocalByCIDR("2002::1234:abcd:ffff:c0a8:101/96"))}, nodePodCIDRs: []string{"2002::1234:abcd:ffff:c0a8:101/96"}, errExpected: false, }, { name: "LocalModeNodeCIDR, no PodCIDRs", mode: proxyconfigapi.LocalModeNodeCIDR, config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""}, expected: [2]proxyutiliptables.LocalTrafficDetector{proxyutiliptables.NewNoOpLocalDetector(), proxyutiliptables.NewNoOpLocalDetector()}, nodePodCIDRs: []string{}, errExpected: false, }, // LocalModeBridgeInterface { name: "LocalModeBridgeInterface", mode: proxyconfigapi.LocalModeBridgeInterface, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"}, }, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByBridgeInterface("eth"))( proxyutiliptables.NewDetectLocalByBridgeInterface("eth")), errExpected: false, }, // LocalModeInterfaceNamePrefix { name: "LocalModeInterfaceNamePrefix", mode: proxyconfigapi.LocalModeInterfaceNamePrefix, config: &proxyconfigapi.KubeProxyConfiguration{ DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "veth"}, }, expected: resolveDualStackLocalDetectors(t)( proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("veth"))( proxyutiliptables.NewDetectLocalByInterfaceNamePrefix("veth")), errExpected: false, }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { r, err := getDualStackLocalDetectorTuple(c.mode, c.config, c.nodePodCIDRs) if c.errExpected { if err == nil { t.Errorf("Expected error, but succeeded with %q", r) } return } if err != nil { t.Errorf("Error resolving detect-local: %v", err) return } if !reflect.DeepEqual(r, c.expected) { t.Errorf("Unexpected detect-local implementation, expected: %q, got: %q", c.expected, r) } }) } } func makeNodeWithPodCIDRs(cidrs ...string) *v1.Node { if len(cidrs) == 0 { return &v1.Node{} } return &v1.Node{ Spec: v1.NodeSpec{ PodCIDR: cidrs[0], PodCIDRs: cidrs, }, } } func resolveLocalDetector(t *testing.T) func(proxyutiliptables.LocalTrafficDetector, error) proxyutiliptables.LocalTrafficDetector { return func(localDetector proxyutiliptables.LocalTrafficDetector, err error) proxyutiliptables.LocalTrafficDetector { t.Helper() if err != nil { t.Fatalf("Error resolving detect-local: %v", err) } return localDetector } } func resolveDualStackLocalDetectors(t *testing.T) func(localDetector proxyutiliptables.LocalTrafficDetector, err1 error) func(proxyutiliptables.LocalTrafficDetector, error) [2]proxyutiliptables.LocalTrafficDetector { return func(localDetector proxyutiliptables.LocalTrafficDetector, err error) func(proxyutiliptables.LocalTrafficDetector, error) [2]proxyutiliptables.LocalTrafficDetector { t.Helper() if err != nil { t.Fatalf("Error resolving dual stack detect-local: %v", err) } return func(otherLocalDetector proxyutiliptables.LocalTrafficDetector, err1 error) [2]proxyutiliptables.LocalTrafficDetector { t.Helper() if err1 != nil { t.Fatalf("Error resolving dual stack detect-local: %v", err) } return [2]proxyutiliptables.LocalTrafficDetector{localDetector, otherLocalDetector} } } } func TestConfigChange(t *testing.T) { setUp := func() (*os.File, string, error) { tempDir, err := os.MkdirTemp("", "kubeproxy-config-change") if err != nil { return nil, "", fmt.Errorf("unable to create temporary directory: %v", err) } fullPath := filepath.Join(tempDir, "kube-proxy-config") file, err := os.Create(fullPath) if err != nil { return nil, "", fmt.Errorf("unexpected error when creating temp file: %v", err) } _, err = file.WriteString(`apiVersion: kubeproxy.config.k8s.io/v1alpha1 bindAddress: 0.0.0.0 bindAddressHardFail: false clientConnection: acceptContentTypes: "" burst: 10 contentType: application/vnd.kubernetes.protobuf kubeconfig: /var/lib/kube-proxy/kubeconfig.conf qps: 5 clusterCIDR: 10.244.0.0/16 configSyncPeriod: 15m0s conntrack: maxPerCore: 32768 min: 131072 tcpCloseWaitTimeout: 1h0m0s tcpEstablishedTimeout: 24h0m0s enableProfiling: false healthzBindAddress: 0.0.0.0:10256 hostnameOverride: "" iptables: masqueradeAll: false masqueradeBit: 14 minSyncPeriod: 0s syncPeriod: 30s ipvs: excludeCIDRs: null minSyncPeriod: 0s scheduler: "" syncPeriod: 30s kind: KubeProxyConfiguration metricsBindAddress: 127.0.0.1:10249 mode: "" nodePortAddresses: null oomScoreAdj: -999 portRange: "" detectLocalMode: "BridgeInterface"`) if err != nil { return nil, "", fmt.Errorf("unexpected error when writing content to temp kube-proxy config file: %v", err) } return file, tempDir, nil } tearDown := func(file *os.File, tempDir string) { file.Close() os.RemoveAll(tempDir) } testCases := []struct { name string proxyServer proxyRun append bool expectedErr string }{ { name: "update config file", proxyServer: new(fakeProxyServerLongRun), append: true, expectedErr: "content of the proxy server's configuration file was updated", }, { name: "fake error", proxyServer: new(fakeProxyServerError), expectedErr: "mocking error from ProxyServer.Run()", }, } for _, tc := range testCases { file, tempDir, err := setUp() if err != nil { t.Fatalf("unexpected error when setting up environment: %v", err) } opt := NewOptions() opt.ConfigFile = file.Name() err = opt.Complete(new(pflag.FlagSet)) if err != nil { t.Fatal(err) } opt.proxyServer = tc.proxyServer errCh := make(chan error, 1) go func() { errCh <- opt.runLoop() }() if tc.append { file.WriteString("append fake content") } select { case err := <-errCh: if err != nil { if !strings.Contains(err.Error(), tc.expectedErr) { t.Errorf("[%s] Expected error containing %v, got %v", tc.name, tc.expectedErr, err) } } case <-time.After(10 * time.Second): t.Errorf("[%s] Timeout: unable to get any events or internal timeout.", tc.name) } tearDown(file, tempDir) } } func Test_waitForPodCIDR(t *testing.T) { expected := []string{"192.168.0.0/24", "fd00:1:2::/64"} nodeName := "test-node" oldNode := &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: nodeName, ResourceVersion: "1000", }, Spec: v1.NodeSpec{ PodCIDR: "10.0.0.0/24", PodCIDRs: []string{"10.0.0.0/24", "2001:db2:1/64"}, }, } node := &v1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: nodeName, ResourceVersion: "1", }, } updatedNode := node.DeepCopy() updatedNode.Spec.PodCIDRs = expected updatedNode.Spec.PodCIDR = expected[0] // start with the new node client := clientsetfake.NewSimpleClientset() client.AddReactor("list", "nodes", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) { obj := &v1.NodeList{} return true, obj, nil }) fakeWatch := watch.NewFake() client.PrependWatchReactor("nodes", clientgotesting.DefaultWatchReactor(fakeWatch, nil)) go func() { fakeWatch.Add(node) // receive a delete event for the old node fakeWatch.Delete(oldNode) // set the PodCIDRs on the new node fakeWatch.Modify(updatedNode) }() got, err := waitForPodCIDR(client, node.Name) if err != nil { t.Errorf("waitForPodCIDR() unexpected error %v", err) return } if !reflect.DeepEqual(got.Spec.PodCIDRs, expected) { t.Errorf("waitForPodCIDR() got %v expected to be %v ", got.Spec.PodCIDRs, expected) } } func TestGetConntrackMax(t *testing.T) { ncores := goruntime.NumCPU() testCases := []struct { min int32 maxPerCore int32 expected int err string }{ { expected: 0, }, { maxPerCore: 67890, // use this if Max is 0 min: 1, // avoid 0 default expected: 67890 * ncores, }, { maxPerCore: 1, // ensure that Min is considered min: 123456, expected: 123456, }, { maxPerCore: 0, // leave system setting min: 123456, expected: 0, }, } for i, tc := range testCases { cfg := proxyconfigapi.KubeProxyConntrackConfiguration{ Min: ptr.To(tc.min), MaxPerCore: ptr.To(tc.maxPerCore), } x, e := getConntrackMax(cfg) if e != nil { if tc.err == "" { t.Errorf("[%d] unexpected error: %v", i, e) } else if !strings.Contains(e.Error(), tc.err) { t.Errorf("[%d] expected an error containing %q: %v", i, tc.err, e) } } else if x != tc.expected { t.Errorf("[%d] expected %d, got %d", i, tc.expected, x) } } } func TestProxyServer_platformSetup(t *testing.T) { tests := []struct { name string node *v1.Node config *proxyconfigapi.KubeProxyConfiguration wantPodCIDRs []string }{ { name: "LocalModeNodeCIDR store the node PodCIDRs obtained", node: makeNodeWithPodCIDRs("10.0.0.0/24"), config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR}, wantPodCIDRs: []string{"10.0.0.0/24"}, }, { name: "LocalModeNodeCIDR store the node PodCIDRs obtained dual stack", node: makeNodeWithPodCIDRs("10.0.0.0/24", "2001:db2:1/64"), config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeNodeCIDR}, wantPodCIDRs: []string{"10.0.0.0/24", "2001:db2:1/64"}, }, { name: "LocalModeClusterCIDR does not get the node PodCIDRs", node: makeNodeWithPodCIDRs("10.0.0.0/24", "2001:db2:1/64"), config: &proxyconfigapi.KubeProxyConfiguration{DetectLocalMode: proxyconfigapi.LocalModeClusterCIDR}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { client := clientsetfake.NewSimpleClientset(tt.node) s := &ProxyServer{ Config: tt.config, Client: client, Hostname: "nodename", NodeIPs: map[v1.IPFamily]net.IP{ v1.IPv4Protocol: netutils.ParseIPSloppy("127.0.0.1"), v1.IPv6Protocol: net.IPv6zero, }, } err := s.platformSetup() if err != nil { t.Errorf("ProxyServer.createProxier() error = %v", err) return } if !reflect.DeepEqual(s.podCIDRs, tt.wantPodCIDRs) { t.Errorf("Expected PodCIDRs %v got %v", tt.wantPodCIDRs, s.podCIDRs) } }) } }