github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/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/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/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 Genesis Genesis 68 SbftLocal SbftLocal 69 } 70 71 // General contains config which should be common among all orderer types. 72 type General struct { 73 LedgerType string 74 ListenAddress string 75 ListenPort uint16 76 TLS TLS 77 GenesisMethod string 78 GenesisProfile string 79 GenesisFile string 80 Profile Profile 81 LogLevel string 82 LocalMSPDir string 83 LocalMSPID string 84 BCCSP *bccsp.FactoryOpts 85 } 86 87 // TLS contains config for TLS connections. 88 type TLS struct { 89 Enabled bool 90 PrivateKey string 91 Certificate string 92 RootCAs []string 93 ClientAuthEnabled bool 94 ClientRootCAs []string 95 } 96 97 // Profile contains configuration for Go pprof profiling. 98 type Profile struct { 99 Enabled bool 100 Address string 101 } 102 103 // FileLedger contains configuration for the file-based ledger. 104 type FileLedger struct { 105 Location string 106 Prefix string 107 } 108 109 // RAMLedger contains configuration for the RAM ledger. 110 type RAMLedger struct { 111 HistorySize uint 112 } 113 114 // Kafka contains configuration for the Kafka-based orderer. 115 type Kafka struct { 116 Retry Retry 117 Verbose bool 118 Version sarama.KafkaVersion // TODO Move this to global config 119 TLS TLS 120 } 121 122 // Retry contains config for the reconnection attempts to the Kafka brokers. 123 type Retry struct { 124 Period time.Duration 125 Stop time.Duration 126 } 127 128 // Genesis is a deprecated structure which was used to put 129 // values into the genesis block, but this is now handled elsewhere. 130 // SBFT did not reference these values via the genesis block however 131 // so it is being left here for backwards compatibility purposes. 132 type Genesis struct { 133 DeprecatedBatchTimeout time.Duration 134 DeprecatedBatchSize uint32 135 SbftShared SbftShared 136 } 137 138 // SbftLocal contains configuration for the SBFT peer/replica. 139 type SbftLocal struct { 140 PeerCommAddr string 141 CertFile string 142 KeyFile string 143 DataDir string 144 } 145 146 // SbftShared contains config for the SBFT network. 147 type SbftShared struct { 148 N uint64 149 F uint64 150 RequestTimeoutNsec uint64 151 Peers map[string]string // Address to Cert mapping 152 } 153 154 var defaults = TopLevel{ 155 General: General{ 156 LedgerType: "ram", 157 ListenAddress: "127.0.0.1", 158 ListenPort: 7050, 159 GenesisMethod: "provisional", 160 GenesisProfile: "SampleSingleMSPSolo", 161 GenesisFile: "genesisblock", 162 Profile: Profile{ 163 Enabled: false, 164 Address: "0.0.0.0:6060", 165 }, 166 LogLevel: "INFO", 167 LocalMSPDir: "msp", 168 LocalMSPID: "DEFAULT", 169 BCCSP: &bccsp.DefaultOpts, 170 }, 171 RAMLedger: RAMLedger{ 172 HistorySize: 10000, 173 }, 174 FileLedger: FileLedger{ 175 Location: "", 176 Prefix: "hyperledger-fabric-ordererledger", 177 }, 178 Kafka: Kafka{ 179 Retry: Retry{ 180 Period: 3 * time.Second, 181 Stop: 60 * time.Second, 182 }, 183 Verbose: false, 184 Version: sarama.V0_9_0_1, 185 TLS: TLS{ 186 Enabled: false, 187 }, 188 }, 189 Genesis: Genesis{ 190 SbftShared: SbftShared{ 191 N: 1, 192 F: 0, 193 RequestTimeoutNsec: uint64(time.Second.Nanoseconds()), 194 Peers: map[string]string{":6101": "sbft/testdata/cert1.pem"}, 195 }, 196 }, 197 SbftLocal: SbftLocal{ 198 PeerCommAddr: ":6101", 199 CertFile: "sbft/testdata/cert1.pem", 200 KeyFile: "sbft/testdata/key.pem", 201 DataDir: "/tmp", 202 }, 203 } 204 205 // Load parses the orderer.yaml file and environment, producing a struct suitable for config use 206 func Load() *TopLevel { 207 config := viper.New() 208 cf.InitViper(config, configName) 209 210 // for environment variables 211 config.SetEnvPrefix(Prefix) 212 config.AutomaticEnv() 213 replacer := strings.NewReplacer(".", "_") 214 config.SetEnvKeyReplacer(replacer) 215 216 err := config.ReadInConfig() 217 if err != nil { 218 logger.Panic("Error reading configuration:", err) 219 } 220 221 var uconf TopLevel 222 err = viperutil.EnhancedExactUnmarshal(config, &uconf) 223 if err != nil { 224 logger.Panic("Error unmarshaling config into struct:", err) 225 } 226 227 uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed())) 228 229 return &uconf 230 } 231 232 func (c *TopLevel) completeInitialization(configDir string) { 233 defer func() { 234 // Translate any paths 235 c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs) 236 c.General.TLS.ClientRootCAs = translateCAs(configDir, c.General.TLS.ClientRootCAs) 237 cf.TranslatePathInPlace(configDir, &c.General.TLS.PrivateKey) 238 cf.TranslatePathInPlace(configDir, &c.General.TLS.Certificate) 239 cf.TranslatePathInPlace(configDir, &c.General.GenesisFile) 240 cf.TranslatePathInPlace(configDir, &c.General.LocalMSPDir) 241 }() 242 243 for { 244 switch { 245 case c.General.LedgerType == "": 246 logger.Infof("General.LedgerType unset, setting to %s", defaults.General.LedgerType) 247 c.General.LedgerType = defaults.General.LedgerType 248 case c.General.ListenAddress == "": 249 logger.Infof("General.ListenAddress unset, setting to %s", defaults.General.ListenAddress) 250 c.General.ListenAddress = defaults.General.ListenAddress 251 case c.General.ListenPort == 0: 252 logger.Infof("General.ListenPort unset, setting to %s", defaults.General.ListenPort) 253 c.General.ListenPort = defaults.General.ListenPort 254 case c.General.LogLevel == "": 255 logger.Infof("General.LogLevel unset, setting to %s", defaults.General.LogLevel) 256 c.General.LogLevel = defaults.General.LogLevel 257 case c.General.GenesisMethod == "": 258 c.General.GenesisMethod = defaults.General.GenesisMethod 259 case c.General.GenesisFile == "": 260 c.General.GenesisFile = defaults.General.GenesisFile 261 case c.General.GenesisProfile == "": 262 c.General.GenesisProfile = defaults.General.GenesisProfile 263 case c.Kafka.TLS.Enabled && c.Kafka.TLS.Certificate == "": 264 logger.Panicf("General.Kafka.TLS.Certificate must be set if General.Kafka.TLS.Enabled is set to true.") 265 case c.Kafka.TLS.Enabled && c.Kafka.TLS.PrivateKey == "": 266 logger.Panicf("General.Kafka.TLS.PrivateKey must be set if General.Kafka.TLS.Enabled is set to true.") 267 case c.Kafka.TLS.Enabled && c.Kafka.TLS.RootCAs == nil: 268 logger.Panicf("General.Kafka.TLS.CertificatePool must be set if General.Kafka.TLS.Enabled is set to true.") 269 case c.General.Profile.Enabled && (c.General.Profile.Address == ""): 270 logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", defaults.General.Profile.Address) 271 c.General.Profile.Address = defaults.General.Profile.Address 272 case c.General.LocalMSPDir == "": 273 logger.Infof("General.LocalMSPDir unset, setting to %s", defaults.General.LocalMSPDir) 274 c.General.LocalMSPDir = defaults.General.LocalMSPDir 275 case c.General.LocalMSPID == "": 276 logger.Infof("General.LocalMSPID unset, setting to %s", defaults.General.LocalMSPID) 277 c.General.LocalMSPID = defaults.General.LocalMSPID 278 case c.FileLedger.Prefix == "": 279 logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix) 280 c.FileLedger.Prefix = defaults.FileLedger.Prefix 281 case c.Kafka.Retry.Period == 0*time.Second: 282 logger.Infof("Kafka.Retry.Period unset, setting to %v", defaults.Kafka.Retry.Period) 283 c.Kafka.Retry.Period = defaults.Kafka.Retry.Period 284 case c.Kafka.Retry.Stop == 0*time.Second: 285 logger.Infof("Kafka.Retry.Stop unset, setting to %v", defaults.Kafka.Retry.Stop) 286 c.Kafka.Retry.Stop = defaults.Kafka.Retry.Stop 287 default: 288 // A bit hacky, but its type makes it impossible to test for a nil value. 289 // This may be overwritten by the Kafka orderer upon instantiation. 290 c.Kafka.Version = defaults.Kafka.Version 291 return 292 } 293 } 294 } 295 296 func translateCAs(configDir string, certificateAuthorities []string) []string { 297 results := make([]string, 0) 298 for _, ca := range certificateAuthorities { 299 result := cf.TranslatePath(configDir, ca) 300 results = append(results, result) 301 } 302 return results 303 }