-
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.
https://jira.hyperledger.org/browse/FAB-1851 This changeset adds a peer sharedconfig package. The sharedconfig is named as such, because it is configuration which is shared across all peers for a channel, as opposed to the local configuration which the peer sources from its yaml file. Change-Id: I46bc408ed15a065020722666ee8e50d9f679e665 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
- Loading branch information
Jason Yellick
committed
Jan 25, 2017
1 parent
e111bac
commit 9f07b96
Showing
4 changed files
with
259 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
Copyright IBM Corp. 2017 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 sharedconfig | ||
|
||
import ( | ||
"fmt" | ||
|
||
cb "github.com/hyperledger/fabric/protos/common" | ||
pb "github.com/hyperledger/fabric/protos/peer" | ||
|
||
"github.com/golang/protobuf/proto" | ||
"github.com/op/go-logging" | ||
) | ||
|
||
// Peer config keys | ||
const ( | ||
// AnchorPeersKey is the cb.ConfigurationItem type key name for the AnchorPeers message | ||
AnchorPeersKey = "AnchorPeers" | ||
) | ||
|
||
var logger = logging.MustGetLogger("peer/sharedconfig") | ||
|
||
// Descriptor stores the common peer configuration | ||
// It is intended to be the primary accessor of DescriptorImpl | ||
// It is intended to discourage use of the other exported DescriptorImpl methods | ||
// which are used for updating the chain configuration by the configtx.Manager | ||
type Descriptor interface { | ||
// AnchorPeers returns the list of anchor peers for the channel | ||
AnchorPeers() []*pb.AnchorPeer | ||
} | ||
|
||
type sharedConfig struct { | ||
anchorPeers []*pb.AnchorPeer | ||
} | ||
|
||
// DescriptorImpl is an implementation of Manager and configtx.ConfigHandler | ||
// In general, it should only be referenced as an Impl for the configtx.Manager | ||
type DescriptorImpl struct { | ||
pendingConfig *sharedConfig | ||
config *sharedConfig | ||
} | ||
|
||
// NewDescriptorImpl creates a new DescriptorImpl with the given CryptoHelper | ||
func NewDescriptorImpl() *DescriptorImpl { | ||
return &DescriptorImpl{ | ||
config: &sharedConfig{}, | ||
} | ||
} | ||
|
||
// AnchorPeers returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver | ||
func (di *DescriptorImpl) AnchorPeers() []*pb.AnchorPeer { | ||
return di.config.anchorPeers | ||
} | ||
|
||
// BeginConfig is used to start a new configuration proposal | ||
func (di *DescriptorImpl) BeginConfig() { | ||
logger.Debugf("Beginning a possible new peer shared configuration") | ||
if di.pendingConfig != nil { | ||
logger.Panicf("Programming error, cannot call begin in the middle of a proposal") | ||
} | ||
di.pendingConfig = &sharedConfig{} | ||
} | ||
|
||
// RollbackConfig is used to abandon a new configuration proposal | ||
func (di *DescriptorImpl) RollbackConfig() { | ||
logger.Debugf("Rolling back proposed peer shared configuration") | ||
di.pendingConfig = nil | ||
} | ||
|
||
// CommitConfig is used to commit a new configuration proposal | ||
func (di *DescriptorImpl) CommitConfig() { | ||
logger.Debugf("Committing new peer shared configuration") | ||
if di.pendingConfig == nil { | ||
logger.Panicf("Programming error, cannot call commit without an existing proposal") | ||
} | ||
di.config = di.pendingConfig | ||
di.pendingConfig = nil | ||
} | ||
|
||
// ProposeConfig is used to add new configuration to the configuration proposal | ||
func (di *DescriptorImpl) ProposeConfig(configItem *cb.ConfigurationItem) error { | ||
if configItem.Type != cb.ConfigurationItem_Peer { | ||
return fmt.Errorf("Expected type of ConfigurationItem_Peer, got %v", configItem.Type) | ||
} | ||
|
||
switch configItem.Key { | ||
case AnchorPeersKey: | ||
anchorPeers := &pb.AnchorPeers{} | ||
if err := proto.Unmarshal(configItem.Value, anchorPeers); err != nil { | ||
return fmt.Errorf("Unmarshaling error for %s: %s", configItem.Key, err) | ||
} | ||
if logger.IsEnabledFor(logging.DEBUG) { | ||
logger.Debugf("Setting %s to %v", configItem.Key, anchorPeers.AnchorPeers) | ||
} | ||
di.pendingConfig.anchorPeers = anchorPeers.AnchorPeers | ||
default: | ||
logger.Warningf("Uknown Peer configuration item with key %s", configItem.Key) | ||
} | ||
return nil | ||
} |
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,102 @@ | ||
/* | ||
Copyright IBM Corp. 2017 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 sharedconfig | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
cb "github.com/hyperledger/fabric/protos/common" | ||
pb "github.com/hyperledger/fabric/protos/peer" | ||
|
||
logging "github.com/op/go-logging" | ||
) | ||
|
||
func init() { | ||
logging.SetLevel(logging.DEBUG, "") | ||
} | ||
|
||
func makeInvalidConfigItem(key string) *cb.ConfigurationItem { | ||
return &cb.ConfigurationItem{ | ||
Type: cb.ConfigurationItem_Peer, | ||
Key: key, | ||
Value: []byte("Garbage Data"), | ||
} | ||
} | ||
|
||
func TestInterface(t *testing.T) { | ||
_ = Descriptor(NewDescriptorImpl()) | ||
} | ||
|
||
func TestDoubleBegin(t *testing.T) { | ||
defer func() { | ||
if err := recover(); err == nil { | ||
t.Fatalf("Should have panicked on multiple begin configs") | ||
} | ||
}() | ||
|
||
m := NewDescriptorImpl() | ||
m.BeginConfig() | ||
m.BeginConfig() | ||
} | ||
|
||
func TestCommitWithoutBegin(t *testing.T) { | ||
defer func() { | ||
if err := recover(); err == nil { | ||
t.Fatalf("Should have panicked on multiple begin configs") | ||
} | ||
}() | ||
|
||
m := NewDescriptorImpl() | ||
m.CommitConfig() | ||
} | ||
|
||
func TestRollback(t *testing.T) { | ||
m := NewDescriptorImpl() | ||
m.pendingConfig = &sharedConfig{} | ||
m.RollbackConfig() | ||
if m.pendingConfig != nil { | ||
t.Fatalf("Should have cleared pending config on rollback") | ||
} | ||
} | ||
|
||
func TestAnchorPeers(t *testing.T) { | ||
endVal := []*pb.AnchorPeer{ | ||
&pb.AnchorPeer{Host: "foo", Port: 234, Cert: []byte("foocert")}, | ||
&pb.AnchorPeer{Host: "bar", Port: 237, Cert: []byte("barcert")}, | ||
} | ||
invalidMessage := makeInvalidConfigItem(AnchorPeersKey) | ||
validMessage := TemplateAnchorPeers(endVal) | ||
m := NewDescriptorImpl() | ||
m.BeginConfig() | ||
|
||
err := m.ProposeConfig(invalidMessage) | ||
if err == nil { | ||
t.Fatalf("Should have failed on invalid message") | ||
} | ||
|
||
err = m.ProposeConfig(validMessage) | ||
if err != nil { | ||
t.Fatalf("Error applying valid config: %s", err) | ||
} | ||
|
||
m.CommitConfig() | ||
|
||
if newVal := m.AnchorPeers(); !reflect.DeepEqual(newVal, endVal) { | ||
t.Fatalf("Unexpected anchor peers, got %v expected %v", newVal, endVal) | ||
} | ||
} |
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,39 @@ | ||
/* | ||
Copyright IBM Corp. 2017 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 sharedconfig | ||
|
||
import ( | ||
cb "github.com/hyperledger/fabric/protos/common" | ||
pb "github.com/hyperledger/fabric/protos/peer" | ||
"github.com/hyperledger/fabric/protos/utils" | ||
) | ||
|
||
var defaultAnchorPeers = []*pb.AnchorPeer{} | ||
|
||
// TemplateAnchorPeers creates a headerless configuration item representing the anchor peers | ||
func TemplateAnchorPeers(anchorPeers []*pb.AnchorPeer) *cb.ConfigurationItem { | ||
return &cb.ConfigurationItem{ | ||
Type: cb.ConfigurationItem_Peer, | ||
Key: AnchorPeersKey, | ||
Value: utils.MarshalOrPanic(&pb.AnchorPeers{AnchorPeers: anchorPeers}), | ||
} | ||
} | ||
|
||
// DefaultAnchorPeers creates a headerless configuration item for the default orderer addresses | ||
func DefaultAnchorPeers() *cb.ConfigurationItem { | ||
return TemplateAnchorPeers(defaultAnchorPeers) | ||
} |