mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			213 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2019 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 validation
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	corev1 "k8s.io/api/core/v1"
 | 
						|
	apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
 | 
						|
	metavalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
 | 
						|
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						|
	"k8s.io/apimachinery/pkg/util/validation"
 | 
						|
	"k8s.io/apimachinery/pkg/util/validation/field"
 | 
						|
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						|
	apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
 | 
						|
	"k8s.io/kubernetes/pkg/apis/discovery"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	supportedAddressTypes = sets.NewString(
 | 
						|
		string(discovery.AddressTypeIPv4),
 | 
						|
		string(discovery.AddressTypeIPv6),
 | 
						|
		string(discovery.AddressTypeFQDN),
 | 
						|
	)
 | 
						|
	supportedPortProtocols = sets.NewString(
 | 
						|
		string(api.ProtocolTCP),
 | 
						|
		string(api.ProtocolUDP),
 | 
						|
		string(api.ProtocolSCTP),
 | 
						|
	)
 | 
						|
	maxTopologyLabels = 16
 | 
						|
	maxAddresses      = 100
 | 
						|
	maxPorts          = 20000
 | 
						|
	maxEndpoints      = 1000
 | 
						|
	maxZoneHints      = 8
 | 
						|
)
 | 
						|
 | 
						|
// ValidateEndpointSliceName can be used to check whether the given endpoint
 | 
						|
// slice name is valid. Prefix indicates this name will be used as part of
 | 
						|
// generation, in which case trailing dashes are allowed.
 | 
						|
var ValidateEndpointSliceName = apimachineryvalidation.NameIsDNSSubdomain
 | 
						|
 | 
						|
// ValidateEndpointSlice validates an EndpointSlice.
 | 
						|
