github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/localconfig/config.go (about) 1 /* 2 Copyright IBM Corp. 2016 All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package config 18 19 import ( 20 "strings" 21 "time" 22 23 "github.com/hyperledger/fabric/common/flogging" 24 "github.com/hyperledger/fabric/common/viperutil" 25 26 "github.com/Shopify/sarama" 27 "github.com/op/go-logging" 28 "github.com/spf13/viper" 29 30 cf "github.com/hyperledger/fabric/core/config" 31 32 "path/filepath" 33 34 bccsp "github.com/hyperledger/fabric/bccsp/factory" 35 ) 36 37 const ( 38 pkgLogID = "orderer/common/localconfig" 39 40 // Prefix identifies the prefix for the orderer-related ENV vars. 41 Prefix = "ORDERER" 42 ) 43 44 var ( 45 logger *logging.Logger 46 47 configName string 48 ) 49 50 func init() { 51 logger = flogging.MustGetLogger(pkgLogID) 52 flogging.SetModuleLevel(pkgLogID, "error") 53 54 configName = strings.ToLower(Prefix) 55 } 56 57 // TopLevel directly corresponds to the orderer config YAML. 58 // Note, for non 1-1 mappings, you may append 59 // something like `mapstructure:"weirdFoRMat"` to 60 // modify the default mapping, see the "Unmarshal" 61 // section of https://github.com/spf13/viper for more info 62 type TopLevel struct { 63 General General 64 FileLedger FileLedger 65 RAMLedger RAMLedger 66 Kafka Kafka 67 } 68 69 // General contains config which should be common among all orderer types. 70 type General struct { 71 LedgerType string 72 ListenAddress string 73 ListenPort uint16 74 TLS TLS 75 GenesisMethod string 76 GenesisProfile string 77 GenesisFile string 78 Profile Profile 79 LogLevel string 80 LocalMSPDir string 81 LocalMSPID string 82 BCCSP *bccsp.FactoryOpts 83 } 84 85 // TLS contains config for TLS connections. 86 type TLS struct { 87 Enabled bool 88 PrivateKey string 89 Certificate string 90 RootCAs []string 91 ClientAuthEnabled bool 92 ClientRootCAs []string 93 } 94 95 // Profile contains configuration for Go pprof profiling. 96 type Profile struct { 97 Enabled bool 98 Address string 99 } 100 101 // FileLedger contains configuration for the file-based ledger. 102 type FileLedger struct { 103 Location string 104 Prefix string 105 } 106 107 // RAMLedger contains configuration for the RAM ledger. 108 type RAMLedger struct { 109 HistorySize uint 110 } 111 112 // Kafka contains configuration for the Kafka-based orderer. 113 type Kafka struct { 114 Retry Retry 115 Verbose bool 116 Version sarama.KafkaVersion // TODO Move this to global config 117 TLS TLS 118 } 119 120 // Retry contains configuration related to retries and timeouts when the 121 // connection to the Kafka cluster cannot be established, or when Metadata 122 // requests needs to be repeated (because the cluster is in the middle of a 123 // leader election). 124 type Retry struct { 125 ShortInterval time.Duration 126 ShortTotal time.Duration 127 LongInterval time.Duration 128 LongTotal time.Duration 129 NetworkTimeouts NetworkTimeouts 130 Metadata Metadata 131 Producer Producer 132 Consumer Consumer 133 } 134 135 // NetworkTimeouts contains the socket timeouts for network requests to the 136 // Kafka cluster. 137 type NetworkTimeouts struct { 138 DialTimeout time.Duration 139 ReadTimeout time.Duration 140 WriteTimeout time.Duration 141 } 142 143 // Metadata contains configuration for the metadata requests to the Kafka 144 // cluster. 145 type Metadata struct { 146 RetryMax int 147 RetryBackoff time.Duration 148 } 149 150 // Producer contains configuration for the producer's retries when failing to 151 // post a message to a Kafka partition. 152 type Producer struct { 153 RetryMax int 154 RetryBackoff time.Duration 155 } 156 157 // Consumer contains configuration for the consumer's retries when failing to 158 // read from a Kafa partition. 159 type Consumer struct { 160 RetryBackoff time.Duration 161 } 162 163 var defaults = TopLevel{ 164 General: General{ 165 LedgerType: "file", 166 ListenAddress: "127.0.0.1", 167 ListenPort: 7050, 168 GenesisMethod: "provisional", 169 GenesisProfile: "SampleSingleMSPSolo", 170 GenesisFile: "genesisblock", 171 Profile: Profile{ 172 Enabled: false, 173 Address: "0.0.0.0:6060", 174 }, 175 LogLevel: "INFO", 176 LocalMSPDir: "msp", 177 LocalMSPID: "DEFAULT", 178 BCCSP: bccsp.GetDefaultOpts(), 179 }, 180 RAMLedger: RAMLedger{ 181 HistorySize: 10000, 182 }, 183 FileLedger: FileLedger{ 184 Location: "/var/hyperledger/production/orderer", 185 Prefix: "hyperledger-fabric-ordererledger", 186 }, 187 Kafka: Kafka{ 188 Retry: Retry{ 189 ShortInterval: 1 * time.Minute, 190 ShortTotal: 10 * time.Minute, 191 LongInterval: 10 * time.Minute, 192 LongTotal: 12 * time.Hour, 193 NetworkTimeouts: NetworkTimeouts{ 194 DialTimeout: 30 * time.Second, 195 ReadTimeout: 30 * time.Second, 196 WriteTimeout: 30 * time.Second, 197 }, 198 Metadata: Metadata{ 199 RetryBackoff: 250 * time.Millisecond, 200 RetryMax: 3, 201 }, 202 Producer: Producer{ 203 RetryBackoff: 100 * time.Millisecond, 204 RetryMax: 3, 205 }, 206 Consumer: Consumer{ 207 RetryBackoff: 2 * time.Second, 208 }, 209 }, 210 Verbose: false, 211 Version: sarama.V0_9_0_1, 212 TLS: TLS{ 213 Enabled: false, 214 }, 215 }, 216 } 217 218 // Load parses the orderer.yaml file and environment, producing a struct suitable for config use 219 func Load() *TopLevel { 220 config := viper.New() 221 cf.InitViper(config, configName) 222 223 // for environment variables 224 config.SetEnvPrefix(Prefix) 225 config.AutomaticEnv() 226 replacer := strings.NewReplacer(".", "_") 227 config.SetEnvKeyReplacer(replacer) 228 229 err := config.ReadInConfig() 230 if err != nil { 231 logger.Panic("Error reading configuration:", err) 232 } 233 234 var uconf TopLevel 235 err = viperutil.EnhancedExactUnmarshal(config, &uconf) 236 if err != nil { 237 logger.Panic("Error unmarshaling config into struct:", err) 238 } 239 240 uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed())) 241 242 return &uconf 243 } 244 245 func (c *TopLevel) completeInitialization(configDir string) { 246 defer func() { 247 // Translate any paths 248 c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs) 249 c.General.TLS.ClientRootCAs = translateCAs(configDir, c.General.TLS.ClientRootCAs) 250 cf.TranslatePathInPlace(configDir, &c.General.TLS.PrivateKey) 251 cf.TranslatePathInPlace(configDir, &c.General.TLS.Certificate) 252 cf.TranslatePathInPlace(configDir, &c.General.GenesisFile) 253 cf.TranslatePathInPlace(configDir, &c.General.LocalMSPDir) 254 }() 255 256 for { 257 switch { 258 case c.General.LedgerType == "": 259 logger.Infof("General.LedgerType unset, setting to %s", defaults.General.LedgerType) 260 c.General.LedgerType = defaults.General.LedgerType 261 262 case c.General.ListenAddress == "": 263 logger.Infof("General.ListenAddress unset, setting to %s", defaults.General.ListenAddress) 264 c.General.ListenAddress = defaults.General.ListenAddress 265 case c.General.ListenPort == 0: 266 logger.Infof("General.ListenPort unset, setting to %s", defaults.General.ListenPort) 267 c.General.ListenPort = defaults.General.ListenPort 268 269 case c.General.LogLevel == "": 270 logger.Infof("General.LogLevel unset, setting to %s", defaults.General.LogLevel) 271 c.General.LogLevel = defaults.General.LogLevel 272 273 case c.General.GenesisMethod == "": 274 c.General.GenesisMethod = defaults.General.GenesisMethod 275 case c.General.GenesisFile == "": 276 c.General.GenesisFile = defaults.General.GenesisFile 277 case c.General.GenesisProfile == "": 278 c.General.GenesisProfile = defaults.General.GenesisProfile 279 280 case c.Kafka.TLS.Enabled && c.Kafka.TLS.Certificate == "": 281 logger.Panicf("General.Kafka.TLS.Certificate must be set if General.Kafka.TLS.Enabled is set to true.") 282 case c.Kafka.TLS.Enabled && c.Kafka.TLS.PrivateKey == "": 283 logger.Panicf("General.Kafka.TLS.PrivateKey must be set if General.Kafka.TLS.Enabled is set to true.") 284 case c.Kafka.TLS.Enabled && c.Kafka.TLS.RootCAs == nil: 285 logger.Panicf("General.Kafka.TLS.CertificatePool must be set if General.Kafka.TLS.Enabled is set to true.") 286 287 case c.General.Profile.Enabled && c.General.Profile.Address == "": 288 logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", defaults.General.Profile.Address) 289 c.General.Profile.Address = defaults.General.Profile.Address 290 291 case c.General.LocalMSPDir == "": 292 logger.Infof("General.LocalMSPDir unset, setting to %s", defaults.General.LocalMSPDir) 293 c.General.LocalMSPDir = defaults.General.LocalMSPDir 294 case c.General.LocalMSPID == "": 295 logger.Infof("General.LocalMSPID unset, setting to %s", defaults.General.LocalMSPID) 296 c.General.LocalMSPID = defaults.General.LocalMSPID 297 298 case c.FileLedger.Prefix == "": 299 logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix) 300 c.FileLedger.Prefix = defaults.FileLedger.Prefix 301 302 case c.Kafka.Retry.ShortInterval == 0*time.Minute: 303 logger.Infof("Kafka.Retry.ShortInterval unset, setting to %v", defaults.Kafka.Retry.ShortInterval) 304 c.Kafka.Retry.ShortInterval = defaults.Kafka.Retry.ShortInterval 305 case c.Kafka.Retry.ShortTotal == 0*time.Minute: 306 logger.Infof("Kafka.Retry.ShortTotal unset, setting to %v", defaults.Kafka.Retry.ShortTotal) 307 c.Kafka.Retry.ShortTotal = defaults.Kafka.Retry.ShortTotal 308 case c.Kafka.Retry.LongInterval == 0*time.Minute: 309 logger.Infof("Kafka.Retry.LongInterval unset, setting to %v", defaults.Kafka.Retry.LongInterval) 310 c.Kafka.Retry.LongInterval = defaults.Kafka.Retry.LongInterval 311 case c.Kafka.Retry.LongTotal == 0*time.Minute: 312 logger.Infof("Kafka.Retry.LongTotal unset, setting to %v", defaults.Kafka.Retry.LongTotal) 313 c.Kafka.Retry.LongTotal = defaults.Kafka.Retry.LongTotal 314 315 case c.Kafka.Retry.NetworkTimeouts.DialTimeout == 0*time.Second: 316 logger.Infof("Kafka.Retry.NetworkTimeouts.DialTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.DialTimeout) 317 c.Kafka.Retry.NetworkTimeouts.DialTimeout = defaults.Kafka.Retry.NetworkTimeouts.DialTimeout 318 case c.Kafka.Retry.NetworkTimeouts.ReadTimeout == 0*time.Second: 319 logger.Infof("Kafka.Retry.NetworkTimeouts.ReadTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout) 320 c.Kafka.Retry.NetworkTimeouts.ReadTimeout = defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout 321 case c.Kafka.Retry.NetworkTimeouts.WriteTimeout == 0*time.Second: 322 logger.Infof("Kafka.Retry.NetworkTimeouts.WriteTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout) 323 c.Kafka.Retry.NetworkTimeouts.WriteTimeout = defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout 324 325 case c.Kafka.Retry.Metadata.RetryBackoff == 0*time.Second: 326 logger.Infof("Kafka.Retry.Metadata.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Metadata.RetryBackoff) 327 c.Kafka.Retry.Metadata.RetryBackoff = defaults.Kafka.Retry.Metadata.RetryBackoff 328 case c.Kafka.Retry.Metadata.RetryMax == 0: 329 logger.Infof("Kafka.Retry.Metadata.RetryMax unset, setting to %v", defaults.Kafka.Retry.Metadata.RetryMax) 330 c.Kafka.Retry.Metadata.RetryMax = defaults.Kafka.Retry.Metadata.RetryMax 331 332 case c.Kafka.Retry.Producer.RetryBackoff == 0*time.Second: 333 logger.Infof("Kafka.Retry.Producer.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Producer.RetryBackoff) 334 c.Kafka.Retry.Producer.RetryBackoff = defaults.Kafka.Retry.Producer.RetryBackoff 335 case c.Kafka.Retry.Producer.RetryMax == 0: 336 logger.Infof("Kafka.Retry.Producer.RetryMax unset, setting to %v", defaults.Kafka.Retry.Producer.RetryMax) 337 c.Kafka.Retry.Producer.RetryMax = defaults.Kafka.Retry.Producer.RetryMax 338 339 case c.Kafka.Retry.Consumer.RetryBackoff == 0*time.Second: 340 logger.Infof("Kafka.Retry.Consumer.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Consumer.RetryBackoff) 341 c.Kafka.Retry.Consumer.RetryBackoff = defaults.Kafka.Retry.Consumer.RetryBackoff 342 343 case c.Kafka.Version == sarama.KafkaVersion{}: 344 logger.Infof("Kafka.Version unset, setting to %v", defaults.Kafka.Version) 345 c.Kafka.Version = defaults.Kafka.Version 346 347 default: 348 return 349 } 350 } 351 } 352 353 func translateCAs(configDir string, certificateAuthorities []string) []string { 354 var results []string 355 for _, ca := range certificateAuthorities { 356 result := cf.TranslatePath(configDir, ca) 357 results = append(results, result) 358 } 359 return results 360 }