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