mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			748 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			748 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
//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"
 | 
						|
	proxyutil "k8s.io/kubernetes/pkg/proxy/util"
 | 
						|
	"k8s.io/kubernetes/test/utils/ktesting"
 | 
						|
	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     proxyutil.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)(proxyutil.NewDetectLocalByCIDR("10.0.0.0/14")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:        "LocalModeClusterCIDR, IPv6 cluster",
 | 
						|
			mode:        proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config:      &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"},
 | 
						|
			family:      v1.IPv6Protocol,
 | 
						|
			expected:    resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/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:    proxyutil.NewNoOpLocalDetector(),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:        "LocalModeClusterCIDR, IPv4 cluster with IPv6 config",
 | 
						|
			mode:        proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config:      &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"},
 | 
						|
			family:      v1.IPv4Protocol,
 | 
						|
			expected:    proxyutil.NewNoOpLocalDetector(),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:        "LocalModeClusterCIDR, IPv4 kube-proxy in dual-stack IPv6-primary cluster",
 | 
						|
			mode:        proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config:      &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"},
 | 
						|
			family:      v1.IPv4Protocol,
 | 
						|
			expected:    resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("10.0.0.0/14")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:        "LocalModeClusterCIDR, no ClusterCIDR",
 | 
						|
			mode:        proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config:      &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""},
 | 
						|
			family:      v1.IPv4Protocol,
 | 
						|
			expected:    proxyutil.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)(proxyutil.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:0:0:1234::/64"},
 | 
						|
			family:       v1.IPv6Protocol,
 | 
						|
			expected:     resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96")),
 | 
						|
			nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/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:     proxyutil.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:0:0:1234::/64"},
 | 
						|
			family:       v1.IPv4Protocol,
 | 
						|
			expected:     proxyutil.NewNoOpLocalDetector(),
 | 
						|
			nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/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:0:0:1234::/64"},
 | 
						|
			family:       v1.IPv6Protocol,
 | 
						|
			expected:     resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96")),
 | 
						|
			nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"},
 | 
						|
			errExpected:  false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:         "LocalModeNodeCIDR, no PodCIDRs",
 | 
						|
			mode:         proxyconfigapi.LocalModeNodeCIDR,
 | 
						|
			config:       &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""},
 | 
						|
			family:       v1.IPv4Protocol,
 | 
						|
			expected:     proxyutil.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:    proxyutil.NewNoOpLocalDetector(),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		// LocalModeBridgeInterface
 | 
						|
		{
 | 
						|
			name: "LocalModeBrideInterface",
 | 
						|
			mode: proxyconfigapi.LocalModeBridgeInterface,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{
 | 
						|
				DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"},
 | 
						|
			},
 | 
						|
			family:      v1.IPv4Protocol,
 | 
						|
			expected:    resolveLocalDetector(t)(proxyutil.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)(proxyutil.NewDetectLocalByBridgeInterface("1234567890123456789")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		// LocalModeInterfaceNamePrefix
 | 
						|
		{
 | 
						|
			name: "LocalModeInterfaceNamePrefix",
 | 
						|
			mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{
 | 
						|
				DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "eth"},
 | 
						|
			},
 | 
						|
			family:      v1.IPv4Protocol,
 | 
						|
			expected:    resolveLocalDetector(t)(proxyutil.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)(proxyutil.NewDetectLocalByInterfaceNamePrefix("1234567890123456789")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, c := range cases {
 | 
						|
		t.Run(c.name, func(t *testing.T) {
 | 
						|
			logger, _ := ktesting.NewTestContext(t)
 | 
						|
			r, err := getLocalDetector(logger, 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]proxyutil.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:0:0:1234::/64"},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"))(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "LocalModeClusterCIDR, dual-stack IPv6-primary cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("10.0.0.0/14"))(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "LocalModeClusterCIDR, single-stack IPv4 cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14"},
 | 
						|
			expected: [2]proxyutil.LocalTrafficDetector{
 | 
						|
				resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("10.0.0.0/14")),
 | 
						|
				proxyutil.NewNoOpLocalDetector()},
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "LocalModeClusterCIDR, single-stack IPv6 cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"},
 | 
						|
			expected: [2]proxyutil.LocalTrafficDetector{
 | 
						|
				proxyutil.NewNoOpLocalDetector(),
 | 
						|
				resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("2002:0:0:1234::/64"))},
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:        "LocalModeClusterCIDR, no ClusterCIDR",
 | 
						|
			mode:        proxyconfigapi.LocalModeClusterCIDR,
 | 
						|
			config:      &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""},
 | 
						|
			expected:    [2]proxyutil.LocalTrafficDetector{proxyutil.NewNoOpLocalDetector(), proxyutil.NewNoOpLocalDetector()},
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		// LocalModeNodeCIDR
 | 
						|
		{
 | 
						|
			name:   "LocalModeNodeCIDR, dual-stack IPv4-primary cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeNodeCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "10.0.0.0/14,2002:0:0:1234::/64"},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"))(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96")),
 | 
						|
			nodePodCIDRs: []string{"10.0.0.0/24", "2002::1234:abcd:ffff:0:0/96"},
 | 
						|
			errExpected:  false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "LocalModeNodeCIDR, dual-stack IPv6-primary cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeNodeCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64,10.0.0.0/14"},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("10.0.0.0/24"))(
 | 
						|
				proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96")),
 | 
						|
			nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/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]proxyutil.LocalTrafficDetector{
 | 
						|
				resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("10.0.0.0/24")),
 | 
						|
				proxyutil.NewNoOpLocalDetector()},
 | 
						|
			nodePodCIDRs: []string{"10.0.0.0/24"},
 | 
						|
			errExpected:  false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:   "LocalModeNodeCIDR, single-stack IPv6 cluster",
 | 
						|
			mode:   proxyconfigapi.LocalModeNodeCIDR,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: "2002:0:0:1234::/64"},
 | 
						|
			expected: [2]proxyutil.LocalTrafficDetector{
 | 
						|
				proxyutil.NewNoOpLocalDetector(),
 | 
						|
				resolveLocalDetector(t)(proxyutil.NewDetectLocalByCIDR("2002::1234:abcd:ffff:0:0/96"))},
 | 
						|
			nodePodCIDRs: []string{"2002::1234:abcd:ffff:0:0/96"},
 | 
						|
			errExpected:  false,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			name:         "LocalModeNodeCIDR, no PodCIDRs",
 | 
						|
			mode:         proxyconfigapi.LocalModeNodeCIDR,
 | 
						|
			config:       &proxyconfigapi.KubeProxyConfiguration{ClusterCIDR: ""},
 | 
						|
			expected:     [2]proxyutil.LocalTrafficDetector{proxyutil.NewNoOpLocalDetector(), proxyutil.NewNoOpLocalDetector()},
 | 
						|
			nodePodCIDRs: []string{},
 | 
						|
			errExpected:  false,
 | 
						|
		},
 | 
						|
		// LocalModeBridgeInterface
 | 
						|
		{
 | 
						|
			name: "LocalModeBridgeInterface",
 | 
						|
			mode: proxyconfigapi.LocalModeBridgeInterface,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{
 | 
						|
				DetectLocal: proxyconfigapi.DetectLocalConfiguration{BridgeInterface: "eth"},
 | 
						|
			},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByBridgeInterface("eth"))(
 | 
						|
				proxyutil.NewDetectLocalByBridgeInterface("eth")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
		// LocalModeInterfaceNamePrefix
 | 
						|
		{
 | 
						|
			name: "LocalModeInterfaceNamePrefix",
 | 
						|
			mode: proxyconfigapi.LocalModeInterfaceNamePrefix,
 | 
						|
			config: &proxyconfigapi.KubeProxyConfiguration{
 | 
						|
				DetectLocal: proxyconfigapi.DetectLocalConfiguration{InterfaceNamePrefix: "veth"},
 | 
						|
			},
 | 
						|
			expected: resolveDualStackLocalDetectors(t)(
 | 
						|
				proxyutil.NewDetectLocalByInterfaceNamePrefix("veth"))(
 | 
						|
				proxyutil.NewDetectLocalByInterfaceNamePrefix("veth")),
 | 
						|
			errExpected: false,
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, c := range cases {
 | 
						|
		t.Run(c.name, func(t *testing.T) {
 | 
						|
			logger, _ := ktesting.NewTestContext(t)
 | 
						|
			r, err := getDualStackLocalDetectorTuple(logger, 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(proxyutil.LocalTrafficDetector, error) proxyutil.LocalTrafficDetector {
 | 
						|
	return func(localDetector proxyutil.LocalTrafficDetector, err error) proxyutil.LocalTrafficDetector {
 | 
						|
		t.Helper()
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Error resolving detect-local: %v", err)
 | 
						|
		}
 | 
						|
		return localDetector
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func resolveDualStackLocalDetectors(t *testing.T) func(localDetector proxyutil.LocalTrafficDetector, err1 error) func(proxyutil.LocalTrafficDetector, error) [2]proxyutil.LocalTrafficDetector {
 | 
						|
	return func(localDetector proxyutil.LocalTrafficDetector, err error) func(proxyutil.LocalTrafficDetector, error) [2]proxyutil.LocalTrafficDetector {
 | 
						|
		t.Helper()
 | 
						|
		if err != nil {
 | 
						|
			t.Fatalf("Error resolving dual stack detect-local: %v", err)
 | 
						|
		}
 | 
						|
		return func(otherLocalDetector proxyutil.LocalTrafficDetector, err1 error) [2]proxyutil.LocalTrafficDetector {
 | 
						|
			t.Helper()
 | 
						|
			if err1 != nil {
 | 
						|
				t.Fatalf("Error resolving dual stack detect-local: %v", err)
 | 
						|
			}
 | 
						|
			return [2]proxyutil.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 {
 | 
						|
		_, ctx := ktesting.NewTestContext(t)
 | 
						|
		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(ctx)
 | 
						|
		}()
 | 
						|
 | 
						|
		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) {
 | 
						|
	_, ctx := ktesting.NewTestContext(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(ctx, 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),
 | 
						|
		}
 | 
						|
		_, ctx := ktesting.NewTestContext(t)
 | 
						|
		x, e := getConntrackMax(ctx, 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) {
 | 
						|
			_, ctx := ktesting.NewTestContext(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(ctx)
 | 
						|
			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)
 | 
						|
			}
 | 
						|
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |