@@ -33,6 +33,7 @@ import (
3333
3434 adctypes "github.com/apache/apisix-ingress-controller/api/adc"
3535 "github.com/apache/apisix-ingress-controller/api/v1alpha1"
36+ apiv2 "github.com/apache/apisix-ingress-controller/api/v2"
3637 "github.com/apache/apisix-ingress-controller/internal/controller/label"
3738 "github.com/apache/apisix-ingress-controller/internal/id"
3839 "github.com/apache/apisix-ingress-controller/internal/provider"
@@ -285,7 +286,7 @@ func (t *Translator) fillHTTPRoutePolicies(routes []*adctypes.Route, policies []
285286}
286287
287288func (t * Translator ) translateEndpointSlice (portName * string , weight int , endpointSlices []discoveryv1.EndpointSlice , endpointFilter func (* discoveryv1.Endpoint ) bool ) adctypes.UpstreamNodes {
288- var nodes adctypes.UpstreamNodes
289+ nodes := adctypes.UpstreamNodes {}
289290 if len (endpointSlices ) == 0 {
290291 return nodes
291292 }
@@ -466,32 +467,89 @@ func (t *Translator) TranslateHTTPRoute(tctx *provider.TranslateContext, httpRou
466467 labels := label .GenLabel (httpRoute )
467468
468469 for ruleIndex , rule := range rules {
469- upstream := adctypes .NewDefaultUpstream ()
470- var backendErr error
470+ service := adctypes .NewDefaultService ()
471+ service .Labels = labels
472+
473+ service .Name = adctypes .ComposeServiceNameWithRule (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d" , ruleIndex ))
474+ service .ID = id .GenID (service .Name )
475+ service .Hosts = hosts
476+
477+ var (
478+ upstreams = make ([]* adctypes.Upstream , 0 )
479+ weightedUpstreams = make ([]adctypes.TrafficSplitConfigRuleWeightedUpstream , 0 )
480+ backendErr error
481+ )
482+
471483 for _ , backend := range rule .BackendRefs {
472484 if backend .Namespace == nil {
473485 namespace := gatewayv1 .Namespace (httpRoute .Namespace )
474486 backend .Namespace = & namespace
475487 }
488+ upstream := adctypes .NewDefaultUpstream ()
476489 upNodes , err := t .translateBackendRef (tctx , backend .BackendRef , DefaultEndpointFilter )
477490 if err != nil {
478491 backendErr = err
479492 continue
480493 }
494+ if len (upNodes ) == 0 {
495+ continue
496+ }
497+
481498 t .AttachBackendTrafficPolicyToUpstream (backend .BackendRef , tctx .BackendTrafficPolicies , upstream )
482- upstream .Nodes = append (upstream .Nodes , upNodes ... )
499+ upstream .Nodes = upNodes
500+ upstreams = append (upstreams , upstream )
483501 }
484502
485- // todo: support multiple backends
486- service := adctypes .NewDefaultService ()
487- service .Labels = labels
503+ // Handle multiple backends with traffic-split plugin
504+ if len (upstreams ) == 0 {
505+ // Create a default upstream if no valid backends
506+ upstream := adctypes .NewDefaultUpstream ()
507+ service .Upstream = upstream
508+ } else if len (upstreams ) == 1 {
509+ // Single backend - use directly as service upstream
510+ service .Upstream = upstreams [0 ]
511+ } else {
512+ // Multiple backends - use traffic-split plugin
513+ service .Upstream = upstreams [0 ]
514+ upstreams = upstreams [1 :]
515+
516+ // Set weight in traffic-split for the default upstream
517+ weight := apiv2 .DefaultWeight
518+ if rule .BackendRefs [0 ].Weight != nil {
519+ weight = int (* rule .BackendRefs [0 ].Weight )
520+ }
521+ weightedUpstreams = append (weightedUpstreams , adctypes.TrafficSplitConfigRuleWeightedUpstream {
522+ Weight : weight ,
523+ })
488524
489- service .Name = adctypes .ComposeServiceNameWithRule (httpRoute .Namespace , httpRoute .Name , fmt .Sprintf ("%d" , ruleIndex ))
490- service .ID = id .GenID (service .Name )
491- service .Hosts = hosts
492- service .Upstream = upstream
525+ // Set other upstreams in traffic-split
526+ for i , upstream := range upstreams {
527+ weight := apiv2 .DefaultWeight
528+ // get weight from the backend refs starting from the second backend
529+ if i + 1 < len (rule .BackendRefs ) && rule .BackendRefs [i + 1 ].Weight != nil {
530+ weight = int (* rule .BackendRefs [i + 1 ].Weight )
531+ }
532+ weightedUpstreams = append (weightedUpstreams , adctypes.TrafficSplitConfigRuleWeightedUpstream {
533+ Upstream : upstream ,
534+ Weight : weight ,
535+ })
536+ }
537+
538+ if len (weightedUpstreams ) > 0 {
539+ if service .Plugins == nil {
540+ service .Plugins = make (map [string ]any )
541+ }
542+ service .Plugins ["traffic-split" ] = & adctypes.TrafficSplitConfig {
543+ Rules : []adctypes.TrafficSplitConfigRule {
544+ {
545+ WeightedUpstreams : weightedUpstreams ,
546+ },
547+ },
548+ }
549+ }
550+ }
493551
494- if backendErr != nil && len (upstream . Nodes ) == 0 {
552+ if backendErr != nil && ( service . Upstream == nil || len (service . Upstream . Nodes ) == 0 ) {
495553 if service .Plugins == nil {
496554 service .Plugins = make (map [string ]any )
497555 }
0 commit comments