@@ -46,55 +46,61 @@ func ValidateHTTPRoute(route *gatewayv1a2.HTTPRoute) field.ErrorList {
4646// validateHTTPRouteSpec validates that required fields of spec are set according to the 
4747// HTTPRoute specification. 
4848func  validateHTTPRouteSpec (spec  * gatewayv1a2.HTTPRouteSpec , path  * field.Path ) field.ErrorList  {
49- 	return  validateHTTPRouteUniqueFilters (spec .Rules , path .Child ("rules" ))
49+ 	var  errs  field.ErrorList 
50+ 	for  i , rule  :=  range  spec .Rules  {
51+ 		errs  =  append (errs , validateHTTPRouteFilters (rule .Filters , path .Child ("rules" ).Index (i ))... )
52+ 		for  j , backendRef  :=  range  rule .BackendRefs  {
53+ 			errs  =  append (errs , validateHTTPRouteFilters (backendRef .Filters , path .Child ("rules" ).Index (i ).Child ("backendsrefs" ).Index (j ))... )
54+ 		}
55+ 	}
56+ 	errs  =  append (errs , validateHTTPRouteBackendServicePorts (spec .Rules , path .Child ("rules" ))... )
57+ 	return  errs 
5058}
5159
52- // validateHTTPRouteUniqueFilters validates whether each core and extended filter 
53- // is used at most once in each rule. 
54- func  validateHTTPRouteUniqueFilters (rules  []gatewayv1a2.HTTPRouteRule , path  * field.Path ) field.ErrorList  {
60+ // validateHTTPRouteBackendServicePorts validates that v1.Service backends always have a port. 
61+ func  validateHTTPRouteBackendServicePorts (rules  []gatewayv1a2.HTTPRouteRule , path  * field.Path ) field.ErrorList  {
5562	var  errs  field.ErrorList 
5663
5764	for  i , rule  :=  range  rules  {
58- 		counts  :=  map [gatewayv1a2.HTTPRouteFilterType ]int {}
59- 		for  _ , filter  :=  range  rule .Filters  {
60- 			counts [filter .Type ]++ 
61- 		}
62- 		// custom filters don't have any validation 
63- 		for  _ , key  :=  range  repeatableHTTPRouteFilters  {
64- 			delete (counts , key )
65- 		}
65+ 		path  =  path .Index (i ).Child ("backendRefs" )
66+ 		for  i , ref  :=  range  rule .BackendRefs  {
67+ 			if  ref .BackendObjectReference .Group  !=  nil  && 
68+ 				* ref .BackendObjectReference .Group  !=  ""  {
69+ 				continue 
70+ 			}
6671
67- 		for   filterType ,  count   :=   range   counts  { 
68- 			if   count   >   1  {
69- 				errs   =   append ( errs ,  field . Invalid ( path . Index ( i ). Child ( "filters" ),  filterType ,  "cannot be used multiple times in the same rule" )) 
72+ 			 if   ref . BackendObjectReference . Kind   !=   nil   && 
73+ 				 * ref . BackendObjectReference . Kind   !=   "Service"  {
74+ 				continue 
7075			}
71- 		}
7276
73- 		if  errList  :=  validateHTTPBackendUniqueFilters (rule .BackendRefs , path , i ); len (errList ) >  0  {
74- 			errs  =  append (errs , errList ... )
77+ 			if  ref .BackendObjectReference .Port  ==  nil  {
78+ 				errs  =  append (errs , field .Required (path .Index (i ).Child ("port" ), "missing port for Service reference" ))
79+ 			}
7580		}
7681	}
7782
7883	return  errs 
7984}
8085
81- func  validateHTTPBackendUniqueFilters (ref  []gatewayv1a2.HTTPBackendRef , path  * field.Path , i  int ) field.ErrorList  {
86+ // validateHTTPRouteFilters validates that a list of core and extended filters 
87+ // is used at most once and that the filter type matches its value 
88+ func  validateHTTPRouteFilters (filters  []gatewayv1a2.HTTPRouteFilter , path  * field.Path ) field.ErrorList  {
8289	var  errs  field.ErrorList 
90+ 	counts  :=  map [gatewayv1a2.HTTPRouteFilterType ]int {}
8391
84- 	for  _ , bkr  :=  range  ref  {
85- 		counts  :=  map [gatewayv1a2.HTTPRouteFilterType ]int {}
86- 		for  _ , filter  :=  range  bkr .Filters  {
87- 			counts [filter .Type ]++ 
88- 		}
92+ 	for  i , filter  :=  range  filters  {
93+ 		counts [filter .Type ]++ 
94+ 		validateHTTPRouteFilterTypeMatchesValue (filter , path .Index (i ))
95+ 	}
96+ 	// custom filters don't have any validation 
97+ 	for  _ , key  :=  range  repeatableHTTPRouteFilters  {
98+ 		delete (counts , key )
99+ 	}
89100
90- 		for  _ , key  :=  range  repeatableHTTPRouteFilters  {
91- 			delete (counts , key )
92- 		}
93- 
94- 		for  filterType , count  :=  range  counts  {
95- 			if  count  >  1  {
96- 				errs  =  append (errs , field .Invalid (path .Index (i ).Child ("BackendRefs" ), filterType , "cannot be used multiple times in the same backend" ))
97- 			}
101+ 	for  filterType , count  :=  range  counts  {
102+ 		if  count  >  1  {
103+ 			errs  =  append (errs , field .Invalid (path .Child ("filters" ), filterType , "cannot be used multiple times in the same rule" ))
98104		}
99105	}
100106	return  errs 
@@ -137,3 +143,34 @@ func validateHTTPPathMatch(path *gatewayv1a2.HTTPPathMatch, fldPath *field.Path)
137143	}
138144	return  allErrs 
139145}
146+ 
147+ // validateHTTPRouteFilterTypeMatchesValue validates that only the expected fields are 
148+ //// set for the specified filter type. 
149+ func  validateHTTPRouteFilterTypeMatchesValue (filter  gatewayv1a2.HTTPRouteFilter , path  * field.Path ) field.ErrorList  {
150+ 	var  errs  field.ErrorList 
151+ 	if  filter .ExtensionRef  !=  nil  &&  filter .Type  !=  gatewayv1a2 .HTTPRouteFilterExtensionRef  {
152+ 		errs  =  append (errs , field .Invalid (path , filter .ExtensionRef , "must be nil if the HTTPRouteFilter.Type is not ExtensionRef" ))
153+ 	}
154+ 	if  filter .ExtensionRef  ==  nil  &&  filter .Type  ==  gatewayv1a2 .HTTPRouteFilterExtensionRef  {
155+ 		errs  =  append (errs , field .Required (path , "filter.ExtensionRef must be specified for ExtensionRef HTTPRouteFilter.Type" ))
156+ 	}
157+ 	if  filter .RequestHeaderModifier  !=  nil  &&  filter .Type  !=  gatewayv1a2 .HTTPRouteFilterRequestHeaderModifier  {
158+ 		errs  =  append (errs , field .Invalid (path , filter .RequestHeaderModifier , "must be nil if the HTTPRouteFilter.Type is not RequestHeaderModifier" ))
159+ 	}
160+ 	if  filter .RequestHeaderModifier  ==  nil  &&  filter .Type  ==  gatewayv1a2 .HTTPRouteFilterRequestHeaderModifier  {
161+ 		errs  =  append (errs , field .Required (path , "filter.RequestHeaderModifier must be specified for RequestHeaderModifier HTTPRouteFilter.Type" ))
162+ 	}
163+ 	if  filter .RequestMirror  !=  nil  &&  filter .Type  !=  gatewayv1a2 .HTTPRouteFilterRequestMirror  {
164+ 		errs  =  append (errs , field .Invalid (path , filter .RequestMirror , "must be nil if the HTTPRouteFilter.Type is not RequestMirror" ))
165+ 	}
166+ 	if  filter .RequestMirror  ==  nil  &&  filter .Type  ==  gatewayv1a2 .HTTPRouteFilterRequestMirror  {
167+ 		errs  =  append (errs , field .Required (path , "filter.RequestMirror must be specified for RequestMirror HTTPRouteFilter.Type" ))
168+ 	}
169+ 	if  filter .RequestRedirect  !=  nil  &&  filter .Type  !=  gatewayv1a2 .HTTPRouteFilterRequestRedirect  {
170+ 		errs  =  append (errs , field .Invalid (path , filter .RequestRedirect , "must be nil if the HTTPRouteFilter.Type is not RequestRedirect" ))
171+ 	}
172+ 	if  filter .RequestRedirect  ==  nil  &&  filter .Type  ==  gatewayv1a2 .HTTPRouteFilterRequestRedirect  {
173+ 		errs  =  append (errs , field .Required (path , "filter.RequestRedirect must be specified for RequestRedirect HTTPRouteFilter.Type" ))
174+ 	}
175+ 	return  errs 
176+ }
0 commit comments