Skip to content

Commit 7e0b4bf

Browse files
author
Jason Yellick
committed
[FAB-2226] Move anchor peers to app org level
https://jira.hyperledger.org/browse/FAB-2226 The anchor peers are per application organization, so should be stored at the app org level. Change-Id: I930244c44c759d628531af2f71da3ced43b85631 Signed-off-by: Jason Yellick <[email protected]>
1 parent e99311d commit 7e0b4bf

13 files changed

+322
-170
lines changed

common/configtx/api/api.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@ type ChannelConfig interface {
4040
OrdererAddresses() []string
4141
}
4242

43-
// ApplicationConfig stores the common shared application config
44-
type ApplicationConfig interface {
43+
// ApplicationOrgConfig stores the per org application config
44+
type ApplicationOrgConfig interface {
4545
// AnchorPeers returns the list of gossip anchor peers
4646
AnchorPeers() []*pb.AnchorPeer
4747
}
4848

49+
// ApplicationConfig stores the common shared application config
50+
type ApplicationConfig interface {
51+
// Organizations returns a map of org ID to ApplicationOrgConfig
52+
Organizations() map[string]ApplicationOrgConfig
53+
}
54+
4955
// OrdererConfig stores the common shared orderer config
5056
type OrdererConfig interface {
5157
// ConsensusType returns the configured consensus type
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/*
2+
Copyright IBM Corp. 2017 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 application
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/hyperledger/fabric/common/configtx/handlers"
23+
mspconfig "github.com/hyperledger/fabric/common/configtx/handlers/msp"
24+
cb "github.com/hyperledger/fabric/protos/common"
25+
pb "github.com/hyperledger/fabric/protos/peer"
26+
27+
"github.com/golang/protobuf/proto"
28+
logging "github.com/op/go-logging"
29+
)
30+
31+
// Application org config keys
32+
const (
33+
// AnchorPeersKey is the key name for the AnchorPeers ConfigValue
34+
AnchorPeersKey = "AnchorPeers"
35+
)
36+
37+
type applicationOrgConfig struct {
38+
anchorPeers []*pb.AnchorPeer
39+
}
40+
41+
// SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler
42+
// In general, it should only be referenced as an Impl for the configtx.Manager
43+
type ApplicationOrgConfig struct {
44+
*handlers.OrgConfig
45+
pendingConfig *applicationOrgConfig
46+
config *applicationOrgConfig
47+
48+
mspConfig *mspconfig.MSPConfigHandler
49+
}
50+
51+
// NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper
52+
func NewApplicationOrgConfig(id string, mspConfig *mspconfig.MSPConfigHandler) *ApplicationOrgConfig {
53+
return &ApplicationOrgConfig{
54+
OrgConfig: handlers.NewOrgConfig(id, mspConfig),
55+
config: &applicationOrgConfig{},
56+
}
57+
}
58+
59+
// AnchorPeers returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
60+
func (oc *ApplicationOrgConfig) AnchorPeers() []*pb.AnchorPeer {
61+
return oc.config.anchorPeers
62+
}
63+
64+
// BeginConfig is used to start a new config proposal
65+
func (oc *ApplicationOrgConfig) BeginConfig() {
66+
logger.Debugf("Beginning a possible new org config")
67+
if oc.pendingConfig != nil {
68+
logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
69+
}
70+
oc.pendingConfig = &applicationOrgConfig{}
71+
}
72+
73+
// RollbackConfig is used to abandon a new config proposal
74+
func (oc *ApplicationOrgConfig) RollbackConfig() {
75+
logger.Debugf("Rolling back proposed org config")
76+
oc.pendingConfig = nil
77+
}
78+
79+
// CommitConfig is used to commit a new config proposal
80+
func (oc *ApplicationOrgConfig) CommitConfig() {
81+
logger.Debugf("Committing new org config")
82+
if oc.pendingConfig == nil {
83+
logger.Panicf("Programming error, cannot call commit without an existing proposal")
84+
}
85+
oc.config = oc.pendingConfig
86+
oc.pendingConfig = nil
87+
}
88+
89+
// ProposeConfig is used to add new config to the config proposal
90+
func (oc *ApplicationOrgConfig) ProposeConfig(key string, configValue *cb.ConfigValue) error {
91+
switch key {
92+
case AnchorPeersKey:
93+
anchorPeers := &pb.AnchorPeers{}
94+
if err := proto.Unmarshal(configValue.Value, anchorPeers); err != nil {
95+
return fmt.Errorf("Unmarshaling error for %s: %s", key, err)
96+
}
97+
if logger.IsEnabledFor(logging.DEBUG) {
98+
logger.Debugf("Setting %s to %v", key, anchorPeers.AnchorPeers)
99+
}
100+
oc.pendingConfig.anchorPeers = anchorPeers.AnchorPeers
101+
default:
102+
return oc.OrgConfig.ProposeConfig(key, configValue)
103+
}
104+
105+
return nil
106+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
Copyright IBM Corp. 2017 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 application
18+
19+
import (
20+
"testing"
21+
22+
configtxapi "github.com/hyperledger/fabric/common/configtx/api"
23+
cb "github.com/hyperledger/fabric/protos/common"
24+
pb "github.com/hyperledger/fabric/protos/peer"
25+
26+
logging "github.com/op/go-logging"
27+
"github.com/stretchr/testify/assert"
28+
)
29+
30+
func init() {
31+
logging.SetLevel(logging.DEBUG, "")
32+
}
33+
34+
func makeInvalidConfigValue() *cb.ConfigValue {
35+
return &cb.ConfigValue{
36+
Value: []byte("Garbage Data"),
37+
}
38+
}
39+
40+
func groupToKeyValue(configGroup *cb.ConfigGroup) (string, *cb.ConfigValue) {
41+
for _, group := range configGroup.Groups[GroupKey].Groups {
42+
for key, value := range group.Values {
43+
return key, value
44+
}
45+
}
46+
panic("No value encoded")
47+
}
48+
49+
func TestApplicationOrgInterface(t *testing.T) {
50+
_ = configtxapi.SubInitializer(NewApplicationOrgConfig("id", nil))
51+
}
52+
53+
func TestApplicationOrgDoubleBegin(t *testing.T) {
54+
m := NewApplicationOrgConfig("id", nil)
55+
m.BeginConfig()
56+
assert.Panics(t, m.BeginConfig, "Two begins back to back should have caused a panic")
57+
}
58+
59+
func TestApplicationOrgCommitWithoutBegin(t *testing.T) {
60+
m := NewApplicationOrgConfig("id", nil)
61+
assert.Panics(t, m.CommitConfig, "Committing without beginning should have caused a panic")
62+
}
63+
64+
func TestApplicationOrgRollback(t *testing.T) {
65+
m := NewApplicationOrgConfig("id", nil)
66+
m.pendingConfig = &applicationOrgConfig{}
67+
m.RollbackConfig()
68+
assert.Nil(t, m.pendingConfig, "Should have cleared pending config on rollback")
69+
}
70+
71+
func TestApplicationOrgAnchorPeers(t *testing.T) {
72+
endVal := []*pb.AnchorPeer{
73+
&pb.AnchorPeer{Host: "foo", Port: 234, Cert: []byte("foocert")},
74+
&pb.AnchorPeer{Host: "bar", Port: 237, Cert: []byte("barcert")},
75+
}
76+
invalidMessage := makeInvalidConfigValue()
77+
validMessage := TemplateAnchorPeers("id", endVal)
78+
m := NewApplicationOrgConfig("id", nil)
79+
m.BeginConfig()
80+
81+
assert.Error(t, m.ProposeConfig(AnchorPeersKey, invalidMessage), "Should have failed on invalid message")
82+
assert.NoError(t, m.ProposeConfig(groupToKeyValue(validMessage)), "Should not have failed on invalid message")
83+
m.CommitConfig()
84+
85+
assert.Equal(t, m.AnchorPeers(), endVal, "Did not set updated anchor peers")
86+
}

common/configtx/handlers/application/sharedconfig.go

+14-36
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ import (
2323
"github.com/hyperledger/fabric/common/configtx/handlers"
2424
"github.com/hyperledger/fabric/common/configtx/handlers/msp"
2525
cb "github.com/hyperledger/fabric/protos/common"
26-
pb "github.com/hyperledger/fabric/protos/peer"
2726

28-
"github.com/golang/protobuf/proto"
2927
"github.com/op/go-logging"
3028
)
3129

@@ -37,7 +35,8 @@ const (
3735
var orgSchema = &cb.ConfigGroupSchema{
3836
Groups: map[string]*cb.ConfigGroupSchema{},
3937
Values: map[string]*cb.ConfigValueSchema{
40-
"MSP": nil, // TODO, consolidate into a constant once common org code exists
38+
AnchorPeersKey: nil,
39+
handlers.MSPKey: nil, // TODO, consolidate into a constant once common org code exists
4140
},
4241
Policies: map[string]*cb.ConfigPolicySchema{
4342
// TODO, set appropriately once hierarchical policies are implemented
@@ -48,25 +47,16 @@ var Schema = &cb.ConfigGroupSchema{
4847
Groups: map[string]*cb.ConfigGroupSchema{
4948
"": orgSchema,
5049
},
51-
Values: map[string]*cb.ConfigValueSchema{
52-
AnchorPeersKey: nil,
53-
},
50+
Values: map[string]*cb.ConfigValueSchema{},
5451
Policies: map[string]*cb.ConfigPolicySchema{
5552
// TODO, set appropriately once hierarchical policies are implemented
5653
},
5754
}
5855

59-
// Peer config keys
60-
const (
61-
// AnchorPeersKey is the key name for the AnchorPeers ConfigValue
62-
AnchorPeersKey = "AnchorPeers"
63-
)
64-
65-
var logger = logging.MustGetLogger("peer/sharedconfig")
56+
var logger = logging.MustGetLogger("common/configtx/handlers/application")
6657

6758
type sharedConfig struct {
68-
anchorPeers []*pb.AnchorPeer
69-
orgs map[string]*handlers.OrgConfig
59+
orgs map[string]api.ApplicationOrgConfig
7060
}
7161

7262
// SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler
@@ -86,19 +76,14 @@ func NewSharedConfigImpl(mspConfig *msp.MSPConfigHandler) *SharedConfigImpl {
8676
}
8777
}
8878

89-
// AnchorPeers returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
90-
func (di *SharedConfigImpl) AnchorPeers() []*pb.AnchorPeer {
91-
return di.config.anchorPeers
92-
}
93-
9479
// BeginConfig is used to start a new config proposal
9580
func (di *SharedConfigImpl) BeginConfig() {
9681
logger.Debugf("Beginning a possible new peer shared config")
9782
if di.pendingConfig != nil {
9883
logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
9984
}
10085
di.pendingConfig = &sharedConfig{
101-
orgs: make(map[string]*handlers.OrgConfig),
86+
orgs: make(map[string]api.ApplicationOrgConfig),
10287
}
10388
}
10489

@@ -120,22 +105,15 @@ func (di *SharedConfigImpl) CommitConfig() {
120105

121106
// ProposeConfig is used to add new config to the config proposal
122107
func (di *SharedConfigImpl) ProposeConfig(key string, configValue *cb.ConfigValue) error {
123-
switch key {
124-
case AnchorPeersKey:
125-
anchorPeers := &pb.AnchorPeers{}
126-
if err := proto.Unmarshal(configValue.Value, anchorPeers); err != nil {
127-
return fmt.Errorf("Unmarshaling error for %s: %s", key, err)
128-
}
129-
if logger.IsEnabledFor(logging.DEBUG) {
130-
logger.Debugf("Setting %s to %v", key, anchorPeers.AnchorPeers)
131-
}
132-
di.pendingConfig.anchorPeers = anchorPeers.AnchorPeers
133-
default:
134-
logger.Warningf("Uknown Peer config item with key %s", key)
135-
}
108+
logger.Warningf("Uknown Peer config item with key %s", key)
136109
return nil
137110
}
138111

112+
// Organizations returns a map of org ID to ApplicationOrgConfig
113+
func (di *SharedConfigImpl) Organizations() map[string]api.ApplicationOrgConfig {
114+
return di.config.orgs
115+
}
116+
139117
// Handler returns the associated api.Handler for the given path
140118
func (pm *SharedConfigImpl) Handler(path []string) (api.Handler, error) {
141119
if len(path) == 0 {
@@ -148,8 +126,8 @@ func (pm *SharedConfigImpl) Handler(path []string) (api.Handler, error) {
148126

149127
org, ok := pm.pendingConfig.orgs[path[0]]
150128
if !ok {
151-
org = handlers.NewOrgConfig(path[0], pm.mspConfig)
129+
org = NewApplicationOrgConfig(path[0], pm.mspConfig)
152130
pm.pendingConfig.orgs[path[0]] = org
153131
}
154-
return org, nil
132+
return org.(*ApplicationOrgConfig), nil
155133
}

0 commit comments

Comments
 (0)