mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 10:33:35 +00:00
vendor updates
This commit is contained in:
20
vendor/k8s.io/kubernetes/pkg/proxy/util/BUILD
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/proxy/util/BUILD
generated
vendored
@ -3,8 +3,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"conntrack.go",
|
||||
"endpoints.go",
|
||||
"network.go",
|
||||
"port.go",
|
||||
"utils.go",
|
||||
],
|
||||
@ -13,28 +13,29 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//pkg/util/net:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"conntrack_test.go",
|
||||
"endpoints_test.go",
|
||||
"port_test.go",
|
||||
"utils_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/proxy/util",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/proxy/util/testing:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec/testing:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@ -47,7 +48,10 @@ filegroup(
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/proxy/util/testing:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
105
vendor/k8s.io/kubernetes/pkg/proxy/util/conntrack.go
generated
vendored
105
vendor/k8s.io/kubernetes/pkg/proxy/util/conntrack.go
generated
vendored
@ -1,105 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
// Utilities for dealing with conntrack
|
||||
|
||||
const NoConnectionToDelete = "0 flow entries have been deleted"
|
||||
|
||||
func IsIPv6(netIP net.IP) bool {
|
||||
return netIP != nil && netIP.To4() == nil
|
||||
}
|
||||
|
||||
func IsIPv6String(ip string) bool {
|
||||
netIP := net.ParseIP(ip)
|
||||
return IsIPv6(netIP)
|
||||
}
|
||||
|
||||
func parametersWithFamily(isIPv6 bool, parameters ...string) []string {
|
||||
if isIPv6 {
|
||||
parameters = append(parameters, "-f", "ipv6")
|
||||
}
|
||||
return parameters
|
||||
}
|
||||
|
||||
// ClearUDPConntrackForIP uses the conntrack tool to delete the conntrack entries
|
||||
// for the UDP connections specified by the given service IP
|
||||
func ClearUDPConntrackForIP(execer exec.Interface, ip string) error {
|
||||
parameters := parametersWithFamily(IsIPv6String(ip), "-D", "--orig-dst", ip, "-p", "udp")
|
||||
err := ExecConntrackTool(execer, parameters...)
|
||||
if err != nil && !strings.Contains(err.Error(), NoConnectionToDelete) {
|
||||
// TODO: Better handling for deletion failure. When failure occur, stale udp connection may not get flushed.
|
||||
// These stale udp connection will keep black hole traffic. Making this a best effort operation for now, since it
|
||||
// is expensive to baby-sit all udp connections to kubernetes services.
|
||||
return fmt.Errorf("error deleting connection tracking state for UDP service IP: %s, error: %v", ip, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExecConntrackTool executes the conntrack tool using the given parameters
|
||||
func ExecConntrackTool(execer exec.Interface, parameters ...string) error {
|
||||
conntrackPath, err := execer.LookPath("conntrack")
|
||||
if err != nil {
|
||||
return fmt.Errorf("error looking for path of conntrack: %v", err)
|
||||
}
|
||||
output, err := execer.Command(conntrackPath, parameters...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("conntrack command returned: %q, error message: %s", string(output), err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearUDPConntrackForPort uses the conntrack tool to delete the conntrack entries
|
||||
// for the UDP connections specified by the port.
|
||||
// When a packet arrives, it will not go through NAT table again, because it is not "the first" packet.
|
||||
// The solution is clearing the conntrack. Known issues:
|
||||
// https://github.com/docker/docker/issues/8795
|
||||
// https://github.com/kubernetes/kubernetes/issues/31983
|
||||
func ClearUDPConntrackForPort(execer exec.Interface, port int, isIPv6 bool) error {
|
||||
if port <= 0 {
|
||||
return fmt.Errorf("Wrong port number. The port number must be greater than zero")
|
||||
}
|
||||
parameters := parametersWithFamily(isIPv6, "-D", "-p", "udp", "--dport", strconv.Itoa(port))
|
||||
err := ExecConntrackTool(execer, parameters...)
|
||||
if err != nil && !strings.Contains(err.Error(), NoConnectionToDelete) {
|
||||
return fmt.Errorf("error deleting conntrack entries for UDP port: %d, error: %v", port, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearUDPConntrackForPeers uses the conntrack tool to delete the conntrack entries
|
||||
// for the UDP connections specified by the {origin, dest} IP pair.
|
||||
func ClearUDPConntrackForPeers(execer exec.Interface, origin, dest string) error {
|
||||
parameters := parametersWithFamily(IsIPv6String(origin), "-D", "--orig-dst", origin, "--dst-nat", dest, "-p", "udp")
|
||||
err := ExecConntrackTool(execer, parameters...)
|
||||
if err != nil && !strings.Contains(err.Error(), NoConnectionToDelete) {
|
||||
// TODO: Better handling for deletion failure. When failure occur, stale udp connection may not get flushed.
|
||||
// These stale udp connection will keep black hole traffic. Making this a best effort operation for now, since it
|
||||
// is expensive to baby sit all udp connections to kubernetes services.
|
||||
return fmt.Errorf("error deleting conntrack entries for UDP peer {%s, %s}, error: %v", origin, dest, err)
|
||||
}
|
||||
return nil
|
||||
}
|
331
vendor/k8s.io/kubernetes/pkg/proxy/util/conntrack_test.go
generated
vendored
331
vendor/k8s.io/kubernetes/pkg/proxy/util/conntrack_test.go
generated
vendored
@ -1,331 +0,0 @@
|
||||
/*
|
||||
Copyright 2015 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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/utils/exec"
|
||||
fakeexec "k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
func familyParamStr(isIPv6 bool) string {
|
||||
if isIPv6 {
|
||||
return " -f ipv6"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestExecConntrackTool(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) {
|
||||
return []byte(""), fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted")
|
||||
},
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return cmd, nil },
|
||||
}
|
||||
|
||||
testCases := [][]string{
|
||||
{"-L", "-p", "udp"},
|
||||
{"-D", "-p", "udp", "-d", "10.0.240.1"},
|
||||
{"-D", "-p", "udp", "--orig-dst", "10.240.0.2", "--dst-nat", "10.0.10.2"},
|
||||
}
|
||||
|
||||
expectErr := []bool{false, false, true}
|
||||
|
||||
for i := range testCases {
|
||||
err := ExecConntrackTool(&fexec, testCases[i]...)
|
||||
|
||||
if expectErr[i] {
|
||||
if err == nil {
|
||||
t.Errorf("expected err, got %v", err)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("expected success, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
execCmd := strings.Join(fcmd.CombinedOutputLog[i], " ")
|
||||
expectCmd := fmt.Sprintf("%s %s", "conntrack", strings.Join(testCases[i], " "))
|
||||
|
||||
if execCmd != expectCmd {
|
||||
t.Errorf("expect execute command: %s, but got: %s", expectCmd, execCmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestClearUDPConntrackForIP(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) {
|
||||
return []byte(""), fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted")
|
||||
},
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return cmd, nil },
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
ip string
|
||||
}{
|
||||
{"IPv4 success", "10.240.0.3"},
|
||||
{"IPv4 success", "10.240.0.5"},
|
||||
{"IPv4 simulated error", "10.240.0.4"},
|
||||
{"IPv6 success", "2001:db8::10"},
|
||||
}
|
||||
|
||||
svcCount := 0
|
||||
for _, tc := range testCases {
|
||||
if err := ClearUDPConntrackForIP(&fexec, tc.ip); err != nil {
|
||||
t.Errorf("%s test case:, Unexpected error: %v", tc.name, err)
|
||||
}
|
||||
expectCommand := fmt.Sprintf("conntrack -D --orig-dst %s -p udp", tc.ip) + familyParamStr(IsIPv6String(tc.ip))
|
||||
execCommand := strings.Join(fcmd.CombinedOutputLog[svcCount], " ")
|
||||
if expectCommand != execCommand {
|
||||
t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand)
|
||||
}
|
||||
svcCount++
|
||||
}
|
||||
if svcCount != fexec.CommandCalls {
|
||||
t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClearUDPConntrackForPort(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) {
|
||||
return []byte(""), fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted")
|
||||
},
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return cmd, nil },
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
port int
|
||||
isIPv6 bool
|
||||
}{
|
||||
{"IPv4, no error", 8080, false},
|
||||
{"IPv4, simulated error", 9090, false},
|
||||
{"IPv6, no error", 6666, true},
|
||||
}
|
||||
svcCount := 0
|
||||
for _, tc := range testCases {
|
||||
err := ClearUDPConntrackForPort(&fexec, tc.port, tc.isIPv6)
|
||||
if err != nil {
|
||||
t.Errorf("%s test case: Unexpected error: %v", tc.name, err)
|
||||
}
|
||||
expectCommand := fmt.Sprintf("conntrack -D -p udp --dport %d", tc.port) + familyParamStr(tc.isIPv6)
|
||||
execCommand := strings.Join(fcmd.CombinedOutputLog[svcCount], " ")
|
||||
if expectCommand != execCommand {
|
||||
t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand)
|
||||
}
|
||||
svcCount++
|
||||
}
|
||||
if svcCount != fexec.CommandCalls {
|
||||
t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUDPConnections(t *testing.T) {
|
||||
fcmd := fakeexec.FakeCmd{
|
||||
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
func() ([]byte, error) {
|
||||
return []byte(""), fmt.Errorf("conntrack v1.4.2 (conntrack-tools): 0 flow entries have been deleted")
|
||||
},
|
||||
func() ([]byte, error) { return []byte("1 flow entries have been deleted"), nil },
|
||||
},
|
||||
}
|
||||
fexec := fakeexec.FakeExec{
|
||||
CommandScript: []fakeexec.FakeCommandAction{
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
func(cmd string, args ...string) exec.Cmd { return fakeexec.InitFakeCmd(&fcmd, cmd, args...) },
|
||||
},
|
||||
LookPathFunc: func(cmd string) (string, error) { return cmd, nil },
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
origin string
|
||||
dest string
|
||||
}{
|
||||
{
|
||||
name: "IPv4 success",
|
||||
origin: "1.2.3.4",
|
||||
dest: "10.20.30.40",
|
||||
},
|
||||
{
|
||||
name: "IPv4 simulated failure",
|
||||
origin: "2.3.4.5",
|
||||
dest: "20.30.40.50",
|
||||
},
|
||||
{
|
||||
name: "IPv6 success",
|
||||
origin: "fd00::600d:f00d",
|
||||
dest: "2001:db8::5",
|
||||
},
|
||||
}
|
||||
svcCount := 0
|
||||
for i, tc := range testCases {
|
||||
err := ClearUDPConntrackForPeers(&fexec, tc.origin, tc.dest)
|
||||
if err != nil {
|
||||
t.Errorf("%s test case: unexpected error: %v", tc.name, err)
|
||||
}
|
||||
expectCommand := fmt.Sprintf("conntrack -D --orig-dst %s --dst-nat %s -p udp", tc.origin, tc.dest) + familyParamStr(IsIPv6String(tc.origin))
|
||||
execCommand := strings.Join(fcmd.CombinedOutputLog[i], " ")
|
||||
if expectCommand != execCommand {
|
||||
t.Errorf("%s test case: Expect command: %s, but executed %s", tc.name, expectCommand, execCommand)
|
||||
}
|
||||
svcCount++
|
||||
}
|
||||
if svcCount != fexec.CommandCalls {
|
||||
t.Errorf("Expect command executed %d times, but got %d", svcCount, fexec.CommandCalls)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIPv6String(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ip string
|
||||
expectIPv6 bool
|
||||
}{
|
||||
{
|
||||
ip: "127.0.0.1",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "192.168.0.0",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "1.2.3.4",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "bad ip",
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: "::1",
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: "fd00::600d:f00d",
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: "2001:db8::5",
|
||||
expectIPv6: true,
|
||||
},
|
||||
}
|
||||
for i := range testCases {
|
||||
isIPv6 := IsIPv6String(testCases[i].ip)
|
||||
if isIPv6 != testCases[i].expectIPv6 {
|
||||
t.Errorf("[%d] Expect ipv6 %v, got %v", i+1, testCases[i].expectIPv6, isIPv6)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsIPv6(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ip net.IP
|
||||
expectIPv6 bool
|
||||
}{
|
||||
{
|
||||
ip: net.IPv4zero,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.IPv4bcast,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("127.0.0.1"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("10.20.40.40"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("172.17.3.0"),
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: nil,
|
||||
expectIPv6: false,
|
||||
},
|
||||
{
|
||||
ip: net.IPv6loopback,
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.IPv6zero,
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("fd00::600d:f00d"),
|
||||
expectIPv6: true,
|
||||
},
|
||||
{
|
||||
ip: net.ParseIP("2001:db8::5"),
|
||||
expectIPv6: true,
|
||||
},
|
||||
}
|
||||
for i := range testCases {
|
||||
isIPv6 := IsIPv6(testCases[i].ip)
|
||||
if isIPv6 != testCases[i].expectIPv6 {
|
||||
t.Errorf("[%d] Expect ipv6 %v, got %v", i+1, testCases[i].expectIPv6, isIPv6)
|
||||
}
|
||||
}
|
||||
}
|
1
vendor/k8s.io/kubernetes/pkg/proxy/util/endpoints.go
generated
vendored
1
vendor/k8s.io/kubernetes/pkg/proxy/util/endpoints.go
generated
vendored
@ -47,6 +47,7 @@ func IPPart(s string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// PortPart returns just the port part of an endpoint string.
|
||||
func PortPart(s string) (int, error) {
|
||||
// Must be IP:port
|
||||
_, port, err := net.SplitHostPort(s)
|
||||
|
45
vendor/k8s.io/kubernetes/pkg/proxy/util/network.go
generated
vendored
Normal file
45
vendor/k8s.io/kubernetes/pkg/proxy/util/network.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
// NetworkInterfacer defines an interface for several net library functions. Production
|
||||
// code will forward to net library functions, and unit tests will override the methods
|
||||
// for testing purposes.
|
||||
type NetworkInterfacer interface {
|
||||
Addrs(intf *net.Interface) ([]net.Addr, error)
|
||||
Interfaces() ([]net.Interface, error)
|
||||
}
|
||||
|
||||
// RealNetwork implements the NetworkInterfacer interface for production code, just
|
||||
// wrapping the underlying net library function calls.
|
||||
type RealNetwork struct{}
|
||||
|
||||
// Addrs wraps net.Interface.Addrs(), it's a part of NetworkInterfacer interface.
|
||||
func (_ RealNetwork) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
return intf.Addrs()
|
||||
}
|
||||
|
||||
// Interfaces wraps net.Interfaces(), it's a part of NetworkInterfacer interface.
|
||||
func (_ RealNetwork) Interfaces() ([]net.Interface, error) {
|
||||
return net.Interfaces()
|
||||
}
|
||||
|
||||
var _ NetworkInterfacer = &RealNetwork{}
|
22
vendor/k8s.io/kubernetes/pkg/proxy/util/testing/BUILD
generated
vendored
Normal file
22
vendor/k8s.io/kubernetes/pkg/proxy/util/testing/BUILD
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["fake.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/proxy/util/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
65
vendor/k8s.io/kubernetes/pkg/proxy/util/testing/fake.go
generated
vendored
Normal file
65
vendor/k8s.io/kubernetes/pkg/proxy/util/testing/fake.go
generated
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
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 testing
|
||||
|
||||
import "net"
|
||||
|
||||
// FakeNetwork implements the NetworkInterfacer interface for test purpose.
|
||||
type FakeNetwork struct {
|
||||
NetworkInterfaces []net.Interface
|
||||
// The key of map Addrs is the network interface name
|
||||
Address map[string][]net.Addr
|
||||
}
|
||||
|
||||
// NewFakeNetwork initializes a FakeNetwork.
|
||||
func NewFakeNetwork() *FakeNetwork {
|
||||
return &FakeNetwork{
|
||||
NetworkInterfaces: make([]net.Interface, 0),
|
||||
Address: make(map[string][]net.Addr),
|
||||
}
|
||||
}
|
||||
|
||||
// AddInterfaceAddr create an interface and its associated addresses for FakeNetwork implementation.
|
||||
func (f *FakeNetwork) AddInterfaceAddr(intf *net.Interface, addrs []net.Addr) {
|
||||
f.NetworkInterfaces = append(f.NetworkInterfaces, *intf)
|
||||
f.Address[intf.Name] = addrs
|
||||
}
|
||||
|
||||
// Addrs is part of NetworkInterfacer interface.
|
||||
func (f *FakeNetwork) Addrs(intf *net.Interface) ([]net.Addr, error) {
|
||||
return f.Address[intf.Name], nil
|
||||
}
|
||||
|
||||
// Interfaces is part of NetworkInterfacer interface.
|
||||
func (f *FakeNetwork) Interfaces() ([]net.Interface, error) {
|
||||
return f.NetworkInterfaces, nil
|
||||
}
|
||||
|
||||
// AddrStruct implements the net.Addr for test purpose.
|
||||
type AddrStruct struct{ Val string }
|
||||
|
||||
// Network is part of net.Addr interface.
|
||||
func (a AddrStruct) Network() string {
|
||||
return a.Val
|
||||
}
|
||||
|
||||
// String is part of net.Addr interface.
|
||||
func (a AddrStruct) String() string {
|
||||
return a.Val
|
||||
}
|
||||
|
||||
var _ net.Addr = &AddrStruct{}
|
90
vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go
generated
vendored
90
vendor/k8s.io/kubernetes/pkg/proxy/util/utils.go
generated
vendored
@ -17,15 +17,32 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/record"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
utilnet "k8s.io/kubernetes/pkg/util/net"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
const (
|
||||
IPv4ZeroCIDR = "0.0.0.0/0"
|
||||
IPv6ZeroCIDR = "::/0"
|
||||
)
|
||||
|
||||
func IsZeroCIDR(cidr string) bool {
|
||||
if cidr == IPv4ZeroCIDR || cidr == IPv6ZeroCIDR {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IsLocalIP(ip string) (bool, error) {
|
||||
addrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
@ -56,3 +73,76 @@ func ShouldSkipService(svcName types.NamespacedName, service *api.Service) bool
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetNodeAddresses return all matched node IP addresses based on given cidr slice.
|
||||
// Some callers, e.g. IPVS proxier, need concrete IPs, not ranges, which is why this exists.
|
||||
// NetworkInterfacer is injected for test purpose.
|
||||
// We expect the cidrs passed in is already validated.
|
||||
// Given an empty input `[]`, it will return `0.0.0.0/0` and `::/0` directly.
|
||||
// If multiple cidrs is given, it will return the minimal IP sets, e.g. given input `[1.2.0.0/16, 0.0.0.0/0]`, it will
|
||||
// only return `0.0.0.0/0`.
|
||||
// NOTE: GetNodeAddresses only accepts CIDRs, if you want concrete IPs, e.g. 1.2.3.4, then the input should be 1.2.3.4/32.
|
||||
func GetNodeAddresses(cidrs []string, nw NetworkInterfacer) (sets.String, error) {
|
||||
uniqueAddressList := sets.NewString()
|
||||
if len(cidrs) == 0 {
|
||||
uniqueAddressList.Insert(IPv4ZeroCIDR)
|
||||
uniqueAddressList.Insert(IPv6ZeroCIDR)
|
||||
return uniqueAddressList, nil
|
||||
}
|
||||
// First round of iteration to pick out `0.0.0.0/0` or `::/0` for the sake of excluding non-zero IPs.
|
||||
for _, cidr := range cidrs {
|
||||
if IsZeroCIDR(cidr) {
|
||||
uniqueAddressList.Insert(cidr)
|
||||
}
|
||||
}
|
||||
// Second round of iteration to parse IPs based on cidr.
|
||||
for _, cidr := range cidrs {
|
||||
if IsZeroCIDR(cidr) {
|
||||
continue
|
||||
}
|
||||
_, ipNet, _ := net.ParseCIDR(cidr)
|
||||
itfs, err := nw.Interfaces()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error listing all interfaces from host, error: %v", err)
|
||||
}
|
||||
for _, itf := range itfs {
|
||||
addrs, err := nw.Addrs(&itf)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting address from interface %s, error: %v", itf.Name, err)
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
if addr == nil {
|
||||
continue
|
||||
}
|
||||
ip, _, err := net.ParseCIDR(addr.String())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing CIDR for interface %s, error: %v", itf.Name, err)
|
||||
}
|
||||
if ipNet.Contains(ip) {
|
||||
if utilnet.IsIPv6(ip) && !uniqueAddressList.Has(IPv6ZeroCIDR) {
|
||||
uniqueAddressList.Insert(ip.String())
|
||||
}
|
||||
if !utilnet.IsIPv6(ip) && !uniqueAddressList.Has(IPv4ZeroCIDR) {
|
||||
uniqueAddressList.Insert(ip.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniqueAddressList, nil
|
||||
}
|
||||
|
||||
// LogAndEmitIncorrectIPVersionEvent logs and emits incorrect IP version event.
|
||||
func LogAndEmitIncorrectIPVersionEvent(recorder record.EventRecorder, fieldName, fieldValue, svcNamespace, svcName string, svcUID types.UID) {
|
||||
errMsg := fmt.Sprintf("%s in %s has incorrect IP version", fieldValue, fieldName)
|
||||
glog.Errorf("%s (service %s/%s).", errMsg, svcNamespace, svcName)
|
||||
if recorder != nil {
|
||||
recorder.Eventf(
|
||||
&v1.ObjectReference{
|
||||
Kind: "Service",
|
||||
Name: svcName,
|
||||
Namespace: svcNamespace,
|
||||
UID: svcUID,
|
||||
}, v1.EventTypeWarning, "KubeProxyIncorrectIPVersion", errMsg)
|
||||
}
|
||||
}
|
||||
|
218
vendor/k8s.io/kubernetes/pkg/proxy/util/utils_test.go
generated
vendored
218
vendor/k8s.io/kubernetes/pkg/proxy/util/utils_test.go
generated
vendored
@ -17,11 +17,14 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
fake "k8s.io/kubernetes/pkg/proxy/util/testing"
|
||||
)
|
||||
|
||||
func TestShouldSkipService(t *testing.T) {
|
||||
@ -109,3 +112,218 @@ func TestShouldSkipService(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type InterfaceAddrsPair struct {
|
||||
itf net.Interface
|
||||
addrs []net.Addr
|
||||
}
|
||||
|
||||
func TestGetNodeAddressses(t *testing.T) {
|
||||
testCases := []struct {
|
||||
cidrs []string
|
||||
nw *fake.FakeNetwork
|
||||
itfAddrsPairs []InterfaceAddrsPair
|
||||
expected sets.String
|
||||
}{
|
||||
{ // case 0
|
||||
cidrs: []string{"10.20.30.0/24"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "100.200.201.1/24"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("10.20.30.51"),
|
||||
},
|
||||
{ // case 1
|
||||
cidrs: []string{"0.0.0.0/0"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("0.0.0.0/0"),
|
||||
},
|
||||
{ // case 2
|
||||
cidrs: []string{"2001:db8::/32", "::1/128"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("2001:db8::1", "::1"),
|
||||
},
|
||||
{ // case 3
|
||||
cidrs: []string{"::/0"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("::/0"),
|
||||
},
|
||||
{ // case 4
|
||||
cidrs: []string{"127.0.0.1/32"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("127.0.0.1"),
|
||||
},
|
||||
{ // case 5
|
||||
cidrs: []string{"127.0.0.0/8"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "127.0.1.1/8"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("127.0.1.1"),
|
||||
},
|
||||
{ // case 6
|
||||
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "100.200.201.1/24"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("10.20.30.51", "100.200.201.1"),
|
||||
},
|
||||
{ // case 7
|
||||
cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "192.168.1.2/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString(),
|
||||
},
|
||||
{ // case 8
|
||||
cidrs: []string{},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "192.168.1.2/24"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
||||
},
|
||||
{ // case 9
|
||||
cidrs: []string{},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("0.0.0.0/0", "::/0"),
|
||||
},
|
||||
{ // case 9
|
||||
cidrs: []string{"1.2.3.0/24", "0.0.0.0/0"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("0.0.0.0/0"),
|
||||
},
|
||||
{ // case 10
|
||||
cidrs: []string{"0.0.0.0/0", "1.2.3.0/24", "::1/128"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("0.0.0.0/0", "::1"),
|
||||
},
|
||||
{ // case 11
|
||||
cidrs: []string{"::/0", "1.2.3.0/24", "::1/128"},
|
||||
nw: fake.NewFakeNetwork(),
|
||||
itfAddrsPairs: []InterfaceAddrsPair{
|
||||
{
|
||||
itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
|
||||
},
|
||||
{
|
||||
itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
|
||||
addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
|
||||
},
|
||||
},
|
||||
expected: sets.NewString("::/0", "1.2.3.4"),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range testCases {
|
||||
for _, pair := range testCases[i].itfAddrsPairs {
|
||||
testCases[i].nw.AddInterfaceAddr(&pair.itf, pair.addrs)
|
||||
}
|
||||
addrList, err := GetNodeAddresses(testCases[i].cidrs, testCases[i].nw)
|
||||
if err != nil {
|
||||
t.Errorf("case [%d], unexpected error: %v", i, err)
|
||||
}
|
||||
if !addrList.Equal(testCases[i].expected) {
|
||||
t.Errorf("case [%d], unexpected mismatch, expected: %v, got: %v", i, testCases[i].expected, addrList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user