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  }