Change:
Is this a request for help? No. What keywords did you search in Kubernetes issues before filing this one? is:issue is:open ipv6 Is this a BUG REPORT or FEATURE REQUEST? (choose one): FEATURE REQUEST Kubernetes version (use ): N/A, these are unit test changes in latest master Environment: Cloud provider or hardware configuration: Kubernetes container dev env on Ubuntu 16.04.1 OS (e.g. from /etc/os-release): Ubuntu 16.04.1 Kernel (e.g. ): 4.4.0-78-generic -Ubuntu x8664 GNU/Linux Install tools: Others: What happened: Upon inspection, no IPv6 test cases found in kubernetes/cmd/kube- What you expected to happen: Expect to see some IPv6 test cases exercised for kube-proxy server code (kubernetes/cmd/kube-). Also need some code coverage for negative conditions in How to reproduce it (as minimally and precisely as possible): Run unit tests in kubernetes/cmd/kube- Anything else we need to know:
There are no sig labels on this issue. Please by:<br(1) mentioning a sig: <br(2) specifying the label manually: <br<brNote: method (1) will trigger a notification to the team. You can find the team list and label list
/sig networking
/area ipv6
/sig network

Discussion:
deps = [ "//pkg/api:go_default_library", "//pkg/apis/componentconfig:go_default_library", <ins> "//pkg/apis/componentconfig/v1alpha1:go_default_library", </ins> "//pkg/util:go_default_library", <ins> "//pkg/util/configz:go_default_library", </ins> "//pkg/util/iptables:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", <ins> "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", </ins> "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", ], )

package app import ( <ins> "errors" </ins> "fmt" "reflect" "runtime"

"github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" <ins> k8sRuntime "k8s.io/apimachinery/pkg/runtime" </ins> "k8s.io/apimachinery/pkg/util/diff" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/componentconfig" <ins> "k8s.io/kubernetes/pkg/apis/componentconfig/v1alpha1" </ins> "k8s.io/kubernetes/pkg/util" <ins> "k8s.io/kubernetes/pkg/util/configz" </ins> "k8s.io/kubernetes/pkg/util/iptables" )

} } <del> // This test verifies that Proxy Server does not crash when CleanupAndExit is true. func TestProxyServerWithCleanupAndExit(t *testing.T) { options, err := NewOptions() if err != nil { t.Fatal(err) </del> <ins> // TestNewOptionsFailures tests failure modes for NewOptions() func TestNewOptionsFailures(t *testing.T) { // Create a fake scheme builder that generates an error errString := fmt.Sprintf("Simulated error") genError := func(scheme *k8sRuntime.Scheme) error { return errors.New(errString) </ins> } <ins> fakeSchemeBuilder := k8sRuntime.NewSchemeBuilder(genError) simulatedErrorTest := func(target string) { var addToScheme *func(s *k8sRuntime.Scheme) error if target == "componentconfig" { addToScheme = &componentconfig.AddToScheme } else { addToScheme = &v1alpha1.AddToScheme } restoreValue := *addToScheme restore := func() { *addToScheme = restoreValue } defer restore() *addToScheme = fakeSchemeBuilder.AddToScheme _, err := NewOptions() assert.Error(t, err, fmt.Sprintf("Simulated error in component %s", target)) } // Simulate errors in calls to AddToScheme() faultTargets := []string{"componentconfig", "v1alpha1"} for _, target := range faultTargets { simulatedErrorTest(target) } } </ins> <del> options.config = &componentconfig.KubeProxyConfiguration{ BindAddress: "0.0.0.0", </del> <ins> // 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 bindAddresses := []string{ "0.0.0.0", "2001:db8::1", </ins> } <del> options.CleanupAndExit = true </del> <ins> for _, addr := range bindAddresses { options, err := NewOptions() if err != nil { t.Fatalf("Unexpected error with address %s: %v", addr, err) } options.config = &componentconfig.KubeProxyConfiguration{ BindAddress: addr, } options.CleanupAndExit = true proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master) </ins> <del> proxyserver, err := NewProxyServer(options.config, options.CleanupAndExit, options.scheme, options.master) </del> <ins> assert.Nil(t, err, "unexpected error in NewProxyServer, addr: %s", addr) assert.NotNil(t, proxyserver, "nil proxy server obj, addr: %s", addr) assert.NotNil(t, proxyserver.IptInterface, "nil iptables intf, addr: %s", addr) </ins> <del> assert.Nil(t, err) assert.NotNil(t, proxyserver) assert.NotNil(t, proxyserver.IptInterface) </del> <ins> // Clean up config for next test case configz.Delete("componentconfig") } </ins> } func TestGetConntrackMax(t *testing.T) {

} } <ins> // TestLoadConfig tests proper operation of loadConfig() </ins> func TestLoadConfig(t *testing.T) { <del> yaml := `apiVersion: componentconfig/v1alpha1 bindAddress: 9.8.7.6 </del> <ins> yamlTemplate := `apiVersion: componentconfig/v1alpha1 bindAddress: %s </ins> clientConnection: acceptContentTypes: "abc" burst: 100 contentType: content-type kubeconfig: "/path/to/kubeconfig" qps: 7 <del> clusterCIDR: "1.2.3.0/24" </del> <ins> clusterCIDR: "%s" </ins> configSyncPeriod: 15s conntrack: max: 4

tcpCloseWaitTimeout: 10s tcpEstablishedTimeout: 20s featureGates: "all" <del> healthzBindAddress: 1.2.3.4:12345 </del> <ins> healthzBindAddress: "%s" </ins> hostnameOverride: "foo" iptables: masqueradeAll: true

