Merge pull request #59289 from rmmh/semantic-check

Automatic merge from submit-queue (batch tested with PRs 53689, 56880, 55856, 59289, 60249). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

 Add test/typecheck, a fast typecheck for all build platforms.

Add test/typecheck, a fast typecheck for all build platforms.

Most of the time spent compiling is spent optimizing and linking
binary code. Most errors occur at the syntax or semantic (type) layers.
Go's compiler is importable as a normal package, so we can do fast
syntax and type checking for the 10 platforms we build on.

This currently takes ~6 minutes of CPU time (parallelized).

This makes presubmit cross builds superfluous, since it should catch
most cross-build breaks (generally Unix and 64-bit assumptions).

Example output:

```$ time go run test/typecheck/main.go
type-checking:  linux/amd64, windows/386, darwin/amd64, linux/arm, 
    linux/386, windows/amd64, linux/arm64, linux/ppc64le, linux/s390x, darwin/386
ERROR(windows/amd64) pkg/proxy/ipvs/proxier.go:1708:27: ENXIO not declared by package unix
ERROR(windows/386) pkg/proxy/ipvs/proxier.go:1708:27: ENXIO not declared by package unix

real    0m45.083s
user    6m15.504s
sys     1m14.000s
```


```release-note
NONE
```
This commit is contained in:
Kubernetes Submit Queue
2018-02-28 00:00:36 -08:00
committed by GitHub
70 changed files with 12999 additions and 310 deletions

View File

