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

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


The following commit(s) were added to refs/heads/master by this push:
     new 9855521  chore: TranslateContext (#400)
9855521 is described below

commit 98555210326c02db4c2c4ca8e2a8e0a27b17c92b
Author: Alex Zhang <[email protected]>
AuthorDate: Sun Apr 25 18:44:27 2021 +0800

    chore: TranslateContext (#400)
    
    * chore: TranslateContext
    
    * test: add unit test case
---
 pkg/ingress/apisix_route.go               |  32 +++--
 pkg/ingress/ingress.go                    |  22 ++--
 pkg/kube/translation/apisix_route.go      |  96 ++++++--------
 pkg/kube/translation/apisix_route_test.go |  22 +---
 pkg/kube/translation/context.go           |  47 +++++++
 pkg/kube/translation/context_test.go      |  76 ++++++++++++
 pkg/kube/translation/ingress.go           |  51 ++++----
 pkg/kube/translation/ingress_test.go      | 200 +++++++++++++++---------------
 pkg/kube/translation/plugin.go            |  15 ++-
 pkg/kube/translation/plugin_test.go       |  66 +++++-----
 pkg/kube/translation/translator.go        |  12 +-
 11 files changed, 349 insertions(+), 290 deletions(-)

diff --git a/pkg/ingress/apisix_route.go b/pkg/ingress/apisix_route.go
index b91c8b7..293ec6a 100644
--- a/pkg/ingress/apisix_route.go
+++ b/pkg/ingress/apisix_route.go
@@ -18,6 +18,7 @@ import (
        "context"
        "time"
 
+       "github.com/apache/apisix-ingress-controller/pkg/kube/translation"
        "go.uber.org/zap"
        v1 "k8s.io/api/core/v1"
        k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -28,7 +29,6 @@ import (
        "github.com/apache/apisix-ingress-controller/pkg/kube"
        "github.com/apache/apisix-ingress-controller/pkg/log"
        "github.com/apache/apisix-ingress-controller/pkg/types"
-       apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
 type apisixRouteController struct {
@@ -89,9 +89,8 @@ func (c *apisixRouteController) sync(ctx context.Context, ev 
*types.Event) error
                return err
        }
        var (
-               ar        kube.ApisixRoute
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
+               ar   kube.ApisixRoute
+               tctx *translation.TranslateContext
        )
        if obj.GroupVersion == kube.ApisixRouteV1 {
                ar, err = c.controller.apisixRouteLister.V1(namespace, name)
@@ -130,7 +129,7 @@ func (c *apisixRouteController) sync(ctx context.Context, 
ev *types.Event) error
                ar = ev.Tombstone.(kube.ApisixRoute)
        }
        if obj.GroupVersion == kube.ApisixRouteV1 {
-               routes, upstreams, err = 
c.controller.translator.TranslateRouteV1(ar.V1())
+               tctx, err = c.controller.translator.TranslateRouteV1(ar.V1())
                if err != nil {
                        log.Errorw("failed to translate ApisixRoute v1",
                                zap.Error(err),
@@ -139,7 +138,7 @@ func (c *apisixRouteController) sync(ctx context.Context, 
ev *types.Event) error
                        return err
                }
        } else {
-               routes, upstreams, err = 
c.controller.translator.TranslateRouteV2alpha1(ar.V2alpha1())
+               tctx, err = 
c.controller.translator.TranslateRouteV2alpha1(ar.V2alpha1())
                if err != nil {
                        log.Errorw("failed to translate ApisixRoute v2alpha1",
                                zap.Error(err),
@@ -150,14 +149,14 @@ func (c *apisixRouteController) sync(ctx context.Context, 
ev *types.Event) error
        }
 
        log.Debugw("translated ApisixRoute",
-               zap.Any("routes", routes),
-               zap.Any("upstreams", upstreams),
+               zap.Any("routes", tctx.Routes),
+               zap.Any("upstreams", tctx.Upstreams),
                zap.Any("apisix_route", ar),
        )
 
        m := &manifest{
-               routes:    routes,
-               upstreams: upstreams,
+               routes:    tctx.Routes,
+               upstreams: tctx.Upstreams,
        }
 
        var (
@@ -171,14 +170,11 @@ func (c *apisixRouteController) sync(ctx context.Context, 
ev *types.Event) error
        } else if ev.Type == types.EventAdd {
                added = m
        } else {
-               var (
-                       oldRoutes    []*apisixv1.Route
-                       oldUpstreams []*apisixv1.Upstream
-               )
+               var oldCtx *translation.TranslateContext
                if obj.GroupVersion == kube.ApisixRouteV1 {
-                       oldRoutes, oldUpstreams, err = 
c.controller.translator.TranslateRouteV1(obj.OldObject.V1())
+                       oldCtx, err = 
c.controller.translator.TranslateRouteV1(obj.OldObject.V1())
                } else {
-                       oldRoutes, oldUpstreams, err = 
c.controller.translator.TranslateRouteV2alpha1(obj.OldObject.V2alpha1())
+                       oldCtx, err = 
c.controller.translator.TranslateRouteV2alpha1(obj.OldObject.V2alpha1())
                }
                if err != nil {
                        log.Errorw("failed to translate old ApisixRoute 
v2alpha1",
@@ -191,8 +187,8 @@ func (c *apisixRouteController) sync(ctx context.Context, 
ev *types.Event) error
                }
 
                om := &manifest{
-                       routes:    oldRoutes,
-                       upstreams: oldUpstreams,
+                       routes:    oldCtx.Routes,
+                       upstreams: oldCtx.Upstreams,
                }
                added, updated, deleted = m.diff(om)
        }
diff --git a/pkg/ingress/ingress.go b/pkg/ingress/ingress.go
index fb3281e..9e2e7a1 100644
--- a/pkg/ingress/ingress.go
+++ b/pkg/ingress/ingress.go
@@ -28,7 +28,6 @@ import (
        "github.com/apache/apisix-ingress-controller/pkg/kube"
        "github.com/apache/apisix-ingress-controller/pkg/log"
        "github.com/apache/apisix-ingress-controller/pkg/types"
-       apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
 const (
@@ -127,8 +126,7 @@ func (c *ingressController) sync(ctx context.Context, ev 
*types.Event) error {
                ing = ev.Tombstone.(kube.Ingress)
        }
 
-       // Translator should generate ID, fullname and name.
-       routes, upstreams, err := c.controller.translator.TranslateIngress(ing)
+       tctx, err := c.controller.translator.TranslateIngress(ing)
        if err != nil {
                log.Errorw("failed to translate ingress",
                        zap.Error(err),
@@ -139,13 +137,13 @@ func (c *ingressController) sync(ctx context.Context, ev 
*types.Event) error {
 
        log.Debugw("translated ingress resource to a couple of routes and 
upstreams",
                zap.Any("ingress", ing),
-               zap.Any("routes", routes),
-               zap.Any("upstreams", upstreams),
+               zap.Any("routes", tctx.Routes),
+               zap.Any("upstreams", tctx.Upstreams),
        )
 
        m := &manifest{
-               routes:    routes,
-               upstreams: upstreams,
+               routes:    tctx.Routes,
+               upstreams: tctx.Upstreams,
        }
 
        var (
@@ -159,11 +157,7 @@ func (c *ingressController) sync(ctx context.Context, ev 
*types.Event) error {
        } else if ev.Type == types.EventAdd {
                added = m
        } else {
-               var (
-                       oldRoutes    []*apisixv1.Route
-                       oldUpstreams []*apisixv1.Upstream
-               )
-               oldRoutes, oldUpstreams, err := 
c.controller.translator.TranslateIngress(ingEv.OldObject)
+               oldCtx, err := 
c.controller.translator.TranslateIngress(ingEv.OldObject)
                if err != nil {
                        log.Errorw("failed to translate ingress",
                                zap.String("event", "update"),
@@ -173,8 +167,8 @@ func (c *ingressController) sync(ctx context.Context, ev 
*types.Event) error {
                        return err
                }
                om := &manifest{
-                       routes:    oldRoutes,
-                       upstreams: oldUpstreams,
+                       routes:    oldCtx.Routes,
+                       upstreams: oldCtx.Upstreams,
                }
                added, updated, deleted = m.diff(om)
        }
diff --git a/pkg/kube/translation/apisix_route.go 
b/pkg/kube/translation/apisix_route.go
index bcd4b99..69cbae4 100644
--- a/pkg/kube/translation/apisix_route.go
+++ b/pkg/kube/translation/apisix_route.go
@@ -27,14 +27,11 @@ import (
        apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
-func (t *translator) TranslateRouteV1(ar *configv1.ApisixRoute) 
([]*apisixv1.Route, []*apisixv1.Upstream, error) {
-       var (
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
-       )
-
+func (t *translator) TranslateRouteV1(ar *configv1.ApisixRoute) 
(*TranslateContext, error) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
        plugins := t.TranslateAnnotations(ar.Annotations)
-       upstreamMap := make(map[string]*apisixv1.Upstream)
 
        for _, r := range ar.Spec.Rules {
                for _, p := range r.Http.Paths {
@@ -66,53 +63,42 @@ func (t *translator) TranslateRouteV1(ar 
*configv1.ApisixRoute) ([]*apisixv1.Rou
                        route.Plugins = pluginMap
                        route.UpstreamId = id.GenID(upstreamName)
 
-                       if _, ok := upstreamMap[upstreamName]; !ok {
+                       if !ctx.checkUpstreamExist(upstreamName) {
                                ups, err := t.TranslateUpstream(ar.Namespace, 
p.Backend.ServiceName, int32(p.Backend.ServicePort))
                                if err != nil {
-                                       return nil, nil, err
+                                       return nil, err
                                }
                                ups.ID = route.UpstreamId
                                ups.Name = upstreamName
-                               upstreamMap[ups.Name] = ups
+                               ctx.addUpstream(ups)
                        }
-                       routes = append(routes, route)
+                       ctx.addRoute(route)
                }
        }
-       for _, ups := range upstreamMap {
-               upstreams = append(upstreams, ups)
-       }
-       return routes, upstreams, nil
+       return ctx, nil
 }
 
-func (t *translator) TranslateRouteV2alpha1(ar *configv2alpha1.ApisixRoute) 
([]*apisixv1.Route, []*apisixv1.Upstream, error) {
-       var (
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
-       )
+func (t *translator) TranslateRouteV2alpha1(ar *configv2alpha1.ApisixRoute) 
(*TranslateContext, error) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
 
-       ruleNameMap := make(map[string]struct{})
-       upstreamMap := make(map[string]*apisixv1.Upstream)
+       if err := t.translateHTTPRoute(ctx, ar); err != nil {
+               return nil, err
+       }
+       if err := t.translateTCPRoute(ctx, ar); err != nil {
+               return nil, err
+       }
+       return ctx, nil
+}
 
+func (t *translator) translateHTTPRoute(ctx *TranslateContext, ar 
*configv2alpha1.ApisixRoute) error {
+       ruleNameMap := make(map[string]struct{})
        for _, part := range ar.Spec.HTTP {
-               if part.Name == "" {
-                       return nil, nil, errors.New("empty route rule name")
-               }
                if _, ok := ruleNameMap[part.Name]; ok {
-                       return nil, nil, errors.New("duplicated route rule 
name")
+                       return errors.New("duplicated route rule name")
                }
                ruleNameMap[part.Name] = struct{}{}
-               if part.Match == nil {
-                       return nil, nil, errors.New("empty route match section")
-               }
-               if len(part.Match.Paths) < 1 {
-                       return nil, nil, errors.New("empty route paths match")
-               }
-               if part.Backend != nil && len(part.Backends) > 1 {
-                       return nil, nil, errors.New("backend and backends are 
exclusive")
-               }
-               if part.Backend == nil && len(part.Backends) == 0 {
-                       return nil, nil, errors.New("no specified backend")
-               }
                backends := part.Backends
                backend := part.Backend
                if len(backends) > 0 {
@@ -129,7 +115,7 @@ func (t *translator) TranslateRouteV2alpha1(ar 
*configv2alpha1.ApisixRoute) ([]*
                                zap.Any("apisix_route", ar),
                                zap.Error(err),
                        )
-                       return nil, nil, err
+                       return err
                }
 
                pluginMap := make(apisixv1.Plugins)
@@ -152,7 +138,7 @@ func (t *translator) TranslateRouteV2alpha1(ar 
*configv2alpha1.ApisixRoute) ([]*
                                        zap.Error(err),
                                        zap.Any("ApisixRoute", ar),
                                )
-                               return nil, nil, err
+                               return err
                        }
                }
                if err := validateRemoteAddrs(part.Match.RemoteAddrs); err != 
nil {
@@ -161,7 +147,7 @@ func (t *translator) TranslateRouteV2alpha1(ar 
*configv2alpha1.ApisixRoute) ([]*
                                zap.Strings("remote_addrs", 
part.Match.RemoteAddrs),
                                zap.Any("ApisixRoute", ar),
                        )
-                       return nil, nil, err
+                       return err
                }
 
                upstreamName := apisixv1.ComposeUpstreamName(ar.Namespace, 
backend.ServiceName, svcPort)
@@ -183,36 +169,26 @@ func (t *translator) TranslateRouteV2alpha1(ar 
*configv2alpha1.ApisixRoute) ([]*
                        if backend.Weight != nil {
                                weight = *backend.Weight
                        }
-                       ups, plugin, err := t.translateTrafficSplitPlugin(ar, 
weight, backends)
+                       plugin, err := t.translateTrafficSplitPlugin(ctx, ar, 
weight, backends)
                        if err != nil {
                                log.Errorw("failed to translate traffic-split 
plugin",
                                        zap.Error(err),
                                        zap.Any("ApisixRoute", ar),
                                )
-                               return nil, nil, err
-                       }
-                       for _, u := range ups {
-                               if _, ok := upstreamMap[u.Name]; !ok {
-                                       upstreamMap[u.Name] = u
-                               }
+                               return err
                        }
                        route.Plugins["traffic-split"] = plugin
                }
-
-               routes = append(routes, route)
-               if _, ok := upstreamMap[upstreamName]; !ok {
+               ctx.addRoute(route)
+               if !ctx.checkUpstreamExist(upstreamName) {
                        ups, err := t.translateUpstream(ar.Namespace, 
backend.ServiceName, backend.ResolveGranularity, svcClusterIP, svcPort)
                        if err != nil {
-                               return nil, nil, err
+                               return err
                        }
-                       upstreamMap[ups.Name] = ups
+                       ctx.addUpstream(ups)
                }
        }
-
-       for _, ups := range upstreamMap {
-               upstreams = append(upstreams, ups)
-       }
-       return routes, upstreams, nil
+       return nil
 }
 
 func (t *translator) translateRouteMatchExprs(nginxVars 
[]configv2alpha1.ApisixRouteHTTPMatchExpr) ([][]apisixv1.StringOrSlice, error) {
@@ -316,3 +292,7 @@ func (t *translator) translateRouteMatchExprs(nginxVars 
[]configv2alpha1.ApisixR
 
        return vars, nil
 }
+
+func (t *translator) translateTCPRoute(ctx *TranslateContext, ar 
*configv2alpha1.ApisixRoute) error {
+       return nil
+}
diff --git a/pkg/kube/translation/apisix_route_test.go 
b/pkg/kube/translation/apisix_route_test.go
index e0a6c59..60baca1 100644
--- a/pkg/kube/translation/apisix_route_test.go
+++ b/pkg/kube/translation/apisix_route_test.go
@@ -170,26 +170,6 @@ func TestRouteMatchExpr(t *testing.T) {
        assert.Equal(t, results[8][2].SliceVal, []string{"a.com", "b.com"})
 }
 
-func TestTranslateApisixRouteV2alpha1WithEmptyName(t *testing.T) {
-       ar := &configv2alpha1.ApisixRoute{
-               ObjectMeta: metav1.ObjectMeta{
-                       Name:      "ar",
-                       Namespace: "test",
-               },
-               Spec: &configv2alpha1.ApisixRouteSpec{
-                       HTTP: []*configv2alpha1.ApisixRouteHTTP{
-                               {
-                                       Name:     "",
-                                       Priority: 0,
-                               },
-                       },
-               },
-       }
-       tr := &translator{}
-       _, _, err := tr.TranslateRouteV2alpha1(ar)
-       assert.Equal(t, err.Error(), "empty route rule name")
-}
-
 func TestTranslateApisixRouteV2alpha1WithDuplicatedName(t *testing.T) {
        svc := &corev1.Service{
                TypeMeta: metav1.TypeMeta{},
@@ -326,6 +306,6 @@ func TestTranslateApisixRouteV2alpha1WithDuplicatedName(t 
*testing.T) {
                },
        }
 
-       _, _, err = tr.TranslateRouteV2alpha1(ar)
+       _, err = tr.TranslateRouteV2alpha1(ar)
        assert.Equal(t, err.Error(), "duplicated route rule name")
 }
diff --git a/pkg/kube/translation/context.go b/pkg/kube/translation/context.go
new file mode 100644
index 0000000..aa6478c
--- /dev/null
+++ b/pkg/kube/translation/context.go
@@ -0,0 +1,47 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package translation
+
+import apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
+
+// TranslateContext contains APISIX resources generated by the translator.
+type TranslateContext struct {
+       Routes       []*apisix.Route
+       StreamRoutes []*apisix.StreamRoute
+       Upstreams    []*apisix.Upstream
+
+       upstreamMap map[string]struct{}
+}
+
+func (tc *TranslateContext) addRoute(r *apisix.Route) {
+       tc.Routes = append(tc.Routes, r)
+}
+
+func (tc *TranslateContext) addStreamRoute(sr *apisix.StreamRoute) {
+       tc.StreamRoutes = append(tc.StreamRoutes, sr)
+}
+
+func (tc *TranslateContext) addUpstream(u *apisix.Upstream) {
+       if _, ok := tc.upstreamMap[u.Name]; ok {
+               return
+       }
+       tc.upstreamMap[u.Name] = struct{}{}
+       tc.Upstreams = append(tc.Upstreams, u)
+}
+
+func (tc *TranslateContext) checkUpstreamExist(name string) (ok bool) {
+       _, ok = tc.upstreamMap[name]
+       return
+}
diff --git a/pkg/kube/translation/context_test.go 
b/pkg/kube/translation/context_test.go
new file mode 100644
index 0000000..b1097a6
--- /dev/null
+++ b/pkg/kube/translation/context_test.go
@@ -0,0 +1,76 @@
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements.  See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License.  You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package translation
+
+import (
+       "testing"
+
+       "github.com/stretchr/testify/assert"
+
+       apisix "github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
+)
+
+func TestTranslateContext(t *testing.T) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
+       r1 := &apisix.Route{
+               Metadata: apisix.Metadata{
+                       ID: "1",
+               },
+       }
+       r2 := &apisix.Route{
+               Metadata: apisix.Metadata{
+                       ID: "2",
+               },
+       }
+       sr1 := &apisix.StreamRoute{
+               ID: "1",
+       }
+       sr2 := &apisix.StreamRoute{
+               ID: "2",
+       }
+       u1 := &apisix.Upstream{
+               Metadata: apisix.Metadata{
+                       ID:   "1",
+                       Name: "aaa",
+               },
+       }
+       u2 := &apisix.Upstream{
+               Metadata: apisix.Metadata{
+                       ID:   "1",
+                       Name: "aaa",
+               },
+       }
+       ctx.addRoute(r1)
+       ctx.addRoute(r2)
+       ctx.addStreamRoute(sr1)
+       ctx.addStreamRoute(sr2)
+       ctx.addUpstream(u1)
+       ctx.addUpstream(u2)
+
+       assert.Len(t, ctx.Routes, 2)
+       assert.Len(t, ctx.StreamRoutes, 2)
+       assert.Len(t, ctx.Upstreams, 1)
+
+       assert.Equal(t, ctx.Routes[0], r1)
+       assert.Equal(t, ctx.Routes[1], r2)
+       assert.Equal(t, ctx.StreamRoutes[0], sr1)
+       assert.Equal(t, ctx.StreamRoutes[1], sr2)
+       assert.Equal(t, ctx.Upstreams[0], u1)
+
+       assert.Equal(t, ctx.checkUpstreamExist("aaa"), true)
+       assert.Equal(t, ctx.checkUpstreamExist("bbb"), false)
+}
diff --git a/pkg/kube/translation/ingress.go b/pkg/kube/translation/ingress.go
index 0ea9903..0590592 100644
--- a/pkg/kube/translation/ingress.go
+++ b/pkg/kube/translation/ingress.go
@@ -29,11 +29,10 @@ import (
        apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
-func (t *translator) translateIngressV1(ing *networkingv1.Ingress) 
([]*apisixv1.Route, []*apisixv1.Upstream, error) {
-       var (
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
-       )
+func (t *translator) translateIngressV1(ing *networkingv1.Ingress) 
(*TranslateContext, error) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
 
        for _, rule := range ing.Spec.Rules {
                for _, pathRule := range rule.HTTP.Paths {
@@ -48,9 +47,9 @@ func (t *translator) translateIngressV1(ing 
*networkingv1.Ingress) ([]*apisixv1.
                                                zap.Error(err),
                                                zap.Any("ingress", ing),
                                        )
-                                       return nil, nil, err
+                                       return nil, err
                                }
-                               upstreams = append(upstreams, ups)
+                               ctx.addUpstream(ups)
                        }
                        uris := []string{pathRule.Path}
                        if pathRule.PathType != nil && *pathRule.PathType == 
networkingv1.PathTypePrefix {
@@ -79,17 +78,16 @@ func (t *translator) translateIngressV1(ing 
*networkingv1.Ingress) ([]*apisixv1.
                        if ups != nil {
                                route.UpstreamId = ups.ID
                        }
-                       routes = append(routes, route)
+                       ctx.addRoute(route)
                }
        }
-       return routes, upstreams, nil
+       return ctx, nil
 }
 
-func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress) 
([]*apisixv1.Route, []*apisixv1.Upstream, error) {
-       var (
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
-       )
+func (t *translator) translateIngressV1beta1(ing *networkingv1beta1.Ingress) 
(*TranslateContext, error) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
 
        for _, rule := range ing.Spec.Rules {
                for _, pathRule := range rule.HTTP.Paths {
@@ -104,9 +102,9 @@ func (t *translator) translateIngressV1beta1(ing 
*networkingv1beta1.Ingress) ([]
                                                zap.Error(err),
                                                zap.Any("ingress", ing),
                                        )
-                                       return nil, nil, err
+                                       return nil, err
                                }
-                               upstreams = append(upstreams, ups)
+                               ctx.addUpstream(ups)
                        }
                        uris := []string{pathRule.Path}
                        if pathRule.PathType != nil && *pathRule.PathType == 
networkingv1beta1.PathTypePrefix {
@@ -135,10 +133,10 @@ func (t *translator) translateIngressV1beta1(ing 
*networkingv1beta1.Ingress) ([]
                        if ups != nil {
                                route.UpstreamId = ups.ID
                        }
-                       routes = append(routes, route)
+                       ctx.addRoute(route)
                }
        }
-       return routes, upstreams, nil
+       return ctx, nil
 }
 
 func (t *translator) translateUpstreamFromIngressV1(namespace string, backend 
*networkingv1.IngressServiceBackend) (*apisixv1.Upstream, error) {
@@ -172,11 +170,10 @@ func (t *translator) 
translateUpstreamFromIngressV1(namespace string, backend *n
        return ups, nil
 }
 
-func (t *translator) translateIngressExtensionsV1beta1(ing 
*extensionsv1beta1.Ingress) ([]*apisixv1.Route, []*apisixv1.Upstream, error) {
-       var (
-               routes    []*apisixv1.Route
-               upstreams []*apisixv1.Upstream
-       )
+func (t *translator) translateIngressExtensionsV1beta1(ing 
*extensionsv1beta1.Ingress) (*TranslateContext, error) {
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
 
        for _, rule := range ing.Spec.Rules {
                for _, pathRule := range rule.HTTP.Paths {
@@ -192,9 +189,9 @@ func (t *translator) translateIngressExtensionsV1beta1(ing 
*extensionsv1beta1.In
                                                zap.Error(err),
                                                zap.Any("ingress", ing),
                                        )
-                                       return nil, nil, err
+                                       return nil, err
                                }
-                               upstreams = append(upstreams, ups)
+                               ctx.addUpstream(ups)
                        }
                        uris := []string{pathRule.Path}
                        if pathRule.PathType != nil && *pathRule.PathType == 
extensionsv1beta1.PathTypePrefix {
@@ -226,10 +223,10 @@ func (t *translator) 
translateIngressExtensionsV1beta1(ing *extensionsv1beta1.In
                        if ups != nil {
                                route.UpstreamId = ups.ID
                        }
-                       routes = append(routes, route)
+                       ctx.addRoute(route)
                }
        }
-       return routes, upstreams, nil
+       return ctx, nil
 }
 
 func (t *translator) translateUpstreamFromIngressV1beta1(namespace string, 
svcName string, svcPort intstr.IntOrString) (*apisixv1.Upstream, error) {
diff --git a/pkg/kube/translation/ingress_test.go 
b/pkg/kube/translation/ingress_test.go
index b6d44c5..9afbd97 100644
--- a/pkg/kube/translation/ingress_test.go
+++ b/pkg/kube/translation/ingress_test.go
@@ -116,12 +116,12 @@ func TestTranslateIngressV1NoBackend(t *testing.T) {
                },
        }
        tr := &translator{}
-       routes, upstreams, err := tr.translateIngressV1(ing)
-       assert.Len(t, routes, 1)
-       assert.Len(t, upstreams, 0)
+       ctx, err := tr.translateIngressV1(ing)
+       assert.Len(t, ctx.Routes, 1)
+       assert.Len(t, ctx.Upstreams, 0)
        assert.Nil(t, err)
-       assert.Equal(t, routes[0].UpstreamId, "")
-       assert.Equal(t, routes[0].Uris, []string{"/foo", "/foo/*"})
+       assert.Equal(t, ctx.Routes[0].UpstreamId, "")
+       assert.Equal(t, ctx.Routes[0].Uris, []string{"/foo", "/foo/*"})
 }
 
 func TestTranslateIngressV1BackendWithInvalidService(t *testing.T) {
@@ -167,10 +167,9 @@ func TestTranslateIngressV1BackendWithInvalidService(t 
*testing.T) {
                        ServiceLister: svcLister,
                },
        }
-       routes, upstreams, err := tr.translateIngressV1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err := tr.translateIngressV1(ing)
        assert.NotNil(t, err)
+       assert.Nil(t, ctx)
        assert.Equal(t, err.Error(), "service \"test-service\" not found")
 
        processCh := make(chan struct{})
@@ -191,9 +190,8 @@ func TestTranslateIngressV1BackendWithInvalidService(t 
*testing.T) {
        assert.Nil(t, err)
 
        <-processCh
-       routes, upstreams, err = tr.translateIngressV1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err = tr.translateIngressV1(ing)
+       assert.Nil(t, ctx, nil)
        assert.Equal(t, err, &translateError{
                field:  "service",
                reason: "port not found",
@@ -286,33 +284,33 @@ func TestTranslateIngressV1(t *testing.T) {
 
        <-processCh
        <-processCh
-       routes, upstreams, err := tr.translateIngressV1(ing)
-       assert.Len(t, routes, 2)
-       assert.Len(t, upstreams, 2)
+       ctx, err := tr.translateIngressV1(ing)
+       assert.Len(t, ctx.Routes, 2)
+       assert.Len(t, ctx.Upstreams, 2)
        assert.Nil(t, err)
 
-       assert.Equal(t, routes[0].Uris, []string{"/foo", "/foo/*"})
-       assert.Equal(t, routes[0].UpstreamId, upstreams[0].ID)
-       assert.Equal(t, routes[0].Host, "apisix.apache.org")
-       assert.Equal(t, routes[1].Uris, []string{"/bar"})
-       assert.Equal(t, routes[1].UpstreamId, upstreams[1].ID)
-       assert.Equal(t, routes[1].Host, "apisix.apache.org")
-
-       assert.Equal(t, upstreams[0].Type, "roundrobin")
-       assert.Equal(t, upstreams[0].Scheme, "http")
-       assert.Len(t, upstreams[0].Nodes, 2)
-       assert.Equal(t, upstreams[0].Nodes[0].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[0].Nodes[1].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[1].Host, "192.168.1.2")
-
-       assert.Equal(t, upstreams[1].Type, "roundrobin")
-       assert.Equal(t, upstreams[1].Scheme, "http")
-       assert.Len(t, upstreams[1].Nodes, 2)
-       assert.Equal(t, upstreams[1].Nodes[0].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[1].Nodes[1].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[1].Host, "192.168.1.2")
+       assert.Equal(t, ctx.Routes[0].Uris, []string{"/foo", "/foo/*"})
+       assert.Equal(t, ctx.Routes[0].UpstreamId, ctx.Upstreams[0].ID)
+       assert.Equal(t, ctx.Routes[0].Host, "apisix.apache.org")
+       assert.Equal(t, ctx.Routes[1].Uris, []string{"/bar"})
+       assert.Equal(t, ctx.Routes[1].UpstreamId, ctx.Upstreams[1].ID)
+       assert.Equal(t, ctx.Routes[1].Host, "apisix.apache.org")
+
+       assert.Equal(t, ctx.Upstreams[0].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[0].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[0].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Host, "192.168.1.2")
+
+       assert.Equal(t, ctx.Upstreams[1].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[1].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[1].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Host, "192.168.1.2")
 }
 
 func TestTranslateIngressV1beta1NoBackend(t *testing.T) {
@@ -342,12 +340,12 @@ func TestTranslateIngressV1beta1NoBackend(t *testing.T) {
                },
        }
        tr := &translator{}
-       routes, upstreams, err := tr.translateIngressV1beta1(ing)
-       assert.Len(t, routes, 1)
-       assert.Len(t, upstreams, 0)
+       ctx, err := tr.translateIngressV1beta1(ing)
+       assert.Len(t, ctx.Routes, 1)
+       assert.Len(t, ctx.Upstreams, 0)
        assert.Nil(t, err)
-       assert.Equal(t, routes[0].UpstreamId, "")
-       assert.Equal(t, routes[0].Uris, []string{"/foo", "/foo/*"})
+       assert.Equal(t, ctx.Routes[0].UpstreamId, "")
+       assert.Equal(t, ctx.Routes[0].Uris, []string{"/foo", "/foo/*"})
 }
 
 func TestTranslateIngressV1beta1BackendWithInvalidService(t *testing.T) {
@@ -392,10 +390,9 @@ func 
TestTranslateIngressV1beta1BackendWithInvalidService(t *testing.T) {
                        ServiceLister: svcLister,
                },
        }
-       routes, upstreams, err := tr.translateIngressV1beta1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err := tr.translateIngressV1beta1(ing)
        assert.NotNil(t, err)
+       assert.Nil(t, ctx)
        assert.Equal(t, err.Error(), "service \"test-service\" not found")
 
        processCh := make(chan struct{})
@@ -416,9 +413,8 @@ func TestTranslateIngressV1beta1BackendWithInvalidService(t 
*testing.T) {
        assert.Nil(t, err)
 
        <-processCh
-       routes, upstreams, err = tr.translateIngressV1beta1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err = tr.translateIngressV1beta1(ing)
+       assert.Nil(t, ctx)
        assert.Equal(t, err, &translateError{
                field:  "service",
                reason: "port not found",
@@ -509,33 +505,33 @@ func TestTranslateIngressV1beta1(t *testing.T) {
 
        <-processCh
        <-processCh
-       routes, upstreams, err := tr.translateIngressV1beta1(ing)
-       assert.Len(t, routes, 2)
-       assert.Len(t, upstreams, 2)
+       ctx, err := tr.translateIngressV1beta1(ing)
+       assert.Len(t, ctx.Routes, 2)
+       assert.Len(t, ctx.Upstreams, 2)
        assert.Nil(t, err)
 
-       assert.Equal(t, routes[0].Uris, []string{"/foo", "/foo/*"})
-       assert.Equal(t, routes[0].UpstreamId, upstreams[0].ID)
-       assert.Equal(t, routes[0].Host, "apisix.apache.org")
-       assert.Equal(t, routes[1].Uris, []string{"/bar"})
-       assert.Equal(t, routes[1].UpstreamId, upstreams[1].ID)
-       assert.Equal(t, routes[1].Host, "apisix.apache.org")
-
-       assert.Equal(t, upstreams[0].Type, "roundrobin")
-       assert.Equal(t, upstreams[0].Scheme, "http")
-       assert.Len(t, upstreams[0].Nodes, 2)
-       assert.Equal(t, upstreams[0].Nodes[0].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[0].Nodes[1].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[1].Host, "192.168.1.2")
-
-       assert.Equal(t, upstreams[1].Type, "roundrobin")
-       assert.Equal(t, upstreams[1].Scheme, "http")
-       assert.Len(t, upstreams[1].Nodes, 2)
-       assert.Equal(t, upstreams[1].Nodes[0].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[1].Nodes[1].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[1].Host, "192.168.1.2")
+       assert.Equal(t, ctx.Routes[0].Uris, []string{"/foo", "/foo/*"})
+       assert.Equal(t, ctx.Routes[0].UpstreamId, ctx.Upstreams[0].ID)
+       assert.Equal(t, ctx.Routes[0].Host, "apisix.apache.org")
+       assert.Equal(t, ctx.Routes[1].Uris, []string{"/bar"})
+       assert.Equal(t, ctx.Routes[1].UpstreamId, ctx.Upstreams[1].ID)
+       assert.Equal(t, ctx.Routes[1].Host, "apisix.apache.org")
+
+       assert.Equal(t, ctx.Upstreams[0].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[0].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[0].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Host, "192.168.1.2")
+
+       assert.Equal(t, ctx.Upstreams[1].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[1].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[1].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Host, "192.168.1.2")
 }
 
 func TestTranslateIngressExtensionsV1beta1(t *testing.T) {
@@ -622,33 +618,33 @@ func TestTranslateIngressExtensionsV1beta1(t *testing.T) {
 
        <-processCh
        <-processCh
-       routes, upstreams, err := tr.translateIngressExtensionsV1beta1(ing)
-       assert.Len(t, routes, 2)
-       assert.Len(t, upstreams, 2)
+       ctx, err := tr.translateIngressExtensionsV1beta1(ing)
+       assert.Len(t, ctx.Routes, 2)
+       assert.Len(t, ctx.Upstreams, 2)
        assert.Nil(t, err)
 
-       assert.Equal(t, routes[0].Uris, []string{"/foo", "/foo/*"})
-       assert.Equal(t, routes[0].UpstreamId, upstreams[0].ID)
-       assert.Equal(t, routes[0].Host, "apisix.apache.org")
-       assert.Equal(t, routes[1].Uris, []string{"/bar"})
-       assert.Equal(t, routes[1].UpstreamId, upstreams[1].ID)
-       assert.Equal(t, routes[1].Host, "apisix.apache.org")
-
-       assert.Equal(t, upstreams[0].Type, "roundrobin")
-       assert.Equal(t, upstreams[0].Scheme, "http")
-       assert.Len(t, upstreams[0].Nodes, 2)
-       assert.Equal(t, upstreams[0].Nodes[0].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[0].Nodes[1].Port, 9080)
-       assert.Equal(t, upstreams[0].Nodes[1].Host, "192.168.1.2")
-
-       assert.Equal(t, upstreams[1].Type, "roundrobin")
-       assert.Equal(t, upstreams[1].Scheme, "http")
-       assert.Len(t, upstreams[1].Nodes, 2)
-       assert.Equal(t, upstreams[1].Nodes[0].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, upstreams[1].Nodes[1].Port, 9443)
-       assert.Equal(t, upstreams[1].Nodes[1].Host, "192.168.1.2")
+       assert.Equal(t, ctx.Routes[0].Uris, []string{"/foo", "/foo/*"})
+       assert.Equal(t, ctx.Routes[0].UpstreamId, ctx.Upstreams[0].ID)
+       assert.Equal(t, ctx.Routes[0].Host, "apisix.apache.org")
+       assert.Equal(t, ctx.Routes[1].Uris, []string{"/bar"})
+       assert.Equal(t, ctx.Routes[1].UpstreamId, ctx.Upstreams[1].ID)
+       assert.Equal(t, ctx.Routes[1].Host, "apisix.apache.org")
+
+       assert.Equal(t, ctx.Upstreams[0].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[0].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[0].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Host, "192.168.1.2")
+
+       assert.Equal(t, ctx.Upstreams[1].Type, "roundrobin")
+       assert.Equal(t, ctx.Upstreams[1].Scheme, "http")
+       assert.Len(t, ctx.Upstreams[1].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Port, 9443)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[1].Host, "192.168.1.2")
 }
 
 func TestTranslateIngressExtensionsV1beta1BackendWithInvalidService(t 
*testing.T) {
@@ -693,9 +689,8 @@ func 
TestTranslateIngressExtensionsV1beta1BackendWithInvalidService(t *testing.T
                        ServiceLister: svcLister,
                },
        }
-       routes, upstreams, err := tr.translateIngressExtensionsV1beta1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err := tr.translateIngressExtensionsV1beta1(ing)
+       assert.Nil(t, ctx)
        assert.NotNil(t, err)
        assert.Equal(t, err.Error(), "service \"test-service\" not found")
 
@@ -717,9 +712,8 @@ func 
TestTranslateIngressExtensionsV1beta1BackendWithInvalidService(t *testing.T
        assert.Nil(t, err)
 
        <-processCh
-       routes, upstreams, err = tr.translateIngressExtensionsV1beta1(ing)
-       assert.Len(t, routes, 0)
-       assert.Len(t, upstreams, 0)
+       ctx, err = tr.translateIngressExtensionsV1beta1(ing)
+       assert.Nil(t, ctx)
        assert.Equal(t, err, &translateError{
                field:  "service",
                reason: "port not found",
diff --git a/pkg/kube/translation/plugin.go b/pkg/kube/translation/plugin.go
index c76f600..9e14356 100644
--- a/pkg/kube/translation/plugin.go
+++ b/pkg/kube/translation/plugin.go
@@ -19,23 +19,22 @@ import (
        apisixv1 
"github.com/apache/apisix-ingress-controller/pkg/types/apisix/v1"
 )
 
-func (t *translator) translateTrafficSplitPlugin(ar 
*configv2alpha1.ApisixRoute, defaultBackendWeight int,
-       backends []*configv2alpha1.ApisixRouteHTTPBackend) 
([]*apisixv1.Upstream, *apisixv1.TrafficSplitConfig, error) {
+func (t *translator) translateTrafficSplitPlugin(ctx *TranslateContext, ar 
*configv2alpha1.ApisixRoute, defaultBackendWeight int,
+       backends []*configv2alpha1.ApisixRouteHTTPBackend) 
(*apisixv1.TrafficSplitConfig, error) {
        var (
-               upstreams []*apisixv1.Upstream
-               wups      []apisixv1.TrafficSplitConfigRuleWeightedUpstream
+               wups []apisixv1.TrafficSplitConfigRuleWeightedUpstream
        )
 
        for _, backend := range backends {
                svcClusterIP, svcPort, err := 
t.getServiceClusterIPAndPort(backend, ar)
                if err != nil {
-                       return nil, nil, err
+                       return nil, err
                }
                ups, err := t.translateUpstream(ar.Namespace, 
backend.ServiceName, backend.ResolveGranularity, svcClusterIP, svcPort)
                if err != nil {
-                       return nil, nil, err
+                       return nil, err
                }
-               upstreams = append(upstreams, ups)
+               ctx.addUpstream(ups)
 
                weight := _defaultWeight
                if backend.Weight != nil {
@@ -59,5 +58,5 @@ func (t *translator) translateTrafficSplitPlugin(ar 
*configv2alpha1.ApisixRoute,
                        },
                },
        }
-       return upstreams, tsCfg, nil
+       return tsCfg, nil
 }
diff --git a/pkg/kube/translation/plugin_test.go 
b/pkg/kube/translation/plugin_test.go
index e8ab921..172429a 100644
--- a/pkg/kube/translation/plugin_test.go
+++ b/pkg/kube/translation/plugin_test.go
@@ -176,21 +176,24 @@ func TestTranslateTrafficSplitPlugin(t *testing.T) {
                EndpointsLister:      epLister,
                ApisixUpstreamLister: auLister,
        }}
-       ups, cfg, err := tr.translateTrafficSplitPlugin(ar1, 30, backends)
+       ctx := &TranslateContext{
+               upstreamMap: make(map[string]struct{}),
+       }
+       cfg, err := tr.translateTrafficSplitPlugin(ctx, ar1, 30, backends)
        assert.Nil(t, err)
 
-       assert.Len(t, ups, 2)
-       assert.Equal(t, ups[0].Name, "test_svc-1_80")
-       assert.Len(t, ups[0].Nodes, 2)
-       assert.Equal(t, ups[0].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, ups[0].Nodes[0].Port, 9080)
-       assert.Equal(t, ups[0].Nodes[1].Host, "192.168.1.2")
-       assert.Equal(t, ups[0].Nodes[1].Port, 9080)
+       assert.Len(t, ctx.Upstreams, 2)
+       assert.Equal(t, ctx.Upstreams[0].Name, "test_svc-1_80")
+       assert.Len(t, ctx.Upstreams[0].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Host, "192.168.1.2")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Port, 9080)
 
-       assert.Equal(t, ups[1].Name, "test_svc-1_443")
-       assert.Len(t, ups[1].Nodes, 1)
-       assert.Equal(t, ups[1].Nodes[0].Host, "10.0.5.3")
-       assert.Equal(t, ups[1].Nodes[0].Port, 443)
+       assert.Equal(t, ctx.Upstreams[1].Name, "test_svc-1_443")
+       assert.Len(t, ctx.Upstreams[1].Nodes, 1)
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Host, "10.0.5.3")
+       assert.Equal(t, ctx.Upstreams[1].Nodes[0].Port, 443)
 
        assert.Len(t, cfg.Rules, 1)
        assert.Len(t, cfg.Rules[0].WeightedUpstreams, 3)
@@ -345,25 +348,17 @@ func TestTranslateTrafficSplitPluginWithSameUpstreams(t 
*testing.T) {
                EndpointsLister:      epLister,
                ApisixUpstreamLister: auLister,
        }}
-       ups, cfg, err := tr.translateTrafficSplitPlugin(ar1, 30, backends)
+       ctx := &TranslateContext{upstreamMap: make(map[string]struct{})}
+       cfg, err := tr.translateTrafficSplitPlugin(ctx, ar1, 30, backends)
        assert.Nil(t, err)
 
-       // Here ups has two elements, but the duplicated one will be
-       // removed in TranslateApisixRouteV2alpha1.
-       assert.Len(t, ups, 2)
-       assert.Equal(t, ups[0].Name, "test_svc-1_80")
-       assert.Len(t, ups[0].Nodes, 2)
-       assert.Equal(t, ups[0].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, ups[0].Nodes[0].Port, 9080)
-       assert.Equal(t, ups[0].Nodes[1].Host, "192.168.1.2")
-       assert.Equal(t, ups[0].Nodes[1].Port, 9080)
-
-       assert.Equal(t, ups[1].Name, "test_svc-1_80")
-       assert.Len(t, ups[1].Nodes, 2)
-       assert.Equal(t, ups[1].Nodes[0].Host, "192.168.1.1")
-       assert.Equal(t, ups[1].Nodes[0].Port, 9080)
-       assert.Equal(t, ups[1].Nodes[1].Host, "192.168.1.2")
-       assert.Equal(t, ups[1].Nodes[1].Port, 9080)
+       assert.Len(t, ctx.Upstreams, 1)
+       assert.Equal(t, ctx.Upstreams[0].Name, "test_svc-1_80")
+       assert.Len(t, ctx.Upstreams[0].Nodes, 2)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Host, "192.168.1.1")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[0].Port, 9080)
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Host, "192.168.1.2")
+       assert.Equal(t, ctx.Upstreams[0].Nodes[1].Port, 9080)
 
        assert.Len(t, cfg.Rules, 1)
        assert.Len(t, cfg.Rules[0].WeightedUpstreams, 3)
@@ -518,22 +513,23 @@ func TestTranslateTrafficSplitPluginBadCases(t 
*testing.T) {
                EndpointsLister:      epLister,
                ApisixUpstreamLister: auLister,
        }}
-       ups, cfg, err := tr.translateTrafficSplitPlugin(ar1, 30, backends)
-       assert.Nil(t, ups)
+       ctx := &TranslateContext{upstreamMap: make(map[string]struct{})}
+       cfg, err := tr.translateTrafficSplitPlugin(ctx, ar1, 30, backends)
        assert.Nil(t, cfg)
+       assert.Len(t, ctx.Upstreams, 0)
        assert.Equal(t, err.Error(), "service \"svc-2\" not found")
 
        backends[0].ServiceName = "svc-1"
        backends[1].ServicePort.StrVal = "port-not-found"
-       ups, cfg, err = tr.translateTrafficSplitPlugin(ar1, 30, backends)
-       assert.Nil(t, ups)
+       ctx = &TranslateContext{upstreamMap: make(map[string]struct{})}
+       cfg, err = tr.translateTrafficSplitPlugin(ctx, ar1, 30, backends)
        assert.Nil(t, cfg)
        assert.Equal(t, err.Error(), "service.spec.ports: port not defined")
 
        backends[1].ServicePort.StrVal = "port2"
        backends[1].ResolveGranularity = "service"
-       ups, cfg, err = tr.translateTrafficSplitPlugin(ar1, 30, backends)
-       assert.Nil(t, ups)
+       ctx = &TranslateContext{upstreamMap: make(map[string]struct{})}
+       cfg, err = tr.translateTrafficSplitPlugin(ctx, ar1, 30, backends)
        assert.Nil(t, cfg)
        assert.Equal(t, err.Error(), "conflict headless service and backend 
resolve granularity")
 }
diff --git a/pkg/kube/translation/translator.go 
b/pkg/kube/translation/translator.go
index f134050..701d7dc 100644
--- a/pkg/kube/translation/translator.go
+++ b/pkg/kube/translation/translator.go
@@ -57,13 +57,13 @@ type Translator interface {
        TranslateUpstream(string, string, int32) (*apisixv1.Upstream, error)
        // TranslateIngress composes a couple of APISIX Routes and upstreams 
according
        // to the given Ingress resource.
-       TranslateIngress(kube.Ingress) ([]*apisixv1.Route, 
[]*apisixv1.Upstream, error)
+       TranslateIngress(kube.Ingress) (*TranslateContext, error)
        // TranslateRouteV1 translates the configv1.ApisixRoute object into 
several Route
        // and Upstream resources.
-       TranslateRouteV1(*configv1.ApisixRoute) ([]*apisixv1.Route, 
[]*apisixv1.Upstream, error)
-       // TranslateRouteV2alpha1 translates the configv2alph1.ApisixRoute 
object into several Route
+       TranslateRouteV1(*configv1.ApisixRoute) (*TranslateContext, error)
+       // TranslateRouteV2alpha1 translates the configv2alpha1.ApisixRoute 
object into several Route
        // and Upstream resources.
-       TranslateRouteV2alpha1(*configv2alpha1.ApisixRoute) ([]*apisixv1.Route, 
[]*apisixv1.Upstream, error)
+       TranslateRouteV2alpha1(*configv2alpha1.ApisixRoute) (*TranslateContext, 
error)
        // TranslateSSL translates the configv2alpha1.ApisixTls object into the 
APISIX SSL resource.
        TranslateSSL(*configv1.ApisixTls) (*apisixv1.Ssl, error)
 }
@@ -191,7 +191,7 @@ func (t *translator) TranslateUpstreamNodes(endpoints 
*corev1.Endpoints, port in
        return nodes, nil
 }
 
-func (t *translator) TranslateIngress(ing kube.Ingress) ([]*apisixv1.Route, 
[]*apisixv1.Upstream, error) {
+func (t *translator) TranslateIngress(ing kube.Ingress) (*TranslateContext, 
error) {
        switch ing.GroupVersion() {
        case kube.IngressV1:
                return t.translateIngressV1(ing.V1())
@@ -200,6 +200,6 @@ func (t *translator) TranslateIngress(ing kube.Ingress) 
([]*apisixv1.Route, []*a
        case kube.IngressExtensionsV1beta1:
                return 
t.translateIngressExtensionsV1beta1(ing.ExtensionsV1beta1())
        default:
-               return nil, nil, fmt.Errorf("translator: source group version 
not supported: %s", ing.GroupVersion())
+               return nil, fmt.Errorf("translator: source group version not 
supported: %s", ing.GroupVersion())
        }
 }

Reply via email to