Adding FQDN address type for EndpointSlice
This commit is contained in:
@@ -32,7 +32,11 @@ type EndpointSlice struct {
|
||||
// +optional
|
||||
metav1.ObjectMeta
|
||||
// addressType specifies the type of address carried by this EndpointSlice.
|
||||
// All addresses in this slice must be the same type.
|
||||
// All addresses in this slice must be the same type. The following address
|
||||
// types are currently supported:
|
||||
// * IP: Represents an IP Address. This can include both IPv4 and IPv6
|
||||
// addresses.
|
||||
// * FQDN: Represents a Fully Qualified Domain Name.
|
||||
// +optional
|
||||
AddressType *AddressType
|
||||
// endpoints is a list of unique endpoints in this slice. Each slice may
|
||||
@@ -53,17 +57,21 @@ type EndpointSlice struct {
|
||||
type AddressType string
|
||||
|
||||
const (
|
||||
// AddressTypeIP represents an IP Address.
|
||||
// AddressTypeIP represents an IP Address. Inclusive of IPv4 and IPv6
|
||||
// addresses.
|
||||
AddressTypeIP = AddressType("IP")
|
||||
// AddressTypeFQDN represents a Fully Qualified Domain Name.
|
||||
AddressTypeFQDN = AddressType("FQDN")
|
||||
)
|
||||
|
||||
// Endpoint represents a single logical "backend" implementing a service.
|
||||
type Endpoint struct {
|
||||
// addresses of this endpoint. The contents of this field are interpreted
|
||||
// according to the corresponding EndpointSlice addressType field. This
|
||||
// allows for cases like dual-stack (IPv4 and IPv6) networking. Consumers
|
||||
// (e.g. kube-proxy) must handle different types of addresses in the context
|
||||
// of their own capabilities. This must contain at least one address but no
|
||||
// allows for cases like dual-stack networking where both IPv4 and IPv6
|
||||
// addresses would be included with the IP addressType. Consumers (e.g.
|
||||
// kube-proxy) must handle different types of addresses in the context of
|
||||
// their own capabilities. This must contain at least one address but no
|
||||
// more than 100.
|
||||
// +listType=set
|
||||
Addresses []string
|
||||
|
@@ -28,7 +28,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
supportedAddressTypes = sets.NewString(string(discovery.AddressTypeIP))
|
||||
supportedAddressTypes = sets.NewString(string(discovery.AddressTypeIP), string(discovery.AddressTypeFQDN))
|
||||
supportedPortProtocols = sets.NewString(string(api.ProtocolTCP), string(api.ProtocolUDP), string(api.ProtocolSCTP))
|
||||
maxTopologyLabels = 16
|
||||
maxAddresses = 100
|
||||
@@ -45,6 +45,8 @@ var ValidateEndpointSliceName = apimachineryvalidation.NameIsDNSSubdomain
|
||||
func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&endpointSlice.ObjectMeta, true, ValidateEndpointSliceName, field.NewPath("metadata"))
|
||||
|
||||
// AddressType should have had a default value set at this point, this is
|
||||
// just a safety check if for some reason that changes or doesn't work.
|
||||
addrType := discovery.AddressType("")
|
||||
if endpointSlice.AddressType == nil {
|
||||
allErrs = append(allErrs, field.Required(field.NewPath("addressType"), ""))
|
||||
@@ -52,8 +54,8 @@ func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice) field.ErrorLi
|
||||
addrType = *endpointSlice.AddressType
|
||||
}
|
||||
|
||||
if endpointSlice.AddressType != nil && !supportedAddressTypes.Has(string(*endpointSlice.AddressType)) {
|
||||
allErrs = append(allErrs, field.NotSupported(field.NewPath("addressType"), *endpointSlice.AddressType, supportedAddressTypes.List()))
|
||||
if !supportedAddressTypes.Has(string(addrType)) {
|
||||
allErrs = append(allErrs, field.NotSupported(field.NewPath("addressType"), addrType, supportedAddressTypes.List()))
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, validateEndpoints(endpointSlice.Endpoints, addrType, field.NewPath("endpoints"))...)
|
||||
@@ -83,17 +85,20 @@ func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.Addres
|
||||
idxPath := fldPath.Index(i)
|
||||
addressPath := idxPath.Child("addresses")
|
||||
|
||||
if addrType == discovery.AddressTypeIP {
|
||||
if len(endpoint.Addresses) == 0 {
|
||||
allErrs = append(allErrs, field.Required(addressPath, "must contain at least 1 address"))
|
||||
} else if len(endpoint.Addresses) > maxAddresses {
|
||||
allErrs = append(allErrs, field.TooMany(addressPath, len(endpoint.Addresses), maxAddresses))
|
||||
}
|
||||
if len(endpoint.Addresses) == 0 {
|
||||
allErrs = append(allErrs, field.Required(addressPath, "must contain at least 1 address"))
|
||||
} else if len(endpoint.Addresses) > maxAddresses {
|
||||
allErrs = append(allErrs, field.TooMany(addressPath, len(endpoint.Addresses), maxAddresses))
|
||||
}
|
||||
|
||||
for i, address := range endpoint.Addresses {
|
||||
for i, address := range endpoint.Addresses {
|
||||
switch addrType {
|
||||
case discovery.AddressTypeIP:
|
||||
for _, msg := range validation.IsValidIP(address) {
|
||||
allErrs = append(allErrs, field.Invalid(addressPath.Index(i), address, msg))
|
||||
}
|
||||
case discovery.AddressTypeFQDN:
|
||||
allErrs = append(allErrs, validation.IsFullyQualifiedDomainName(addressPath.Index(i), address)...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,22 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"good-fqdns": {
|
||||
expectedErrors: 0,
|
||||
endpointSlice: &discovery.EndpointSlice{
|
||||
ObjectMeta: standardMeta,
|
||||
AddressType: addressTypePtr(discovery.AddressTypeFQDN),
|
||||
Ports: []discovery.EndpointPort{{
|
||||
Name: utilpointer.StringPtr("http"),
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: []string{"foo.example.com", "example.com", "example.com.", "hyphens-are-good.example.com"},
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
@@ -67,7 +82,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolSCTP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
@@ -85,7 +100,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -125,7 +140,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(maxAddresses),
|
||||
Addresses: generateIPAddresses(maxAddresses),
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -139,7 +154,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Topology: generateTopology(maxTopologyLabels),
|
||||
}},
|
||||
},
|
||||
@@ -223,7 +238,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(0),
|
||||
Addresses: generateIPAddresses(0),
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -237,7 +252,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(maxAddresses + 1),
|
||||
Addresses: generateIPAddresses(maxAddresses + 1),
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -251,7 +266,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
}},
|
||||
},
|
||||
},
|
||||
@@ -265,7 +280,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Topology: map[string]string{"--INVALID": "example"},
|
||||
}},
|
||||
},
|
||||
@@ -280,7 +295,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Topology: generateTopology(maxTopologyLabels + 1),
|
||||
}},
|
||||
},
|
||||
@@ -295,7 +310,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Hostname: utilpointer.StringPtr("--INVALID"),
|
||||
}},
|
||||
},
|
||||
@@ -313,14 +328,46 @@ func TestValidateEndpointSlice(t *testing.T) {
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: generateAddresses(1),
|
||||
Addresses: generateIPAddresses(1),
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"bad-ip": {
|
||||
expectedErrors: 1,
|
||||
endpointSlice: &discovery.EndpointSlice{
|
||||
ObjectMeta: standardMeta,
|
||||
AddressType: addressTypePtr(discovery.AddressTypeIP),
|
||||
Ports: []discovery.EndpointPort{{
|
||||
Name: utilpointer.StringPtr("http"),
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: []string{"123.456.789.012"},
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"bad-fqdns": {
|
||||
expectedErrors: 4,
|
||||
endpointSlice: &discovery.EndpointSlice{
|
||||
ObjectMeta: standardMeta,
|
||||
AddressType: addressTypePtr(discovery.AddressTypeFQDN),
|
||||
Ports: []discovery.EndpointPort{{
|
||||
Name: utilpointer.StringPtr("http"),
|
||||
Protocol: protocolPtr(api.ProtocolTCP),
|
||||
}},
|
||||
Endpoints: []discovery.Endpoint{{
|
||||
Addresses: []string{"foo.*", "FOO.example.com", "underscores_are_bad.example.com", "*.example.com"},
|
||||
Hostname: utilpointer.StringPtr("valid-123"),
|
||||
}},
|
||||
},
|
||||
},
|
||||
"empty-everything": {
|
||||
expectedErrors: 3,
|
||||
endpointSlice: &discovery.EndpointSlice{},
|
||||
endpointSlice: &discovery.EndpointSlice{
|
||||
AddressType: addressTypePtr(""),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -422,7 +469,7 @@ func generateEndpoints(n int) []discovery.Endpoint {
|
||||
return endpoints
|
||||
}
|
||||
|
||||
func generateAddresses(n int) []string {
|
||||
func generateIPAddresses(n int) []string {
|
||||
addresses := []string{}
|
||||
for i := 0; i < n; i++ {
|
||||
addresses = append(addresses, fmt.Sprintf("10.1.2.%d", i%255))
|
||||
|
Reference in New Issue
Block a user