minSyncPeriod: 10s syncPeriod: 60s kind: KubeProxyConfiguration <del> metricsBindAddress: 2.3.4.5:23456 </del> <ins> metricsBindAddress: "%s" </ins> mode: "iptables" oomScoreAdj: 17 portRange: "2-7"

udpTimeoutMilliseconds: 123ms ` <del> expected := &componentconfig.KubeProxyConfiguration{ BindAddress: "9.8.7.6", ClientConnection: componentconfig.ClientConnectionConfiguration{ AcceptContentTypes: "abc", Burst:              100, ContentType:        "content-type", KubeConfigFile:     "/path/to/kubeconfig", QPS:                7, }, ClusterCIDR:      "1.2.3.0/24", ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, Conntrack: componentconfig.KubeProxyConntrackConfiguration{ Max:                   4, MaxPerCore:            2, Min:                   1, TCPCloseWaitTimeout:   metav1.Duration{Duration: 10 * time.Second}, TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second}, </del> <ins> testCases := []struct { name               string bindAddress        string clusterCIDR        string healthzBindAddress string metricsBindAddress string }{ { name:               "IPv4 config", bindAddress:        "9.8.7.6", clusterCIDR:        "1.2.3.0/24", healthzBindAddress: "1.2.3.4:12345", metricsBindAddress: "2.3.4.5:23456", </ins> }, <del> FeatureGates:       "all", HealthzBindAddress: "1.2.3.4:12345", HostnameOverride:   "foo", IPTables: componentconfig.KubeProxyIPTablesConfiguration{ MasqueradeAll: true, MasqueradeBit: util.Int32Ptr(17), MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, SyncPeriod:    metav1.Duration{Duration: 60 * time.Second}, </del> <ins> { name:               "IPv6 config", bindAddress:        "2001:db8::1", clusterCIDR:        "fd00:1::0/64", healthzBindAddress: "[fd00:1::5]:12345", metricsBindAddress: "[fd00:2::5]:23456", </ins> }, <del> MetricsBindAddress: "2.3.4.5:23456", Mode:               "iptables", OOMScoreAdj:        util.Int32Ptr(17), PortRange:          "2-7", ResourceContainer:  "/foo", UDPIdleTimeout:     metav1.Duration{Duration: 123 * time.Millisecond}, </del> } <del> options, err := NewOptions() assert.NoError(t, err) </del> <ins> for _, tc := range testCases { expected := &componentconfig.KubeProxyConfiguration{ BindAddress: tc.bindAddress, ClientConnection: componentconfig.ClientConnectionConfiguration{ AcceptContentTypes: "abc", Burst:              100, ContentType:        "content-type", KubeConfigFile:     "/path/to/kubeconfig", QPS:                7, }, ClusterCIDR:      tc.clusterCIDR, ConfigSyncPeriod: metav1.Duration{Duration: 15 * time.Second}, Conntrack: componentconfig.KubeProxyConntrackConfiguration{ Max:                   4, MaxPerCore:            2, Min:                   1, TCPCloseWaitTimeout:   metav1.Duration{Duration: 10 * time.Second}, TCPEstablishedTimeout: metav1.Duration{Duration: 20 * time.Second}, }, FeatureGates:       "all", HealthzBindAddress: tc.healthzBindAddress, HostnameOverride:   "foo", IPTables: componentconfig.KubeProxyIPTablesConfiguration{ MasqueradeAll: true, MasqueradeBit: util.Int32Ptr(17), MinSyncPeriod: metav1.Duration{Duration: 10 * time.Second}, SyncPeriod:    metav1.Duration{Duration: 60 * time.Second}, }, MetricsBindAddress: tc.metricsBindAddress, Mode:               "iptables", OOMScoreAdj:        util.Int32Ptr(17), PortRange:          "2-7", ResourceContainer:  "/foo", UDPIdleTimeout:     metav1.Duration{Duration: 123 * time.Millisecond}, } options, err := NewOptions() assert.NoError(t, err, "unexpected error for %s: %v", tc.name, err) yaml := fmt.Sprintf( yamlTemplate, tc.bindAddress, tc.clusterCIDR, tc.healthzBindAddress, tc.metricsBindAddress) config, err := options.loadConfig([]byte(yaml)) assert.NoError(t, err, "unexpected error for %s: %v", tc.name, err) if !reflect.DeepEqual(expected, config) { t.Fatalf("unexpected config for %s test, diff = %s", tc.name, diff.ObjectDiff(config, expected)) } } } </ins> <del> config, err := options.loadConfig([]byte(yaml)) assert.NoError(t, err) if !reflect.DeepEqual(expected, config) { t.Fatalf("unexpected config, diff = %s", diff.ObjectDiff(config, expected)) </del> <ins> // TestLoadConfigFailures tests failure modes for loadConfig() func TestLoadConfigFailures(t *testing.T) { testCases := []struct { name   string config string expErr string }{ { name:   "Decode error test", config: "Twas bryllyg, and ye slythy toves", expErr: "could not find expected ':'", }, { name:   "Bad config type test", config: "kind: KubeSchedulerConfiguration", expErr: "unexpected config type", }, } version := "apiVersion: componentconfig/v1alpha1" for _, tc := range testCases { options, _ := NewOptions() config := fmt.Sprintf("%sn%s", version, tc.config) _, err := options.loadConfig([]byte(config)) if assert.Error(t, err, tc.name) { assert.Contains(t, err.Error(), tc.expErr, tc.name) } </ins> } }