github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/common/configtx/tool/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 localconfig 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/op/go-logging" 29 "github.com/spf13/viper" 30 31 bccsp "github.com/hyperledger/fabric/bccsp/factory" 32 ) 33 34 const ( 35 // SampleInsecureProfile references the sample profile which does not include any MSPs and uses solo for consensus 36 SampleInsecureProfile = "SampleInsecureSolo" 37 38 // SampleSingleMSPSoloProfile references the sample profile which includes only the sample MSP and uses solo for consensus 39 SampleSingleMSPSoloProfile = "SampleSingleMSPSolo" 40 ) 41 42 var logger = logging.MustGetLogger("configtx/tool/localconfig") 43 44 // Prefix is the default config prefix for the orderer 45 const Prefix string = "CONFIGTX" 46 47 // TopLevel contains the genesis structures for use by the provisional bootstrapper 48 type TopLevel struct { 49 Profiles map[string]*Profile 50 Organizations []*Organization 51 Application *Application 52 Orderer *Orderer 53 } 54 55 // TopLevel contains the genesis structures for use by the provisional bootstrapper 56 type Profile struct { 57 Application *Application 58 Orderer *Orderer 59 } 60 61 // Application encodes the configuration needed for the config transaction 62 type Application struct { 63 Organizations []*Organization 64 } 65 66 type Organization struct { 67 Name string 68 ID string 69 MSPDir string 70 BCCSP *bccsp.FactoryOpts 71 72 // Note, the viper deserialization does not seem to care for 73 // embedding of types, so we use one organization structure for 74 // both orderers and applications 75 AnchorPeers []*AnchorPeer 76 } 77 78 type AnchorPeer struct { 79 Host string 80 Port int 81 } 82 83 type ApplicationOrganization struct { 84 Organization 85 } 86 87 // Orderer contains config which is used for orderer genesis by the provisional bootstrapper 88 type Orderer struct { 89 OrdererType string 90 Addresses []string 91 BatchTimeout time.Duration 92 BatchSize BatchSize 93 Kafka Kafka 94 Organizations []*Organization 95 } 96 97 // BatchSize contains configuration affecting the size of batches 98 type BatchSize struct { 99 MaxMessageCount uint32 100 AbsoluteMaxBytes uint32 101 PreferredMaxBytes uint32 102 } 103 104 // Kafka contains config for the Kafka orderer 105 type Kafka struct { 106 Brokers []string 107 } 108 109 var genesisDefaults = TopLevel{ 110 Orderer: &Orderer{ 111 OrdererType: "solo", 112 Addresses: []string{"127.0.0.1:7050"}, 113 BatchTimeout: 10 * time.Second, 114 BatchSize: BatchSize{ 115 MaxMessageCount: 10, 116 AbsoluteMaxBytes: 100000000, 117 PreferredMaxBytes: 512 * 1024, 118 }, 119 Kafka: Kafka{ 120 Brokers: []string{"127.0.0.1:9092"}, 121 }, 122 }, 123 } 124 125 func (g *Profile) completeInitialization() { 126 for { 127 switch { 128 case g.Orderer.OrdererType == "": 129 logger.Infof("Orderer.OrdererType unset, setting to %s", genesisDefaults.Orderer.OrdererType) 130 g.Orderer.OrdererType = genesisDefaults.Orderer.OrdererType 131 case g.Orderer.Addresses == nil: 132 logger.Infof("Orderer.Addresses unset, setting to %s", genesisDefaults.Orderer.Addresses) 133 g.Orderer.Addresses = genesisDefaults.Orderer.Addresses 134 case g.Orderer.BatchTimeout == 0: 135 logger.Infof("Orderer.BatchTimeout unset, setting to %s", genesisDefaults.Orderer.BatchTimeout) 136 g.Orderer.BatchTimeout = genesisDefaults.Orderer.BatchTimeout 137 case g.Orderer.BatchSize.MaxMessageCount == 0: 138 logger.Infof("Orderer.BatchSize.MaxMessageCount unset, setting to %s", genesisDefaults.Orderer.BatchSize.MaxMessageCount) 139 g.Orderer.BatchSize.MaxMessageCount = genesisDefaults.Orderer.BatchSize.MaxMessageCount 140 case g.Orderer.BatchSize.AbsoluteMaxBytes == 0: 141 logger.Infof("Orderer.BatchSize.AbsoluteMaxBytes unset, setting to %s", genesisDefaults.Orderer.BatchSize.AbsoluteMaxBytes) 142 g.Orderer.BatchSize.AbsoluteMaxBytes = genesisDefaults.Orderer.BatchSize.AbsoluteMaxBytes 143 case g.Orderer.BatchSize.PreferredMaxBytes == 0: 144 logger.Infof("Orderer.BatchSize.PreferredMaxBytes unset, setting to %s", genesisDefaults.Orderer.BatchSize.PreferredMaxBytes) 145 g.Orderer.BatchSize.PreferredMaxBytes = genesisDefaults.Orderer.BatchSize.PreferredMaxBytes 146 case g.Orderer.Kafka.Brokers == nil: 147 logger.Infof("Orderer.Kafka.Brokers unset, setting to %v", genesisDefaults.Orderer.Kafka.Brokers) 148 g.Orderer.Kafka.Brokers = genesisDefaults.Orderer.Kafka.Brokers 149 default: 150 return 151 } 152 } 153 } 154 155 func Load(profile string) *Profile { 156 config := viper.New() 157 158 config.SetConfigName("configtx") 159 var cfgPath string 160 161 // Path to look for the config file in based on GOPATH 162 searchPath := []string{ 163 os.Getenv("ORDERER_CFG_PATH"), 164 os.Getenv("PEER_CFG_PATH"), 165 } 166 167 for _, p := range filepath.SplitList(os.Getenv("GOPATH")) { 168 searchPath = append(searchPath, filepath.Join(p, "src/github.com/hyperledger/fabric/common/configtx/tool/")) 169 } 170 171 for _, genesisPath := range searchPath { 172 logger.Infof("Checking for configtx.yaml at: %s", genesisPath) 173 if _, err := os.Stat(filepath.Join(genesisPath, "configtx.yaml")); err != nil { 174 // The yaml file does not exist in this component of the path 175 continue 176 } 177 cfgPath = genesisPath 178 } 179 180 if cfgPath == "" { 181 logger.Fatalf("Could not find configtx.yaml in paths of %s. Try setting ORDERER_CFG_PATH, PEER_CFG_PATH, or GOPATH correctly", searchPath) 182 } 183 config.AddConfigPath(cfgPath) // Path to look for the config file in 184 185 // for environment variables 186 config.SetEnvPrefix(Prefix) 187 config.AutomaticEnv() 188 // This replacer allows substitution within the particular profile without having to fully qualify the name 189 replacer := strings.NewReplacer(strings.ToUpper(fmt.Sprintf("profiles.%s.", profile)), "", ".", "_") 190 config.SetEnvKeyReplacer(replacer) 191 192 err := config.ReadInConfig() 193 if err != nil { 194 panic(fmt.Errorf("Error reading %s plugin config from %s: %s", Prefix, cfgPath, err)) 195 } 196 197 var uconf TopLevel 198 199 err = viperutil.EnhancedExactUnmarshal(config, &uconf) 200 if err != nil { 201 panic(fmt.Errorf("Error unmarshaling into structure: %s", err)) 202 } 203 204 result, ok := uconf.Profiles[profile] 205 if !ok { 206 logger.Panicf("Could not find profile %s", profile) 207 } 208 209 result.completeInitialization() 210 211 return result 212 }