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