func ValidateEndpointSlice(endpointSlice *discovery.EndpointSlice) field.ErrorList {
 | 
						|
	allErrs := apivalidation.ValidateObjectMeta(&endpointSlice.ObjectMeta, true, ValidateEndpointSliceName, field.NewPath("metadata"))
 | 
						|
	allErrs = append(allErrs, validateAddressType(endpointSlice.AddressType)...)
 | 
						|
	allErrs = append(allErrs, validateEndpoints(endpointSlice.Endpoints, endpointSlice.AddressType, field.NewPath("endpoints"))...)
 | 
						|
	allErrs = append(allErrs, validatePorts(endpointSlice.Ports, field.NewPath("ports"))...)
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 | 
						|
 | 
						|
// ValidateEndpointSliceCreate validates an EndpointSlice when it is created.
 | 
						|
func ValidateEndpointSliceCreate(endpointSlice *discovery.EndpointSlice) field.ErrorList {
 | 
						|
	return ValidateEndpointSlice(endpointSlice)
 | 
						|
}
 | 
						|
 | 
						|
// ValidateEndpointSliceUpdate validates an EndpointSlice when it is updated.
 | 
						|
func ValidateEndpointSliceUpdate(newEndpointSlice, oldEndpointSlice *discovery.EndpointSlice) field.ErrorList {
 | 
						|
	allErrs := ValidateEndpointSlice(newEndpointSlice)
 | 
						|
	allErrs = append(allErrs, apivalidation.ValidateImmutableField(newEndpointSlice.AddressType, oldEndpointSlice.AddressType, field.NewPath("addressType"))...)
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 | 
						|
 | 
						|
func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.AddressType, fldPath *field.Path) field.ErrorList {
 | 
						|
	allErrs := field.ErrorList{}
 | 
						|
 | 
						|
	if len(endpoints) > maxEndpoints {
 | 
						|
		allErrs = append(allErrs, field.TooMany(fldPath, len(endpoints), maxEndpoints))
 | 
						|
		return allErrs
 | 
						|
	}
 | 
						|
 | 
						|
	for i, endpoint := range endpoints {
 | 
						|
		idxPath := fldPath.Index(i)
 | 
						|
		addressPath := idxPath.Child("addresses")
 | 
						|
 | 
						|
		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 {
 | 
						|
			// This validates known address types, unknown types fall through
 | 
						|
			// and do not get validated.
 | 
						|
			switch addrType {
 | 
						|
			case discovery.AddressTypeIPv4:
 | 
						|
				allErrs = append(allErrs, validation.IsValidIPv4Address(addressPath.Index(i), address)...)
 | 
						|
				allErrs = append(allErrs, apivalidation.ValidateNonSpecialIP(address, addressPath.Index(i))...)
 | 
						|
			case discovery.AddressTypeIPv6:
 | 
						|
				allErrs = append(allErrs, validation.IsValidIPv6Address(addressPath.Index(i), address)...)
 | 
						|
				allErrs = append(allErrs, apivalidation.ValidateNonSpecialIP(address, addressPath.Index(i))...)
 | 
						|
			case discovery.AddressTypeFQDN:
 | 
						|
				allErrs = append(allErrs, validation.IsFullyQualifiedDomainName(addressPath.Index(i), address)...)
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if endpoint.NodeName != nil {
 | 
						|
			nnPath := idxPath.Child("nodeName")
 | 
						|
			for _, msg := range apivalidation.ValidateNodeName(*endpoint.NodeName, false) {
 | 
						|
				allErrs = append(allErrs, field.Invalid(nnPath, *endpoint.NodeName, msg))
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		topologyPath := idxPath.Child("deprecatedTopology")
 | 
						|
		if len(endpoint.DeprecatedTopology) > maxTopologyLabels {
 | 
						|
			allErrs = append(allErrs, field.TooMany(topologyPath, len(endpoint.DeprecatedTopology), maxTopologyLabels))
 | 
						|
		}
 | 
						|
		allErrs = append(allErrs, metavalidation.ValidateLabels(endpoint.DeprecatedTopology, topologyPath)...)
 | 
						|
		if _, found := endpoint.DeprecatedTopology[corev1.LabelTopologyZone]; found {
 | 
						|
			allErrs = append(allErrs, field.InternalError(topologyPath.Key(corev1.LabelTopologyZone), fmt.Errorf("reserved key was not removed in conversion")))
 | 
						|
		}
 | 
						|
 | 
						|
		if endpoint.Hostname != nil {
 | 
						|
			allErrs = append(allErrs, apivalidation.ValidateDNS1123Label(*endpoint.Hostname, idxPath.Child("hostname"))...)
 | 
						|
		}
 | 
						|
 | 
						|
		if endpoint.Hints != nil {
 | 
						|
			allErrs = append(allErrs, validateHints(endpoint.Hints, idxPath.Child("hints"))...)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 | 
						|
 | 
						|
func validatePorts(endpointPorts []discovery.EndpointPort, fldPath *field.Path) field.ErrorList {
 | 
						|
	allErrs := field.ErrorList{}
 | 
						|
 | 
						|
	if len(endpointPorts) > maxPorts {
 | 
						|
		allErrs = append(allErrs, field.TooMany(fldPath, len(endpointPorts), maxPorts))
 | 
						|
		return allErrs
 | 
						|
	}
 | 
						|
 | 
						|
	portNames := sets.String{}
 | 
						|
	for i, endpointPort := range endpointPorts {
 | 
						|
		idxPath := fldPath.Index(i)
 | 
						|
 | 
						|
		if len(*endpointPort.Name) > 0 {
 | 
						|
			allErrs = append(allErrs, apivalidation.ValidateDNS1123Label(*endpointPort.Name, idxPath.Child("name"))...)
 | 
						|
		}
 | 
						|
 | 
						|
		if portNames.Has(*endpointPort.Name) {
 | 
						|
			allErrs = append(allErrs, field.Duplicate(idxPath.Child("name"), endpointPort.Name))
 | 
						|
		} else {
 | 
						|
			portNames.Insert(*endpointPort.Name)
 | 
						|
		}
 | 
						|
 | 
						|
		if endpointPort.Protocol == nil {
 | 
						|
			allErrs = append(allErrs, field.Required(idxPath.Child("protocol"), ""))
 | 
						|
		} else if !supportedPortProtocols.Has(string(*endpointPort.Protocol)) {
 | 
						|
			allErrs = append(allErrs, field.NotSupported(idxPath.Child("protocol"), *endpointPort.Protocol, supportedPortProtocols.List()))
 | 
						|
		}
 | 
						|
 | 
						|
		if endpointPort.AppProtocol != nil {
 | 
						|
			allErrs = append(allErrs, apivalidation.ValidateQualifiedName(*endpointPort.AppProtocol, idxPath.Child("appProtocol"))...)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 | 
						|
 | 
						|
func validateAddressType(addressType discovery.AddressType) field.ErrorList {
 | 
						|
	allErrs := field.ErrorList{}
 | 
						|
 | 
						|
	if addressType == "" {
 | 
						|
		allErrs = append(allErrs, field.Required(field.NewPath("addressType"), ""))
 | 
						|
	} else if !supportedAddressTypes.Has(string(addressType)) {
 | 
						|
		allErrs = append(allErrs, field.NotSupported(field.NewPath("addressType"), addressType, supportedAddressTypes.List()))
 | 
						|
	}
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 | 
						|
 | 
						|
func validateHints(endpointHints *discovery.EndpointHints, fldPath *field.Path) field.ErrorList {
 | 
						|
	allErrs := field.ErrorList{}
 | 
						|
 | 
						|
	fzPath := fldPath.Child("forZones")
 | 
						|
	if len(endpointHints.ForZones) > maxZoneHints {
 | 
						|
		allErrs = append(allErrs, field.TooMany(fzPath, len(endpointHints.ForZones), maxZoneHints))
 | 
						|
		return allErrs
 | 
						|
	}
 | 
						|
 | 
						|
	zoneNames := sets.String{}
 | 
						|
	for i, forZone := range endpointHints.ForZones {
 | 
						|
		zonePath := fzPath.Index(i).Child("name")
 | 
						|
		if zoneNames.Has(forZone.Name) {
 | 
						|
			allErrs = append(allErrs, field.Duplicate(zonePath, forZone.Name))
 | 
						|
		} else {
 | 
						|
			zoneNames.Insert(forZone.Name)
 | 
						|
		}
 | 
						|
 | 
						|
		for _, msg := range validation.IsValidLabelValue(forZone.Name) {
 | 
						|
			allErrs = append(allErrs, field.Invalid(zonePath, forZone.Name, msg))
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return allErrs
 | 
						|
}
 |