This is an automated email from the ASF dual-hosted git repository. liujun pushed a commit to branch refactor-with-go-components-experimental in repository https://gitbox.apache.org/repos/asf/dubbo-admin.git
commit 6c1c76c6217c2b285852017019005e77da58d94c Author: chickenlj <[email protected]> AuthorDate: Fri Aug 4 10:52:35 2023 +0800 Add dubbo3 service discovery support --- conf/admin.yml | 6 +- pkg/admin/cache/registry/extension.go | 4 +- pkg/admin/cache/registry/kube/registry.go | 7 +- pkg/admin/cache/registry/universal/registry.go | 8 +- .../service_instances_changed_listener_impl.go | 26 ++- pkg/admin/constant/const.go | 5 + pkg/admin/handlers/service.go | 100 ++++++++- pkg/admin/model/provider.go | 30 +-- pkg/admin/model/registry_source.go | 26 --- pkg/admin/model/service_dto.go | 23 ++- pkg/admin/model/traffic.go | 48 ++++- pkg/admin/model/util/sync_utils.go | 4 +- pkg/admin/providers/mock/mock_provider.go | 5 +- pkg/admin/router/router.go | 4 + pkg/admin/services/generic_service_Impl.go | 64 ++++++ pkg/admin/services/provider_service_impl.go | 5 +- pkg/admin/services/registry_service_sync.go | 74 ++++++- pkg/admin/services/service_testing_v3.go | 223 +++++++++++++++++++++ pkg/admin/services/traffic/accesslog.go | 7 +- pkg/admin/services/traffic/argument.go | 7 +- pkg/admin/services/traffic/mock.go | 7 +- pkg/admin/services/traffic/region.go | 7 +- pkg/admin/services/traffic/retry.go | 14 +- pkg/admin/services/traffic/timeout.go | 21 +- pkg/admin/services/traffic/weight.go | 7 +- pkg/config/admin/address_config.go | 9 +- pkg/config/config.go | 7 +- 27 files changed, 636 insertions(+), 112 deletions(-) diff --git a/conf/admin.yml b/conf/admin.yml index f1d02e30..42d8bf8d 100644 --- a/conf/admin.yml +++ b/conf/admin.yml @@ -14,11 +14,11 @@ # limitations under the License. admin: admin-port: 38080 - config-center: zookeeper://127.0.0.1:2181 + config-center: nacos://127.0.0.1:8848 metadata-report: - address: zookeeper://127.0.0.1:2181 + address: nacos://127.0.0.1:8848 registry: - address: zookeeper://127.0.0.1:2181 + address: nacos://127.0.0.1:8848 prometheus: ip: 127.0.0.1 port: 9090 diff --git a/pkg/admin/cache/registry/extension.go b/pkg/admin/cache/registry/extension.go index 43c34554..79b7cee3 100644 --- a/pkg/admin/cache/registry/extension.go +++ b/pkg/admin/cache/registry/extension.go @@ -2,6 +2,7 @@ package registry import ( "dubbo.apache.org/dubbo-go/v3/common" + dubboRegistry "dubbo.apache.org/dubbo-go/v3/registry" ) var registries = make(map[string]func(u *common.URL) (AdminRegistry, error)) @@ -25,8 +26,9 @@ func Registry(name string, config *common.URL) (AdminRegistry, error) { type AdminRegistry interface { Subscribe(listener AdminNotifyListener) error Destroy() error + Delegate() dubboRegistry.Registry } type AdminNotifyListener interface { - Notify(url *common.URL) + Notify(event *dubboRegistry.ServiceEvent) } diff --git a/pkg/admin/cache/registry/kube/registry.go b/pkg/admin/cache/registry/kube/registry.go index 72468f6d..3cc489a5 100644 --- a/pkg/admin/cache/registry/kube/registry.go +++ b/pkg/admin/cache/registry/kube/registry.go @@ -2,12 +2,13 @@ package kube import ( "dubbo.apache.org/dubbo-go/v3/common" + dubboRegistry "dubbo.apache.org/dubbo-go/v3/registry" "github.com/apache/dubbo-admin/pkg/admin/cache/registry" "github.com/apache/dubbo-admin/pkg/core/kubeclient/client" ) func init() { - registry.AddRegistry("universal", func(u *common.URL) (registry.AdminRegistry, error) { + registry.AddRegistry("kube", func(u *common.URL) (registry.AdminRegistry, error) { return NewRegistry() }) } @@ -20,6 +21,10 @@ func NewRegistry() (*Registry, error) { return nil, nil } +func (kr *Registry) Delegate() dubboRegistry.Registry { + return nil +} + func (kr *Registry) Subscribe(listener registry.AdminNotifyListener) error { return nil } diff --git a/pkg/admin/cache/registry/universal/registry.go b/pkg/admin/cache/registry/universal/registry.go index 9f731c9f..67139c75 100644 --- a/pkg/admin/cache/registry/universal/registry.go +++ b/pkg/admin/cache/registry/universal/registry.go @@ -68,6 +68,10 @@ func NewRegistry(delegate dubboRegistry.Registry, sdDelegate dubboRegistry.Servi } } +func (kr *Registry) Delegate() dubboRegistry.Registry { + return kr.delegate +} + func (kr *Registry) Subscribe(listener registry.AdminNotifyListener) error { delRegistryListener := DubboRegistryNotifyListener{listener: listener} go func() { @@ -115,9 +119,7 @@ type DubboRegistryNotifyListener struct { } func (l DubboRegistryNotifyListener) Notify(event *dubboRegistry.ServiceEvent) { - // TODO implement me - serviceURL := event.Service - l.listener.Notify(serviceURL) + l.listener.Notify(event) } func (l DubboRegistryNotifyListener) NotifyAll(events []*dubboRegistry.ServiceEvent, f func()) { diff --git a/pkg/admin/cache/registry/universal/service_instances_changed_listener_impl.go b/pkg/admin/cache/registry/universal/service_instances_changed_listener_impl.go index b50bc716..8b1059aa 100644 --- a/pkg/admin/cache/registry/universal/service_instances_changed_listener_impl.go +++ b/pkg/admin/cache/registry/universal/service_instances_changed_listener_impl.go @@ -18,7 +18,9 @@ package universal import ( + "dubbo.apache.org/dubbo-go/v3/metadata/service/local" "reflect" + "sync" ) import ( @@ -29,10 +31,12 @@ import ( import ( "dubbo.apache.org/dubbo-go/v3/common" - "dubbo.apache.org/dubbo-go/v3/common/constant" + dubboconstant "dubbo.apache.org/dubbo-go/v3/common/constant" "dubbo.apache.org/dubbo-go/v3/common/extension" "dubbo.apache.org/dubbo-go/v3/registry" "dubbo.apache.org/dubbo-go/v3/remoting" + + "github.com/apache/dubbo-admin/pkg/admin/constant" ) // DubboSDNotifyListener The Service Discovery Changed Event Listener @@ -42,6 +46,8 @@ type DubboSDNotifyListener struct { serviceUrls map[string][]*common.URL revisionToMetadata map[string]*common.MetadataInfo allInstances map[string][]registry.ServiceInstance + + mutex sync.Mutex } func NewDubboSDNotifyListener(services *gxset.HashSet) registry.ServiceInstancesChangedListener { @@ -61,6 +67,10 @@ func (lstn *DubboSDNotifyListener) OnEvent(e observer.Event) error { return nil } var err error + + lstn.mutex.Lock() + defer lstn.mutex.Unlock() + lstn.allInstances[ce.ServiceName] = ce.Instances revisionToInstances := make(map[string][]registry.ServiceInstance) newRevisionToMetadata := make(map[string]*common.MetadataInfo) @@ -76,7 +86,7 @@ func (lstn *DubboSDNotifyListener) OnEvent(e observer.Event) error { logger.Warnf("Instance metadata is nil: %s", instance.GetHost()) continue } - revision := instance.GetMetadata()[constant.ExportedServicesRevisionPropertyName] + revision := instance.GetMetadata()[dubboconstant.ExportedServicesRevisionPropertyName] if "0" == revision { logger.Infof("Find instance without valid service metadata: %s", instance.GetHost()) continue @@ -134,7 +144,7 @@ func (lstn *DubboSDNotifyListener) OnEvent(e observer.Event) error { urls := lstn.serviceUrls[key] events := make([]*registry.ServiceEvent, 0, len(urls)) for _, url := range urls { - url.AddParam("TYPE", "instance") + url.SetParam(constant.RegistryType, constant.RegistryInstance) events = append(events, ®istry.ServiceEvent{ Action: remoting.EventTypeAdd, Service: url, @@ -151,6 +161,7 @@ func (lstn *DubboSDNotifyListener) AddListenerAndNotify(serviceKey string, notif lstn.listeners[serviceKey] = notify urls := lstn.serviceUrls[serviceKey] for _, url := range urls { + url.SetParam(constant.RegistryType, constant.RegistryInstance) notify.Notify(®istry.ServiceEvent{ Action: remoting.EventTypeAdd, Service: url, @@ -191,11 +202,11 @@ func GetMetadataInfo(instance registry.ServiceInstance, revision string) (*commo var metadataStorageType string var metadataInfo *common.MetadataInfo if instance.GetMetadata() == nil { - metadataStorageType = constant.DefaultMetadataStorageType + metadataStorageType = dubboconstant.DefaultMetadataStorageType } else { - metadataStorageType = instance.GetMetadata()[constant.MetadataStorageTypePropertyName] + metadataStorageType = instance.GetMetadata()[dubboconstant.MetadataStorageTypePropertyName] } - if metadataStorageType == constant.RemoteMetadataStorageType { + if metadataStorageType == dubboconstant.RemoteMetadataStorageType { remoteMetadataServiceImpl, err := extension.GetRemoteMetadataService() if err != nil { return nil, err @@ -206,8 +217,9 @@ func GetMetadataInfo(instance registry.ServiceInstance, revision string) (*commo } } else { var err error - proxyFactory := extension.GetMetadataServiceProxyFactory(constant.DefaultKey) + proxyFactory := extension.GetMetadataServiceProxyFactory(dubboconstant.DefaultKey) metadataService := proxyFactory.GetProxy(instance) + defer metadataService.(*local.MetadataServiceProxy).Invoker.Destroy() metadataInfo, err = metadataService.GetMetadataInfo(revision) if err != nil { return nil, err diff --git a/pkg/admin/constant/const.go b/pkg/admin/constant/const.go index 833a5976..405635f4 100644 --- a/pkg/admin/constant/const.go +++ b/pkg/admin/constant/const.go @@ -71,6 +71,11 @@ const ( ConditionRuleSuffix = ".condition-router" TagRuleSuffix = ".tag-router" ConfigFileEnvKey = "conf" // config file path + RegistryAll = "ALL" + RegistryInterface = "INTERFACE" + RegistryInstance = "INSTANCE" + RegistryType = "TYPE" + NamespaceKey = "namespace" ) var Configs = set.NewSet(WeightKey, BalancingKey) diff --git a/pkg/admin/handlers/service.go b/pkg/admin/handlers/service.go index 155ea64b..f13a76e7 100644 --- a/pkg/admin/handlers/service.go +++ b/pkg/admin/handlers/service.go @@ -18,12 +18,14 @@ package handlers import ( + "dubbo.apache.org/dubbo-go/v3/config/generic" "encoding/json" - "net/http" - "strconv" - "github.com/apache/dubbo-admin/pkg/core/cmd/version" "github.com/apache/dubbo-admin/pkg/core/logger" + hessian "github.com/apache/dubbo-go-hessian2" + "net/http" + "strconv" + "time" "dubbo.apache.org/dubbo-go/v3/metadata/definition" @@ -42,9 +44,11 @@ import ( ) var ( - providerService services.ProviderService = &services.ProviderServiceImpl{} - consumerService services.ConsumerService = &services.ConsumerServiceImpl{} - monitorService services.MonitorService = &services.PrometheusServiceImpl{} + providerService services.ProviderService = &services.ProviderServiceImpl{} + consumerService services.ConsumerService = &services.ConsumerServiceImpl{} + monitorService services.MonitorService = &services.PrometheusServiceImpl{} + genericServiceImpl *services.GenericServiceImpl = &services.GenericServiceImpl{} + serviceTesting *services.ServiceTestingV3 = &services.ServiceTestingV3{} ) // AllServices get all services @@ -317,3 +321,87 @@ func PromDiscovery(c *gin.Context) { } c.JSON(http.StatusOK, targets) } + +// Test works for dubbo2 tcp protocol +func Test(c *gin.Context) { + var serviceTestDTO model.ServiceTest + + err := c.BindJSON(&serviceTestDTO) + if err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + refConf := genericServiceImpl.NewRefConf("dubbo-admin", serviceTestDTO.Service, "dubbo") + time.Sleep(2 * time.Second) + resp, err := refConf. + GetRPCService().(*generic.GenericService). + Invoke( + c, + serviceTestDTO.Method, + serviceTestDTO.ParameterTypes, + []hessian.Object{"A003"}, //fixme + ) + refConf.GetInvoker().Destroy() + if err != nil { + logger.Error("Error do generic invoke for service test", err) + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, resp) +} + +// HttpTest works for triple protocol +func HttpTest(c *gin.Context) { + //pattern := c.Query("service") + //filter := c.Query("method") + //address := c.Query("address") + + // send standard http request to backend http://address/service/method content-type:json + + c.JSON(http.StatusOK, gin.H{ + "code": 1, + "data": "implement me", + }) +} + +func MethodDetail(c *gin.Context) { + service := c.Query("service") + group := util.GetGroup(service) + version := util.GetVersion(service) + interfaze := util.GetInterface(service) + application := c.Query("application") + method := c.Query("method") + + identifier := &identifier.MetadataIdentifier{ + Application: application, + BaseMetadataIdentifier: identifier.BaseMetadataIdentifier{ + ServiceInterface: interfaze, + Version: version, + Group: group, + Side: constant.ProviderSide, + }, + } + metadata, _ := config.MetadataReportCenter.GetServiceDefinition(identifier) + var methodMetadata model.MethodMetadata + if metadata != "" { + serviceDefinition := &definition.FullServiceDefinition{} + err := json.Unmarshal([]byte(metadata), &serviceDefinition) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": err.Error(), + }) + return + } + methods := serviceDefinition.Methods + if methods != nil { + for _, m := range methods { + if serviceTesting.SameMethod(m, method) { + methodMetadata = serviceTesting.GenerateMethodMeta(*serviceDefinition, m) + break + } + } + } + } + + c.JSON(http.StatusOK, methodMetadata) +} diff --git a/pkg/admin/model/provider.go b/pkg/admin/model/provider.go index 2acc17e4..e84c2d2c 100644 --- a/pkg/admin/model/provider.go +++ b/pkg/admin/model/provider.go @@ -19,19 +19,19 @@ import "time" type Provider struct { Entity - Service string `json:"service"` - URL string `json:"url"` - Parameters string `json:"parameters"` - Address string `json:"address"` - Registry string `json:"registry"` - Dynamic bool `json:"dynamic"` - Enabled bool `json:"enabled"` - Timeout int64 `json:"timeout"` - Serialization string `json:"serialization"` - Weight int64 `json:"weight"` - Application string `json:"application"` - Username string `json:"username"` - Expired time.Duration `json:"expired"` - Alived int64 `json:"alived"` - RegistrySource RegistrySource `json:"registrySource"` + Service string `json:"service"` + URL string `json:"url"` + Parameters string `json:"parameters"` + Address string `json:"address"` + Registry string `json:"registry"` + Dynamic bool `json:"dynamic"` + Enabled bool `json:"enabled"` + Timeout int64 `json:"timeout"` + Serialization string `json:"serialization"` + Weight int64 `json:"weight"` + Application string `json:"application"` + Username string `json:"username"` + Expired time.Duration `json:"expired"` + Alived int64 `json:"alived"` + RegistrySource string `json:"registrySource"` } diff --git a/pkg/admin/model/registry_source.go b/pkg/admin/model/registry_source.go deleted file mode 100644 index dff55390..00000000 --- a/pkg/admin/model/registry_source.go +++ /dev/null @@ -1,26 +0,0 @@ -// 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 model - -type RegistrySource string - -const ( - All RegistrySource = "ALL" - - Interface = "INTERFACE" - - Instance = "INSTANCE" -) diff --git a/pkg/admin/model/service_dto.go b/pkg/admin/model/service_dto.go index afa817a2..7d1b60ac 100644 --- a/pkg/admin/model/service_dto.go +++ b/pkg/admin/model/service_dto.go @@ -17,11 +17,11 @@ package model // ServiceDTO is the transforming format of service type ServiceDTO struct { - Service string `json:"service"` - AppName string `json:"appName"` - Group string `json:"group"` - Version string `json:"version"` - RegistrySource RegistrySource `json:"registrySource"` + Service string `json:"service"` + AppName string `json:"appName"` + Group string `json:"group"` + Version string `json:"version"` + RegistrySource string `json:"registrySource"` } type ListServiceByPage struct { @@ -34,3 +34,16 @@ type ListServiceByPage struct { PageNumber string `json:"pageNumber"` Offset int `json:"offset"` } + +type ServiceTest struct { + Service string `json:"service"` + Method string `json:"method"` + ParameterTypes []string `json:"ParameterTypes"` + Params []interface{} `json:"params"` +} + +type MethodMetadata struct { + Signature string `json:"signature"` + ParameterTypes []interface{} `json:"parameterTypes"` + ReturnType string `json:"returnType"` +} diff --git a/pkg/admin/model/traffic.go b/pkg/admin/model/traffic.go index b3805a22..3f1292a6 100644 --- a/pkg/admin/model/traffic.go +++ b/pkg/admin/model/traffic.go @@ -49,6 +49,13 @@ func (t Timeout) ToRule() Override { } } +func (t Timeout) GetKey() string { + interfaze := util.GetInterface(t.Service) + group := util.GetGroup(t.Service) + version := util.GetVersion(t.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Retry struct { Service string `json:"service" binding:"required"` Group string `json:"group"` @@ -69,6 +76,13 @@ func (t Retry) ToRule() Override { } } +func (r Retry) GetKey() string { + interfaze := util.GetInterface(r.Service) + group := util.GetGroup(r.Service) + version := util.GetVersion(r.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Accesslog struct { Application string `json:"application" binding:"required"` Accesslog string `json:"accesslog"` @@ -106,6 +120,13 @@ func (r Region) ToRule() ConditionRoute { } } +func (r Region) GetKey() string { + interfaze := util.GetInterface(r.Service) + group := util.GetGroup(r.Service) + version := util.GetVersion(r.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Gray struct { Application string `json:"application" binding:"required"` Tags []Tag `json:"tags" binding:"required"` @@ -141,6 +162,13 @@ func (r Argument) ToRule() ConditionRoute { } } +func (a Argument) GetKey() string { + interfaze := util.GetInterface(a.Service) + group := util.GetGroup(a.Service) + version := util.GetVersion(a.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Percentage struct { Service string `json:"service" binding:"required"` Group string `json:"group"` @@ -170,6 +198,13 @@ func (p Percentage) ToRule() Override { } } +func (p Percentage) GetKey() string { + interfaze := util.GetInterface(p.Service) + group := util.GetGroup(p.Service) + version := util.GetVersion(p.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Mock struct { Service string `json:"service" binding:"required"` Group string `json:"group"` @@ -177,19 +212,26 @@ type Mock struct { Mock string `json:"mock" binding:"required"` } -func (t Mock) ToRule() Override { +func (m Mock) ToRule() Override { return Override{ - Key: t.Service, + Key: m.Service, Scope: "service", ConfigVersion: "v3.0", Enabled: true, Configs: []OverrideConfig{{ Side: "consumer", - Parameters: map[string]interface{}{"mock": t.Mock}, + Parameters: map[string]interface{}{"mock": m.Mock}, }}, } } +func (m Mock) GetKey() string { + interfaze := util.GetInterface(m.Service) + group := util.GetGroup(m.Service) + version := util.GetVersion(m.Service) + return util.ColonSeparatedKey(interfaze, group, version) +} + type Host struct { Condition string `json:"condition" binding:"required"` Host string `json:"host" binding:"required"` diff --git a/pkg/admin/model/util/sync_utils.go b/pkg/admin/model/util/sync_utils.go index cfd99bf1..446c3efe 100644 --- a/pkg/admin/model/util/sync_utils.go +++ b/pkg/admin/model/util/sync_utils.go @@ -53,7 +53,7 @@ func URL2Provider(id string, url *common.URL) *model.Provider { Timeout: url.GetParamInt(constant.TimeoutKey, constant.DefaultTimeout), Weight: url.GetParamInt(constant.WeightKey, constant.DefaultWeight), Username: url.GetParam(constant.OwnerKey, ""), - RegistrySource: model.Interface, + RegistrySource: url.GetParam(constant.RegistryType, constant.RegistryInterface), } } @@ -198,7 +198,7 @@ func Providers2DTO(providers []*model.Provider) []*model.ServiceDTO { serviceDTOs := make([]*model.ServiceDTO, len(providers)) for i := range providers { serviceDTOs[i] = &model.ServiceDTO{ - Service: providers[i].Service, + Service: util.GetInterface(providers[i].Service), AppName: providers[i].Application, Group: util.GetGroup(providers[i].Service), Version: util.GetVersion(providers[i].Service), diff --git a/pkg/admin/providers/mock/mock_provider.go b/pkg/admin/providers/mock/mock_provider.go index 03a6f5a6..1b54a526 100644 --- a/pkg/admin/providers/mock/mock_provider.go +++ b/pkg/admin/providers/mock/mock_provider.go @@ -23,6 +23,7 @@ import ( "github.com/apache/dubbo-admin/pkg/core/logger" + dubboconstant "dubbo.apache.org/dubbo-go/v3/common/constant" dubbogo "dubbo.apache.org/dubbo-go/v3/config" _ "dubbo.apache.org/dubbo-go/v3/imports" "github.com/apache/dubbo-admin/pkg/admin/mapper" @@ -57,7 +58,9 @@ func RunMockServiceServer(admin admin.Admin, dubboConfig dubbogo.RootConfig) { mockRuleService: mockRuleService, }) - builder := dubbogo.NewRootConfigBuilder().AddRegistry("zkRegistryKey", dubbogo.NewRegistryConfigBuilder().SetAddress(admin.Registry.Address).Build()) + builder := dubbogo.NewRootConfigBuilder(). + AddRegistry("zkRegistryKey", dubbogo.NewRegistryConfigBuilder().SetAddress(admin.Registry.Address).SetRegistryType(dubboconstant.RegistryTypeAll). + Build()).SetApplication(dubbogo.NewApplicationConfigBuilder().SetName("dubbo-admin").Build()) for k, v := range dubboConfig.Protocols { builder.AddProtocol(k, dubbogo.NewProtocolConfigBuilder().SetName(v.Name).SetPort(v.Port).Build()) diff --git a/pkg/admin/router/router.go b/pkg/admin/router/router.go index fd270526..6b3f2b92 100644 --- a/pkg/admin/router/router.go +++ b/pkg/admin/router/router.go @@ -200,6 +200,10 @@ func InitRouter() *Router { trafficRegion.GET("/", traffic.SearchRegion) } + // ServiceTest + router.POST("/api/:env/test", handlers.Test) + router.GET("/api/:env/test/method", handlers.MethodDetail) + // Admin UI router.StaticFS("/admin", http.FS(ui.FS())) diff --git a/pkg/admin/services/generic_service_Impl.go b/pkg/admin/services/generic_service_Impl.go new file mode 100644 index 00000000..1798dcc3 --- /dev/null +++ b/pkg/admin/services/generic_service_Impl.go @@ -0,0 +1,64 @@ +// 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 services + +import ( + "dubbo.apache.org/dubbo-go/v3/common" + dubboConfig "dubbo.apache.org/dubbo-go/v3/config" + "github.com/apache/dubbo-admin/pkg/admin/config" + "github.com/apache/dubbo-admin/pkg/admin/constant" + "github.com/apache/dubbo-admin/pkg/admin/util" + + dubboconstant "dubbo.apache.org/dubbo-go/v3/common/constant" + dubboconfig "dubbo.apache.org/dubbo-go/v3/config" +) + +type GenericServiceImpl struct{} + +func (p *GenericServiceImpl) NewRefConf(appName, iface, protocol string) dubboConfig.ReferenceConfig { + + fromUrl := config.AdminRegistry.Delegate().GetURL().Clone() + + registryConfig := dubboConfig.RegistryConfig{} + registryConfig.Group = fromUrl.GetParam("group", "") + address, _ := common.NewURL(fromUrl.Protocol + "://" + fromUrl.Location) + if fromUrl.GetParam(constant.NamespaceKey, "") != "" { + address.AddParam(constant.NamespaceKey, fromUrl.GetParam(constant.NamespaceKey, "")) + } + registryConfig.Address = address.String() + registryConfig.RegistryType = dubboconstant.RegistryTypeInterface + + refConf := dubboConfig.ReferenceConfig{ + InterfaceName: util.GetInterface(iface), + Group: util.GetGroup(iface), + Version: util.GetVersion(iface), + Cluster: "failover", + RegistryIDs: []string{"genericRegistry"}, + Protocol: protocol, + Generic: "true", + } + + rootConfig := dubboconfig.NewRootConfigBuilder(). + AddRegistry("genericRegistry", ®istryConfig). + Build() + if err := dubboconfig.Load(dubboconfig.WithRootConfig(rootConfig)); err != nil { + panic(err) + } + _ = refConf.Init(rootConfig) + refConf.GenericLoad(appName) + + return refConf +} diff --git a/pkg/admin/services/provider_service_impl.go b/pkg/admin/services/provider_service_impl.go index 5e1d99a2..12a61bd4 100644 --- a/pkg/admin/services/provider_service_impl.go +++ b/pkg/admin/services/provider_service_impl.go @@ -284,6 +284,7 @@ func (p *ProviderServiceImpl) FindService(pattern string, filter string) ([]*mod reg *regexp.Regexp err error ) + result := make([]*model.Provider, 0) if !strings.Contains(filter, constant.AnyValue) && !strings.Contains(filter, constant.InterrogationPoint) { if pattern == constant.IP { providers, err = p.findByAddress(filter) @@ -303,6 +304,7 @@ func (p *ProviderServiceImpl) FindService(pattern string, filter string) ([]*mod } else { return nil, fmt.Errorf("unsupport the pattern: %s", pattern) } + result = providers } else { var candidates *set.HashSet if pattern == constant.IP { @@ -352,11 +354,12 @@ func (p *ProviderServiceImpl) FindService(pattern string, filter string) ([]*mod return nil, err } } + result = append(result, providers...) } } } - return util.Providers2DTO(providers), nil + return util.Providers2DTO(result), nil } func hasPrefixOrSuffix(filter string) bool { diff --git a/pkg/admin/services/registry_service_sync.go b/pkg/admin/services/registry_service_sync.go index 5748b3da..daadf8e9 100644 --- a/pkg/admin/services/registry_service_sync.go +++ b/pkg/admin/services/registry_service_sync.go @@ -18,6 +18,8 @@ package services import ( + dubboRegistry "dubbo.apache.org/dubbo-go/v3/registry" + "dubbo.apache.org/dubbo-go/v3/remoting" "github.com/apache/dubbo-admin/pkg/admin/cache/registry" "strings" "sync" @@ -53,9 +55,10 @@ type adminNotifyListener struct { mu sync.Mutex } -func (al *adminNotifyListener) Notify(serviceURL *common.URL) { +func (al *adminNotifyListener) Notify(event *dubboRegistry.ServiceEvent) { var interfaceName string al.mu.Lock() + serviceURL := event.Service categories := make(map[string]map[string]map[string]*common.URL) category := serviceURL.GetParam(constant.CategoryKey, "") if len(category) == 0 { @@ -66,7 +69,7 @@ func (al *adminNotifyListener) Notify(serviceURL *common.URL) { category = constant.ProvidersCategory } } - if strings.EqualFold(constant.EmptyProtocol, serviceURL.Protocol) { + if event.Action == remoting.EventTypeDel { if services, ok := cache.InterfaceRegistryCache.Load(category); ok { if services != nil { servicesMap, ok := services.(*sync.Map) @@ -78,14 +81,14 @@ func (al *adminNotifyListener) Notify(serviceURL *common.URL) { group := serviceURL.Group() version := serviceURL.Version() if constant.AnyValue != group && constant.AnyValue != version { - servicesMap.Delete(serviceURL.Service()) + deleteURL(servicesMap, serviceURL) } else { // iterator services servicesMap.Range(func(key, value interface{}) bool { if util2.GetInterface(key.(string)) == serviceURL.Service() && (constant.AnyValue == group || group == util2.GetGroup(key.(string))) && (constant.AnyValue == version || version == util2.GetVersion(key.(string))) { - servicesMap.Delete(key) + deleteURL(servicesMap, serviceURL) } return true }) @@ -108,10 +111,10 @@ func (al *adminNotifyListener) Notify(serviceURL *common.URL) { services[service] = ids } if md5, ok := UrlIdsMapper.Load(serviceURL.Key()); ok { - ids[md5.(string)] = serviceURL + ids[md5.(string)] = getURLToAdd(nil, serviceURL) } else { md5 := util2.Md5_16bit(serviceURL.Key()) - ids[md5] = serviceURL + ids[md5] = getURLToAdd(nil, serviceURL) UrlIdsMapper.LoadOrStore(serviceURL.Key(), md5) } } @@ -128,21 +131,72 @@ func (al *adminNotifyListener) Notify(serviceURL *common.URL) { } // iterator services key set servicesMap.Range(func(key, inner any) bool { - _, ok := value[key.(string)] + ids, ok := value[key.(string)] if util2.GetInterface(key.(string)) == interfaceName && !ok { servicesMap.Delete(key) + } else { + for k, v := range ids { + inner.(map[string]*common.URL)[k] = getURLToAdd(inner.(map[string]*common.URL)[k], v) + } } return true }) + + for k, v := range value { + _, ok := services.(*sync.Map).Load(k) + if !ok { + services.(*sync.Map).Store(k, v) + } + } } else { services = &sync.Map{} cache.InterfaceRegistryCache.Store(category, services) - } - for k, v := range value { - services.(*sync.Map).Store(k, v) + for k, v := range value { + services.(*sync.Map).Store(k, v) + } } } } al.mu.Unlock() } + +func getURLToAdd(url *common.URL, newURL *common.URL) *common.URL { + if url == nil { + newURL = newURL.Clone() + if currentType, ok := newURL.GetNonDefaultParam(constant.RegistryType); !ok { + newURL.SetParam(constant.RegistryType, constant.RegistryInterface) + } else { + newURL.SetParam(constant.RegistryType, strings.ToUpper(currentType)) + } + } else { + currentType, _ := url.GetNonDefaultParam(constant.RegistryType) + changedType, _ := newURL.GetNonDefaultParam(constant.RegistryType) + if currentType == constant.RegistryAll || currentType != changedType { + newURL = newURL.Clone() + newURL.SetParam(constant.RegistryType, constant.RegistryAll) + } + } + return newURL +} + +func deleteURL(servicesMap *sync.Map, serviceURL *common.URL) { + if innerServices, ok := servicesMap.Load(serviceURL.Service()); ok { + innerServicesMap := innerServices.(map[string]*common.URL) + if len(innerServicesMap) > 0 { + for _, url := range innerServicesMap { + currentType, _ := url.GetNonDefaultParam(constant.RegistryType) + changedType := serviceURL.GetParam(constant.RegistryType, constant.RegistryInterface) + if currentType == constant.RegistryAll { + if changedType == constant.RegistryInstance { + url.SetParam(constant.RegistryType, constant.RegistryInterface) + } else { + url.SetParam(constant.RegistryType, constant.RegistryInstance) + } + } else if currentType == changedType { + servicesMap.Delete(serviceURL.Service()) + } + } + } + } +} diff --git a/pkg/admin/services/service_testing_v3.go b/pkg/admin/services/service_testing_v3.go new file mode 100644 index 00000000..07fbb821 --- /dev/null +++ b/pkg/admin/services/service_testing_v3.go @@ -0,0 +1,223 @@ +// 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 services + +import ( + "dubbo.apache.org/dubbo-go/v3/metadata/definition" + "github.com/apache/dubbo-admin/pkg/admin/model" + "regexp" + "strings" + "time" +) + +var COLLECTION_PATTERN = regexp.MustCompile("^java\\.util\\..*(Set|List|Queue|Collection|Deque)(<.*>)*$") +var MAP_PATTERN = regexp.MustCompile("^java\\.util\\..*Map.*(<.*>)*$") + +type ServiceTestingV3 struct{} + +func (p *ServiceTestingV3) SameMethod(m definition.MethodDefinition, methodSig string) bool { + name := m.Name + parameters := m.ParameterTypes + var sb strings.Builder + sb.WriteString(name) + sb.WriteString("~") + for _, parameter := range parameters { + sb.WriteString(parameter) + sb.WriteString(";") + } + sig := strings.TrimSuffix(sb.String(), ";") + return sig == methodSig +} + +func (p *ServiceTestingV3) GenerateMethodMeta(serviceDefinition definition.FullServiceDefinition, methodDefinition definition.MethodDefinition) model.MethodMetadata { + var methodMetadata model.MethodMetadata + parameterTypes := methodDefinition.ParameterTypes + returnType := methodDefinition.ReturnType + signature := methodDefinition.Name + "~" + strings.Join(parameterTypes, ";") + methodMetadata.Signature = signature + methodMetadata.ReturnType = returnType + parameters := p.GenerateParameterTypes(parameterTypes, serviceDefinition.ServiceDefinition) + methodMetadata.ParameterTypes = parameters + return methodMetadata +} + +func (p *ServiceTestingV3) GenerateParameterTypes(parameterTypes []string, serviceDefinition definition.ServiceDefinition) []interface{} { + var parameters []interface{} + for _, tp := range parameterTypes { + result := p.GenerateType(serviceDefinition, tp) + parameters = append(parameters, result) + } + return parameters +} + +func (p *ServiceTestingV3) FindTypeDefinition(serviceDefinition definition.ServiceDefinition, typeName string) definition.TypeDefinition { + for _, t := range serviceDefinition.Types { + if t.Type == typeName { + return t + } + } + return definition.TypeDefinition{Type: typeName} +} + +func (p *ServiceTestingV3) GenerateType(sd definition.ServiceDefinition, typeName string) interface{} { + td := p.FindTypeDefinition(sd, typeName) + return p.GenerateTypeHelper(sd, td) +} + +func (p *ServiceTestingV3) GenerateTypeHelper(sd definition.ServiceDefinition, td definition.TypeDefinition) interface{} { + if p.IsPrimitiveType(td) { + return p.GeneratePrimitiveType(td) + } else if p.IsMap(td) { + return p.GenerateMapType(sd, td) + } else if p.IsArray(td) { + return p.GenerateArrayType(sd, td) + } else if p.IsCollection(td) { + return p.GenerateCollectionType(sd, td) + } else { + return p.GenerateComplexType(sd, td) + } +} + +func (p *ServiceTestingV3) IsPrimitiveType(td definition.TypeDefinition) bool { + typeName := td.Type + return p.IsPrimitiveTypeHelper(typeName) +} + +func (p *ServiceTestingV3) IsPrimitiveTypeHelper(typeName string) bool { + primitiveTypes := map[string]bool{ + "byte": true, + "java.lang.Byte": true, + "short": true, + "java.lang.Short": true, + "int": true, + "java.lang.Integer": true, + "long": true, + "java.lang.Long": true, + "float": true, + "java.lang.Float": true, + "double": true, + "java.lang.Double": true, + "boolean": true, + "java.lang.Boolean": true, + "void": true, + "java.lang.Void": true, + "java.lang.String": true, + "java.util.Date": true, + "java.lang.Object": true, + } + return primitiveTypes[typeName] +} + +func (p *ServiceTestingV3) GeneratePrimitiveType(td definition.TypeDefinition) interface{} { + return p.GeneratePrimitiveTypeHelper(td.Type) +} + +func (p *ServiceTestingV3) GeneratePrimitiveTypeHelper(typeName string) interface{} { + switch typeName { + case "byte", "java.lang.Byte", "short", "java.lang.Short", + "int", "java.lang.Integer", "long", "java.lang.Long": + return 0 + case "float", "java.lang.Float", "double", "java.lang.Double": + return 0.0 + case "boolean", "java.lang.Boolean": + return true + case "void", "java.lang.Void": + return nil + case "java.lang.String": + return "" + case "java.lang.Object": + return make(map[string]interface{}) + case "java.util.Date": + return time.Now().UnixNano() / int64(time.Millisecond) + default: + return make(map[string]interface{}) + } +} + +func (p *ServiceTestingV3) IsMap(td definition.TypeDefinition) bool { + mapType := strings.Split(td.Type, "<")[0] + return MAP_PATTERN.MatchString(mapType) +} + +func (p *ServiceTestingV3) GenerateMapType(sd definition.ServiceDefinition, td definition.TypeDefinition) interface{} { + keyType := strings.TrimSpace(strings.Split(strings.Split(td.Type, "<")[1], ",")[0]) + key := p.GenerateType(sd, keyType) + valueType := strings.TrimSpace(strings.Split(strings.Split(td.Type, ",")[1], ">")[0]) + if valueType == "" { + valueType = "java.lang.Object" + } + value := p.GenerateType(sd, valueType) + + mapObj := make(map[interface{}]interface{}) + mapObj[key] = value + return mapObj +} + +func (p *ServiceTestingV3) IsArray(td definition.TypeDefinition) bool { + return strings.HasSuffix(td.Type, "[]") +} + +func (p *ServiceTestingV3) GenerateArrayType(sd definition.ServiceDefinition, td definition.TypeDefinition) interface{} { + typeStr := strings.TrimSuffix(td.Type, "[]") + elem := p.GenerateType(sd, typeStr) + return []interface{}{elem} +} + +func (p *ServiceTestingV3) IsCollection(td definition.TypeDefinition) bool { + typeStr := strings.Split(td.Type, "<")[0] + return COLLECTION_PATTERN.MatchString(typeStr) +} + +func (p *ServiceTestingV3) GenerateCollectionType(sd definition.ServiceDefinition, td definition.TypeDefinition) interface{} { + typeStr := strings.SplitAfterN(td.Type, "<", 2)[1] + if typeStr == "" { + // if type is null return empty collection + return []interface{}{} + } + elem := p.GenerateType(sd, typeStr) + return []interface{}{elem} +} + +func (p *ServiceTestingV3) GenerateComplexType(sd definition.ServiceDefinition, td definition.TypeDefinition) interface{} { + holder := make(map[string]interface{}) + p.GenerateComplexTypeHelper(sd, td, holder) + return holder +} + +func (p *ServiceTestingV3) GenerateComplexTypeHelper(sd definition.ServiceDefinition, td definition.TypeDefinition, holder map[string]interface{}) { + for name, property := range td.Properties { + if p.IsPrimitiveType(property) { + holder[name] = p.GeneratePrimitiveType(property) + } else { + p.GenerateEnclosedType(holder, name, sd, property.Type) + } + } +} + +func (p *ServiceTestingV3) GenerateEnclosedType(holder map[string]interface{}, key string, sd definition.ServiceDefinition, typeName string) { + if p.IsPrimitiveTypeHelper(typeName) { + holder[key] = p.GenerateType(sd, typeName) + } else { + td := p.FindTypeDefinition(sd, typeName) + if td.Properties == nil || len(td.Properties) == 0 { + holder[key] = p.GenerateTypeHelper(sd, td) + } else { + enclosedMap := make(map[string]interface{}) + holder[key] = enclosedMap + p.GenerateComplexTypeHelper(sd, td, enclosedMap) + } + } +} diff --git a/pkg/admin/services/traffic/accesslog.go b/pkg/admin/services/traffic/accesslog.go index 4c6c502d..14f774da 100644 --- a/pkg/admin/services/traffic/accesslog.go +++ b/pkg/admin/services/traffic/accesslog.go @@ -22,6 +22,7 @@ import ( "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" "gopkg.in/yaml.v2" + "strconv" ) type AccesslogService struct{} @@ -74,7 +75,11 @@ func (tm *AccesslogService) Search(a *model.Accesslog) ([]*model.Accesslog, erro accesslog := &model.Accesslog{ Application: override.Key, } - accesslog.Accesslog = alv.(string) + if alvBool, ok := alv.(bool); ok { + accesslog.Accesslog = strconv.FormatBool(alvBool) + } else { + accesslog.Accesslog = alv.(string) + } result = append(result, accesslog) } } diff --git a/pkg/admin/services/traffic/argument.go b/pkg/admin/services/traffic/argument.go index 6872caaa..15bbb8bf 100644 --- a/pkg/admin/services/traffic/argument.go +++ b/pkg/admin/services/traffic/argument.go @@ -23,7 +23,6 @@ import ( "github.com/apache/dubbo-admin/pkg/admin/constant" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" - "github.com/apache/dubbo-admin/pkg/admin/util" "gopkg.in/yaml.v2" ) @@ -31,7 +30,7 @@ type ArgumentService struct{} // CreateOrUpdate create or update timeout rule func (tm *ArgumentService) CreateOrUpdate(a *model.Argument) error { - key := services.GetRoutePath(util.ColonSeparatedKey(a.Service, a.Group, a.Version), constant.ConditionRoute) + key := services.GetRoutePath(a.GetKey(), constant.ConditionRoute) newRule := a.ToRule() err := createOrUpdateCondition(key, newRule) @@ -39,7 +38,7 @@ func (tm *ArgumentService) CreateOrUpdate(a *model.Argument) error { } func (tm *ArgumentService) Delete(a *model.Argument) error { - key := services.GetRoutePath(util.ColonSeparatedKey(a.Service, a.Group, a.Version), constant.ConditionRoute) + key := services.GetRoutePath(a.GetKey(), constant.ConditionRoute) err2 := removeCondition(key, a.Rule, model.RegionAdminIdentifier) if err2 != nil { return err2 @@ -52,7 +51,7 @@ func (tm *ArgumentService) Search(a *model.Argument) ([]*model.Argument, error) var con string if a.Service != "" && a.Service != "*" { - con = util.ColonSeparatedKey(a.Service, a.Group, a.Version) + con = a.GetKey() } list, err := services.GetRules(con, constant.ConditionRuleSuffix) diff --git a/pkg/admin/services/traffic/mock.go b/pkg/admin/services/traffic/mock.go index bcdac0e9..6aaee7bf 100644 --- a/pkg/admin/services/traffic/mock.go +++ b/pkg/admin/services/traffic/mock.go @@ -23,14 +23,13 @@ import ( "github.com/apache/dubbo-admin/pkg/admin/constant" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" - "github.com/apache/dubbo-admin/pkg/admin/util" ) type MockService struct{} // CreateOrUpdate create or update timeout rule func (tm *MockService) CreateOrUpdate(m *model.Mock) error { - key := services.GetOverridePath(util.ColonSeparatedKey(m.Service, m.Group, m.Version)) + key := services.GetOverridePath(m.GetKey()) newRule := m.ToRule() err := createOrUpdateOverride(key, "consumer", "mock", newRule) @@ -38,7 +37,7 @@ func (tm *MockService) CreateOrUpdate(m *model.Mock) error { } func (tm *MockService) Delete(m *model.Mock) error { - key := services.GetOverridePath(util.ColonSeparatedKey(m.Service, m.Group, m.Version)) + key := services.GetOverridePath(m.GetKey()) err2 := removeFromOverride(key, "consumer", "mock") if err2 != nil { return err2 @@ -51,7 +50,7 @@ func (tm *MockService) Search(m *model.Mock) ([]*model.Mock, error) { var con string if m.Service != "" && m.Service != "*" { - con = util.ColonSeparatedKey(m.Service, m.Group, m.Version) + con = m.GetKey() } list, err := services.GetRules(con, constant.ConfiguratorRuleSuffix) if err != nil { diff --git a/pkg/admin/services/traffic/region.go b/pkg/admin/services/traffic/region.go index 5705b2d4..bd4eaadc 100644 --- a/pkg/admin/services/traffic/region.go +++ b/pkg/admin/services/traffic/region.go @@ -23,7 +23,6 @@ import ( "github.com/apache/dubbo-admin/pkg/admin/constant" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" - "github.com/apache/dubbo-admin/pkg/admin/util" "gopkg.in/yaml.v2" ) @@ -31,7 +30,7 @@ type RegionService struct{} // CreateOrUpdate create or update timeout rule func (tm *RegionService) CreateOrUpdate(r *model.Region) error { - key := services.GetRoutePath(util.ColonSeparatedKey(r.Service, r.Group, r.Version), constant.ConditionRoute) + key := services.GetRoutePath(r.GetKey(), constant.ConditionRoute) newRule := r.ToRule() var err error @@ -45,7 +44,7 @@ func (tm *RegionService) CreateOrUpdate(r *model.Region) error { } func (tm *RegionService) Delete(r *model.Region) error { - key := services.GetRoutePath(util.ColonSeparatedKey(r.Service, r.Group, r.Version), constant.ConditionRoute) + key := services.GetRoutePath(r.GetKey(), constant.ConditionRoute) err2 := removeCondition(key, r.Rule, model.RegionAdminIdentifier) if err2 != nil { return err2 @@ -58,7 +57,7 @@ func (tm *RegionService) Search(r *model.Region) ([]*model.Region, error) { var con string if r.Service != "" && r.Service != "*" { - con = util.ColonSeparatedKey(r.Service, r.Group, r.Version) + con = r.GetKey() } list, err := services.GetRules(con, constant.ConditionRuleSuffix) diff --git a/pkg/admin/services/traffic/retry.go b/pkg/admin/services/traffic/retry.go index 15b73c3c..9e15f9d0 100644 --- a/pkg/admin/services/traffic/retry.go +++ b/pkg/admin/services/traffic/retry.go @@ -18,6 +18,9 @@ package traffic import ( + "fmt" + "github.com/apache/dubbo-admin/pkg/core/logger" + "strconv" "strings" "github.com/apache/dubbo-admin/pkg/admin/constant" @@ -77,7 +80,16 @@ func (tm *RetryService) Search(r *model.Retry) ([]*model.Retry, error) { return result, err2 } if rv != nil { - retry.Retry = rv.(int) + if rvStr, ok := rv.(string); ok { + rvInt, err := strconv.Atoi(rvStr) + if err != nil { + logger.Error(fmt.Sprintf("Error parsing retry rule %s", v), err) + return result, err + } + retry.Retry = rvInt + } else { + retry.Retry = rv.(int) + } result = append(result, retry) } } diff --git a/pkg/admin/services/traffic/timeout.go b/pkg/admin/services/traffic/timeout.go index f17e4ca8..abe0a2f6 100644 --- a/pkg/admin/services/traffic/timeout.go +++ b/pkg/admin/services/traffic/timeout.go @@ -18,19 +18,21 @@ package traffic import ( + "fmt" + "github.com/apache/dubbo-admin/pkg/core/logger" + "strconv" "strings" "github.com/apache/dubbo-admin/pkg/admin/constant" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" - "github.com/apache/dubbo-admin/pkg/admin/util" ) type TimeoutService struct{} // CreateOrUpdate create or update timeout rule func (tm *TimeoutService) CreateOrUpdate(t *model.Timeout) error { - key := services.GetOverridePath(util.ColonSeparatedKey(t.Service, t.Group, t.Version)) + key := services.GetOverridePath(t.GetKey()) newRule := t.ToRule() err := createOrUpdateOverride(key, "consumer", "timeout", newRule) @@ -38,7 +40,7 @@ func (tm *TimeoutService) CreateOrUpdate(t *model.Timeout) error { } func (tm *TimeoutService) Delete(t *model.Timeout) error { - key := services.GetOverridePath(util.ColonSeparatedKey(t.Service, t.Group, t.Version)) + key := services.GetOverridePath(t.GetKey()) err2 := removeFromOverride(key, "consumer", "timeout") if err2 != nil { return err2 @@ -51,7 +53,7 @@ func (tm *TimeoutService) Search(t *model.Timeout) ([]*model.Timeout, error) { var con string if t.Service != "" && t.Service != "*" { - con = util.ColonSeparatedKey(t.Service, t.Group, t.Version) + con = t.GetKey() } list, err := services.GetRules(con, constant.ConfiguratorRuleSuffix) @@ -79,7 +81,16 @@ func (tm *TimeoutService) Search(t *model.Timeout) ([]*model.Timeout, error) { } if tv != nil { - t.Timeout = tv.(int) + if tvStr, ok := tv.(string); ok { + tvInt, err := strconv.Atoi(tvStr) + if err != nil { + logger.Error(fmt.Sprintf("Error parsing timeout rule %s", v), err) + return result, err + } + t.Timeout = tvInt + } else { + t.Timeout = tv.(int) + } result = append(result, t) } } diff --git a/pkg/admin/services/traffic/weight.go b/pkg/admin/services/traffic/weight.go index 6384ba45..09882cce 100644 --- a/pkg/admin/services/traffic/weight.go +++ b/pkg/admin/services/traffic/weight.go @@ -23,7 +23,6 @@ import ( "github.com/apache/dubbo-admin/pkg/admin/constant" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/admin/services" - "github.com/apache/dubbo-admin/pkg/admin/util" "gopkg.in/yaml.v2" ) @@ -31,7 +30,7 @@ type WeightService struct{} // CreateOrUpdate create or update timeout rule func (tm *WeightService) CreateOrUpdate(p *model.Percentage) error { - key := services.GetOverridePath(util.ColonSeparatedKey(p.Service, p.Group, p.Version)) + key := services.GetOverridePath(p.GetKey()) newRule := p.ToRule() err := createOrUpdateOverride(key, "provider", "weight", newRule) @@ -39,7 +38,7 @@ func (tm *WeightService) CreateOrUpdate(p *model.Percentage) error { } func (tm *WeightService) Delete(p *model.Percentage) error { - key := services.GetOverridePath(util.ColonSeparatedKey(p.Service, p.Group, p.Version)) + key := services.GetOverridePath(p.GetKey()) err := removeFromOverride(key, "provider", "weight") if err != nil { return err @@ -52,7 +51,7 @@ func (tm *WeightService) Search(p *model.Percentage) ([]*model.Percentage, error var con string if p.Service != "" && p.Service != "*" { - con = util.ColonSeparatedKey(p.Service, p.Group, p.Version) + con = p.GetKey() } list, err := services.GetRules(con, constant.ConfiguratorRuleSuffix) diff --git a/pkg/config/admin/address_config.go b/pkg/config/admin/address_config.go index 5885cd6f..98bae69e 100644 --- a/pkg/config/admin/address_config.go +++ b/pkg/config/admin/address_config.go @@ -19,6 +19,7 @@ package admin import ( "net/url" + "strings" "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/constant" @@ -46,7 +47,9 @@ func (c *AddressConfig) GetAddress() string { func (c *AddressConfig) GetUrlMap() url.Values { urlMap := url.Values{} urlMap.Set(constant.ConfigNamespaceKey, c.param("namespace", "")) - urlMap.Set(constant.ConfigGroupKey, c.param("group", "")) + urlMap.Set(constant.ConfigGroupKey, c.param(constant.GroupKey, "dubbo")) + urlMap.Set(constant.MetadataReportGroupKey, c.param(constant.GroupKey, "dubbo")) + urlMap.Set(constant.ClientNameKey, clientNameID(c.Url.Scheme, c.Url.Host)) return urlMap } @@ -67,3 +70,7 @@ func (c *AddressConfig) ToURL() (*common.URL, error) { common.WithPassword(c.param("password", "")), ) } + +func clientNameID(protocol, address string) string { + return strings.Join([]string{protocol, address}, "-") +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 9e5dab81..81b8acbb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -18,10 +18,9 @@ package config const ( - SanitizedValue = "*****" - conf = "./conf/admin.yml" - confPathKey = "ADMIN_CONFIG_PATH" - MockProviderConf = "./conf/mock_provider.yml" + SanitizedValue = "*****" + conf = "./conf/admin.yml" + confPathKey = "ADMIN_CONFIG_PATH" ) type Config interface {
