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  }