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  }