github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/orderer/common/localconfig/config.go (about)

     1  // Copyright hechain. All Rights Reserved.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package localconfig
     5  
     6  import (
     7  	"encoding/json"
     8  	"fmt"
     9  	"path/filepath"
    10  	"sync"
    11  	"time"
    12  
    13  	"github.com/Shopify/sarama"
    14  	bccsp "github.com/hechain20/hechain/bccsp/factory"
    15  	"github.com/hechain20/hechain/common/flogging"
    16  	"github.com/hechain20/hechain/common/viperutil"
    17  	coreconfig "github.com/hechain20/hechain/core/config"
    18  	"github.com/hechain20/hechain/internal/pkg/comm"
    19  )
    20  
    21  var logger = flogging.MustGetLogger("localconfig")
    22  
    23  // TopLevel directly corresponds to the orderer config YAML.
    24  type TopLevel struct {
    25  	General              General
    26  	FileLedger           FileLedger
    27  	Kafka                Kafka
    28  	Debug                Debug
    29  	Consensus            interface{}
    30  	Operations           Operations
    31  	Metrics              Metrics
    32  	ChannelParticipation ChannelParticipation
    33  	Admin                Admin
    34  }
    35  
    36  // General contains config which should be common among all orderer types.
    37  type General struct {
    38  	ListenAddress     string
    39  	ListenPort        uint16
    40  	TLS               TLS
    41  	Cluster           Cluster
    42  	Keepalive         Keepalive
    43  	ConnectionTimeout time.Duration
    44  	GenesisMethod     string // For compatibility only, will be replaced by BootstrapMethod
    45  	GenesisFile       string // For compatibility only, will be replaced by BootstrapFile
    46  	BootstrapMethod   string
    47  	BootstrapFile     string
    48  	Profile           Profile
    49  	LocalMSPDir       string
    50  	LocalMSPID        string
    51  	BCCSP             *bccsp.FactoryOpts
    52  	Authentication    Authentication
    53  	MaxRecvMsgSize    int32
    54  	MaxSendMsgSize    int32
    55  }
    56  
    57  type Cluster struct {
    58  	ListenAddress                        string
    59  	ListenPort                           uint16
    60  	ServerCertificate                    string
    61  	ServerPrivateKey                     string
    62  	ClientCertificate                    string
    63  	ClientPrivateKey                     string
    64  	RootCAs                              []string
    65  	DialTimeout                          time.Duration
    66  	RPCTimeout                           time.Duration
    67  	ReplicationBufferSize                int
    68  	ReplicationPullTimeout               time.Duration
    69  	ReplicationRetryTimeout              time.Duration
    70  	ReplicationBackgroundRefreshInterval time.Duration
    71  	ReplicationMaxRetries                int
    72  	SendBufferSize                       int
    73  	CertExpirationWarningThreshold       time.Duration
    74  	TLSHandshakeTimeShift                time.Duration
    75  }
    76  
    77  // Keepalive contains configuration for gRPC servers.
    78  type Keepalive struct {
    79  	ServerMinInterval time.Duration
    80  	ServerInterval    time.Duration
    81  	ServerTimeout     time.Duration
    82  }
    83  
    84  // TLS contains configuration for TLS connections.
    85  type TLS struct {
    86  	Enabled               bool
    87  	PrivateKey            string
    88  	Certificate           string
    89  	RootCAs               []string
    90  	ClientAuthRequired    bool
    91  	ClientRootCAs         []string
    92  	TLSHandshakeTimeShift time.Duration
    93  }
    94  
    95  // SASLPlain contains configuration for SASL/PLAIN authentication
    96  type SASLPlain struct {
    97  	Enabled  bool
    98  	User     string
    99  	Password string
   100  }
   101  
   102  // Authentication contains configuration parameters related to authenticating
   103  // client messages.
   104  type Authentication struct {
   105  	TimeWindow         time.Duration
   106  	NoExpirationChecks bool
   107  }
   108  
   109  // Profile contains configuration for Go pprof profiling.
   110  type Profile struct {
   111  	Enabled bool
   112  	Address string
   113  }
   114  
   115  // FileLedger contains configuration for the file-based ledger.
   116  type FileLedger struct {
   117  	Location string
   118  	Prefix   string // For compatibility only. This setting is no longer supported.
   119  }
   120  
   121  // Kafka contains configuration for the Kafka-based orderer.
   122  type Kafka struct {
   123  	Retry     Retry
   124  	Verbose   bool
   125  	Version   sarama.KafkaVersion // TODO Move this to global config
   126  	TLS       TLS
   127  	SASLPlain SASLPlain
   128  	Topic     Topic
   129  }
   130  
   131  // Retry contains configuration related to retries and timeouts when the
   132  // connection to the Kafka cluster cannot be established, or when Metadata
   133  // requests needs to be repeated (because the cluster is in the middle of a
   134  // leader election).
   135  type Retry struct {
   136  	ShortInterval   time.Duration
   137  	ShortTotal      time.Duration
   138  	LongInterval    time.Duration
   139  	LongTotal       time.Duration
   140  	NetworkTimeouts NetworkTimeouts
   141  	Metadata        Metadata
   142  	Producer        Producer
   143  	Consumer        Consumer
   144  }
   145  
   146  // NetworkTimeouts contains the socket timeouts for network requests to the
   147  // Kafka cluster.
   148  type NetworkTimeouts struct {
   149  	DialTimeout  time.Duration
   150  	ReadTimeout  time.Duration
   151  	WriteTimeout time.Duration
   152  }
   153  
   154  // Metadata contains configuration for the metadata requests to the Kafka
   155  // cluster.
   156  type Metadata struct {
   157  	RetryMax     int
   158  	RetryBackoff time.Duration
   159  }
   160  
   161  // Producer contains configuration for the producer's retries when failing to
   162  // post a message to a Kafka partition.
   163  type Producer struct {
   164  	RetryMax     int
   165  	RetryBackoff time.Duration
   166  }
   167  
   168  // Consumer contains configuration for the consumer's retries when failing to
   169  // read from a Kafa partition.
   170  type Consumer struct {
   171  	RetryBackoff time.Duration
   172  }
   173  
   174  // Topic contains the settings to use when creating Kafka topics
   175  type Topic struct {
   176  	ReplicationFactor int16
   177  }
   178  
   179  // Debug contains configuration for the orderer's debug parameters.
   180  type Debug struct {
   181  	BroadcastTraceDir string
   182  	DeliverTraceDir   string
   183  }
   184  
   185  // Operations configures the operations endpoint for the orderer.
   186  type Operations struct {
   187  	ListenAddress string
   188  	TLS           TLS
   189  }
   190  
   191  // Metrics configures the metrics provider for the orderer.
   192  type Metrics struct {
   193  	Provider string
   194  	Statsd   Statsd
   195  }
   196  
   197  // Statsd provides the configuration required to emit statsd metrics from the orderer.
   198  type Statsd struct {
   199  	Network       string
   200  	Address       string
   201  	WriteInterval time.Duration
   202  	Prefix        string
   203  }
   204  
   205  // Admin configures the admin endpoint for the orderer.
   206  type Admin struct {
   207  	ListenAddress string
   208  	TLS           TLS
   209  }
   210  
   211  // ChannelParticipation provides the channel participation API configuration for the orderer.
   212  // Channel participation uses the same ListenAddress and TLS settings of the Operations service.
   213  type ChannelParticipation struct {
   214  	Enabled            bool
   215  	MaxRequestBodySize uint32
   216  }
   217  
   218  // Defaults carries the default orderer configuration values.
   219  var Defaults = TopLevel{
   220  	General: General{
   221  		ListenAddress:   "127.0.0.1",
   222  		ListenPort:      7050,
   223  		BootstrapMethod: "file",
   224  		BootstrapFile:   "genesisblock",
   225  		Profile: Profile{
   226  			Enabled: false,
   227  			Address: "0.0.0.0:6060",
   228  		},
   229  		Cluster: Cluster{
   230  			ReplicationMaxRetries:                12,
   231  			RPCTimeout:                           time.Second * 7,
   232  			DialTimeout:                          time.Second * 5,
   233  			ReplicationBufferSize:                20971520,
   234  			SendBufferSize:                       10,
   235  			ReplicationBackgroundRefreshInterval: time.Minute * 5,
   236  			ReplicationRetryTimeout:              time.Second * 5,
   237  			ReplicationPullTimeout:               time.Second * 5,
   238  			CertExpirationWarningThreshold:       time.Hour * 24 * 7,
   239  		},
   240  		LocalMSPDir: "msp",
   241  		LocalMSPID:  "SampleOrg",
   242  		BCCSP:       bccsp.GetDefaultOpts(),
   243  		Authentication: Authentication{
   244  			TimeWindow: time.Duration(15 * time.Minute),
   245  		},
   246  		MaxRecvMsgSize: comm.DefaultMaxRecvMsgSize,
   247  		MaxSendMsgSize: comm.DefaultMaxSendMsgSize,
   248  	},
   249  	FileLedger: FileLedger{
   250  		Location: "/var/hyperledger/production/orderer",
   251  	},
   252  	Kafka: Kafka{
   253  		Retry: Retry{
   254  			ShortInterval: 1 * time.Minute,
   255  			ShortTotal:    10 * time.Minute,
   256  			LongInterval:  10 * time.Minute,
   257  			LongTotal:     12 * time.Hour,
   258  			NetworkTimeouts: NetworkTimeouts{
   259  				DialTimeout:  30 * time.Second,
   260  				ReadTimeout:  30 * time.Second,
   261  				WriteTimeout: 30 * time.Second,
   262  			},
   263  			Metadata: Metadata{
   264  				RetryBackoff: 250 * time.Millisecond,
   265  				RetryMax:     3,
   266  			},
   267  			Producer: Producer{
   268  				RetryBackoff: 100 * time.Millisecond,
   269  				RetryMax:     3,
   270  			},
   271  			Consumer: Consumer{
   272  				RetryBackoff: 2 * time.Second,
   273  			},
   274  		},
   275  		Verbose: false,
   276  		Version: sarama.V0_10_2_0,
   277  		TLS: TLS{
   278  			Enabled: false,
   279  		},
   280  		Topic: Topic{
   281  			ReplicationFactor: 3,
   282  		},
   283  	},
   284  	Debug: Debug{
   285  		BroadcastTraceDir: "",
   286  		DeliverTraceDir:   "",
   287  	},
   288  	Operations: Operations{
   289  		ListenAddress: "127.0.0.1:0",
   290  	},
   291  	Metrics: Metrics{
   292  		Provider: "disabled",
   293  	},
   294  	ChannelParticipation: ChannelParticipation{
   295  		Enabled:            false,
   296  		MaxRequestBodySize: 1024 * 1024,
   297  	},
   298  	Admin: Admin{
   299  		ListenAddress: "127.0.0.1:0",
   300  	},
   301  }
   302  
   303  // Load parses the orderer YAML file and environment, producing
   304  // a struct suitable for config use, returning error on failure.
   305  func Load() (*TopLevel, error) {
   306  	return cache.load()
   307  }
   308  
   309  // configCache stores marshalled bytes of config structures that produced from
   310  // EnhancedExactUnmarshal. Cache key is the path of the configuration file that was used.
   311  type configCache struct {
   312  	mutex sync.Mutex
   313  	cache map[string][]byte
   314  }
   315  
   316  var cache = &configCache{}
   317  
   318  // Load will load the configuration and cache it on the first call; subsequent
   319  // calls will return a clone of the configuration that was previously loaded.
   320  func (c *configCache) load() (*TopLevel, error) {
   321  	var uconf TopLevel
   322  
   323  	config := viperutil.New()
   324  	config.SetConfigName("orderer")
   325  
   326  	if err := config.ReadInConfig(); err != nil {
   327  		return nil, fmt.Errorf("Error reading configuration: %s", err)
   328  	}
   329  
   330  	c.mutex.Lock()
   331  	defer c.mutex.Unlock()
   332  	serializedConf, ok := c.cache[config.ConfigFileUsed()]
   333  	if !ok {
   334  		err := config.EnhancedExactUnmarshal(&uconf)
   335  		if err != nil {
   336  			return nil, fmt.Errorf("Error unmarshalling config into struct: %s", err)
   337  		}
   338  
   339  		serializedConf, err = json.Marshal(uconf)
   340  		if err != nil {
   341  			return nil, err
   342  		}
   343  
   344  		if c.cache == nil {
   345  			c.cache = map[string][]byte{}
   346  		}
   347  		c.cache[config.ConfigFileUsed()] = serializedConf
   348  	}
   349  
   350  	err := json.Unmarshal(serializedConf, &uconf)
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  	uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed()))
   355  
   356  	return &uconf, nil
   357  }
   358  
   359  func (c *TopLevel) completeInitialization(configDir string) {
   360  	defer func() {
   361  		// Translate any paths for cluster TLS configuration if applicable
   362  		if c.General.Cluster.ClientPrivateKey != "" {
   363  			coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientPrivateKey)
   364  		}
   365  		if c.General.Cluster.ClientCertificate != "" {
   366  			coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientCertificate)
   367  		}
   368  		c.General.Cluster.RootCAs = translateCAs(configDir, c.General.Cluster.RootCAs)
   369  		// Translate any paths for general TLS configuration
   370  		c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs)
   371  		c.General.TLS.ClientRootCAs = translateCAs(configDir, c.General.TLS.ClientRootCAs)
   372  		coreconfig.TranslatePathInPlace(configDir, &c.General.TLS.PrivateKey)
   373  		coreconfig.TranslatePathInPlace(configDir, &c.General.TLS.Certificate)
   374  		coreconfig.TranslatePathInPlace(configDir, &c.General.BootstrapFile)
   375  		coreconfig.TranslatePathInPlace(configDir, &c.General.LocalMSPDir)
   376  		// Translate file ledger location
   377  		coreconfig.TranslatePathInPlace(configDir, &c.FileLedger.Location)
   378  	}()
   379  
   380  	for {
   381  		switch {
   382  		case c.General.ListenAddress == "":
   383  			logger.Infof("General.ListenAddress unset, setting to %s", Defaults.General.ListenAddress)
   384  			c.General.ListenAddress = Defaults.General.ListenAddress
   385  		case c.General.ListenPort == 0:
   386  			logger.Infof("General.ListenPort unset, setting to %v", Defaults.General.ListenPort)
   387  			c.General.ListenPort = Defaults.General.ListenPort
   388  		case c.General.BootstrapMethod == "":
   389  			if c.General.GenesisMethod != "" {
   390  				// This is to keep the compatibility with old config file that uses genesismethod
   391  				logger.Warn("General.GenesisMethod should be replaced by General.BootstrapMethod")
   392  				c.General.BootstrapMethod = c.General.GenesisMethod
   393  			} else {
   394  				c.General.BootstrapMethod = Defaults.General.BootstrapMethod
   395  			}
   396  		case c.General.BootstrapFile == "":
   397  			if c.General.GenesisFile != "" {
   398  				// This is to keep the compatibility with old config file that uses genesisfile
   399  				logger.Warn("General.GenesisFile should be replaced by General.BootstrapFile")
   400  				c.General.BootstrapFile = c.General.GenesisFile
   401  			} else {
   402  				c.General.BootstrapFile = Defaults.General.BootstrapFile
   403  			}
   404  		case c.General.Cluster.RPCTimeout == 0:
   405  			c.General.Cluster.RPCTimeout = Defaults.General.Cluster.RPCTimeout
   406  		case c.General.Cluster.DialTimeout == 0:
   407  			c.General.Cluster.DialTimeout = Defaults.General.Cluster.DialTimeout
   408  		case c.General.Cluster.ReplicationMaxRetries == 0:
   409  			c.General.Cluster.ReplicationMaxRetries = Defaults.General.Cluster.ReplicationMaxRetries
   410  		case c.General.Cluster.SendBufferSize == 0:
   411  			c.General.Cluster.SendBufferSize = Defaults.General.Cluster.SendBufferSize
   412  		case c.General.Cluster.ReplicationBufferSize == 0:
   413  			c.General.Cluster.ReplicationBufferSize = Defaults.General.Cluster.ReplicationBufferSize
   414  		case c.General.Cluster.ReplicationPullTimeout == 0:
   415  			c.General.Cluster.ReplicationPullTimeout = Defaults.General.Cluster.ReplicationPullTimeout
   416  		case c.General.Cluster.ReplicationRetryTimeout == 0:
   417  			c.General.Cluster.ReplicationRetryTimeout = Defaults.General.Cluster.ReplicationRetryTimeout
   418  		case c.General.Cluster.ReplicationBackgroundRefreshInterval == 0:
   419  			c.General.Cluster.ReplicationBackgroundRefreshInterval = Defaults.General.Cluster.ReplicationBackgroundRefreshInterval
   420  		case c.General.Cluster.CertExpirationWarningThreshold == 0:
   421  			c.General.Cluster.CertExpirationWarningThreshold = Defaults.General.Cluster.CertExpirationWarningThreshold
   422  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.Certificate == "":
   423  			logger.Panicf("General.Kafka.TLS.Certificate must be set if General.Kafka.TLS.Enabled is set to true.")
   424  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.PrivateKey == "":
   425  			logger.Panicf("General.Kafka.TLS.PrivateKey must be set if General.Kafka.TLS.Enabled is set to true.")
   426  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.RootCAs == nil:
   427  			logger.Panicf("General.Kafka.TLS.CertificatePool must be set if General.Kafka.TLS.Enabled is set to true.")
   428  
   429  		case c.Kafka.SASLPlain.Enabled && c.Kafka.SASLPlain.User == "":
   430  			logger.Panic("General.Kafka.SASLPlain.User must be set if General.Kafka.SASLPlain.Enabled is set to true.")
   431  		case c.Kafka.SASLPlain.Enabled && c.Kafka.SASLPlain.Password == "":
   432  			logger.Panic("General.Kafka.SASLPlain.Password must be set if General.Kafka.SASLPlain.Enabled is set to true.")
   433  
   434  		case c.General.Profile.Enabled && c.General.Profile.Address == "":
   435  			logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", Defaults.General.Profile.Address)
   436  			c.General.Profile.Address = Defaults.General.Profile.Address
   437  
   438  		case c.General.LocalMSPDir == "":
   439  			logger.Infof("General.LocalMSPDir unset, setting to %s", Defaults.General.LocalMSPDir)
   440  			c.General.LocalMSPDir = Defaults.General.LocalMSPDir
   441  		case c.General.LocalMSPID == "":
   442  			logger.Infof("General.LocalMSPID unset, setting to %s", Defaults.General.LocalMSPID)
   443  			c.General.LocalMSPID = Defaults.General.LocalMSPID
   444  
   445  		case c.General.Authentication.TimeWindow == 0:
   446  			logger.Infof("General.Authentication.TimeWindow unset, setting to %s", Defaults.General.Authentication.TimeWindow)
   447  			c.General.Authentication.TimeWindow = Defaults.General.Authentication.TimeWindow
   448  
   449  		case c.Kafka.Retry.ShortInterval == 0:
   450  			logger.Infof("Kafka.Retry.ShortInterval unset, setting to %v", Defaults.Kafka.Retry.ShortInterval)
   451  			c.Kafka.Retry.ShortInterval = Defaults.Kafka.Retry.ShortInterval
   452  		case c.Kafka.Retry.ShortTotal == 0:
   453  			logger.Infof("Kafka.Retry.ShortTotal unset, setting to %v", Defaults.Kafka.Retry.ShortTotal)
   454  			c.Kafka.Retry.ShortTotal = Defaults.Kafka.Retry.ShortTotal
   455  		case c.Kafka.Retry.LongInterval == 0:
   456  			logger.Infof("Kafka.Retry.LongInterval unset, setting to %v", Defaults.Kafka.Retry.LongInterval)
   457  			c.Kafka.Retry.LongInterval = Defaults.Kafka.Retry.LongInterval
   458  		case c.Kafka.Retry.LongTotal == 0:
   459  			logger.Infof("Kafka.Retry.LongTotal unset, setting to %v", Defaults.Kafka.Retry.LongTotal)
   460  			c.Kafka.Retry.LongTotal = Defaults.Kafka.Retry.LongTotal
   461  
   462  		case c.Kafka.Retry.NetworkTimeouts.DialTimeout == 0:
   463  			logger.Infof("Kafka.Retry.NetworkTimeouts.DialTimeout unset, setting to %v", Defaults.Kafka.Retry.NetworkTimeouts.DialTimeout)
   464  			c.Kafka.Retry.NetworkTimeouts.DialTimeout = Defaults.Kafka.Retry.NetworkTimeouts.DialTimeout
   465  		case c.Kafka.Retry.NetworkTimeouts.ReadTimeout == 0:
   466  			logger.Infof("Kafka.Retry.NetworkTimeouts.ReadTimeout unset, setting to %v", Defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout)
   467  			c.Kafka.Retry.NetworkTimeouts.ReadTimeout = Defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout
   468  		case c.Kafka.Retry.NetworkTimeouts.WriteTimeout == 0:
   469  			logger.Infof("Kafka.Retry.NetworkTimeouts.WriteTimeout unset, setting to %v", Defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout)
   470  			c.Kafka.Retry.NetworkTimeouts.WriteTimeout = Defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout
   471  
   472  		case c.Kafka.Retry.Metadata.RetryBackoff == 0:
   473  			logger.Infof("Kafka.Retry.Metadata.RetryBackoff unset, setting to %v", Defaults.Kafka.Retry.Metadata.RetryBackoff)
   474  			c.Kafka.Retry.Metadata.RetryBackoff = Defaults.Kafka.Retry.Metadata.RetryBackoff
   475  		case c.Kafka.Retry.Metadata.RetryMax == 0:
   476  			logger.Infof("Kafka.Retry.Metadata.RetryMax unset, setting to %v", Defaults.Kafka.Retry.Metadata.RetryMax)
   477  			c.Kafka.Retry.Metadata.RetryMax = Defaults.Kafka.Retry.Metadata.RetryMax
   478  
   479  		case c.Kafka.Retry.Producer.RetryBackoff == 0:
   480  			logger.Infof("Kafka.Retry.Producer.RetryBackoff unset, setting to %v", Defaults.Kafka.Retry.Producer.RetryBackoff)
   481  			c.Kafka.Retry.Producer.RetryBackoff = Defaults.Kafka.Retry.Producer.RetryBackoff
   482  		case c.Kafka.Retry.Producer.RetryMax == 0:
   483  			logger.Infof("Kafka.Retry.Producer.RetryMax unset, setting to %v", Defaults.Kafka.Retry.Producer.RetryMax)
   484  			c.Kafka.Retry.Producer.RetryMax = Defaults.Kafka.Retry.Producer.RetryMax
   485  
   486  		case c.Kafka.Retry.Consumer.RetryBackoff == 0:
   487  			logger.Infof("Kafka.Retry.Consumer.RetryBackoff unset, setting to %v", Defaults.Kafka.Retry.Consumer.RetryBackoff)
   488  			c.Kafka.Retry.Consumer.RetryBackoff = Defaults.Kafka.Retry.Consumer.RetryBackoff
   489  
   490  		case c.Kafka.Version == sarama.KafkaVersion{}:
   491  			logger.Infof("Kafka.Version unset, setting to %v", Defaults.Kafka.Version)
   492  			c.Kafka.Version = Defaults.Kafka.Version
   493  
   494  		case c.Admin.TLS.Enabled && !c.Admin.TLS.ClientAuthRequired:
   495  			logger.Panic("Admin.TLS.ClientAuthRequired must be set to true if Admin.TLS.Enabled is set to true")
   496  
   497  		case c.General.MaxRecvMsgSize == 0:
   498  			logger.Infof("General.MaxRecvMsgSize is unset, setting to %v", Defaults.General.MaxRecvMsgSize)
   499  			c.General.MaxRecvMsgSize = Defaults.General.MaxRecvMsgSize
   500  		case c.General.MaxSendMsgSize == 0:
   501  			logger.Infof("General.MaxSendMsgSize is unset, setting to %v", Defaults.General.MaxSendMsgSize)
   502  			c.General.MaxSendMsgSize = Defaults.General.MaxSendMsgSize
   503  		default:
   504  			return
   505  		}
   506  	}
   507  }
   508  
   509  func translateCAs(configDir string, certificateAuthorities []string) []string {
   510  	var results []string
   511  	for _, ca := range certificateAuthorities {
   512  		result := coreconfig.TranslatePath(configDir, ca)
   513  		results = append(results, result)
   514  	}
   515  	return results
   516  }