This is an automated email from the ASF dual-hosted git repository.

mark4z pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new bca3213f Feature/nacos config (#497)
bca3213f is described below

commit bca3213fc367bb4c8bdc5109190e2c445cbdca57
Author: Phil <[email protected]>
AuthorDate: Mon Oct 31 11:18:41 2022 +0800

    Feature/nacos config (#497)
    
    * uddapte: nacos config
    
    * Add: nacos config center
    
    * update: nacos config
    
    * add ut
    
    * fmt
    
    * clean code for CI
    
    * update: listen
    
    * Add go sum
    
    * update: fix config_center UT, ignore the cache and log dir
    
    * fix UT
    
    * update: off nacos_config_center UT
---
 .gitignore                       |   2 +
 cmd/pixiu/deployer.go            |  26 +++++++
 cmd/pixiu/gateway.go             |  24 ++-----
 cmd/pixiu/pixiu.go               |  50 ++++++++++++-
 configcenter/configclient.go     |  28 ++++++++
 configcenter/load.go             | 124 ++++++++++++++++++++++++++++++++
 configcenter/load_test.go        | 148 +++++++++++++++++++++++++++++++++++++++
 configcenter/nacos_load.go       | 137 ++++++++++++++++++++++++++++++++++++
 docs/sample/dubbo/dubbo-error.md |   2 +-
 go.mod                           |   2 +-
 pixiu/pkg/config/config_load.go  |  83 ++++++++++++++++++++++
 pixiu/pkg/model/bootstrap.go     |  54 ++++++++++++++
 pixiu/pkg/server/pixiu_start.go  |   1 -
 pkg/common/constant/log.go       |  23 ++++++
 14 files changed, 680 insertions(+), 24 deletions(-)

diff --git a/.gitignore b/.gitignore
index e283ccaa..dbda91fd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@ samples/dubbogo/simple/server/app/app
 /logs
 /.idea
 /.vscode
+.cache
+.log
 
 .DS_Store
 vendor/
diff --git a/cmd/pixiu/deployer.go b/cmd/pixiu/deployer.go
new file mode 100644
index 00000000..a21bcddc
--- /dev/null
+++ b/cmd/pixiu/deployer.go
@@ -0,0 +1,26 @@
+/*
+ * 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 main
+
+type Deployer interface {
+       initialize() error
+
+       start() error
+
+       stop() error
+}
diff --git a/cmd/pixiu/gateway.go b/cmd/pixiu/gateway.go
index 70a1a7d2..245bebc6 100644
--- a/cmd/pixiu/gateway.go
+++ b/cmd/pixiu/gateway.go
@@ -27,8 +27,6 @@ import (
 
 import (
        "github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/constant"
-       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
-       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/server"
 )
 
 var (
@@ -43,28 +41,18 @@ var (
                Version: Version,
                PreRun: func(cmd *cobra.Command, args []string) {
                        initDefaultValue()
-               },
-               Run: func(cmd *cobra.Command, args []string) {
-                       err := initLog()
-                       if err != nil {
-                               logger.Warnf("[startGatewayCmd] failed to init 
logger, %s", err.Error())
-                       }
 
-                       bootstrap, meta, err := initApiConfig()
+                       err := deploy.initialize()
                        if err != nil {
-                               if meta {
-                                       logger.Warnf("[startGatewayCmd] failed 
to get api meta config, %s", err.Error())
-                               } else {
-                                       logger.Errorf("[startGatewayCmd] failed 
to get api meta config, %s", err.Error())
-                               }
+                               panic(err)
                        }
+               },
+               Run: func(cmd *cobra.Command, args []string) {
 
-                       err = initLimitCpus()
+                       err := deploy.start()
                        if err != nil {
-                               logger.Errorf("[startCmd] failed to get limit 
cpu number, %s", err.Error())
+                               panic(err)
                        }
-
-                       server.Start(bootstrap)
                },
        }
 )
diff --git a/cmd/pixiu/pixiu.go b/cmd/pixiu/pixiu.go
index 8cefca74..78de4f5a 100644
--- a/cmd/pixiu/pixiu.go
+++ b/cmd/pixiu/pixiu.go
@@ -19,6 +19,7 @@ package main
 
 import (
        "fmt"
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/server"
        _ "net/http/pprof"
        "runtime"
        "strconv"
@@ -40,7 +41,7 @@ import (
 
 var (
        // Version pixiu version
-       Version = "0.3.0"
+       Version = "0.5.1"
 
        flagToLogLevel = map[string]string{
                "trace":    "TRACE",
@@ -65,6 +66,9 @@ var (
        initFromRemote = false
 )
 
+// deploy server deployment
+var deploy = &DefaultDeployer{}
+
 // main pixiu run method
 func main() {
        app := getRootCmd()
@@ -90,6 +94,42 @@ func getRootCmd() *cobra.Command {
        return rootCmd
 }
 
+type DefaultDeployer struct {
+       bootstrap    *model.Bootstrap
+       configManger *config.ConfigManager
+}
+
+func (d *DefaultDeployer) initialize() error {
+
+       err := initLog()
+       if err != nil {
+               logger.Warnf("[startGatewayCmd] failed to init logger, %s", 
err.Error())
+       }
+
+       // load Bootstrap config
+       d.bootstrap = d.configManger.LoadBootConfig(configPath)
+       if err != nil {
+               panic(fmt.Errorf("[startGatewayCmd] failed to get api meta 
config, %s", err.Error()))
+       }
+
+       err = initLimitCpus()
+       if err != nil {
+               logger.Errorf("[startCmd] failed to get limit cpu number, %s", 
err.Error())
+       }
+
+       return err
+}
+
+func (d *DefaultDeployer) start() error {
+       server.Start(d.bootstrap)
+       return nil
+}
+
+func (d *DefaultDeployer) stop() error {
+       //TODO implement me
+       panic("implement me")
+}
+
 // initDefaultValue If not set both in args and env, set default values
 func initDefaultValue() {
        if configPath == "" {
@@ -135,9 +175,9 @@ func initLog() error {
 }
 
 // initApiConfig return value of the bool is for the judgment of whether is a 
api meta data error, a kind of silly (?)
-func initApiConfig() (*model.Bootstrap, bool, error) {
+func initApiConfig() (*model.Bootstrap, error) {
        bootstrap := config.Load(configPath)
-       return bootstrap, false, nil
+       return bootstrap, nil
 }
 
 func initLimitCpus() error {
@@ -153,3 +193,7 @@ func initLimitCpus() error {
        logger.Infof("GOMAXPROCS set to %v", limitCpuNumber)
        return nil
 }
+
+func init() {
+       deploy.configManger = config.NewConfigManger()
+}
diff --git a/configcenter/configclient.go b/configcenter/configclient.go
new file mode 100644
index 00000000..37475ce4
--- /dev/null
+++ b/configcenter/configclient.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 configcenter
+
+type (
+       ConfigClient interface {
+               LoadConfig(properties map[string]interface{}) (string, error)
+
+               ListenConfig(properties map[string]interface{}) (err error)
+       }
+
+       ListenConfig func(data string)
+)
diff --git a/configcenter/load.go b/configcenter/load.go
new file mode 100644
index 00000000..e8e582bf
--- /dev/null
+++ b/configcenter/load.go
@@ -0,0 +1,124 @@
+/*
+ * 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 configcenter
+
+import (
+       "strings"
+)
+
+import (
+       "github.com/ghodss/yaml"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
+)
+
+const (
+       KEY_CONFIG_TYPE_NACOS = "nacos"
+)
+
+var Parsers = map[string]func(data []byte, v interface{}) error{
+       ".yaml": ParseYamlBytes,
+       ".yml":  ParseYamlBytes,
+}
+
+type (
+       Load interface {
+               LoadConfigs(boot *model.Bootstrap, opts ...Option) (v 
*model.Bootstrap, err error)
+       }
+
+       Option func(opt *Options)
+
+       Options struct {
+               Remote bool
+               DataId string
+               Group  string
+               path   string
+               parser string
+       }
+)
+
+type DefaultConfigLoad struct {
+       bootConfig   *model.Bootstrap
+       configClient ConfigClient
+}
+
+func NewConfigLoad(bootConfig *model.Bootstrap) *DefaultConfigLoad {
+
+       var configClient ConfigClient
+
+       // config center load
+       if strings.EqualFold(bootConfig.Config.Type, KEY_CONFIG_TYPE_NACOS) {
+               configClient, _ = NewNacosConfig(bootConfig)
+       }
+
+       if configClient == nil {
+               logger.Warnf("no remote config-center")
+               return nil
+       }
+
+       return &DefaultConfigLoad{
+               bootConfig:   bootConfig,
+               configClient: configClient,
+       }
+}
+
+func (d *DefaultConfigLoad) LoadConfigs(boot *model.Bootstrap, opts ...Option) 
(v *model.Bootstrap, err error) {
+
+       var opt Options
+       for _, o := range opts {
+               o(&opt)
+       }
+
+       if !opt.Remote {
+               return nil, nil
+       }
+
+       m := map[string]interface{}{}
+
+       if strings.EqualFold(boot.Config.Type, KEY_CONFIG_TYPE_NACOS) {
+               m["dataId"] = getOrDefault(opt.DataId, DataId)
+               m["group"] = getOrDefault(opt.Group, Group)
+       }
+
+       if len(m) == 0 {
+               logger.Errorf("no identify properties key when load from remote 
config center")
+               return boot, nil
+       }
+
+       data, err := d.configClient.LoadConfig(m)
+
+       if err != nil {
+               return nil, err
+       }
+
+       if len(data) == 0 {
+               logger.Errorf("the config data load from remote is nil, config 
center : %s", boot.Config.Type)
+               return boot, err
+       }
+
+       err = Parsers[".yml"]([]byte(data), boot)
+
+       return boot, err
+}
+
+func ParseYamlBytes(content []byte, v interface{}) error {
+       return yaml.Unmarshal(content, v)
+}
diff --git a/configcenter/load_test.go b/configcenter/load_test.go
new file mode 100644
index 00000000..1932dd4a
--- /dev/null
+++ b/configcenter/load_test.go
@@ -0,0 +1,148 @@
+/*
+ * 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 configcenter
+
+import (
+       "encoding/json"
+       "testing"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
+)
+
+func getBootstrap() *model.Bootstrap {
+
+       return &model.Bootstrap{
+               Config: &model.ConfigCenter{
+                       Type:   "nacos",
+                       Enable: "true",
+               },
+               Nacos: &model.Nacos{
+                       ServerConfigs: []*model.NacosServerConfig{
+                               {
+                                       IpAddr:      IpAddr,
+                                       Port:        Port,
+                                       Scheme:      Scheme,
+                                       ContextPath: ContextPath,
+                               },
+                       },
+                       ClientConfig: &model.NacosClientConfig{
+                               CacheDir:            "./.cache",
+                               LogDir:              "./.log",
+                               NotLoadCacheAtStart: true,
+                               NamespaceId:         Namespace,
+                       },
+                       DataId: DataId,
+                       Group:  Group,
+               },
+       }
+}
+
+func getNacosClient() ConfigClient {
+       config, _ := NewNacosConfig(getBootstrap())
+       return config
+}
+
+func TestDefaultConfigLoad_LoadConfigs(t *testing.T) {
+       type fields struct {
+               bootConfig   *model.Bootstrap
+               configClient ConfigClient
+       }
+       type args struct {
+               boot *model.Bootstrap
+               opts []Option
+       }
+       var tests = []struct {
+               name    string
+               fields  fields
+               args    args
+               wantV   *model.Bootstrap
+               wantErr bool
+       }{
+               {
+                       name: "Normal_NacosConfigLoadTest",
+                       fields: fields{
+                               bootConfig:   getBootstrap(),
+                               configClient: getNacosClient(),
+                       },
+                       args: args{
+                               boot: getBootstrap(),
+                               opts: []Option{func(opt *Options) {
+                                       opt.Remote = false // off
+                                       opt.DataId = DataId
+                                       opt.Group = Group
+                               }},
+                       },
+                       wantV:   nil,
+                       wantErr: false,
+               },
+               {
+                       name: "NilDataId_NacosConfigLoadTest",
+                       fields: fields{
+                               bootConfig:   getBootstrap(),
+                               configClient: getNacosClient(),
+                       },
+                       args: args{
+                               boot: getBootstrap(),
+                               opts: []Option{func(opt *Options) {
+                                       opt.Remote = false // off
+                                       opt.DataId = ""
+                                       opt.Group = Group
+                               }},
+                       },
+                       wantV:   nil,
+                       wantErr: false,
+               },
+               {
+                       name: "ErrorDataId_NacosConfigLoadTest",
+                       fields: fields{
+                               bootConfig:   getBootstrap(),
+                               configClient: getNacosClient(),
+                       },
+                       args: args{
+                               boot: getBootstrap(),
+                               opts: []Option{func(opt *Options) {
+                                       opt.Remote = false // off
+                                       opt.DataId = "ErrorDataId"
+                                       opt.Group = Group
+                               }},
+                       },
+                       wantV:   nil,
+                       wantErr: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       d := &DefaultConfigLoad{
+                               bootConfig:   tt.fields.bootConfig,
+                               configClient: tt.fields.configClient,
+                       }
+                       gotV, err := d.LoadConfigs(tt.args.boot, 
tt.args.opts...)
+                       if (err != nil) != tt.wantErr {
+                               t.Errorf("LoadConfigs() error = %v, wantErr 
%v", err, tt.wantErr)
+                               return
+                       }
+                       //assert.True(t, gotV.Nacos.DataId == DataId, "load 
config by nacos config center error!")
+                       //assert.True(t, len(gotV.StaticResources.Listeners) > 
0, "load config by nacos config center error!")
+                       conf, _ := json.Marshal(gotV)
+                       logger.Infof("config of Bootstrap load by nacos : %v", 
string(conf))
+               })
+       }
+}
diff --git a/configcenter/nacos_load.go b/configcenter/nacos_load.go
new file mode 100644
index 00000000..fb30da88
--- /dev/null
+++ b/configcenter/nacos_load.go
@@ -0,0 +1,137 @@
+/*
+ * 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 configcenter
+
+import (
+       "github.com/nacos-group/nacos-sdk-go/clients"
+       "github.com/nacos-group/nacos-sdk-go/clients/config_client"
+       "github.com/nacos-group/nacos-sdk-go/common/constant"
+       "github.com/nacos-group/nacos-sdk-go/vo"
+       "github.com/pkg/errors"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
+       "github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
+)
+
+const (
+       KeyDataId  = "dataId"
+       KeyGroup   = "group"
+       KeyContent = "content"
+       KeyTag     = "tag"
+       KeyAppName = "appName"
+       KeyTenant  = "tenant"
+)
+
+const (
+       DataId    = "pixiu.yaml"
+       Group     = "DEFAULT_GROUP"
+       Namespace = "dubbo-go-pixiu"
+
+       IpAddr      = "localhost"
+       ContextPath = "/nacos"
+       Port        = 8848
+       Scheme      = "http"
+)
+
+type (
+       NacosConfig struct {
+               client config_client.IConfigClient
+
+               // todo not support now
+               listenConfigCallback ListenConfig
+       }
+)
+
+func NewNacosConfig(boot *model.Bootstrap) (configClient ConfigClient, err 
error) {
+
+       var sc []constant.ServerConfig
+       if len(boot.Nacos.ServerConfigs) == 0 {
+               return nil, errors.New("no nacos server be setted")
+       }
+       for _, serveConfig := range boot.Nacos.ServerConfigs {
+               sc = append(sc, constant.ServerConfig{
+                       Port:   serveConfig.Port,
+                       IpAddr: serveConfig.IpAddr,
+               })
+       }
+
+       cc := constant.ClientConfig{
+               NamespaceId:         boot.Nacos.ClientConfig.NamespaceId,
+               TimeoutMs:           boot.Nacos.ClientConfig.TimeoutMs,
+               NotLoadCacheAtStart: 
boot.Nacos.ClientConfig.NotLoadCacheAtStart,
+               LogDir:              boot.Nacos.ClientConfig.LogDir,
+               CacheDir:            boot.Nacos.ClientConfig.CacheDir,
+               LogLevel:            boot.Nacos.ClientConfig.LogLevel,
+       }
+
+       pa := vo.NacosClientParam{
+               ClientConfig:  &cc,
+               ServerConfigs: sc,
+       }
+       nacos, err := clients.NewConfigClient(pa)
+       if err != nil {
+               return nil, err
+       }
+       configClient = &NacosConfig{
+               client: nacos,
+       }
+
+       return configClient, nil
+}
+
+func (n *NacosConfig) LoadConfig(param map[string]interface{}) (string, error) 
{
+
+       return n.client.GetConfig(vo.ConfigParam{
+               DataId: getOrDefault(param[KeyDataId].(string), DataId),
+               Group:  getOrDefault(param[KeyGroup].(string), Group),
+       })
+}
+
+func getOrDefault(target string, quiet string) string {
+       if len(target) == 0 {
+               target = quiet
+       }
+       return target
+}
+
+func (n *NacosConfig) ListenConfig(param map[string]interface{}) (err error) {
+       // todo noop, not support
+       if true {
+               return nil
+       }
+       listen := n.listen(getOrDefault(param[KeyDataId].(string), DataId), 
getOrDefault(param[KeyGroup].(string), Group))
+       return listen()
+}
+
+func (n *NacosConfig) listen(dataId, group string) func() error {
+       return func() error {
+               return n.client.ListenConfig(vo.ConfigParam{
+                       DataId: dataId,
+                       Group:  group,
+                       OnChange: func(namespace, group, dataId, data string) {
+                               if len(data) == 0 {
+                                       logger.Errorf("nacos listen callback 
data nil error ,  namespace : %s,group : %s , dataId : %s , data : %s")
+                                       return
+                               }
+                               n.listenConfigCallback(data)
+                       },
+               })
+       }
+}
diff --git a/docs/sample/dubbo/dubbo-error.md b/docs/sample/dubbo/dubbo-error.md
index 3fae4384..a9391cf5 100644
--- a/docs/sample/dubbo/dubbo-error.md
+++ b/docs/sample/dubbo/dubbo-error.md
@@ -32,7 +32,7 @@ Dubbo server return error:
 
 ```bash
 2020-11-17T11:19:18.019+0800    ERROR   remote/call.go:87       
[dubbo-go-pixiu] client call err:data is exist!
-github.com/apache/dubbo-go-pixiu/pkg/logger.Errorf
+github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger.Errorf
         
/Users/tc/Documents/workspace_2020/dubbo-go-pixiu/pkg/logger/logging.go:52
 github.com/apache/dubbo-go-pixiu/pkg/filter/remote.(*clientFilter).doRemoteCall
         
/Users/tc/Documents/workspace_2020/dubbo-go-pixiu/pkg/filter/remote/call.go:87
diff --git a/go.mod b/go.mod
index 328b5a56..dfedef12 100644
--- a/go.mod
+++ b/go.mod
@@ -62,6 +62,7 @@ require (
        github.com/hashicorp/go-multierror v1.1.1
        github.com/hashicorp/go-version v1.4.0
        github.com/hashicorp/golang-lru v0.5.4
+       github.com/imdario/mergo v0.3.12
        github.com/jhump/protoreflect v1.9.0
        github.com/kr/pretty v0.3.0
        github.com/kylelemons/godebug v1.1.0
@@ -216,7 +217,6 @@ require (
        github.com/hashicorp/errwrap v1.1.0 // indirect
        github.com/hashicorp/hcl v1.0.0 // indirect
        github.com/huandu/xstrings v1.3.2 // indirect
-       github.com/imdario/mergo v0.3.12 // indirect
        github.com/inconshreveable/mousetrap v1.0.0 // indirect
        github.com/jinzhu/copier v0.3.5 // indirect
        github.com/jmespath/go-jmespath v0.4.0 // indirect
diff --git a/pixiu/pkg/config/config_load.go b/pixiu/pkg/config/config_load.go
index 048fe391..94780286 100644
--- a/pixiu/pkg/config/config_load.go
+++ b/pixiu/pkg/config/config_load.go
@@ -21,6 +21,8 @@ import (
        "log"
        "os"
        "path/filepath"
+       "strings"
+       "sync"
 )
 
 import (
@@ -29,9 +31,12 @@ import (
        "github.com/ghodss/yaml"
 
        "github.com/goinggo/mapstructure"
+
+       "github.com/imdario/mergo"
 )
 
 import (
+       "github.com/apache/dubbo-go-pixiu/configcenter"
        "github.com/apache/dubbo-go-pixiu/pixiu/pkg/common/constant"
        "github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
        "github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
@@ -41,6 +46,9 @@ var (
        configPath     string
        config         *model.Bootstrap
        configLoadFunc LoadFunc = LoadYAMLConfig
+
+       configCenterType map[string]interface{}
+       once             sync.Once
 )
 
 // LoadFunc ConfigLoadFunc parse a input(usually file path) into a pixiu config
@@ -175,3 +183,78 @@ func GetDiscoveryType(cfg *model.Bootstrap) (err error) {
        }
        return nil
 }
+
+type ConfigManager struct {
+       path         string
+       localConfig  *model.Bootstrap
+       remoteConfig *model.Bootstrap
+       load         configcenter.Load
+}
+
+func NewConfigManger() *ConfigManager {
+       return &ConfigManager{}
+}
+
+func (m *ConfigManager) LoadBootConfig(path string) *model.Bootstrap {
+
+       var configs *model.Bootstrap
+
+       // load file
+       configs = m.loadLocalBootConfigs(path)
+
+       if strings.EqualFold(m.localConfig.Config.Enable, "true") {
+               configs = m.loadRemoteBootConfigs()
+       }
+
+       config = configs
+
+       err := m.check()
+
+       if err != nil {
+               logger.Errorf("[Pixiu-Config] check bootstrap config fail : 
%s", err.Error())
+               panic(err)
+       }
+
+       return configs
+}
+
+func (m *ConfigManager) loadLocalBootConfigs(path string) *model.Bootstrap {
+       m.localConfig = Load(path)
+       return m.localConfig
+}
+
+func (m *ConfigManager) loadRemoteBootConfigs() *model.Bootstrap {
+
+       bootstrap := m.localConfig
+
+       // load remote
+       once.Do(func() {
+               m.load = configcenter.NewConfigLoad(bootstrap)
+       })
+
+       configs, err := m.load.LoadConfigs(bootstrap, func(opt 
*configcenter.Options) {
+               opt.Remote = true
+       })
+
+       if err != nil {
+               panic(err)
+       }
+
+       err = mergo.Merge(configs, bootstrap, func(c *mergo.Config) {
+               c.Overwrite = false
+               c.AppendSlice = true
+       })
+
+       if err != nil {
+               panic(err)
+       }
+
+       m.remoteConfig = configs
+
+       return configs
+}
+
+func (m *ConfigManager) check() error {
+
+       return Adapter(config)
+}
diff --git a/pixiu/pkg/model/bootstrap.go b/pixiu/pkg/model/bootstrap.go
index 2b7fa5ee..0e94009c 100644
--- a/pixiu/pkg/model/bootstrap.go
+++ b/pixiu/pkg/model/bootstrap.go
@@ -33,6 +33,9 @@ type Bootstrap struct {
        Node             *Node             `yaml:"node" json:"node" 
mapstructure:"node"`
        Trace            *TracerConfig     `yaml:"tracing" json:"tracing" 
mapstructure:"tracing"`
        Wasm             *WasmConfig       `yaml:"wasm" json:"wasm" 
mapstructure:"wasm"`
+       Config           *ConfigCenter
+       // Third party dependency
+       Nacos *Nacos `yaml:"nacos" json:"nacos" mapstructure:"nacos"`
 }
 
 // Node node info for dynamic identifier
@@ -131,3 +134,54 @@ type TimeoutConfig struct {
        ConnectTimeoutStr string `default:"5s" yaml:"connect_timeout" 
json:"connect_timeout,omitempty"` // ConnectTimeout timeout for connect to 
cluster node
        RequestTimeoutStr string `default:"10s" yaml:"request_timeout" 
json:"request_timeout,omitempty"`
 }
+
+type Config struct {
+       Listeners      []*Listener      `yaml:"listeners" json:"listeners" 
mapstructure:"listeners"`
+       Clusters       []*ClusterConfig `yaml:"clusters" json:"clusters" 
mapstructure:"clusters"`
+       Adapters       []*Adapter       `yaml:"adapters" json:"adapters" 
mapstructure:"adapters"`
+       ShutdownConfig *ShutdownConfig  `yaml:"shutdown_config" 
json:"shutdown_config" mapstructure:"shutdown_config"`
+       PprofConf      PprofConf        `yaml:"pprofConf" json:"pprofConf" 
mapstructure:"pprofConf"`
+}
+
+type Nacos struct {
+       ServerConfigs []*NacosServerConfig `yaml:"server_configs" 
json:"server-configs" mapstructure:"server_configs"`
+       ClientConfig  *NacosClientConfig   `yaml:"client-config" 
json:"client-config" mapstructure:"client_config"`
+       DataId        string               `yaml:"data-id" json:"data-id" 
mapstructure:"data_id" default:"pixiu.yaml"`
+       Group         string               `yaml:"group" json:"group" 
mapstructure:"group" default:"DEFAULT_GROUP"`
+}
+
+type NacosServerConfig struct {
+       IpAddr      string `json:"ip_addr,omitempty" yaml:"ip_addr" 
mapstructure:"ip_addr"`
+       Port        uint64 `json:"port,omitempty" yaml:"port" 
mapstructure:"port"`
+       Scheme      string `json:"scheme" yaml:"scheme" mapstructure:"scheme"`
+       ContextPath string `json:"contextPath" yaml:"contextPath" 
mapstructure:"contextPath"`
+}
+
+type NacosClientConfig struct {
+       TimeoutMs            uint64 `json:"timeout_ms,omitempty" 
yaml:"timeout_ms" mapstructure:"timeout_ms"`                                    
    // timeout for requesting Nacos server, default value is 10000ms
+       ListenInterval       uint64 `json:"listen_interval,omitempty" 
yaml:"listen_interval" mapstructure:"listen_interval"`                         
// Deprecated
+       BeatInterval         int64  `json:"beat_interval,omitempty" 
yaml:"beat_interval" mapstructure:"beat_interval"`                              
 // the time interval for sending beat to server,default value is 5000ms
+       NamespaceId          string `json:"namespace_id,omitempty" 
yaml:"namespace_id" mapstructure:"namespace_id"`                                
  // the namespaceId of Nacos.When namespace is public, fill in the blank 
string here.
+       AppName              string `json:"app_name,omitempty" yaml:"app_name" 
mapstructure:"app_name"`                                              // the 
appName
+       Endpoint             string `json:"endpoint,omitempty" yaml:"endpoint" 
mapstructure:"endpoint"`                                              // the 
endpoint for get Nacos server addresses
+       RegionId             string `json:"region_id,omitempty" 
yaml:"region_id" mapstructure:"region_id"`                                      
     // the regionId for kms
+       AccessKey            string `json:"access_key,omitempty" 
yaml:"access_key" mapstructure:"access_key"`                                    
    // the AccessKey for kms
+       SecretKey            string `json:"secret_key,omitempty" 
yaml:"secret_key" mapstructure:"secret_key"`                                    
    // the SecretKey for kms
+       OpenKMS              bool   `json:"open_kms,omitempty" yaml:"open_kms" 
mapstructure:"open_kms"`                                              // it's 
to open kms,default is false. https://help.aliyun.com/product/28933.html
+       CacheDir             string `json:"cache_dir,omitempty" 
yaml:"cache_dir" mapstructure:"cache_dir" default:"/tmp/nacos/cache"`           
     // the directory for persist nacos service info,default value is current 
path
+       UpdateThreadNum      int    `json:"update_thread_num,omitempty" 
yaml:"update_thread_num" mapstructure:"update_thread_num"`                   // 
the number of gorutine for update nacos service info,default value is 20
+       NotLoadCacheAtStart  bool   `json:"not_load_cache_at_start,omitempty" 
yaml:"not_load_cache_at_start" mapstructure:"not_load_cache_at_start"` // not 
to load persistent nacos service info in CacheDir at start time
+       UpdateCacheWhenEmpty bool   `json:"update_cache_when_empty,omitempty" 
yaml:"update_cache_when_empty" mapstructure:"update_cache_when_empty"` // 
update cache when get empty service instance from server
+       Username             string `json:"username,omitempty" yaml:"username" 
mapstructure:"username"`                                              // the 
username for nacos auth
+       Password             string `json:"password,omitempty" yaml:"password" 
mapstructure:"password"`                                              // the 
password for nacos auth
+       LogDir               string `json:"log_dir,omitempty" yaml:"log_dir" 
mapstructure:"log_dir" default:"/tmp/nacos/log"`                        // the 
directory for log, default is current path
+       LogLevel             string `json:"log_level,omitempty" 
yaml:"log_level" mapstructure:"log_level"`                                      
     // the level of log, it's must be debug,info,warn,error, default value is 
info
+       //LogSampling          *ClientLogSamplingConfig // the sampling config 
of log
+       ContextPath string `json:"context_path,omitempty" yaml:"context_path" 
mapstructure:"context_path"` // the nacos server contextpath
+       //LogRollingConfig     *ClientLogRollingConfig  // the log rolling 
config
+}
+
+type ConfigCenter struct {
+       Type   string `json:"type,omitempty" yaml:"type"`
+       Enable string `json:"enable" yaml:"enable"`
+}
diff --git a/pixiu/pkg/server/pixiu_start.go b/pixiu/pkg/server/pixiu_start.go
index 07b729f8..8dbb76cc 100644
--- a/pixiu/pkg/server/pixiu_start.go
+++ b/pixiu/pkg/server/pixiu_start.go
@@ -90,7 +90,6 @@ func (s *Server) Start() {
        defer func() {
                if re := recover(); re != nil {
                        logger.Error(re)
-                       // TODO stop
                }
        }()
 
diff --git a/pkg/common/constant/log.go b/pkg/common/constant/log.go
new file mode 100644
index 00000000..54bb539c
--- /dev/null
+++ b/pkg/common/constant/log.go
@@ -0,0 +1,23 @@
+/*
+ * 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 constant
+
+// Log scene or topic
+const (
+       LogPixiu = "[Pixiu]"
+)

Reply via email to