github.com/myafeier/fabric@v1.0.1-0.20170722181825-3a4b1f2bce86/orderer/common/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/common/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  }
    68  
    69  // General contains config which should be common among all orderer types.
    70  type General struct {
    71  	LedgerType     string
    72  	ListenAddress  string
    73  	ListenPort     uint16
    74  	TLS            TLS
    75  	GenesisMethod  string
    76  	GenesisProfile string
    77  	GenesisFile    string
    78  	Profile        Profile
    79  	LogLevel       string
    80  	LocalMSPDir    string
    81  	LocalMSPID     string
    82  	BCCSP          *bccsp.FactoryOpts
    83  }
    84  
    85  // TLS contains config for TLS connections.
    86  type TLS struct {
    87  	Enabled           bool
    88  	PrivateKey        string
    89  	Certificate       string
    90  	RootCAs           []string
    91  	ClientAuthEnabled bool
    92  	ClientRootCAs     []string
    93  }
    94  
    95  // Profile contains configuration for Go pprof profiling.
    96  type Profile struct {
    97  	Enabled bool
    98  	Address string
    99  }
   100  
   101  // FileLedger contains configuration for the file-based ledger.
   102  type FileLedger struct {
   103  	Location string
   104  	Prefix   string
   105  }
   106  
   107  // RAMLedger contains configuration for the RAM ledger.
   108  type RAMLedger struct {
   109  	HistorySize uint
   110  }
   111  
   112  // Kafka contains configuration for the Kafka-based orderer.
   113  type Kafka struct {
   114  	Retry   Retry
   115  	Verbose bool
   116  	Version sarama.KafkaVersion // TODO Move this to global config
   117  	TLS     TLS
   118  }
   119  
   120  // Retry contains configuration related to retries and timeouts when the
   121  // connection to the Kafka cluster cannot be established, or when Metadata
   122  // requests needs to be repeated (because the cluster is in the middle of a
   123  // leader election).
   124  type Retry struct {
   125  	ShortInterval   time.Duration
   126  	ShortTotal      time.Duration
   127  	LongInterval    time.Duration
   128  	LongTotal       time.Duration
   129  	NetworkTimeouts NetworkTimeouts
   130  	Metadata        Metadata
   131  	Producer        Producer
   132  	Consumer        Consumer
   133  }
   134  
   135  // NetworkTimeouts contains the socket timeouts for network requests to the
   136  // Kafka cluster.
   137  type NetworkTimeouts struct {
   138  	DialTimeout  time.Duration
   139  	ReadTimeout  time.Duration
   140  	WriteTimeout time.Duration
   141  }
   142  
   143  // Metadata contains configuration for the metadata requests to the Kafka
   144  // cluster.
   145  type Metadata struct {
   146  	RetryMax     int
   147  	RetryBackoff time.Duration
   148  }
   149  
   150  // Producer contains configuration for the producer's retries when failing to
   151  // post a message to a Kafka partition.
   152  type Producer struct {
   153  	RetryMax     int
   154  	RetryBackoff time.Duration
   155  }
   156  
   157  // Consumer contains configuration for the consumer's retries when failing to
   158  // read from a Kafa partition.
   159  type Consumer struct {
   160  	RetryBackoff time.Duration
   161  }
   162  
   163  var defaults = TopLevel{
   164  	General: General{
   165  		LedgerType:     "file",
   166  		ListenAddress:  "127.0.0.1",
   167  		ListenPort:     7050,
   168  		GenesisMethod:  "provisional",
   169  		GenesisProfile: "SampleSingleMSPSolo",
   170  		GenesisFile:    "genesisblock",
   171  		Profile: Profile{
   172  			Enabled: false,
   173  			Address: "0.0.0.0:6060",
   174  		},
   175  		LogLevel:    "INFO",
   176  		LocalMSPDir: "msp",
   177  		LocalMSPID:  "DEFAULT",
   178  		BCCSP:       bccsp.GetDefaultOpts(),
   179  	},
   180  	RAMLedger: RAMLedger{
   181  		HistorySize: 10000,
   182  	},
   183  	FileLedger: FileLedger{
   184  		Location: "/var/hyperledger/production/orderer",
   185  		Prefix:   "hyperledger-fabric-ordererledger",
   186  	},
   187  	Kafka: Kafka{
   188  		Retry: Retry{
   189  			ShortInterval: 1 * time.Minute,
   190  			ShortTotal:    10 * time.Minute,
   191  			LongInterval:  10 * time.Minute,
   192  			LongTotal:     12 * time.Hour,
   193  			NetworkTimeouts: NetworkTimeouts{
   194  				DialTimeout:  30 * time.Second,
   195  				ReadTimeout:  30 * time.Second,
   196  				WriteTimeout: 30 * time.Second,
   197  			},
   198  			Metadata: Metadata{
   199  				RetryBackoff: 250 * time.Millisecond,
   200  				RetryMax:     3,
   201  			},
   202  			Producer: Producer{
   203  				RetryBackoff: 100 * time.Millisecond,
   204  				RetryMax:     3,
   205  			},
   206  			Consumer: Consumer{
   207  				RetryBackoff: 2 * time.Second,
   208  			},
   209  		},
   210  		Verbose: false,
   211  		Version: sarama.V0_9_0_1,
   212  		TLS: TLS{
   213  			Enabled: false,
   214  		},
   215  	},
   216  }
   217  
   218  // Load parses the orderer.yaml file and environment, producing a struct suitable for config use
   219  func Load() *TopLevel {
   220  	config := viper.New()
   221  	cf.InitViper(config, configName)
   222  
   223  	// for environment variables
   224  	config.SetEnvPrefix(Prefix)
   225  	config.AutomaticEnv()
   226  	replacer := strings.NewReplacer(".", "_")
   227  	config.SetEnvKeyReplacer(replacer)
   228  
   229  	err := config.ReadInConfig()
   230  	if err != nil {
   231  		logger.Panic("Error reading configuration:", err)
   232  	}
   233  
   234  	var uconf TopLevel
   235  	err = viperutil.EnhancedExactUnmarshal(config, &uconf)
   236  	if err != nil {
   237  		logger.Panic("Error unmarshaling config into struct:", err)
   238  	}
   239  
   240  	uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed()))
   241  
   242  	return &uconf
   243  }
   244  
   245  func (c *TopLevel) completeInitialization(configDir string) {
   246  	defer func() {
   247  		// Translate any paths
   248  		c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs)
   249  		c.General.TLS.ClientRootCAs = translateCAs(configDir, c.General.TLS.ClientRootCAs)
   250  		cf.TranslatePathInPlace(configDir, &c.General.TLS.PrivateKey)
   251  		cf.TranslatePathInPlace(configDir, &c.General.TLS.Certificate)
   252  		cf.TranslatePathInPlace(configDir, &c.General.GenesisFile)
   253  		cf.TranslatePathInPlace(configDir, &c.General.LocalMSPDir)
   254  	}()
   255  
   256  	for {
   257  		switch {
   258  		case c.General.LedgerType == "":
   259  			logger.Infof("General.LedgerType unset, setting to %s", defaults.General.LedgerType)
   260  			c.General.LedgerType = defaults.General.LedgerType
   261  
   262  		case c.General.ListenAddress == "":
   263  			logger.Infof("General.ListenAddress unset, setting to %s", defaults.General.ListenAddress)
   264  			c.General.ListenAddress = defaults.General.ListenAddress
   265  		case c.General.ListenPort == 0:
   266  			logger.Infof("General.ListenPort unset, setting to %s", defaults.General.ListenPort)
   267  			c.General.ListenPort = defaults.General.ListenPort
   268  
   269  		case c.General.LogLevel == "":
   270  			logger.Infof("General.LogLevel unset, setting to %s", defaults.General.LogLevel)
   271  			c.General.LogLevel = defaults.General.LogLevel
   272  
   273  		case c.General.GenesisMethod == "":
   274  			c.General.GenesisMethod = defaults.General.GenesisMethod
   275  		case c.General.GenesisFile == "":
   276  			c.General.GenesisFile = defaults.General.GenesisFile
   277  		case c.General.GenesisProfile == "":
   278  			c.General.GenesisProfile = defaults.General.GenesisProfile
   279  
   280  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.Certificate == "":
   281  			logger.Panicf("General.Kafka.TLS.Certificate must be set if General.Kafka.TLS.Enabled is set to true.")
   282  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.PrivateKey == "":
   283  			logger.Panicf("General.Kafka.TLS.PrivateKey must be set if General.Kafka.TLS.Enabled is set to true.")
   284  		case c.Kafka.TLS.Enabled && c.Kafka.TLS.RootCAs == nil:
   285  			logger.Panicf("General.Kafka.TLS.CertificatePool must be set if General.Kafka.TLS.Enabled is set to true.")
   286  
   287  		case c.General.Profile.Enabled && c.General.Profile.Address == "":
   288  			logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", defaults.General.Profile.Address)
   289  			c.General.Profile.Address = defaults.General.Profile.Address
   290  
   291  		case c.General.LocalMSPDir == "":
   292  			logger.Infof("General.LocalMSPDir unset, setting to %s", defaults.General.LocalMSPDir)
   293  			c.General.LocalMSPDir = defaults.General.LocalMSPDir
   294  		case c.General.LocalMSPID == "":
   295  			logger.Infof("General.LocalMSPID unset, setting to %s", defaults.General.LocalMSPID)
   296  			c.General.LocalMSPID = defaults.General.LocalMSPID
   297  
   298  		case c.FileLedger.Prefix == "":
   299  			logger.Infof("FileLedger.Prefix unset, setting to %s", defaults.FileLedger.Prefix)
   300  			c.FileLedger.Prefix = defaults.FileLedger.Prefix
   301  
   302  		case c.Kafka.Retry.ShortInterval == 0*time.Minute:
   303  			logger.Infof("Kafka.Retry.ShortInterval unset, setting to %v", defaults.Kafka.Retry.ShortInterval)
   304  			c.Kafka.Retry.ShortInterval = defaults.Kafka.Retry.ShortInterval
   305  		case c.Kafka.Retry.ShortTotal == 0*time.Minute:
   306  			logger.Infof("Kafka.Retry.ShortTotal unset, setting to %v", defaults.Kafka.Retry.ShortTotal)
   307  			c.Kafka.Retry.ShortTotal = defaults.Kafka.Retry.ShortTotal
   308  		case c.Kafka.Retry.LongInterval == 0*time.Minute:
   309  			logger.Infof("Kafka.Retry.LongInterval unset, setting to %v", defaults.Kafka.Retry.LongInterval)
   310  			c.Kafka.Retry.LongInterval = defaults.Kafka.Retry.LongInterval
   311  		case c.Kafka.Retry.LongTotal == 0*time.Minute:
   312  			logger.Infof("Kafka.Retry.LongTotal unset, setting to %v", defaults.Kafka.Retry.LongTotal)
   313  			c.Kafka.Retry.LongTotal = defaults.Kafka.Retry.LongTotal
   314  
   315  		case c.Kafka.Retry.NetworkTimeouts.DialTimeout == 0*time.Second:
   316  			logger.Infof("Kafka.Retry.NetworkTimeouts.DialTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.DialTimeout)
   317  			c.Kafka.Retry.NetworkTimeouts.DialTimeout = defaults.Kafka.Retry.NetworkTimeouts.DialTimeout
   318  		case c.Kafka.Retry.NetworkTimeouts.ReadTimeout == 0*time.Second:
   319  			logger.Infof("Kafka.Retry.NetworkTimeouts.ReadTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout)
   320  			c.Kafka.Retry.NetworkTimeouts.ReadTimeout = defaults.Kafka.Retry.NetworkTimeouts.ReadTimeout
   321  		case c.Kafka.Retry.NetworkTimeouts.WriteTimeout == 0*time.Second:
   322  			logger.Infof("Kafka.Retry.NetworkTimeouts.WriteTimeout unset, setting to %v", defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout)
   323  			c.Kafka.Retry.NetworkTimeouts.WriteTimeout = defaults.Kafka.Retry.NetworkTimeouts.WriteTimeout
   324  
   325  		case c.Kafka.Retry.Metadata.RetryBackoff == 0*time.Second:
   326  			logger.Infof("Kafka.Retry.Metadata.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Metadata.RetryBackoff)
   327  			c.Kafka.Retry.Metadata.RetryBackoff = defaults.Kafka.Retry.Metadata.RetryBackoff
   328  		case c.Kafka.Retry.Metadata.RetryMax == 0:
   329  			logger.Infof("Kafka.Retry.Metadata.RetryMax unset, setting to %v", defaults.Kafka.Retry.Metadata.RetryMax)
   330  			c.Kafka.Retry.Metadata.RetryMax = defaults.Kafka.Retry.Metadata.RetryMax
   331  
   332  		case c.Kafka.Retry.Producer.RetryBackoff == 0*time.Second:
   333  			logger.Infof("Kafka.Retry.Producer.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Producer.RetryBackoff)
   334  			c.Kafka.Retry.Producer.RetryBackoff = defaults.Kafka.Retry.Producer.RetryBackoff
   335  		case c.Kafka.Retry.Producer.RetryMax == 0:
   336  			logger.Infof("Kafka.Retry.Producer.RetryMax unset, setting to %v", defaults.Kafka.Retry.Producer.RetryMax)
   337  			c.Kafka.Retry.Producer.RetryMax = defaults.Kafka.Retry.Producer.RetryMax
   338  
   339  		case c.Kafka.Retry.Consumer.RetryBackoff == 0*time.Second:
   340  			logger.Infof("Kafka.Retry.Consumer.RetryBackoff unset, setting to %v", defaults.Kafka.Retry.Consumer.RetryBackoff)
   341  			c.Kafka.Retry.Consumer.RetryBackoff = defaults.Kafka.Retry.Consumer.RetryBackoff
   342  
   343  		case c.Kafka.Version == sarama.KafkaVersion{}:
   344  			logger.Infof("Kafka.Version unset, setting to %v", defaults.Kafka.Version)
   345  			c.Kafka.Version = defaults.Kafka.Version
   346  
   347  		default:
   348  			return
   349  		}
   350  	}
   351  }
   352  
   353  func translateCAs(configDir string, certificateAuthorities []string) []string {
   354  	var results []string
   355  	for _, ca := range certificateAuthorities {
   356  		result := cf.TranslatePath(configDir, ca)
   357  		results = append(results, result)
   358  	}
   359  	return results
   360  }