Unverified Commit 7c384c52 authored by Yoav Tock's avatar Yoav Tock Committed by Artem Barger
Browse files

FAB-13265 migration status in channelconfig



Change the channelconfig of an Orderer to reflect the extension of ConsensusType:
- MigrationState
- MigrationContext

Add a method to the bundle to validate the migartion steps of
a new versus old config.

Add test-cases to bundle_test.go to unit-test said method.

Improved comments language.

Needed to regenerate and update mocks in 'common' and 'blockcutter' packages
for unit tests to build correctly.

Change-Id: If060c05bcb9a0e0ca81b1f754a2b0e69a7f6c896
Signed-off-by: default avatarYoav Tock <tock@il.ibm.com>
parent aa35c9f8
......@@ -86,6 +86,12 @@ type Orderer interface {
// ConsensusMetadata returns the metadata associated with the consensus type.
ConsensusMetadata() []byte
// ConsensusMigrationState returns the consensus-type migration state.
ConsensusMigrationState() ab.ConsensusType_MigrationState
// ConsensusMigrationContext returns the consensus-type migration context.
ConsensusMigrationContext() uint64
// BatchSize returns the maximum number of messages to include in a block
BatchSize() *ab.BatchSize
......@@ -181,6 +187,9 @@ type OrdererCapabilities interface {
// ExpirationCheck specifies whether the orderer checks for identity expiration checks
// when validating messages
ExpirationCheck() bool
// Kafka2RaftMigration checks whether the orderer permits a Kafka to Raft migration.
Kafka2RaftMigration() bool
}
// PolicyMapper is an interface for
......
......@@ -13,6 +13,7 @@ import (
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/msp"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/pkg/errors"
)
......@@ -35,49 +36,49 @@ type Bundle struct {
configtxManager configtx.Validator
}
// PolicyManager returns the policy manager constructed for this config
// PolicyManager returns the policy manager constructed for this config.
func (b *Bundle) PolicyManager() policies.Manager {
return b.policyManager
}
// MSPManager returns the MSP manager constructed for this config
// MSPManager returns the MSP manager constructed for this config.
func (b *Bundle) MSPManager() msp.MSPManager {
return b.channelConfig.MSPManager()
}
// ChannelConfig returns the config.Channel for the chain
// ChannelConfig returns the config.Channel for the chain.
func (b *Bundle) ChannelConfig() Channel {
return b.channelConfig
}
// OrdererConfig returns the config.Orderer for the channel
// and whether the Orderer config exists
// and whether the Orderer config exists.
func (b *Bundle) OrdererConfig() (Orderer, bool) {
result := b.channelConfig.OrdererConfig()
return result, result != nil
}
// ConsortiumsConfig() returns the config.Consortiums for the channel
// and whether the consortiums config exists
// ConsortiumsConfig returns the config.Consortiums for the channel
// and whether the consortiums config exists.
func (b *Bundle) ConsortiumsConfig() (Consortiums, bool) {
result := b.channelConfig.ConsortiumsConfig()
return result, result != nil
}
// ApplicationConfig returns the configtxapplication.SharedConfig for the channel
// and whether the Application config exists
// and whether the Application config exists.
func (b *Bundle) ApplicationConfig() (Application, bool) {
result := b.channelConfig.ApplicationConfig()
return result, result != nil
}
// ConfigtxValidator returns the configtx.Validator for the channel
// ConfigtxValidator returns the configtx.Validator for the channel.
func (b *Bundle) ConfigtxValidator() configtx.Validator {
return b.configtxManager
}
// ValidateNew checks if a new bundle's contained configuration is valid to be derived from the current bundle.
// This allows checks of the nature "Make sure that the consensus type did not change." which is otherwise
// This allows checks of the nature "Make sure that the consensus type did not change".
func (b *Bundle) ValidateNew(nb Resources) error {
if oc, ok := b.OrdererConfig(); ok {
noc, ok := nb.OrdererConfig()
......@@ -85,8 +86,20 @@ func (b *Bundle) ValidateNew(nb Resources) error {
return errors.New("Current config has orderer section, but new config does not")
}
if oc.ConsensusType() != noc.ConsensusType() {
return errors.Errorf("Attempted to change consensus type from %s to %s", oc.ConsensusType(), noc.ConsensusType())
// Prevent consensus-type migration when capabilities Kafka2RaftMigration is disabled
if !oc.Capabilities().Kafka2RaftMigration() {
if oc.ConsensusType() != noc.ConsensusType() {
return errors.Errorf("Attempted to change consensus type from %s to %s",
oc.ConsensusType(), noc.ConsensusType())
}
if noc.ConsensusMigrationState() != ab.ConsensusType_MIG_STATE_NONE || noc.ConsensusMigrationContext() != 0 {
return errors.Errorf("New config has unexpected consensus-migration state or context: (%s/%d) should be (MIG_STATE_NONE/0)",
noc.ConsensusMigrationState().String(), noc.ConsensusMigrationContext())
}
} else {
if err := validateMigrationStep(oc, noc); err != nil {
return err
}
}
for orgName, org := range oc.Organizations() {
......@@ -238,3 +251,99 @@ func preValidate(config *cb.Config) error {
return nil
}
// validateMigrationStep checks the validity of the state transitions of a possible migration step.
// Since at this point we don't know whether it is a system or standard channel, we allow a wider range of options.
// The migration state machine (for both types of channels) is enforced in the chain implementation.
func validateMigrationStep(oc Orderer, noc Orderer) error {
oldType := oc.ConsensusType()
oldState := oc.ConsensusMigrationState()
newType := noc.ConsensusType()
newState := noc.ConsensusMigrationState()
newContext := noc.ConsensusMigrationContext()
// The following code explicitly checks for permitted transitions; all other transitions return an error.
if oldType != newType {
// Consensus-type changes from Kafka to Raft in the "green" path:
// - The system channel starts the migration
// - A standard channel prepares the context, type change Kafka to Raft
// - The system channel commits the migration, type change Kafka to Raft
// Consensus-type changes from Raft to Kafka in the "abort" path:
// - The system channel starts the migration
// - A standard channel prepares the context, type change Kafka to Raft
// - The system channel aborts the migration
// - The standard channel reverts the type back, type change Raft to Kafka
if oldType == "kafka" && newType == "etcdraft" {
// On the system channels, this is permitted, green path commit
isSysCommit := oldState == ab.ConsensusType_MIG_STATE_START && newState == ab.ConsensusType_MIG_STATE_COMMIT
// On the standard channels, this is permitted, green path context
isStdCtx := oldState == ab.ConsensusType_MIG_STATE_NONE && newState == ab.ConsensusType_MIG_STATE_CONTEXT
if isSysCommit || isStdCtx {
logger.Debugf("Kafka-to-etcdraft migration, config update, state transition: %s to %s", oldState, newState)
} else {
return errors.Errorf("Attempted to change consensus type from %s to %s, unexpected migration state transition: %s to %s",
oldType, newType, oldState, newState)
}
} else if oldType == "etcdraft" && newType == "kafka" {
// On the standard channels, this is permitted, abort path
if oldState == ab.ConsensusType_MIG_STATE_CONTEXT && newState == ab.ConsensusType_MIG_STATE_NONE {
logger.Debugf("Kafka-to-etcdraft migration, config update, state transition: %s to %s", oldState, newState)
} else {
return errors.Errorf("Attempted to change consensus type from %s to %s, unexpected migration state transition: %s to %s",
oldType, newType, oldState, newState)
}
} else {
return errors.Errorf("Attempted to change consensus type from %s to %s, only kafka to etcdraft is supported",
oldType, newType)
}
} else {
// On the system channel & standard channels, this is always permitted, not a migration
isNotMig := oldState == ab.ConsensusType_MIG_STATE_NONE && newState == ab.ConsensusType_MIG_STATE_NONE
// Migration state may change when the type stays the same
if oldType == "kafka" {
// On the system channel, these transitions are permitted
// In the "green" path: the system channel starts migration
isSysStart := oldState == ab.ConsensusType_MIG_STATE_NONE && newState == ab.ConsensusType_MIG_STATE_START
// In the "abort" path: the system channel aborts a migration
isSysAbort := oldState == ab.ConsensusType_MIG_STATE_START && newState == ab.ConsensusType_MIG_STATE_ABORT
// In the "abort" path: the system channel reconfigures after an abort, not a migration
isSysNotMigAfterAbort := oldState == ab.ConsensusType_MIG_STATE_ABORT && newState == ab.ConsensusType_MIG_STATE_NONE
// In the "abort" path: the system channel starts a new migration attempt after an abort
isSysStartAfterAbort := oldState == ab.ConsensusType_MIG_STATE_ABORT && newState == ab.ConsensusType_MIG_STATE_START
if !(isNotMig || isSysStart || isSysAbort || isSysNotMigAfterAbort || isSysStartAfterAbort) {
return errors.Errorf("Consensus type %s, unexpected migration state transition: %s to %s",
oldType, oldState, newState)
} else if newState != ab.ConsensusType_MIG_STATE_NONE {
logger.Debugf("Kafka-to-etcdraft migration, config update, state transition: %s to %s", oldState, newState)
}
} else if oldType == "etcdraft" {
// On the system channel, this is permitted
// In the "green" path: the system channel reconfigures after a successful migration
isSysAfterSuccess := oldState == ab.ConsensusType_MIG_STATE_COMMIT && newState == ab.ConsensusType_MIG_STATE_NONE
// On the standard channels, this is permitted
// In the "green" path: a standard channel reconfigures after a successful migration
isStdAfterSuccess := oldState == ab.ConsensusType_MIG_STATE_CONTEXT && newState == ab.ConsensusType_MIG_STATE_NONE
if !(isNotMig || isSysAfterSuccess || isStdAfterSuccess) {
return errors.Errorf("Consensus type %s, unexpected migration state transition: %s to %s",
oldType, oldState.String(), newState)
}
}
}
// Check for a valid range on migration context
switch newState {
case ab.ConsensusType_MIG_STATE_START, ab.ConsensusType_MIG_STATE_ABORT, ab.ConsensusType_MIG_STATE_NONE:
if newContext != 0 {
return errors.Errorf("Consensus migration state %s, unexpected migration context: %d (expected: 0)",
newState, newContext)
}
case ab.ConsensusType_MIG_STATE_CONTEXT, ab.ConsensusType_MIG_STATE_COMMIT:
if newContext <= 0 {
return errors.Errorf("Consensus migration state %s, unexpected migration context: %d (expected >0)",
newState, newContext)
}
}
return nil
}
......@@ -9,6 +9,7 @@ package channelconfig
import (
"testing"
cc "github.com/hyperledger/fabric/common/capabilities"
cb "github.com/hyperledger/fabric/protos/common"
ab "github.com/hyperledger/fabric/protos/orderer"
"github.com/stretchr/testify/assert"
......@@ -64,43 +65,46 @@ func TestValidateNew(t *testing.T) {
})
t.Run("ConsensusTypeChange", func(t *testing.T) {
cb := &Bundle{
currb := &Bundle{
channelConfig: &ChannelConfig{
ordererConfig: &OrdererConfig{
protos: &OrdererProtos{
ConsensusType: &ab.ConsensusType{
Type: "type1",
},
Capabilities: &cb.Capabilities{},
},
},
},
}
nb := &Bundle{
newb := &Bundle{
channelConfig: &ChannelConfig{
ordererConfig: &OrdererConfig{
protos: &OrdererProtos{
ConsensusType: &ab.ConsensusType{
Type: "type2",
},
Capabilities: &cb.Capabilities{},
},
},
},
}
err := cb.ValidateNew(nb)
err := currb.ValidateNew(newb)
assert.Error(t, err)
assert.Regexp(t, "Attempted to change consensus type from", err.Error())
})
t.Run("OrdererOrgMSPIDChange", func(t *testing.T) {
cb := &Bundle{
currb := &Bundle{
channelConfig: &ChannelConfig{
ordererConfig: &OrdererConfig{
protos: &OrdererProtos{
ConsensusType: &ab.ConsensusType{
Type: "type1",
},
Capabilities: &cb.Capabilities{},
},
orgs: map[string]Org{
"org1": &OrganizationConfig{mspID: "org1msp"},
......@@ -111,13 +115,14 @@ func TestValidateNew(t *testing.T) {
},
}
nb := &Bundle{
newb := &Bundle{
channelConfig: &ChannelConfig{
ordererConfig: &OrdererConfig{
protos: &OrdererProtos{
ConsensusType: &ab.ConsensusType{
Type: "type1",
},
Capabilities: &cb.Capabilities{},
},
orgs: map[string]Org{
"org1": &OrganizationConfig{mspID: "org1msp"},
......@@ -127,7 +132,7 @@ func TestValidateNew(t *testing.T) {
},
}
err := cb.ValidateNew(nb)
err := currb.ValidateNew(newb)
assert.Error(t, err)
assert.Regexp(t, "Orderer org org3 attempted to change MSP ID from", err.Error())
})
......@@ -201,6 +206,241 @@ func TestValidateNew(t *testing.T) {
})
}
func TestValidateNewWithConsensusMigration(t *testing.T) {
t.Run("ConsensusTypeMigration Green Path on System Channel", func(t *testing.T) {
b0 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err := b0.ValidateNew(b1)
assert.NoError(t, err)
b2 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_START, 0)
err = b1.ValidateNew(b2)
assert.NoError(t, err)
b3 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_COMMIT, 4)
err = b2.ValidateNew(b3)
assert.NoError(t, err)
b4 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b3.ValidateNew(b4)
assert.NoError(t, err)
b5 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b4.ValidateNew(b5)
assert.NoError(t, err)
})
t.Run("ConsensusTypeMigration Green Path on Standard Channel", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 7)
err := b1.ValidateNew(b2)
assert.NoError(t, err)
b3 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b2.ValidateNew(b3)
assert.NoError(t, err)
})
t.Run("ConsensusTypeMigration Abort Path on System Channel", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_START, 0)
err := b1.ValidateNew(b2)
assert.NoError(t, err)
b3 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b2.ValidateNew(b3)
assert.NoError(t, err)
b4none := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b3.ValidateNew(b4none)
assert.NoError(t, err)
b4retry := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_START, 0)
err = b3.ValidateNew(b4retry)
assert.NoError(t, err)
})
t.Run("ConsensusTypeMigration Abort Path on Standard Channel", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 7)
err := b1.ValidateNew(b2)
assert.NoError(t, err)
b3 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b2.ValidateNew(b3)
assert.NoError(t, err)
})
t.Run("ConsensusTypeMigration Bad Transitions on System Channel, from NONE", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_COMMIT, 4)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from kafka to etcdraft, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_COMMIT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_COMMIT, 2)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type kafka, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_COMMIT")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from kafka to etcdraft, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_ABORT")
})
t.Run("ConsensusTypeMigration Bad Transitions on System Channel, from START", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_START, 0)
b2 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_COMMIT, 4)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type kafka, unexpected migration state transition: MIG_STATE_START to MIG_STATE_COMMIT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type kafka, unexpected migration state transition: MIG_STATE_START to MIG_STATE_NONE")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from kafka to etcdraft, unexpected migration state transition: MIG_STATE_START to MIG_STATE_NONE")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from kafka to etcdraft, unexpected migration state transition: MIG_STATE_START to MIG_STATE_ABORT")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_COMMIT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus migration state MIG_STATE_COMMIT, unexpected migration context: 0 (expected >0)")
})
t.Run("ConsensusTypeMigration Bad Transitions on System Channel, from COMMIT", func(t *testing.T) {
b1 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_COMMIT, 4)
b2 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_ABORT, 0)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_COMMIT to MIG_STATE_ABORT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_START, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_COMMIT to MIG_STATE_START")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_START, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type etcdraft, unexpected migration state transition: MIG_STATE_COMMIT to MIG_STATE_START")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type etcdraft, unexpected migration state transition: MIG_STATE_COMMIT to MIG_STATE_ABORT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_COMMIT to MIG_STATE_NONE")
})
t.Run("ConsensusTypeMigration Bad Transitions on Standard Channel, from NONE-1", func(t *testing.T) {
b1 := generateMigrationBundle("kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 0)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus migration state MIG_STATE_CONTEXT, unexpected migration context: 0 (expected >0)")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_CONTEXT, 7)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type kafka, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_CONTEXT")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from kafka to etcdraft, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_NONE")
})
t.Run("ConsensusTypeMigration Bad Transitions on Standard Channel, from NONE-2", func(t *testing.T) {
b1 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_NONE, 0)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 0)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type etcdraft, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_CONTEXT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_CONTEXT, 7)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_CONTEXT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_NONE, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_NONE to MIG_STATE_NONE")
})
t.Run("ConsensusTypeMigration Bad Transitions on Standard Channel, from CONTEXT", func(t *testing.T) {
b1 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 7)
b2 := generateMigrationBundle("etcdraft", ab.ConsensusType_MIG_STATE_CONTEXT, 8)
err := b1.ValidateNew(b2)
assert.EqualError(t, err,
"Consensus type etcdraft, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_CONTEXT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_CONTEXT, 8)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_CONTEXT")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_START, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err,
"Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_START")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_START, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err, "Consensus type etcdraft, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_START")
updateConsensusType(b2, "kafka", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err, "Attempted to change consensus type from etcdraft to kafka, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_ABORT")
updateConsensusType(b2, "etcdraft", ab.ConsensusType_MIG_STATE_ABORT, 0)
err = b1.ValidateNew(b2)
assert.EqualError(t, err, "Consensus type etcdraft, unexpected migration state transition: MIG_STATE_CONTEXT to MIG_STATE_ABORT")
})
}
func updateConsensusType(b2 *Bundle, cType string, cState ab.ConsensusType_MigrationState, cContext uint64) {
b2.channelConfig.ordererConfig.protos.ConsensusType.Type = cType
b2.channelConfig.ordererConfig.protos.ConsensusType.MigrationState = cState
b2.channelConfig.ordererConfig.protos.ConsensusType.MigrationContext = cContext
}
func generateMigrationBundle(cType string, cState ab.ConsensusType_MigrationState, cContext uint64) *Bundle {
b := &Bundle{
channelConfig: &ChannelConfig{
ordererConfig: &OrdererConfig{
protos: &OrdererProtos{
ConsensusType: &ab.ConsensusType{
Type: cType,
MigrationState: cState,
MigrationContext: cContext,
},
Capabilities: &cb.Capabilities{
Capabilities: map[string]*cb.Capability{
cc.OrdererV2_0: {},
},
},
},
},
},
}
return b
}
func TestPrevalidation(t *testing.T) {
t.Run("NilConfig", func(t *testing.T) {
err := preValidate(nil)
......
......@@ -20,28 +20,28 @@ import (
)
const (
// OrdererGroupKey is the group name for the orderer config
// 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 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 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 is the cb.ConfigItem type key name for the BatchTimeout message.
BatchTimeoutKey = "BatchTimeout"
// ChannelRestrictionsKey is the key name for the ChannelRestrictions message
// ChannelRestrictionsKey is the key name for the ChannelRestrictions message.
ChannelRestrictionsKey = "ChannelRestrictions"
// KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message
// KafkaBrokersKey is the cb.ConfigItem type key name for the KafkaBrokers message.
KafkaBrokersKey = "KafkaBrokers"
)
// OrdererProtos is used as the source of the OrdererConfig
// OrdererProtos is used as the source of the OrdererConfig.
type OrdererProtos struct {
ConsensusType *ab.ConsensusType
BatchSize *ab.BatchSize
......@@ -51,7 +51,7 @@ type OrdererProtos struct {
Capabilities *cb.Capabilities
}
// OrdererConfig holds the orderer configuration information
// OrdererConfig holds the orderer configuration information.
type OrdererConfig struct {
protos *OrdererProtos
orgs map[string]Org
......@@ -59,7 +59,7 @@ type OrdererConfig struct {
batchTimeout time.Duration
}
// NewOrdererConfig creates a new instance of the orderer config
// NewOrdererConfig creates a new instance of the orderer config.
func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler) (*OrdererConfig, error) {
oc := &OrdererConfig{
protos: &OrdererProtos{},
......@@ -83,7 +83,7 @@ func NewOrdererConfig(ordererGroup *cb.ConfigGroup, mspConfig *MSPConfigHandler)
return oc, nil
}
// ConsensusType returns the configured consensus type
// ConsensusType returns the configured consensus type.
func (oc *OrdererConfig) ConsensusType() string {
return oc.protos.ConsensusType.Type
}
......@@ -93,34 +93,44 @@ func (oc *OrdererConfig) ConsensusMetadata() []byte {
return oc.protos.ConsensusType.Metadata
}