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