Skip to content

Commit 67762d9

Browse files
authored
Merge pull request #1071 from robscott/cherrypick-946
Cherry pick webhook improvements and bug fixes into release-0.4
2 parents 5b89780 + 8fa96ef commit 67762d9

File tree

2 files changed

+333
-37
lines changed

2 files changed

+333
-37
lines changed

apis/v1alpha2/validation/httproute.go

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
4848
func 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

Comments
 (0)