From b7be5213d6cddf0eeb8f9a5d09e534cf7265d484 Mon Sep 17 00:00:00 2001 From: tian Date: Tue, 21 Jan 2020 17:16:16 +0800 Subject: [PATCH] refactor remote source API --- README.md | 19 +++++------ archaius.go | 32 +++++------------ archaius_test.go | 7 +--- options.go | 12 +++---- pkg/configcenter/client.go | 2 +- remote.go | 30 ++++++++++++++++ remote_test.go | 28 +++++++++++++++ source/remote/client.go | 6 ++-- .../{remote.go => config_center_source.go} | 34 ++++++++++++++----- ...e_test.go => config_center_source_test.go} | 31 +++++------------ 10 files changed, 120 insertions(+), 81 deletions(-) create mode 100644 remote.go create mode 100644 remote_test.go rename source/remote/{remote.go => config_center_source.go} (88%) rename source/remote/{remote_test.go => config_center_source_test.go} (83%) diff --git a/README.md b/README.md index e1ba86aa..9fbca1e5 100755 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ and you can use archaius API to get its value Here is the precedence list: -0: remote source - use [config client](https://github.com/go-chassis/go-chassis-config) to pull remote config server data into local +0: remote source - pull remote config server data into local -1: Memory source - after process start, you can set key value in runtime. +1: Memory source - after init, you can set key value in runtime. 2: Command Line source - read the command lines arguments, while starting the process. @@ -107,24 +107,24 @@ v := archaius.GetString("/etc/component/xxx.txt", "") ``` ### Enable remote source -import a config client implementation +Before you enable a remote source, you must install a implementation first ```go -import _ "github.com/go-chassis/go-archaius/source/remote/configcenter" +archaius.InstallRemoteSource("config_center", remote.NewConfigCenterSource) ``` -set config client to init config center source +set remote info to init remote source ```go - ci := archaius.RemoteInfo{ + ri := archaius.RemoteInfo{ //input your remote source config } //create config client - cc,_:=remote.NewClient("config_center",ccclient.Options{ + cc,_:=remote.NewClient("config-center",ccclient.Options{ ServerURI:"the address of config server endpoint", }) //manage local and remote key value at same time err = archaius.Init( archaius.WithRequiredFiles([]string{filename1}), archaius.WithOptionalFiles([]string{filename2}), - archaius.WithRemoteSource(ci, cc), + archaius.WithRemoteSource("config-center", ri), ) ``` @@ -132,8 +132,7 @@ Supported distributed configuration management service: | name | import |description | |----------|----------|:-------------:| -|config_center |github.com/go-chassis/go-chassis-config/configcenter |huawei cloud CSE config center https://www.huaweicloud.com/product/cse.html | -|servicecomb-kie |github.com/apache/servicecomb-kie/client/adaptor |apache servicecomb-kie https://github.com/apache/servicecomb-kie | +|config center |github.com/go-chassis/go-archaius/configcenter |huawei cloud CSE config center https://www.huaweicloud.com/product/cse.html | ### Example: Manage local configurations Complete [example](https://github.com/go-chassis/go-archaius/tree/master/examples/file) diff --git a/archaius.go b/archaius.go index a68b9ce3..051ac190 100755 --- a/archaius.go +++ b/archaius.go @@ -4,17 +4,16 @@ package archaius import ( "errors" - "github.com/go-chassis/go-archaius/cast" "os" "strings" + "github.com/go-chassis/go-archaius/cast" "github.com/go-chassis/go-archaius/event" "github.com/go-chassis/go-archaius/source" "github.com/go-chassis/go-archaius/source/cli" "github.com/go-chassis/go-archaius/source/env" "github.com/go-chassis/go-archaius/source/file" "github.com/go-chassis/go-archaius/source/mem" - "github.com/go-chassis/go-archaius/source/remote" "github.com/go-mesh/openlogging" ) @@ -76,8 +75,8 @@ func Init(opts ...Option) error { return err } - if o.RemoteInfo != nil { - if err = EnableRemoteSource(o.RemoteInfo, o.ConfigClient); err != nil { + if o.RemoteSource != "" { + if err = EnableRemoteSource(o.RemoteSource, o.RemoteInfo); err != nil { return err } } @@ -124,7 +123,7 @@ func CustomInit(sources ...source.ConfigSource) error { //EnableRemoteSource create a remote source singleton //A config center source pull remote config server key values into local memory //so that you can use GetXXX to get value easily -func EnableRemoteSource(ci *RemoteInfo, cc remote.Client) error { +func EnableRemoteSource(remoteSource string, ci *RemoteInfo) error { if ci == nil { return errors.New("RemoteInfo can not be empty") } @@ -133,28 +132,15 @@ func EnableRemoteSource(ci *RemoteInfo, cc remote.Client) error { return nil } - var err error - if cc == nil { - opts := remote.Options{ - ServerURI: ci.URL, - TenantName: ci.TenantName, - EnableSSL: ci.EnableSSL, - TLSConfig: ci.TLSConfig, - RefreshPort: ci.RefreshPort, - AutoDiscovery: ci.AutoDiscovery, - Labels: ci.DefaultDimension, - } - cc, err = remote.NewClient(ci.ClientType, opts) - if err != nil { - return err - } + f, ok := newFuncMap[remoteSource] + if !ok { + return errors.New("don not support remote source: " + remoteSource) } - configCenterSource := remote.NewConfigCenterSource(cc, ci.RefreshMode, - ci.RefreshInterval) - err = manager.AddSource(configCenterSource) + s, err := f(ci) if err != nil { return err } + err = manager.AddSource(s) configServerRunning = true return nil } diff --git a/archaius_test.go b/archaius_test.go index ab71bfb7..aa777557 100755 --- a/archaius_test.go +++ b/archaius_test.go @@ -145,11 +145,7 @@ metadata: } func TestInitConfigCenter(t *testing.T) { - err := archaius.EnableRemoteSource(&archaius.RemoteInfo{}, nil) - assert.Error(t, err) - err = archaius.EnableRemoteSource(&archaius.RemoteInfo{ - ClientType: "fake", - }, nil) + err := archaius.EnableRemoteSource("fake", nil) assert.Error(t, err) } func TestClean(t *testing.T) { @@ -157,5 +153,4 @@ func TestClean(t *testing.T) { assert.NoError(t, err) s := archaius.Get("age") assert.Equal(t, nil, s) - } diff --git a/options.go b/options.go index 7c27f630..a4fb4cda 100644 --- a/options.go +++ b/options.go @@ -2,7 +2,6 @@ package archaius import ( "crypto/tls" - "github.com/go-chassis/go-archaius/source/remote" "github.com/go-chassis/go-archaius/source/util" ) @@ -41,7 +40,7 @@ type Options struct { OptionalFiles []string FileHandler util.FileHandler RemoteInfo *RemoteInfo - ConfigClient remote.Client + RemoteSource string UseCLISource bool UseENVSource bool UseMemSource bool @@ -72,14 +71,11 @@ func WithDefaultFileHandler(handler util.FileHandler) Option { } } -//WithRemoteSource accept the information for initiating a config center source, -//RemoteInfo is required if you want to use config center source -//client is optional,if client is nil, archaius will create one based on RemoteInfo -//config client will be injected into config source as a client to interact with a config server -func WithRemoteSource(ri *RemoteInfo, c remote.Client) Option { +//WithRemoteSource accept the information for initiating a remote source +func WithRemoteSource(provider string, ri *RemoteInfo) Option { return func(options *Options) { options.RemoteInfo = ri - options.ConfigClient = c + options.RemoteSource = provider } } diff --git a/pkg/configcenter/client.go b/pkg/configcenter/client.go index e6692560..a4be2b46 100644 --- a/pkg/configcenter/client.go +++ b/pkg/configcenter/client.go @@ -72,7 +72,7 @@ var ( environmentConfig = "" ) -//Client is a struct +//c is a struct type Client struct { opts Options sync.RWMutex diff --git a/remote.go b/remote.go new file mode 100644 index 00000000..a6fda3b5 --- /dev/null +++ b/remote.go @@ -0,0 +1,30 @@ +/* + * 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 archaius + +import "github.com/go-chassis/go-archaius/source" + +var newFuncMap = make(map[string]NewRemoteSource) + +//NewRemoteSource create a new remote source +type NewRemoteSource func(info *RemoteInfo) (source.ConfigSource, error) + +//InstallRemoteSource allow user customize remote source +func InstallRemoteSource(source string, remoteSource NewRemoteSource) { + newFuncMap[source] = remoteSource +} diff --git a/remote_test.go b/remote_test.go new file mode 100644 index 00000000..be182559 --- /dev/null +++ b/remote_test.go @@ -0,0 +1,28 @@ +/* + * 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 archaius_test + +import ( + "github.com/go-chassis/go-archaius" + "github.com/go-chassis/go-archaius/source/remote" + "testing" +) + +func TestInstallRemoteSource(t *testing.T) { + archaius.InstallRemoteSource("config_center", remote.NewConfigCenterSource) +} diff --git a/source/remote/client.go b/source/remote/client.go index a777cbe7..fcebcdee 100644 --- a/source/remote/client.go +++ b/source/remote/client.go @@ -25,15 +25,15 @@ func InstallConfigClientPlugin(name string, f func(options Options) (Client, err openlogging.GetLogger().Infof("Installed %s Plugin", name) } -//Client is the interface of config server client, it has basic func to interact with config server +//c is the interface of config server client, it has basic func to interact with config server type Client interface { //PullConfigs pull all configs from remote PullConfigs(labels ...map[string]string) (map[string]interface{}, error) //PullConfig pull one config from remote PullConfig(key, contentType string, labels map[string]string) (interface{}, error) - // PushConfigs push config to cc + // PushConfigs push config to c PushConfigs(data map[string]interface{}, labels map[string]string) (map[string]interface{}, error) - // DeleteConfigsByKeys delete config for cc by keys + // DeleteConfigsByKeys delete config for c by keys DeleteConfigsByKeys(keys []string, labels map[string]string) (map[string]interface{}, error) //Watch get kv change results, you can compare them with local kv cache and refresh local cache Watch(f func(map[string]interface{}), errHandler func(err error), labels map[string]string) error diff --git a/source/remote/remote.go b/source/remote/config_center_source.go similarity index 88% rename from source/remote/remote.go rename to source/remote/config_center_source.go index d2759126..1a64f7c7 100755 --- a/source/remote/remote.go +++ b/source/remote/config_center_source.go @@ -19,6 +19,7 @@ package remote import ( "errors" + "github.com/go-chassis/go-archaius" "reflect" "sync" "time" @@ -38,7 +39,7 @@ const ( //Source handles configs from config center type Source struct { - cc Client + c Client connsLock sync.Mutex @@ -58,14 +59,28 @@ type Source struct { } //NewConfigCenterSource initializes all components of configuration center -func NewConfigCenterSource(cc Client, refreshMode, refreshInterval int) source.ConfigSource { +func NewConfigCenterSource(ci *archaius.RemoteInfo) (source.ConfigSource, error) { + opts := Options{ + ServerURI: ci.URL, + TenantName: ci.TenantName, + EnableSSL: ci.EnableSSL, + TLSConfig: ci.TLSConfig, + RefreshPort: ci.RefreshPort, + AutoDiscovery: ci.AutoDiscovery, + Labels: ci.DefaultDimension, + } + cc, err := NewClient(ci.ClientType, opts) + if err != nil { + openlogging.Error(err.Error()) + return nil, err + } s := new(Source) s.dimensions = []map[string]string{cc.Options().Labels} s.priority = configCenterSourcePriority - s.cc = cc - s.RefreshMode = refreshMode - s.RefreshInterval = time.Second * time.Duration(refreshInterval) - return s + s.c = cc + s.RefreshMode = ci.RefreshMode + s.RefreshInterval = time.Second * time.Duration(ci.RefreshInterval) + return s, nil } //GetConfigurations pull config from remote and start refresh configs interval @@ -106,7 +121,7 @@ func (rs *Source) refreshConfigurations() error { events []*event.Event ) - config, err = rs.cc.PullConfigs(rs.dimensions...) + config, err = rs.c.PullConfigs(rs.dimensions...) if err != nil { openlogging.GetLogger().Warnf("Failed to pull configurations from config center server", err) //Warn return err @@ -175,7 +190,7 @@ func (rs *Source) Watch(callback source.EventHandler) error { // Pull All the configuration for the first time. rs.refreshConfigurations() //Start watch and receive change events. - err := rs.cc.Watch( + err := rs.c.Watch( func(kv map[string]interface{}) { events, err := rs.populateEvents(kv) if err != nil { @@ -257,3 +272,6 @@ func (rs *Source) Set(key string, value interface{}) error { func (rs *Source) Delete(key string) error { return nil } +func init() { + archaius.InstallRemoteSource("config-center", NewConfigCenterSource) +} diff --git a/source/remote/remote_test.go b/source/remote/config_center_source_test.go similarity index 83% rename from source/remote/remote_test.go rename to source/remote/config_center_source_test.go index f65f3578..eaf2433f 100755 --- a/source/remote/remote_test.go +++ b/source/remote/config_center_source_test.go @@ -1,13 +1,14 @@ package remote_test import ( + "errors" + "github.com/go-chassis/go-archaius" "github.com/go-chassis/go-archaius/event" "github.com/go-chassis/go-archaius/source/remote" + _ "github.com/go-chassis/go-archaius/source/remote/configcenter" "github.com/stretchr/testify/assert" - "time" - - "errors" "testing" + "time" ) type mockClient struct { @@ -81,33 +82,19 @@ func (ccenter *EventHandler) OnEvent(event *event.Event) { } func TestNewConfigCenterSource(t *testing.T) { - opts := remote.Options{ - Labels: map[string]string{ + opts := &archaius.RemoteInfo{ + DefaultDimension: map[string]string{ "app": "default", "serviceName": "cart", }, TenantName: "default", - ServerURI: "http://", + URL: "http://", + ClientType: "mock-client", } - cc, err := remote.NewClient("mock-client", opts) + ccs, err := remote.NewConfigCenterSource(opts) assert.NoError(t, err) - ccs := remote.NewConfigCenterSource(cc, 1, - 1) - configs, err := ccs.GetConfigurations() assert.NoError(t, err) assert.Equal(t, true, configs["some.enable"]) - eh := new(EventHandler) - - _ = ccs.Watch(eh) - _, _ = cc.PushConfigs(map[string]interface{}{ - "some.enable": true, - "some": "new", - }, nil) - - time.Sleep(2 * time.Second) - configs, err = ccs.GetConfigurations() - assert.NoError(t, err) - assert.Equal(t, "new", configs["some"]) }