github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/servermaster/config.go (about) 1 // Copyright 2022 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package servermaster 15 16 import ( 17 "bytes" 18 "encoding/json" 19 "fmt" 20 "strings" 21 "time" 22 23 "github.com/BurntSushi/toml" 24 validation "github.com/go-ozzo/ozzo-validation/v4" 25 "github.com/pingcap/log" 26 resModel "github.com/pingcap/tiflow/engine/pkg/externalresource/model" 27 metaModel "github.com/pingcap/tiflow/engine/pkg/meta/model" 28 "github.com/pingcap/tiflow/engine/servermaster/jobop" 29 "github.com/pingcap/tiflow/pkg/errors" 30 "github.com/pingcap/tiflow/pkg/logutil" 31 "github.com/pingcap/tiflow/pkg/security" 32 "go.uber.org/zap" 33 ) 34 35 const ( 36 defaultKeepAliveTTL = "20s" 37 defaultKeepAliveInterval = "500ms" 38 defaultMetricInterval = 15 * time.Second 39 defaultMasterAddr = "127.0.0.1:10240" 40 41 // DefaultBusinessMetaID is the ID for default business metastore 42 DefaultBusinessMetaID = "_default" 43 defaultBusinessMetaEndpoints = "127.0.0.1:3336" 44 defaultBusinessMetaUser = "root" 45 defaultBusinessMetaPassword = "" 46 defaultBusinessMetaSchema = "test_business" 47 48 // FrameMetaID is the ID for frame metastore 49 FrameMetaID = "_root" 50 defaultFrameMetaEndpoints = "127.0.0.1:3336" 51 defaultFrameMetaUser = "root" 52 defaultFrameMetaPassword = "" 53 defaultFrameMetaSchema = "test_framework" 54 55 defaultFrameworkStoreType = metaModel.StoreTypeMySQL 56 defaultBusinessStoreType = metaModel.StoreTypeMySQL 57 ) 58 59 // Config is the configuration for server-master. 60 type Config struct { 61 LogConf logutil.Config `toml:"log" json:"log"` 62 63 Name string `toml:"name" json:"name"` 64 Addr string `toml:"addr" json:"addr"` 65 AdvertiseAddr string `toml:"advertise-addr" json:"advertise-addr"` 66 67 FrameworkMeta *metaModel.StoreConfig `toml:"framework-meta" json:"framework-meta"` 68 BusinessMeta *metaModel.StoreConfig `toml:"business-meta" json:"business-meta"` 69 70 KeepAliveTTLStr string `toml:"keepalive-ttl" json:"keepalive-ttl"` 71 // time interval string to check executor aliveness 72 KeepAliveIntervalStr string `toml:"keepalive-interval" json:"keepalive-interval"` 73 74 KeepAliveTTL time.Duration `toml:"-" json:"-"` 75 KeepAliveInterval time.Duration `toml:"-" json:"-"` 76 77 Storage resModel.Config `toml:"storage" json:"storage"` 78 79 Security *security.Credential `toml:"security" json:"security"` 80 81 JobBackoff *jobop.BackoffConfig `toml:"job-backoff" json:"job-backoff"` 82 } 83 84 func (c *Config) String() string { 85 cfg, err := json.Marshal(c) 86 if err != nil { 87 log.Error("marshal to json", zap.Reflect("master config", c), logutil.ShortError(err)) 88 } 89 return string(cfg) 90 } 91 92 // Toml returns TOML format representation of config. 93 func (c *Config) Toml() (string, error) { 94 var b bytes.Buffer 95 96 err := toml.NewEncoder(&b).Encode(c) 97 if err != nil { 98 log.Error("fail to marshal config to toml", logutil.ShortError(err)) 99 } 100 101 return b.String(), nil 102 } 103 104 // AdjustAndValidate validates and adjusts the master configuration 105 func (c *Config) AdjustAndValidate() (err error) { 106 // adjust the metastore type 107 c.FrameworkMeta.StoreType = strings.ToLower(strings.TrimSpace(c.FrameworkMeta.StoreType)) 108 c.BusinessMeta.StoreType = strings.ToLower(strings.TrimSpace(c.BusinessMeta.StoreType)) 109 110 if c.FrameworkMeta.Schema == defaultFrameMetaSchema { 111 log.Warn("use default schema for framework metastore, "+ 112 "better to use predefined schema in production environment", 113 zap.String("schema", defaultFrameMetaSchema)) 114 } 115 if c.BusinessMeta.Schema == defaultBusinessMetaSchema { 116 log.Warn("use default schema for business metastore, "+ 117 "better to use predefined schema in production environment", 118 zap.String("schema", defaultBusinessMetaSchema)) 119 } 120 121 if c.AdvertiseAddr == "" { 122 c.AdvertiseAddr = c.Addr 123 } 124 125 if c.Name == "" { 126 c.Name = fmt.Sprintf("master-%s", c.AdvertiseAddr) 127 } 128 129 c.KeepAliveInterval, err = time.ParseDuration(c.KeepAliveIntervalStr) 130 if err != nil { 131 return err 132 } 133 134 c.KeepAliveTTL, err = time.ParseDuration(c.KeepAliveTTLStr) 135 if err != nil { 136 return err 137 } 138 139 if err := validation.ValidateStruct(c, validation.Field(&c.Storage)); err != nil { 140 return err 141 } 142 143 return validation.ValidateStruct(c, 144 validation.Field(&c.FrameworkMeta), 145 validation.Field(&c.BusinessMeta), 146 ) 147 } 148 149 func (c *Config) configFromString(data string) error { 150 metaData, err := toml.Decode(data, c) 151 if err != nil { 152 return errors.WrapError(errors.ErrMasterDecodeConfigFile, err) 153 } 154 return checkUndecodedItems(metaData) 155 } 156 157 // GetDefaultMasterConfig returns a default master config 158 func GetDefaultMasterConfig() *Config { 159 return &Config{ 160 LogConf: logutil.Config{ 161 Level: "info", 162 File: "", 163 }, 164 Name: "", 165 Addr: defaultMasterAddr, 166 AdvertiseAddr: "", 167 FrameworkMeta: newFrameMetaConfig(), 168 BusinessMeta: NewDefaultBusinessMetaConfig(), 169 KeepAliveTTLStr: defaultKeepAliveTTL, 170 KeepAliveIntervalStr: defaultKeepAliveInterval, 171 JobBackoff: jobop.NewDefaultBackoffConfig(), 172 Storage: resModel.DefaultConfig, 173 } 174 } 175 176 func checkUndecodedItems(metaData toml.MetaData) error { 177 undecoded := metaData.Undecoded() 178 if len(undecoded) > 0 { 179 var undecodedItems []string 180 for _, item := range undecoded { 181 undecodedItems = append(undecodedItems, item.String()) 182 } 183 return errors.ErrMasterConfigUnknownItem.GenWithStackByArgs(strings.Join(undecodedItems, ",")) 184 } 185 return nil 186 } 187 188 // newFrameMetaConfig return the default framework metastore config 189 func newFrameMetaConfig() *metaModel.StoreConfig { 190 conf := metaModel.DefaultStoreConfig() 191 conf.Schema = defaultFrameMetaSchema 192 conf.StoreID = FrameMetaID 193 conf.StoreType = defaultFrameworkStoreType 194 conf.Endpoints = append(conf.Endpoints, defaultFrameMetaEndpoints) 195 conf.User = defaultFrameMetaUser 196 conf.Password = defaultFrameMetaPassword 197 198 return conf 199 } 200 201 // NewDefaultBusinessMetaConfig return the default business metastore config 202 func NewDefaultBusinessMetaConfig() *metaModel.StoreConfig { 203 conf := metaModel.DefaultStoreConfig() 204 conf.Schema = defaultBusinessMetaSchema 205 conf.StoreID = DefaultBusinessMetaID 206 conf.StoreType = defaultBusinessStoreType 207 conf.Endpoints = append(conf.Endpoints, defaultBusinessMetaEndpoints) 208 conf.User = defaultBusinessMetaUser 209 conf.Password = defaultBusinessMetaPassword 210 211 return conf 212 }