From 7b62d000a4d9c37138143eda4e2f4f653e4fb299 Mon Sep 17 00:00:00 2001 From: "Dr. Stefan Schimanski" Date: Mon, 3 Jul 2023 14:51:42 +0200 Subject: [PATCH] MOVE: pkg/controlplane: move bootstrap controller to controllers/kubernetesservice --- pkg/controlplane/client_util.go | 43 -- .../kubernetesservice}/controller.go | 2 +- .../kubernetesservice/controller_test.go | 436 ++++++++++++++++++ pkg/controlplane/controller_test.go | 417 +---------------- 4 files changed, 439 insertions(+), 459 deletions(-) delete mode 100644 pkg/controlplane/client_util.go rename pkg/controlplane/{ => controller/kubernetesservice}/controller.go (99%) create mode 100644 pkg/controlplane/controller/kubernetesservice/controller_test.go diff --git a/pkg/controlplane/client_util.go b/pkg/controlplane/client_util.go deleted file mode 100644 index 20bf644b3cb..00000000000 --- a/pkg/controlplane/client_util.go +++ /dev/null @@ -1,43 +0,0 @@ -/* -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 controlplane - -import ( - "context" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - corev1client "k8s.io/client-go/kubernetes/typed/core/v1" -) - -func createNamespaceIfNeeded(c corev1client.NamespacesGetter, ns string) error { - if _, err := c.Namespaces().Get(context.TODO(), ns, metav1.GetOptions{}); err == nil { - // the namespace already exists - return nil - } - newNs := &corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: ns, - Namespace: "", - }, - } - _, err := c.Namespaces().Create(context.TODO(), newNs, metav1.CreateOptions{}) - if err != nil && errors.IsAlreadyExists(err) { - err = nil - } - return err -} diff --git a/pkg/controlplane/controller.go b/pkg/controlplane/controller/kubernetesservice/controller.go similarity index 99% rename from pkg/controlplane/controller.go rename to pkg/controlplane/controller/kubernetesservice/controller.go index 3b2f8d8e4e1..fc5adee22b3 100644 --- a/pkg/controlplane/controller.go +++ b/pkg/controlplane/controller/kubernetesservice/controller.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package controlplane +package kubernetesservice import ( "context" diff --git a/pkg/controlplane/controller/kubernetesservice/controller_test.go b/pkg/controlplane/controller/kubernetesservice/controller_test.go new file mode 100644 index 00000000000..2cf20f3a9ef --- /dev/null +++ b/pkg/controlplane/controller/kubernetesservice/controller_test.go @@ -0,0 +1,436 @@ +/* +Copyright 2014 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 kubernetesservice + +import ( + "reflect" + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + netutils "k8s.io/utils/net" +) + +func TestCreateOrUpdateMasterService(t *testing.T) { + singleStack := corev1.IPFamilyPolicySingleStack + ns := metav1.NamespaceDefault + om := func(name string) metav1.ObjectMeta { + return metav1.ObjectMeta{Namespace: ns, Name: name} + } + + createTests := []struct { + testName string + serviceName string + servicePorts []corev1.ServicePort + serviceType corev1.ServiceType + expectCreate *corev1.Service // nil means none expected + }{ + { + testName: "service does not exist", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + expectCreate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + IPFamilyPolicy: &singleStack, + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + } + for _, test := range createTests { + master := Controller{} + fakeClient := fake.NewSimpleClientset() + master.client = fakeClient + master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, false) + creates := []core.CreateAction{} + for _, action := range fakeClient.Actions() { + if action.GetVerb() == "create" { + creates = append(creates, action.(core.CreateAction)) + } + } + if test.expectCreate != nil { + if len(creates) != 1 { + t.Errorf("case %q: unexpected creations: %v", test.testName, creates) + } else { + obj := creates[0].GetObject() + if e, a := test.expectCreate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + } + if test.expectCreate == nil && len(creates) > 1 { + t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates) + } + } + + reconcileTests := []struct { + testName string + serviceName string + servicePorts []corev1.ServicePort + serviceType corev1.ServiceType + service *corev1.Service + expectUpdate *corev1.Service // nil means none expected + }{ + { + testName: "service definition wrong port", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8000, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition missing port", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + {Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + {Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition incorrect port", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "bar", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt32(1000)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition incorrect port name", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt32(1000)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition incorrect target port", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition incorrect protocol", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "UDP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition has incorrect type", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeNodePort, + }, + }, + expectUpdate: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + }, + { + testName: "service definition satisfies", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: nil, + }, + } + for _, test := range reconcileTests { + master := Controller{} + fakeClient := fake.NewSimpleClientset(test.service) + master.client = fakeClient + err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, true) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) + } + updates := []core.UpdateAction{} + for _, action := range fakeClient.Actions() { + if action.GetVerb() == "update" { + updates = append(updates, action.(core.UpdateAction)) + } + } + if test.expectUpdate != nil { + if len(updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, updates) + } else { + obj := updates[0].GetObject() + if e, a := test.expectUpdate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + } + if test.expectUpdate == nil && len(updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates) + } + } + + nonReconcileTests := []struct { + testName string + serviceName string + servicePorts []corev1.ServicePort + serviceType corev1.ServiceType + service *corev1.Service + expectUpdate *corev1.Service // nil means none expected + }{ + { + testName: "service definition wrong port, no expected update", + serviceName: "foo", + servicePorts: []corev1.ServicePort{ + {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, + }, + serviceType: corev1.ServiceTypeClusterIP, + service: &corev1.Service{ + ObjectMeta: om("foo"), + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + {Name: "foo", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, + }, + Selector: nil, + ClusterIP: "1.2.3.4", + SessionAffinity: corev1.ServiceAffinityNone, + Type: corev1.ServiceTypeClusterIP, + }, + }, + expectUpdate: nil, + }, + } + for _, test := range nonReconcileTests { + master := Controller{} + fakeClient := fake.NewSimpleClientset(test.service) + master.client = fakeClient + err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, false) + if err != nil { + t.Errorf("case %q: unexpected error: %v", test.testName, err) + } + updates := []core.UpdateAction{} + for _, action := range fakeClient.Actions() { + if action.GetVerb() == "update" { + updates = append(updates, action.(core.UpdateAction)) + } + } + if test.expectUpdate != nil { + if len(updates) != 1 { + t.Errorf("case %q: unexpected updates: %v", test.testName, updates) + } else { + obj := updates[0].GetObject() + if e, a := test.expectUpdate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { + t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) + } + } + } + if test.expectUpdate == nil && len(updates) > 0 { + t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates) + } + } +} diff --git a/pkg/controlplane/controller_test.go b/pkg/controlplane/controller_test.go index f8588e3f522..340d27c03c4 100644 --- a/pkg/controlplane/controller_test.go +++ b/pkg/controlplane/controller_test.go @@ -17,430 +17,17 @@ limitations under the License. package controlplane import ( - "reflect" "testing" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" genericapiserver "k8s.io/apiserver/pkg/server" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/kubernetes/fake" - core "k8s.io/client-go/testing" + netutils "k8s.io/utils/net" + "k8s.io/kubernetes/pkg/controlplane/reconcilers" corerest "k8s.io/kubernetes/pkg/registry/core/rest" - netutils "k8s.io/utils/net" ) -func TestCreateOrUpdateMasterService(t *testing.T) { - singleStack := corev1.IPFamilyPolicySingleStack - ns := metav1.NamespaceDefault - om := func(name string) metav1.ObjectMeta { - return metav1.ObjectMeta{Namespace: ns, Name: name} - } - - createTests := []struct { - testName string - serviceName string - servicePorts []corev1.ServicePort - serviceType corev1.ServiceType - expectCreate *corev1.Service // nil means none expected - }{ - { - testName: "service does not exist", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - expectCreate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - IPFamilyPolicy: &singleStack, - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - } - for _, test := range createTests { - master := Controller{} - fakeClient := fake.NewSimpleClientset() - master.client = fakeClient - master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, false) - creates := []core.CreateAction{} - for _, action := range fakeClient.Actions() { - if action.GetVerb() == "create" { - creates = append(creates, action.(core.CreateAction)) - } - } - if test.expectCreate != nil { - if len(creates) != 1 { - t.Errorf("case %q: unexpected creations: %v", test.testName, creates) - } else { - obj := creates[0].GetObject() - if e, a := test.expectCreate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected create:\n%#v\ngot:\n%#v\n", test.testName, e, a) - } - } - } - if test.expectCreate == nil && len(creates) > 1 { - t.Errorf("case %q: no create expected, yet saw: %v", test.testName, creates) - } - } - - reconcileTests := []struct { - testName string - serviceName string - servicePorts []corev1.ServicePort - serviceType corev1.ServiceType - service *corev1.Service - expectUpdate *corev1.Service // nil means none expected - }{ - { - testName: "service definition wrong port", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8000, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition missing port", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - {Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - {Name: "baz", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition incorrect port", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "bar", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt32(1000)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition incorrect port name", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 1000, Protocol: "UDP", TargetPort: intstr.FromInt32(1000)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition incorrect target port", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition incorrect protocol", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "UDP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition has incorrect type", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeNodePort, - }, - }, - expectUpdate: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - }, - { - testName: "service definition satisfies", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: nil, - }, - } - for _, test := range reconcileTests { - master := Controller{} - fakeClient := fake.NewSimpleClientset(test.service) - master.client = fakeClient - err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, true) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - updates := []core.UpdateAction{} - for _, action := range fakeClient.Actions() { - if action.GetVerb() == "update" { - updates = append(updates, action.(core.UpdateAction)) - } - } - if test.expectUpdate != nil { - if len(updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, updates) - } else { - obj := updates[0].GetObject() - if e, a := test.expectUpdate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) - } - } - } - if test.expectUpdate == nil && len(updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates) - } - } - - nonReconcileTests := []struct { - testName string - serviceName string - servicePorts []corev1.ServicePort - serviceType corev1.ServiceType - service *corev1.Service - expectUpdate *corev1.Service // nil means none expected - }{ - { - testName: "service definition wrong port, no expected update", - serviceName: "foo", - servicePorts: []corev1.ServicePort{ - {Name: "foo", Port: 8080, Protocol: "TCP", TargetPort: intstr.FromInt32(8080)}, - }, - serviceType: corev1.ServiceTypeClusterIP, - service: &corev1.Service{ - ObjectMeta: om("foo"), - Spec: corev1.ServiceSpec{ - Ports: []corev1.ServicePort{ - {Name: "foo", Port: 1000, Protocol: "TCP", TargetPort: intstr.FromInt32(1000)}, - }, - Selector: nil, - ClusterIP: "1.2.3.4", - SessionAffinity: corev1.ServiceAffinityNone, - Type: corev1.ServiceTypeClusterIP, - }, - }, - expectUpdate: nil, - }, - } - for _, test := range nonReconcileTests { - master := Controller{} - fakeClient := fake.NewSimpleClientset(test.service) - master.client = fakeClient - err := master.CreateOrUpdateMasterServiceIfNeeded(test.serviceName, netutils.ParseIPSloppy("1.2.3.4"), test.servicePorts, test.serviceType, false) - if err != nil { - t.Errorf("case %q: unexpected error: %v", test.testName, err) - } - updates := []core.UpdateAction{} - for _, action := range fakeClient.Actions() { - if action.GetVerb() == "update" { - updates = append(updates, action.(core.UpdateAction)) - } - } - if test.expectUpdate != nil { - if len(updates) != 1 { - t.Errorf("case %q: unexpected updates: %v", test.testName, updates) - } else { - obj := updates[0].GetObject() - if e, a := test.expectUpdate.Spec, obj.(*corev1.Service).Spec; !reflect.DeepEqual(e, a) { - t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a) - } - } - } - if test.expectUpdate == nil && len(updates) > 0 { - t.Errorf("case %q: no update expected, yet saw: %v", test.testName, updates) - } - } -} - func Test_completedConfig_NewBootstrapController(t *testing.T) { - _, ipv4cidr, err := netutils.ParseCIDRSloppy("192.168.0.0/24") if err != nil { t.Fatalf("Unexpected error %v", err)