This is an automated email from the ASF dual-hosted git repository. ronething pushed a commit to branch v2.0.0 in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git
commit c6e00d7d62a9519ed5156d149a94cab367eb984e Author: Ashing Zheng <[email protected]> AuthorDate: Thu Jan 8 18:21:29 2026 +0800 fix: modify upstream name generation method (#2694) Signed-off-by: Ashing Zheng <[email protected]> (cherry picked from commit 80585882b8460619bd123f85efa61d0465b1b218) --- api/adc/types.go | 30 +++----------- internal/adc/translator/apisixroute.go | 8 ++-- test/e2e/crds/v2/route.go | 71 ++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 28 deletions(-) diff --git a/api/adc/types.go b/api/adc/types.go index f4557450..b1738bf2 100644 --- a/api/adc/types.go +++ b/api/adc/types.go @@ -27,7 +27,6 @@ import ( "time" "github.com/incubator4/go-resty-expr/expr" - "k8s.io/apimachinery/pkg/util/intstr" ) const ( @@ -816,22 +815,11 @@ var ( } ) -// ComposeUpstreamName uses namespace, name, subset (optional), port, resolveGranularity info to compose +// ComposeUpstreamName uses namespace, name, ruleIndex, backendIndex, serviceName info to compose // the upstream name. -// the resolveGranularity is not composited in the upstream name when it is endpoint. -// ref: https://github.com/apache/apisix-ingress-controller/blob/10059afe3e84b693cc61e6df7a0040890a9d16eb/pkg/types/apisix/v1/types.go#L595-L598 -func ComposeUpstreamName(namespace, name, subset string, port intstr.IntOrString, resolveGranularity string) string { - pstr := port.String() - // FIXME Use sync.Pool to reuse this buffer if the upstream - // name composing code path is hot. +func ComposeUpstreamName(namespace, name, ruleIndex, backendIndex string) string { var p []byte - plen := len(namespace) + len(name) + len(pstr) + 2 - if subset != "" { - plen = plen + len(subset) + 1 - } - if resolveGranularity == ResolveGranularity.Service { - plen = plen + len(resolveGranularity) + 1 - } + plen := len(namespace) + len(name) + len(ruleIndex) + len(backendIndex) + 3 p = make([]byte, 0, plen) buf := bytes.NewBuffer(p) @@ -839,15 +827,9 @@ func ComposeUpstreamName(namespace, name, subset string, port intstr.IntOrString buf.WriteByte('_') buf.WriteString(name) buf.WriteByte('_') - if subset != "" { - buf.WriteString(subset) - buf.WriteByte('_') - } - buf.WriteString(pstr) - if resolveGranularity == ResolveGranularity.Service { - buf.WriteByte('_') - buf.WriteString(resolveGranularity) - } + buf.WriteString(ruleIndex) + buf.WriteByte('_') + buf.WriteString(backendIndex) return buf.String() } diff --git a/internal/adc/translator/apisixroute.go b/internal/adc/translator/apisixroute.go index f5a509e1..575d26e4 100644 --- a/internal/adc/translator/apisixroute.go +++ b/internal/adc/translator/apisixroute.go @@ -72,7 +72,7 @@ func (t *Translator) translateHTTPRule(tctx *provider.TranslateContext, ar *apiv var enableWebsocket *bool service := t.buildService(ar, rule, ruleIndex) - t.buildUpstream(tctx, service, ar, rule, &enableWebsocket) + t.buildUpstream(tctx, service, ar, rule, ruleIndex, &enableWebsocket) t.buildRoute(ar, service, rule, plugins, timeout, vars, &enableWebsocket) return service, nil } @@ -205,13 +205,13 @@ func (t *Translator) buildRoute(ar *apiv2.ApisixRoute, service *adc.Service, rul service.Routes = []*adc.Route{route} } -func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc.Service, ar *apiv2.ApisixRoute, rule apiv2.ApisixRouteHTTP, enableWebsocket **bool) { +func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc.Service, ar *apiv2.ApisixRoute, rule apiv2.ApisixRouteHTTP, ruleIndex int, enableWebsocket **bool) { var ( upstreams = make([]*adc.Upstream, 0) weightedUpstreams = make([]adc.TrafficSplitConfigRuleWeightedUpstream, 0) ) - for _, backend := range rule.Backends { + for backendIndex, backend := range rule.Backends { // try to get the apisixupstream with the same name as the backend service to be upstream config. // err is ignored because it does not care about the externalNodes of the apisixupstream. upstream, err := t.translateApisixRouteHTTPBackend(tctx, ar, backend, enableWebsocket) @@ -220,7 +220,7 @@ func (t *Translator) buildUpstream(tctx *provider.TranslateContext, service *adc continue } - upstreamName := adc.ComposeUpstreamName(ar.Namespace, backend.ServiceName, backend.Subset, backend.ServicePort, backend.ResolveGranularity) + upstreamName := adc.ComposeUpstreamName(ar.Namespace, ar.Name, fmt.Sprintf("%d", ruleIndex), fmt.Sprintf("%d", backendIndex)) upstream.Name = upstreamName upstream.ID = id.GenID(upstreamName) upstreams = append(upstreams, upstream) diff --git a/test/e2e/crds/v2/route.go b/test/e2e/crds/v2/route.go index 67c6770f..a1a9edc6 100644 --- a/test/e2e/crds/v2/route.go +++ b/test/e2e/crds/v2/route.go @@ -2166,4 +2166,75 @@ spec: Expect(string(msg)).To(Equal(testMessage), "message content verification") }) }) + + Context("Test ApisixRoute with multiple backends", func() { + It("create ApisixRoute with multiple backends", func() { + var httpService = ` +apiVersion: v1 +kind: Service +metadata: + name: httpbin-service-e2e-test2 +spec: + selector: + app: httpbin-deployment-e2e-test + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 80 + type: ClusterIP +` + err := s.CreateResourceFromString(httpService) + Expect(err).ShouldNot(HaveOccurred()) + s.EnsureNumEndpointsReady(GinkgoT(), "httpbin-service-e2e-test2", 1) + + const apisixRouteSpec = ` +apiVersion: apisix.apache.org/v2 +kind: ApisixRoute +metadata: + name: httpbin +spec: + ingressClassName: %s + http: + - name: get + match: + paths: + - /get + backends: + - serviceName: httpbin-service-e2e-test + servicePort: 80 + - serviceName: httpbin-service-e2e-test2 + servicePort: 80 + - name: ip + match: + paths: + - /ip + backends: + - serviceName: httpbin-service-e2e-test + servicePort: 80 + - serviceName: httpbin-service-e2e-test2 + servicePort: 80 +` + By("apply ApisixRoute") + applier.MustApplyAPIv2(types.NamespacedName{Namespace: s.Namespace(), Name: "httpbin"}, + &apiv2.ApisixRoute{}, fmt.Sprintf(apisixRouteSpec, s.Namespace())) + + By("check upstreams") + upstreams, err := s.DefaultDataplaneResource().Upstream().List(context.Background()) + Expect(err).ShouldNot(HaveOccurred()) + Expect(upstreams).Should(HaveLen(4)) + + By("verify ApisixRoute works") + s.RequestAssert(&scaffold.RequestAssert{ + Method: "GET", + Path: "/get", + Check: scaffold.WithExpectedStatus(http.StatusOK), + }) + s.RequestAssert(&scaffold.RequestAssert{ + Method: "GET", + Path: "/ip", + Check: scaffold.WithExpectedStatus(http.StatusOK), + }) + }) + }) })
