sigs.k8s.io/gateway-api@v1.0.0/apis/v1beta1/validation/common.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package validation 18 19 import ( 20 "k8s.io/apimachinery/pkg/util/sets" 21 "k8s.io/apimachinery/pkg/util/validation/field" 22 23 gatewayv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1" 24 ) 25 26 // ValidateParentRefs validates ParentRefs SectionName must be set and unique 27 // when ParentRefs includes 2 or more references to the same parent 28 func ValidateParentRefs(parentRefs []gatewayv1b1.ParentReference, path *field.Path) field.ErrorList { 29 var errs field.ErrorList 30 if len(parentRefs) <= 1 { 31 return nil 32 } 33 type sameKindParentRefs struct { 34 name gatewayv1b1.ObjectName 35 namespace gatewayv1b1.Namespace 36 kind gatewayv1b1.Kind 37 } 38 type parentQualifier struct { 39 section gatewayv1b1.SectionName 40 port gatewayv1b1.PortNumber 41 } 42 parentRefsSectionMap := make(map[sameKindParentRefs]sets.Set[parentQualifier]) 43 for i, p := range parentRefs { 44 targetParentRefs := sameKindParentRefs{name: p.Name, namespace: gatewayv1b1.Namespace(""), kind: gatewayv1b1.Kind("")} 45 pq := parentQualifier{} 46 if p.Namespace != nil { 47 targetParentRefs.namespace = *p.Namespace 48 } 49 if p.Kind != nil { 50 targetParentRefs.kind = *p.Kind 51 } 52 if p.SectionName != nil { 53 pq.section = *p.SectionName 54 } 55 if p.Port != nil { 56 pq.port = *p.Port 57 } 58 if s, ok := parentRefsSectionMap[targetParentRefs]; ok { 59 if s.UnsortedList()[0] == (parentQualifier{}) || pq == (parentQualifier{}) { 60 errs = append(errs, field.Required(path.Child("parentRefs"), "sectionNames or ports must be specified when more than one parentRef refers to the same parent")) 61 return errs 62 } 63 if s.Has(pq) { 64 fieldPath := path.Index(i).Child("parentRefs") 65 var val any 66 if len(pq.section) > 0 { 67 fieldPath = fieldPath.Child("sectionName") 68 val = pq.section 69 } else { 70 fieldPath = fieldPath.Child("port") 71 val = pq.port 72 } 73 errs = append(errs, field.Invalid(fieldPath, val, "must be unique when ParentRefs includes 2 or more references to the same parent")) 74 return errs 75 } 76 parentRefsSectionMap[targetParentRefs].Insert(pq) 77 } else { 78 parentRefsSectionMap[targetParentRefs] = sets.New(pq) 79 } 80 } 81 return errs 82 } 83 84 func ptrTo[T any](a T) *T { 85 return &a 86 }