vendor updates

This commit is contained in:
Serguei Bezverkhi
2018-03-06 17:33:18 -05:00
parent 4b3ebc171b
commit e9033989a0
5854 changed files with 248382 additions and 119809 deletions

View File

@ -15,11 +15,13 @@ filegroup(
"//pkg/util/bandwidth:all-srcs",
"//pkg/util/config:all-srcs",
"//pkg/util/configz:all-srcs",
"//pkg/util/conntrack:all-srcs",
"//pkg/util/dbus:all-srcs",
"//pkg/util/ebtables:all-srcs",
"//pkg/util/env:all-srcs",
"//pkg/util/file:all-srcs",
"//pkg/util/filesystem:all-srcs",
"//pkg/util/flag:all-srcs",
"//pkg/util/flock:all-srcs",
"//pkg/util/goroutinemap:all-srcs",
"//pkg/util/hash:all-srcs",

View File

@ -25,8 +25,7 @@ go_test(
"bounded_frequency_runner_test.go",
"runner_test.go",
],
importpath = "k8s.io/kubernetes/pkg/util/async",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -109,7 +109,7 @@ var _ timer = realTimer{}
// multiple runs are serialized. If the function needs to hold locks, it must
// take them internally.
//
// Runs of the funtion will have at least minInterval between them (from
// Runs of the function will have at least minInterval between them (from
// completion to next start), except that up to bursts may be allowed. Burst
// runs are "accumulated" over time, one per minInterval up to burstRuns total.
// This can be used, for example, to mitigate the impact of expensive operations

View File

@ -61,6 +61,7 @@ type fakeTimer struct {
func newFakeTimer() *fakeTimer {
ft := &fakeTimer{
now: time.Date(2000, 0, 0, 0, 0, 0, 0, time.UTC),
c: make(chan time.Time),
updated: make(chan timerUpdate),
}

View File

@ -12,19 +12,48 @@ go_library(
"doc.go",
"fake_shaper.go",
"interfaces.go",
"unsupported.go",
"utils.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/bandwidth",
deps = [
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
@ -38,19 +67,18 @@ go_test(
srcs = [
"utils_test.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"linux_test.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/bandwidth",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",
],

View File

@ -128,15 +128,15 @@ func asciiCIDR(cidr string) (string, error) {
return fmt.Sprintf("%s/%d", ip.String(), size), nil
}
func (t *tcShaper) findCIDRClass(cidr string) (class, handle string, found bool, err error) {
func (t *tcShaper) findCIDRClass(cidr string) (classAndHandleList [][]string, found bool, err error) {
data, err := t.e.Command("tc", "filter", "show", "dev", t.iface).CombinedOutput()
if err != nil {
return "", "", false, err
return classAndHandleList, false, err
}
hex, err := hexCIDR(cidr)
if err != nil {
return "", "", false, err
return classAndHandleList, false, err
}
spec := fmt.Sprintf("match %s", hex)
@ -156,12 +156,17 @@ func (t *tcShaper) findCIDRClass(cidr string) (class, handle string, found bool,
// expected tc line:
// filter parent 1: protocol ip pref 1 u32 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1
if len(parts) != 19 {
return "", "", false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(parts), parts)
return classAndHandleList, false, fmt.Errorf("unexpected output from tc: %s %d (%v)", filter, len(parts), parts)
} else {
resultTmp := []string{parts[18], parts[9]}
classAndHandleList = append(classAndHandleList, resultTmp)
}
return parts[18], parts[9], true, nil
}
}
return "", "", false, nil
if len(classAndHandleList) > 0 {
return classAndHandleList, true, nil
}
return classAndHandleList, false, nil
}
func makeKBitString(rsrc *resource.Quantity) string {
@ -237,7 +242,7 @@ func (t *tcShaper) interfaceExists() (bool, string, error) {
}
func (t *tcShaper) ReconcileCIDR(cidr string, upload, download *resource.Quantity) error {
_, _, found, err := t.findCIDRClass(cidr)
_, found, err := t.findCIDRClass(cidr)
if err != nil {
return err
}
@ -272,22 +277,31 @@ func (t *tcShaper) initializeInterface() error {
}
func (t *tcShaper) Reset(cidr string) error {
class, handle, found, err := t.findCIDRClass(cidr)
classAndHandle, found, err := t.findCIDRClass(cidr)
if err != nil {
return err
}
if !found {
return fmt.Errorf("Failed to find cidr: %s on interface: %s", cidr, t.iface)
}
if err := t.execAndLog("tc", "filter", "del",
"dev", t.iface,
"parent", "1:",
"proto", "ip",
"prio", "1",
"handle", handle, "u32"); err != nil {
return err
for i := 0; i < len(classAndHandle); i++ {
if err := t.execAndLog("tc", "filter", "del",
"dev", t.iface,
"parent", "1:",
"proto", "ip",
"prio", "1",
"handle", classAndHandle[i][1], "u32"); err != nil {
return err
}
if err := t.execAndLog("tc", "class", "del",
"dev", t.iface,
"parent", "1:",
"classid", classAndHandle[i][0]); err != nil {
return err
}
}
return t.execAndLog("tc", "class", "del", "dev", t.iface, "parent", "1:", "classid", class)
return nil
}
func (t *tcShaper) deleteInterface(class string) error {

View File

@ -259,7 +259,7 @@ func TestFindCIDRClass(t *testing.T) {
},
}
shaper := &tcShaper{e: &fexec}
class, handle, found, err := shaper.findCIDRClass(test.cidr)
classAndHandle, found, err := shaper.findCIDRClass(test.cidr)
if test.expectErr {
if err == nil {
t.Errorf("unexpected non-error")
@ -270,14 +270,14 @@ func TestFindCIDRClass(t *testing.T) {
}
if test.expectNotFound {
if found {
t.Errorf("unexpectedly found an interface: %s %s", class, handle)
t.Errorf("unexpectedly found an interface: %s", classAndHandle)
}
} else {
if class != test.expectedClass {
t.Errorf("expected: %s, found %s", test.expectedClass, class)
if classAndHandle[0][0] != test.expectedClass {
t.Errorf("expected class: %s, found %s", test.expectedClass, classAndHandle)
}
if handle != test.expectedHandle {
t.Errorf("expected: %s, found %s", test.expectedHandle, handle)
if classAndHandle[0][1] != test.expectedHandle {
t.Errorf("expected handle: %s, found %s", test.expectedHandle, classAndHandle)
}
}
}

View File

@ -19,8 +19,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["config_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/config",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -15,8 +15,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["configz_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/configz",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

43
vendor/k8s.io/kubernetes/pkg/util/conntrack/BUILD generated vendored Normal file
View File

@ -0,0 +1,43 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"conntrack.go",
],
importpath = "k8s.io/kubernetes/pkg/util/conntrack",
visibility = ["//visibility:public"],
deps = [
"//pkg/util/net:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"conntrack_test.go",
],
embed = [":go_default_library"],
deps = [
"//pkg/util/net:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,109 @@
/*
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 conntrack
import (
"fmt"
"strconv"
"strings"
"k8s.io/api/core/v1"
utilnet "k8s.io/kubernetes/pkg/util/net"
"k8s.io/utils/exec"
)
// Utilities for dealing with conntrack
// NoConnectionToDelete is the error string returned by conntrack when no matching connections are found
const NoConnectionToDelete = "0 flow entries have been deleted"
func protoStr(proto v1.Protocol) string {
return strings.ToLower(string(proto))
}
func parametersWithFamily(isIPv6 bool, parameters ...string) []string {
if isIPv6 {
parameters = append(parameters, "-f", "ipv6")
}
return parameters
}
// ClearEntriesForIP uses the conntrack tool to delete the conntrack entries
// for the UDP connections specified by the given service IP
func ClearEntriesForIP(execer exec.Interface, ip string, protocol v1.Protocol) error {
parameters := parametersWithFamily(utilnet.IsIPv6String(ip), "-D", "--orig-dst", ip, "-p", protoStr(protocol))
err := Exec(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
}
// Exec executes the conntrack tool using the given parameters
func Exec(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
}
// Exists returns true if conntrack binary is installed.
func Exists(execer exec.Interface) bool {
_, err := execer.LookPath("conntrack")
return err == nil
}
// ClearEntriesForPort uses the conntrack tool to delete the conntrack entries
// for 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 ClearEntriesForPort(execer exec.Interface, port int, isIPv6 bool, protocol v1.Protocol) error {
if port <= 0 {
return fmt.Errorf("Wrong port number. The port number must be greater than zero")
}
parameters := parametersWithFamily(isIPv6, "-D", "-p", protoStr(protocol), "--dport", strconv.Itoa(port))
err := Exec(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
}
// ClearEntriesForNAT uses the conntrack tool to delete the conntrack entries
// for connections specified by the {origin, dest} IP pair.
func ClearEntriesForNAT(execer exec.Interface, origin, dest string, protocol v1.Protocol) error {
parameters := parametersWithFamily(utilnet.IsIPv6String(origin), "-D", "--orig-dst", origin, "--dst-nat", dest,
"-p", protoStr(protocol))
err := Exec(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
}

View File

@ -0,0 +1,236 @@
/*
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 conntrack
import (
"fmt"
"strings"
"testing"
"k8s.io/api/core/v1"
utilnet "k8s.io/kubernetes/pkg/util/net"
"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 := Exec(&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 := ClearEntriesForIP(&fexec, tc.ip, v1.ProtocolUDP); 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(utilnet.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 := ClearEntriesForPort(&fexec, tc.port, tc.isIPv6, v1.ProtocolUDP)
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 := ClearEntriesForNAT(&fexec, tc.origin, tc.dest, v1.ProtocolUDP)
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(utilnet.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)
}
}

View File

@ -20,8 +20,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["dbus_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/dbus",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/github.com/godbus/dbus:go_default_library"],
)

View File

@ -25,21 +25,16 @@ import (
)
const (
DBusNameFlagAllowReplacement uint32 = 1 << (iota + 1)
DBusNameFlagReplaceExisting
DBusNameFlagDoNotQueue
DBusNameFlagDoNotQueue uint32 = 1 << (iota + 1)
)
const (
DBusRequestNameReplyPrimaryOwner uint32 = iota + 1
DBusRequestNameReplyInQueue
DBusRequestNameReplyExists
DBusRequestNameReplyAlreadyOwner
)
const (
DBusReleaseNameReplyReleased uint32 = iota + 1
DBusReleaseNameReplyNonExistent
DBusReleaseNameReplyNotOwner
)

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["ebtables_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/ebtables",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/utils/exec:go_default_library",
"//vendor/k8s.io/utils/exec/testing:go_default_library",

View File

@ -15,8 +15,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["env_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/env",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
)

View File

@ -28,8 +28,7 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["file_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/file",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/github.com/spf13/afero:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -70,7 +70,7 @@ func TestFileUtils(t *testing.T) {
t.Fatal("Failed to test: failed to change work dir.")
}
// recover test enviroment
// recover test environment
defer RecoverEnv(currentDir, tmpDir)
t.Run("TestFileExists", func(t *testing.T) {

29
vendor/k8s.io/kubernetes/pkg/util/flag/BUILD generated vendored Normal file
View File

@ -0,0 +1,29 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["flags.go"],
importpath = "k8s.io/kubernetes/pkg/util/flag",
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)

29
vendor/k8s.io/kubernetes/pkg/util/flag/flags.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
/*
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 flag
import (
"github.com/golang/glog"
"github.com/spf13/pflag"
)
// PrintFlags logs the flags in the flagset
func PrintFlags(flags *pflag.FlagSet) {
flags.VisitAll(func(flag *pflag.Flag) {
glog.V(1).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
})
}

View File

@ -7,23 +7,60 @@ load(
go_library(
name = "go_default_library",
srcs = [
"flock_other.go",
] + select({
"@io_bazel_rules_go//go/platform:darwin_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"flock_other.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:dragonfly": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"flock_other.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"flock_unix.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"flock_other.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"flock_other.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"flock_other.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/flock",
deps = select({
"@io_bazel_rules_go//go/platform:darwin_amd64": [
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"//conditions:default": [],

View File

@ -20,8 +20,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["goroutinemap_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/goroutinemap",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library"],
)

View File

@ -24,27 +24,12 @@ package goroutinemap
import (
"fmt"
"sync"
"time"
"github.com/golang/glog"
k8sRuntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
)
const (
// initialDurationBeforeRetry is the amount of time after an error occurs
// that GoRoutineMap will refuse to allow another operation to start with
// the same operation name (if exponentialBackOffOnError is enabled). Each
// successive error results in a wait 2x times the previous.
initialDurationBeforeRetry = 500 * time.Millisecond
// maxDurationBeforeRetry is the maximum amount of time that
// durationBeforeRetry will grow to due to exponential backoff.
// Value is slightly offset from 2 minutes to make timeouts due to this
// constant recognizable.
maxDurationBeforeRetry = 2*time.Minute + 1*time.Second
)
// GoRoutineMap defines a type that can run named goroutines and track their
// state. It prevents the creation of multiple goroutines with the same name
// and may prevent recreation of a goroutine until after the a backoff time

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["hash_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/hash",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/github.com/davecgh/go-spew/spew:go_default_library"],
)

View File

@ -12,7 +12,10 @@ go_library(
"writer.go",
],
importpath = "k8s.io/kubernetes/pkg/util/io",
deps = ["//vendor/github.com/golang/glog:go_default_library"],
deps = [
"//pkg/util/nsenter:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
],
)
filegroup(

View File

@ -21,7 +21,8 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"k8s.io/kubernetes/pkg/util/nsenter"
"github.com/golang/glog"
)
@ -54,25 +55,20 @@ type NsenterWriter struct{}
// WriteFile calls 'nsenter cat - > <the file>' and 'nsenter chmod' to create a
// file on the host.
func (writer *NsenterWriter) WriteFile(filename string, data []byte, perm os.FileMode) error {
cmd := "nsenter"
baseArgs := []string{
"--mount=/rootfs/proc/1/ns/mnt",
"--",
}
echoArgs := append(baseArgs, "sh", "-c", fmt.Sprintf("cat > %s", filename))
glog.V(5).Infof("Command to write data to file: %v %v", cmd, echoArgs)
command := exec.Command(cmd, echoArgs...)
command.Stdin = bytes.NewBuffer(data)
ne := nsenter.NewNsenter()
echoArgs := []string{"-c", fmt.Sprintf("cat > %s", filename)}
glog.V(5).Infof("nsenter: write data to file %s by nsenter", filename)
command := ne.Exec("sh", echoArgs)
command.SetStdin(bytes.NewBuffer(data))
outputBytes, err := command.CombinedOutput()
if err != nil {
glog.Errorf("Output from writing to %q: %v", filename, string(outputBytes))
return err
}
chmodArgs := append(baseArgs, "chmod", fmt.Sprintf("%o", perm), filename)
glog.V(5).Infof("Command to change permissions to file: %v %v", cmd, chmodArgs)
outputBytes, err = exec.Command(cmd, chmodArgs...).CombinedOutput()
chmodArgs := []string{fmt.Sprintf("%o", perm), filename}
glog.V(5).Infof("nsenter: change permissions of file %s to %s", filename, chmodArgs[0])
outputBytes, err = ne.Exec("chmod", chmodArgs).CombinedOutput()
if err != nil {
glog.Errorf("Output from chmod command: %v", string(outputBytes))
return err

View File

@ -22,8 +22,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["ipconfig_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/ipconfig",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/utils/exec:go_default_library"],
)

View File

@ -8,14 +8,16 @@ go_library(
],
importpath = "k8s.io/kubernetes/pkg/util/ipset",
visibility = ["//visibility:public"],
deps = ["//vendor/k8s.io/utils/exec:go_default_library"],
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["ipset_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/ipset",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",

8
vendor/k8s.io/kubernetes/pkg/util/ipset/OWNERS generated vendored Normal file
View File

@ -0,0 +1,8 @@
reviewers:
- thockin
- brendandburns
- m1093782566
approvers:
- thockin
- brendandburns
- m1093782566

View File

@ -19,10 +19,12 @@ package ipset
import (
"bytes"
"fmt"
"net"
"regexp"
"strconv"
"strings"
"github.com/golang/glog"
utilexec "k8s.io/utils/exec"
)
@ -34,10 +36,10 @@ type Interface interface {
DestroySet(set string) error
// DestroyAllSets deletes all sets.
DestroyAllSets() error
// CreateSet creates a new set, it will ignore error when the set already exists if ignoreExistErr=true.
// CreateSet creates a new set. It will ignore error when the set already exists if ignoreExistErr=true.
CreateSet(set *IPSet, ignoreExistErr bool) error
// AddEntry adds a new entry to the named set.
AddEntry(entry string, set string, ignoreExistErr bool) error
// AddEntry adds a new entry to the named set. It will ignore error when the entry already exists if ignoreExistErr=true.
AddEntry(entry string, set *IPSet, ignoreExistErr bool) error
// DelEntry deletes one entry from the named set
DelEntry(entry string, set string) error
// Test test if an entry exists in the named set
@ -85,6 +87,39 @@ type IPSet struct {
MaxElem int
// PortRange specifies the port range of bitmap:port type ipset.
PortRange string
// TODO: add comment message for ipset
}
// Validate checks if a given ipset is valid or not.
func (set *IPSet) Validate() bool {
// Check if protocol is valid for `HashIPPort`, `HashIPPortIP` and `HashIPPortNet` type set.
if set.SetType == HashIPPort || set.SetType == HashIPPortIP || set.SetType == HashIPPortNet {
if valid := validateHashFamily(set.HashFamily); !valid {
return false
}
}
// check set type
if valid := validateIPSetType(set.SetType); !valid {
return false
}
// check port range for bitmap type set
if set.SetType == BitmapPort {
if valid := validatePortRange(set.PortRange); !valid {
return false
}
}
// check hash size value of ipset
if set.HashSize <= 0 {
return false
}
// check max elem value of ipset
if set.MaxElem <= 0 {
glog.Errorf("Invalid maxelem value %d, should be >0", set.MaxElem)
return false
}
return true
}
// Entry represents a ipset entry.
@ -102,10 +137,92 @@ type Entry struct {
Net string
// IP2 is the entry's second IP. IP2 may not be empty for `hash:ip,port,ip` type ip set.
IP2 string
// SetType specifies the type of ip set where the entry exists.
// SetType is the type of ipset where the entry exists.
SetType Type
}
// Validate checks if a given ipset entry is valid or not. The set parameter is the ipset that entry belongs to.
func (e *Entry) Validate(set *IPSet) bool {
if e.Port < 0 {
glog.Errorf("Entry %v port number %d should be >=0 for ipset %v", e, e.Port, set)
return false
}
switch e.SetType {
case HashIPPort:
// set default protocol to tcp if empty
if len(e.Protocol) == 0 {
e.Protocol = ProtocolTCP
}
if net.ParseIP(e.IP) == nil {
glog.Errorf("Error parsing entry %v ip address %v for ipset %v", e, e.IP, set)
return false
}
if valid := validateProtocol(e.Protocol); !valid {
return false
}
case HashIPPortIP:
// set default protocol to tcp if empty
if len(e.Protocol) == 0 {
e.Protocol = ProtocolTCP
}
if net.ParseIP(e.IP) == nil {
glog.Errorf("Error parsing entry %v ip address %v for ipset %v", e, e.IP, set)
return false
}
if valid := validateProtocol(e.Protocol); !valid {
return false
}
// IP2 can not be empty for `hash:ip,port,ip` type ip set
if net.ParseIP(e.IP2) == nil {
glog.Errorf("Error parsing entry %v second ip address %v for ipset %v", e, e.IP2, set)
return false
}
case HashIPPortNet:
// set default protocol to tcp if empty
if len(e.Protocol) == 0 {
e.Protocol = ProtocolTCP
}
if net.ParseIP(e.IP) == nil {
glog.Errorf("Error parsing entry %v ip address %v for ipset %v", e, e.IP, set)
return false
}
if valid := validateProtocol(e.Protocol); !valid {
return false
}
// Net can not be empty for `hash:ip,port,net` type ip set
if _, ipNet, _ := net.ParseCIDR(e.Net); ipNet == nil {
glog.Errorf("Error parsing entry %v ip net %v for ipset %v", e, e.Net, set)
return false
}
case BitmapPort:
// check if port number satisfies its ipset's requirement of port range
if set == nil {
glog.Errorf("Unable to reference ip set where the entry %v exists", e)
return false
}
begin, end, err := parsePortRange(set.PortRange)
if err != nil {
glog.Errorf("Failed to parse set %v port range %s for ipset %v, error: %v", set, set.PortRange, set, err)
return false
}
if e.Port < begin || e.Port > end {
glog.Errorf("Entry %v port number %d is not in the port range %s of its ipset %v", e, e.Port, set.PortRange, set)
return false
}
}
return true
}
// String returns the string format for ipset entry.
func (e *Entry) String() string {
switch e.SetType {
case HashIPPort:
@ -141,28 +258,30 @@ func New(exec utilexec.Interface) Interface {
// CreateSet creates a new set, it will ignore error when the set already exists if ignoreExistErr=true.
func (runner *runner) CreateSet(set *IPSet, ignoreExistErr bool) error {
// Using default values.
// Setting default values if not present
if set.HashSize == 0 {
set.HashSize = 1024
}
if set.MaxElem == 0 {
set.MaxElem = 65536
}
// Default protocol is IPv4
if set.HashFamily == "" {
set.HashFamily = ProtocolFamilyIPV4
}
if len(set.HashFamily) != 0 && set.HashFamily != ProtocolFamilyIPV4 && set.HashFamily != ProtocolFamilyIPV6 {
return fmt.Errorf("Currently supported protocol families are: %s and %s, %s is not supported", ProtocolFamilyIPV4, ProtocolFamilyIPV6, set.HashFamily)
}
// Default ipset type is "hash:ip,port"
if len(set.SetType) == 0 {
set.SetType = HashIPPort
}
// Check if setType is supported
if !IsValidIPSetType(set.SetType) {
return fmt.Errorf("Currently supported ipset types are: %v, %s is not supported", ValidIPSetTypes, set.SetType)
if len(set.PortRange) == 0 {
set.PortRange = DefaultPortRange
}
// Validate ipset before creating
valid := set.Validate()
if !valid {
return fmt.Errorf("error creating ipset since it's invalid")
}
return runner.createSet(set, ignoreExistErr)
}
@ -178,12 +297,6 @@ func (runner *runner) createSet(set *IPSet, ignoreExistErr bool) error {
)
}
if set.SetType == BitmapPort {
if len(set.PortRange) == 0 {
set.PortRange = DefaultPortRange
}
if !validatePortRange(set.PortRange) {
return fmt.Errorf("invalid port range for %s type ip set: %s, expect: a-b", BitmapPort, set.PortRange)
}
args = append(args, "range", set.PortRange)
}
if ignoreExistErr {
@ -198,8 +311,8 @@ func (runner *runner) createSet(set *IPSet, ignoreExistErr bool) error {
// AddEntry adds a new entry to the named set.
// If the -exist option is specified, ipset ignores the error otherwise raised when
// the same set (setname and create parameters are identical) already exists.
func (runner *runner) AddEntry(entry string, set string, ignoreExistErr bool) error {
args := []string{"add", set, entry}
func (runner *runner) AddEntry(entry string, set *IPSet, ignoreExistErr bool) error {
args := []string{"add", set.Name, entry}
if ignoreExistErr {
args = append(args, "-exist")
}
@ -243,8 +356,8 @@ func (runner *runner) FlushSet(set string) error {
// DestroySet is used to destroy a named set.
func (runner *runner) DestroySet(set string) error {
if _, err := runner.exec.Command(IPSetCmd, "destroy", set).CombinedOutput(); err != nil {
return fmt.Errorf("error destroying set %s:, error: %v", set, err)
if out, err := runner.exec.Command(IPSetCmd, "destroy", set).CombinedOutput(); err != nil {
return fmt.Errorf("error destroying set %s, error: %v(%s)", set, err, out)
}
return nil
}
@ -309,17 +422,110 @@ func getIPSetVersionString(exec utilexec.Interface) (string, error) {
return match[0], nil
}
// checks if port range is valid. The begin port number is not necessarily less than
// end port number - ipset util can accept it. It means both 1-100 and 100-1 are valid.
func validatePortRange(portRange string) bool {
strs := strings.Split(portRange, "-")
if len(strs) != 2 {
glog.Errorf("port range should be in the format of `a-b`")
return false
}
for i := range strs {
if _, err := strconv.Atoi(strs[i]); err != nil {
num, err := strconv.Atoi(strs[i])
if err != nil {
glog.Errorf("Failed to parse %s, error: %v", strs[i], err)
return false
}
if num < 0 {
glog.Errorf("port number %d should be >=0", num)
return false
}
}
return true
}
// checks if the given ipset type is valid.
func validateIPSetType(set Type) bool {
for _, valid := range ValidIPSetTypes {
if set == valid {
return true
}
}
glog.Errorf("Currently supported ipset types are: %v, %s is not supported", ValidIPSetTypes, set)
return false
}
// checks if given hash family is supported in ipset
func validateHashFamily(family string) bool {
if family == ProtocolFamilyIPV4 || family == ProtocolFamilyIPV6 {
return true
}
glog.Errorf("Currently supported ip set hash families are: [%s, %s], %s is not supported", ProtocolFamilyIPV4, ProtocolFamilyIPV6, family)
return false
}
// IsNotFoundError returns true if the error indicates "not found". It parses
// the error string looking for known values, which is imperfect but works in
// practice.
func IsNotFoundError(err error) bool {
es := err.Error()
if strings.Contains(es, "does not exist") {
// set with the same name already exists
// xref: https://github.com/Olipro/ipset/blob/master/lib/errcode.c#L32-L33
return true
}
if strings.Contains(es, "element is missing") {
// entry is missing from the set
// xref: https://github.com/Olipro/ipset/blob/master/lib/parse.c#L1904
// https://github.com/Olipro/ipset/blob/master/lib/parse.c#L1925
return true
}
return false
}
// checks if given protocol is supported in entry
func validateProtocol(protocol string) bool {
if protocol == ProtocolTCP || protocol == ProtocolUDP {
return true
}
glog.Errorf("Invalid entry's protocol: %s, supported protocols are [%s, %s]", protocol, ProtocolTCP, ProtocolUDP)
return false
}
// parsePortRange parse the begin and end port from a raw string(format: a-b). beginPort <= endPort
// in the return value.
func parsePortRange(portRange string) (beginPort int, endPort int, err error) {
if len(portRange) == 0 {
portRange = DefaultPortRange
}
strs := strings.Split(portRange, "-")
if len(strs) != 2 {
// port number -1 indicates invalid
return -1, -1, fmt.Errorf("port range should be in the format of `a-b`")
}
for i := range strs {
num, err := strconv.Atoi(strs[i])
if err != nil {
// port number -1 indicates invalid
return -1, -1, err
}
if num < 0 {
// port number -1 indicates invalid
return -1, -1, fmt.Errorf("port number %d should be >=0", num)
}
if i == 0 {
beginPort = num
continue
}
endPort = num
// switch when first port number > second port number
if beginPort > endPort {
endPort = beginPort
beginPort = num
}
}
return beginPort, endPort, nil
}
var _ = Interface(&runner{})

View File

@ -233,6 +233,10 @@ func TestAddEntry(t *testing.T) {
SetType: HashIPPort,
}
testSet := &IPSet{
Name: "FOOBAR",
}
fcmd := fakeexec.FakeCmd{
CombinedOutputScript: []fakeexec.FakeCombinedOutputAction{
// Success
@ -254,7 +258,7 @@ func TestAddEntry(t *testing.T) {
}
runner := New(&fexec)
// Create with ignoreExistErr = false, expect success
err := runner.AddEntry(testEntry.String(), "FOOBAR", false)
err := runner.AddEntry(testEntry.String(), testSet, false)
if err != nil {
t.Errorf("expected success, got %v", err)
}
@ -265,7 +269,7 @@ func TestAddEntry(t *testing.T) {
t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[0])
}
// Create with ignoreExistErr = true, expect success
err = runner.AddEntry(testEntry.String(), "FOOBAR", true)
err = runner.AddEntry(testEntry.String(), testSet, true)
if err != nil {
t.Errorf("expected success, got %v", err)
}
@ -276,7 +280,7 @@ func TestAddEntry(t *testing.T) {
t.Errorf("wrong CombinedOutput() log, got %s", fcmd.CombinedOutputLog[1])
}
// Create with ignoreExistErr = false, expect failure
err = runner.AddEntry(testEntry.String(), "FOOBAR", false)
err = runner.AddEntry(testEntry.String(), testSet, false)
if err == nil {
t.Errorf("expected failure, got nil")
}
@ -308,6 +312,7 @@ func TestDelEntry(t *testing.T) {
},
}
runner := New(&fexec)
err := runner.DelEntry(testEntry.String(), "FOOBAR")
if err != nil {
t.Errorf("expected success, got %v", err)
@ -481,3 +486,817 @@ baz`
t.Errorf("expected sets: %v, got: %v", expected, list)
}
}
func Test_validIPSetType(t *testing.T) {
testCases := []struct {
setType Type
valid bool
}{
{ // case[0]
setType: Type("foo"),
valid: false,
},
{ // case[1]
setType: HashIPPortNet,
valid: true,
},
{ // case[2]
setType: HashIPPort,
valid: true,
},
{ // case[3]
setType: HashIPPortIP,
valid: true,
},
{ // case[4]
setType: BitmapPort,
valid: true,
},
{ // case[5]
setType: Type(""),
valid: false,
},
}
for i := range testCases {
valid := validateIPSetType(testCases[i].setType)
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v]", i, testCases[i].valid, valid)
}
}
}
func Test_validatePortRange(t *testing.T) {
testCases := []struct {
portRange string
valid bool
desc string
}{
{ // case[0]
portRange: "a-b",
valid: false,
desc: "invalid port number",
},
{ // case[1]
portRange: "1-2",
valid: true,
desc: "valid",
},
{ // case[2]
portRange: "90-1",
valid: true,
desc: "ipset util can accept the input of begin port number can be less than end port number",
},
{ // case[3]
portRange: DefaultPortRange,
valid: true,
desc: "default port range is valid, of course",
},
{ // case[4]
portRange: "12",
valid: false,
desc: "a single number is invalid",
},
{ // case[5]
portRange: "1-",
valid: false,
desc: "should specify end port",
},
{ // case[6]
portRange: "-100",
valid: false,
desc: "should specify begin port",
},
{ // case[7]
portRange: "1:100",
valid: false,
desc: "delimiter should be -",
},
{ // case[8]
portRange: "1~100",
valid: false,
desc: "delimiter should be -",
},
{ // case[9]
portRange: "1,100",
valid: false,
desc: "delimiter should be -",
},
{ // case[10]
portRange: "100-100",
valid: true,
desc: "begin port number can be equal to end port number",
},
{ // case[11]
portRange: "",
valid: false,
desc: "empty string is invalid",
},
{ // case[12]
portRange: "-1-12",
valid: false,
desc: "port number can not be negative value",
},
{ // case[13]
portRange: "-1--8",
valid: false,
desc: "port number can not be negative value",
},
}
for i := range testCases {
valid := validatePortRange(testCases[i].portRange)
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v], desc: %s", i, testCases[i].valid, valid, testCases[i].desc)
}
}
}
func Test_validateFamily(t *testing.T) {
testCases := []struct {
family string
valid bool
}{
{ // case[0]
family: "foo",
valid: false,
},
{ // case[1]
family: ProtocolFamilyIPV4,
valid: true,
},
{ // case[2]
family: ProtocolFamilyIPV6,
valid: true,
},
{ // case[3]
family: "ipv4",
valid: false,
},
{ // case[4]
family: "ipv6",
valid: false,
},
{ // case[5]
family: "tcp",
valid: false,
},
{ // case[6]
family: "udp",
valid: false,
},
{ // case[7]
family: "",
valid: false,
},
}
for i := range testCases {
valid := validateHashFamily(testCases[i].family)
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v]", i, testCases[i].valid, valid)
}
}
}
func Test_validateProtocol(t *testing.T) {
testCases := []struct {
protocol string
valid bool
desc string
}{
{ // case[0]
protocol: "foo",
valid: false,
},
{ // case[1]
protocol: ProtocolTCP,
valid: true,
},
{ // case[2]
protocol: ProtocolUDP,
valid: true,
},
{ // case[3]
protocol: "ipv4",
valid: false,
},
{ // case[4]
protocol: "ipv6",
valid: false,
},
{ // case[5]
protocol: "TCP",
valid: false,
desc: "should be low case",
},
{ // case[6]
protocol: "UDP",
valid: false,
desc: "should be low case",
},
{ // case[7]
protocol: "",
valid: false,
},
}
for i := range testCases {
valid := validateProtocol(testCases[i].protocol)
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v], desc: %s", i, testCases[i].valid, valid, testCases[i].desc)
}
}
}
func TestValidateIPSet(t *testing.T) {
testCases := []struct {
ipset *IPSet
valid bool
desc string
}{
{ // case[0]
ipset: &IPSet{
Name: "test",
SetType: HashIPPort,
HashFamily: ProtocolFamilyIPV4,
HashSize: 1024,
MaxElem: 1024,
},
valid: true,
},
{ // case[1]
ipset: &IPSet{
Name: "SET",
SetType: BitmapPort,
HashFamily: ProtocolFamilyIPV6,
HashSize: 65535,
MaxElem: 2048,
PortRange: DefaultPortRange,
},
valid: true,
},
{ // case[2]
ipset: &IPSet{
Name: "foo",
SetType: BitmapPort,
HashFamily: ProtocolFamilyIPV6,
HashSize: 65535,
MaxElem: 2048,
},
valid: false,
desc: "should specify right port range for bitmap type set",
},
{ // case[3]
ipset: &IPSet{
Name: "bar",
SetType: BitmapPort,
HashFamily: ProtocolFamilyIPV6,
HashSize: 0,
MaxElem: 2048,
},
valid: false,
desc: "wrong hash size number",
},
{ // case[4]
ipset: &IPSet{
Name: "baz",
SetType: BitmapPort,
HashFamily: ProtocolFamilyIPV6,
HashSize: 1024,
MaxElem: -1,
},
valid: false,
desc: "wrong hash max elem number",
},
{ // case[5]
ipset: &IPSet{
Name: "baz",
SetType: HashIPPortNet,
HashFamily: "ip",
HashSize: 1024,
MaxElem: 1024,
},
valid: false,
desc: "wrong protocol",
},
{ // case[6]
ipset: &IPSet{
Name: "foo-bar",
SetType: "xxx",
HashFamily: ProtocolFamilyIPV4,
HashSize: 1024,
MaxElem: 1024,
},
valid: false,
desc: "wrong set type",
},
}
for i := range testCases {
valid := testCases[i].ipset.Validate()
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v], desc: %s", i, testCases[i].valid, valid, testCases[i].desc)
}
}
}
func Test_parsePortRange(t *testing.T) {
testCases := []struct {
portRange string
expectErr bool
beginPort int
endPort int
desc string
}{
{ // case[0]
portRange: "1-100",
expectErr: false,
beginPort: 1,
endPort: 100,
},
{ // case[1]
portRange: "0-0",
expectErr: false,
beginPort: 0,
endPort: 0,
},
{ // case[2]
portRange: "100-10",
expectErr: false,
beginPort: 10,
endPort: 100,
},
{ // case[3]
portRange: "1024",
expectErr: true,
desc: "single port number is not allowed",
},
{ // case[4]
portRange: DefaultPortRange,
expectErr: false,
beginPort: 0,
endPort: 65535,
},
{ // case[5]
portRange: "1-",
expectErr: true,
desc: "should specify end port",
},
{ // case[6]
portRange: "-100",
expectErr: true,
desc: "should specify begin port",
},
{ // case[7]
portRange: "1:100",
expectErr: true,
desc: "delimiter should be -",
},
{ // case[8]
portRange: "1~100",
expectErr: true,
desc: "delimiter should be -",
},
{ // case[9]
portRange: "1,100",
expectErr: true,
desc: "delimiter should be -",
},
{ // case[10]
portRange: "100-100",
expectErr: false,
desc: "begin port number can be equal to end port number",
beginPort: 100,
endPort: 100,
},
{ // case[11]
portRange: "",
expectErr: false,
desc: "empty string indicates default port range",
beginPort: 0,
endPort: 65535,
},
{ // case[12]
portRange: "-1-12",
expectErr: true,
desc: "port number can not be negative value",
},
{ // case[13]
portRange: "-1--8",
expectErr: true,
desc: "port number can not be negative value",
},
}
for i := range testCases {
begin, end, err := parsePortRange(testCases[i].portRange)
if err != nil {
if !testCases[i].expectErr {
t.Errorf("case [%d]: unexpected err: %v, desc: %s", i, err, testCases[i].desc)
}
continue
}
if begin != testCases[i].beginPort || end != testCases[i].endPort {
t.Errorf("case [%d]: unexpected mismatch [beginPort, endPort] pair, expect [%d, %d], got [%d, %d], desc: %s", i, testCases[i].beginPort, testCases[i].endPort, begin, end, testCases[i].desc)
}
}
}
// This is a coarse test, but it offers some modicum of confidence as the code is evolved.
func TestValidateEntry(t *testing.T) {
testCases := []struct {
entry *Entry
set *IPSet
valid bool
desc string
}{
{ // case[0]
entry: &Entry{
SetType: BitmapPort,
},
set: &IPSet{
PortRange: DefaultPortRange,
},
valid: true,
desc: "port number can be empty, default is 0. And port number is in the range of its ipset's port range",
},
{ // case[1]
entry: &Entry{
SetType: BitmapPort,
Port: 0,
},
set: &IPSet{
PortRange: DefaultPortRange,
},
valid: true,
desc: "port number can be 0. And port number is in the range of its ipset's port range",
},
{ // case[2]
entry: &Entry{
SetType: BitmapPort,
Port: -1,
},
valid: false,
desc: "port number can not be negative value",
},
{ // case[3]
entry: &Entry{
SetType: BitmapPort,
Port: 1080,
},
set: &IPSet{
Name: "baz",
PortRange: DefaultPortRange,
},
desc: "port number is in the range of its ipset's port range",
valid: true,
},
{ // case[4]
entry: &Entry{
SetType: BitmapPort,
Port: 1080,
},
set: &IPSet{
Name: "foo",
PortRange: "0-1079",
},
desc: "port number is NOT in the range of its ipset's port range",
valid: false,
},
{ // case[5]
entry: &Entry{
SetType: HashIPPort,
IP: "1.2.3.4",
Protocol: ProtocolTCP,
Port: 8080,
},
set: &IPSet{
Name: "bar",
},
valid: true,
},
{ // case[6]
entry: &Entry{
SetType: HashIPPort,
IP: "1.2.3.4",
Protocol: ProtocolUDP,
Port: 0,
},
set: &IPSet{
Name: "bar",
},
valid: true,
},
{ // case[7]
entry: &Entry{
SetType: HashIPPort,
IP: "FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
Protocol: ProtocolTCP,
Port: 1111,
},
set: &IPSet{
Name: "ipv6",
},
valid: true,
},
{ // case[8]
entry: &Entry{
SetType: HashIPPort,
IP: "",
Protocol: ProtocolTCP,
Port: 1234,
},
set: &IPSet{
Name: "empty-ip",
},
valid: false,
},
{ // case[9]
entry: &Entry{
SetType: HashIPPort,
IP: "1-2-3-4",
Protocol: ProtocolTCP,
Port: 8900,
},
set: &IPSet{
Name: "bad-ip",
},
valid: false,
},
{ // case[10]
entry: &Entry{
SetType: HashIPPort,
IP: "10.20.30.40",
Protocol: "",
Port: 8090,
},
set: &IPSet{
Name: "empty-protocol",
},
valid: true,
},
{ // case[11]
entry: &Entry{
SetType: HashIPPort,
IP: "10.20.30.40",
Protocol: "ICMP",
Port: 8090,
},
set: &IPSet{
Name: "unsupported-protocol",
},
valid: false,
},
{ // case[11]
entry: &Entry{
SetType: HashIPPort,
IP: "10.20.30.40",
Protocol: "ICMP",
Port: -1,
},
set: &IPSet{
// TODO: set name string with white space?
Name: "negative-port-number",
},
valid: false,
},
{ // case[12]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: ProtocolUDP,
Port: 53,
IP2: "10.20.30.40",
},
set: &IPSet{
Name: "LOOP-BACK",
},
valid: true,
},
{ // case[13]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: ProtocolUDP,
Port: 53,
IP2: "",
},
set: &IPSet{
Name: "empty IP2",
},
valid: false,
},
{ // case[14]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: ProtocolUDP,
Port: 53,
IP2: "foo",
},
set: &IPSet{
Name: "invalid IP2",
},
valid: false,
},
{ // case[15]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: ProtocolTCP,
Port: 0,
IP2: "1.2.3.4",
},
set: &IPSet{
Name: "zero port",
},
valid: true,
},
{ // case[16]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10::40",
Protocol: ProtocolTCP,
Port: 10000,
IP2: "1::4",
},
set: &IPSet{
Name: "IPV6",
// TODO: check set's hash family
},
valid: true,
},
{ // case[17]
entry: &Entry{
SetType: HashIPPortIP,
IP: "",
Protocol: ProtocolTCP,
Port: 1234,
IP2: "1.2.3.4",
},
set: &IPSet{
Name: "empty-ip",
},
valid: false,
},
{ // case[18]
entry: &Entry{
SetType: HashIPPortIP,
IP: "1-2-3-4",
Protocol: ProtocolTCP,
Port: 8900,
IP2: "10.20.30.41",
},
set: &IPSet{
Name: "bad-ip",
},
valid: false,
},
{ // case[19]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: "SCTP ",
Port: 8090,
IP2: "10.20.30.41",
},
set: &IPSet{
Name: "unsupported-protocol",
},
valid: false,
},
{ // case[20]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: "ICMP",
Port: -1,
IP2: "100.200.30.41",
},
set: &IPSet{
Name: "negative-port-number",
},
valid: false,
},
{ // case[21]
entry: &Entry{
SetType: HashIPPortNet,
IP: "10.20.30.40",
Protocol: ProtocolTCP,
Port: 53,
// TODO: CIDR /32 may not be valid
Net: "10.20.30.0/24",
},
set: &IPSet{
Name: "abc",
},
valid: true,
},
{ // case[22]
entry: &Entry{
SetType: HashIPPortNet,
IP: "11.21.31.41",
Protocol: ProtocolUDP,
Port: 1122,
Net: "",
},
set: &IPSet{
Name: "empty Net",
},
valid: false,
},
{ // case[23]
entry: &Entry{
SetType: HashIPPortNet,
IP: "10.20.30.40",
Protocol: ProtocolUDP,
Port: 8080,
Net: "x-y-z-w",
},
set: &IPSet{
Name: "invalid Net",
},
valid: false,
},
{ // case[24]
entry: &Entry{
SetType: HashIPPortNet,
IP: "10.20.30.40",
Protocol: ProtocolTCP,
Port: 0,
Net: "10.1.0.0/16",
},
set: &IPSet{
Name: "zero port",
},
valid: true,
},
{ // case[25]
entry: &Entry{
SetType: HashIPPortNet,
IP: "10::40",
Protocol: ProtocolTCP,
Port: 80,
Net: "2001:db8::/32",
},
set: &IPSet{
Name: "IPV6",
// TODO: check set's hash family
},
valid: true,
},
{ // case[26]
entry: &Entry{
SetType: HashIPPortNet,
IP: "",
Protocol: ProtocolTCP,
Port: 1234,
Net: "1.2.3.4/22",
},
set: &IPSet{
Name: "empty-ip",
},
valid: false,
},
{ // case[27]
entry: &Entry{
SetType: HashIPPortNet,
IP: "1-2-3-4",
Protocol: ProtocolTCP,
Port: 8900,
Net: "10.20.30.41/31",
},
set: &IPSet{
Name: "bad-ip",
},
valid: false,
},
{ // case[28]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: "FOO",
Port: 8090,
IP2: "10.20.30.0/10",
},
set: &IPSet{
Name: "unsupported-protocol",
},
valid: false,
},
{ // case[29]
entry: &Entry{
SetType: HashIPPortIP,
IP: "10.20.30.40",
Protocol: ProtocolUDP,
Port: -1,
IP2: "100.200.30.0/12",
},
set: &IPSet{
Name: "negative-port-number",
},
valid: false,
},
}
for i := range testCases {
valid := testCases[i].entry.Validate(testCases[i].set)
if valid != testCases[i].valid {
t.Errorf("case [%d]: unexpected mismatch, expect valid[%v], got valid[%v], desc: %s", i, testCases[i].valid, valid, testCases[i].entry)
}
}
}

View File

@ -1,11 +1,14 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["fake.go"],
importpath = "k8s.io/kubernetes/pkg/util/ipset/testing",
visibility = ["//visibility:public"],
deps = ["//pkg/util/ipset:go_default_library"],
deps = [
"//pkg/util/ipset:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)
filegroup(
@ -21,3 +24,13 @@ filegroup(
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["fake_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/util/ipset:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
],
)

View File

@ -17,67 +17,127 @@ limitations under the License.
package testing
import (
"fmt"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/ipset"
)
// FakeIPSet is a no-op implementation of ipset Interface
type FakeIPSet struct {
Lines []byte
// version of ipset util
Version string
// The key of Sets map is the ip set name
Sets map[string]*ipset.IPSet
// The key of Entries map is the ip set name where the entries exists
Entries map[string]sets.String
}
// NewFake create a new fake ipset interface.
func NewFake() *FakeIPSet {
return &FakeIPSet{}
// NewFake create a new fake ipset interface - it initialize the FakeIPSet.
func NewFake(version string) *FakeIPSet {
return &FakeIPSet{
Version: version,
Sets: make(map[string]*ipset.IPSet),
Entries: make(map[string]sets.String),
}
}
// GetVersion is part of interface.
func (*FakeIPSet) GetVersion() (string, error) {
return "0.0", nil
func (f *FakeIPSet) GetVersion() (string, error) {
return f.Version, nil
}
// FlushSet is part of interface.
func (*FakeIPSet) FlushSet(set string) error {
// FlushSet is part of interface. It deletes all entries from a named set but keeps the set itself.
func (f *FakeIPSet) FlushSet(set string) error {
if f.Entries == nil {
return fmt.Errorf("entries map can't be nil")
}
// delete all entry elements
for true {
if _, has := f.Entries[set].PopAny(); has {
continue
}
break
}
return nil
}
// DestroySet is part of interface.
func (*FakeIPSet) DestroySet(set string) error {
// DestroySet is part of interface. It deletes both the entries and the set itself.
func (f *FakeIPSet) DestroySet(set string) error {
delete(f.Sets, set)
delete(f.Entries, set)
return nil
}
// DestroyAllSets is part of interface.
func (*FakeIPSet) DestroyAllSets() error {
func (f *FakeIPSet) DestroyAllSets() error {
f.Sets = nil
f.Entries = nil
return nil
}
// CreateSet is part of interface.
func (*FakeIPSet) CreateSet(set *ipset.IPSet, ignoreExistErr bool) error {
func (f *FakeIPSet) CreateSet(set *ipset.IPSet, ignoreExistErr bool) error {
if f.Sets[set.Name] != nil {
if !ignoreExistErr {
// already exists
return fmt.Errorf("Set cannot be created: set with the same name already exists")
}
return nil
}
f.Sets[set.Name] = set
// initialize entry map
f.Entries[set.Name] = sets.NewString()
return nil
}
// AddEntry is part of interface.
func (*FakeIPSet) AddEntry(entry string, set string, ignoreExistErr bool) error {
func (f *FakeIPSet) AddEntry(entry string, set *ipset.IPSet, ignoreExistErr bool) error {
if f.Entries[set.Name].Has(entry) {
if !ignoreExistErr {
// already exists
return fmt.Errorf("Element cannot be added to the set: it's already added")
}
return nil
}
f.Entries[set.Name].Insert(entry)
return nil
}
// DelEntry is part of interface.
func (*FakeIPSet) DelEntry(entry string, set string) error {
func (f *FakeIPSet) DelEntry(entry string, set string) error {
if f.Entries == nil {
return fmt.Errorf("entries map can't be nil")
}
f.Entries[set].Delete(entry)
return nil
}
// TestEntry is part of interface.
func (*FakeIPSet) TestEntry(entry string, set string) (bool, error) {
return true, nil
func (f *FakeIPSet) TestEntry(entry string, set string) (bool, error) {
if f.Entries == nil {
return false, fmt.Errorf("entries map can't be nil")
}
found := f.Entries[set].Has(entry)
return found, nil
}
// ListEntries is part of interface.
func (*FakeIPSet) ListEntries(set string) ([]string, error) {
return nil, nil
func (f *FakeIPSet) ListEntries(set string) ([]string, error) {
if f.Entries == nil {
return nil, fmt.Errorf("entries map can't be nil")
}
return f.Entries[set].UnsortedList(), nil
}
// ListSets is part of interface.
func (*FakeIPSet) ListSets() ([]string, error) {
return nil, nil
func (f *FakeIPSet) ListSets() ([]string, error) {
res := []string{}
for set := range f.Sets {
res = append(res, set)
}
return res, nil
}
var _ = ipset.Interface(&FakeIPSet{})

View File

@ -0,0 +1,152 @@
/*
Copyright 2017 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 (
"testing"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/ipset"
)
const testVersion = "v6.19"
func TestSetEntry(t *testing.T) {
fake := NewFake(testVersion)
version, err := fake.GetVersion()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if version != testVersion {
t.Errorf("Unexpected version mismatch, expected: %s, got: %s", testVersion, version)
}
// create a set
set := &ipset.IPSet{
Name: "foo",
SetType: ipset.HashIPPort,
HashFamily: ipset.ProtocolFamilyIPV4,
}
if err := fake.CreateSet(set, true); err != nil {
t.Errorf("Unexpected error: %v", err)
}
// add two entries
fake.AddEntry("192.168.1.1,tcp:8080", set, true)
fake.AddEntry("192.168.1.2,tcp:8081", set, true)
entries, err := fake.ListEntries(set.Name)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(entries) != 2 {
t.Errorf("Expected 2 entries, got %d", len(entries))
}
expectedEntries := sets.NewString("192.168.1.1,tcp:8080", "192.168.1.2,tcp:8081")
if !expectedEntries.Equal(sets.NewString(entries...)) {
t.Errorf("Unexpected entries mismatch, expected: %v, got: %v", expectedEntries, entries)
}
// test entries
found, err := fake.TestEntry("192.168.1.1,tcp:8080", set.Name)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if !found {
t.Errorf("Unexpected entry 192.168.1.1,tcp:8080 not found")
}
found, err = fake.TestEntry("192.168.1.2,tcp:8081", set.Name)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if !found {
t.Errorf("Unexpected entry 192.168.1.2,tcp:8081 not found")
}
// delete entry from a given set
if err := fake.DelEntry("192.168.1.1,tcp:8080", set.Name); err != nil {
t.Errorf("Unexpected error: %v", err)
}
entries, err = fake.ListEntries(set.Name)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(entries) != 1 {
t.Errorf("Expected 1 entries, got %d", len(entries))
}
expectedEntries = sets.NewString("192.168.1.2,tcp:8081")
if !expectedEntries.Equal(sets.NewString(entries...)) {
t.Errorf("Unexpected entries mismatch, expected: %v, got: %v", expectedEntries, entries)
}
// Flush set
if err := fake.FlushSet(set.Name); err != nil {
t.Errorf("Unexpected error: %v", err)
}
entries, err = fake.ListEntries(set.Name)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(entries) != 0 {
t.Errorf("Expected 0 entries, got %d, entries: %v", len(entries), entries)
}
// create another set
set2 := &ipset.IPSet{
Name: "bar",
SetType: ipset.HashIPPortIP,
HashFamily: ipset.ProtocolFamilyIPV6,
}
if err := fake.CreateSet(set2, true); err != nil {
t.Errorf("Unexpected error: %v", err)
}
setList, err := fake.ListSets()
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(setList) != 2 {
t.Errorf("Expected 2 sets, got %d", len(setList))
}
expectedSets := sets.NewString("foo", "bar")
if !expectedSets.Equal(sets.NewString(setList...)) {
t.Errorf("Unexpected sets mismatch, expected: %v, got: %v", expectedSets, setList)
}
// Destroy a given set
if err := fake.DestroySet(set.Name); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if fake.Sets[set.Name] != nil {
t.Errorf("Unexpected set: %v", fake.Sets[set.Name])
}
if fake.Entries[set.Name] != nil {
t.Errorf("Unexpected entries: %v", fake.Entries[set.Name])
}
// Destroy all sets
if err := fake.DestroyAllSets(); err != nil {
t.Errorf("Unexpected error: %v", err)
}
if len(fake.Sets) != 0 {
t.Errorf("Expected 0 sets, got %d, sets: %v", len(fake.Sets), fake.Sets)
}
if len(fake.Entries) != 0 {
t.Errorf("Expected 0 entries, got %d, entries: %v", len(fake.Entries), fake.Entries)
}
}
// TODO: Test ignoreExistErr=false

View File

@ -58,13 +58,3 @@ var ValidIPSetTypes = []Type{
BitmapPort,
HashIPPortNet,
}
// IsValidIPSetType checks if the given ipset type is valid.
func IsValidIPSetType(set Type) bool {
for _, valid := range ValidIPSetTypes {
if set == valid {
return true
}
}
return false
}

View File

@ -11,12 +11,41 @@ go_library(
srcs = [
"doc.go",
"iptables.go",
"iptables_unsupported.go",
"save_restore.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"iptables_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"iptables_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"iptables_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/iptables",
@ -28,7 +57,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
@ -40,15 +69,14 @@ go_library(
go_test(
name = "go_default_test",
srcs = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"iptables_test.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/iptables",
library = ":go_default_library",
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/util/dbus:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",

View File

@ -2,8 +2,8 @@ reviewers:
- dcbw
- thockin
- eparis
- danwinship
approvers:
- dcbw
- thockin
- eparis

View File

@ -97,8 +97,8 @@ func (*FakeIPTables) AddReloadFunc(reloadFunc func()) {}
func (*FakeIPTables) Destroy() {}
func getToken(line, seperator string) string {
tokens := strings.Split(line, seperator)
func getToken(line, separator string) string {
tokens := strings.Split(line, separator)
if len(tokens) == 2 {
return strings.Split(tokens[1], " ")[0]
}

View File

@ -11,15 +11,14 @@ go_test(
srcs = [
"ipvs_test.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"ipvs_linux_test.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/ipvs",
library = ":go_default_library",
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/docker/libnetwork/ipvs:go_default_library",
],
"//conditions:default": [],
@ -30,20 +29,78 @@ go_library(
name = "go_default_library",
srcs = [
"ipvs.go",
"ipvs_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"ipvs_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"ipvs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"ipvs_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/ipvs",
deps = [
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
deps = select({
"@io_bazel_rules_go//go/platform:android": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/docker/libnetwork/ipvs:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"//conditions:default": [],
}),

7
vendor/k8s.io/kubernetes/pkg/util/ipvs/OWNERS generated vendored Normal file
View File

@ -0,0 +1,7 @@
reviewers:
- thockin
- m1093782566
approvers:
- thockin
- m1093782566

View File

@ -25,83 +25,86 @@ import (
"strings"
"syscall"
"github.com/docker/libnetwork/ipvs"
libipvs "github.com/docker/libnetwork/ipvs"
"github.com/golang/glog"
utilexec "k8s.io/utils/exec"
)
// runner implements Interface.
// runner implements ipvs.Interface.
type runner struct {
exec utilexec.Interface
ipvsHandle *ipvs.Handle
ipvsHandle *libipvs.Handle
}
// Protocol is the IPVS service protocol type
type Protocol uint16
// New returns a new Interface which will call ipvs APIs.
func New(exec utilexec.Interface) Interface {
ihandle, err := ipvs.New("")
handle, err := libipvs.New("")
if err != nil {
glog.Errorf("IPVS interface can't be initialized, error: %v", err)
return nil
}
return &runner{
exec: exec,
ipvsHandle: ihandle,
ipvsHandle: handle,
}
}
// AddVirtualServer is part of Interface.
// AddVirtualServer is part of ipvs.Interface.
func (runner *runner) AddVirtualServer(vs *VirtualServer) error {
eSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return err
}
return runner.ipvsHandle.NewService(eSvc)
return runner.ipvsHandle.NewService(svc)
}
// UpdateVirtualServer is part of Interface.
// UpdateVirtualServer is part of ipvs.Interface.
func (runner *runner) UpdateVirtualServer(vs *VirtualServer) error {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return err
}
return runner.ipvsHandle.UpdateService(bSvc)
return runner.ipvsHandle.UpdateService(svc)
}
// DeleteVirtualServer is part of Interface.
// DeleteVirtualServer is part of ipvs.Interface.
func (runner *runner) DeleteVirtualServer(vs *VirtualServer) error {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return err
}
return runner.ipvsHandle.DelService(bSvc)
return runner.ipvsHandle.DelService(svc)
}
// GetVirtualServer is part of Interface.
// GetVirtualServer is part of ipvs.Interface.
func (runner *runner) GetVirtualServer(vs *VirtualServer) (*VirtualServer, error) {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return nil, err
}
ipvsService, err := runner.ipvsHandle.GetService(bSvc)
ipvsSvc, err := runner.ipvsHandle.GetService(svc)
if err != nil {
return nil, err
}
virtualServer, err := toVirtualServer(ipvsService)
vServ, err := toVirtualServer(ipvsSvc)
if err != nil {
return nil, err
}
return virtualServer, nil
return vServ, nil
}
// GetVirtualServers is part of Interface.
// GetVirtualServers is part of ipvs.Interface.
func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) {
ipvsServices, err := runner.ipvsHandle.GetServices()
ipvsSvcs, err := runner.ipvsHandle.GetServices()
if err != nil {
return nil, err
}
vss := make([]*VirtualServer, 0)
for _, ipvsService := range ipvsServices {
vs, err := toVirtualServer(ipvsService)
for _, ipvsSvc := range ipvsSvcs {
vs, err := toVirtualServer(ipvsSvc)
if err != nil {
return nil, err
}
@ -110,61 +113,61 @@ func (runner *runner) GetVirtualServers() ([]*VirtualServer, error) {
return vss, nil
}
// Flush is part of Interface. Currently we delete IPVS services one by one
// Flush is part of ipvs.Interface. Currently we delete IPVS services one by one
func (runner *runner) Flush() error {
return runner.ipvsHandle.Flush()
}
// AddRealServer is part of Interface.
// AddRealServer is part of ipvs.Interface.
func (runner *runner) AddRealServer(vs *VirtualServer, rs *RealServer) error {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return err
}
bDst, err := toBackendDestination(rs)
dst, err := toIPVSDestination(rs)
if err != nil {
return err
}
return runner.ipvsHandle.NewDestination(bSvc, bDst)
return runner.ipvsHandle.NewDestination(svc, dst)
}
// DeleteRealServer is part of Interface.
// DeleteRealServer is part of ipvs.Interface.
func (runner *runner) DeleteRealServer(vs *VirtualServer, rs *RealServer) error {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return err
}
bDst, err := toBackendDestination(rs)
dst, err := toIPVSDestination(rs)
if err != nil {
return err
}
return runner.ipvsHandle.DelDestination(bSvc, bDst)
return runner.ipvsHandle.DelDestination(svc, dst)
}
// GetRealServers is part of Interface.
// GetRealServers is part of ipvs.Interface.
func (runner *runner) GetRealServers(vs *VirtualServer) ([]*RealServer, error) {
bSvc, err := toBackendService(vs)
svc, err := toIPVSService(vs)
if err != nil {
return nil, err
}
bDestinations, err := runner.ipvsHandle.GetDestinations(bSvc)
dsts, err := runner.ipvsHandle.GetDestinations(svc)
if err != nil {
return nil, err
}
realServers := make([]*RealServer, 0)
for _, dest := range bDestinations {
dst, err := toRealServer(dest)
rss := make([]*RealServer, 0)
for _, dst := range dsts {
dst, err := toRealServer(dst)
// TODO: aggregate errors?
if err != nil {
return nil, err
}
realServers = append(realServers, dst)
rss = append(rss, dst)
}
return realServers, nil
return rss, nil
}
// toVirtualServer converts an IPVS service representation to the equivalent virtual server structure.
func toVirtualServer(svc *ipvs.Service) (*VirtualServer, error) {
// toVirtualServer converts an IPVS Service to the equivalent VirtualServer structure.
func toVirtualServer(svc *libipvs.Service) (*VirtualServer, error) {
if svc == nil {
return nil, errors.New("ipvs svc should not be empty")
}
@ -172,7 +175,7 @@ func toVirtualServer(svc *ipvs.Service) (*VirtualServer, error) {
Address: svc.Address,
Port: svc.Port,
Scheduler: svc.SchedName,
Protocol: protocolNumbeToString(ProtoType(svc.Protocol)),
Protocol: protocolToString(Protocol(svc.Protocol)),
Timeout: svc.Timeout,
}
@ -194,8 +197,8 @@ func toVirtualServer(svc *ipvs.Service) (*VirtualServer, error) {
return vs, nil
}
// toRealServer converts an IPVS destination representation to the equivalent real server structure.
func toRealServer(dst *ipvs.Destination) (*RealServer, error) {
// toRealServer converts an IPVS Destination to the equivalent RealServer structure.
func toRealServer(dst *libipvs.Destination) (*RealServer, error) {
if dst == nil {
return nil, errors.New("ipvs destination should not be empty")
}
@ -206,14 +209,14 @@ func toRealServer(dst *ipvs.Destination) (*RealServer, error) {
}, nil
}
// toBackendService converts an IPVS real server representation to the equivalent "backend" service structure.
func toBackendService(vs *VirtualServer) (*ipvs.Service, error) {
// toIPVSService converts a VirtualServer to the equivalent IPVS Service structure.
func toIPVSService(vs *VirtualServer) (*libipvs.Service, error) {
if vs == nil {
return nil, errors.New("virtual server should not be empty")
}
bakSvc := &ipvs.Service{
ipvsSvc := &libipvs.Service{
Address: vs.Address,
Protocol: stringToProtocolNumber(vs.Protocol),
Protocol: stringToProtocol(vs.Protocol),
Port: vs.Port,
SchedName: vs.Scheduler,
Flags: uint32(vs.Flags),
@ -221,29 +224,29 @@ func toBackendService(vs *VirtualServer) (*ipvs.Service, error) {
}
if ip4 := vs.Address.To4(); ip4 != nil {
bakSvc.AddressFamily = syscall.AF_INET
bakSvc.Netmask = 0xffffffff
ipvsSvc.AddressFamily = syscall.AF_INET
ipvsSvc.Netmask = 0xffffffff
} else {
bakSvc.AddressFamily = syscall.AF_INET6
bakSvc.Netmask = 128
ipvsSvc.AddressFamily = syscall.AF_INET6
ipvsSvc.Netmask = 128
}
return bakSvc, nil
return ipvsSvc, nil
}
// toBackendDestination converts an IPVS real server representation to the equivalent "backend" destination structure.
func toBackendDestination(rs *RealServer) (*ipvs.Destination, error) {
// toIPVSDestination converts a RealServer to the equivalent IPVS Destination structure.
func toIPVSDestination(rs *RealServer) (*libipvs.Destination, error) {
if rs == nil {
return nil, errors.New("real server should not be empty")
}
return &ipvs.Destination{
return &libipvs.Destination{
Address: rs.Address,
Port: rs.Port,
Weight: rs.Weight,
}, nil
}
// stringToProtocolNumber returns the protocol value for the given name
func stringToProtocolNumber(protocol string) uint16 {
// stringToProtocolType returns the protocol type for the given name
func stringToProtocol(protocol string) uint16 {
switch strings.ToLower(protocol) {
case "tcp":
return uint16(syscall.IPPROTO_TCP)
@ -253,8 +256,8 @@ func stringToProtocolNumber(protocol string) uint16 {
return uint16(0)
}
// protocolNumbeToString returns the name for the given protocol value.
func protocolNumbeToString(proto ProtoType) string {
// protocolTypeToString returns the name for the given protocol.
func protocolToString(proto Protocol) string {
switch proto {
case syscall.IPPROTO_TCP:
return "TCP"
@ -263,6 +266,3 @@ func protocolNumbeToString(proto ProtoType) string {
}
return ""
}
// ProtoType is IPVS service protocol type
type ProtoType uint16

View File

@ -25,18 +25,18 @@ import (
"syscall"
"testing"
"github.com/docker/libnetwork/ipvs"
libipvs "github.com/docker/libnetwork/ipvs"
)
func Test_toVirtualServer(t *testing.T) {
Tests := []struct {
ipvsService ipvs.Service
ipvsService libipvs.Service
virtualServer VirtualServer
expectError bool
reason string
}{
{
ipvs.Service{
libipvs.Service{
Flags: 0x0,
},
VirtualServer{},
@ -44,7 +44,7 @@ func Test_toVirtualServer(t *testing.T) {
fmt.Sprintf("IPVS Service Flags should be >= %d, got 0x0", FlagHashed),
},
{
ipvs.Service{
libipvs.Service{
Flags: 0x1,
},
VirtualServer{},
@ -52,7 +52,7 @@ func Test_toVirtualServer(t *testing.T) {
fmt.Sprintf("IPVS Service Flags should be >= %d, got 0x1", FlagHashed),
},
{
ipvs.Service{
libipvs.Service{
Protocol: syscall.IPPROTO_TCP,
Port: 80,
FWMark: 0,
@ -76,7 +76,7 @@ func Test_toVirtualServer(t *testing.T) {
"",
},
{
ipvs.Service{
libipvs.Service{
Protocol: syscall.IPPROTO_UDP,
Port: 33434,
FWMark: 0,
@ -100,7 +100,7 @@ func Test_toVirtualServer(t *testing.T) {
"",
},
{
ipvs.Service{
libipvs.Service{
Protocol: 0,
Port: 0,
FWMark: 0,
@ -124,7 +124,7 @@ func Test_toVirtualServer(t *testing.T) {
"",
},
{
ipvs.Service{
libipvs.Service{
Protocol: 0,
Port: 0,
FWMark: 0,
@ -165,13 +165,13 @@ func Test_toVirtualServer(t *testing.T) {
}
}
func Test_toBackendService(t *testing.T) {
func Test_toIPVSService(t *testing.T) {
Tests := []struct {
ipvsService ipvs.Service
ipvsService libipvs.Service
virtualServer VirtualServer
}{
{
ipvs.Service{
libipvs.Service{
Protocol: syscall.IPPROTO_TCP,
Port: 80,
FWMark: 0,
@ -193,7 +193,7 @@ func Test_toBackendService(t *testing.T) {
},
},
{
ipvs.Service{
libipvs.Service{
Protocol: syscall.IPPROTO_UDP,
Port: 33434,
FWMark: 0,
@ -215,7 +215,7 @@ func Test_toBackendService(t *testing.T) {
},
},
{
ipvs.Service{
libipvs.Service{
Protocol: 0,
Port: 0,
FWMark: 0,
@ -237,7 +237,7 @@ func Test_toBackendService(t *testing.T) {
},
},
{
ipvs.Service{
libipvs.Service{
Protocol: 0,
Port: 0,
FWMark: 0,
@ -261,7 +261,7 @@ func Test_toBackendService(t *testing.T) {
}
for i := range Tests {
got, err := toBackendService(&Tests[i].virtualServer)
got, err := toIPVSService(&Tests[i].virtualServer)
if err != nil {
t.Errorf("case: %d, unexpected error: %v", i, err)
}
@ -271,13 +271,13 @@ func Test_toBackendService(t *testing.T) {
}
}
func Test_toFrontendDestination(t *testing.T) {
func Test_toRealServer(t *testing.T) {
Tests := []struct {
ipvsDestination ipvs.Destination
ipvsDestination libipvs.Destination
realServer RealServer
}{
{
ipvs.Destination{
libipvs.Destination{
Port: 54321,
ConnectionFlags: 0,
Weight: 1,
@ -290,7 +290,7 @@ func Test_toFrontendDestination(t *testing.T) {
},
},
{
ipvs.Destination{
libipvs.Destination{
Port: 53,
ConnectionFlags: 0,
Weight: 1,
@ -314,10 +314,10 @@ func Test_toFrontendDestination(t *testing.T) {
}
}
func Test_toBackendDestination(t *testing.T) {
func Test_toIPVSDestination(t *testing.T) {
Tests := []struct {
realServer RealServer
ipvsDestination ipvs.Destination
ipvsDestination libipvs.Destination
}{
{
RealServer{
@ -325,7 +325,7 @@ func Test_toBackendDestination(t *testing.T) {
Port: 54321,
Weight: 1,
},
ipvs.Destination{
libipvs.Destination{
Port: 54321,
ConnectionFlags: 0,
Weight: 1,
@ -338,7 +338,7 @@ func Test_toBackendDestination(t *testing.T) {
Port: 53,
Weight: 1,
},
ipvs.Destination{
libipvs.Destination{
Port: 53,
ConnectionFlags: 0,
Weight: 1,
@ -347,44 +347,44 @@ func Test_toBackendDestination(t *testing.T) {
},
}
for i := range Tests {
got, err := toBackendDestination(&Tests[i].realServer)
got, err := toIPVSDestination(&Tests[i].realServer)
if err != nil {
t.Errorf("case %d unexpected error: %d", i, err)
}
if !reflect.DeepEqual(*got, Tests[i].ipvsDestination) {
t.Errorf("case %d Failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].ipvsDestination)
t.Errorf("case %d failed to translate Destination - got %#v, want %#v", i, *got, Tests[i].ipvsDestination)
}
}
}
func Test_stringToProtocolNumber(t *testing.T) {
func Test_stringToProtocol(t *testing.T) {
tests := []string{
"TCP", "UDP", "ICMP",
}
expecteds := []uint16{
expected := []uint16{
uint16(syscall.IPPROTO_TCP), uint16(syscall.IPPROTO_UDP), uint16(0),
}
for i := range tests {
got := stringToProtocolNumber(tests[i])
if got != expecteds[i] {
t.Errorf("stringToProtocolNumber() failed - got %#v, want %#v",
got, expecteds[i])
got := stringToProtocol(tests[i])
if got != expected[i] {
t.Errorf("stringToProtocol() failed - got %#v, want %#v",
got, expected[i])
}
}
}
func Test_protocolNumberToString(t *testing.T) {
tests := []ProtoType{
syscall.IPPROTO_TCP, syscall.IPPROTO_UDP, ProtoType(0),
func Test_protocolToString(t *testing.T) {
tests := []Protocol{
syscall.IPPROTO_TCP, syscall.IPPROTO_UDP, Protocol(0),
}
expecteds := []string{
expected := []string{
"TCP", "UDP", "",
}
for i := range tests {
got := protocolNumbeToString(tests[i])
if got != expecteds[i] {
t.Errorf("protocolNumbeToString() failed - got %#v, want %#v",
got, expecteds[i])
got := protocolToString(tests[i])
if got != expected[i] {
t.Errorf("protocolToString() failed - got %#v, want %#v",
got, expected[i])
}
}
}

View File

@ -29,7 +29,6 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["fake_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/ipvs/testing",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//pkg/util/ipvs:go_default_library"],
)

View File

@ -18,6 +18,8 @@ package testing
import (
"fmt"
"net"
"strconv"
utilipvs "k8s.io/kubernetes/pkg/util/ipvs"
)
@ -39,6 +41,15 @@ func (s *serviceKey) String() string {
return fmt.Sprintf("%s:%d/%s", s.IP, s.Port, s.Protocol)
}
type realServerKey struct {
Address net.IP
Port uint16
}
func (r *realServerKey) String() string {
return net.JoinHostPort(r.Address.String(), strconv.Itoa(int(r.Port)))
}
//NewFake creates a fake ipvs implementation - a cache store.
func NewFake() *FakeIPVS {
return &FakeIPVS{
@ -55,6 +66,13 @@ func toServiceKey(serv *utilipvs.VirtualServer) serviceKey {
}
}
func toRealServerKey(rs *utilipvs.RealServer) *realServerKey {
return &realServerKey{
Address: rs.Address,
Port: rs.Port,
}
}
//AddVirtualServer is a fake implementation, it simply adds the VirtualServer into the cache store.
func (f *FakeIPVS) AddVirtualServer(serv *utilipvs.VirtualServer) error {
if serv == nil {
@ -159,18 +177,19 @@ func (f *FakeIPVS) DeleteRealServer(serv *utilipvs.VirtualServer, dest *utilipvs
return fmt.Errorf("Failed to delete destination for service %v, service not found", key.String())
}
dests := f.Destinations[key]
var i int
for i = range dests {
if dests[i].Equal(dest) {
exist := false
for i := range dests {
if toRealServerKey(dests[i]).String() == toRealServerKey(dest).String() {
// Delete one element
f.Destinations[key] = append(f.Destinations[key][:i], f.Destinations[key][i+1:]...)
exist = true
break
}
}
// Not Found
if i >= len(f.Destinations[key]) {
if !exist {
return fmt.Errorf("Failed to delete real server for service %v, real server not found", key.String())
}
// Delete one element
f.Destinations[key] = append(f.Destinations[key][:i], f.Destinations[key][i+1:]...)
return nil
}

View File

@ -35,12 +35,12 @@ func TestVirtualServer(t *testing.T) {
}
err := fake.AddVirtualServer(vs1)
if err != nil {
t.Errorf("Fail to add virutal server, error: %v", err)
t.Errorf("Fail to add virtual server, error: %v", err)
}
// Get a specific virtual server
got1, err := fake.GetVirtualServer(vs1)
if err != nil {
t.Errorf("Fail to get virutal server, error: %v", err)
t.Errorf("Fail to get virtual server, error: %v", err)
}
if !vs1.Equal(got1) {
t.Errorf("Expect virtual server: %v, got: %v", vs1, got1)
@ -54,12 +54,12 @@ func TestVirtualServer(t *testing.T) {
}
err = fake.UpdateVirtualServer(vs12)
if err != nil {
t.Errorf("Fail to update virutal server, error: %v", err)
t.Errorf("Fail to update virtual server, error: %v", err)
}
// Check the updated virtual server
got12, err := fake.GetVirtualServer(vs1)
if !got12.Equal(vs12) {
t.Errorf("Expect virutal server: %v, got: %v", vs12, got12)
t.Errorf("Expect virtual server: %v, got: %v", vs12, got12)
}
// Add another virtual server
vs2 := &utilipvs.VirtualServer{
@ -69,20 +69,20 @@ func TestVirtualServer(t *testing.T) {
}
err = fake.AddVirtualServer(vs2)
if err != nil {
t.Errorf("Unexpected error when add virutal server, error: %v", err)
t.Errorf("Unexpected error when add virtual server, error: %v", err)
}
// List all virtual servers
list, err := fake.GetVirtualServers()
if err != nil {
t.Errorf("Fail to list virutal servers, error: %v", err)
t.Errorf("Fail to list virtual servers, error: %v", err)
}
if len(list) != 2 {
t.Errorf("Expect 2 virutal servers, got: %d", len(list))
t.Errorf("Expect 2 virtual servers, got: %d", len(list))
}
// Delete a virtual server
err = fake.DeleteVirtualServer(vs1)
if err != nil {
t.Errorf("Fail to delete virutal server: %v, error: %v", vs1, err)
t.Errorf("Fail to delete virtual server: %v, error: %v", vs1, err)
}
// Check the deleted virtual server no longer exists
got, _ := fake.GetVirtualServer(vs1)
@ -92,15 +92,15 @@ func TestVirtualServer(t *testing.T) {
// Flush all virtual servers
err = fake.Flush()
if err != nil {
t.Errorf("Fail to flush virutal servers, error: %v", err)
t.Errorf("Fail to flush virtual servers, error: %v", err)
}
// List all virtual servers
list, err = fake.GetVirtualServers()
if err != nil {
t.Errorf("Fail to list virutal servers, error: %v", err)
t.Errorf("Fail to list virtual servers, error: %v", err)
}
if len(list) != 0 {
t.Errorf("Expect 0 virutal servers, got: %d", len(list))
t.Errorf("Expect 0 virtual servers, got: %d", len(list))
}
}
@ -113,46 +113,59 @@ func TestRealServer(t *testing.T) {
Port: uint16(80),
Protocol: string("TCP"),
}
rss := []*utilipvs.RealServer{
{net.ParseIP("172.16.2.1"), 8080, 1},
{net.ParseIP("172.16.2.2"), 8080, 2},
{net.ParseIP("172.16.2.3"), 8080, 3},
}
err := fake.AddVirtualServer(vs)
if err != nil {
t.Errorf("Fail to add virutal server, error: %v", err)
t.Errorf("Fail to add virtual server, error: %v", err)
}
// Add a real server to the virtual server
rs1 := &utilipvs.RealServer{
Address: net.ParseIP("172.16.2.1"),
// Add real server to the virtual server
for i := range rss {
if err = fake.AddRealServer(vs, rss[i]); err != nil {
t.Errorf("Fail to add real server, error: %v", err)
}
}
// Delete a real server of the virtual server
// Make sure any position of the list can be real deleted
rssLen := len(rss)
for i := range rss {
// List all real servers of the virtual server
list, err := fake.GetRealServers(vs)
if err != nil {
t.Errorf("Fail to get real servers of the virtual server, error: %v", err)
}
if len(list) != rssLen {
t.Errorf("Expect %d virtual servers, got: %d", len(rss), len(list))
}
rsToDel := list[i]
if err = fake.DeleteRealServer(vs, rsToDel); err != nil {
t.Errorf("Fail to delete real server of the virtual server, error: %v", err)
} else {
dests, err := fake.GetRealServers(vs)
if err != nil {
t.Errorf("Fail to get real servers of the virtual server, error: %v", err)
}
for _, dest := range dests {
if toRealServerKey(dest).String() == toRealServerKey(rsToDel).String() {
t.Errorf("Expect real server %q be deleted.", rsToDel.String())
}
}
if err = fake.AddRealServer(vs, rsToDel); err != nil {
t.Errorf("Fail to add real server, error: %v", err)
}
}
}
// Test delete real server that not exist
rs := &utilipvs.RealServer{
Address: net.ParseIP("172.16.2.4"),
Port: uint16(8080),
Weight: 1,
}
err = fake.AddRealServer(vs, rs1)
if err != nil {
t.Errorf("Fail to add real server, error: %v", err)
}
// Add another real server to the virtual server
rs2 := &utilipvs.RealServer{
Address: net.ParseIP("172.16.3.2"),
Port: uint16(8080),
Weight: 2,
}
err = fake.AddRealServer(vs, rs2)
if err != nil {
t.Errorf("Fail to add real server, error: %v", err)
}
// List all real servers of the virtual server
list, err := fake.GetRealServers(vs)
if err != nil {
t.Errorf("Fail to get real servers of the virtual server, error: %v", err)
}
if len(list) != 2 {
t.Errorf("Expect 2 virutal servers, got: %d", len(list))
}
// Delete a real server of the virtual server
err = fake.DeleteRealServer(vs, rs2)
list, err = fake.GetRealServers(vs)
if err != nil {
t.Errorf("Fail to get real servers of the virtual server, error: %v", err)
}
if len(list) != 1 {
t.Errorf("Expect 1 real server, got: %d", len(list))
if err = fake.DeleteRealServer(vs, rs); err == nil {
t.Errorf("Delete real server that not exist, Expect error, got nil")
}
// Delete the virtual server
err = fake.DeleteVirtualServer(vs)

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["keymutex_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/keymutex",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -19,8 +19,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["labels_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/labels",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library"],
)

View File

@ -18,8 +18,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["limitwriter_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/limitwriter",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -13,7 +13,6 @@ go_library(
deps = [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
],
)
@ -21,8 +20,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["util_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/metrics",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
],

View File

@ -21,7 +21,6 @@ import (
"sync"
"time"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/flowcontrol"
"github.com/golang/glog"
@ -71,11 +70,13 @@ func RegisterMetricAndTrackRateLimiterUsage(ownerName string, rateLimiter flowco
if err := registerRateLimiterMetric(ownerName); err != nil {
return err
}
go wait.Until(func() {
metricsLock.Lock()
defer metricsLock.Unlock()
rateLimiterMetrics[ownerName].metric.Set(rateLimiter.Saturation())
}, updatePeriod, rateLimiterMetrics[ownerName].stopCh)
// TODO: determine how to track rate limiter saturation
// See discussion at https://go-review.googlesource.com/c/time/+/29958#message-4caffc11669cadd90e2da4c05122cfec50ea6a22
// go wait.Until(func() {
// metricsLock.Lock()
// defer metricsLock.Unlock()
// rateLimiterMetrics[ownerName].metric.Set()
// }, updatePeriod, rateLimiterMetrics[ownerName].stopCh)
return nil
}

View File

@ -11,19 +11,63 @@ go_library(
srcs = [
"doc.go",
"exec.go",
"exec_mount_unsupported.go",
"fake.go",
"mount.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"exec_mount.go",
"mount_linux.go",
"nsenter_mount.go",
],
"@io_bazel_rules_go//go/platform:windows_amd64": [
"@io_bazel_rules_go//go/platform:nacl": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"exec_mount_unsupported.go",
"mount_unsupported.go",
"nsenter_mount_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"exec_mount_unsupported.go",
"mount_windows.go",
"nsenter_mount_unsupported.go",
],
"//conditions:default": [],
}),
@ -32,7 +76,7 @@ go_library(
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/util/io:go_default_library",
"//pkg/util/nsenter:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
@ -47,19 +91,20 @@ go_test(
srcs = [
"safe_format_and_mount_test.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"exec_mount_test.go",
"mount_linux_test.go",
"nsenter_mount_test.go",
],
"@io_bazel_rules_go//go/platform:windows_amd64": [
"@io_bazel_rules_go//go/platform:windows": [
"mount_windows_test.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/mount",
library = ":go_default_library",
deps = ["//vendor/k8s.io/utils/exec/testing:go_default_library"],
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/utils/exec/testing:go_default_library",
],
)
filegroup(

View File

@ -1,7 +1,10 @@
reviewers:
- jingxu97
- saad-ali
- jsafrane
- msau42
approvers:
- jingxu97
- saad-ali
- jsafrane

View File

@ -56,7 +56,7 @@ func (m *execMounter) Mount(source string, target string, fstype string, options
return m.doExecMount(source, target, fstype, options)
}
// doExecMount calls exec(mount <waht> <where>) using given exec interface.
// doExecMount calls exec(mount <what> <where>) using given exec interface.
func (m *execMounter) doExecMount(source, target, fstype string, options []string) error {
glog.V(5).Infof("Exec Mounting %s %s %s %v", source, target, fstype, options)
mountArgs := makeMountArgs(source, target, fstype, options)

View File

@ -19,7 +19,9 @@ limitations under the License.
package mount
import (
"os"
"path/filepath"
"strings"
)
type FileType string
@ -124,12 +126,6 @@ type SafeFormatAndMount struct {
// disk is already formatted or it is being mounted as read-only, it
// will be mounted without formatting.
func (mounter *SafeFormatAndMount) FormatAndMount(source string, target string, fstype string, options []string) error {
// Don't attempt to format if mounting as readonly. Go straight to mounting.
for _, option := range options {
if option == "ro" {
return mounter.Interface.Mount(source, target, fstype, options)
}
}
return mounter.formatAndMount(source, target, fstype, options)
}
@ -208,6 +204,12 @@ func IsNotMountPoint(mounter Interface, file string) (bool, error) {
// IsLikelyNotMountPoint provides a quick check
// to determine whether file IS A mountpoint
notMnt, notMntErr := mounter.IsLikelyNotMountPoint(file)
if notMntErr != nil && os.IsPermission(notMntErr) {
// We were not allowed to do the simple stat() check, e.g. on NFS with
// root_squash. Fall back to /proc/mounts check below.
notMnt = true
notMntErr = nil
}
if notMntErr != nil {
return notMnt, notMntErr
}
@ -254,3 +256,21 @@ func isBind(options []string) (bool, []string) {
return bind, bindRemountOpts
}
// TODO: this is a workaround for the unmount device issue caused by gci mounter.
// In GCI cluster, if gci mounter is used for mounting, the container started by mounter
// script will cause additional mounts created in the container. Since these mounts are
// irrelevant to the original mounts, they should be not considered when checking the
// mount references. Current solution is to filter out those mount paths that contain
// the string of original mount path.
// Plan to work on better approach to solve this issue.
func HasMountRefs(mountPath string, mountRefs []string) bool {
count := 0
for _, ref := range mountRefs {
if !strings.Contains(ref, mountPath) {
count = count + 1
}
}
return count > 0
}

View File

@ -19,6 +19,7 @@ limitations under the License.
package mount
import (
"errors"
"fmt"
"os"
"os/exec"
@ -69,7 +70,7 @@ func New(mounterPath string) Interface {
}
// Mount mounts source to target as fstype with given options. 'source' and 'fstype' must
// be an emtpy string in case it's not required, e.g. for remount, or for auto filesystem
// be an empty string in case it's not required, e.g. for remount, or for auto filesystem
// type, where kernel handles fstype for you. The mount 'options' is a list of options,
// currently come from mount(8), e.g. "ro", "remount", "bind", etc. If no more option is
// required, call Mount with an empty string list or nil.
@ -265,7 +266,7 @@ func (mounter *Mounter) IsLikelyNotMountPoint(file string) (bool, error) {
if err != nil {
return true, err
}
rootStat, err := os.Lstat(file + "/..")
rootStat, err := os.Lstat(filepath.Dir(strings.TrimSuffix(file, "/")))
if err != nil {
return true, err
}
@ -313,7 +314,7 @@ func exclusiveOpenFailsOnDevice(pathname string) (bool, error) {
}
if !isDevice {
glog.Errorf("Path %q is not refering to a device.", pathname)
glog.Errorf("Path %q is not referring to a device.", pathname)
return false, nil
}
fd, errno := unix.Open(pathname, unix.O_RDONLY|unix.O_EXCL, 0)
@ -431,7 +432,7 @@ func (mounter *Mounter) GetFileType(pathname string) (FileType, error) {
case syscall.S_IFBLK:
return FileTypeBlockDev, nil
case syscall.S_IFCHR:
return FileTypeBlockDev, nil
return FileTypeCharDev, nil
case syscall.S_IFDIR:
return FileTypeDirectory, nil
case syscall.S_IFREG:
@ -472,23 +473,33 @@ func (mounter *Mounter) ExistsPath(pathname string) bool {
// formatAndMount uses unix utils to format and mount the given disk
func (mounter *SafeFormatAndMount) formatAndMount(source string, target string, fstype string, options []string) error {
readOnly := false
for _, option := range options {
if option == "ro" {
readOnly = true
break
}
}
options = append(options, "defaults")
// Run fsck on the disk to fix repairable issues
glog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
args := []string{"-a", source}
out, err := mounter.Exec.Run("fsck", args...)
if err != nil {
ee, isExitError := err.(utilexec.ExitError)
switch {
case err == utilexec.ErrExecutableNotFound:
glog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
glog.Infof("Device %s has errors which were corrected by fsck.", source)
case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out))
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
glog.Infof("`fsck` error %s", string(out))
if !readOnly {
// Run fsck on the disk to fix repairable issues, only do this for volumes requested as rw.
glog.V(4).Infof("Checking for issues with fsck on disk: %s", source)
args := []string{"-a", source}
out, err := mounter.Exec.Run("fsck", args...)
if err != nil {
ee, isExitError := err.(utilexec.ExitError)
switch {
case err == utilexec.ErrExecutableNotFound:
glog.Warningf("'fsck' not found on system; continuing mount without running 'fsck'.")
case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
glog.Infof("Device %s has errors which were corrected by fsck.", source)
case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s.", source, string(out))
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
glog.Infof("`fsck` error %s", string(out))
}
}
}
@ -503,8 +514,13 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
return err
}
if existingFormat == "" {
if readOnly {
// Don't attempt to format if mounting as readonly, return an error to reflect this.
return errors.New("failed to mount unformatted volume as read only")
}
// Disk is unformatted so format it.
args = []string{source}
args := []string{source}
// Use 'ext4' as the default
if len(fstype) == 0 {
fstype = "ext4"
@ -536,36 +552,57 @@ func (mounter *SafeFormatAndMount) formatAndMount(source string, target string,
return mountErr
}
// GetDiskFormat uses 'lsblk' to see if the given disk is unformated
// GetDiskFormat uses 'blkid' to see if the given disk is unformated
func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
args := []string{"-n", "-o", "FSTYPE", disk}
glog.V(4).Infof("Attempting to determine if disk %q is formatted using lsblk with args: (%v)", disk, args)
dataOut, err := mounter.Exec.Run("lsblk", args...)
args := []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", disk}
glog.V(4).Infof("Attempting to determine if disk %q is formatted using blkid with args: (%v)", disk, args)
dataOut, err := mounter.Exec.Run("blkid", args...)
output := string(dataOut)
glog.V(4).Infof("Output: %q", output)
glog.V(4).Infof("Output: %q, err: %v", output, err)
if err != nil {
if exit, ok := err.(utilexec.ExitError); ok {
if exit.ExitStatus() == 2 {
// Disk device is unformatted.
// For `blkid`, if the specified token (TYPE/PTTYPE, etc) was
// not found, or no (specified) devices could be identified, an
// exit code of 2 is returned.
return "", nil
}
}
glog.Errorf("Could not determine if disk %q is formatted (%v)", disk, err)
return "", err
}
// Split lsblk output into lines. Unformatted devices should contain only
// "\n". Beware of "\n\n", that's a device with one empty partition.
output = strings.TrimSuffix(output, "\n") // Avoid last empty line
var fstype, pttype string
lines := strings.Split(output, "\n")
if lines[0] != "" {
// The device is formatted
return lines[0], nil
for _, l := range lines {
if len(l) <= 0 {
// Ignore empty line.
continue
}
cs := strings.Split(l, "=")
if len(cs) != 2 {
return "", fmt.Errorf("blkid returns invalid output: %s", output)
}
// TYPE is filesystem type, and PTTYPE is partition table type, according
// to https://www.kernel.org/pub/linux/utils/util-linux/v2.21/libblkid-docs/.
if cs[0] == "TYPE" {
fstype = cs[1]
} else if cs[0] == "PTTYPE" {
pttype = cs[1]
}
}
if len(lines) == 1 {
// The device is unformatted and has no dependent devices
return "", nil
if len(pttype) > 0 {
glog.V(4).Infof("Disk %s detected partition table type: %s", pttype)
// Returns a special non-empty string as filesystem type, then kubelet
// will not format it.
return "unknown data, probably partitions", nil
}
// The device has dependent devices, most probably partitions (LVM, LUKS
// and MD RAID are reported as FSTYPE and caught above).
return "unknown data, probably partitions", nil
return fstype, nil
}
// isShared returns true, if given path is on a mount point that has shared

View File

@ -89,10 +89,7 @@ func (mounter *Mounter) Mount(source string, target string, fstype string, optio
cmdLine += fmt.Sprintf(";New-SmbGlobalMapping -RemotePath %s -Credential $Credential", source)
if output, err := exec.Command("powershell", "/c", cmdLine).CombinedOutput(); err != nil {
// we don't return error here, even though New-SmbGlobalMapping failed, we still make it successful,
// will return error when Windows 2016 RS3 is ready on azure
glog.Errorf("azureMount: SmbGlobalMapping failed: %v, only SMB mount is supported now, output: %q", err, string(output))
return os.MkdirAll(target, 0755)
return fmt.Errorf("azureMount: SmbGlobalMapping failed: %v, only SMB mount is supported now, output: %q", err, string(output))
}
}

View File

@ -165,7 +165,7 @@ func (n *NsenterMounter) IsLikelyNotMountPoint(file string) (bool, error) {
glog.V(5).Infof("nsenter findmnt args: %v", args)
out, err := n.ne.Exec("findmnt", args).CombinedOutput()
if err != nil {
glog.V(2).Infof("Failed findmnt command for path %s: %v", file, err)
glog.V(2).Infof("Failed findmnt command for path %s: %s %v", file, out, err)
// Different operating systems behave differently for paths which are not mount points.
// On older versions (e.g. 2.20.1) we'd get error, on newer ones (e.g. 2.26.2) we'd get "/".
// It's safer to assume that it's not a mount point.

View File

@ -100,55 +100,55 @@ func TestSafeFormatAndMount(t *testing.T) {
},
},
{
description: "Test that 'lsblk' is called and fails",
description: "Test that 'blkid' is called and fails",
fstype: "ext4",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "ext4\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "DEVNAME=/dev/foo\nTYPE=ext4\n", nil},
},
expectedError: fmt.Errorf("unknown filesystem type '(null)'"),
},
{
description: "Test that 'lsblk' is called and confirms unformatted disk, format fails",
description: "Test that 'blkid' is called and confirms unformatted disk, format fails",
fstype: "ext4",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", fmt.Errorf("formatting failed")},
},
expectedError: fmt.Errorf("formatting failed"),
},
{
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount fails",
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount fails",
fstype: "ext4",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), fmt.Errorf("Still cannot mount")},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
},
expectedError: fmt.Errorf("Still cannot mount"),
},
{
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes",
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount passes",
fstype: "ext4",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
{"mkfs.ext4", []string{"-F", "/dev/foo"}, "", nil},
},
expectedError: nil,
},
{
description: "Test that 'lsblk' is called and confirms unformatted disk, format passes, second mount passes with ext3",
description: "Test that 'blkid' is called and confirms unformatted disk, format passes, second mount passes with ext3",
fstype: "ext3",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
{"mkfs.ext3", []string{"-F", "/dev/foo"}, "", nil},
},
expectedError: nil,
@ -159,30 +159,31 @@ func TestSafeFormatAndMount(t *testing.T) {
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 2}},
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
},
expectedError: nil,
},
{
description: "Test that 'lsblk' is called and reports ext4 partition",
description: "Test that 'blkid' is called and reports ext4 partition",
fstype: "ext3",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\next4\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "DEVNAME=/dev/foo\nPTTYPE=dos\n", nil},
},
expectedError: fmt.Errorf("failed to mount the volume as \"ext3\", it already contains unknown data, probably partitions. Mount error: unknown filesystem type '(null)'"),
},
{
description: "Test that 'lsblk' is called and reports empty partition",
fstype: "ext3",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'")},
description: "Test that 'blkid' is called but has some usage or other errors (an exit code of 4 is returned)",
fstype: "xfs",
mountErrs: []error{fmt.Errorf("unknown filesystem type '(null)'"), nil},
execScripts: []ExecArgs{
{"fsck", []string{"-a", "/dev/foo"}, "", nil},
{"lsblk", []string{"-n", "-o", "FSTYPE", "/dev/foo"}, "\n\n", nil},
{"blkid", []string{"-p", "-s", "TYPE", "-s", "PTTYPE", "-o", "export", "/dev/foo"}, "", &fakeexec.FakeExitError{Status: 4}},
{"mkfs.xfs", []string{"/dev/foo"}, "", nil},
},
expectedError: fmt.Errorf("failed to mount the volume as \"ext3\", it already contains unknown data, probably partitions. Mount error: unknown filesystem type '(null)'"),
expectedError: fmt.Errorf("exit 4"),
},
}

View File

@ -1,3 +1,5 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
package(default_visibility = ["//visibility:public"])
filegroup(
@ -15,3 +17,15 @@ filegroup(
],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["net.go"],
importpath = "k8s.io/kubernetes/pkg/util/net",
)
go_test(
name = "go_default_test",
srcs = ["net_test.go"],
embed = [":go_default_library"],
)

4
vendor/k8s.io/kubernetes/pkg/util/net/OWNERS generated vendored Normal file
View File

@ -0,0 +1,4 @@
reviewers:
- sig-network-reviewers
approvers:
- sig-network-approvers

61
vendor/k8s.io/kubernetes/pkg/util/net/net.go generated vendored Normal file
View File

@ -0,0 +1,61 @@
/*
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 net
import (
"net"
)
// IsIPv6 returns if netIP is IPv6.
func IsIPv6(netIP net.IP) bool {
return netIP != nil && netIP.To4() == nil
}
// IsIPv6String returns if ip is IPv6.
func IsIPv6String(ip string) bool {
netIP := net.ParseIP(ip)
return IsIPv6(netIP)
}
// IsIPv6CIDR returns if cidr is IPv6.
// This assumes cidr is a valid CIDR.
func IsIPv6CIDR(cidr string) bool {
ip, _, _ := net.ParseCIDR(cidr)
return IsIPv6(ip)
}
// FilterIncorrectIPVersion filters out the incorrect IP version case from a slice of IP strings.
func FilterIncorrectIPVersion(ipStrings []string, isIPv6Mode bool) ([]string, []string) {
return filterWithCondition(ipStrings, isIPv6Mode, IsIPv6String)
}
// FilterIncorrectCIDRVersion filters out the incorrect IP version case from a slice of CIDR strings.
func FilterIncorrectCIDRVersion(ipStrings []string, isIPv6Mode bool) ([]string, []string) {
return filterWithCondition(ipStrings, isIPv6Mode, IsIPv6CIDR)
}
func filterWithCondition(strs []string, expectedCondition bool, conditionFunc func(string) bool) ([]string, []string) {
var corrects, incorrects []string
for _, str := range strs {
if conditionFunc(str) != expectedCondition {
incorrects = append(incorrects, str)
} else {
corrects = append(corrects, str)
}
}
return corrects, incorrects
}

286
vendor/k8s.io/kubernetes/pkg/util/net/net_test.go generated vendored Normal file
View File

@ -0,0 +1,286 @@
/*
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 net
import (
"net"
"reflect"
"testing"
)
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)
}
}
}
func TestIsIPv6CIDR(t *testing.T) {
testCases := []struct {
desc string
cidr string
expectResult bool
}{
{
desc: "ipv4 CIDR 1",
cidr: "10.0.0.0/8",
expectResult: false,
},
{
desc: "ipv4 CIDR 2",
cidr: "192.168.0.0/16",
expectResult: false,
},
{
desc: "ipv6 CIDR 1",
cidr: "::/1",
expectResult: true,
},
{
desc: "ipv6 CIDR 2",
cidr: "2000::/10",
expectResult: true,
},
{
desc: "ipv6 CIDR 3",
cidr: "2001:db8::/32",
expectResult: true,
},
}
for _, tc := range testCases {
res := IsIPv6CIDR(tc.cidr)
if res != tc.expectResult {
t.Errorf("%v: want IsIPv6CIDR=%v, got %v", tc.desc, tc.expectResult, res)
}
}
}
func TestFilterIncorrectIPVersion(t *testing.T) {
testCases := []struct {
desc string
isIPv6 bool
ipStrings []string
expectCorrects []string
expectIncorrects []string
}{
{
desc: "all ipv4 strings in ipv4 mode",
isIPv6: false,
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
expectCorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
expectIncorrects: nil,
},
{
desc: "all ipv6 strings in ipv4 mode",
isIPv6: false,
ipStrings: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
expectCorrects: nil,
expectIncorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
},
{
desc: "mixed versions in ipv4 mode",
isIPv6: false,
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1", "::1", "fd00::600d:f00d", "2001:db8::5"},
expectCorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
expectIncorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
},
{
desc: "all ipv4 strings in ipv6 mode",
isIPv6: true,
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
expectCorrects: nil,
expectIncorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
},
{
desc: "all ipv6 strings in ipv6 mode",
isIPv6: true,
ipStrings: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
expectCorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
expectIncorrects: nil,
},
{
desc: "mixed versions in ipv6 mode",
isIPv6: true,
ipStrings: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1", "::1", "fd00::600d:f00d", "2001:db8::5"},
expectCorrects: []string{"::1", "fd00::600d:f00d", "2001:db8::5"},
expectIncorrects: []string{"10.0.0.1", "192.168.0.1", "127.0.0.1"},
},
}
for _, tc := range testCases {
corrects, incorrects := FilterIncorrectIPVersion(tc.ipStrings, tc.isIPv6)
if !reflect.DeepEqual(tc.expectCorrects, corrects) {
t.Errorf("%v: want corrects=%v, got %v", tc.desc, tc.expectCorrects, corrects)
}
if !reflect.DeepEqual(tc.expectIncorrects, incorrects) {
t.Errorf("%v: want incorrects=%v, got %v", tc.desc, tc.expectIncorrects, incorrects)
}
}
}
func TestFilterIncorrectCIDRVersion(t *testing.T) {
testCases := []struct {
desc string
isIPv6 bool
cidrStrings []string
expectCorrects []string
expectIncorrects []string
}{
{
desc: "all ipv4 strings in ipv4 mode",
isIPv6: false,
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1"},
expectCorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
expectIncorrects: nil,
},
{
desc: "all ipv6 strings in ipv4 mode",
isIPv6: false,
cidrStrings: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectCorrects: nil,
expectIncorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
},
{
desc: "mixed versions in ipv4 mode",
isIPv6: false,
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1", "2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectCorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
expectIncorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
},
{
desc: "all ipv4 strings in ipv6 mode",
isIPv6: true,
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1"},
expectCorrects: nil,
expectIncorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
},
{
desc: "all ipv6 strings in ipv6 mode",
isIPv6: true,
cidrStrings: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectCorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectIncorrects: nil,
},
{
desc: "mixed versions in ipv6 mode",
isIPv6: true,
cidrStrings: []string{"0.0.0.0/1", "1.0.0.0/1", "2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectCorrects: []string{"2001:db8::/32", "2001:0db8:0123:4567::/64"},
expectIncorrects: []string{"0.0.0.0/1", "1.0.0.0/1"},
},
}
for _, tc := range testCases {
corrects, incorrects := FilterIncorrectCIDRVersion(tc.cidrStrings, tc.isIPv6)
if !reflect.DeepEqual(tc.expectCorrects, corrects) {
t.Errorf("%v: want corrects=%v, got %v", tc.desc, tc.expectCorrects, corrects)
}
if !reflect.DeepEqual(tc.expectIncorrects, incorrects) {
t.Errorf("%v: want incorrects=%v, got %v", tc.desc, tc.expectIncorrects, incorrects)
}
}
}

View File

@ -18,8 +18,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["ipnet_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/net/sets",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -38,8 +38,7 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["netsh_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/netsh",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",

View File

@ -26,8 +26,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["node_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/node",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//pkg/kubelet/apis:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",

View File

@ -166,10 +166,23 @@ func PatchNodeCIDR(c clientset.Interface, node types.NodeName, cidr string) erro
}
// PatchNodeStatus patches node status.
func PatchNodeStatus(c v1core.CoreV1Interface, nodeName types.NodeName, oldNode *v1.Node, newNode *v1.Node) (*v1.Node, error) {
func PatchNodeStatus(c v1core.CoreV1Interface, nodeName types.NodeName, oldNode *v1.Node, newNode *v1.Node) (*v1.Node, []byte, error) {
patchBytes, err := preparePatchBytesforNodeStatus(nodeName, oldNode, newNode)
if err != nil {
return nil, nil, err
}
updatedNode, err := c.Nodes().Patch(string(nodeName), types.StrategicMergePatchType, patchBytes, "status")
if err != nil {
return nil, nil, fmt.Errorf("failed to patch status %q for node %q: %v", patchBytes, nodeName, err)
}
return updatedNode, patchBytes, nil
}
func preparePatchBytesforNodeStatus(nodeName types.NodeName, oldNode *v1.Node, newNode *v1.Node) ([]byte, error) {
oldData, err := json.Marshal(oldNode)
if err != nil {
return nil, fmt.Errorf("failed to marshal old node %#v for node %q: %v", oldNode, nodeName, err)
return nil, fmt.Errorf("failed to Marshal oldData for node %q: %v", nodeName, err)
}
// Reset spec to make sure only patch for Status or ObjectMeta is generated.
@ -179,17 +192,12 @@ func PatchNodeStatus(c v1core.CoreV1Interface, nodeName types.NodeName, oldNode
newNode.Spec = oldNode.Spec
newData, err := json.Marshal(newNode)
if err != nil {
return nil, fmt.Errorf("failed to marshal new node %#v for node %q: %v", newNode, nodeName, err)
return nil, fmt.Errorf("failed to Marshal newData for node %q: %v", nodeName, err)
}
patchBytes, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, v1.Node{})
if err != nil {
return nil, fmt.Errorf("failed to create patch for node %q: %v", nodeName, err)
return nil, fmt.Errorf("failed to CreateTwoWayMergePatch for node %q: %v", nodeName, err)
}
updatedNode, err := c.Nodes().Patch(string(nodeName), types.StrategicMergePatchType, patchBytes, "status")
if err != nil {
return nil, fmt.Errorf("failed to patch status %q for node %q: %v", patchBytes, nodeName, err)
}
return updatedNode, nil
return patchBytes, nil
}

View File

@ -2,21 +2,78 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"nsenter_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"nsenter.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"nsenter_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"nsenter_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/nsenter",
visibility = ["//visibility:public"],
deps = [
"//vendor/k8s.io/utils/exec:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
deps = select({
"@io_bazel_rules_go//go/platform:android": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/k8s.io/utils/exec:go_default_library",
],
"//conditions:default": [],
}),

View File

@ -35,7 +35,7 @@ func NewNsenter() *Nsenter {
}
// Exec executes nsenter commands in hostProcMountNsPath mount namespace
func (ne *Nsenter) Exec(args ...string) exec.Cmd {
func (ne *Nsenter) Exec(cmd string, args []string) exec.Cmd {
return nil
}

View File

@ -12,16 +12,45 @@ go_library(
"doc.go",
"oom.go",
"oom_fake.go",
"oom_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"oom_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"oom_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"oom_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/oom",
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/kubelet/cm/util:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
],
@ -32,15 +61,14 @@ go_library(
go_test(
name = "go_default_test",
srcs = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"oom_linux_test.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/oom",
library = ":go_default_library",
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
"//conditions:default": [],

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["parsers_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/parsers",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -9,8 +9,7 @@ load(
go_test(
name = "go_default_test",
srcs = ["pointer_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/pointer",
library = ":go_default_library",
embed = [":go_default_library"],
)
go_library(

View File

@ -12,16 +12,45 @@ go_library(
"doc.go",
"procfs.go",
"procfs_fake.go",
"procfs_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"procfs_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"procfs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"procfs_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/procfs",
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
],
@ -32,7 +61,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"procfs_linux_test.go",
],
"//conditions:default": [],
@ -40,10 +69,9 @@ go_test(
data = [
"example_proc_cgroup",
],
importpath = "k8s.io/kubernetes/pkg/util/procfs",
library = ":go_default_library",
embed = [":go_default_library"],
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/stretchr/testify/assert:go_default_library",
],
"//conditions:default": [],

View File

@ -9,8 +9,7 @@ load(
go_test(
name = "go_default_test",
srcs = ["removeall_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/removeall",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//pkg/util/mount:go_default_library",
"//vendor/k8s.io/client-go/util/testing:go_default_library",

View File

@ -2,22 +2,78 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"resizefs_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"resizefs_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"resizefs_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"resizefs_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/resizefs",
visibility = ["//visibility:public"],
deps = [
"//pkg/util/mount:go_default_library",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
deps = select({
"@io_bazel_rules_go//go/platform:android": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/util/mount:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//pkg/util/mount:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//pkg/util/mount:go_default_library",
],
"//conditions:default": [],
}),

View File

@ -23,14 +23,6 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/util/mount"
utilexec "k8s.io/utils/exec"
)
const (
// 'fsck' found errors and corrected them
fsckErrorsCorrected = 1
// 'fsck' found errors but exited without correcting them
fsckErrorsUncorrected = 4
)
// ResizeFs Provides support for resizing file systems
@ -44,11 +36,11 @@ func NewResizeFs(mounter *mount.SafeFormatAndMount) *ResizeFs {
}
// Resize perform resize of file system
func (resizefs *ResizeFs) Resize(devicePath string) (bool, error) {
func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (bool, error) {
format, err := resizefs.mounter.GetDiskFormat(devicePath)
if err != nil {
formatErr := fmt.Errorf("error checking format for device %s: %v", devicePath, err)
formatErr := fmt.Errorf("ResizeFS.Resize - error checking format for device %s: %v", devicePath, err)
return false, formatErr
}
@ -58,63 +50,14 @@ func (resizefs *ResizeFs) Resize(devicePath string) (bool, error) {
return false, nil
}
deviceOpened, err := resizefs.mounter.DeviceOpened(devicePath)
if err != nil {
deviceOpenErr := fmt.Errorf("error verifying if device %s is open: %v", devicePath, err)
return false, deviceOpenErr
}
if deviceOpened {
deviceAlreadyOpenErr := fmt.Errorf("the device %s is already in use", devicePath)
return false, deviceAlreadyOpenErr
}
glog.V(3).Infof("ResizeFS.Resize - Expanding mounted volume %s", devicePath)
switch format {
case "ext3", "ext4":
fsckErr := resizefs.extFsck(devicePath, format)
if fsckErr != nil {
return false, fsckErr
}
return resizefs.extResize(devicePath)
case "xfs":
fsckErr := resizefs.fsckDevice(devicePath)
if fsckErr != nil {
return false, fsckErr
}
return resizefs.xfsResize(devicePath)
return resizefs.xfsResize(deviceMountPath)
}
return false, fmt.Errorf("resize of format %s is not supported for device %s", format, devicePath)
}
func (resizefs *ResizeFs) fsckDevice(devicePath string) error {
glog.V(4).Infof("Checking for issues with fsck on device: %s", devicePath)
args := []string{"-a", devicePath}
out, err := resizefs.mounter.Exec.Run("fsck", args...)
if err != nil {
ee, isExitError := err.(utilexec.ExitError)
switch {
case err == utilexec.ErrExecutableNotFound:
glog.Warningf("'fsck' not found on system; continuing resizing without running 'fsck'.")
case isExitError && ee.ExitStatus() == fsckErrorsCorrected:
glog.V(2).Infof("Device %s has errors which were corrected by fsck: %s", devicePath, string(out))
case isExitError && ee.ExitStatus() == fsckErrorsUncorrected:
return fmt.Errorf("'fsck' found errors on device %s but could not correct them: %s", devicePath, string(out))
case isExitError && ee.ExitStatus() > fsckErrorsUncorrected:
glog.Infof("`fsck` error %s", string(out))
}
}
return nil
}
func (resizefs *ResizeFs) extFsck(devicePath string, fsType string) error {
glog.V(4).Infof("Checking for issues with fsck.%s on device: %s", fsType, devicePath)
args := []string{"-f", "-y", devicePath}
out, err := resizefs.mounter.Run("fsck."+fsType, args...)
if err != nil {
return fmt.Errorf("running fsck.%s failed on %s with error: %v\n Output: %s", fsType, devicePath, err, string(out))
}
return nil
return false, fmt.Errorf("ResizeFS.Resize - resize of format %s is not supported for device %s mounted at %s", format, devicePath, deviceMountPath)
}
func (resizefs *ResizeFs) extResize(devicePath string) (bool, error) {
@ -129,15 +72,15 @@ func (resizefs *ResizeFs) extResize(devicePath string) (bool, error) {
}
func (resizefs *ResizeFs) xfsResize(devicePath string) (bool, error) {
args := []string{"-d", devicePath}
func (resizefs *ResizeFs) xfsResize(deviceMountPath string) (bool, error) {
args := []string{"-d", deviceMountPath}
output, err := resizefs.mounter.Exec.Run("xfs_growfs", args...)
if err == nil {
glog.V(2).Infof("Device %s resized successfully", devicePath)
glog.V(2).Infof("Device %s resized successfully", deviceMountPath)
return true, nil
}
resizeError := fmt.Errorf("resize of device %s failed: %v. xfs_growfs output: %s", devicePath, err, string(output))
resizeError := fmt.Errorf("resize of device %s failed: %v. xfs_growfs output: %s", deviceMountPath, err, string(output))
return false, resizeError
}

View File

@ -35,6 +35,6 @@ func NewResizeFs(mounter *mount.SafeFormatAndMount) *ResizeFs {
}
// Resize perform resize of file system
func (resizefs *ResizeFs) Resize(devicePath string) (bool, error) {
func (resizefs *ResizeFs) Resize(devicePath string, deviceMountPath string) (bool, error) {
return false, fmt.Errorf("Resize is not supported for this build")
}

View File

@ -7,17 +7,45 @@ load(
go_library(
name = "go_default_library",
srcs = [
"resource_container_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"resource_container_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"resource_container_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"resource_container_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/resourcecontainer",
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
"//vendor/github.com/opencontainers/runc/libcontainer/configs:go_default_library",
],

View File

@ -7,17 +7,45 @@ load(
go_library(
name = "go_default_library",
srcs = [
"rlimit_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"rlimit_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"rlimit_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"rlimit_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/rlimit",
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/golang.org/x/sys/unix:go_default_library",
],
"//conditions:default": [],

View File

@ -10,16 +10,45 @@ go_library(
srcs = [
"doc.go",
"selinux.go",
"selinux_unsupported.go",
] + select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:android": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"selinux_linux.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"selinux_unsupported.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"selinux_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/selinux",
deps = select({
"@io_bazel_rules_go//go/platform:linux_amd64": [
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/opencontainers/selinux/go-selinux:go_default_library",
],
"//conditions:default": [],

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["slice_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/slice",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -68,3 +68,24 @@ func ContainsString(slice []string, s string, modifier func(s string) string) bo
}
return false
}
// RemoveString returns a newly created []string that contains all items from slice that
// are not equal to s and modifier(s) in case modifier func is provided.
func RemoveString(slice []string, s string, modifier func(s string) string) []string {
newSlice := make([]string, 0)
for _, item := range slice {
if item == s {
continue
}
if modifier != nil && modifier(item) == s {
continue
}
newSlice = append(newSlice, item)
}
if len(newSlice) == 0 {
// Sanitize for unit tests so we don't need to distinguish empty array
// and nil.
newSlice = nil
}
return newSlice
}

View File

@ -106,3 +106,67 @@ func TestContainsString(t *testing.T) {
t.Errorf("ContainsString didn't find the string by modifier")
}
}
func TestRemoveString(t *testing.T) {
modifier := func(s string) string {
if s == "ab" {
return "ee"
}
return s
}
tests := []struct {
testName string
input []string
remove string
modifier func(s string) string
want []string
}{
{
testName: "Nil input slice",
input: nil,
remove: "",
modifier: nil,
want: nil,
},
{
testName: "Slice doesn't contain the string",
input: []string{"a", "ab", "cdef"},
remove: "NotPresentInSlice",
modifier: nil,
want: []string{"a", "ab", "cdef"},
},
{
testName: "All strings removed, result is nil",
input: []string{"a"},
remove: "a",
modifier: nil,
want: nil,
},
{
testName: "No modifier func, one string removed",
input: []string{"a", "ab", "cdef"},
remove: "ab",
modifier: nil,
want: []string{"a", "cdef"},
},
{
testName: "No modifier func, all(three) strings removed",
input: []string{"ab", "a", "ab", "cdef", "ab"},
remove: "ab",
modifier: nil,
want: []string{"a", "cdef"},
},
{
testName: "Removed both the string and the modifier func result",
input: []string{"a", "cd", "ab", "ee"},
remove: "ee",
modifier: modifier,
want: []string{"a", "cd"},
},
}
for _, tt := range tests {
if got := RemoveString(tt.input, tt.remove, tt.modifier); !reflect.DeepEqual(got, tt.want) {
t.Errorf("%v: RemoveString(%v, %q, %T) = %v WANT %v", tt.testName, tt.input, tt.remove, tt.modifier, got, tt.want)
}
}
}

View File

@ -23,8 +23,7 @@ go_test(
"line_delimiter_test.go",
"strings_test.go",
],
importpath = "k8s.io/kubernetes/pkg/util/strings",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -15,8 +15,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["system_utils_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/system",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@ -22,8 +22,7 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["tail_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/tail",
library = ":go_default_library",
embed = [":go_default_library"],
)
go_library(

View File

@ -53,7 +53,7 @@ func ReadAtMost(path string, max int64) ([]byte, bool, error) {
if size < max {
max = size
}
offset, err := f.Seek(-max, os.SEEK_END)
offset, err := f.Seek(-max, io.SeekEnd)
if err != nil {
return nil, false, err
}
@ -70,7 +70,7 @@ func FindTailLineStartIndex(f io.ReadSeeker, n int64) (int64, error) {
if n < 0 {
return 0, nil
}
size, err := f.Seek(0, os.SEEK_END)
size, err := f.Seek(0, io.SeekEnd)
if err != nil {
return 0, err
}
@ -82,7 +82,7 @@ func FindTailLineStartIndex(f io.ReadSeeker, n int64) (int64, error) {
left = 0
buf = make([]byte, right)
}
if _, err := f.Seek(left, os.SEEK_SET); err != nil {
if _, err := f.Seek(left, io.SeekStart); err != nil {
return 0, err
}
if _, err := f.Read(buf); err != nil {

View File

@ -23,8 +23,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["taints_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/taints",
library = ":go_default_library",
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",

View File

@ -9,8 +9,7 @@ load(
go_test(
name = "go_default_test",
srcs = ["template_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/template",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//vendor/github.com/stretchr/testify/assert:go_default_library"],
)

View File

@ -7,19 +7,89 @@ load(
go_library(
name = "go_default_library",
srcs = [
"setsize.go",
] + select({
"@io_bazel_rules_go//go/platform:windows_amd64": [
srcs = select({
"@io_bazel_rules_go//go/platform:android": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"setsize.go",
],
"@io_bazel_rules_go//go/platform:windows": [
"setsize_unsupported.go",
],
"//conditions:default": [],
}),
importpath = "k8s.io/kubernetes/pkg/util/term",
deps = [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
deps = select({
"@io_bazel_rules_go//go/platform:android": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//vendor/github.com/docker/docker/pkg/term:go_default_library",
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"@io_bazel_rules_go//go/platform:windows": [
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(

View File

@ -16,8 +16,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["deadlock-detector_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/threading",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(

View File

@ -32,7 +32,6 @@ filegroup(
go_test(
name = "go_default_test",
srcs = ["tolerations_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/tolerations",
library = ":go_default_library",
embed = [":go_default_library"],
deps = ["//pkg/apis/core:go_default_library"],
)

View File

@ -18,8 +18,7 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["version_test.go"],
importpath = "k8s.io/kubernetes/pkg/util/version",
library = ":go_default_library",
embed = [":go_default_library"],
)
filegroup(