@@ -186,21 +186,104 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["server_test.go"],
srcs = [
"server_test.go",
] + select({
"@io_bazel_rules_go//go/platform:android": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:darwin": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:linux": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:nacl": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:plan9": [
"server_others_test.go",
],
"@io_bazel_rules_go//go/platform:solaris": [
"server_others_test.go",
],
"//conditions:default": [],
}),
embed = [":go_default_library"],
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/features:go_default_library",
"//pkg/proxy/apis/kubeproxyconfig:go_default_library",
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/configz:go_default_library",
"//pkg/util/iptables:go_default_library",
"//pkg/util/pointer:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
] + select({
"@io_bazel_rules_go//go/platform:android": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:darwin": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:dragonfly": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:freebsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:linux": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:nacl": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:netbsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:openbsd": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:plan9": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"@io_bazel_rules_go//go/platform:solaris": [
"//pkg/proxy/ipvs:go_default_library",
"//pkg/util/iptables:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
],
"//conditions:default": [],
}),
)
filegroup(

View File

@@ -0,0 +1,247 @@
// +build !windows
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"fmt"
"testing"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/proxy/ipvs"
"k8s.io/kubernetes/pkg/util/iptables"
)
func Test_getProxyMode(t *testing.T) {
var cases = []struct {
flag string
annotationKey string
annotationVal string
iptablesVersion string
ipsetVersion string
kmods []string
kernelCompat bool
iptablesError error
ipsetError error
expected string
}{
{ // flag says userspace
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
flag: "iptables",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // flag says iptables, version too low
flag: "iptables",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, error
flag: "",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // detect, version too low
flag: "",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel not compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is compatible
flag: "ipvs",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // specify ipvs, feature gateway disabled, iptables version too low
flag: "ipvs",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is not compatible
flag: "ipvs",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
}
for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandler := &fakeKernelHandler{c.kmods}
r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater)
if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
}
}
}
// This is a coarse test, but it offers some modicum of confidence as the code is evolved.
func Test_getProxyModeEnableFeatureGateway(t *testing.T) {
// enable IPVS feature gateway
utilfeature.DefaultFeatureGate.Set("SupportIPVSProxyMode=true")
var cases = []struct {
flag string
iptablesVersion string
ipsetVersion string
kernelCompat bool
iptablesError error
ipsetError error
mods []string
expected string
}{
{ // flag says userspace
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
flag: "iptables",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // flag says iptables, version too low
flag: "iptables",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, error
flag: "",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // detect, version too low
flag: "",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel not compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, ipset version ok, kernel modules installed
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
expected: proxyModeIPVS,
},
{ // flag says ipvs, ipset version too low, fallback on iptables mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, bad ipset version, fallback on iptables mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "a.b.c",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, fallback on iptables mode
flag: "ipvs",
mods: []string{"foo", "bar", "baz"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode
flag: "ipvs",
mods: []string{"foo", "bar", "baz"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: "0.0.0",
kernelCompat: true,
expected: proxyModeUserspace,
},
{ // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
}
for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandle := &fakeKernelHandler{c.mods}
r := getProxyMode(c.flag, versioner, khandle, ipsetver, kcompater)
if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
}
}
}

View File

@@ -28,13 +28,10 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/diff"
utilfeature "k8s.io/apiserver/pkg/util/feature"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/proxy/apis/kubeproxyconfig"
"k8s.io/kubernetes/pkg/proxy/ipvs"
"k8s.io/kubernetes/pkg/util/configz"
"k8s.io/kubernetes/pkg/util/iptables"
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
)
@@ -55,6 +52,10 @@ func (fake *fakeIPTablesVersioner) GetVersion() (string, error) {
return fake.version, fake.err
}
func (fake *fakeIPTablesVersioner) IsCompatible() error {
return fake.err
}
type fakeIPSetVersioner struct {
version string // what to return
err error // what to return
@@ -84,232 +85,6 @@ func (fake *fakeKernelHandler) GetModules() ([]string, error) {
return fake.modules, nil
}
func Test_getProxyMode(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("skipping on non-Linux")
}
var cases = []struct {
flag string
annotationKey string
annotationVal string
iptablesVersion string
ipsetVersion string
kmods []string
kernelCompat bool
iptablesError error
ipsetError error
expected string
}{
{ // flag says userspace
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
flag: "iptables",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // flag says iptables, version too low
flag: "iptables",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, error
flag: "",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // detect, version too low
flag: "",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel not compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is compatible
flag: "ipvs",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // specify ipvs, feature gateway disabled, iptables version too low
flag: "ipvs",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // specify ipvs, feature gateway disabled, iptables version ok, kernel is not compatible
flag: "ipvs",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
}
for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandler := &fakeKernelHandler{c.kmods}
r := getProxyMode(c.flag, versioner, khandler, ipsetver, kcompater)
if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
}
}
}
// This is a coarse test, but it offers some modicum of confidence as the code is evolved.
func Test_getProxyModeEnableFeatureGateway(t *testing.T) {
if runtime.GOOS != "linux" {
t.Skip("skipping on non-Linux")
}
// enable IPVS feature gateway
utilfeature.DefaultFeatureGate.Set("SupportIPVSProxyMode=true")
var cases = []struct {
flag string
iptablesVersion string
ipsetVersion string
kernelCompat bool
iptablesError error
ipsetError error
mods []string
expected string
}{
{ // flag says userspace
flag: "userspace",
expected: proxyModeUserspace,
},
{ // flag says iptables, error detecting version
flag: "iptables",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // flag says iptables, version too low
flag: "iptables",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel not compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // flag says iptables, version ok, kernel is compatible
flag: "iptables",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, error
flag: "",
iptablesError: fmt.Errorf("oops!"),
expected: proxyModeUserspace,
},
{ // detect, version too low
flag: "",
iptablesVersion: "0.0.0",
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel not compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // detect, version ok, kernel is compatible
flag: "",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, ipset version ok, kernel modules installed
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
expected: proxyModeIPVS,
},
{ // flag says ipvs, ipset version too low, fallback on iptables mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, bad ipset version, fallback on iptables mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "a.b.c",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, fallback on iptables mode
flag: "ipvs",
mods: []string{"foo", "bar", "baz"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: true,
expected: proxyModeIPTables,
},
{ // flag says ipvs, required kernel modules are not installed, iptables version too old, fallback on userspace mode
flag: "ipvs",
mods: []string{"foo", "bar", "baz"},
ipsetVersion: ipvs.MinIPSetCheckVersion,
iptablesVersion: "0.0.0",
kernelCompat: true,
expected: proxyModeUserspace,
},
{ // flag says ipvs, ipset version too low, iptables version too old, kernel not compatible, fallback on userspace mode
flag: "ipvs",
mods: []string{"ip_vs", "ip_vs_rr", "ip_vs_wrr", "ip_vs_sh", "nf_conntrack_ipv4"},
ipsetVersion: "0.0",
iptablesVersion: iptables.MinCheckVersion,
kernelCompat: false,
expected: proxyModeUserspace,
},
}
for i, c := range cases {
versioner := &fakeIPTablesVersioner{c.iptablesVersion, c.iptablesError}
kcompater := &fakeKernelCompatTester{c.kernelCompat}
ipsetver := &fakeIPSetVersioner{c.ipsetVersion, c.ipsetError}
khandle := &fakeKernelHandler{c.mods}
r := getProxyMode(c.flag, versioner, khandle, ipsetver, kcompater)
if r != c.expected {
t.Errorf("Case[%d] Expected %q, got %q", i, c.expected, r)
}
}
}
// This test verifies that NewProxyServer does not crash when CleanupAndExit is true.
func TestProxyServerWithCleanupAndExit(t *testing.T) {
// Each bind address below is a separate test case