Skip to content

Commit

Permalink
update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
randmonkey committed Dec 4, 2024
1 parent f4d27eb commit 5a84a0f
Show file tree
Hide file tree
Showing 8 changed files with 692 additions and 80 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
_format_version: "3.0"
services:
- connect_timeout: 60000
host: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
id: 112d14cb-01c4-549a-aa72-1a4a234c0372
name: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
host: httproute.default.httproute-testing.0
id: 4e3cb785-a8d0-5866-aa05-117f7c64f24d
name: httproute.default.httproute-testing.0
port: 8080
protocol: http
read_timeout: 60000
Expand Down Expand Up @@ -31,7 +31,7 @@ services:
write_timeout: 60000
upstreams:
- algorithm: round-robin
name: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
name: httproute.default.httproute-testing.0
tags:
- k8s-name:httproute-testing
- k8s-namespace:default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
_format_version: "3.0"
services:
- connect_timeout: 60000
host: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
id: 112d14cb-01c4-549a-aa72-1a4a234c0372
name: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
host: httproute.default.httproute-testing.0
id: 4e3cb785-a8d0-5866-aa05-117f7c64f24d
name: httproute.default.httproute-testing.0
port: 8080
protocol: http
read_timeout: 60000
Expand Down Expand Up @@ -42,7 +42,7 @@ services:
write_timeout: 60000
upstreams:
- algorithm: round-robin
name: httproute.default.svc.default.httpbin.80.75_default.nginx.8080.25
name: httproute.default.httproute-testing.0
tags:
- k8s-name:httproute-testing
- k8s-namespace:default
Expand Down
41 changes: 8 additions & 33 deletions internal/dataplane/translator/subtranslator/httproute.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ type HTTPRoutesTranslationResult struct {
HTTPRouteNameToTranslationErrors map[k8stypes.NamespacedName][]error
}

type splitHTTPRouteMatchesWithPrioritiesGroupedByRule map[string][]SplitHTTPRouteMatchToKongRoutePriority

