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), + }) + }) + }) })
