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