From 39f5bfeebb1f2179de0129985eb219a0ff3a7efa Mon Sep 17 00:00:00 2001 From: LaurenceLiZhixin <382673304@qq.com> Date: Tue, 26 Jan 2021 16:51:16 +0800 Subject: [PATCH] feat: add config api --- config/config_api.go | 471 ++++++++++++++++++++++++++++++++++++++ config/config_api_test.go | 158 +++++++++++++ 2 files changed, 629 insertions(+) create mode 100644 config/config_api.go create mode 100644 config/config_api_test.go diff --git a/config/config_api.go b/config/config_api.go new file mode 100644 index 000000000..15db1d80d --- /dev/null +++ b/config/config_api.go @@ -0,0 +1,471 @@ +/* + * 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 config + +import ( + "context" + "time" +) + +//////////////////////////////////// default registry config +const defaultZKAddr = "127.0.0.1:2181" +const defaultConsulAddr = "127.0.0.1:8500" +const defaultNacosAddr = "127.0.0.1:8848" +const defaultRegistryTimeout = "3s" + +func NewDefaultRegistryConfig(protocol string) *RegistryConfig { + switch protocol { + case "zookeeper": + return &RegistryConfig{ + Protocol: protocol, + Address: defaultZKAddr, + TimeoutStr: defaultRegistryTimeout, + } + case "consul": + return &RegistryConfig{ + Protocol: protocol, + Address: defaultConsulAddr, + TimeoutStr: defaultRegistryTimeout, + } + case "nacos": + return &RegistryConfig{ + Protocol: protocol, + Address: defaultNacosAddr, + TimeoutStr: defaultRegistryTimeout, + } + default: + return &RegistryConfig{ + Protocol: protocol, + } + } +} + +///////////////////////////////////// registry config api +type RegistryConfigOpt func(config *RegistryConfig) *RegistryConfig + +func NewRegistryConfig(opts ...RegistryConfigOpt) *RegistryConfig { + newRegistryConfig := NewDefaultRegistryConfig("none") + for _, v := range opts { + newRegistryConfig = v(newRegistryConfig) + } + return newRegistryConfig +} + +func WithRegistryProtocol(regProtocol string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Protocol = regProtocol + return config + } +} + +func WithRegistryAddress(addr string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Address = addr + return config + } +} + +func WithRegistryTimeOut(timeout string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.TimeoutStr = timeout + return config + } +} + +func WithRegistryGroup(group string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Group = group + return config + } +} + +func WithRegistryTTL(ttl string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.TTL = ttl + return config + } +} + +func WithRegistryUserName(userName string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Username = userName + return config + } +} + +func WithRegistryPassword(psw string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Password = psw + return config + } +} + +func WithRegistrySimplified(simplified bool) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Simplified = simplified + return config + } +} + +func WithRegistryPreferred(preferred bool) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Preferred = preferred + return config + } +} + +func WithRegistryWeight(weight int64) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Weight = weight + return config + } +} + +func WithRegistryParams(params map[string]string) RegistryConfigOpt { + return func(config *RegistryConfig) *RegistryConfig { + config.Params = params + return config + } +} + +///////////////////////////////////// consumer config api +type ConsumerConfigOpt func(config *ConsumerConfig) *ConsumerConfig + +func NewDefaultConsumerConfig() *ConsumerConfig { + check := true + newConsumerConfig := &ConsumerConfig{ + BaseConfig: BaseConfig{}, + Registries: make(map[string]*RegistryConfig, 8), + References: make(map[string]*ReferenceConfig, 8), + ConnectTimeout: 3 * time.Second, + RequestTimeout: 3 * time.Second, + Check: &check, + } + return newConsumerConfig +} + +func NewConsumerConfig(opts ...ConsumerConfigOpt) *ConsumerConfig { + newConfig := NewDefaultConsumerConfig() + for _, v := range opts { + v(newConfig) + } + return newConfig +} +func WithConsumerAppConfig(appConfig *ApplicationConfig) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.ApplicationConfig = appConfig + return config + } +} + +func WithConsumerRegistryConfig(registryKey string, regConfig *RegistryConfig) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.Registries[registryKey] = regConfig + return config + } +} + +func WithConsumerReferenceConfig(referenceKey string, refConfig *ReferenceConfig) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.References[referenceKey] = refConfig + return config + } +} + +func WithConsumerConnTimeout(timeout time.Duration) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.ConnectTimeout = timeout + return config + } +} + +func WithConsumerRequestTimeout(timeout time.Duration) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.RequestTimeout = timeout + return config + } +} + +func WithConsumerConfigCenterConfig(configCenterConfig *ConfigCenterConfig) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + config.ConfigCenterConfig = configCenterConfig + return config + } +} + +func WithConsumerConfigCheck(check bool) ConsumerConfigOpt { + return func(config *ConsumerConfig) *ConsumerConfig { + *config.Check = check + return config + } +} + +//////////////////////////////////// reference config api +type ReferenceConfigOpt func(config *ReferenceConfig) *ReferenceConfig + +func NewDefaultReferenceConfig() *ReferenceConfig { + newReferenceConfig := NewReferenceConfig("", context.Background()) + newReferenceConfig.Methods = make([]*MethodConfig, 0, 8) + newReferenceConfig.Params = make(map[string]string, 8) + return newReferenceConfig +} + +func NewReferenceConfigByAPI(opts ...ReferenceConfigOpt) *ReferenceConfig { + newreferenceConfig := NewDefaultReferenceConfig() + for _, v := range opts { + v(newreferenceConfig) + } + return newreferenceConfig +} + +func WithReferenceRegistry(registry string) ReferenceConfigOpt { + return func(config *ReferenceConfig) *ReferenceConfig { + config.Registry = registry + return config + } +} +func WithReferenceProtocol(protocol string) ReferenceConfigOpt { + return func(config *ReferenceConfig) *ReferenceConfig { + config.Protocol = protocol + return config + } +} +func WithReferenceInterface(interfaceName string) ReferenceConfigOpt { + return func(config *ReferenceConfig) *ReferenceConfig { + config.InterfaceName = interfaceName + return config + } +} +func WithReferenceCluster(cluster string) ReferenceConfigOpt { + return func(config *ReferenceConfig) *ReferenceConfig { + config.Cluster = cluster + return config + } +} +func WithReferenceMethod(methodName, retries, lb string) ReferenceConfigOpt { + return func(config *ReferenceConfig) *ReferenceConfig { + config.Methods = append(config.Methods, &MethodConfig{ + Name: methodName, + Retries: retries, + LoadBalance: lb, + }) + return config + } +} + +///////////////////////////////////// provider config api +type ProviderConfigOpt func(config *ProviderConfig) *ProviderConfig + +func NewDefaultProviderConfig() *ProviderConfig { + newConsumerConfig := &ProviderConfig{ + BaseConfig: BaseConfig{ + ApplicationConfig: &ApplicationConfig{ + Name: "dubbo", + Module: "module", + Organization: "dubbo_org", + Owner: "dubbo", + }, + }, + Services: make(map[string]*ServiceConfig), + Registries: make(map[string]*RegistryConfig, 8), + Protocols: make(map[string]*ProtocolConfig, 8), + } + return newConsumerConfig +} + +func NewProviderConfig(opts ...ProviderConfigOpt) *ProviderConfig { + newConfig := NewDefaultProviderConfig() + for _, v := range opts { + v(newConfig) + } + return newConfig +} + +func WithPrividerRegistryConfig(regConfig *RegistryConfig) ProviderConfigOpt { + return func(config *ProviderConfig) *ProviderConfig { + config.Registries[regConfig.Protocol] = regConfig + return config + } +} + +func WithProviderAppConfig(appConfig *ApplicationConfig) ProviderConfigOpt { + return func(config *ProviderConfig) *ProviderConfig { + config.ApplicationConfig = appConfig + return config + } +} + +func WithProviderServices(serviceName string, serviceConfig *ServiceConfig) ProviderConfigOpt { + return func(config *ProviderConfig) *ProviderConfig { + config.Services[serviceName] = serviceConfig + return config + } +} + +func WithProviderProtocol(protocolKey, protocol, port string) ProviderConfigOpt { + return func(config *ProviderConfig) *ProviderConfig { + config.Protocols[protocolKey] = &ProtocolConfig{ + Name: protocol, + Port: port, + } + return config + } +} + +func WithProviderRegistry(registryKey string, registryConfig *RegistryConfig) ProviderConfigOpt { + return func(config *ProviderConfig) *ProviderConfig { + config.Registries[registryKey] = registryConfig + return config + } +} + +/////////////////////////////////////// service config api +type ServiceConfigOpt func(config *ServiceConfig) *ServiceConfig + +func NewDefaultServiceConfig() *ServiceConfig { + newServiceConfig := NewServiceConfig("", context.Background()) + newServiceConfig.Params = make(map[string]string) + newServiceConfig.Methods = make([]*MethodConfig, 0, 8) + return newServiceConfig +} + +// NewServiceConfigByAPI is named as api, because there is NewServiceConfig func already declared +func NewServiceConfigByAPI(opts ...ServiceConfigOpt) *ServiceConfig { + defaultServiceConfig := NewDefaultServiceConfig() + for _, v := range opts { + v(defaultServiceConfig) + } + return defaultServiceConfig +} + +func WithServiceRegistry(registry string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Registry = registry + return config + } +} + +func WithServiceProtocol(protocol string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Protocol = protocol + return config + } +} +func WithServiceInterface(interfaceName string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.InterfaceName = interfaceName + return config + } +} +func WithServiceLoadBalance(lb string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Loadbalance = lb + return config + } +} + +func WithServiceWarmUpTime(warmUp string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Warmup = warmUp + return config + } +} + +func WithServiceCluster(cluster string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Cluster = cluster + return config + } +} + +func WithServiceMethod(name, retries, lb string) ServiceConfigOpt { + return func(config *ServiceConfig) *ServiceConfig { + config.Methods = append(config.Methods, &MethodConfig{ + Name: name, + Retries: retries, + LoadBalance: lb, + }) + return config + } +} + +///////////////////////////////////////// Application config api +type ApplicationConfigOpt func(config *ApplicationConfig) *ApplicationConfig + +func NewDefaultApplicationConfig() *ApplicationConfig { + newAppConfig := &ApplicationConfig{ + Name: "dubbo.io", + Module: "sample", + Organization: "dubbo.io", + Owner: "dubbogo", + Version: "0.0.1", + Environment: "dev", + } + return newAppConfig +} + +// NewApplicationConfig is named as api, because there is NewServiceConfig func already declared +func NewApplicationConfig(opts ...ApplicationConfigOpt) *ApplicationConfig { + defaultServiceConfig := NewDefaultApplicationConfig() + for _, v := range opts { + v(defaultServiceConfig) + } + return defaultServiceConfig +} + +func WithAppName(name string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Name = name + return config + } +} + +func WithAppModule(module string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Module = module + return config + } +} + +func WithAppOrganization(org string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Organization = org + return config + } +} + +func WithAppOwner(owner string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Owner = owner + return config + } +} + +func WithAppVersion(version string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Version = version + return config + } +} + +func WithAppEnvironment(env string) ApplicationConfigOpt { + return func(config *ApplicationConfig) *ApplicationConfig { + config.Environment = env + return config + } +} diff --git a/config/config_api_test.go b/config/config_api_test.go new file mode 100644 index 000000000..5e6d5f529 --- /dev/null +++ b/config/config_api_test.go @@ -0,0 +1,158 @@ +package config + +import ( + "github.com/stretchr/testify/assert" + "strconv" + "testing" + "time" +) + +func TestNewDefaultServiceConfig(t *testing.T) { + serviceConfig := NewServiceConfigByAPI( + WithServiceCluster("test-cluster"), + WithServiceInterface("test-interface"), + WithServiceLoadBalance("test-loadbalance"), + WithServiceMethod("test-method1", "test-retries1", "test-lb1"), + WithServiceMethod("test-method2", "test-retries2", "test-lb2"), + WithServiceMethod("test-method3", "test-retries3", "test-lb3"), + WithServiceProtocol("test-protocol"), + WithServiceRegistry("test-registry"), + WithServiceWarmUpTime("test-warmup"), + ) + assert.Equal(t, serviceConfig.Cluster, "test-cluster") + assert.Equal(t, serviceConfig.InterfaceName, "test-interface") + assert.Equal(t, serviceConfig.Loadbalance, "test-loadbalance") + for i, v := range serviceConfig.Methods { + backFix := strconv.Itoa(i + 1) + assert.Equal(t, v.Name, "test-method"+backFix) + assert.Equal(t, v.Retries, "test-retries"+backFix) + assert.Equal(t, v.LoadBalance, "test-lb"+backFix) + } + assert.Equal(t, serviceConfig.Protocol, "test-protocol") + assert.Equal(t, serviceConfig.Registry, "test-registry") + assert.Equal(t, serviceConfig.Warmup, "test-warmup") +} + +func TestNewReferenceConfigByAPI(t *testing.T) { + refConfig := NewReferenceConfigByAPI( + WithReferenceCluster("test-cluster"), + WithReferenceInterface("test-interface"), + WithReferenceMethod("test-method1", "test-retries1", "test-lb1"), + WithReferenceMethod("test-method2", "test-retries2", "test-lb2"), + WithReferenceMethod("test-method3", "test-retries3", "test-lb3"), + WithReferenceProtocol("test-protocol"), + WithReferenceRegistry("test-registry"), + ) + assert.Equal(t, refConfig.Cluster, "test-cluster") + assert.Equal(t, refConfig.InterfaceName, "test-interface") + for i, v := range refConfig.Methods { + backFix := strconv.Itoa(i + 1) + assert.Equal(t, v.Name, "test-method"+backFix) + assert.Equal(t, v.Retries, "test-retries"+backFix) + assert.Equal(t, v.LoadBalance, "test-lb"+backFix) + } + assert.Equal(t, refConfig.Protocol, "test-protocol") + assert.Equal(t, refConfig.Registry, "test-registry") +} + +func TestNewRegistryConfig(t *testing.T) { + regConfig := NewRegistryConfig( + WithRegistryTimeOut("test-timeout"), + WithRegistryProtocol("test-protocol"), + WithRegistryGroup("test-group"), + WithRegistryAddress("test-address"), + WithRegistrySimplified(true), + WithRegistryUserName("test-username"), + WithRegistryPassword("test-password"), + ) + assert.Equal(t, regConfig.TimeoutStr, "test-timeout") + assert.Equal(t, regConfig.Protocol, "test-protocol") + assert.Equal(t, regConfig.Group, "test-group") + assert.Equal(t, regConfig.Address, "test-address") + assert.Equal(t, regConfig.Simplified, true) + assert.Equal(t, regConfig.Username, "test-username") + assert.Equal(t, regConfig.Password, "test-password") +} + +func TestNewConsumerConfig(t *testing.T) { + referConfig := NewReferenceConfigByAPI( + WithReferenceCluster("test-cluster"), + WithReferenceInterface("test-interface"), + WithReferenceMethod("test-method1", "test-retries1", "test-lb1"), + WithReferenceMethod("test-method2", "test-retries2", "test-lb2"), + WithReferenceMethod("test-method3", "test-retries3", "test-lb3"), + WithReferenceProtocol("test-protocol"), + WithReferenceRegistry("test-registry"), + ) + defaultZKRegistry := NewDefaultRegistryConfig("zookeeper") + assert.Equal(t, defaultZKRegistry.Address, defaultZKAddr) + assert.Equal(t, defaultZKRegistry.Protocol, "zookeeper") + assert.Equal(t, defaultZKRegistry.TimeoutStr, defaultRegistryTimeout) + + consumerConfig := NewConsumerConfig( + WithConsumerConfigCheck(true), + WithConsumerConnTimeout(time.Minute), + WithConsumerRequestTimeout(time.Hour), + WithConsumerReferenceConfig("UserProvider", referConfig), + WithConsumerRegistryConfig("demoZK", defaultZKRegistry), + ) + + assert.Equal(t, *consumerConfig.Check, true) + assert.Equal(t, consumerConfig.ConnectTimeout, time.Minute) + assert.Equal(t, consumerConfig.RequestTimeout, time.Hour) + assert.Equal(t, consumerConfig.Registries["demoZK"], defaultZKRegistry) + assert.Equal(t, consumerConfig.References["UserProvider"], referConfig) +} + +func TestNewProviderConfig(t *testing.T) { + serviceConfig := NewServiceConfigByAPI( + WithServiceCluster("test-cluster"), + WithServiceInterface("test-interface"), + WithServiceLoadBalance("test-loadbalance"), + WithServiceMethod("test-method1", "test-retries1", "test-lb1"), + WithServiceMethod("test-method2", "test-retries2", "test-lb2"), + WithServiceMethod("test-method3", "test-retries3", "test-lb3"), + WithServiceProtocol("test-protocol"), + WithServiceRegistry("test-registry"), + WithServiceWarmUpTime("test-warmup"), + ) + + defaultConsulRegistry := NewDefaultRegistryConfig("consul") + assert.Equal(t, defaultConsulRegistry.Address, defaultConsulAddr) + assert.Equal(t, defaultConsulRegistry.Protocol, "consul") + assert.Equal(t, defaultConsulRegistry.TimeoutStr, defaultRegistryTimeout) + + defaultNacosRegistry := NewDefaultRegistryConfig("nacos") + assert.Equal(t, defaultNacosRegistry.Address, defaultNacosAddr) + assert.Equal(t, defaultNacosRegistry.Protocol, "nacos") + assert.Equal(t, defaultNacosRegistry.TimeoutStr, defaultRegistryTimeout) + + providerConfig := NewProviderConfig( + WithProviderServices("UserProvider", serviceConfig), + WithProviderProtocol("dubbo", "dubbo", "20000"), + WithProviderRegistry("demoConsul", defaultConsulRegistry), + WithProviderRegistry("demoNacos", defaultNacosRegistry), + ) + + assert.NotNil(t, providerConfig.Services) + for k, v := range providerConfig.Services { + assert.Equal(t, k, "UserProvider") + assert.Equal(t, v, serviceConfig) + } + assert.NotNil(t, providerConfig.Registries) + i := 0 + for k, v := range providerConfig.Registries { + if i == 0 { + assert.Equal(t, k, "demoConsul") + assert.Equal(t, v, defaultConsulRegistry) + i++ + } else { + assert.Equal(t, k, "demoNacos") + assert.Equal(t, v, defaultNacosRegistry) + } + } + + assert.NotNil(t, providerConfig.Protocols) + assert.Equal(t, providerConfig.Protocols["dubbo"].Name, "dubbo") + assert.Equal(t, providerConfig.Protocols["dubbo"].Port, "20000") +} -- GitLab