2018-03-14 14:12:26 +08:00
|
|
|
// Copyright (C) 2014-2018 Goodrain Co., Ltd.
|
2017-11-07 11:40:44 +08:00
|
|
|
// RAINBOND, Application Management Platform
|
2018-03-14 14:33:31 +08:00
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version. For any non-GPL usage of Rainbond,
|
|
|
|
// one or multiple Commercial Licenses authorized by Goodrain Co., Ltd.
|
|
|
|
// must be obtained first.
|
2018-03-14 14:33:31 +08:00
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
2018-03-14 14:33:31 +08:00
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2017-11-08 21:39:51 +08:00
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/coreos/etcd/mvcc/mvccpb"
|
|
|
|
"github.com/pquerna/ffjson/ffjson"
|
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
"github.com/goodrain/rainbond/cmd/node/option"
|
2018-04-24 16:44:59 +08:00
|
|
|
"github.com/goodrain/rainbond/node/api/model"
|
|
|
|
"github.com/goodrain/rainbond/node/core/store"
|
|
|
|
"github.com/goodrain/rainbond/util"
|
2017-11-07 11:40:44 +08:00
|
|
|
|
|
|
|
"github.com/Sirupsen/logrus"
|
2017-11-08 21:39:51 +08:00
|
|
|
client "github.com/coreos/etcd/clientv3"
|
2017-11-07 11:40:44 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
//DataCenterConfig 数据中心配置
|
|
|
|
type DataCenterConfig struct {
|
|
|
|
config *model.GlobalConfig
|
|
|
|
options *option.Conf
|
2017-11-08 21:39:51 +08:00
|
|
|
ctx context.Context
|
|
|
|
cancel context.CancelFunc
|
2017-12-19 18:46:49 +08:00
|
|
|
//group config 不持久化
|
|
|
|
groupConfigs map[string]*GroupContext
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
|
|
|
|
2017-11-13 21:54:11 +08:00
|
|
|
var dataCenterConfig *DataCenterConfig
|
|
|
|
|
|
|
|
//GetDataCenterConfig 获取
|
|
|
|
func GetDataCenterConfig() *DataCenterConfig {
|
|
|
|
if dataCenterConfig == nil {
|
|
|
|
return CreateDataCenterConfig()
|
|
|
|
}
|
|
|
|
return dataCenterConfig
|
|
|
|
}
|
|
|
|
|
2017-11-07 11:40:44 +08:00
|
|
|
//CreateDataCenterConfig 创建
|
2017-11-13 21:54:11 +08:00
|
|
|
func CreateDataCenterConfig() *DataCenterConfig {
|
2017-11-08 21:39:51 +08:00
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
2017-11-13 21:54:11 +08:00
|
|
|
dataCenterConfig = &DataCenterConfig{
|
|
|
|
options: option.Config,
|
2017-11-08 21:39:51 +08:00
|
|
|
ctx: ctx,
|
|
|
|
cancel: cancel,
|
|
|
|
config: &model.GlobalConfig{
|
|
|
|
Configs: make(map[string]*model.ConfigUnit),
|
|
|
|
},
|
2017-12-19 18:46:49 +08:00
|
|
|
groupConfigs: make(map[string]*GroupContext),
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
2017-11-13 21:54:11 +08:00
|
|
|
res, err := store.DefalutClient.Get(dataCenterConfig.options.ConfigStoragePath+"/global", client.WithPrefix())
|
2017-11-07 11:40:44 +08:00
|
|
|
if err != nil {
|
2017-11-08 21:39:51 +08:00
|
|
|
logrus.Error("load datacenter config error.", err.Error())
|
|
|
|
}
|
2017-11-09 17:32:02 +08:00
|
|
|
if len(res.Kvs) < 1 {
|
2017-12-21 18:02:28 +08:00
|
|
|
// dgc := model.CreateDefaultGlobalConfig()
|
|
|
|
// err := dataCenterConfig.PutDataCenterConfig(dgc)
|
|
|
|
// if err != nil {
|
|
|
|
// logrus.Error("put datacenter config error,", err.Error())
|
|
|
|
// }
|
2017-12-21 18:21:02 +08:00
|
|
|
|
|
|
|
dgc := &model.GlobalConfig{
|
|
|
|
Configs: make(map[string]*model.ConfigUnit),
|
|
|
|
}
|
|
|
|
dataCenterConfig.config = dgc
|
2017-11-09 17:32:02 +08:00
|
|
|
} else {
|
|
|
|
for _, kv := range res.Kvs {
|
2017-11-13 21:54:11 +08:00
|
|
|
dataCenterConfig.PutConfigKV(kv)
|
2017-11-09 17:32:02 +08:00
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
2017-11-13 21:54:11 +08:00
|
|
|
return dataCenterConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
//Start 启动,监听配置变化
|
|
|
|
func (d *DataCenterConfig) Start() {
|
2018-04-18 11:12:38 +08:00
|
|
|
go util.Exec(d.ctx, func() error {
|
|
|
|
ctx, cancel := context.WithCancel(d.ctx)
|
|
|
|
defer cancel()
|
2017-11-08 21:39:51 +08:00
|
|
|
logrus.Info("datacenter config listener start")
|
2018-04-18 11:12:38 +08:00
|
|
|
ch := store.DefalutClient.WatchByCtx(ctx, d.options.ConfigStoragePath+"/global", client.WithPrefix())
|
2018-04-18 09:45:57 +08:00
|
|
|
for event := range ch {
|
|
|
|
for _, e := range event.Events {
|
|
|
|
switch {
|
|
|
|
case e.IsCreate(), e.IsModify():
|
|
|
|
d.PutConfigKV(e.Kv)
|
|
|
|
case e.Type == client.EventTypeDelete:
|
|
|
|
d.DeleteConfig(util.GetIDFromKey(string(e.Kv.Key)))
|
2017-11-08 21:39:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-04-18 11:12:38 +08:00
|
|
|
return nil
|
|
|
|
}, 1)
|
2017-11-08 21:39:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//Stop 停止监听
|
|
|
|
func (d *DataCenterConfig) Stop() {
|
|
|
|
d.cancel()
|
|
|
|
logrus.Info("datacenter config listener stop")
|
|
|
|
}
|
|
|
|
|
|
|
|
//GetDataCenterConfig 获取配置
|
|
|
|
func (d *DataCenterConfig) GetDataCenterConfig() (*model.GlobalConfig, error) {
|
2017-11-07 11:40:44 +08:00
|
|
|
return d.config, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//PutDataCenterConfig 更改配置
|
|
|
|
func (d *DataCenterConfig) PutDataCenterConfig(c *model.GlobalConfig) (err error) {
|
2017-11-08 21:39:51 +08:00
|
|
|
if c == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for k, v := range c.Configs {
|
|
|
|
d.config.Add(*v)
|
|
|
|
_, err = store.DefalutClient.Put(d.options.ConfigStoragePath+"/global/"+k, v.String())
|
|
|
|
}
|
2017-11-07 11:40:44 +08:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2017-11-08 21:39:51 +08:00
|
|
|
//GetConfig 获取全局配置
|
2017-11-13 21:54:11 +08:00
|
|
|
func (d *DataCenterConfig) GetConfig(name string) *model.ConfigUnit {
|
2017-11-08 21:39:51 +08:00
|
|
|
return d.config.Get(name)
|
|
|
|
}
|
|
|
|
|
2018-01-17 22:52:35 +08:00
|
|
|
//CacheConfig 更新配置缓存
|
|
|
|
func (d *DataCenterConfig) CacheConfig(c *model.ConfigUnit) error {
|
|
|
|
if c.Name == "" {
|
|
|
|
return fmt.Errorf("config name can not be empty")
|
|
|
|
}
|
|
|
|
logrus.Debugf("add config %v", c)
|
|
|
|
//将值类型由[]interface{} 转 []string
|
|
|
|
if c.ValueType == "array" {
|
|
|
|
switch c.Value.(type) {
|
|
|
|
case []interface{}:
|
|
|
|
var data []string
|
|
|
|
for _, v := range c.Value.([]interface{}) {
|
|
|
|
data = append(data, v.(string))
|
|
|
|
}
|
|
|
|
c.Value = data
|
|
|
|
}
|
|
|
|
oldC := d.config.Get(c.Name)
|
|
|
|
if oldC != nil {
|
|
|
|
|
|
|
|
switch oldC.Value.(type) {
|
|
|
|
case string:
|
|
|
|
value := append(c.Value.([]string), oldC.Value.(string))
|
|
|
|
util.Deweight(&value)
|
|
|
|
c.Value = value
|
|
|
|
case []string:
|
|
|
|
value := append(c.Value.([]string), oldC.Value.([]string)...)
|
|
|
|
util.Deweight(&value)
|
|
|
|
c.Value = value
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
d.config.Add(*c)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2017-11-08 21:39:51 +08:00
|
|
|
//PutConfig 增加or更新配置
|
|
|
|
func (d *DataCenterConfig) PutConfig(c *model.ConfigUnit) error {
|
|
|
|
if c.Name == "" {
|
|
|
|
return fmt.Errorf("config name can not be empty")
|
|
|
|
}
|
2018-01-17 22:52:35 +08:00
|
|
|
logrus.Debugf("add config %v", c)
|
2017-12-22 16:45:21 +08:00
|
|
|
//将值类型由[]interface{} 转 []string
|
|
|
|
if c.ValueType == "array" {
|
|
|
|
switch c.Value.(type) {
|
|
|
|
case []interface{}:
|
|
|
|
var data []string
|
|
|
|
for _, v := range c.Value.([]interface{}) {
|
|
|
|
data = append(data, v.(string))
|
|
|
|
}
|
|
|
|
c.Value = data
|
|
|
|
}
|
2017-12-20 17:28:21 +08:00
|
|
|
oldC := d.config.Get(c.Name)
|
|
|
|
if oldC != nil {
|
2017-12-22 17:01:54 +08:00
|
|
|
|
2017-12-22 16:45:21 +08:00
|
|
|
switch oldC.Value.(type) {
|
|
|
|
case string:
|
2017-12-22 17:01:54 +08:00
|
|
|
value := append(c.Value.([]string), oldC.Value.(string))
|
|
|
|
util.Deweight(&value)
|
|
|
|
c.Value = value
|
2017-12-22 16:45:21 +08:00
|
|
|
case []string:
|
2017-12-22 17:01:54 +08:00
|
|
|
value := append(c.Value.([]string), oldC.Value.([]string)...)
|
|
|
|
util.Deweight(&value)
|
|
|
|
c.Value = value
|
2017-12-22 16:45:21 +08:00
|
|
|
default:
|
2017-12-20 17:28:21 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-08 21:39:51 +08:00
|
|
|
d.config.Add(*c)
|
|
|
|
//持久化
|
|
|
|
_, err := store.DefalutClient.Put(d.options.ConfigStoragePath+"/global/"+c.Name, c.String())
|
|
|
|
if err != nil {
|
|
|
|
logrus.Error("put datacenter config to etcd error.", err.Error())
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
//PutConfigKV 更新
|
|
|
|
func (d *DataCenterConfig) PutConfigKV(kv *mvccpb.KeyValue) {
|
|
|
|
var cn model.ConfigUnit
|
|
|
|
if err := ffjson.Unmarshal(kv.Value, &cn); err == nil {
|
2018-01-17 22:52:35 +08:00
|
|
|
d.CacheConfig(&cn)
|
2017-11-08 21:39:51 +08:00
|
|
|
} else {
|
|
|
|
logrus.Errorf("parse config error,%s", err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//DeleteConfig 删除配置
|
|
|
|
func (d *DataCenterConfig) DeleteConfig(name string) {
|
|
|
|
d.config.Delete(name)
|
2017-11-07 11:40:44 +08:00
|
|
|
}
|
2017-12-19 18:46:49 +08:00
|
|
|
|
|
|
|
//GetGroupConfig get group config
|
|
|
|
func (d *DataCenterConfig) GetGroupConfig(groupID string) *GroupContext {
|
|
|
|
if c, ok := d.groupConfigs[groupID]; ok {
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
c := NewGroupContext(groupID)
|
|
|
|
d.groupConfigs[groupID] = c
|
|
|
|
return c
|
|
|
|
}
|