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  }