From d8d52bb694baf6037242cc12a4999e222c2d32b0 Mon Sep 17 00:00:00 2001 From: liaochuntao Date: Thu, 29 Sep 2022 15:56:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BC=98=E5=8C=96v2=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E8=A7=84=E5=88=99=E5=AF=B9=E4=BA=8Ev1=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E8=A7=84=E5=88=99=E7=9A=84=E5=85=BC=E5=AE=B9=E9=80=BB=E8=BE=91?= =?UTF-8?q?=20(#707)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix issue #629 (#693) * docs:优化错误信息描述 * Update zh.toml * fix:修复eureka心跳协议错误码不兼容问题 * fix:修复eureka心跳协议错误码不兼容问题 * unit:添加单元测试 * test:调整测试配置文件位置 * fix:issue #692 * fix:issue #692 * fix:issue #692 * fix:issue #692 * docs:add error code desc * fix:优化v2路由规则对于v1路由规则的兼容逻辑 * fix:优化v2路由规则对于v1路由规则的兼容逻辑 * fix:优化v2路由规则对于v1路由规则的兼容逻辑 --- apiserver/httpserver/server.go | 10 +- .../{ => v1}/naming_client_access.go | 20 +- .../httpserver/v2/naming_client_access.go | 93 +++++++++ cache/routing_config.go | 1 - common/api/v2/response.go | 4 +- common/model/v2/routing.go | 1 - common/routing/routing.go | 3 - polaris-server.yaml | 6 +- service/main_test.go | 98 ++++++++- service/routing_config_v2.go | 86 +------- service/routing_config_v2_test.go | 186 +++++++++++++++++- store/boltdb/routing_config_v2.go | 2 +- store/sqldb/scripts/delta/v1_8_0-v1_11_0.sql | 2 +- 13 files changed, 399 insertions(+), 113 deletions(-) rename apiserver/httpserver/{ => v1}/naming_client_access.go (88%) create mode 100644 apiserver/httpserver/v2/naming_client_access.go diff --git a/apiserver/httpserver/server.go b/apiserver/httpserver/server.go index b52067279..2b8f48f5a 100644 --- a/apiserver/httpserver/server.go +++ b/apiserver/httpserver/server.go @@ -358,11 +358,17 @@ func (h *HTTPServer) createRestfulContainer() (*restful.Container, error) { } case "client": if config.Enable { - service, err := h.GetClientAccessServer(config.Include) + serviceV1, err := h.v1Server.GetClientAccessServer(config.Include) if err != nil { return nil, err } - wsContainer.Add(service) + wsContainer.Add(serviceV1) + + serviceV2, err := h.v2Server.GetClientAccessServer(config.Include) + if err != nil { + return nil, err + } + wsContainer.Add(serviceV2) } case "config": if config.Enable { diff --git a/apiserver/httpserver/naming_client_access.go b/apiserver/httpserver/v1/naming_client_access.go similarity index 88% rename from apiserver/httpserver/naming_client_access.go rename to apiserver/httpserver/v1/naming_client_access.go index 9e9ffefb9..40a1cb043 100644 --- a/apiserver/httpserver/naming_client_access.go +++ b/apiserver/httpserver/v1/naming_client_access.go @@ -15,7 +15,7 @@ * specific language governing permissions and limitations under the License. */ -package httpserver +package v1 import ( "fmt" @@ -30,7 +30,7 @@ import ( ) // GetClientAccessServer get client access server -func (h *HTTPServer) GetClientAccessServer(include []string) (*restful.WebService, error) { +func (h *HTTPServerV1) GetClientAccessServer(include []string) (*restful.WebService, error) { clientAccess := []string{apiserver.DiscoverAccess, apiserver.RegisterAccess, apiserver.HealthcheckAccess} ws := new(restful.WebService) @@ -61,7 +61,7 @@ func (h *HTTPServer) GetClientAccessServer(include []string) (*restful.WebServic } // addDiscoverAccess 增加服务发现接口 -func (h *HTTPServer) addDiscoverAccess(ws *restful.WebService) { +func (h *HTTPServerV1) addDiscoverAccess(ws *restful.WebService) { tags := []string{"DiscoverAccess"} ws.Route(ws.POST("/ReportClient").To(h.ReportClient). Doc("上报客户端"). @@ -73,7 +73,7 @@ func (h *HTTPServer) addDiscoverAccess(ws *restful.WebService) { } // addRegisterAccess 增加注册/反注册接口 -func (h *HTTPServer) addRegisterAccess(ws *restful.WebService) { +func (h *HTTPServerV1) addRegisterAccess(ws *restful.WebService) { tags := []string{"Instances", "RegisterAccess"} ws.Route(ws.POST("/RegisterInstance"). Doc("注册实例"). @@ -87,12 +87,12 @@ func (h *HTTPServer) addRegisterAccess(ws *restful.WebService) { } // addHealthCheckAccess 增加健康检查接口 -func (h *HTTPServer) addHealthCheckAccess(ws *restful.WebService) { +func (h *HTTPServerV1) addHealthCheckAccess(ws *restful.WebService) { ws.Route(ws.POST("/Heartbeat").To(h.Heartbeat)) } // ReportClient 客户端上报信息 -func (h *HTTPServer) ReportClient(req *restful.Request, rsp *restful.Response) { +func (h *HTTPServerV1) ReportClient(req *restful.Request, rsp *restful.Response) { handler := &httpcommon.Handler{req, rsp} client := &api.Client{} ctx, err := handler.Parse(client) @@ -105,7 +105,7 @@ func (h *HTTPServer) ReportClient(req *restful.Request, rsp *restful.Response) { } // RegisterInstance 注册服务实例 -func (h *HTTPServer) RegisterInstance(req *restful.Request, rsp *restful.Response) { +func (h *HTTPServerV1) RegisterInstance(req *restful.Request, rsp *restful.Response) { handler := &httpcommon.Handler{req, rsp} instance := &api.Instance{} @@ -119,7 +119,7 @@ func (h *HTTPServer) RegisterInstance(req *restful.Request, rsp *restful.Respons } // DeregisterInstance 反注册服务实例 -func (h *HTTPServer) DeregisterInstance(req *restful.Request, rsp *restful.Response) { +func (h *HTTPServerV1) DeregisterInstance(req *restful.Request, rsp *restful.Response) { handler := &httpcommon.Handler{req, rsp} instance := &api.Instance{} @@ -133,7 +133,7 @@ func (h *HTTPServer) DeregisterInstance(req *restful.Request, rsp *restful.Respo } // Discover 统一发现接口 -func (h *HTTPServer) Discover(req *restful.Request, rsp *restful.Response) { +func (h *HTTPServerV1) Discover(req *restful.Request, rsp *restful.Response) { handler := &httpcommon.Handler{req, rsp} discoverRequest := &api.DiscoverRequest{} @@ -171,7 +171,7 @@ func (h *HTTPServer) Discover(req *restful.Request, rsp *restful.Response) { } // Heartbeat 服务实例心跳 -func (h *HTTPServer) Heartbeat(req *restful.Request, rsp *restful.Response) { +func (h *HTTPServerV1) Heartbeat(req *restful.Request, rsp *restful.Response) { handler := &httpcommon.Handler{req, rsp} instance := &api.Instance{} diff --git a/apiserver/httpserver/v2/naming_client_access.go b/apiserver/httpserver/v2/naming_client_access.go new file mode 100644 index 000000000..c8408d606 --- /dev/null +++ b/apiserver/httpserver/v2/naming_client_access.go @@ -0,0 +1,93 @@ +/** + * Tencent is pleased to support the open source community by making Polaris available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * 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 v2 + +import ( + "fmt" + + "github.com/emicklei/go-restful/v3" + restfulspec "github.com/polarismesh/go-restful-openapi/v2" + "go.uber.org/zap" + + "github.com/polarismesh/polaris-server/apiserver" + httpcommon "github.com/polarismesh/polaris-server/apiserver/httpserver/http" + api "github.com/polarismesh/polaris-server/common/api/v1" + apiv2 "github.com/polarismesh/polaris-server/common/api/v2" +) + +// GetClientAccessServer get client access server +func (h *HTTPServerV2) GetClientAccessServer(include []string) (*restful.WebService, error) { + clientAccess := []string{apiserver.DiscoverAccess, apiserver.RegisterAccess, apiserver.HealthcheckAccess} + + ws := new(restful.WebService) + + ws.Path("/v2").Consumes(restful.MIME_JSON).Produces(restful.MIME_JSON) + + // 如果为空,则开启全部接口 + if len(include) == 0 { + include = clientAccess + } + + // 客户端接口:增删改请求操作存储层,查请求访问缓存 + for _, item := range include { + switch item { + case apiserver.DiscoverAccess: + h.addDiscoverAccess(ws) + } + } + + return ws, nil +} + +// addDiscoverAccess 增加服务发现接口 +func (h *HTTPServerV2) addDiscoverAccess(ws *restful.WebService) { + tags := []string{"DiscoverAccess"} + ws.Route(ws.POST("/Discover").To(h.Discover). + Doc("服务发现"). + Metadata(restfulspec.KeyOpenAPITags, tags)) +} + +// Discover 统一发现接口 +func (h *HTTPServerV2) Discover(req *restful.Request, rsp *restful.Response) { + handler := &httpcommon.Handler{req, rsp} + + discoverRequest := &apiv2.DiscoverRequest{} + ctx, err := handler.Parse(discoverRequest) + if err != nil { + handler.WriteHeaderAndProto(api.NewResponseWithMsg(api.ParseException, err.Error())) + return + } + + msg := fmt.Sprintf("receive http discover request: %s", discoverRequest.GetSerivce().String()) + namingLog.Info(msg, + zap.String("type", api.DiscoverRequest_DiscoverRequestType_name[int32(discoverRequest.Type)]), + zap.String("client-address", req.Request.RemoteAddr), + zap.String("user-agent", req.HeaderParameter("User-Agent")), + zap.String("request-id", req.HeaderParameter("Request-Id")), + ) + + var ret *apiv2.DiscoverResponse + switch discoverRequest.Type { + case apiv2.DiscoverRequest_ROUTING: + ret = h.namingServer.GetRoutingConfigV2WithCache(ctx, discoverRequest.GetSerivce()) + default: + ret = apiv2.NewDiscoverRoutingResponse(api.InvalidDiscoverResource, discoverRequest.GetSerivce()) + } + + handler.WriteHeaderAndProtoV2(ret) +} diff --git a/cache/routing_config.go b/cache/routing_config.go index 93df99d1d..8578146dd 100644 --- a/cache/routing_config.go +++ b/cache/routing_config.go @@ -221,7 +221,6 @@ func formatRoutingResponseV1(ret *apiv1.Routing) *apiv1.Routing { for i := range outBounds { outBounds[i].ExtendInfo = nil } - return ret } diff --git a/common/api/v2/response.go b/common/api/v2/response.go index 14049b647..73afccac5 100644 --- a/common/api/v2/response.go +++ b/common/api/v2/response.go @@ -99,8 +99,8 @@ func NewRoutingResponse(code uint32, routing *Routing) *Response { ret, err := ptypes.MarshalAny(routing) if err != nil { return &Response{ - Code: v1.ExecuteException, - Info: v1.Code2Info(code) + ": " + err.Error(), + Code: code, + Info: v1.Code2Info(code), } } diff --git a/common/model/v2/routing.go b/common/model/v2/routing.go index 06017d090..9e2baf43c 100644 --- a/common/model/v2/routing.go +++ b/common/model/v2/routing.go @@ -100,7 +100,6 @@ func (r *ExtendRoutingConfig) ToApi() (*apiv2.Routing, error) { Etime: commontime.Time2String(r.EnableTime), Priority: r.Priority, Description: r.Description, - ExtendInfo: r.ExtendInfo, }, nil } diff --git a/common/routing/routing.go b/common/routing/routing.go index ea0059192..0e54b30d0 100644 --- a/common/routing/routing.go +++ b/common/routing/routing.go @@ -306,9 +306,6 @@ func BuildInBoundsFromV2(service, namespace string, item *v2.ExtendRoutingConfig { Sources: v1sources, Destinations: v1destinations, - ExtendInfo: map[string]string{ - v2.V2RuleIDKey: item.ID, - }, }, } } diff --git a/polaris-server.yaml b/polaris-server.yaml index 6d6bf59cf..e87ffa7fb 100644 --- a/polaris-server.yaml +++ b/polaris-server.yaml @@ -311,9 +311,9 @@ store: # master: # dbType: mysql # dbName: polaris_server - # dbUser: root ##DB_USER## - # dbPwd: polaris ##DB_PWD## - # dbAddr: 127.0.0.1:3306 ##DB_ADDR## + # dbUser: ##DB_USER## + # dbPwd: ##DB_PWD## + # dbAddr: ##DB_ADDR## # maxOpenConns: 300 # maxIdleConns: 50 # connMaxLifetime: 300 # 单位秒 diff --git a/service/main_test.go b/service/main_test.go index 732dedfbe..2eb178912 100644 --- a/service/main_test.go +++ b/service/main_test.go @@ -744,6 +744,97 @@ func (d *DiscoverTestSuit) createCommonRoutingConfig(t *testing.T, service *api. return conf, resp.Responses[0].GetRouting() } +// 创建一个路由配置 +func (d *DiscoverTestSuit) createCommonRoutingConfigV1IntoOldStore(t *testing.T, service *api.Service, + inCount int, outCount int) (*api.Routing, *api.Routing) { + + inBounds := make([]*api.Route, 0, inCount) + for i := 0; i < inCount; i++ { + matchString := &api.MatchString{ + Type: api.MatchString_EXACT, + Value: utils.NewStringValue(fmt.Sprintf("in-meta-value-%d", i)), + } + source := &api.Source{ + Service: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)), + Namespace: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)), + Metadata: map[string]*api.MatchString{ + fmt.Sprintf("in-metadata-%d", i): matchString, + }, + } + destination := &api.Destination{ + Service: service.Name, + Namespace: service.Namespace, + Metadata: map[string]*api.MatchString{ + fmt.Sprintf("in-metadata-%d", i): matchString, + }, + Priority: utils.NewUInt32Value(120), + Weight: utils.NewUInt32Value(100), + Transfer: utils.NewStringValue("abcdefg"), + } + + entry := &api.Route{ + Sources: []*api.Source{source}, + Destinations: []*api.Destination{destination}, + } + inBounds = append(inBounds, entry) + } + + conf := &api.Routing{ + Service: utils.NewStringValue(service.GetName().GetValue()), + Namespace: utils.NewStringValue(service.GetNamespace().GetValue()), + Inbounds: inBounds, + ServiceToken: utils.NewStringValue(service.GetToken().GetValue()), + } + + resp := d.server.(*serverAuthAbility).targetServer.CreateRoutingConfig(d.defaultCtx, conf) + if !respSuccess(resp) { + t.Fatalf("error: %+v", resp) + } + + return conf, resp.GetRouting() +} + +func mockRoutingV1(serviceName, serviceNamespace string, inCount int) *api.Routing { + inBounds := make([]*api.Route, 0, inCount) + for i := 0; i < inCount; i++ { + matchString := &api.MatchString{ + Type: api.MatchString_EXACT, + Value: utils.NewStringValue(fmt.Sprintf("in-meta-value-%d", i)), + } + source := &api.Source{ + Service: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)), + Namespace: utils.NewStringValue(fmt.Sprintf("in-source-service-%d", i)), + Metadata: map[string]*api.MatchString{ + fmt.Sprintf("in-metadata-%d", i): matchString, + }, + } + destination := &api.Destination{ + Service: utils.NewStringValue(serviceName), + Namespace: utils.NewStringValue(serviceNamespace), + Metadata: map[string]*api.MatchString{ + fmt.Sprintf("in-metadata-%d", i): matchString, + }, + Priority: utils.NewUInt32Value(120), + Weight: utils.NewUInt32Value(100), + Transfer: utils.NewStringValue("abcdefg"), + } + + entry := &api.Route{ + Sources: []*api.Source{source}, + Destinations: []*api.Destination{destination}, + } + inBounds = append(inBounds, entry) + } + + conf := &api.Routing{ + Service: utils.NewStringValue(serviceName), + Namespace: utils.NewStringValue(serviceNamespace), + Inbounds: inBounds, + } + + return conf +} + func mockRoutingV2(t *testing.T, cnt int32) []*apiv2.Routing { rules := make([]*apiv2.Routing, 0, cnt) for i := int32(0); i < cnt; i++ { @@ -790,9 +881,6 @@ func mockRoutingV2(t *testing.T, cnt int32) []*apiv2.Routing { Etime: "", Priority: 0, Description: "", - ExtendInfo: map[string]string{ - "": "", - }, } rules = append(rules, item) @@ -815,6 +903,10 @@ func (d *DiscoverTestSuit) createCommonRoutingConfigV2WithReq(t *testing.T, rule t.Fatalf("error: %+v", resp) } + if len(rules) != len(resp.GetResponses()) { + t.Fatal("error: create v2 routings not equal resp") + } + ret := []*apiv2.Routing{} for i := range resp.GetResponses() { item := resp.GetResponses()[i] diff --git a/service/routing_config_v2.go b/service/routing_config_v2.go index ffe4b8b00..9f5754519 100644 --- a/service/routing_config_v2.go +++ b/service/routing_config_v2.go @@ -114,7 +114,7 @@ func (s *Server) deleteRoutingConfigV2(ctx context.Context, req *apiv2.Routing) // 判断当前的路由规则是否只是从 v1 版本中的内存中转换过来的 if _, ok := s.Cache().RoutingConfig().IsConvertFromV1(req.Id); ok { - resp := s.transferV1toV2OnEnableOrDelete(ctx, req) + resp := s.transferV1toV2OnModify(ctx, req) if resp.GetCode() != apiv1.ExecuteSuccess { return resp } @@ -147,13 +147,13 @@ func (s *Server) UpdateRoutingConfigsV2(ctx context.Context, req []*apiv2.Routin // updateRoutingConfigV2 更新单个路由配置 func (s *Server) updateRoutingConfigV2(ctx context.Context, req *apiv2.Routing) *apiv2.Response { - extendInfo := req.GetExtendInfo() // 如果当前待修改的 v2 路由规则,其实是从 v1 规则在 cache 中转换而来的,则需要先做以下几个步骤 // step 1: 将 v1 规则真实的转为 v2 规则 // step 2: 将本次要修改的 v2 规则,在 v1 规则中的 inBound 或者 outBound 找到对应的 route,设置其规则 ID // step 3: 进行存储持久化 - if _, ok := extendInfo[v2.V1RuleIDKey]; ok { - resp := s.updateRoutingConfigV2FromV1(ctx, req) + // 判断当前的路由规则是否只是从 v1 版本中的内存中转换过来的 + if _, ok := s.Cache().RoutingConfig().IsConvertFromV1(req.Id); ok { + resp := s.transferV1toV2OnModify(ctx, req) if resp.GetCode() != apiv1.ExecuteSuccess { return resp } @@ -193,78 +193,6 @@ func (s *Server) updateRoutingConfigV2(ctx context.Context, req *apiv2.Routing) return apiv2.NewResponse(api.ExecuteSuccess) } -// updateRoutingConfigV2FromV1 这里需要兼容 v1 版本的更新路由规则动作,将 v1 的数据转为 v2 进行存储 -func (s *Server) updateRoutingConfigV2FromV1(ctx context.Context, req *apiv2.Routing) *apiv2.Response { - - extendInfo := req.GetExtendInfo() - val, _ := extendInfo[v2.V1RuleIDKey] - - // 如果当前要修改的 v2 路由规则是从 v1 版本转换过来的,需要先做一下几个步骤 - // stpe 1: 现将 v1 规则转换为 v2 规则存储 - // stpe 2: 删除原本的 v1 规则 - // step 3: 更新当前的 v2 路由规则 - v1rule, err := s.storage.GetRoutingConfigWithID(val) - if err != nil { - log.Error("[Service][Routing] get routing config v1 store layer", - utils.ZapRequestIDByCtx(ctx), zap.Error(err)) - return apiv2.NewResponse(apiv1.StoreLayerException) - } - - if v1rule == nil { - return apiv2.NewResponse(apiv1.ExecuteSuccess) - } - - svc, err := s.storage.GetServiceByID(v1rule.ID) - if err != nil { - log.Error("[Service][Routing] get routing config v1 link service store layer", - utils.ZapRequestIDByCtx(ctx), zap.Error(err)) - return apiv2.NewResponse(apiv1.ExecuteException) - } - v1req, err := routingConfig2API(v1rule, svc.Name, svc.Namespace) - if err != nil { - log.Error("[Service][Routing] delete routing config v2 store layer", - utils.ZapRequestIDByCtx(ctx), zap.Error(err)) - return apiv2.NewResponse(apiv1.ExecuteException) - } - - // 由于 v1 规则的 inBound 以及 outBound 是 []*api.Route,每一个 Route 都是一条 v2 的路由规则 - // 因此这里需要找到对应的 route,更新其 extendInfo 插入相关额外控制信息 - - indexStr, hasIndex := extendInfo[v2.V1RuleRouteIndexKey] - if hasIndex { - index, err := strconv.ParseInt(indexStr, 10, 64) - if err == nil { - routeType := extendInfo[v2.V1RuleRouteTypeKey] - if routeType == v2.V1RuleInRoute { - for i := range v1req.Inbounds { - if i == int(index) { - v1req.Inbounds[i].ExtendInfo = map[string]string{ - v2.V2RuleIDKey: req.Id, - } - break - } - } - } - if routeType == v2.V1RuleOutRoute { - for i := range v1req.Outbounds { - if i == int(index) { - v1req.Outbounds[i].ExtendInfo = map[string]string{ - v2.V2RuleIDKey: req.Id, - } - break - } - } - } - } else { - log.Error("[Service][Routing] parse route index when update v2 from v1", - utils.ZapRequestIDByCtx(ctx), zap.Error(err)) - } - } - - resp := s.createRoutingConfigV1toV2(ctx, v1req) - return apiv2.NewResponse(resp.GetCode().GetValue()) -} - // GetRoutingConfigsV2 提供给OSS的查询路由配置的接口 func (s *Server) GetRoutingConfigsV2(ctx context.Context, query map[string]string) *apiv2.BatchQueryResponse { args, presp := parseRoutingArgs(query, ctx) @@ -310,7 +238,7 @@ func (s *Server) enableRoutings(ctx context.Context, req *apiv2.Routing) *apiv2. // 判断当前的路由规则是否只是从 v1 版本中的内存中转换过来的 if _, ok := s.Cache().RoutingConfig().IsConvertFromV1(req.Id); ok { - resp := s.transferV1toV2OnEnableOrDelete(ctx, req) + resp := s.transferV1toV2OnModify(ctx, req) if resp.GetCode() != apiv1.ExecuteSuccess { return resp } @@ -340,8 +268,8 @@ func (s *Server) enableRoutings(ctx context.Context, req *apiv2.Routing) *apiv2. return apiv2.NewResponse(api.ExecuteSuccess) } -// transferV1toV2OnEnableRouting 在针对 v2 规则进行启用或者禁止时,需要将 v1 规则转为 v2 规则并执行持久化存储 -func (s *Server) transferV1toV2OnEnableOrDelete(ctx context.Context, req *apiv2.Routing) *apiv2.Response { +// transferV1toV2OnModify 在针对 v2 规则进行启用或者禁止时,需要将 v1 规则转为 v2 规则并执行持久化存储 +func (s *Server) transferV1toV2OnModify(ctx context.Context, req *apiv2.Routing) *apiv2.Response { svcId, _ := s.Cache().RoutingConfig().IsConvertFromV1(req.Id) v1conf, err := s.storage.GetRoutingConfigWithID(svcId) if err != nil { diff --git a/service/routing_config_v2_test.go b/service/routing_config_v2_test.go index 517f835e1..fda10c2b3 100644 --- a/service/routing_config_v2_test.go +++ b/service/routing_config_v2_test.go @@ -49,7 +49,7 @@ func TestCreateRoutingConfigV2(t *testing.T) { t.Run("正常创建路由配置配置请求", func(t *testing.T) { req := discoverSuit.createCommonRoutingConfigV2(t, 3) - defer discoverSuit.cleanCommonRoutingConfigV2(req) + defer discoverSuit.truncateCommonRoutingConfigV2() // 对写进去的数据进行查询 time.Sleep(discoverSuit.updateCacheInterval * 5) @@ -61,7 +61,185 @@ func TestCreateRoutingConfigV2(t *testing.T) { t.Fatalf("error: %+v", out) } + ret, _ := unmarshalRoutingV2toAnySlice(out.GetData()) + t.Logf("query routing v2 : %#v", ret) + // assert.Equal(t, int(3), int(out.Amount), "query routing size") + + // 按照名字查询 + + out = discoverSuit.server.GetRoutingConfigsV2(discoverSuit.defaultCtx, map[string]string{ + "limit": "100", + "offset": "0", + "name": req[0].Name, + }) + if !respSuccessV2(out) { + t.Fatalf("error: %+v", out) + } + + assert.Equal(t, int(1), int(out.Amount), "query routing size") + }) +} + +// TestCompatibleRoutingConfigV2AndV1 测试V2版本的路由规则和V1版本的路由规则 +func TestCompatibleRoutingConfigV2AndV1(t *testing.T) { + + discoverSuit := &DiscoverTestSuit{} + if err := discoverSuit.initialize(); err != nil { + t.Fatal(err) + } + defer discoverSuit.Destroy() + + svc := &api.Service{ + Name: utils.NewStringValue("compatible-routing"), + Namespace: utils.NewStringValue("compatible"), + } + + createSvcResp := discoverSuit.server.CreateServices(discoverSuit.defaultCtx, []*api.Service{svc}) + if !respSuccess(createSvcResp) { + t.Fatalf("error: %s", createSvcResp.GetInfo().GetValue()) + } + + _ = createSvcResp.Responses[0].GetService() + defer discoverSuit.cleanServices([]*api.Service{svc}) + + t.Run("V1的存量规则-走V2接口可以查询到,ExtendInfo符合要求", func(t *testing.T) { + _, _ = discoverSuit.createCommonRoutingConfigV1IntoOldStore(t, svc, 3, 0) + defer func() { + discoverSuit.cleanCommonRoutingConfig(svc.GetName().GetValue(), svc.GetNamespace().GetValue()) + discoverSuit.truncateCommonRoutingConfigV2() + }() + + time.Sleep(discoverSuit.updateCacheInterval * 5) + // 从缓存中查询应该查到 3+3 条 v2 的路由规则 + out := discoverSuit.server.GetRoutingConfigsV2(discoverSuit.defaultCtx, map[string]string{ + "limit": "100", + "offset": "0", + }) + if !respSuccessV2(out) { + t.Fatalf("error: %+v", out) + } + assert.Equal(t, int(3), int(out.Amount), "query routing size") + + rulesV2, err := unmarshalRoutingV2toAnySlice(out.GetData()) + assert.NoError(t, err) + + for i := range rulesV2 { + item := rulesV2[i] + assert.True(t, item.Enable, "v1 to v2 need default open enable") + } + }) + + t.Run("V1的存量规则-走v2规则的启用可正常迁移v1规则", func(t *testing.T) { + _, _ = discoverSuit.createCommonRoutingConfigV1IntoOldStore(t, svc, 3, 0) + defer func() { + discoverSuit.cleanCommonRoutingConfig(svc.GetName().GetValue(), svc.GetNamespace().GetValue()) + discoverSuit.truncateCommonRoutingConfigV2() + }() + + time.Sleep(discoverSuit.updateCacheInterval * 5) + // 从缓存中查询应该查到 3+3 条 v2 的路由规则 + out := discoverSuit.server.GetRoutingConfigsV2(discoverSuit.defaultCtx, map[string]string{ + "limit": "100", + "offset": "0", + }) + if !respSuccessV2(out) { + t.Fatalf("error: %+v", out) + } + assert.Equal(t, int(3), int(out.Amount), "query routing size") + + rulesV2, err := unmarshalRoutingV2toAnySlice(out.GetData()) + assert.NoError(t, err) + + // 选择其中一条规则进行enable操作 + v2resp := discoverSuit.server.EnableRoutings(discoverSuit.defaultCtx, []*apiv2.Routing{rulesV2[0]}) + if !respSuccessV2(v2resp) { + t.Fatalf("error: %+v", v2resp) + } + // 直接查询存储无法查询到 v1 的路由规则 + total, routingsV1, err := discoverSuit.storage.GetRoutingConfigs(map[string]string{}, 0, 100) + assert.NoError(t, err, err) + assert.Equal(t, uint32(0), total, "v1 routing must delete and transfer to v1") + assert.Equal(t, 0, len(routingsV1), "v1 routing ret len need zero") + }) + + t.Run("V1的存量规则-走v2规则的删除可正常迁移v1规则", func(t *testing.T) { + _, _ = discoverSuit.createCommonRoutingConfigV1IntoOldStore(t, svc, 3, 0) + defer func() { + discoverSuit.cleanCommonRoutingConfig(svc.GetName().GetValue(), svc.GetNamespace().GetValue()) + discoverSuit.truncateCommonRoutingConfigV2() + }() + + time.Sleep(discoverSuit.updateCacheInterval * 5) + // 从缓存中查询应该查到 3+3 条 v2 的路由规则 + out := discoverSuit.server.GetRoutingConfigsV2(discoverSuit.defaultCtx, map[string]string{ + "limit": "100", + "offset": "0", + }) + if !respSuccessV2(out) { + t.Fatalf("error: %+v", out) + } + assert.Equal(t, int(3), int(out.Amount), "query routing size") + + rulesV2, err := unmarshalRoutingV2toAnySlice(out.GetData()) + assert.NoError(t, err) + + // 选择其中一条规则进行删除操作 + v2resp := discoverSuit.server.DeleteRoutingConfigsV2(discoverSuit.defaultCtx, []*apiv2.Routing{rulesV2[0]}) + if !respSuccessV2(v2resp) { + t.Fatalf("error: %+v", v2resp) + } + // 直接查询存储无法查询到 v1 的路由规则 + total, routingsV1, err := discoverSuit.storage.GetRoutingConfigs(map[string]string{}, 0, 100) + assert.NoError(t, err, err) + assert.Equal(t, uint32(0), total, "v1 routing must delete and transfer to v1") + assert.Equal(t, 0, len(routingsV1), "v1 routing ret len need zero") + + // 查询对应的 v2 规则也查询不到 + ruleV2, err := discoverSuit.storage.GetRoutingConfigV2WithID(rulesV2[0].Id) + assert.NoError(t, err, err) + assert.Nil(t, ruleV2, "v2 routing must delete") + }) + + t.Run("V1的存量规则-走v2规则的编辑可正常迁移v1规则", func(t *testing.T) { + _, _ = discoverSuit.createCommonRoutingConfigV1IntoOldStore(t, svc, 3, 0) + defer func() { + discoverSuit.cleanCommonRoutingConfig(svc.GetName().GetValue(), svc.GetNamespace().GetValue()) + discoverSuit.truncateCommonRoutingConfigV2() + }() + + time.Sleep(discoverSuit.updateCacheInterval * 5) + // 从缓存中查询应该查到 3+3 条 v2 的路由规则 + out := discoverSuit.server.GetRoutingConfigsV2(discoverSuit.defaultCtx, map[string]string{ + "limit": "100", + "offset": "0", + }) + if !respSuccessV2(out) { + t.Fatalf("error: %+v", out) + } + assert.Equal(t, int(3), int(out.Amount), "query routing size") + + rulesV2, err := unmarshalRoutingV2toAnySlice(out.GetData()) + assert.NoError(t, err) + + // 需要将 v2 规则的 extendInfo 规则清理掉 + // 选择其中一条规则进行enable操作 + rulesV2[0].Description = "update v2 rule and transfer v1 to v2" + v2resp := discoverSuit.server.UpdateRoutingConfigsV2(discoverSuit.defaultCtx, []*apiv2.Routing{rulesV2[0]}) + if !respSuccessV2(v2resp) { + t.Fatalf("error: %+v", v2resp) + } + // 直接查询存储无法查询到 v1 的路由规则 + total, routingsV1, err := discoverSuit.storage.GetRoutingConfigs(map[string]string{}, 0, 100) + assert.NoError(t, err, err) + assert.Equal(t, uint32(0), total, "v1 routing must delete and transfer to v1") + assert.Equal(t, 0, len(routingsV1), "v1 routing ret len need zero") + + // 查询对应的 v2 规则也查询不到 + ruleV2, err := discoverSuit.storage.GetRoutingConfigV2WithID(rulesV2[0].Id) + assert.NoError(t, err, err) + assert.NotNil(t, ruleV2, "v2 routing must exist") + assert.Equal(t, rulesV2[0].Description, ruleV2.Description) }) } @@ -166,9 +344,6 @@ func TestCreateCheckRoutingFieldLenV2(t *testing.T) { Etime: "", Priority: 0, Description: "", - ExtendInfo: map[string]string{ - "": "", - }, } t.Run("创建路由规则,规则名称超长", func(t *testing.T) { @@ -234,9 +409,6 @@ func TestUpdateCheckRoutingFieldLenV2(t *testing.T) { Etime: "", Priority: 0, Description: "", - ExtendInfo: map[string]string{ - "": "", - }, } t.Run("更新路由规则,规则ID为空", func(t *testing.T) { diff --git a/store/boltdb/routing_config_v2.go b/store/boltdb/routing_config_v2.go index 21355fb8b..d474e0d07 100644 --- a/store/boltdb/routing_config_v2.go +++ b/store/boltdb/routing_config_v2.go @@ -119,7 +119,7 @@ func (r *routingStoreV2) UpdateRoutingConfigV2(conf *v2.RoutingConfig) error { log.Errorf("[Store][boltdb] update routing config v2 missing id or revision") return store.NewStatusError(store.EmptyParamsErr, "missing id or revision") } - if conf.Name == "" || conf.Config == "" { + if conf.Policy == "" || conf.Config == "" { log.Errorf("[Store][boltdb] create routing config v2 missing params") return store.NewStatusError(store.EmptyParamsErr, "missing some params") } diff --git a/store/sqldb/scripts/delta/v1_8_0-v1_11_0.sql b/store/sqldb/scripts/delta/v1_8_0-v1_11_0.sql index 60a4a244c..d0192c8db 100644 --- a/store/sqldb/scripts/delta/v1_8_0-v1_11_0.sql +++ b/store/sqldb/scripts/delta/v1_8_0-v1_11_0.sql @@ -20,7 +20,7 @@ USE `polaris_server`; -ALTER TABLE `ratelimit_config` CHANGE `cluster_id` `name` varchar(64) NOT NULL; +ALTER TABLE `ratelimit_config` ADD COLUMN `name` varchar(64) NOT NULL; ALTER TABLE `ratelimit_config` ADD COLUMN `disable` tinyint(4) NOT NULL DEFAULT '0'; ALTER TABLE `ratelimit_config` ADD COLUMN `etime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP; ALTER TABLE `ratelimit_config` ADD COLUMN `method` varchar(512) NOT NULL;