github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/engine/pkg/meta/model/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 model 15 16 import ( 17 "crypto/tls" 18 "strings" 19 20 validation "github.com/go-ozzo/ozzo-validation/v4" 21 dmysql "github.com/go-sql-driver/mysql" 22 "github.com/pingcap/tidb/pkg/util" 23 "github.com/pingcap/tiflow/engine/pkg/dbutil" 24 "github.com/pingcap/tiflow/pkg/errors" 25 "github.com/pingcap/tiflow/pkg/security" 26 ) 27 28 const ( 29 defaultReadTimeout = "3s" 30 defaultWriteTimeout = "3s" 31 defaultDialTimeout = "3s" 32 ) 33 34 // StoreType is the type of metastore 35 type StoreType = string 36 37 const ( 38 defaultStoreType = StoreTypeMySQL 39 // StoreTypeEtcd is the store type string for etcd 40 StoreTypeEtcd = "etcd" 41 // StoreTypeMySQL is the store type string for MySQL 42 StoreTypeMySQL = "mysql" 43 44 // StoreTypeSQLite is the store type string for SQLite 45 // Only for test now 46 StoreTypeSQLite = "sqlite" 47 // StoreTypeMockKV is a specific store type which can generate 48 // a mock kvclient (using map as backend) 49 // Only for test now 50 StoreTypeMockKV = "mock-kv" 51 ) 52 53 // AuthConfParams is basic authentication configurations 54 type AuthConfParams struct { 55 User string `toml:"user" json:"user"` 56 Passwd string `toml:"passwd" json:"passwd"` 57 } 58 59 // StoreConfig is metastore connection configurations 60 type StoreConfig struct { 61 // StoreID is the unique readable identifier for a store 62 StoreID string `toml:"store-id" json:"store-id"` 63 // StoreType supports 'etcd' or 'mysql', default is 'mysql' 64 StoreType StoreType `toml:"store-type" json:"store-type"` 65 Endpoints []string `toml:"endpoints" json:"endpoints"` 66 User string `toml:"user" json:"user"` 67 Password string `toml:"password" json:"password"` 68 // Schema is the predefine schema name for mysql-compatible metastore 69 // 1.It needs to stay UNCHANGED for one dataflow engine cluster 70 // 2.It needs be different between any two dataflow engine clusters 71 // 3.Naming rule: https://dev.mysql.com/doc/refman/5.7/en/identifiers.html 72 Schema string `toml:"schema" json:"schema"` 73 ReadTimeout string `toml:"read-timeout" json:"read-timeout"` 74 WriteTimeout string `toml:"write-timeout" json:"write-timeout"` 75 DialTimeout string `toml:"dial-timeout" json:"dial-timeout"` 76 // DBConf is the db config for mysql-compatible metastore 77 DBConf *dbutil.DBConfig `toml:"dbconfs" json:"dbconfs"` 78 79 Security *security.Credential `toml:"security" json:"security"` 80 } 81 82 // SetEndpoints sets endpoints to StoreConfig 83 func (s *StoreConfig) SetEndpoints(endpoints string) { 84 if endpoints != "" { 85 s.Endpoints = strings.Split(endpoints, ",") 86 } 87 } 88 89 // Validate implements the validation.Validatable interface 90 func (s StoreConfig) Validate() error { 91 return validation.ValidateStruct(&s, 92 validation.Field(&s.StoreType, validation.In(StoreTypeEtcd, StoreTypeMySQL)), 93 validation.Field(&s.Schema, validation.When(s.StoreType == StoreTypeMySQL, validation.Required, validation.Length(1, 128))), 94 ) 95 } 96 97 // DefaultStoreConfig return a default *StoreConfig 98 func DefaultStoreConfig() *StoreConfig { 99 return &StoreConfig{ 100 StoreType: defaultStoreType, 101 Endpoints: []string{}, 102 ReadTimeout: defaultReadTimeout, 103 WriteTimeout: defaultWriteTimeout, 104 DialTimeout: defaultDialTimeout, 105 DBConf: dbutil.DefaultDBConfig(), 106 } 107 } 108 109 // GenerateDSNByParams generates a dsn string. 110 // dsn format: [username[:password]@][protocol[(address)]]/ 111 func GenerateDSNByParams(storeConf *StoreConfig, pairs map[string]string) (string, error) { 112 if storeConf == nil { 113 return "", errors.ErrMetaParamsInvalid.GenWithStackByArgs("input store config is nil") 114 } 115 116 dsnCfg := dmysql.NewConfig() 117 if dsnCfg.Params == nil { 118 dsnCfg.Params = make(map[string]string, 1) 119 } 120 if storeConf.User != "" { 121 dsnCfg.User = storeConf.User 122 } 123 if storeConf.Password != "" { 124 dsnCfg.Passwd = storeConf.Password 125 } 126 127 if storeConf.Security != nil { 128 cfg, err := util.NewTLSConfig( 129 util.WithCAPath(storeConf.Security.CAPath), 130 util.WithCertAndKeyPath(storeConf.Security.CertPath, storeConf.Security.KeyPath), 131 util.WithVerifyCommonName(storeConf.Security.CertAllowedCN), 132 util.WithMinTLSVersion(tls.VersionTLS10)) 133 if err != nil { 134 return "", errors.ErrMetaParamsInvalid.Wrap(err) 135 } 136 tlsName := "engine_tls" + storeConf.StoreID 137 if cfg != nil { 138 if err := dmysql.RegisterTLSConfig(tlsName, cfg); err != nil { 139 return "", errors.ErrMetaParamsInvalid.Wrap(err) 140 } 141 } 142 dsnCfg.Params["tls"] = tlsName 143 } 144 145 dsnCfg.Net = "tcp" 146 dsnCfg.Addr = storeConf.Endpoints[0] 147 dsnCfg.DBName = storeConf.Schema 148 dsnCfg.InterpolateParams = true 149 dsnCfg.Params["parseTime"] = "true" 150 // TODO: check for timezone 151 dsnCfg.Params["loc"] = "Local" 152 dsnCfg.Params["readTimeout"] = storeConf.ReadTimeout 153 dsnCfg.Params["writeTimeout"] = storeConf.WriteTimeout 154 dsnCfg.Params["timeout"] = storeConf.DialTimeout 155 156 for k, v := range pairs { 157 dsnCfg.Params[k] = v 158 } 159 160 return dsnCfg.FormatDSN(), nil 161 } 162 163 // ToClientType translates store type to client type 164 func ToClientType(storeType StoreType) ClientType { 165 switch storeType { 166 case StoreTypeEtcd: 167 return EtcdKVClientType 168 case StoreTypeMySQL: 169 return SQLKVClientType 170 case StoreTypeMockKV: 171 return MockKVClientType 172 } 173 174 return UnknownKVClientType 175 }