func()

in pkg/providers/gateway/translation/gateway_httproute.go [133:280]


func (t *translator) TranslateGatewayHTTPRouteV1beta1(httpRoute *gatewayv1beta1.HTTPRoute) (*translation.TranslateContext, error) {
	ctx := translation.DefaultEmptyTranslateContext()

	var hosts []string
	for _, hostname := range httpRoute.Spec.Hostnames {
		hosts = append(hosts, string(hostname))

		// TODO: See the document of gatewayv1beta1.Listener.Hostname
		_ = gatewayv1beta1.Listener{}.Hostname
		// For HTTPRoute and TLSRoute resources, there is an interaction with the
		// `spec.hostnames` array. When both listener and route specify hostnames,
		// there MUST be an intersection between the values for a Route to be
		// accepted. For more information, refer to the Route specific Hostnames
		// documentation.
	}

	rules := httpRoute.Spec.Rules

	for i, rule := range rules {
		backends := rule.BackendRefs
		if len(backends) == 0 {
			continue
		}

		var ruleUpstreams []*apisixv1.Upstream
		var weightedUpstreams []apisixv1.TrafficSplitConfigRuleWeightedUpstream

		for j, backend := range backends {
			// TODO: Support filters
			// filters := backend.Filters
			var kind string
			if backend.Kind == nil {
				kind = "service"
			} else {
				kind = strings.ToLower(string(*backend.Kind))
			}
			if kind != "service" {
				log.Warnw(fmt.Sprintf("ignore non-service kind at Rules[%v].BackendRefs[%v]", i, j),
					zap.String("kind", kind),
				)
				continue
			}

			var ns string
			if backend.Namespace == nil {
				ns = httpRoute.Namespace
			} else {
				ns = string(*backend.Namespace)
			}
			//if ns != httpRoute.Namespace {
			// TODO: check gatewayv1beta1.ReferencePolicy
			//}

			if backend.Port == nil {
				log.Warnw(fmt.Sprintf("ignore nil port at Rules[%v].BackendRefs[%v]", i, j),
					zap.String("kind", kind),
				)
				continue
			}

			ups, err := t.KubeTranslator.TranslateService(ns, string(backend.Name), "", int32(*backend.Port))
			if err != nil {
				return nil, errors.Wrap(err, fmt.Sprintf("failed to translate Rules[%v].BackendRefs[%v]", i, j))
			}
			ups.Name = apisixv1.ComposeUpstreamName(ns, string(backend.Name), "", int32(*backend.Port), types.ResolveGranularity.Endpoint)

			// APISIX limits max length of label value
			// https://github.com/apache/apisix/blob/5b95b85faea3094d5e466ee2d39a52f1f805abbb/apisix/schema_def.lua#L85
			ups.Labels["meta_namespace"] = utils.TruncateString(ns, 64)
			ups.Labels["meta_backend"] = utils.TruncateString(string(backend.Name), 64)
			ups.Labels["meta_port"] = fmt.Sprintf("%v", int32(*backend.Port))

			ups.ID = id.GenID(ups.Name)
			log.Debugw("translated HTTPRoute upstream",
				zap.Int("backendRefs_index", j),
				zap.String("backendRefs_name", string(backend.Name)),
				zap.String("name", ups.Name),
			)
			ctx.AddUpstream(ups)
			ruleUpstreams = append(ruleUpstreams, ups)

			if backend.Weight == nil {
				weightedUpstreams = append(weightedUpstreams, apisixv1.TrafficSplitConfigRuleWeightedUpstream{
					UpstreamID: ups.ID,
					Weight:     1, // 1 is default value of BackendRef
				})
			} else {
				weightedUpstreams = append(weightedUpstreams, apisixv1.TrafficSplitConfigRuleWeightedUpstream{
					UpstreamID: ups.ID,
					Weight:     int(*backend.Weight),
				})
			}
		}
		if len(ruleUpstreams) == 0 {
			log.Warnw(fmt.Sprintf("ignore all-failed backend refs at Rules[%v]", i),
				zap.Any("BackendRefs", rule.BackendRefs),
			)
			continue
		}

		matches := rule.Matches
		if len(matches) == 0 {
			defaultType := gatewayv1beta1.PathMatchPathPrefix
			defaultValue := "/"
			matches = []gatewayv1beta1.HTTPRouteMatch{
				{
					Path: &gatewayv1beta1.HTTPPathMatch{
						Type:  &defaultType,
						Value: &defaultValue,
					},
				},
			}
		}
		plugins := t.generatePluginsFromHTTPRouteFilter(httpRoute.Namespace, rule.Filters)

		for j, match := range matches {
			route, err := t.translateGatewayHTTPRouteMatch(&match)
			if err != nil {
				return nil, errors.Wrap(err, fmt.Sprintf("failed to translate Rules[%v].Matches[%v]", i, j))
			}

			name := apisixv1.ComposeRouteName(httpRoute.Namespace, httpRoute.Name, fmt.Sprintf("%d-%d", i, j))
			route.ID = id.GenID(name)
			route.Hosts = hosts
			route.Plugins = plugins

			// Bind Upstream
			if len(ruleUpstreams) == 1 {
				route.UpstreamId = ruleUpstreams[0].ID
			} else if len(ruleUpstreams) > 0 {
				route.Plugins["traffic-split"] = &apisixv1.TrafficSplitConfig{
					Rules: []apisixv1.TrafficSplitConfigRule{
						{
							WeightedUpstreams: weightedUpstreams,
						},
					},
				}
			}

			ctx.AddRoute(route)
		}

		// TODO: Support filters
		// filters := rule.Filters
	}

	return ctx, nil
}