This is an automated email from the ASF dual-hosted git repository.

ronething pushed a commit to branch fix/upstream_id_gen
in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git

commit 35ead734ec596a02a6fc855443aa91bd485ee53d
Author: Ashing Zheng <[email protected]>
AuthorDate: Tue Jan 6 17:51:19 2026 +0800

    fix: modify upstream name generation method
    
    Signed-off-by: Ashing Zheng <[email protected]>
---
 api/adc/types.go                       | 30 +++-----------
 go.mod                                 |  3 --
 go.sum                                 |  6 ---
 internal/adc/translator/apisixroute.go |  8 ++--
 internal/manager/controllers.go        |  2 +-
 test/e2e/crds/v2/route.go              | 71 ++++++++++++++++++++++++++++++++++
 6 files changed, 82 insertions(+), 38 deletions(-)

diff --git a/api/adc/types.go b/api/adc/types.go
index e5966ac2..aa67679d 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 (
@@ -806,22 +805,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)
@@ -829,15 +817,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/go.mod b/go.mod
index 757f8e28..cab91fbc 100644
--- a/go.mod
+++ b/go.mod
@@ -21,7 +21,6 @@ require (
        github.com/olekukonko/tablewriter v1.1.1
        github.com/onsi/ginkgo/v2 v2.22.0
        github.com/onsi/gomega v1.36.1
-       github.com/panjf2000/ants/v2 v2.11.3
        github.com/pkg/errors v0.9.1
        github.com/prometheus/client_golang v1.19.1
        github.com/samber/lo v1.47.0
@@ -35,7 +34,6 @@ require (
        k8s.io/apiextensions-apiserver v0.32.3
        k8s.io/apimachinery v0.32.3
        k8s.io/client-go v0.32.3
-       k8s.io/code-generator v0.32.3
        k8s.io/kubectl v0.30.3
        k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738
        sigs.k8s.io/controller-runtime v0.20.4
@@ -213,7 +211,6 @@ require (
        gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
        k8s.io/apiserver v0.32.3 // indirect
        k8s.io/component-base v0.32.3 // indirect
-       k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 // indirect
        k8s.io/klog/v2 v2.130.1 // indirect
        k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
        moul.io/http2curl/v2 v2.3.0 // indirect
diff --git a/go.sum b/go.sum
index eddf72b5..a1c9c8d3 100644
--- a/go.sum
+++ b/go.sum
@@ -333,8 +333,6 @@ github.com/onsi/ginkgo/v2 v2.22.0 
h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg
 github.com/onsi/ginkgo/v2 v2.22.0/go.mod 
h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
 github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
 github.com/onsi/gomega v1.36.1/go.mod 
h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
-github.com/panjf2000/ants/v2 v2.11.3 
h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg=
-github.com/panjf2000/ants/v2 v2.11.3/go.mod 
h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
 github.com/pelletier/go-toml/v2 v2.0.1/go.mod 
h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
 github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod 
h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod 
h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -597,12 +595,8 @@ k8s.io/apiserver v0.32.3 
h1:kOw2KBuHOA+wetX1MkmrxgBr648ksz653j26ESuWNY8=
 k8s.io/apiserver v0.32.3/go.mod h1:q1x9B8E/WzShF49wh3ADOh6muSfpmFL0I2t+TG0Zdgc=
 k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
 k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
-k8s.io/code-generator v0.32.3 h1:31p2TVzC9+hVdSkAFruAk3JY+iSfzrJ83Qij1yZutyw=
-k8s.io/code-generator v0.32.3/go.mod 
h1:+mbiYID5NLsBuqxjQTygKM/DAdKpAjvBzrJd64NU1G8=
 k8s.io/component-base v0.32.3 h1:98WJvvMs3QZ2LYHBzvltFSeJjEx7t5+8s71P7M74u8k=
 k8s.io/component-base v0.32.3/go.mod 
h1:LWi9cR+yPAv7cu2X9rZanTiFKB2kHA+JjmhkKjCZRpI=
-k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9 
h1:si3PfKm8dDYxgfbeA6orqrtLkvvIeH8UqffFJDl0bz4=
-k8s.io/gengo/v2 v2.0.0-20240911193312-2b36238f13e9/go.mod 
h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU=
 k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
 k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
 k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f 
h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
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/internal/manager/controllers.go b/internal/manager/controllers.go
index 38d437ac..a3970566 100644
--- a/internal/manager/controllers.go
+++ b/internal/manager/controllers.go
@@ -20,6 +20,7 @@ package manager
 import (
        "context"
 
+       "github.com/go-logr/logr"
        netv1 "k8s.io/api/networking/v1"
        "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
        "k8s.io/apimachinery/pkg/runtime"
@@ -40,7 +41,6 @@ import (
        "github.com/apache/apisix-ingress-controller/internal/provider"
        types "github.com/apache/apisix-ingress-controller/internal/types"
        "github.com/apache/apisix-ingress-controller/pkg/utils"
-       "github.com/go-logr/logr"
 )
 
 // K8s
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),
+                       })
+               })
+       })
 })

Reply via email to