github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 "fmt" 21 "os" 22 "path/filepath" 23 "strings" 24 "time" 25 26 "github.com/hyperledger/fabric/common/viperutil" 27 28 "github.com/Shopify/sarama" 29 "github.com/op/go-logging" 30 "github.com/spf13/viper" 31 32 bccsp "github.com/hyperledger/fabric/bccsp/factory" 33 ) 34 35 var logger = logging.MustGetLogger("orderer/config") 36 37 func init() { 38 logging.SetLevel(logging.ERROR, "") 39 } 40 41 // Prefix is the default config prefix for the orderer 42 const Prefix string = "ORDERER" 43 44 // General contains config which should be common among all orderer types 45 type General struct { 46 LedgerType string 47 ListenAddress string 48 ListenPort uint16 49 TLS TLS 50 GenesisMethod string 51 GenesisProfile string 52 GenesisFile string 53 Profile Profile 54 LogLevel string 55 LocalMSPDir string 56 LocalMSPID string 57 BCCSP *bccsp.FactoryOpts 58 } 59 60 //TLS contains config used to configure TLS 61 type TLS struct { 62 Enabled bool 63 PrivateKey string 64 Certificate string 65 RootCAs []string 66 ClientAuthEnabled bool 67 ClientRootCAs []string 68 } 69 70 // Genesis is a deprecated structure which was used to put 71 // values into the genesis block, but this is now handled elsewhere 72 // SBFT did not reference these values via the genesis block however 73 // so it is being left here for backwards compatibility purposes 74 type Genesis struct { 75 DeprecatedBatchTimeout time.Duration 76 DeprecatedBatchSize uint32 77 SbftShared SbftShared 78 } 79 80 // Profile contains configuration for Go pprof profiling 81 type Profile struct { 82 Enabled bool 83 Address string 84 } 85 86 // RAMLedger contains config for the RAM ledger 87 type RAMLedger struct { 88 HistorySize uint 89 } 90 91 // FileLedger contains config for the File ledger 92 type FileLedger struct { 93 Location string 94 Prefix string 95 } 96 97 // Kafka contains config for the Kafka orderer 98 type Kafka struct { 99 Retry Retry 100 Verbose bool 101 Version sarama.KafkaVersion 102 TLS TLS 103 } 104 105 // SbftLocal contains config for the SBFT peer/replica 106 type SbftLocal struct { 107 PeerCommAddr string 108 CertFile string 109 KeyFile string 110 DataDir string 111 } 112 113 // SbftShared contains config for the SBFT network 114 type SbftShared struct { 115 N uint64 116 F uint64 117 RequestTimeoutNsec uint64 118 Peers map[string]string // Address to Cert mapping 119 } 120 121 // Retry contains config for the reconnection attempts to the Kafka brokers 122 type Retry struct { 123 Period time.Duration 124 Stop time.Duration 125 } 126 127 type RuntimeAndGenesis struct { 128 runtime *TopLevel 129 genesis *Genesis 130 } 131 132 // TopLevel directly corresponds to the orderer config yaml 133 // Note, for non 1-1 mappings, you may append 134 // something like `mapstructure:"weirdFoRMat"` to 135 // modify the default mapping, see the "Unmarshal" 136 // section of https://github.com/spf13/viper for more info 137 type TopLevel struct { 138 General General 139 RAMLedger RAMLedger 140 FileLedger FileLedger 141 Kafka Kafka 142 Genesis Genesis 143 SbftLocal SbftLocal 144 } 145 146 var defaults = TopLevel{ 147 General: General{ 148 LedgerType: "ram", 149 ListenAddress: "127.0.0.1", 150 ListenPort: 7050, 151 GenesisMethod: "provisional", 152 GenesisProfile: "SampleSingleMSPSolo", 153 GenesisFile: "./genesisblock", 154 Profile: Profile{ 155 Enabled: false, 156 Address: "0.0.0.0:6060", 157 }, 158 LogLevel: "INFO", 159 LocalMSPDir: "../msp/sampleconfig/", 160 LocalMSPID: "DEFAULT", 161 BCCSP: &bccsp.DefaultOpts, 162 }, 163 RAMLedger: RAMLedger{ 164 HistorySize: 10000, 165 }, 166 FileLedger: FileLedger{ 167 Location: "", 168 Prefix: "hyperledger-fabric-ordererledger", 169 }, 170 Kafka: Kafka{ 171 Retry: Retry{ 172 Period: 3 * time.Second, 173 Stop: 60 * time.Second, 174 }, 175 Verbose: false, 176 Version: sarama.V0_9_0_1, 177 TLS: TLS{ 178 Enabled: false, 179 }, 180 }, 181 Genesis: Genesis{ 182 SbftShared: SbftShared{ 183 N: 1, 184 F: 0, 185 RequestTimeoutNsec: uint64(time.Second.Nanoseconds()), 186 Peers: map[string]string{":6101": "sbft/testdata/cert1.pem"}, 187 }, 188 }, 189 SbftLocal: SbftLocal{ 190 PeerCommAddr: ":6101", 191 CertFile: "sbft/testdata/cert1.pem", 192 KeyFile: "sbft/testdata/key.pem", 193 DataDir: "/tmp", 194 }, 195 } 196 197 func (c *TopLevel) completeInitialization() { 198 defer logger.Infof("Validated configuration to: %+v", c) 199 200 for { 201 switch { 202 case c.General.LedgerType == "": 203 logger.Infof("General.LedgerType unset, setting to %s", defaults.General.LedgerType) 204 c.General.LedgerType = defaults.General.LedgerType 205 case c.General.ListenAddress == "": 206 logger.Infof("General.ListenAddress unset, setting to %s", defaults.General.ListenAddress) 207 c.General.ListenAddress = defaults.General.ListenAddress 208 case c.General.ListenPort == 0: 209 logger.Infof("General.ListenPort unset, setting to %s", defaults.General.ListenPort) 210 c.General.ListenPort = defaults.General.ListenPort 211 case c.General.LogLevel == "": 212 logger.Infof("General.LogLevel unset, setting to %s", defaults.General.LogLevel) 213 c.General.LogLevel = defaults.General.LogLevel 214 case c.General.GenesisMethod == "": 215 c.General.GenesisMethod = defaults.General.GenesisMethod 216 case c.General.GenesisFile == "": 217 c.General.GenesisFile = defaults.General.GenesisFile 218 case c.General.GenesisProfile == "": 219 c.General.GenesisProfile = defaults.General.GenesisProfile 220 case c.Kafka.TLS.Enabled && c.Kafka.TLS.Certificate == "": 221 logger.Panicf("General.Kafka.TLS.Certificate must be set if General.Kafka.TLS.Enabled is set to true.") 222 case c.Kafka.TLS.Enabled && c.Kafka.TLS.PrivateKey == "": 223 logger.Panicf("General.Kafka.TLS.PrivateKey must be set if General.Kafka.TLS.Enabled is set to true.") 224 case c.Kafka.TLS.Enabled && c.Kafka.TLS.RootCAs == nil: 225 logger.Panicf("General.Kafka.TLS.CertificatePool must be set if General.Kafka.TLS.Enabled is set to true.") 226 case c.General.Profile.Enabled && (c.General.Profile.Address == ""): 227 logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", defaults.General.Profile.Address) 228 c.General.Profile.Address = defaults.General.Profile.Address 229 case c.General.LocalMSPDir == "": 230 logger.Infof("General.LocalMSPDir unset, setting to %s", defaults.General.LocalMSPDir) 231 // Note, this is a bit of a weird one, the orderer may set the ORDERER_CFG_PATH after 232 // the file is initialized, so we cannot initialize this in the structure, so we 233 // deference the env portion here 234 c.General.LocalMSPDir = filepath.Join(os.Getenv("ORDERER_CFG_PATH"), defaults.General.LocalMSPDir) 235 case c.General.LocalMSPID == "": 236 logger.Infof("General.LocalMSPID unset, setting to %s", defaults.General.LocalMSPID) 237 c.General.LocalMSPID = defaults.General.LocalMSPID 238 case c.FileLedger.Prefix == "": 239 logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix) 240 c.FileLedger.Prefix = defaults.FileLedger.Prefix 241 case c.Kafka.Retry.Period == 0*time.Second: 242 logger.Infof("Kafka.Retry.Period unset, setting to %v", defaults.Kafka.Retry.Period) 243 c.Kafka.Retry.Period = defaults.Kafka.Retry.Period 244 case c.Kafka.Retry.Stop == 0*time.Second: 245 logger.Infof("Kafka.Retry.Stop unset, setting to %v", defaults.Kafka.Retry.Stop) 246 c.Kafka.Retry.Stop = defaults.Kafka.Retry.Stop 247 default: 248 // A bit hacky, but its type makes it impossible to test for a nil value. 249 // This may be overwritten by the Kafka orderer upon instantiation. 250 c.Kafka.Version = defaults.Kafka.Version 251 return 252 } 253 } 254 } 255 256 // Load parses the orderer.yaml file and environment, producing a struct suitable for config use 257 func Load() *TopLevel { 258 config := viper.New() 259 260 config.SetConfigName("orderer") 261 cfgPath := os.Getenv("ORDERER_CFG_PATH") 262 if cfgPath == "" { 263 logger.Infof("No orderer cfg path set, assuming development environment, deriving from go path") 264 // Path to look for the config file in based on GOPATH 265 gopath := os.Getenv("GOPATH") 266 for _, p := range filepath.SplitList(gopath) { 267 ordererPath := filepath.Join(p, "src/github.com/hyperledger/fabric/orderer/") 268 if _, err := os.Stat(filepath.Join(ordererPath, "orderer.yaml")); err != nil { 269 // The yaml file does not exist in this component of the go src 270 continue 271 } 272 cfgPath = ordererPath 273 } 274 if cfgPath == "" { 275 logger.Fatalf("Could not find orderer.yaml, try setting ORDERER_CFG_PATH or GOPATH correctly") 276 } 277 logger.Infof("Setting ORDERER_CFG_PATH to: %s", cfgPath) 278 os.Setenv("ORDERER_CFG_PATH", cfgPath) 279 } 280 config.AddConfigPath(cfgPath) // Path to look for the config file in 281 282 // for environment variables 283 config.SetEnvPrefix(Prefix) 284 config.AutomaticEnv() 285 replacer := strings.NewReplacer(".", "_") 286 config.SetEnvKeyReplacer(replacer) 287 288 err := config.ReadInConfig() 289 if err != nil { 290 panic(fmt.Errorf("Error reading %s plugin config: %s", Prefix, err)) 291 } 292 293 var uconf TopLevel 294 295 err = viperutil.EnhancedExactUnmarshal(config, &uconf) 296 if err != nil { 297 panic(fmt.Errorf("Error unmarshaling into structure: %s", err)) 298 } 299 300 uconf.completeInitialization() 301 302 return &uconf 303 }