From 4295ae9de073c7b5e613e378e79a7753b013fe57 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Wed, 10 Feb 2021 15:42:35 +0000 Subject: [PATCH 1/6] Log error on failure in discovering network plugin in operator Signed-off-by: Masaki Kimura --- controllers/submariner/submariner_networkdiscovery.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/controllers/submariner/submariner_networkdiscovery.go b/controllers/submariner/submariner_networkdiscovery.go index 491734920..24ddbb9b9 100644 --- a/controllers/submariner/submariner_networkdiscovery.go +++ b/controllers/submariner/submariner_networkdiscovery.go @@ -31,6 +31,9 @@ func (r *SubmarinerReconciler) getClusterNetwork(submariner *submopv1a1.Submarin } clusterNetwork, err := network.Discover(r.dynClient, r.clientSet, r.submClient, submariner.Namespace) + if err != nil { + log.Error(err, "Error trying to discover network") + } if clusterNetwork != nil { r.clusterNetwork = clusterNetwork From 863f37d194ac9c83a66d01f3d2a1dddd035794fc Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Wed, 3 Feb 2021 20:25:33 +0000 Subject: [PATCH 2/6] Clearly make findPod not return error when no pod found Signed-off-by: Masaki Kimura --- pkg/discovery/network/pods.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/discovery/network/pods.go b/pkg/discovery/network/pods.go index 458767366..dafc881b4 100644 --- a/pkg/discovery/network/pods.go +++ b/pkg/discovery/network/pods.go @@ -55,8 +55,13 @@ func findPod(clientSet kubernetes.Interface, labelSelector string) (*v1.Pod, err Limit: 1, }) - if err != nil || len(pods.Items) == 0 { + if err != nil { return nil, errors.WithMessagef(err, "error listing Pods by label selector %q", labelSelector) } + + if len(pods.Items) == 0 { + return nil, nil + } + return &pods.Items[0], nil } From 62ba069b30abb80f4d61440e668280a1bb9b3473 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Wed, 10 Feb 2021 16:36:52 +0000 Subject: [PATCH 3/6] Refactor discoverGenericNetwork Signed-off-by: Masaki Kimura --- pkg/discovery/network/generic.go | 36 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/pkg/discovery/network/generic.go b/pkg/discovery/network/generic.go index 64f1765bd..9c4988d1c 100644 --- a/pkg/discovery/network/generic.go +++ b/pkg/discovery/network/generic.go @@ -25,27 +25,16 @@ func discoverGenericNetwork(clientSet kubernetes.Interface) (*ClusterNetwork, er NetworkPlugin: "generic", } - podIPRange, err := findPodIPRangeKubeController(clientSet) + podIPRange, err := findPodIPRange(clientSet) if err != nil { return nil, err } - if podIPRange == "" { - podIPRange, err = findPodIPRangeKubeProxy(clientSet) - if err != nil { - return nil, err - } - } - if podIPRange != "" { clusterNetwork.PodCIDRs = []string{podIPRange} } - // on some self-hosted platforms, the platform itself will provide the kube-apiserver, thus - // our discovery method of looking for the kube-apiserver pod is useless, and we won't be - // able to return such detail clusterIPRange, err := findClusterIPRange(clientSet) - if err != nil { return nil, err } @@ -62,9 +51,32 @@ func discoverGenericNetwork(clientSet kubernetes.Interface) (*ClusterNetwork, er } func findClusterIPRange(clientSet kubernetes.Interface) (string, error) { + clusterIPRange, err := findClusterIPRangeFromApiserver(clientSet) + if err != nil || clusterIPRange != "" { + return clusterIPRange, err + } + + return "", nil +} + +func findClusterIPRangeFromApiserver(clientSet kubernetes.Interface) (string, error) { return findPodCommandParameter(clientSet, "component=kube-apiserver", "--service-cluster-ip-range") } +func findPodIPRange(clientSet kubernetes.Interface) (string, error) { + podIPRange, err := findPodIPRangeKubeController(clientSet) + if err != nil || podIPRange != "" { + return podIPRange, err + } + + podIPRange, err = findPodIPRangeKubeProxy(clientSet) + if err != nil || podIPRange != "" { + return podIPRange, err + } + + return "", nil +} + func findPodIPRangeKubeController(clientSet kubernetes.Interface) (string, error) { return findPodCommandParameter(clientSet, "component=kube-controller-manager", "--cluster-cidr") } From 62c8624eb620cba457332cebdbdc5e847da3d930 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Tue, 2 Feb 2021 18:37:32 +0000 Subject: [PATCH 4/6] Apply weave's service cidr detection logic to canal Signed-off-by: Masaki Kimura --- pkg/discovery/network/canal.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/discovery/network/canal.go b/pkg/discovery/network/canal.go index 8866a4903..71d39ac6e 100644 --- a/pkg/discovery/network/canal.go +++ b/pkg/discovery/network/canal.go @@ -52,14 +52,14 @@ func discoverCanalFlannelNetwork(clientSet kubernetes.Interface) (*ClusterNetwor PodCIDRs: []string{*podCIDR}, } - // Try to networkPluginsDiscovery the service CIDRs using the generic functions - genNetwork, err := discoverGenericNetwork(clientSet) + // Try to detect the service CIDRs using the generic functions + clusterIPRange, err := findClusterIPRange(clientSet) if err != nil { return nil, err } - if genNetwork != nil { - clusterNetwork.ServiceCIDRs = genNetwork.ServiceCIDRs + if clusterIPRange != "" { + clusterNetwork.ServiceCIDRs = []string{clusterIPRange} } return clusterNetwork, nil From 0dea1700b9fd9fb6c80b48e9d992ae51f97f27de Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Wed, 10 Feb 2021 17:09:29 +0000 Subject: [PATCH 5/6] Add fall-back logic to detect pod cidrs from node spec Signed-off-by: Masaki Kimura --- pkg/discovery/network/generic.go | 28 +++++++++++ pkg/discovery/network/generic_test.go | 54 +++++++++++++++++++++ pkg/discovery/network/network_suite_test.go | 11 +++++ 3 files changed, 93 insertions(+) diff --git a/pkg/discovery/network/generic.go b/pkg/discovery/network/generic.go index 9c4988d1c..fabf7aeb4 100644 --- a/pkg/discovery/network/generic.go +++ b/pkg/discovery/network/generic.go @@ -17,6 +17,9 @@ limitations under the License. package network import ( + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + v1meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" ) @@ -74,6 +77,11 @@ func findPodIPRange(clientSet kubernetes.Interface) (string, error) { return podIPRange, err } + podIPRange, err = findPodIPRangeFromNodeSpec(clientSet) + if err != nil || podIPRange != "" { + return podIPRange, err + } + return "", nil } @@ -84,3 +92,23 @@ func findPodIPRangeKubeController(clientSet kubernetes.Interface) (string, error func findPodIPRangeKubeProxy(clientSet kubernetes.Interface) (string, error) { return findPodCommandParameter(clientSet, "component=kube-proxy", "--cluster-cidr") } + +func findPodIPRangeFromNodeSpec(clientSet kubernetes.Interface) (string, error) { + nodes, err := clientSet.CoreV1().Nodes().List(v1meta.ListOptions{}) + + if err != nil { + return "", errors.WithMessagef(err, "error listing nodes") + } + + return parseToPodCidr(nodes.Items) +} + +func parseToPodCidr(nodes []v1.Node) (string, error) { + for _, node := range nodes { + if node.Spec.PodCIDR != "" { + return node.Spec.PodCIDR, nil + } + } + + return "", nil +} diff --git a/pkg/discovery/network/generic_test.go b/pkg/discovery/network/generic_test.go index 12fa5b5c1..60fd8e856 100644 --- a/pkg/discovery/network/generic_test.go +++ b/pkg/discovery/network/generic_test.go @@ -157,6 +157,60 @@ var _ = Describe("discoverGenericNetwork", func() { Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) }) }) + + When("There is no pod cidr information on node", func() { + It("Should return nil cluster network", func() { + clusterNet := testDiscoverGenericWith( + fakeNode("node1", ""), + fakeNode("node2", ""), + ) + Expect(clusterNet).To(BeNil()) + }) + }) + + When("There is pod cidr information on any of nodes", func() { + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( + fakeNode("node1", ""), + fakeNode("node2", testPodCIDR), + ) + }) + + It("Should return the ClusterNetwork structure with PodCIDR", func() { + Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with empty service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(BeEmpty()) + }) + }) + + When("There is pod cidr information on any of nodes and there is kubeapi pod", func() { + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( + fakeNode("node1", testPodCIDR), + fakePod("kube-apiserver", []string{"kube-apiserver", "--service-cluster-ip-range=" + testServiceCIDR}, []v1.EnvVar{}), + ) + }) + + It("Should return ClusterNetwork with all CIDRs", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDR})) + Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + }) + }) func testDiscoverGenericWith(objects ...runtime.Object) *ClusterNetwork { diff --git a/pkg/discovery/network/network_suite_test.go b/pkg/discovery/network/network_suite_test.go index b6ccf5314..d7af38cb5 100644 --- a/pkg/discovery/network/network_suite_test.go +++ b/pkg/discovery/network/network_suite_test.go @@ -67,3 +67,14 @@ func fakeService(namespace, name, component string) *v1.Service { Spec: v1.ServiceSpec{}, } } + +func fakeNode(name, podCIDR string) *v1.Node { + return &v1.Node{ + ObjectMeta: v1meta.ObjectMeta{ + Name: name, + }, + Spec: v1.NodeSpec{ + PodCIDR: podCIDR, + }, + } +} From 317aaf69ae13a4b849d8472ac754a14302149fa6 Mon Sep 17 00:00:00 2001 From: Masaki Kimura Date: Tue, 2 Feb 2021 19:56:04 +0000 Subject: [PATCH 6/6] Add fall-back logic to detect service cidrs from invalid svc creation Signed-off-by: Masaki Kimura --- pkg/discovery/network/canal_test.go | 12 +- pkg/discovery/network/generic.go | 65 +++++++++ pkg/discovery/network/generic_test.go | 183 ++++++++++++++++++++----- pkg/discovery/network/weavenet_test.go | 9 +- 4 files changed, 220 insertions(+), 49 deletions(-) diff --git a/pkg/discovery/network/canal_test.go b/pkg/discovery/network/canal_test.go index 3b5b3ff89..ca20968e0 100644 --- a/pkg/discovery/network/canal_test.go +++ b/pkg/discovery/network/canal_test.go @@ -20,7 +20,6 @@ import ( v1 "k8s.io/api/core/v1" v1meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/fake" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -28,17 +27,18 @@ import ( var _ = Describe("discoverCanalFlannelNetwork", func() { When("There are no generic k8s pods to look at", func() { - It("Should return still return the pod CIDR", func() { + It("Should return the ClusterNetwork structure with the pod CIDR and the service CIDR", func() { clusterNet := testDiscoverCanalFlannelWith(&canalFlannelCfgMap) Expect(clusterNet).NotTo(BeNil()) Expect(clusterNet.NetworkPlugin).To(Equal("canal-flannel")) Expect(clusterNet.PodCIDRs).To(Equal([]string{testCannalFlannelPodCIDR})) + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) - When("There is a kubeapi pod at least ", func() { + When("There is a kube-api pod", func() { - It("Should return the ClusterNetwork structure with ServiceCIDRs too", func() { + It("Should return the ClusterNetwork structure with the pod CIDR and the service CIDR", func() { clusterNet := testDiscoverWith( &canalFlannelCfgMap, fakePod("kube-apiserver", []string{"kube-apiserver", "--service-cluster-ip-range=" + testServiceCIDR}, []v1.EnvVar{}), @@ -53,14 +53,14 @@ var _ = Describe("discoverCanalFlannelNetwork", func() { }) func testDiscoverCanalFlannelWith(objects ...runtime.Object) *ClusterNetwork { - clientSet := fake.NewSimpleClientset(objects...) + clientSet := newTestClient(objects...) clusterNet, err := discoverCanalFlannelNetwork(clientSet) Expect(err).NotTo(HaveOccurred()) return clusterNet } func testDiscoverWith(objects ...runtime.Object) *ClusterNetwork { - clientSet := fake.NewSimpleClientset(objects...) + clientSet := newTestClient(objects...) clusterNet, err := Discover(nil, clientSet, nil, "") Expect(err).NotTo(HaveOccurred()) return clusterNet diff --git a/pkg/discovery/network/generic.go b/pkg/discovery/network/generic.go index fabf7aeb4..868fa8435 100644 --- a/pkg/discovery/network/generic.go +++ b/pkg/discovery/network/generic.go @@ -17,9 +17,14 @@ limitations under the License. package network import ( + "fmt" + "os" + "regexp" + "github.com/pkg/errors" v1 "k8s.io/api/core/v1" v1meta "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/kubernetes" ) @@ -59,6 +64,11 @@ func findClusterIPRange(clientSet kubernetes.Interface) (string, error) { return clusterIPRange, err } + clusterIPRange, err = findClusterIPRangeFromServiceCreation(clientSet) + if err != nil || clusterIPRange != "" { + return clusterIPRange, err + } + return "", nil } @@ -66,6 +76,61 @@ func findClusterIPRangeFromApiserver(clientSet kubernetes.Interface) (string, er return findPodCommandParameter(clientSet, "component=kube-apiserver", "--service-cluster-ip-range") } +func findClusterIPRangeFromServiceCreation(clientSet kubernetes.Interface) (string, error) { + // find service cidr based on https://stackoverflow.com/questions/44190607/how-do-you-find-the-cluster-service-cidr-of-a-kubernetes-cluster + invalidSvcSpec := &v1.Service{ + ObjectMeta: v1meta.ObjectMeta{ + Name: "invalid-svc", + }, + Spec: v1.ServiceSpec{ + ClusterIP: "1.1.1.1", + Ports: []v1.ServicePort{ + { + Port: 443, + TargetPort: intstr.IntOrString{ + IntVal: 443, + }, + }, + }, + }, + } + + ns := os.Getenv("WATCH_NAMESPACE") + // WATCH_NAMESPACE env should be set to operator's namespace, if running in operator + if ns == "" { + // otherwise, it should be called from subctl command, so use "default" namespace + ns = "default" + } + + // create service to the namespace + _, err := clientSet.CoreV1().Services(ns).Create(invalidSvcSpec) + + // creating invalid service didn't fail as expected + if err == nil { + return "", fmt.Errorf("creating invalid service(%v) didn't fail", invalidSvcSpec) + } + + return parseServiceCIDRFrom(err.Error()) +} + +func parseServiceCIDRFrom(msg string) (string, error) { + // expected msg is below: + // "The Service \"invalid-svc\" is invalid: spec.clusterIPs: Invalid value: []string{\"1.1.1.1\"}: + // failed to allocated ip:1.1.1.1 with error:provided IP is not in the valid range. + // The range of valid IPs is 10.45.0.0/16" + // expected matched string is below: + // 10.45.0.0/16 + re := regexp.MustCompile(".*valid IPs is (.*)$") + + match := re.FindStringSubmatch(msg) + if match == nil { + return "", fmt.Errorf("parsing (%s) failed. it doesn't match with %v", msg, re) + } + + // returns first matching string + return match[1], nil +} + func findPodIPRange(clientSet kubernetes.Interface) (string, error) { podIPRange, err := findPodIPRangeKubeController(clientSet) if err != nil || podIPRange != "" { diff --git a/pkg/discovery/network/generic_test.go b/pkg/discovery/network/generic_test.go index 60fd8e856..b401275a3 100644 --- a/pkg/discovery/network/generic_test.go +++ b/pkg/discovery/network/generic_test.go @@ -17,9 +17,13 @@ limitations under the License. package network import ( + "fmt" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/fake" + fakecorev1 "k8s.io/client-go/kubernetes/typed/core/v1/fake" + "k8s.io/client-go/testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -27,44 +31,79 @@ import ( const testPodCIDR = "1.2.3.4/16" const testServiceCIDR = "4.5.6.7/16" +const testServiceCIDRFromService = "7.8.9.10/16" var _ = Describe("discoverGenericNetwork", func() { - When("There are no generic k8s pods to look at", func() { - It("Should return nil cluster network", func() { - clusterNet := testDiscoverGenericWith() - Expect(clusterNet).To(BeNil()) - }) - }) - When("There is a kube-proxy with no expected parameters", func() { - It("Should return nil cluster network", func() { - clusterNet := testDiscoverGenericWith( + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( fakePod("kube-proxy", []string{"kube-proxy", "--cluster-ABCD=1.2.3.4"}, []v1.EnvVar{}), ) - Expect(clusterNet).To(BeNil()) + Expect(clusterNet).NotTo(BeNil()) + }) + + It("Should return the ClusterNetwork structure with empty PodCIDRs", func() { + Expect(clusterNet.PodCIDRs).To(BeEmpty()) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) When("There is a kube-controller with no expected parameters", func() { - It("Should return nil cluster network", func() { - clusterNet := testDiscoverGenericWith( - fakePod("kube-controller", []string{"kube-controller", "--cluster-ABCD=1.2.3.4"}, []v1.EnvVar{}), + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( + fakePod("kube-controller-manager", []string{"kube-controller-manager", "--cluster-ABCD=1.2.3.4"}, []v1.EnvVar{}), ) - Expect(clusterNet).To(BeNil()) + Expect(clusterNet).NotTo(BeNil()) + }) + + It("Should return the ClusterNetwork structure with empty PodCIDRs", func() { + Expect(clusterNet.PodCIDRs).To(BeEmpty()) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) When("There is a kube-api with no expected parameters", func() { - It("Should return nil cluster network", func() { - clusterNet := testDiscoverGenericWith( - fakePod("kube-controller", []string{"kube-api", "--cluster-ABCD=1.2.3.4"}, []v1.EnvVar{}), + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( + fakePod("kube-apiserver", []string{"kube-apiserver", "--cluster-ABCD=1.2.3.4"}, []v1.EnvVar{}), ) - Expect(clusterNet).To(BeNil()) + Expect(clusterNet).NotTo(BeNil()) + }) + + It("Should return the ClusterNetwork structure with empty PodCIDRs", func() { + Expect(clusterNet.PodCIDRs).To(BeEmpty()) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) When("There is a kube-controller pod with the right parameter", func() { - var clusterNet *ClusterNetwork BeforeEach(func() { @@ -74,7 +113,7 @@ var _ = Describe("discoverGenericNetwork", func() { Expect(clusterNet).NotTo(BeNil()) }) - It("Should return the ClusterNetwork structure with PodCIDR", func() { + It("Should return the ClusterNetwork structure with pod CIDR", func() { Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) }) @@ -82,13 +121,12 @@ var _ = Describe("discoverGenericNetwork", func() { Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) }) - It("Should return the ClusterNetwork structure with empty service CIDR", func() { - Expect(clusterNet.ServiceCIDRs).To(BeEmpty()) + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) When("There is a kube-proxy pod but no kube-controller", func() { - var clusterNet *ClusterNetwork BeforeEach(func() { @@ -106,10 +144,9 @@ var _ = Describe("discoverGenericNetwork", func() { Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) }) - It("Should return the ClusterNetwork structure with empty service CIDR", func() { - Expect(clusterNet.ServiceCIDRs).To(BeEmpty()) + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) - }) When("There is a kubeapi pod", func() { @@ -133,11 +170,9 @@ var _ = Describe("discoverGenericNetwork", func() { It("Should return the ClusterNetwork structure with empty PodCIDRs", func() { Expect(clusterNet.PodCIDRs).To(BeEmpty()) }) - }) When("There is a kube-proxy and api pods", func() { - var clusterNet *ClusterNetwork BeforeEach(func() { @@ -158,17 +193,30 @@ var _ = Describe("discoverGenericNetwork", func() { }) }) - When("There is no pod cidr information on node", func() { - It("Should return nil cluster network", func() { - clusterNet := testDiscoverGenericWith( + When("No pod CIDR information exists on any node", func() { + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith( fakeNode("node1", ""), fakeNode("node2", ""), ) - Expect(clusterNet).To(BeNil()) + }) + + It("Should return the ClusterNetwork structure with empty PodCIDRs", func() { + Expect(clusterNet.PodCIDRs).To(BeEmpty()) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) - When("There is pod cidr information on any of nodes", func() { + When("Pod CIDR information exists on a node", func() { var clusterNet *ClusterNetwork BeforeEach(func() { @@ -178,7 +226,7 @@ var _ = Describe("discoverGenericNetwork", func() { ) }) - It("Should return the ClusterNetwork structure with PodCIDR", func() { + It("Should return the ClusterNetwork structure with the pod CIDR", func() { Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) }) @@ -186,12 +234,12 @@ var _ = Describe("discoverGenericNetwork", func() { Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) }) - It("Should return the ClusterNetwork structure with empty service CIDR", func() { - Expect(clusterNet.ServiceCIDRs).To(BeEmpty()) + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) }) - When("There is pod cidr information on any of nodes and there is kubeapi pod", func() { + When("Both pod and service CIDR information exists", func() { var clusterNet *ClusterNetwork BeforeEach(func() { @@ -211,11 +259,70 @@ var _ = Describe("discoverGenericNetwork", func() { }) }) + When("No kube-api pod exists and invalid service creation returns no error", func() { + It("Should return error and nil cluster network", func() { + clientSet := fake.NewSimpleClientset() + clusterNet, err := discoverGenericNetwork(clientSet) + Expect(err).To(HaveOccurred()) + Expect(clusterNet).To(BeNil()) + }) + }) + + When("No kube-api pod exists and invalid service creation returns an unexpected error", func() { + It("Should return error and nil cluster network", func() { + clientSet := fake.NewSimpleClientset() + // Inject error for create services to return expectedErr + clientSet.CoreV1().(*fakecorev1.FakeCoreV1).PrependReactor("create", "services", + func(action testing.Action) (handled bool, ret runtime.Object, err error) { + return true, + nil, + fmt.Errorf("%s", testServiceCIDR) + }) + clusterNet, err := discoverGenericNetwork(clientSet) + Expect(err).To(HaveOccurred()) + Expect(clusterNet).To(BeNil()) + }) + }) + + When("No kube-api pod exists and invalid service creation returns the expected error", func() { + var clusterNet *ClusterNetwork + + BeforeEach(func() { + clusterNet = testDiscoverGenericWith() + }) + + It("Should return the ClusterNetwork structure with empty pod CIDR", func() { + Expect(clusterNet.PodCIDRs).To(BeEmpty()) + }) + + It("Should identify the networkplugin as generic", func() { + Expect(clusterNet.NetworkPlugin).To(BeIdenticalTo("generic")) + }) + + It("Should return the ClusterNetwork structure with the service CIDR", func() { + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) + }) + }) }) func testDiscoverGenericWith(objects ...runtime.Object) *ClusterNetwork { - clientSet := fake.NewSimpleClientset(objects...) + clientSet := newTestClient(objects...) clusterNet, err := discoverGenericNetwork(clientSet) Expect(err).NotTo(HaveOccurred()) return clusterNet } + +func newTestClient(objects ...runtime.Object) *fake.Clientset { + clientSet := fake.NewSimpleClientset(objects...) + // Inject error for create services to return expectedErr + clientSet.CoreV1().(*fakecorev1.FakeCoreV1).PrependReactor("create", "services", + func(action testing.Action) (handled bool, ret runtime.Object, err error) { + return true, + nil, + fmt.Errorf("The Service \"invalid-svc\" is invalid: "+ + "spec.clusterIPs: Invalid value: []string{\"1.1.1.1\"}: failed to "+ + "allocated ip:1.1.1.1 with error:provided IP is not in the valid range. "+ + "The range of valid IPs is %s", testServiceCIDRFromService) + }) + return clientSet +} diff --git a/pkg/discovery/network/weavenet_test.go b/pkg/discovery/network/weavenet_test.go index a551bc1d5..697fb7e02 100644 --- a/pkg/discovery/network/weavenet_test.go +++ b/pkg/discovery/network/weavenet_test.go @@ -21,7 +21,6 @@ import ( . "github.com/onsi/gomega" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" - "k8s.io/client-go/kubernetes/fake" ) var _ = Describe("discoverWeaveNetwork", func() { @@ -42,9 +41,9 @@ var _ = Describe("discoverWeaveNetwork", func() { ) Expect(clusterNet).NotTo(BeNil()) }) - It("Should return the ClusterNetwork structure with PodCIDR and no ServiceCIDRs", func() { + It("Should return the ClusterNetwork structure with the pod CIDR and the service CIDR", func() { Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) - Expect(clusterNet.ServiceCIDRs).To(BeEmpty()) + Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDRFromService})) }) It("Should identify the networkplugin as weave-net", func() { @@ -64,7 +63,7 @@ var _ = Describe("discoverWeaveNetwork", func() { Expect(clusterNet).NotTo(BeNil()) }) - It("Should return ClusterNetwork with Pod and Service CIDRs", func() { + It("Should return ClusterNetwork with the pod CIDR and the service CIDR", func() { Expect(clusterNet.ServiceCIDRs).To(Equal([]string{testServiceCIDR})) Expect(clusterNet.PodCIDRs).To(Equal([]string{testPodCIDR})) }) @@ -76,7 +75,7 @@ var _ = Describe("discoverWeaveNetwork", func() { }) func testDiscoverWeaveWith(objects ...runtime.Object) *ClusterNetwork { - clientSet := fake.NewSimpleClientset(objects...) + clientSet := newTestClient(objects...) clusterNet, err := discoverWeaveNetwork(clientSet) Expect(err).NotTo(HaveOccurred()) return clusterNet