github.com/nginxinc/kubernetes-ingress@v1.12.5/pkg/apis/configuration/validation/globalconfiguration.go (about) 1 package validation 2 3 import ( 4 "fmt" 5 6 "github.com/nginxinc/kubernetes-ingress/pkg/apis/configuration/v1alpha1" 7 "k8s.io/apimachinery/pkg/util/sets" 8 "k8s.io/apimachinery/pkg/util/validation" 9 "k8s.io/apimachinery/pkg/util/validation/field" 10 ) 11 12 // GlobalConfigurationValidator validates a GlobalConfiguration resource. 13 type GlobalConfigurationValidator struct { 14 forbiddenListenerPorts map[int]bool 15 } 16 17 // NewGlobalConfigurationValidator creates a new GlobalConfigurationValidator. 18 func NewGlobalConfigurationValidator(forbiddenListenerPorts map[int]bool) *GlobalConfigurationValidator { 19 return &GlobalConfigurationValidator{ 20 forbiddenListenerPorts: forbiddenListenerPorts, 21 } 22 } 23 24 // ValidateGlobalConfiguration validates a GlobalConfiguration. 25 func (gcv *GlobalConfigurationValidator) ValidateGlobalConfiguration(globalConfiguration *v1alpha1.GlobalConfiguration) error { 26 allErrs := gcv.validateGlobalConfigurationSpec(&globalConfiguration.Spec, field.NewPath("spec")) 27 return allErrs.ToAggregate() 28 } 29 30 func (gcv *GlobalConfigurationValidator) validateGlobalConfigurationSpec(spec *v1alpha1.GlobalConfigurationSpec, fieldPath *field.Path) field.ErrorList { 31 return gcv.validateListeners(spec.Listeners, fieldPath.Child("listeners")) 32 } 33 34 func (gcv *GlobalConfigurationValidator) validateListeners(listeners []v1alpha1.Listener, fieldPath *field.Path) field.ErrorList { 35 allErrs := field.ErrorList{} 36 37 listenerNames := sets.String{} 38 portProtocolCombinations := sets.String{} 39 40 for i, l := range listeners { 41 idxPath := fieldPath.Index(i) 42 portProtocolKey := generatePortProtocolKey(l.Port, l.Protocol) 43 44 listenerErrs := gcv.validateListener(l, idxPath) 45 if len(listenerErrs) > 0 { 46 allErrs = append(allErrs, listenerErrs...) 47 } else if listenerNames.Has(l.Name) { 48 allErrs = append(allErrs, field.Duplicate(idxPath.Child("name"), l.Name)) 49 } else if portProtocolCombinations.Has(portProtocolKey) { 50 msg := fmt.Sprintf("Duplicated port/protocol combination %s", portProtocolKey) 51 allErrs = append(allErrs, field.Duplicate(fieldPath, msg)) 52 } else { 53 listenerNames.Insert(l.Name) 54 portProtocolCombinations.Insert(portProtocolKey) 55 } 56 } 57 58 return allErrs 59 } 60 61 func generatePortProtocolKey(port int, protocol string) string { 62 return fmt.Sprintf("%d/%s", port, protocol) 63 } 64 65 func (gcv *GlobalConfigurationValidator) validateListener(listener v1alpha1.Listener, fieldPath *field.Path) field.ErrorList { 66 allErrs := field.ErrorList{} 67 68 allErrs = append(allErrs, validateGlobalConfigurationListenerName(listener.Name, fieldPath.Child("name"))...) 69 allErrs = append(allErrs, gcv.validateListenerPort(listener.Port, fieldPath.Child("port"))...) 70 allErrs = append(allErrs, validateListenerProtocol(listener.Protocol, fieldPath.Child("protocol"))...) 71 72 return allErrs 73 } 74 75 func validateGlobalConfigurationListenerName(name string, fieldPath *field.Path) field.ErrorList { 76 allErrs := field.ErrorList{} 77 78 if name == v1alpha1.TLSPassthroughListenerName { 79 return append(allErrs, field.Forbidden(fieldPath, "is the name of a built-in listener")) 80 } 81 82 return validateListenerName(name, fieldPath) 83 } 84 85 func (gcv *GlobalConfigurationValidator) validateListenerPort(port int, fieldPath *field.Path) field.ErrorList { 86 allErrs := field.ErrorList{} 87 88 if gcv.forbiddenListenerPorts[port] { 89 msg := fmt.Sprintf("port %v is forbidden", port) 90 return append(allErrs, field.Forbidden(fieldPath, msg)) 91 } 92 93 for _, msg := range validation.IsValidPortNum(port) { 94 allErrs = append(allErrs, field.Invalid(fieldPath, port, msg)) 95 } 96 97 return allErrs 98 }