bugfix: initialize secondary range registry with the right value

When MultiCIDRServiceAllocator feature is enabled, we added an
additional feature gate DisableAllocatorDualWrite that allows to enable
a mirror behavior on the old allocator to deal with problems during
cluster upgrades.

During the implementation the secondary range of the legacy allocator
was initialized with the valuye of the primary range, hence, when a
Service tried to allocate a new IP on the secondary range, it succeded
in the new ip allocator but failed when it tried to allocate the same IP
on the legacy allocator, since it has a different range.

Expand the integration test that run over all the combinations of
Service ClusterIP possibilities to run with all the possible
combinations of the feature gates.

The integration test need to change the way of starting the apiserver
otherwise it will timeout.
This commit is contained in:
Antonio Ojea 2024-09-24 15:19:50 +00:00
parent 5973accf48
commit 7a9bca3888
2 changed files with 1096 additions and 975 deletions

View File

@ -440,7 +440,7 @@ func (c *Config) newServiceIPAllocators() (registries rangeRegistries, primaryCl
if err != nil {
return nil, err
}
rangeRegistry.Range = serviceClusterIPRange.String()
rangeRegistry.Range = c.Services.SecondaryClusterIPRange.String()
if len(rangeRegistry.ResourceVersion) == 0 {
klog.Infof("kube-apiserver started with IP allocator and dual write enabled but bitmap allocator does not exist, recreating it ...")
err := etcd.CreateOrUpdate(rangeRegistry)

View File

@ -31,11 +31,11 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
"k8s.io/client-go/kubernetes"
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
"k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/test/integration/framework"
"k8s.io/kubernetes/test/utils/ktesting"
netutils "k8s.io/utils/net"
@ -43,16 +43,29 @@ import (
// TestCreateServiceSingleStackIPv4 test the Service dualstackness in an IPv4 SingleStack cluster
func TestCreateServiceSingleStackIPv4(t *testing.T) {
for _, enableMultiServiceCIDR := range []bool{false, true} {
for _, disableAllocatorDualWrite := range []bool{false, true} {
t.Run(fmt.Sprintf("MultiServiceCIDR=%v DisableAllocatorDualWrite=%v", enableMultiServiceCIDR, disableAllocatorDualWrite), func(t *testing.T) {
// Create an IPv4 single stack control-plane
serviceCIDR := "10.0.0.0/16"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = serviceCIDR
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
fmt.Sprintf("--runtime-config=networking.k8s.io/v1beta1=%v", enableMultiServiceCIDR),
"--service-cluster-ip-range=10.0.0.0/16",
"--advertise-address=10.1.1.1",
"--disable-admission-plugins=ServiceAccount",
fmt.Sprintf("--feature-gates=%s=%v,%s=%v", features.MultiCIDRServiceAllocator, enableMultiServiceCIDR, features.DisableAllocatorDualWrite, disableAllocatorDualWrite),
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -267,21 +280,36 @@ func TestCreateServiceSingleStackIPv4(t *testing.T) {
}
})
}
})
}
}
}
// TestCreateServiceDualStackIPv6 test the Service dualstackness in an IPv6 only DualStack cluster
func TestCreateServiceDualStackIPv6(t *testing.T) {
// Create an IPv6 only dual stack control-plane
serviceCIDR := "2001:db8:1::/112"
// TestCreateServiceSingleStackIPv6 test the Service dualstackness in an IPv6 only DualStack cluster
func TestCreateServiceSingleStackIPv6(t *testing.T) {
for _, enableMultiServiceCIDR := range []bool{false, true} {
for _, disableAllocatorDualWrite := range []bool{false, true} {
t.Run(fmt.Sprintf("MultiServiceCIDR=%v DisableAllocatorDualWrite=%v", enableMultiServiceCIDR, disableAllocatorDualWrite), func(t *testing.T) {
// Create an IPv6 only control-plane
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = serviceCIDR
opts.GenericServerRunOptions.AdvertiseAddress = netutils.ParseIPSloppy("2001:db8::10")
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
fmt.Sprintf("--runtime-config=networking.k8s.io/v1beta1=%v", enableMultiServiceCIDR),
"--service-cluster-ip-range=2001:db8:1::/112",
"--advertise-address=2001:db8::10",
"--disable-admission-plugins=ServiceAccount",
fmt.Sprintf("--feature-gates=%s=%v,%s=%v", features.MultiCIDRServiceAllocator, enableMultiServiceCIDR, features.DisableAllocatorDualWrite, disableAllocatorDualWrite),
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -483,21 +511,36 @@ func TestCreateServiceDualStackIPv6(t *testing.T) {
}
})
}
})
}
}
}
// TestCreateServiceDualStackIPv4IPv6 test the Service dualstackness in a IPv4IPv6 DualStack cluster
func TestCreateServiceDualStackIPv4IPv6(t *testing.T) {
for _, enableMultiServiceCIDR := range []bool{false, true} {
for _, disableAllocatorDualWrite := range []bool{false, true} {
t.Run(fmt.Sprintf("MultiServiceCIDR=%v DisableAllocatorDualWrite=%v", enableMultiServiceCIDR, disableAllocatorDualWrite), func(t *testing.T) {
// Create an IPv4IPv6 dual stack control-plane
serviceCIDR := "10.0.0.0/16"
secondaryServiceCIDR := "2001:db8:1::/112"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
fmt.Sprintf("--runtime-config=networking.k8s.io/v1beta1=%v", enableMultiServiceCIDR),
"--service-cluster-ip-range=10.0.0.0/16,2001:db8:1::/112",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
fmt.Sprintf("--feature-gates=%s=%v,%s=%v", features.MultiCIDRServiceAllocator, enableMultiServiceCIDR, features.DisableAllocatorDualWrite, disableAllocatorDualWrite),
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -747,22 +790,36 @@ func TestCreateServiceDualStackIPv4IPv6(t *testing.T) {
}
})
}
})
}
}
}
// TestCreateServiceDualStackIPv6IPv4 test the Service dualstackness in a IPv6IPv4 DualStack cluster
func TestCreateServiceDualStackIPv6IPv4(t *testing.T) {
for _, enableMultiServiceCIDR := range []bool{false, true} {
for _, disableAllocatorDualWrite := range []bool{false, true} {
t.Run(fmt.Sprintf("MultiServiceCIDR=%v DisableAllocatorDualWrite=%v", enableMultiServiceCIDR, disableAllocatorDualWrite), func(t *testing.T) {
// Create an IPv6IPv4 dual stack control-plane
serviceCIDR := "2001:db8:1::/112"
secondaryServiceCIDR := "10.0.0.0/16"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
opts.GenericServerRunOptions.AdvertiseAddress = netutils.ParseIPSloppy("2001:db8::10")
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
fmt.Sprintf("--runtime-config=networking.k8s.io/v1beta1=%v", enableMultiServiceCIDR),
"--service-cluster-ip-range=2001:db8:1::/112,10.0.0.0/16",
"--advertise-address=2001:db8::10",
"--disable-admission-plugins=ServiceAccount",
fmt.Sprintf("--feature-gates=%s=%v,%s=%v", features.MultiCIDRServiceAllocator, enableMultiServiceCIDR, features.DisableAllocatorDualWrite, disableAllocatorDualWrite),
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -967,21 +1024,31 @@ func TestCreateServiceDualStackIPv6IPv4(t *testing.T) {
}
})
}
})
}
}
}
// TestUpgradeDowngrade tests upgrading and downgrading a service from/to dual-stack
func TestUpgradeDowngrade(t *testing.T) {
// Create an IPv4IPv6 dual stack control-plane
serviceCIDR := "10.0.0.0/16"
secondaryServiceCIDR := "2001:db8:1::/112"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=10.0.0.0/16,2001:db8:1::/112",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1012,7 +1079,7 @@ func TestUpgradeDowngrade(t *testing.T) {
}
// create a service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
if err != nil {
t.Fatalf("unexpected error while creating service:%v", err)
}
@ -1076,16 +1143,23 @@ func TestUpgradeDowngrade(t *testing.T) {
// may not clear ClusterIPs
func TestConvertToFromExternalName(t *testing.T) {
// Create an IPv4IPv6 dual stack control-plane
serviceCIDR := "10.0.0.0/16"
secondaryServiceCIDR := "2001:db8:1::/112"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=10.0.0.0/16,2001:db8:1::/112",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1115,7 +1189,7 @@ func TestConvertToFromExternalName(t *testing.T) {
}
// create a service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
if err != nil {
t.Fatalf("unexpected error while creating service:%v", err)
}
@ -1158,16 +1232,23 @@ func TestConvertToFromExternalName(t *testing.T) {
// TestPreferDualStack preferDualstack on create and update
func TestPreferDualStack(t *testing.T) {
// Create an IPv4IPv6 dual stack control-plane
serviceCIDR := "10.0.0.0/16"
secondaryServiceCIDR := "2001:db8:1::/112"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=10.0.0.0/16,2001:db8:1::/112",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1201,7 +1282,7 @@ func TestPreferDualStack(t *testing.T) {
}
// create a service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
if err != nil {
t.Fatalf("unexpected error while creating service:%v", err)
}
@ -1233,15 +1314,23 @@ type labelsForMergePatch struct {
// tests an update service while dualstack flag is off
func TestServiceUpdate(t *testing.T) {
// Create an IPv4 single stack control-plane
serviceCIDR := "10.0.0.0/16"
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.ServiceClusterIPRanges = serviceCIDR
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=10.0.0.0/16",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1271,7 +1360,7 @@ func TestServiceUpdate(t *testing.T) {
}
// create the service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
// if no error was expected validate the service otherwise return
if err != nil {
t.Errorf("unexpected error creating service:%v", err)
@ -1393,18 +1482,23 @@ func validateServiceAndClusterIPFamily(svc *v1.Service, expectedIPFamilies []v1.
func TestUpgradeServicePreferToDualStack(t *testing.T) {
sharedEtcd := framework.SharedEtcd()
tCtx := ktesting.Init(t)
// Create an IPv4 only dual stack control-plane
serviceCIDR := "192.168.0.0/24"
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.Etcd.StorageConfig = *sharedEtcd
opts.ServiceClusterIPRanges = serviceCIDR
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=192.168.0.0/24",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
sharedEtcd)
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1439,7 +1533,7 @@ func TestUpgradeServicePreferToDualStack(t *testing.T) {
}
// create the service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
@ -1453,17 +1547,21 @@ func TestUpgradeServicePreferToDualStack(t *testing.T) {
}
// reconfigure the apiserver to be dual-stack
tearDownFn()
s.TearDownFn()
secondaryServiceCIDR := "2001:db8:1::/112"
client, _, tearDownFn = framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.Etcd.StorageConfig = *sharedEtcd
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
s = kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=192.168.0.0/24,2001:db8:1::/112",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
sharedEtcd)
defer s.TearDownFn()
client, err = kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err = wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1487,20 +1585,24 @@ func TestUpgradeServicePreferToDualStack(t *testing.T) {
}
func TestDowngradeServicePreferToDualStack(t *testing.T) {
sharedEtcd := framework.SharedEtcd()
tCtx := ktesting.Init(t)
// Create a dual stack control-plane
serviceCIDR := "192.168.0.0/24"
secondaryServiceCIDR := "2001:db8:1::/112"
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.Etcd.StorageConfig = *sharedEtcd
opts.ServiceClusterIPRanges = fmt.Sprintf("%s,%s", serviceCIDR, secondaryServiceCIDR)
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=192.168.0.0/24,2001:db8:1::/112",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
etcdOptions)
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err := wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
@ -1533,7 +1635,7 @@ func TestDowngradeServicePreferToDualStack(t *testing.T) {
},
}
// create the service
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
_, err = client.CoreV1().Services(metav1.NamespaceDefault).Create(tCtx, svc, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
@ -1545,18 +1647,24 @@ func TestDowngradeServicePreferToDualStack(t *testing.T) {
if err := validateServiceAndClusterIPFamily(svc, []v1.IPFamily{v1.IPv4Protocol, v1.IPv6Protocol}); err != nil {
t.Fatalf("Unexpected error validating the service %s %v", svc.Name, err)
}
// reconfigure the apiserver to be sinlge stack
tearDownFn()
// reconfigure the apiserver to be single stack
s.TearDownFn()
// reset secondary
client, _, tearDownFn = framework.StartTestServer(tCtx, t, framework.TestServerSetup{
ModifyServerRunOptions: func(opts *options.ServerRunOptions) {
opts.Etcd.StorageConfig = *sharedEtcd
opts.ServiceClusterIPRanges = serviceCIDR
s = kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=192.168.0.0/24",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
})
defer tearDownFn()
etcdOptions)
defer s.TearDownFn()
client, err = kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
// Wait until the default "kubernetes" service is created.
if err = wait.Poll(250*time.Millisecond, time.Minute, func() (bool, error) {
_, err := client.CoreV1().Services(metav1.NamespaceDefault).Get(tCtx, "kubernetes", metav1.GetOptions{})
@ -1589,8 +1697,22 @@ type specMergePatch struct {
// tests success when converting ClusterIP:Headless service to ExternalName
func Test_ServiceChangeTypeHeadlessToExternalNameWithPatch(t *testing.T) {
tCtx := ktesting.Init(t)
client, _, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{})
defer tearDownFn()
etcdOptions := framework.SharedEtcd()
apiServerOptions := kubeapiservertesting.NewDefaultTestServerOptions()
s := kubeapiservertesting.StartTestServerOrDie(t,
apiServerOptions,
[]string{
"--service-cluster-ip-range=192.168.0.0/24",
"--advertise-address=10.0.0.1",
"--disable-admission-plugins=ServiceAccount",
},
etcdOptions)
defer s.TearDownFn()
client, err := kubernetes.NewForConfig(s.ClientConfig)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
ns := framework.CreateNamespaceOrDie(client, "test-service-allocate-node-ports", t)
defer framework.DeleteNamespaceOrDie(client, ns, t)
@ -1606,7 +1728,6 @@ func Test_ServiceChangeTypeHeadlessToExternalNameWithPatch(t *testing.T) {
},
}
var err error
service, err = client.CoreV1().Services(ns.Name).Create(tCtx, service, metav1.CreateOptions{})
if err != nil {
t.Fatalf("Error creating test service: %v", err)