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  }