github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/libraries/doltcore/servercfg/yaml_config.go (about)

     1  // Copyright 2020 Dolthub, 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  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package servercfg
    16  
    17  import (
    18  	"fmt"
    19  	"path/filepath"
    20  	"strings"
    21  	"unicode"
    22  	"unicode/utf8"
    23  
    24  	"gopkg.in/yaml.v2"
    25  
    26  	"github.com/dolthub/dolt/go/libraries/utils/filesys"
    27  )
    28  
    29  func nillableStrPtr(s string) *string {
    30  	if s == "" {
    31  		return nil
    32  	}
    33  	return &s
    34  }
    35  
    36  func nillableBoolPtr(b bool) *bool {
    37  	if b == false {
    38  		return nil
    39  	}
    40  	return &b
    41  }
    42  
    43  func nillableIntPtr(n int) *int {
    44  	if n == 0 {
    45  		return nil
    46  	}
    47  	return &n
    48  }
    49  
    50  // BehaviorYAMLConfig contains server configuration regarding how the server should behave
    51  type BehaviorYAMLConfig struct {
    52  	ReadOnly   *bool `yaml:"read_only"`
    53  	AutoCommit *bool `yaml:"autocommit"`
    54  	// PersistenceBehavior regulates loading persisted system variable configuration.
    55  	PersistenceBehavior *string `yaml:"persistence_behavior"`
    56  	// Disable processing CLIENT_MULTI_STATEMENTS support on the
    57  	// sql server.  Dolt's handling of CLIENT_MULTI_STATEMENTS is currently
    58  	// broken. If a client advertises to support it (mysql cli client
    59  	// does), and then sends statements that contain embedded unquoted ';'s
    60  	// (such as a CREATE TRIGGER), then those incoming queries will be
    61  	// misprocessed.
    62  	DisableClientMultiStatements *bool `yaml:"disable_client_multi_statements"`
    63  	// DoltTransactionCommit enables the @@dolt_transaction_commit system variable, which
    64  	// automatically creates a Dolt commit when any SQL transaction is committed.
    65  	DoltTransactionCommit *bool `yaml:"dolt_transaction_commit"`
    66  
    67  	EventSchedulerStatus *string `yaml:"event_scheduler,omitempty" minver:"1.17.0"`
    68  }
    69  
    70  // UserYAMLConfig contains server configuration regarding the user account clients must use to connect
    71  type UserYAMLConfig struct {
    72  	Name     *string `yaml:"name"`
    73  	Password *string `yaml:"password"`
    74  }
    75  
    76  // ListenerYAMLConfig contains information on the network connection that the server will open
    77  type ListenerYAMLConfig struct {
    78  	HostStr            *string `yaml:"host"`
    79  	PortNumber         *int    `yaml:"port"`
    80  	MaxConnections     *uint64 `yaml:"max_connections"`
    81  	ReadTimeoutMillis  *uint64 `yaml:"read_timeout_millis"`
    82  	WriteTimeoutMillis *uint64 `yaml:"write_timeout_millis"`
    83  	// TLSKey is a file system path to an unencrypted private TLS key in PEM format.
    84  	TLSKey *string `yaml:"tls_key"`
    85  	// TLSCert is a file system path to a TLS certificate chain in PEM format.
    86  	TLSCert *string `yaml:"tls_cert"`
    87  	// RequireSecureTransport can enable a mode where non-TLS connections are turned away.
    88  	RequireSecureTransport *bool `yaml:"require_secure_transport"`
    89  	// AllowCleartextPasswords enables use of cleartext passwords.
    90  	AllowCleartextPasswords *bool `yaml:"allow_cleartext_passwords"`
    91  	// Socket is unix socket file path
    92  	Socket *string `yaml:"socket,omitempty"`
    93  }
    94  
    95  // PerformanceYAMLConfig contains configuration parameters for performance tweaking
    96  type PerformanceYAMLConfig struct {
    97  	QueryParallelism *int `yaml:"query_parallelism"`
    98  }
    99  
   100  type MetricsYAMLConfig struct {
   101  	Labels map[string]string `yaml:"labels"`
   102  	Host   *string           `yaml:"host"`
   103  	Port   *int              `yaml:"port"`
   104  }
   105  
   106  type RemotesapiYAMLConfig struct {
   107  	Port_     *int  `yaml:"port,omitempty"`
   108  	ReadOnly_ *bool `yaml:"read_only,omitempty" minver:"1.30.5"`
   109  }
   110  
   111  func (r RemotesapiYAMLConfig) Port() int {
   112  	return *r.Port_
   113  }
   114  
   115  func (r RemotesapiYAMLConfig) ReadOnly() bool {
   116  	return *r.ReadOnly_
   117  }
   118  
   119  type UserSessionVars struct {
   120  	Name string            `yaml:"name"`
   121  	Vars map[string]string `yaml:"vars"`
   122  }
   123  
   124  // YAMLConfig is a ServerConfig implementation which is read from a yaml file
   125  type YAMLConfig struct {
   126  	LogLevelStr       *string               `yaml:"log_level,omitempty"`
   127  	MaxQueryLenInLogs *int                  `yaml:"max_logged_query_len,omitempty"`
   128  	EncodeLoggedQuery *bool                 `yaml:"encode_logged_query,omitempty"`
   129  	BehaviorConfig    BehaviorYAMLConfig    `yaml:"behavior"`
   130  	UserConfig        UserYAMLConfig        `yaml:"user"`
   131  	ListenerConfig    ListenerYAMLConfig    `yaml:"listener"`
   132  	PerformanceConfig PerformanceYAMLConfig `yaml:"performance"`
   133  	DataDirStr        *string               `yaml:"data_dir,omitempty"`
   134  	CfgDirStr         *string               `yaml:"cfg_dir,omitempty"`
   135  	MetricsConfig     MetricsYAMLConfig     `yaml:"metrics"`
   136  	RemotesapiConfig  RemotesapiYAMLConfig  `yaml:"remotesapi"`
   137  	ClusterCfg        *ClusterYAMLConfig    `yaml:"cluster,omitempty"`
   138  	PrivilegeFile     *string               `yaml:"privilege_file,omitempty"`
   139  	BranchControlFile *string               `yaml:"branch_control_file,omitempty"`
   140  	// TODO: Rename to UserVars_
   141  	Vars            []UserSessionVars      `yaml:"user_session_vars"`
   142  	SystemVars_     map[string]interface{} `yaml:"system_variables,omitempty" minver:"1.11.1"`
   143  	Jwks            []JwksConfig           `yaml:"jwks"`
   144  	GoldenMysqlConn *string                `yaml:"golden_mysql_conn,omitempty"`
   145  }
   146  
   147  var _ ServerConfig = YAMLConfig{}
   148  var _ ValidatingServerConfig = YAMLConfig{}
   149  var _ WritableServerConfig = &YAMLConfig{}
   150  
   151  func NewYamlConfig(configFileData []byte) (*YAMLConfig, error) {
   152  	var cfg YAMLConfig
   153  	err := yaml.UnmarshalStrict(configFileData, &cfg)
   154  	if cfg.LogLevelStr != nil {
   155  		loglevel := strings.ToLower(*cfg.LogLevelStr)
   156  		cfg.LogLevelStr = &loglevel
   157  	}
   158  	return &cfg, err
   159  }
   160  
   161  // YamlConfigFromFile returns server config variables with values defined in yaml file.
   162  func YamlConfigFromFile(fs filesys.Filesys, path string) (ServerConfig, error) {
   163  	data, err := fs.ReadFile(path)
   164  	if err != nil {
   165  		return nil, fmt.Errorf("Failed to read file '%s'. Error: %s", path, err.Error())
   166  	}
   167  
   168  	cfg, err := NewYamlConfig(data)
   169  	if err != nil {
   170  		return nil, fmt.Errorf("Failed to parse yaml file '%s'. Error: %s", path, err.Error())
   171  	}
   172  
   173  	return cfg, nil
   174  }
   175  
   176  func ServerConfigAsYAMLConfig(cfg ServerConfig) *YAMLConfig {
   177  	systemVars := map[string]interface{}(cfg.SystemVars())
   178  	return &YAMLConfig{
   179  		LogLevelStr:       ptr(string(cfg.LogLevel())),
   180  		MaxQueryLenInLogs: nillableIntPtr(cfg.MaxLoggedQueryLen()),
   181  		EncodeLoggedQuery: nillableBoolPtr(cfg.ShouldEncodeLoggedQuery()),
   182  		BehaviorConfig: BehaviorYAMLConfig{
   183  			ptr(cfg.ReadOnly()),
   184  			ptr(cfg.AutoCommit()),
   185  			ptr(cfg.PersistenceBehavior()),
   186  			ptr(cfg.DisableClientMultiStatements()),
   187  			ptr(cfg.DoltTransactionCommit()),
   188  			ptr(cfg.EventSchedulerStatus()),
   189  		},
   190  		UserConfig: UserYAMLConfig{
   191  			Name:     ptr(cfg.User()),
   192  			Password: ptr(cfg.Password()),
   193  		},
   194  		ListenerConfig: ListenerYAMLConfig{
   195  			ptr(cfg.Host()),
   196  			ptr(cfg.Port()),
   197  			ptr(cfg.MaxConnections()),
   198  			ptr(cfg.ReadTimeout()),
   199  			ptr(cfg.WriteTimeout()),
   200  			nillableStrPtr(cfg.TLSKey()),
   201  			nillableStrPtr(cfg.TLSCert()),
   202  			nillableBoolPtr(cfg.RequireSecureTransport()),
   203  			nillableBoolPtr(cfg.AllowCleartextPasswords()),
   204  			nillableStrPtr(cfg.Socket()),
   205  		},
   206  		PerformanceConfig: PerformanceYAMLConfig{
   207  			QueryParallelism: nillableIntPtr(cfg.QueryParallelism()),
   208  		},
   209  		DataDirStr: ptr(cfg.DataDir()),
   210  		CfgDirStr:  ptr(cfg.CfgDir()),
   211  		MetricsConfig: MetricsYAMLConfig{
   212  			Labels: cfg.MetricsLabels(),
   213  			Host:   nillableStrPtr(cfg.MetricsHost()),
   214  			Port:   ptr(cfg.MetricsPort()),
   215  		},
   216  		RemotesapiConfig: RemotesapiYAMLConfig{
   217  			Port_:     cfg.RemotesapiPort(),
   218  			ReadOnly_: cfg.RemotesapiReadOnly(),
   219  		},
   220  		ClusterCfg:        clusterConfigAsYAMLConfig(cfg.ClusterConfig()),
   221  		PrivilegeFile:     ptr(cfg.PrivilegeFilePath()),
   222  		BranchControlFile: ptr(cfg.BranchControlFilePath()),
   223  		SystemVars_:       systemVars,
   224  		Vars:              cfg.UserVars(),
   225  		Jwks:              cfg.JwksConfig(),
   226  	}
   227  }
   228  
   229  func clusterConfigAsYAMLConfig(config ClusterConfig) *ClusterYAMLConfig {
   230  	if config == nil {
   231  		return nil
   232  	}
   233  
   234  	return &ClusterYAMLConfig{
   235  		StandbyRemotes_: nil,
   236  		BootstrapRole_:  config.BootstrapRole(),
   237  		BootstrapEpoch_: config.BootstrapEpoch(),
   238  		RemotesAPI: ClusterRemotesAPIYAMLConfig{
   239  			Addr_:      config.RemotesAPIConfig().Address(),
   240  			Port_:      config.RemotesAPIConfig().Port(),
   241  			TLSKey_:    config.RemotesAPIConfig().TLSKey(),
   242  			TLSCert_:   config.RemotesAPIConfig().TLSCert(),
   243  			TLSCA_:     config.RemotesAPIConfig().TLSCA(),
   244  			URLMatches: config.RemotesAPIConfig().ServerNameURLMatches(),
   245  			DNSMatches: config.RemotesAPIConfig().ServerNameDNSMatches(),
   246  		},
   247  	}
   248  }
   249  
   250  // String returns the YAML representation of the config
   251  func (cfg YAMLConfig) String() string {
   252  	data, err := yaml.Marshal(cfg)
   253  
   254  	if err != nil {
   255  		return "Failed to marshal as yaml: " + err.Error()
   256  	}
   257  
   258  	unformatted := string(data)
   259  
   260  	// format the yaml to be easier to read.
   261  	lines := strings.Split(unformatted, "\n")
   262  
   263  	var formatted []string
   264  	formatted = append(formatted, lines[0])
   265  	for i := 1; i < len(lines); i++ {
   266  		if len(lines[i]) == 0 {
   267  			continue
   268  		}
   269  
   270  		r, _ := utf8.DecodeRuneInString(lines[i])
   271  		if !unicode.IsSpace(r) {
   272  			formatted = append(formatted, "")
   273  		}
   274  
   275  		formatted = append(formatted, lines[i])
   276  	}
   277  
   278  	result := strings.Join(formatted, "\n")
   279  	return result
   280  }
   281  
   282  // Host returns the domain that the server will run on. Accepts an IPv4 or IPv6 address, in addition to localhost.
   283  func (cfg YAMLConfig) Host() string {
   284  	if cfg.ListenerConfig.HostStr == nil {
   285  		return DefaultHost
   286  	}
   287  
   288  	return *cfg.ListenerConfig.HostStr
   289  }
   290  
   291  // Port returns the port that the server will run on. The valid range is [1024, 65535].
   292  func (cfg YAMLConfig) Port() int {
   293  	if cfg.ListenerConfig.PortNumber == nil {
   294  		return DefaultPort
   295  	}
   296  
   297  	return *cfg.ListenerConfig.PortNumber
   298  }
   299  
   300  // ReadTimeout returns the read timeout in milliseconds.
   301  func (cfg YAMLConfig) ReadTimeout() uint64 {
   302  	if cfg.ListenerConfig.ReadTimeoutMillis == nil {
   303  		return DefaultTimeout
   304  	}
   305  
   306  	return *cfg.ListenerConfig.ReadTimeoutMillis
   307  }
   308  
   309  // WriteTimeout returns the write timeout in milliseconds.
   310  func (cfg YAMLConfig) WriteTimeout() uint64 {
   311  	if cfg.ListenerConfig.WriteTimeoutMillis == nil {
   312  		return DefaultTimeout
   313  	}
   314  
   315  	return *cfg.ListenerConfig.WriteTimeoutMillis
   316  }
   317  
   318  // User returns the username that connecting clients must use.
   319  func (cfg YAMLConfig) User() string {
   320  	if cfg.UserConfig.Name == nil {
   321  		return DefaultUser
   322  	}
   323  
   324  	return *cfg.UserConfig.Name
   325  }
   326  
   327  func (cfg *YAMLConfig) SetUserName(s string) {
   328  	cfg.UserConfig.Name = &s
   329  }
   330  
   331  func (cfg *YAMLConfig) SetPassword(s string) {
   332  	cfg.UserConfig.Password = &s
   333  }
   334  
   335  // Password returns the password that connecting clients must use.
   336  func (cfg YAMLConfig) Password() string {
   337  	if cfg.UserConfig.Password == nil {
   338  		return DefaultPass
   339  	}
   340  
   341  	return *cfg.UserConfig.Password
   342  }
   343  
   344  // ReadOnly returns whether the server will only accept read statements or all statements.
   345  func (cfg YAMLConfig) ReadOnly() bool {
   346  	if cfg.BehaviorConfig.ReadOnly == nil {
   347  		return DefaultReadOnly
   348  	}
   349  
   350  	return *cfg.BehaviorConfig.ReadOnly
   351  }
   352  
   353  // AutoCommit defines the value of the @@autocommit session variable used on every connection
   354  func (cfg YAMLConfig) AutoCommit() bool {
   355  	if cfg.BehaviorConfig.AutoCommit == nil {
   356  		return DefaultAutoCommit
   357  	}
   358  
   359  	return *cfg.BehaviorConfig.AutoCommit
   360  }
   361  
   362  // DoltTransactionCommit defines the value of the @@dolt_transaction_commit session variable that enables Dolt
   363  // commits to be automatically created when a SQL transaction is committed.
   364  func (cfg YAMLConfig) DoltTransactionCommit() bool {
   365  	if cfg.BehaviorConfig.DoltTransactionCommit == nil {
   366  		return DefaultDoltTransactionCommit
   367  	}
   368  
   369  	return *cfg.BehaviorConfig.DoltTransactionCommit
   370  }
   371  
   372  // LogLevel returns the level of logging that the server will use.
   373  func (cfg YAMLConfig) LogLevel() LogLevel {
   374  	if cfg.LogLevelStr == nil {
   375  		return DefaultLogLevel
   376  	}
   377  
   378  	return LogLevel(*cfg.LogLevelStr)
   379  }
   380  
   381  // MaxConnections returns the maximum number of simultaneous connections the server will allow.  The default is 1
   382  func (cfg YAMLConfig) MaxConnections() uint64 {
   383  	if cfg.ListenerConfig.MaxConnections == nil {
   384  		return DefaultMaxConnections
   385  	}
   386  
   387  	return *cfg.ListenerConfig.MaxConnections
   388  }
   389  
   390  // DisableClientMultiStatements returns true if the server should run in a mode
   391  // where the CLIENT_MULTI_STATEMENTS option are ignored and every incoming
   392  // ComQuery packet is assumed to be a standalone query.
   393  func (cfg YAMLConfig) DisableClientMultiStatements() bool {
   394  	if cfg.BehaviorConfig.DisableClientMultiStatements == nil {
   395  		return false
   396  	}
   397  
   398  	return *cfg.BehaviorConfig.DisableClientMultiStatements
   399  }
   400  
   401  // MetricsLabels returns labels that are applied to all prometheus metrics
   402  func (cfg YAMLConfig) MetricsLabels() map[string]string {
   403  	return cfg.MetricsConfig.Labels
   404  }
   405  
   406  func (cfg YAMLConfig) MetricsHost() string {
   407  	if cfg.MetricsConfig.Host == nil {
   408  		return DefaultMetricsHost
   409  	}
   410  
   411  	return *cfg.MetricsConfig.Host
   412  }
   413  
   414  func (cfg YAMLConfig) MetricsPort() int {
   415  	if cfg.MetricsConfig.Host == nil {
   416  		return DefaultMetricsPort
   417  	}
   418  
   419  	return *cfg.MetricsConfig.Port
   420  }
   421  
   422  func (cfg YAMLConfig) RemotesapiPort() *int {
   423  	return cfg.RemotesapiConfig.Port_
   424  }
   425  
   426  func (cfg YAMLConfig) RemotesapiReadOnly() *bool {
   427  	return cfg.RemotesapiConfig.ReadOnly_
   428  }
   429  
   430  // PrivilegeFilePath returns the path to the file which contains all needed privilege information in the form of a
   431  // JSON string.
   432  func (cfg YAMLConfig) PrivilegeFilePath() string {
   433  	if cfg.PrivilegeFile != nil {
   434  		return *cfg.PrivilegeFile
   435  	}
   436  	return filepath.Join(cfg.CfgDir(), DefaultPrivilegeFilePath)
   437  }
   438  
   439  // BranchControlFilePath returns the path to the file which contains the branch control permissions.
   440  func (cfg YAMLConfig) BranchControlFilePath() string {
   441  	if cfg.BranchControlFile != nil {
   442  		return *cfg.BranchControlFile
   443  	}
   444  	return filepath.Join(cfg.CfgDir(), DefaultBranchControlFilePath)
   445  }
   446  
   447  // UserVars is an array containing user specific session variables
   448  func (cfg YAMLConfig) UserVars() []UserSessionVars {
   449  	if cfg.Vars != nil {
   450  		return cfg.Vars
   451  	}
   452  
   453  	return nil
   454  }
   455  
   456  func (cfg YAMLConfig) SystemVars() map[string]interface{} {
   457  	if cfg.SystemVars_ == nil {
   458  		return map[string]interface{}{}
   459  	}
   460  
   461  	return cfg.SystemVars_
   462  }
   463  
   464  // wksConfig is JSON Web Key Set config, and used to validate a user authed with a jwt (JSON Web Token).
   465  func (cfg YAMLConfig) JwksConfig() []JwksConfig {
   466  	if cfg.Jwks != nil {
   467  		return cfg.Jwks
   468  	}
   469  	return nil
   470  }
   471  
   472  func (cfg YAMLConfig) AllowCleartextPasswords() bool {
   473  	if cfg.ListenerConfig.AllowCleartextPasswords == nil {
   474  		return DefaultAllowCleartextPasswords
   475  	}
   476  	return *cfg.ListenerConfig.AllowCleartextPasswords
   477  }
   478  
   479  // QueryParallelism returns the parallelism that should be used by the go-mysql-server analyzer
   480  func (cfg YAMLConfig) QueryParallelism() int {
   481  	if cfg.PerformanceConfig.QueryParallelism == nil {
   482  		return DefaultQueryParallelism
   483  	}
   484  
   485  	return *cfg.PerformanceConfig.QueryParallelism
   486  }
   487  
   488  // TLSKey returns a path to the servers PEM-encoded private TLS key. "" if there is none.
   489  func (cfg YAMLConfig) TLSKey() string {
   490  	if cfg.ListenerConfig.TLSKey == nil {
   491  		return ""
   492  	}
   493  	return *cfg.ListenerConfig.TLSKey
   494  }
   495  
   496  // TLSCert returns a path to the servers PEM-encoded TLS certificate chain. "" if there is none.
   497  func (cfg YAMLConfig) TLSCert() string {
   498  	if cfg.ListenerConfig.TLSCert == nil {
   499  		return ""
   500  	}
   501  	return *cfg.ListenerConfig.TLSCert
   502  }
   503  
   504  // RequireSecureTransport is true if the server should reject non-TLS connections.
   505  func (cfg YAMLConfig) RequireSecureTransport() bool {
   506  	if cfg.ListenerConfig.RequireSecureTransport == nil {
   507  		return false
   508  	}
   509  	return *cfg.ListenerConfig.RequireSecureTransport
   510  }
   511  
   512  // MaxLoggedQueryLen is the max length of queries written to the logs.  Queries longer than this number are truncated.
   513  // If this value is 0 then the query is not truncated and will be written to the logs in its entirety.  If the value
   514  // is less than 0 then the queries will be omitted from the logs completely
   515  func (cfg YAMLConfig) MaxLoggedQueryLen() int {
   516  	if cfg.MaxQueryLenInLogs == nil {
   517  		return DefaultMaxLoggedQueryLen
   518  	}
   519  
   520  	return *cfg.MaxQueryLenInLogs
   521  }
   522  
   523  func (cfg YAMLConfig) ShouldEncodeLoggedQuery() bool {
   524  	if cfg.EncodeLoggedQuery == nil {
   525  		return DefaultEncodeLoggedQuery
   526  	}
   527  
   528  	return *cfg.EncodeLoggedQuery
   529  }
   530  
   531  // PersistenceBehavior is "load" if we include persisted system globals on server init
   532  func (cfg YAMLConfig) PersistenceBehavior() string {
   533  	if cfg.BehaviorConfig.PersistenceBehavior == nil {
   534  		return LoadPerisistentGlobals
   535  	}
   536  	return *cfg.BehaviorConfig.PersistenceBehavior
   537  }
   538  
   539  // DataDir is the path to a directory to use as the data dir, both to create new databases and locate existing ones.
   540  func (cfg YAMLConfig) DataDir() string {
   541  	if cfg.DataDirStr != nil {
   542  		return *cfg.DataDirStr
   543  	}
   544  	return DefaultDataDir
   545  }
   546  
   547  // CfgDir is the path to a directory to use to store the dolt configuration files.
   548  func (cfg YAMLConfig) CfgDir() string {
   549  	if cfg.CfgDirStr != nil {
   550  		return *cfg.CfgDirStr
   551  	}
   552  	return filepath.Join(cfg.DataDir(), DefaultCfgDir)
   553  }
   554  
   555  // Socket is a path to the unix socket file
   556  func (cfg YAMLConfig) Socket() string {
   557  	if cfg.ListenerConfig.Socket == nil {
   558  		return ""
   559  	}
   560  	// if defined but empty -> default
   561  	if *cfg.ListenerConfig.Socket == "" {
   562  		return DefaultUnixSocketFilePath
   563  	}
   564  	return *cfg.ListenerConfig.Socket
   565  }
   566  
   567  func (cfg YAMLConfig) GoldenMysqlConnectionString() (s string) {
   568  	if cfg.GoldenMysqlConn != nil {
   569  		s = *cfg.GoldenMysqlConn
   570  	}
   571  	return
   572  }
   573  
   574  func (cfg YAMLConfig) ClusterConfig() ClusterConfig {
   575  	if cfg.ClusterCfg == nil {
   576  		return nil
   577  	}
   578  	return cfg.ClusterCfg
   579  }
   580  
   581  func (cfg YAMLConfig) EventSchedulerStatus() string {
   582  	if cfg.BehaviorConfig.EventSchedulerStatus == nil {
   583  		return "ON"
   584  	}
   585  	switch *cfg.BehaviorConfig.EventSchedulerStatus {
   586  	case "1":
   587  		return "ON"
   588  	case "0":
   589  		return "OFF"
   590  	default:
   591  		return strings.ToUpper(*cfg.BehaviorConfig.EventSchedulerStatus)
   592  	}
   593  }
   594  
   595  type ClusterYAMLConfig struct {
   596  	StandbyRemotes_ []StandbyRemoteYAMLConfig   `yaml:"standby_remotes"`
   597  	BootstrapRole_  string                      `yaml:"bootstrap_role"`
   598  	BootstrapEpoch_ int                         `yaml:"bootstrap_epoch"`
   599  	RemotesAPI      ClusterRemotesAPIYAMLConfig `yaml:"remotesapi"`
   600  }
   601  
   602  type StandbyRemoteYAMLConfig struct {
   603  	Name_              string `yaml:"name"`
   604  	RemoteURLTemplate_ string `yaml:"remote_url_template"`
   605  }
   606  
   607  func (c StandbyRemoteYAMLConfig) Name() string {
   608  	return c.Name_
   609  }
   610  
   611  func (c StandbyRemoteYAMLConfig) RemoteURLTemplate() string {
   612  	return c.RemoteURLTemplate_
   613  }
   614  
   615  func (c *ClusterYAMLConfig) StandbyRemotes() []ClusterStandbyRemoteConfig {
   616  	ret := make([]ClusterStandbyRemoteConfig, len(c.StandbyRemotes_))
   617  	for i := range c.StandbyRemotes_ {
   618  		ret[i] = c.StandbyRemotes_[i]
   619  	}
   620  	return ret
   621  }
   622  
   623  func (c *ClusterYAMLConfig) BootstrapRole() string {
   624  	return c.BootstrapRole_
   625  }
   626  
   627  func (c *ClusterYAMLConfig) BootstrapEpoch() int {
   628  	return c.BootstrapEpoch_
   629  }
   630  
   631  func (c *ClusterYAMLConfig) RemotesAPIConfig() ClusterRemotesAPIConfig {
   632  	return c.RemotesAPI
   633  }
   634  
   635  type ClusterRemotesAPIYAMLConfig struct {
   636  	Addr_      string   `yaml:"address"`
   637  	Port_      int      `yaml:"port"`
   638  	TLSKey_    string   `yaml:"tls_key"`
   639  	TLSCert_   string   `yaml:"tls_cert"`
   640  	TLSCA_     string   `yaml:"tls_ca"`
   641  	URLMatches []string `yaml:"server_name_urls"`
   642  	DNSMatches []string `yaml:"server_name_dns"`
   643  }
   644  
   645  func (c ClusterRemotesAPIYAMLConfig) Address() string {
   646  	return c.Addr_
   647  }
   648  
   649  func (c ClusterRemotesAPIYAMLConfig) Port() int {
   650  	return c.Port_
   651  }
   652  
   653  func (c ClusterRemotesAPIYAMLConfig) TLSKey() string {
   654  	return c.TLSKey_
   655  }
   656  
   657  func (c ClusterRemotesAPIYAMLConfig) TLSCert() string {
   658  	return c.TLSCert_
   659  }
   660  
   661  func (c ClusterRemotesAPIYAMLConfig) TLSCA() string {
   662  	return c.TLSCA_
   663  }
   664  
   665  func (c ClusterRemotesAPIYAMLConfig) ServerNameURLMatches() []string {
   666  	return c.URLMatches
   667  }
   668  
   669  func (c ClusterRemotesAPIYAMLConfig) ServerNameDNSMatches() []string {
   670  	return c.DNSMatches
   671  }
   672  
   673  func (cfg YAMLConfig) ValueSet(value string) bool {
   674  	switch value {
   675  	case ReadTimeoutKey:
   676  		return cfg.ListenerConfig.ReadTimeoutMillis != nil
   677  	case WriteTimeoutKey:
   678  		return cfg.ListenerConfig.WriteTimeoutMillis != nil
   679  	case MaxConnectionsKey:
   680  		return cfg.ListenerConfig.MaxConnections != nil
   681  	case EventSchedulerKey:
   682  		return cfg.BehaviorConfig.EventSchedulerStatus != nil
   683  	}
   684  	return false
   685  }