// TranslateHTTPRoutesToKongstateServices translates a set of HTTPRoutes to kongstate services,
// and collect the translation errors in the process of translating.
func TranslateHTTPRoutesToKongstateServices(
Expand All @@ -61,20 +63,12 @@ func TranslateHTTPRoutesToKongstateServices(
) HTTPRoutesTranslationResult {
serviceNameToRules := groupRulesFromHTTPRoutesByKongServiceName(routes, combinedServicesFromDifferentHTTPRoutes)

// first, split HTTPRoutes by hostnames and matches.
ruleToSplitMatchesWithPriorities := make(map[string][]SplitHTTPRouteMatchToKongRoutePriority)
// When feature flag expression routes is enabled, we need first split the matches and assign priorities to them
// to set proper priorities to the translated Kong routes for satisfying the specification of priorities of HTTPRoute matches:
// https://gateway-api.sigs.k8s.io/reference/spec/#gateway.networking.k8s.io/v1.HTTPRouteRule
ruleToSplitMatchesWithPriorities := make(splitHTTPRouteMatchesWithPrioritiesGroupedByRule)
if expressionRoutes {
splitHTTPRouteMatches := []SplitHTTPRouteMatch{}
for _, route := range routes {
splitHTTPRouteMatches = append(splitHTTPRouteMatches, SplitHTTPRoute(route)...)
}
// assign priorities to split HTTPRoutes.
splitHTTPRouteMatchesWithPriorities := AssignRoutePriorityToSplitHTTPRouteMatches(logger, splitHTTPRouteMatches)
for _, matchWithPriority := range splitHTTPRouteMatchesWithPriorities {
sourceRoute := matchWithPriority.Match.Source
ruleKey := fmt.Sprintf("%s/%s.%d", sourceRoute.Namespace, sourceRoute.Name, matchWithPriority.Match.RuleIndex)
ruleToSplitMatchesWithPriorities[ruleKey] = append(ruleToSplitMatchesWithPriorities[ruleKey], matchWithPriority)
}
ruleToSplitMatchesWithPriorities = groupHTTPRouteMatchesWithPrioritiesByRule(logger, routes)
}

kongstateServiceCache := map[string]kongstate.Service{}
Expand Down Expand Up @@ -270,7 +264,7 @@ func translateHTTPRouteRulesMetaToKongstateService(
}

if expressionRoutes {
routes, err := translateHTTPRouteRulesMetaToKongstateRoutesWithExpression(matchesWithPriorities)
routes, err := translateSplitHTTPRouteMatchesToKongstateRoutesWithExpression(matchesWithPriorities)
if err != nil {
return kongstate.Service{}, err
}
Expand Down Expand Up @@ -397,24 +391,6 @@ func translateHTTPRouteRulesMetaToKongstateRoutes(
return routes, nil
}

func translateHTTPRouteRulesMetaToKongstateRoutesWithExpression(
matchesWithPriorities []SplitHTTPRouteMatchToKongRoutePriority,
) ([]kongstate.Route, error) {
routes := []kongstate.Route{}
for _, matchWithPriority := range matchesWithPriorities {
// Since each match is assigned a deterministic priority, we have to generate one route for each split match
// because every match have a different priority.
// TODO: update the algorithm to assign priorities to matches to make it possible to consilidate some matches.
// For example, we can assign the same priority to multiple matches from the same rule if they tie on the priority from the fixed fields.
route, err := KongExpressionRouteFromHTTPRouteMatchWithPriority(matchWithPriority)
if err != nil {
return []kongstate.Route{}, err
}
routes = append(routes, *route)
}
return routes, nil
}

// extractUniqueHTTPRoutes extracts unique HTTPRoutes in a grouped list of HTTPRouteRuleMeta.
func extractUniqueHTTPRoutes(rulesMeta []httpRouteRuleMeta) []*gatewayapi.HTTPRoute {
routes := lo.Map(rulesMeta, func(m httpRouteRuleMeta, _ int) *gatewayapi.HTTPRoute {
Expand Down Expand Up @@ -554,7 +530,6 @@ func (m httpRouteRuleMeta) getKongServiceNameByBackendRefs() string {
hash := sha256.Sum256([]byte(name))
// We have already returned when there are no backends in the rule, so it is safe to use backendNames[0].
trimmedName := fmt.Sprintf("httproute.%s.svc.%s_combined.%x", m.parentRoute.Namespace, backendNames[0], hash)
// REVIEW: should we emit a log here to tell that the name is trimmed? And should we record the original long name?
return trimmedName
}
return name
Expand Down
62 changes: 43 additions & 19 deletions internal/dataplane/translator/subtranslator/httproute_atc.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,14 +444,14 @@ func (t HTTPRoutePriorityTraits) EncodeToPriority() RoutePriorityType {
return priority
}

// AssignRoutePriorityToSplitHTTPRouteMatches assigns priority to
// assignRoutePriorityToSplitHTTPRouteMatches assigns priority to
// ALL split matches from ALL HTTPRoutes in the cache.
// Firstly assign "fixed" bits by the following fields of the match:
// hostname, path type, path length, method match, number of header matches, number of query param matches.
// If ties exists in the first step, where multiple matches has the same priority
// calculated from the fields, we run a sort for the matches in the tie
// and assign the bits for "relative order" according to the sorting result of these matches.
func AssignRoutePriorityToSplitHTTPRouteMatches(
func assignRoutePriorityToSplitHTTPRouteMatches(
logger logr.Logger,
splitHTTPRouteMatches []SplitHTTPRouteMatch,
) []SplitHTTPRouteMatchToKongRoutePriority {
Expand Down Expand Up @@ -534,9 +534,9 @@ func compareSplitHTTPRouteMatchesRelativePriority(match1, match2 SplitHTTPRouteM
return true
}

// KongExpressionRouteFromHTTPRouteMatchWithPriority translates a split HTTPRoute match into expression
// kongExpressionRouteFromHTTPRouteMatchWithPriority translates a split HTTPRoute match into expression
// based kong route with assigned priority.
func KongExpressionRouteFromHTTPRouteMatchWithPriority(
func kongExpressionRouteFromHTTPRouteMatchWithPriority(
httpRouteMatchWithPriority SplitHTTPRouteMatchToKongRoutePriority,
) (*kongstate.Route, error) {
match := httpRouteMatchWithPriority.Match
Expand Down Expand Up @@ -599,20 +599,44 @@ func KongExpressionRouteFromHTTPRouteMatchWithPriority(
return r, nil
}

// KongServiceNameFromSplitHTTPRouteMatch generates service name from split HTTPRoute match.
// since one HTTPRoute may be split by hostname and rule, the service name will be generated
// in the format "httproute.<namespace>.<name>.<hostname>.<rule index>".
// For example: `httproute.default.example.foo.com.0`.
func KongServiceNameFromSplitHTTPRouteMatch(match SplitHTTPRouteMatch) string {
httproute := match.Source
hostname := "_"
if len(match.Hostname) > 0 {
hostname = strings.ReplaceAll(match.Hostname, "*", "_")
// groupHTTPRouteMatchesWithPrioritiesByRule groups split HTTPRoute matches that has priorities assigned by the source HTTPRoute rule,.
func groupHTTPRouteMatchesWithPrioritiesByRule(
logger logr.Logger, routes []*gatewayapi.HTTPRoute,
) splitHTTPRouteMatchesWithPrioritiesGroupedByRule {
//
splitHTTPRouteMatches := []SplitHTTPRouteMatch{}
for _, route := range routes {
splitHTTPRouteMatches = append(splitHTTPRouteMatches, SplitHTTPRoute(route)...)
}
// assign priorities to split HTTPRoutes.
splitHTTPRouteMatchesWithPriorities := assignRoutePriorityToSplitHTTPRouteMatches(logger, splitHTTPRouteMatches)

// group the matches with priorities by its source HTTPRoute rule.
ruleToSplitMatchesWithPriorities := splitHTTPRouteMatchesWithPrioritiesGroupedByRule{}
for _, matchWithPriority := range splitHTTPRouteMatchesWithPriorities {
sourceRoute := matchWithPriority.Match.Source
ruleKey := fmt.Sprintf("%s/%s.%d", sourceRoute.Namespace, sourceRoute.Name, matchWithPriority.Match.RuleIndex)
ruleToSplitMatchesWithPriorities[ruleKey] = append(ruleToSplitMatchesWithPriorities[ruleKey], matchWithPriority)
}
return ruleToSplitMatchesWithPriorities
}

// translateSplitHTTPRouteMatchesToKongstateRoutesWithExpression translates a list of split HTTPRoute matches with assigned priorities
// that are poiting to the same service to list of kongstate route with expressions.
func translateSplitHTTPRouteMatchesToKongstateRoutesWithExpression(
matchesWithPriorities []SplitHTTPRouteMatchToKongRoutePriority,
) ([]kongstate.Route, error) {
routes := []kongstate.Route{}
for _, matchWithPriority := range matchesWithPriorities {
// Since each match is assigned a deterministic priority, we have to generate one route for each split match
// because every match have a different priority.
// TODO: update the algorithm to assign priorities to matches to make it possible to consolidate some matches.
// For example, we can assign the same priority to multiple matches from the same rule if they tie on the priority from the fixed fields.
route, err := kongExpressionRouteFromHTTPRouteMatchWithPriority(matchWithPriority)
if err != nil {
return []kongstate.Route{}, err
}
routes = append(routes, *route)
}
return fmt.Sprintf("httproute.%s.%s.%s.%d",
httproute.Namespace,
httproute.Name,
hostname,
match.RuleIndex,
)
return routes, nil
}
Loading

0 comments on commit 5a84a0f

Please sign in to comment.