Skip to content
Snippets Groups Projects
Commit f5bc9ed0 authored by vito.he's avatar vito.he Committed by GitHub
Browse files

Merge branch 'feature/dubbo-2.7.5' into develop

parents 8394c305 2e0d7102
No related branches found
No related tags found
No related merge requests found
Showing
with 473 additions and 36 deletions
......@@ -131,6 +131,7 @@ const (
ProviderConfigPrefix = "dubbo.provider."
ConsumerConfigPrefix = "dubbo.consumer."
ShutdownConfigPrefix = "dubbo.shutdown."
MetadataReportPrefix = "dubbo.metadata-report."
RouterConfigPrefix = "dubbo.router."
)
......@@ -214,6 +215,19 @@ const (
SECRET_ACCESS_KEY_KEY = "secretAccessKey"
)
// metadata report
const (
METACONFIG_REMOTE = "remote"
METACONFIG_LOCAL = "local"
KEY_SEPARATOR = ":"
DEFAULT_PATH_TAG = "metadata"
KEY_REVISON_PREFIX = "revision"
// metadata service
METADATA_SERVICE_NAME = "org.apache.dubbo.metadata.MetadataService"
)
// HealthCheck Router
const (
// The key of HealthCheck SPI
......@@ -235,3 +249,9 @@ const (
// The default time window of circuit-tripped in millisecond if not specfied
MAX_CIRCUIT_TRIPPED_TIMEOUT_IN_MS = 30000
)
// service discovery
const (
NACOS_GROUP = "nacos.group"
)
/*
* 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 extension
import (
"github.com/apache/dubbo-go/metadata"
)
var (
metaDataReportFactories = make(map[string]func() metadata.MetadataReportFactory, 8)
)
// SetMetadataReportFactory ...
func SetMetadataReportFactory(name string, v func() metadata.MetadataReportFactory) {
metaDataReportFactories[name] = v
}
// GetMetadataReportFactory ...
func GetMetadataReportFactory(name string) metadata.MetadataReportFactory {
if metaDataReportFactories[name] == nil {
panic("metadata report for " + name + " is not existing, make sure you have import the package.")
}
return metaDataReportFactories[name]()
}
/*
* 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 extension
import (
perrors "github.com/pkg/errors"
)
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/registry"
)
var (
discoveryCreatorMap = make(map[string]func(url *common.URL) (registry.ServiceDiscovery, error), 4)
)
// SetServiceDiscovery will store the creator and name
func SetServiceDiscovery(name string, creator func(url *common.URL) (registry.ServiceDiscovery, error)) {
discoveryCreatorMap[name] = creator
}
// GetServiceDiscovery will return the registry.ServiceDiscovery
// if not found, or initialize instance failed, it will return error.
func GetServiceDiscovery(name string, url *common.URL) (registry.ServiceDiscovery, error) {
creator, ok := discoveryCreatorMap[name]
if !ok {
return nil, perrors.New("Could not find the service discovery with name: " + name)
}
return creator(url)
}
......@@ -33,6 +33,7 @@ type ApplicationConfig struct {
Version string `yaml:"version" json:"version,omitempty" property:"version"`
Owner string `yaml:"owner" json:"owner,omitempty" property:"owner"`
Environment string `yaml:"environment" json:"environment,omitempty" property:"environment"`
MetadataType string `default:"local" yaml:"metadataType" json:"metadataType,omitempty" property:"metadataType"` //field for metadata report
}
// Prefix ...
......
......@@ -44,6 +44,7 @@ type ConsumerConfig struct {
Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
// application
ApplicationConfig *ApplicationConfig `yaml:"application" json:"application,omitempty" property:"application"`
// client
Connect_Timeout string `default:"100ms" yaml:"connect_timeout" json:"connect_timeout,omitempty" property:"connect_timeout"`
ConnectTimeout time.Duration
......@@ -117,6 +118,7 @@ func ConsumerInit(confConFile string) error {
return perrors.WithMessagef(err, "time.ParseDuration(Connect_Timeout{%#v})", consumerConfig.Connect_Timeout)
}
}
logger.Debugf("consumer config{%#v}\n", consumerConfig)
return nil
......
/*
* 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 instance
import (
"sync"
)
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/extension"
"github.com/apache/dubbo-go/metadata"
)
var (
instance metadata.MetadataReport
once sync.Once
)
// GetMetadataReportInstance ...
func GetMetadataReportInstance(url *common.URL) metadata.MetadataReport {
once.Do(func() {
instance = extension.GetMetadataReportFactory(url.Protocol).CreateMetadataReport(url)
})
return instance
}
/*
* 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 (
"net/url"
)
import (
"github.com/creasty/defaults"
perrors "github.com/pkg/errors"
)
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/common/constant"
"github.com/apache/dubbo-go/config/instance"
)
// MethodConfig ...
type MetadataReportConfig struct {
Protocol string `required:"true" yaml:"protocol" json:"protocol,omitempty"`
Address string `yaml:"address" json:"address,omitempty" property:"address"`
Username string `yaml:"username" json:"username,omitempty" property:"username"`
Password string `yaml:"password" json:"password,omitempty" property:"password"`
Params map[string]string `yaml:"params" json:"params,omitempty" property:"params"`
TimeoutStr string `yaml:"timeout" default:"5s" json:"timeout,omitempty" property:"timeout"` // unit: second
Group string `yaml:"group" json:"group,omitempty" property:"group"`
}
// Prefix ...
func (c *MetadataReportConfig) Prefix() string {
return constant.MetadataReportPrefix
}
// UnmarshalYAML ...
func (c *MetadataReportConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
if err := defaults.Set(c); err != nil {
return perrors.WithStack(err)
}
type plain MetadataReportConfig
if err := unmarshal((*plain)(c)); err != nil {
return perrors.WithStack(err)
}
return nil
}
// ToUrl ...
func (c *MetadataReportConfig) ToUrl() (*common.URL, error) {
urlMap := make(url.Values)
if c.Params != nil {
for k, v := range c.Params {
urlMap.Set(k, v)
}
}
url, err := common.NewURL(c.Address,
common.WithParams(urlMap),
common.WithUsername(c.Username),
common.WithPassword(c.Password),
common.WithLocation(c.Address),
common.WithProtocol(c.Protocol),
)
if err != nil || len(url.Protocol) == 0 {
return nil, perrors.New("Invalid MetadataReportConfig.")
}
url.SetParam("metadata", url.Protocol)
return &url, nil
}
func (c *MetadataReportConfig) IsValid() bool {
return len(c.Protocol) != 0
}
// StartMetadataReport: The entry of metadata report start
func startMetadataReport(metadataType string, metadataReportConfig *MetadataReportConfig) error {
if metadataReportConfig == nil || metadataReportConfig.IsValid() {
return nil
}
if metadataType == constant.METACONFIG_REMOTE {
return perrors.New("No MetadataConfig found, you must specify the remote Metadata Center address when 'metadata=remote' is enabled.")
} else if metadataType == constant.METACONFIG_REMOTE && len(metadataReportConfig.Address) == 0 {
return perrors.New("MetadataConfig address can not be empty.")
}
if url, err := metadataReportConfig.ToUrl(); err == nil {
instance.GetMetadataReportInstance(url)
} else {
return perrors.New("MetadataConfig is invalid!")
}
return nil
}
package config
import "testing"
import (
"github.com/stretchr/testify/assert"
)
func TestMetadataReportConfig_ToUrl(t *testing.T) {
metadataReportConfig := MetadataReportConfig{
Protocol: "mock",
Address: "127.0.0.1:2181",
Username: "test",
Password: "test",
TimeoutStr: "3s",
Params: map[string]string{
"k": "v",
},
}
url, error := metadataReportConfig.ToUrl()
assert.NoError(t, error)
assert.Equal(t, "mock", url.Protocol)
assert.Equal(t, "127.0.0.1:2181", url.Location)
assert.Equal(t, "127.0.0.1", url.Ip)
assert.Equal(t, "2181", url.Port)
assert.Equal(t, "test", url.Username)
assert.Equal(t, "test", url.Password)
assert.Equal(t, "v", url.GetParam("k", ""))
assert.Equal(t, "mock", url.GetParam("metadata", ""))
}
......@@ -41,6 +41,8 @@ type ProviderConfig struct {
BaseConfig `yaml:",inline"`
Filter string `yaml:"filter" json:"filter,omitempty" property:"filter"`
ProxyFactory string `yaml:"proxy_factory" default:"default" json:"proxy_factory,omitempty" property:"proxy_factory"`
// metadata-report
MetadataReportConfig *MetadataReportConfig `yaml:"metadata_report" json:"metadata_report,omitempty" property:"metadata_report"`
ApplicationConfig *ApplicationConfig `yaml:"application" json:"application,omitempty" property:"application"`
Registry *RegistryConfig `yaml:"registry" json:"registry,omitempty" property:"registry"`
......@@ -95,7 +97,10 @@ func ProviderInit(confProFile string) error {
n.InterfaceId = k
}
}
//start the metadata report if config set
if err := startMetadataReport(providerConfig.ApplicationConfig.MetadataType, providerConfig.MetadataReportConfig); err != nil {
return perrors.WithMessagef(err, "Provider starts metadata report error, and the error is {%#v}", err)
}
logger.Debugf("provider config{%#v}\n", providerConfig)
return nil
......
......@@ -93,7 +93,7 @@ func loadRegistries(targetRegistries string, registries map[string]*RegistryConf
addresses := strings.Split(registryConf.Address, ",")
address := addresses[0]
address = traslateRegistryConf(address, registryConf)
address = translateRegistryConf(address, registryConf)
url, err = common.NewURL(constant.REGISTRY_PROTOCOL+"://"+address,
common.WithParams(registryConf.getUrlMap(roleType)),
common.WithUsername(registryConf.Username),
......@@ -127,7 +127,7 @@ func (c *RegistryConfig) getUrlMap(roleType common.RoleType) url.Values {
return urlMap
}
func traslateRegistryConf(address string, registryConf *RegistryConfig) string {
func translateRegistryConf(address string, registryConf *RegistryConfig) string {
if strings.Contains(address, "://") {
translatedUrl, err := url.Parse(address)
if err != nil {
......
......@@ -25,7 +25,8 @@ import (
)
import (
"github.com/pkg/errors"
gxset "github.com/dubbogo/gost/container/set"
perrors "github.com/pkg/errors"
"github.com/zouyx/agollo"
)
......@@ -119,7 +120,7 @@ func getNamespaceName(namespace string, configFileFormat agollo.ConfigFileFormat
func (c *apolloConfiguration) GetInternalProperty(key string, opts ...cc.Option) (string, error) {
config := agollo.GetConfig(c.appConf.NamespaceName)
if config == nil {
return "", errors.New(fmt.Sprintf("nothing in namespace:%s ", key))
return "", perrors.New(fmt.Sprintf("nothing in namespace:%s ", key))
}
return config.GetStringValue(key, ""), nil
}
......@@ -128,6 +129,16 @@ func (c *apolloConfiguration) GetRule(key string, opts ...cc.Option) (string, er
return c.GetInternalProperty(key, opts...)
}
// PublishConfig will publish the config with the (key, group, value) pair
func (c *apolloConfiguration) PublishConfig(string, string, string) error {
return perrors.New("unsupport operation")
}
// GetConfigKeysByGroup will return all keys with the group
func (c *apolloConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
return nil, perrors.New("unsupport operation")
}
func (c *apolloConfiguration) GetProperties(key string, opts ...cc.Option) (string, error) {
/**
* when group is not null, we are getting startup configs(config file) from Config Center, for example:
......@@ -135,7 +146,7 @@ func (c *apolloConfiguration) GetProperties(key string, opts ...cc.Option) (stri
*/
config := agollo.GetConfig(key)
if config == nil {
return "", errors.New(fmt.Sprintf("nothing in namespace:%s ", key))
return "", perrors.New(fmt.Sprintf("nothing in namespace:%s ", key))
}
return config.GetContent(agollo.Properties), nil
}
......
......@@ -21,14 +21,18 @@ import (
"time"
)
import (
gxset "github.com/dubbogo/gost/container/set"
)
import (
"github.com/apache/dubbo-go/common"
"github.com/apache/dubbo-go/config_center/parser"
)
//////////////////////////////////////////
// ////////////////////////////////////////
// DynamicConfiguration
//////////////////////////////////////////
// ////////////////////////////////////////
const (
// DEFAULT_GROUP: default group
DEFAULT_GROUP = "dubbo"
......@@ -42,14 +46,20 @@ type DynamicConfiguration interface {
SetParser(parser.ConfigurationParser)
AddListener(string, ConfigurationListener, ...Option)
RemoveListener(string, ConfigurationListener, ...Option)
//GetProperties get properties file
// GetProperties get properties file
GetProperties(string, ...Option) (string, error)
//GetRule get Router rule properties file
// GetRule get Router rule properties file
GetRule(string, ...Option) (string, error)
//GetInternalProperty get value by key in Default properties file(dubbo.properties)
// GetInternalProperty get value by key in Default properties file(dubbo.properties)
GetInternalProperty(string, ...Option) (string, error)
// PublishConfig will publish the config with the (key, group, value) pair
PublishConfig(string, string, string) error
// GetConfigKeysByGroup will return all keys with the group
GetConfigKeysByGroup(group string) (*gxset.HashSet, error)
}
// Options ...
......@@ -75,7 +85,7 @@ func WithTimeout(time time.Duration) Option {
}
}
//GetRuleKey The format is '{interfaceName}:[version]:[group]'
// GetRuleKey The format is '{interfaceName}:[version]:[group]'
func GetRuleKey(url common.URL) string {
return url.ColonSeparatedKey()
}
......@@ -22,6 +22,7 @@ import (
)
import (
gxset "github.com/dubbogo/gost/container/set"
"gopkg.in/yaml.v2"
)
......@@ -81,6 +82,16 @@ func (f *MockDynamicConfigurationFactory) GetDynamicConfiguration(_ *common.URL)
}
// PublishConfig will publish the config with the (key, group, value) pair
func (c *MockDynamicConfiguration) PublishConfig(string, string, string) error {
return nil
}
// GetConfigKeysByGroup will return all keys with the group
func (c *MockDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
return gxset.NewSet(c.content), nil
}
// MockDynamicConfiguration ...
type MockDynamicConfiguration struct {
parser parser.ConfigurationParser
......
......@@ -18,10 +18,12 @@
package nacos
import (
"strings"
"sync"
)
import (
gxset "github.com/dubbogo/gost/container/set"
"github.com/nacos-group/nacos-sdk-go/vo"
perrors "github.com/pkg/errors"
)
......@@ -74,7 +76,7 @@ func (n *nacosDynamicConfiguration) RemoveListener(key string, listener config_c
n.removeListener(key, listener)
}
//nacos distinguishes configuration files based on group and dataId. defalut group = "dubbo" and dataId = key
// GetProperties nacos distinguishes configuration files based on group and dataId. defalut group = "dubbo" and dataId = key
func (n *nacosDynamicConfiguration) GetProperties(key string, opts ...config_center.Option) (string, error) {
return n.GetRule(key, opts...)
}
......@@ -84,6 +86,33 @@ func (n *nacosDynamicConfiguration) GetInternalProperty(key string, opts ...conf
return n.GetProperties(key, opts...)
}
// PublishConfig will publish the config with the (key, group, value) pair
func (n *nacosDynamicConfiguration) PublishConfig(key string, group string, value string) error {
group = n.resolvedGroup(group)
ok, err := (*n.client.Client()).PublishConfig(vo.ConfigParam{
DataId: key,
Group: group,
Content: value,
})
if err != nil {
return perrors.WithStack(err)
}
if !ok {
return perrors.New("publish config to Nocos failed")
}
return nil
}
// GetConfigKeysByGroup will return all keys with the group
func (n *nacosDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
// TODO (the golang client of nacos does not support batch API)
// we should build a issue and then think about how to resolve this problem
return nil, perrors.New("unsupport operation, wait for implement")
}
// GetRule Get router rule
func (n *nacosDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
tmpOpts := &config_center.Options{}
......@@ -92,12 +121,12 @@ func (n *nacosDynamicConfiguration) GetRule(key string, opts ...config_center.Op
}
content, err := (*n.client.Client()).GetConfig(vo.ConfigParam{
DataId: key,
Group: tmpOpts.Group,
Group: n.resolvedGroup(tmpOpts.Group),
})
if err != nil {
return "", perrors.WithStack(err)
} else {
return string(content), nil
return content, nil
}
}
......@@ -145,6 +174,15 @@ func (n *nacosDynamicConfiguration) Destroy() {
n.closeConfigs()
}
// resolvedGroup will regular the group. Now, it will replace the '/' with '-'.
// '/' is a special character for nacos
func (n *nacosDynamicConfiguration) resolvedGroup(group string) string {
if len(group) <= 0 {
return group
}
return strings.ReplaceAll(group, "/", "-")
}
// IsAvailable Get available status
func (n *nacosDynamicConfiguration) IsAvailable() bool {
select {
......@@ -155,12 +193,12 @@ func (n *nacosDynamicConfiguration) IsAvailable() bool {
}
}
func (r *nacosDynamicConfiguration) closeConfigs() {
r.cltLock.Lock()
client := r.client
r.client = nil
r.cltLock.Unlock()
func (n *nacosDynamicConfiguration) closeConfigs() {
n.cltLock.Lock()
client := n.client
n.client = nil
n.cltLock.Unlock()
// Close the old client first to close the tmp node
client.Close()
logger.Infof("begin to close provider nacos client")
logger.Infof("begin to close provider n client")
}
......@@ -60,12 +60,7 @@ func runMockConfigServer(configHandler func(http.ResponseWriter, *http.Request),
func mockCommonNacosServer() *httptest.Server {
return runMockConfigServer(func(writer http.ResponseWriter, request *http.Request) {
data := `
dubbo.service.com.ikurento.user.UserProvider.cluster=failback
dubbo.service.com.ikurento.user.UserProvider.protocol=myDubbo1
dubbo.protocols.myDubbo.port=20000
dubbo.protocols.myDubbo.name=dubbo
`
data := "true"
fmt.Fprintf(writer, "%s", data)
}, func(writer http.ResponseWriter, request *http.Request) {
data := `dubbo.properties%02dubbo%02dubbo.service.com.ikurento.user.UserProvider.cluster=failback`
......@@ -93,6 +88,16 @@ func Test_GetConfig(t *testing.T) {
assert.NoError(t, err)
}
func TestNacosDynamicConfiguration_PublishConfig(t *testing.T) {
nacos, err := initNacosData(t)
assert.Nil(t, err)
key := "myKey"
group := "/custom/a/b"
value := "MyValue"
err = nacos.PublishConfig(key, group, value)
assert.Nil(t, err)
}
func Test_AddListener(t *testing.T) {
nacos, err := initNacosData(t)
assert.NoError(t, err)
......
......@@ -35,11 +35,11 @@ func callback(listener config_center.ConfigurationListener, namespace, group, da
listener.Process(&config_center.ConfigChangeEvent{Key: dataId, Value: data, ConfigType: remoting.EventTypeUpdate})
}
func (l *nacosDynamicConfiguration) addListener(key string, listener config_center.ConfigurationListener) {
_, loaded := l.keyListeners.Load(key)
func (n *nacosDynamicConfiguration) addListener(key string, listener config_center.ConfigurationListener) {
_, loaded := n.keyListeners.Load(key)
if !loaded {
_, cancel := context.WithCancel(context.Background())
err := (*l.client.Client()).ListenConfig(vo.ConfigParam{
err := (*n.client.Client()).ListenConfig(vo.ConfigParam{
DataId: key,
Group: "dubbo",
OnChange: func(namespace, group, dataId, data string) {
......@@ -49,14 +49,14 @@ func (l *nacosDynamicConfiguration) addListener(key string, listener config_cent
logger.Errorf("nacos : listen config fail, error:%v ", err)
newListener := make(map[config_center.ConfigurationListener]context.CancelFunc)
newListener[listener] = cancel
l.keyListeners.Store(key, newListener)
n.keyListeners.Store(key, newListener)
} else {
// TODO check goroutine alive, but this version of go_nacos_sdk is not support.
logger.Infof("profile:%s. this profile is already listening", key)
}
}
func (l *nacosDynamicConfiguration) removeListener(key string, listener config_center.ConfigurationListener) {
func (n *nacosDynamicConfiguration) removeListener(key string, listener config_center.ConfigurationListener) {
// TODO: not supported in current go_nacos_sdk version
logger.Warn("not supported in current go_nacos_sdk version")
}
......@@ -25,6 +25,7 @@ import (
import (
"github.com/dubbogo/go-zookeeper/zk"
gxset "github.com/dubbogo/gost/container/set"
perrors "github.com/pkg/errors"
)
......@@ -39,8 +40,9 @@ import (
const (
// ZkClient
//zookeeper client name
ZkClient = "zk config_center"
// zookeeper client name
ZkClient = "zk config_center"
pathSeparator = "/"
)
type zookeeperDynamicConfiguration struct {
......@@ -143,11 +145,39 @@ func (c *zookeeperDynamicConfiguration) GetProperties(key string, opts ...config
return string(content), nil
}
//For zookeeper, getConfig and getConfigs have the same meaning.
// GetInternalProperty For zookeeper, getConfig and getConfigs have the same meaning.
func (c *zookeeperDynamicConfiguration) GetInternalProperty(key string, opts ...config_center.Option) (string, error) {
return c.GetProperties(key, opts...)
}
// PublishConfig will put the value into Zk with specific path
func (c *zookeeperDynamicConfiguration) PublishConfig(key string, group string, value string) error {
path := c.getPath(key, group)
err := c.client.CreateWithValue(path, []byte(value))
if err != nil {
return perrors.WithStack(err)
}
return nil
}
// GetConfigKeysByGroup will return all keys with the group
func (c *zookeeperDynamicConfiguration) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) {
path := c.getPath("", group)
result, err := c.client.GetChildren(path)
if err != nil {
return nil, perrors.WithStack(err)
}
if len(result) == 0 {
return nil, perrors.New("could not find keys with group: " + group)
}
set := gxset.NewSet()
for _, e := range result {
set.Add(e)
}
return set, nil
}
func (c *zookeeperDynamicConfiguration) GetRule(key string, opts ...config_center.Option) (string, error) {
return c.GetProperties(key, opts...)
}
......@@ -214,3 +244,17 @@ func (c *zookeeperDynamicConfiguration) closeConfigs() {
func (c *zookeeperDynamicConfiguration) RestartCallBack() bool {
return true
}
func (c *zookeeperDynamicConfiguration) getPath(key string, group string) string {
if len(key) == 0 {
return c.buildPath(group)
}
return c.buildPath(group) + pathSeparator + key
}
func (c *zookeeperDynamicConfiguration) buildPath(group string) string {
if len(group) == 0 {
group = config_center.DEFAULT_GROUP
}
return c.rootPath + pathSeparator + group
}
......@@ -24,6 +24,7 @@ import (
import (
"github.com/dubbogo/go-zookeeper/zk"
gxset "github.com/dubbogo/gost/container/set"
"github.com/stretchr/testify/assert"
)
......@@ -156,6 +157,26 @@ func Test_RemoveListener(t *testing.T) {
assert.Equal(t, "", listener.event)
}
func TestZookeeperDynamicConfiguration_PublishConfig(t *testing.T) {
value := "Test Data"
customGroup := "Custom Group"
key := "myKey"
ts, zk := initZkData(config_center.DEFAULT_GROUP, t)
defer ts.Stop()
err := zk.PublishConfig(key, customGroup, value)
assert.Nil(t, err)
result, err := zk.GetInternalProperty("myKey", config_center.WithGroup(customGroup))
assert.Nil(t, err)
assert.Equal(t, value, result)
var keys *gxset.HashSet
keys, err = zk.GetConfigKeysByGroup(customGroup)
assert.Nil(t, err)
assert.Equal(t, 1, keys.Size())
assert.True(t, keys.Contains(key))
}
type mockDataListener struct {
wg sync.WaitGroup
event string
......
......@@ -38,7 +38,7 @@ require (
github.com/magiconair/properties v1.8.1
github.com/mitchellh/mapstructure v1.1.2
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb
github.com/nacos-group/nacos-sdk-go v0.0.0-20191128082542-fe1b325b125c
github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v1.1.0
......
......@@ -113,6 +113,8 @@ github.com/dubbogo/go-zookeeper v1.0.0/go.mod h1:fn6n2CAEer3novYgk9ULLwAjuV8/g4D
github.com/dubbogo/gost v1.5.1/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/dubbogo/gost v1.5.2 h1:ri/03971hdpnn3QeCU+4UZgnRNGDXLDGDucR/iozZm8=
github.com/dubbogo/gost v1.5.2/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/dubbogo/gost v1.7.0 h1:lWNBIE2hk1Aj2be2uXkyRTpZG0RQZj0/xbXnkIq6EHE=
github.com/dubbogo/gost v1.7.0/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/dubbogo/gost v1.8.0 h1:9ACbQe5OwMjqtinQcNJC5xp16kky27OsfSGw5L9A6vw=
github.com/dubbogo/gost v1.8.0/go.mod h1:pPTjVyoJan3aPxBPNUX0ADkXjPibLo+/Ib0/fADXSG8=
github.com/duosecurity/duo_api_golang v0.0.0-20190308151101-6c680f768e74 h1:2MIhn2R6oXQbgW5yHfS+d6YqyMfXiu2L55rFZC4UD/M=
......@@ -385,6 +387,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb h1:lbmvw8r9W55w+aQgWn35W1nuleRIECMoqUrmwAOAvoI=
github.com/nacos-group/nacos-sdk-go v0.0.0-20190723125407-0242d42e3dbb/go.mod h1:CEkSvEpoveoYjA81m4HNeYQ0sge0LFGKSEqO3JKHllo=
github.com/nacos-group/nacos-sdk-go v0.0.0-20191128082542-fe1b325b125c h1:WoCa3AvgQMVKNs+RIFlWPRgY9QVJwUxJDrGxHs0fcRo=
github.com/nacos-group/nacos-sdk-go v0.0.0-20191128082542-fe1b325b125c/go.mod h1:CEkSvEpoveoYjA81m4HNeYQ0sge0LFGKSEqO3JKHllo=
github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 h1:BQ1HW7hr4IVovMwWg0E0PYcyW8CzqDcVmaew9cujU4s=
github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk=
github.com/oklog/run v0.0.0-20180308005104-6934b124db28 h1:Hbr3fbVPXea52oPQeP7KLSxP52g6SFaNY1IqAmUyEW0=
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment