-
Notifications
You must be signed in to change notification settings - Fork 8.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FAB-2396] Move orderer config to common Proposer
https://jira.hyperledger.org/browse/FAB-2396 This is the second in a series of CRs which will migrate the config value handlers off of their own custom transaction handling code and onto the common Proposer code. This will not only reduce the amount of reimplimented logic (and corresponding bugs) and will also facilitate the two-way config translation for the configtxgen tool. Change-Id: I0e4bd1228c12b02fbf074b05379e917d463bf877 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
- v3.0.0
- v3.0.0-rc1
- v3.0.0-preview
- v3.0.0-beta
- v2.5.10
- v2.5.9
- v2.5.8
- v2.5.7
- v2.5.6
- v2.5.5
- v2.5.4
- v2.5.3
- v2.5.2
- v2.5.1
- v2.5.0
- v2.5.0-beta2
- v2.5.0-beta
- v2.5.0-alpha3
- v2.5.0-alpha2
- v2.5.0-alpha1
- v2.4.9
- v2.4.8
- v2.4.7
- v2.4.6
- v2.4.5
- v2.4.4
- v2.4.3
- v2.4.2
- v2.4.1
- v2.4.0
- v2.4.0-beta
- v2.4.0-alpha
- v2.3.3
- v2.3.2
- v2.3.1
- v2.3.0
- v2.2.15
- v2.2.14
- v2.2.13
- v2.2.12
- v2.2.11
- v2.2.10
- v2.2.9
- v2.2.8
- v2.2.7
- v2.2.6
- v2.2.5
- v2.2.4
- v2.2.3
- v2.2.2
- v2.2.1
- v2.2.0
- v2.1.1
- v2.1.0
- v2.0.1
- v2.0.0
- v2.0.0-beta
- v2.0.0-alpha
- v1.4.12
- v1.4.11
- v1.4.10
- v1.4.9
- v1.4.8
- v1.4.7
- v1.4.6
- v1.4.5
- v1.4.4
- v1.4.3
- v1.4.2
- v1.4.1
- v1.4.1-rc1
- v1.4.0
- v1.4.0-rc2
- v1.4.0-rc1
- v1.3.0
- v1.3.0-rc1
- v1.2.1
- v1.2.0
- v1.2.0-rc1
- v1.1.1
- v1.1.0
- v1.1.0-rc1
- v1.1.0-preview
- v1.1.0-alpha
- v1.0.6
- v1.0.5
- v1.0.4
- v1.0.3
- v1.0.2
- v1.0.1
- v1.0.0
- v1.0.0-rc1
- v1.0.0-beta
- v1.0.0-alpha2
- v1.0.0-alpha
Jason Yellick
committed
Mar 7, 2017
1 parent
8b20459
commit c8ff4b1
Showing
14 changed files
with
366 additions
and
677 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
333 changes: 0 additions & 333 deletions
333
common/configvalues/channel/orderer/sharedconfig_test.go
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
/* | ||
Copyright IBM Corp. 2016 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package config | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
"strconv" | ||
"strings" | ||
"time" | ||
|
||
api "github.com/hyperledger/fabric/common/configvalues" | ||
"github.com/hyperledger/fabric/common/configvalues/channel/common/organization" | ||
"github.com/hyperledger/fabric/common/configvalues/msp" | ||
ab "github.com/hyperledger/fabric/protos/orderer" | ||
) | ||
|
||
const ( | ||
// OrdererGroupKey is the group name for the orderer config | ||
OrdererGroupKey = "Orderer" | ||
) | ||
|
||
const ( | ||
// ConsensusTypeKey is the cb.ConfigItem type key name for the ConsensusType message | ||
ConsensusTypeKey = "ConsensusType" | ||
|
||
// BatchSizeKey is the cb.ConfigItem type key name for the BatchSize message | ||
BatchSizeKey = "BatchSize" | ||
|
||
// BatchTimeoutKey is the cb.ConfigItem type key name for the BatchTimeout message | ||
BatchTimeoutKey = "BatchTimeout" | ||
|
||
// ChainCreationPolicyNamesKey is the cb.ConfigItem type key name for the ChainCreationPolicyNames message | ||
ChainCreationPolicyNamesKey = "ChainCreationPolicyNames" | ||
|
||
// KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message | ||
KafkaBrokersKey = "KafkaBrokers" | ||
) | ||
|
||
// OrdererProtos is used as the source of the OrdererConfig | ||
type OrdererProtos struct { | ||
ConsensusType *ab.ConsensusType | ||
BatchSize *ab.BatchSize | ||
BatchTimeout *ab.BatchTimeout | ||
ChainCreationPolicyNames *ab.ChainCreationPolicyNames | ||
KafkaBrokers *ab.KafkaBrokers | ||
CreationPolicy *ab.CreationPolicy | ||
} | ||
|
||
// Config is stores the orderer component configuration | ||
type OrdererGroup struct { | ||
*Proposer | ||
*OrdererConfig | ||
|
||
mspConfig *msp.MSPConfigHandler | ||
} | ||
|
||
// NewConfig creates a new *OrdererConfig | ||
func NewOrdererGroup(mspConfig *msp.MSPConfigHandler) *OrdererGroup { | ||
og := &OrdererGroup{ | ||
mspConfig: mspConfig, | ||
} | ||
og.Proposer = NewProposer(og) | ||
return og | ||
} | ||
|
||
// NewGroup returns an Org instance | ||
func (og *OrdererGroup) NewGroup(name string) (api.ValueProposer, error) { | ||
return organization.NewOrgConfig(name, og.mspConfig), nil | ||
} | ||
|
||
func (og *OrdererGroup) Allocate() Values { | ||
return NewOrdererConfig(og) | ||
} | ||
|
||
// OrdererConfig holds the orderer configuration information | ||
type OrdererConfig struct { | ||
*standardValues | ||
protos *OrdererProtos | ||
ordererGroup *OrdererGroup | ||
|
||
batchTimeout time.Duration | ||
} | ||
|
||
// NewOrdererConfig creates a new instance of the orderer config | ||
func NewOrdererConfig(og *OrdererGroup) *OrdererConfig { | ||
oc := &OrdererConfig{ | ||
protos: &OrdererProtos{}, | ||
ordererGroup: og, | ||
} | ||
|
||
var err error | ||
oc.standardValues, err = NewStandardValues(oc.protos) | ||
if err != nil { | ||
logger.Panicf("Programming error: %s", err) | ||
} | ||
return oc | ||
} | ||
|
||
// Commit writes the orderer config back to the orderer config group | ||
func (oc *OrdererConfig) Commit() { | ||
oc.ordererGroup.OrdererConfig = oc | ||
} | ||
|
||
// ConsensusType returns the configured consensus type | ||
func (oc *OrdererConfig) ConsensusType() string { | ||
return oc.protos.ConsensusType.Type | ||
} | ||
|
||
// BatchSize returns the maximum number of messages to include in a block | ||
func (oc *OrdererConfig) BatchSize() *ab.BatchSize { | ||
return oc.protos.BatchSize | ||
} | ||
|
||
// BatchTimeout returns the amount of time to wait before creating a batch | ||
func (oc *OrdererConfig) BatchTimeout() time.Duration { | ||
return oc.batchTimeout | ||
} | ||
|
||
// ChainCreationPolicyNames returns the policy names which are allowed for chain creation | ||
// This field is only set for the system ordering chain | ||
func (oc *OrdererConfig) ChainCreationPolicyNames() []string { | ||
return oc.protos.ChainCreationPolicyNames.Names | ||
} | ||
|
||
// KafkaBrokers returns the addresses (IP:port notation) of a set of "bootstrap" | ||
// Kafka brokers, i.e. this is not necessarily the entire set of Kafka brokers | ||
// used for ordering | ||
func (oc *OrdererConfig) KafkaBrokers() []string { | ||
return oc.protos.KafkaBrokers.Brokers | ||
} | ||
|
||
func (oc *OrdererConfig) Validate(groups map[string]api.ValueProposer) error { | ||
for _, validator := range []func() error{ | ||
oc.validateConsensusType, | ||
oc.validateBatchSize, | ||
oc.validateBatchTimeout, | ||
oc.validateKafkaBrokers, | ||
} { | ||
if err := validator(); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (oc *OrdererConfig) validateConsensusType() error { | ||
if oc.ordererGroup.OrdererConfig != nil && oc.ordererGroup.ConsensusType() != oc.protos.ConsensusType.Type { | ||
// The first config we accept the consensus type regardless | ||
return fmt.Errorf("Attempted to change the consensus type from %s to %s after init", oc.ordererGroup.ConsensusType(), oc.protos.ConsensusType.Type) | ||
} | ||
return nil | ||
} | ||
|
||
func (oc *OrdererConfig) validateBatchSize() error { | ||
if oc.protos.BatchSize.MaxMessageCount == 0 { | ||
return fmt.Errorf("Attempted to set the batch size max message count to an invalid value: 0") | ||
} | ||
if oc.protos.BatchSize.AbsoluteMaxBytes == 0 { | ||
return fmt.Errorf("Attempted to set the batch size absolute max bytes to an invalid value: 0") | ||
} | ||
if oc.protos.BatchSize.PreferredMaxBytes == 0 { | ||
return fmt.Errorf("Attempted to set the batch size preferred max bytes to an invalid value: 0") | ||
} | ||
if oc.protos.BatchSize.PreferredMaxBytes > oc.protos.BatchSize.AbsoluteMaxBytes { | ||
return fmt.Errorf("Attempted to set the batch size preferred max bytes (%v) greater than the absolute max bytes (%v).", oc.protos.BatchSize.PreferredMaxBytes, oc.protos.BatchSize.AbsoluteMaxBytes) | ||
} | ||
return nil | ||
} | ||
|
||
func (oc *OrdererConfig) validateBatchTimeout() error { | ||
var err error | ||
oc.batchTimeout, err = time.ParseDuration(oc.protos.BatchTimeout.Timeout) | ||
if err != nil { | ||
return fmt.Errorf("Attempted to set the batch timeout to a invalid value: %s", err) | ||
} | ||
if oc.batchTimeout <= 0 { | ||
return fmt.Errorf("Attempted to set the batch timeout to a non-positive value: %s", oc.batchTimeout) | ||
} | ||
return nil | ||
} | ||
|
||
func (oc *OrdererConfig) validateKafkaBrokers() error { | ||
for _, broker := range oc.protos.KafkaBrokers.Brokers { | ||
if !brokerEntrySeemsValid(broker) { | ||
return fmt.Errorf("Invalid broker entry: %s", broker) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// This does just a barebones sanity check. | ||
func brokerEntrySeemsValid(broker string) bool { | ||
if !strings.Contains(broker, ":") { | ||
return false | ||
} | ||
|
||
parts := strings.Split(broker, ":") | ||
if len(parts) > 2 { | ||
return false | ||
} | ||
|
||
host := parts[0] | ||
port := parts[1] | ||
|
||
if _, err := strconv.ParseUint(port, 10, 16); err != nil { | ||
return false | ||
} | ||
|
||
// Valid hostnames may contain only the ASCII letters 'a' through 'z' (in a | ||
// case-insensitive manner), the digits '0' through '9', and the hyphen. IP | ||
// v4 addresses are represented in dot-decimal notation, which consists of | ||
// four decimal numbers, each ranging from 0 to 255, separated by dots, | ||
// e.g., 172.16.254.1 | ||
// The following regular expression: | ||
// 1. allows just a-z (case-insensitive), 0-9, and the dot and hyphen characters | ||
// 2. does not allow leading trailing dots or hyphens | ||
re, _ := regexp.Compile("^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9.-]*[a-zA-Z0-9])$") | ||
matched := re.FindString(host) | ||
return len(matched) == len(host) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
Copyright IBM Corp. 2016 All Rights Reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package config | ||
|
||
import ( | ||
"testing" | ||
|
||
ab "github.com/hyperledger/fabric/protos/orderer" | ||
|
||
logging "github.com/op/go-logging" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func init() { | ||
logging.SetLevel(logging.DEBUG, "") | ||
} | ||
|
||
func TestConsensusType(t *testing.T) { | ||
oc := &OrdererConfig{ordererGroup: &OrdererGroup{}, protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "foo"}}} | ||
assert.NoError(t, oc.validateConsensusType(), "Should have validly set new consensus type") | ||
|
||
oc = &OrdererConfig{ | ||
ordererGroup: &OrdererGroup{OrdererConfig: &OrdererConfig{protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "foo"}}}}, | ||
protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "foo"}}, | ||
} | ||
assert.NoError(t, oc.validateConsensusType(), "Should have kept consensus type") | ||
|
||
oc = &OrdererConfig{ | ||
ordererGroup: &OrdererGroup{OrdererConfig: &OrdererConfig{protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "bar"}}}}, | ||
protos: &OrdererProtos{ConsensusType: &ab.ConsensusType{Type: "foo"}}, | ||
} | ||
assert.Error(t, oc.validateConsensusType(), "Should have failed to change consensus type") | ||
} | ||
|
||
func TestBatchSize(t *testing.T) { | ||
|
||
validMaxMessageCount := uint32(10) | ||
validAbsoluteMaxBytes := uint32(1000) | ||
validPreferredMaxBytes := uint32(500) | ||
|
||
oc := &OrdererConfig{protos: &OrdererProtos{BatchSize: &ab.BatchSize{MaxMessageCount: validMaxMessageCount, AbsoluteMaxBytes: validAbsoluteMaxBytes, PreferredMaxBytes: validPreferredMaxBytes}}} | ||
assert.NoError(t, oc.validateBatchSize(), "BatchSize was valid") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{BatchSize: &ab.BatchSize{MaxMessageCount: 0, AbsoluteMaxBytes: validAbsoluteMaxBytes, PreferredMaxBytes: validPreferredMaxBytes}}} | ||
assert.Error(t, oc.validateBatchSize(), "MaxMessageCount was zero") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{BatchSize: &ab.BatchSize{MaxMessageCount: validMaxMessageCount, AbsoluteMaxBytes: 0, PreferredMaxBytes: validPreferredMaxBytes}}} | ||
assert.Error(t, oc.validateBatchSize(), "AbsoluteMaxBytes was zero") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{BatchSize: &ab.BatchSize{MaxMessageCount: validMaxMessageCount, AbsoluteMaxBytes: validAbsoluteMaxBytes, PreferredMaxBytes: validAbsoluteMaxBytes + 1}}} | ||
assert.Error(t, oc.validateBatchSize(), "PreferredMaxBytes larger to AbsoluteMaxBytes") | ||
} | ||
|
||
func TestBatchTimeout(t *testing.T) { | ||
oc := &OrdererConfig{protos: &OrdererProtos{BatchTimeout: &ab.BatchTimeout{Timeout: "1s"}}} | ||
assert.NoError(t, oc.validateBatchTimeout(), "Valid batch timeout") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{BatchTimeout: &ab.BatchTimeout{Timeout: "-1s"}}} | ||
assert.Error(t, oc.validateBatchTimeout(), "Negative batch timeout") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{BatchTimeout: &ab.BatchTimeout{Timeout: "0s"}}} | ||
assert.Error(t, oc.validateBatchTimeout(), "Zero batch timeout") | ||
} | ||
|
||
func TestKafkaBrokers(t *testing.T) { | ||
oc := &OrdererConfig{protos: &OrdererProtos{KafkaBrokers: &ab.KafkaBrokers{Brokers: []string{"127.0.0.1:9092", "foo.bar:9092"}}}} | ||
assert.NoError(t, oc.validateKafkaBrokers(), "Valid kafka brokers") | ||
|
||
oc = &OrdererConfig{protos: &OrdererProtos{KafkaBrokers: &ab.KafkaBrokers{Brokers: []string{"127.0.0.1", "foo.bar", "127.0.0.1:-1", "localhost:65536", "foo.bar.:9092", ".127.0.0.1:9092", "-foo.bar:9092"}}}} | ||
assert.Error(t, oc.validateKafkaBrokers(), "Invalid kafka brokers") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters