Merge pull request #16812 from rook/mergify/bp/release-1.19/pr-16792

external: fix endpoint slice type for ipv6 clusters (backport #16792)
This commit is contained in:
subham rai authored and GitHub committed 2025-12-08 21:05:37 +05:30
commit 7a496484db
4 files changed
+125 -7

No files matched your search

+7 -2
View File
@@ -871,13 +871,18 @@ func createExternalMetricsEndpoints(namespace string, monitoringSpec cephv1.Moni
addresses[i] = endpoint.IP
}
addressType, err := k8sutil.GetIpAddressType(addresses)
if err != nil {
return nil, errors.Wrap(err, "failed to get the addressType")
}
endpoints := &discoveryv1.EndpointSlice{
ObjectMeta: metav1.ObjectMeta{
Name: ExternalMgrAppName,
Namespace: namespace,
Labels: labels,
},
AddressType: discoveryv1.AddressTypeIPv4,
AddressType: addressType,
Endpoints: []discoveryv1.Endpoint{
{
Addresses: addresses,
@@ -895,7 +900,7 @@ func createExternalMetricsEndpoints(namespace string, monitoringSpec cephv1.Moni
},
}
err := ownerInfo.SetControllerReference(endpoints)
err = ownerInfo.SetControllerReference(endpoints)
if err != nil {
return nil, errors.Wrapf(err, "failed to set owner reference to metric endpoints %q", endpoints.Name)
}
+13 -5
View File
@@ -735,7 +735,7 @@ func (c *clusterConfig) generateService(cephObjectStore *cephv1.CephObjectStore)
return svc
}
func (c *clusterConfig) generateEndpoint(cephObjectStore *cephv1.CephObjectStore) *discoveryv1.EndpointSlice {
func (c *clusterConfig) generateEndpoint(cephObjectStore *cephv1.CephObjectStore) (*discoveryv1.EndpointSlice, error) {
labels := getLabels(cephObjectStore.Name, cephObjectStore.Namespace, true)
// Convert to string addresses
@@ -744,13 +744,18 @@ func (c *clusterConfig) generateEndpoint(cephObjectStore *cephv1.CephObjectStore
k8sEndpointAddrs = append(k8sEndpointAddrs, rookEndpoint.IP)
}
addressType, err := k8sutil.GetIpAddressType(k8sEndpointAddrs)
if err != nil {
return nil, errors.Wrap(err, "failed to get the addressType")
}
endpoints := &discoveryv1.EndpointSlice{
ObjectMeta: metav1.ObjectMeta{
Name: instanceName(cephObjectStore.Name),
Namespace: cephObjectStore.Namespace,
Labels: labels,
},
AddressType: discoveryv1.AddressTypeIPv4,
AddressType: addressType,
Endpoints: []discoveryv1.Endpoint{
{
Addresses: k8sEndpointAddrs,
@@ -765,16 +770,19 @@ func (c *clusterConfig) generateEndpoint(cephObjectStore *cephv1.CephObjectStore
addPortToEndpoint(endpoints, "http", cephObjectStore.Spec.Gateway.Port)
addPortToEndpoint(endpoints, "https", cephObjectStore.Spec.Gateway.SecurePort)
return endpoints
return endpoints, nil
}
func (c *clusterConfig) reconcileExternalEndpoint(cephObjectStore *cephv1.CephObjectStore) error {
nsName := controller.NsName(c.store.Namespace, c.store.Name)
log.NamedInfo(nsName, logger, "reconciling external object store service")
endpoint := c.generateEndpoint(cephObjectStore)
endpoint, err := c.generateEndpoint(cephObjectStore)
if err != nil {
return errors.Wrapf(err, "failed to generate the endpoint %q", endpoint.Name)
}
// Set owner ref to the parent object
err := c.ownerInfo.SetControllerReference(endpoint)
err = c.ownerInfo.SetControllerReference(endpoint)
if err != nil {
return errors.Wrapf(err, "failed to set owner reference to ceph object store endpoint %q", endpoint.Name)
}
+38
View File
@@ -18,11 +18,13 @@ package k8sutil
import (
"encoding/json"
"net/netip"
"strings"
nadv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
"github.com/pkg/errors"
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -110,3 +112,39 @@ func ParseLinuxIpAddrOutput(rawOutput string) ([]LinuxIpAddrResult, error) {
}
return results, nil
}
func GetIpAddressType(addresses []string) (discoveryv1.AddressType, error) {
var addressType discoveryv1.AddressType
if len(addresses) == 0 {
return addressType, errors.New("failed to get the address type for ip address, address list is empty type")
}
ip, err := netip.ParseAddr(addresses[0])
if err != nil {
return addressType, errors.Wrapf(err, "failed to get the address type for ip address %q", addresses[0])
}
addressType = discoveryv1.AddressTypeIPv4
if ip.Is6() {
addressType = discoveryv1.AddressTypeIPv6
}
// validate all addresses are of the same type
for _, addr := range addresses[1:] {
ip, err := netip.ParseAddr(addr)
if err != nil {
return addressType, errors.Wrapf(err, "failed to get the address type for ip address %q", addr)
}
if ip.Is6() {
if addressType != discoveryv1.AddressTypeIPv6 {
return addressType, errors.Errorf("all ip address are not of same type %v", addresses)
}
} else {
if addressType != discoveryv1.AddressTypeIPv4 {
return addressType, errors.Errorf("all ip address are not of same type %v", addresses)
}
}
}
return addressType, nil
}
+67
View File
@@ -22,6 +22,7 @@ import (
cephv1 "github.com/rook/rook/pkg/apis/ceph.rook.io/v1"
"github.com/stretchr/testify/assert"
discoveryv1 "k8s.io/api/discovery/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -307,3 +308,69 @@ func removeLastChar(in string) string {
len := len(chars)
return string(chars[0 : len-1])
}
// test for GetIpAddressType
func TestGetIpAddressType(t *testing.T) {
// test cases
tests := []struct {
name string
addresses []string
wantType discoveryv1.AddressType
wantErr bool
}{
{
name: "single IPv4 address",
addresses: []string{"192.168.1.1"},
wantType: discoveryv1.AddressTypeIPv4,
wantErr: false,
},
{
name: "IPv4 address",
addresses: []string{"192.168.1.1", "192.146.1.1"},
wantType: discoveryv1.AddressTypeIPv4,
wantErr: false,
},
{
name: "single IPv6 address",
addresses: []string{"2001:0db8:85a3:0000:0000:8a2e:0370:7334"},
wantType: discoveryv1.AddressTypeIPv6,
wantErr: false,
},
{
name: "IPv6 address",
addresses: []string{"2001:0db8:85a3:0000:0000:8a2e:0370:7334", "fe80::1ff:fe23:4567:890a"},
wantType: discoveryv1.AddressTypeIPv6,
wantErr: false,
},
{
name: "Mixed addresses",
addresses: []string{"192.168.1.1", "192.146.1.1", "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "fe80::1ff:fe23:4567:890a"},
wantType: "",
wantErr: true,
},
{
name: "Empty address list",
addresses: []string{},
wantType: "",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotType, err := GetIpAddressType(tt.addresses)
if err != nil {
if !tt.wantErr {
t.Errorf("GetIpAddressType() unexpected error: %v", err)
return
}
} else {
if tt.wantErr {
t.Errorf("GetIpAddressType() expected error but got none")
return
}
assert.Equal(t, tt.wantType, gotType)
}
})
}
}