go_study/fabric-main/orderer/common/localconfig/config.go

357 lines
12 KiB
Go

// Copyright IBM Corp. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package localconfig
import (
"encoding/json"
"fmt"
"path/filepath"
"sync"
"time"
bccsp "github.com/hyperledger/fabric/bccsp/factory"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/viperutil"
coreconfig "github.com/hyperledger/fabric/core/config"
"github.com/hyperledger/fabric/internal/pkg/comm"
)
var logger = flogging.MustGetLogger("localconfig")
// TopLevel directly corresponds to the orderer config YAML.
type TopLevel struct {
General General
FileLedger FileLedger
Debug Debug
Consensus interface{}
Operations Operations
Metrics Metrics
ChannelParticipation ChannelParticipation
Admin Admin
}
// General contains config which should be common among all orderer types.
type General struct {
ListenAddress string
ListenPort uint16
TLS TLS
Cluster Cluster
Keepalive Keepalive
ConnectionTimeout time.Duration
GenesisMethod string // Deprecated: For compatibility only, will be replaced by BootstrapMethod
GenesisFile string // Deprecated: For compatibility only, will be replaced by BootstrapFile
BootstrapMethod string // Deprecated: System channel is no longer supported.
BootstrapFile string // Deprecated: System channel is no longer supported.
Profile Profile
LocalMSPDir string
LocalMSPID string
BCCSP *bccsp.FactoryOpts
Authentication Authentication
MaxRecvMsgSize int32
MaxSendMsgSize int32
}
type Cluster struct {
ListenAddress string
ListenPort uint16
ServerCertificate string
ServerPrivateKey string
ClientCertificate string
ClientPrivateKey string
RootCAs []string
DialTimeout time.Duration
RPCTimeout time.Duration
ReplicationBufferSize int
ReplicationPullTimeout time.Duration
ReplicationRetryTimeout time.Duration
ReplicationBackgroundRefreshInterval time.Duration
ReplicationMaxRetries int
SendBufferSize int
CertExpirationWarningThreshold time.Duration
TLSHandshakeTimeShift time.Duration
}
// Keepalive contains configuration for gRPC servers.
type Keepalive struct {
ServerMinInterval time.Duration
ServerInterval time.Duration
ServerTimeout time.Duration
}
// TLS contains configuration for TLS connections.
type TLS struct {
Enabled bool
PrivateKey string
Certificate string
RootCAs []string
ClientAuthRequired bool
ClientRootCAs []string
TLSHandshakeTimeShift time.Duration
}
// Authentication contains configuration parameters related to authenticating
// client messages.
type Authentication struct {
TimeWindow time.Duration
NoExpirationChecks bool
}
// Profile contains configuration for Go pprof profiling.
type Profile struct {
Enabled bool
Address string
}
// FileLedger contains configuration for the file-based ledger.
type FileLedger struct {
Location string
Prefix string // For compatibility only. This setting is no longer supported.
}
// Debug contains configuration for the orderer's debug parameters.
type Debug struct {
BroadcastTraceDir string
DeliverTraceDir string
}
// Operations configures the operations endpoint for the orderer.
type Operations struct {
ListenAddress string
TLS TLS
}
// Metrics configures the metrics provider for the orderer.
type Metrics struct {
Provider string
Statsd Statsd
}
// Statsd provides the configuration required to emit statsd metrics from the orderer.
type Statsd struct {
Network string
Address string
WriteInterval time.Duration
Prefix string
}
// Admin configures the admin endpoint for the orderer.
type Admin struct {
ListenAddress string
TLS TLS
}
// ChannelParticipation provides the channel participation API configuration for the orderer.
// Channel participation uses the same ListenAddress and TLS settings of the Operations service.
type ChannelParticipation struct {
Enabled bool // Deprecated: always overridden to 'true'
MaxRequestBodySize uint32
}
// Defaults carries the default orderer configuration values.
var Defaults = TopLevel{
General: General{
ListenAddress: "127.0.0.1",
ListenPort: 7050,
BootstrapMethod: "none",
Profile: Profile{
Enabled: false,
Address: "0.0.0.0:6060",
},
Cluster: Cluster{
ReplicationMaxRetries: 12,
RPCTimeout: time.Second * 7,
DialTimeout: time.Second * 5,
ReplicationBufferSize: 20971520,
SendBufferSize: 100,
ReplicationBackgroundRefreshInterval: time.Minute * 5,
ReplicationRetryTimeout: time.Second * 5,
ReplicationPullTimeout: time.Second * 5,
CertExpirationWarningThreshold: time.Hour * 24 * 7,
},
LocalMSPDir: "msp",
LocalMSPID: "SampleOrg",
BCCSP: bccsp.GetDefaultOpts(),
Authentication: Authentication{
TimeWindow: time.Duration(15 * time.Minute),
},
MaxRecvMsgSize: comm.DefaultMaxRecvMsgSize,
MaxSendMsgSize: comm.DefaultMaxSendMsgSize,
},
FileLedger: FileLedger{
Location: "/var/hyperledger/production/orderer",
},
Debug: Debug{
BroadcastTraceDir: "",
DeliverTraceDir: "",
},
Operations: Operations{
ListenAddress: "127.0.0.1:0",
},
Metrics: Metrics{
Provider: "disabled",
},
ChannelParticipation: ChannelParticipation{
Enabled: true,
MaxRequestBodySize: 1024 * 1024,
},
Admin: Admin{
ListenAddress: "127.0.0.1:0",
},
}
// Load parses the orderer YAML file and environment, producing
// a struct suitable for config use, returning error on failure.
func Load() (*TopLevel, error) {
return cache.load()
}
// configCache stores marshalled bytes of config structures that produced from
// EnhancedExactUnmarshal. Cache key is the path of the configuration file that was used.
type configCache struct {
mutex sync.Mutex
cache map[string][]byte
}
var cache = &configCache{}
// Load will load the configuration and cache it on the first call; subsequent
// calls will return a clone of the configuration that was previously loaded.
func (c *configCache) load() (*TopLevel, error) {
var uconf TopLevel
config := viperutil.New()
config.SetConfigName("orderer")
if err := config.ReadInConfig(); err != nil {
return nil, fmt.Errorf("Error reading configuration: %s", err)
}
c.mutex.Lock()
defer c.mutex.Unlock()
serializedConf, ok := c.cache[config.ConfigFileUsed()]
if !ok {
err := config.EnhancedExactUnmarshal(&uconf)
if err != nil {
return nil, fmt.Errorf("Error unmarshalling config into struct: %s", err)
}
serializedConf, err = json.Marshal(uconf)
if err != nil {
return nil, err
}
if c.cache == nil {
c.cache = map[string][]byte{}
}
c.cache[config.ConfigFileUsed()] = serializedConf
}
err := json.Unmarshal(serializedConf, &uconf)
if err != nil {
return nil, err
}
uconf.completeInitialization(filepath.Dir(config.ConfigFileUsed()))
return &uconf, nil
}
func (c *TopLevel) completeInitialization(configDir string) {
defer func() {
// Translate any paths for cluster TLS configuration if applicable
if c.General.Cluster.ClientPrivateKey != "" {
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientPrivateKey)
}
if c.General.Cluster.ClientCertificate != "" {
coreconfig.TranslatePathInPlace(configDir, &c.General.Cluster.ClientCertificate)
}
c.General.Cluster.RootCAs = translateCAs(configDir, c.General.Cluster.RootCAs)
// Translate any paths for general TLS configuration
c.General.TLS.RootCAs = translateCAs(configDir, c.General.TLS.RootCAs)
c.General.TLS.ClientRootCAs = translateCAs(configDir, c.General.TLS.ClientRootCAs)
coreconfig.TranslatePathInPlace(configDir, &c.General.TLS.PrivateKey)
coreconfig.TranslatePathInPlace(configDir, &c.General.TLS.Certificate)
coreconfig.TranslatePathInPlace(configDir, &c.General.BootstrapFile)
coreconfig.TranslatePathInPlace(configDir, &c.General.LocalMSPDir)
// Translate file ledger location
coreconfig.TranslatePathInPlace(configDir, &c.FileLedger.Location)
}()
for {
switch {
case c.General.ListenAddress == "":
logger.Infof("General.ListenAddress unset, setting to %s", Defaults.General.ListenAddress)
c.General.ListenAddress = Defaults.General.ListenAddress
case c.General.ListenPort == 0:
logger.Infof("General.ListenPort unset, setting to %v", Defaults.General.ListenPort)
c.General.ListenPort = Defaults.General.ListenPort
case c.General.BootstrapMethod == "":
if c.General.GenesisMethod != "" {
// This is to keep the compatibility with old config file that uses genesismethod
logger.Warn("General.GenesisMethod should be replaced by General.BootstrapMethod")
c.General.BootstrapMethod = c.General.GenesisMethod
} else {
c.General.BootstrapMethod = Defaults.General.BootstrapMethod
}
case c.General.Cluster.RPCTimeout == 0:
c.General.Cluster.RPCTimeout = Defaults.General.Cluster.RPCTimeout
case c.General.Cluster.DialTimeout == 0:
c.General.Cluster.DialTimeout = Defaults.General.Cluster.DialTimeout
case c.General.Cluster.ReplicationMaxRetries == 0:
c.General.Cluster.ReplicationMaxRetries = Defaults.General.Cluster.ReplicationMaxRetries
case c.General.Cluster.SendBufferSize == 0:
c.General.Cluster.SendBufferSize = Defaults.General.Cluster.SendBufferSize
case c.General.Cluster.ReplicationBufferSize == 0:
c.General.Cluster.ReplicationBufferSize = Defaults.General.Cluster.ReplicationBufferSize
case c.General.Cluster.ReplicationPullTimeout == 0:
c.General.Cluster.ReplicationPullTimeout = Defaults.General.Cluster.ReplicationPullTimeout
case c.General.Cluster.ReplicationRetryTimeout == 0:
c.General.Cluster.ReplicationRetryTimeout = Defaults.General.Cluster.ReplicationRetryTimeout
case c.General.Cluster.ReplicationBackgroundRefreshInterval == 0:
c.General.Cluster.ReplicationBackgroundRefreshInterval = Defaults.General.Cluster.ReplicationBackgroundRefreshInterval
case c.General.Cluster.CertExpirationWarningThreshold == 0:
c.General.Cluster.CertExpirationWarningThreshold = Defaults.General.Cluster.CertExpirationWarningThreshold
case c.General.Profile.Enabled && c.General.Profile.Address == "":
logger.Infof("Profiling enabled and General.Profile.Address unset, setting to %s", Defaults.General.Profile.Address)
c.General.Profile.Address = Defaults.General.Profile.Address
case c.General.LocalMSPDir == "":
logger.Infof("General.LocalMSPDir unset, setting to %s", Defaults.General.LocalMSPDir)
c.General.LocalMSPDir = Defaults.General.LocalMSPDir
case c.General.LocalMSPID == "":
logger.Infof("General.LocalMSPID unset, setting to %s", Defaults.General.LocalMSPID)
c.General.LocalMSPID = Defaults.General.LocalMSPID
case c.General.Authentication.TimeWindow == 0:
logger.Infof("General.Authentication.TimeWindow unset, setting to %s", Defaults.General.Authentication.TimeWindow)
c.General.Authentication.TimeWindow = Defaults.General.Authentication.TimeWindow
case !c.ChannelParticipation.Enabled:
logger.Info("General.ChannelParticipation.Enabled was set to false, setting to true")
c.ChannelParticipation.Enabled = true
case c.Admin.TLS.Enabled && !c.Admin.TLS.ClientAuthRequired:
logger.Panic("Admin.TLS.ClientAuthRequired must be set to true if Admin.TLS.Enabled is set to true")
case c.General.MaxRecvMsgSize == 0:
logger.Infof("General.MaxRecvMsgSize is unset, setting to %v", Defaults.General.MaxRecvMsgSize)
c.General.MaxRecvMsgSize = Defaults.General.MaxRecvMsgSize
case c.General.MaxSendMsgSize == 0:
logger.Infof("General.MaxSendMsgSize is unset, setting to %v", Defaults.General.MaxSendMsgSize)
c.General.MaxSendMsgSize = Defaults.General.MaxSendMsgSize
default:
return
}
}
}
func translateCAs(configDir string, certificateAuthorities []string) []string {
var results []string
for _, ca := range certificateAuthorities {
result := coreconfig.TranslatePath(configDir, ca)
results = append(results, result)
}
return results
}