Skip to content

Commit

Permalink
[FAB-2399] ApplicationOrg config to common Proposer
Browse files Browse the repository at this point in the history
https://jira.hyperledger.org/browse/FAB-2399

This CR moves the last standalone config component, the application org
config over to the common Proposer framework.

Change-Id: I1f6aa2426b2e41d89dc972963dfe6e5643e08a06
Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
  • Loading branch information
Jason Yellick committed Mar 7, 2017
1 parent 2541878 commit efa8237
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 125 deletions.
6 changes: 3 additions & 3 deletions common/configvalues/root/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,10 @@ func NewApplicationGroup(mspConfig *msp.MSPConfigHandler) *ApplicationGroup {
}

func (ag *ApplicationGroup) NewGroup(name string) (api.ValueProposer, error) {
return NewApplicationOrgConfig(name, ag.mspConfig), nil
return NewApplicationOrgGroup(name, ag.mspConfig), nil
}

// Allocate returns the
// Allocate returns a new instance of the ApplicationConfig
func (ag *ApplicationGroup) Allocate() Values {
return NewApplicationConfig(ag)
}
Expand All @@ -79,7 +79,7 @@ func (ac *ApplicationConfig) Validate(groups map[string]api.ValueProposer) error
ac.applicationOrgs = make(map[string]api.ApplicationOrg)
var ok bool
for key, value := range groups {
ac.applicationOrgs[key], ok = value.(*ApplicationOrgConfig)
ac.applicationOrgs[key], ok = value.(*ApplicationOrgGroup)
if !ok {
return fmt.Errorf("Application sub-group %s was not an ApplicationOrgGroup, actually %T", key, value)
}
Expand Down
102 changes: 41 additions & 61 deletions common/configvalues/root/applicationorg.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,10 @@ limitations under the License.
package config

import (
"fmt"

api "github.com/hyperledger/fabric/common/configvalues"
mspconfig "github.com/hyperledger/fabric/common/configvalues/msp"
cb "github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"

"github.com/golang/protobuf/proto"
logging "github.com/op/go-logging"
)

Expand All @@ -34,82 +30,66 @@ const (
AnchorPeersKey = "AnchorPeers"
)

type applicationOrgConfig struct {
anchorPeers []*pb.AnchorPeer
type ApplicationOrgProtos struct {
AnchorPeers *pb.AnchorPeers
}

// SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler
// In general, it should only be referenced as an Impl for the configtx.Manager
type ApplicationOrgConfig struct {
*OrganizationGroup
pendingConfig *applicationOrgConfig
config *applicationOrgConfig
*OrganizationConfig
protos *ApplicationOrgProtos

applicationOrgGroup *ApplicationOrgGroup
}

mspConfig *mspconfig.MSPConfigHandler
// ApplicationOrgGroup defines the configuration for an application org
type ApplicationOrgGroup struct {
*Proposer
*OrganizationGroup
*ApplicationOrgConfig
}

// NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper
func NewApplicationOrgConfig(id string, mspConfig *mspconfig.MSPConfigHandler) *ApplicationOrgConfig {
return &ApplicationOrgConfig{
// NewApplicationOrgGroup creates a new ApplicationOrgGroup
func NewApplicationOrgGroup(id string, mspConfig *mspconfig.MSPConfigHandler) *ApplicationOrgGroup {
aog := &ApplicationOrgGroup{
OrganizationGroup: NewOrganizationGroup(id, mspConfig),
config: &applicationOrgConfig{},
}
aog.Proposer = NewProposer(aog)
return aog
}

// AnchorPeers returns the list of valid orderer addresses to connect to to invoke Broadcast/Deliver
func (oc *ApplicationOrgConfig) AnchorPeers() []*pb.AnchorPeer {
return oc.config.anchorPeers
func (aog *ApplicationOrgConfig) AnchorPeers() []*pb.AnchorPeer {
return aog.protos.AnchorPeers.AnchorPeers
}

// BeginValueProposals is used to start a new config proposal
func (oc *ApplicationOrgConfig) BeginValueProposals(groups []string) ([]api.ValueProposer, error) {
logger.Debugf("Beginning a possible new org config")
if len(groups) != 0 {
return nil, fmt.Errorf("ApplicationGroup does not support subgroups")
}
if oc.pendingConfig != nil {
logger.Panicf("Programming error, cannot call begin in the middle of a proposal")
}
oc.pendingConfig = &applicationOrgConfig{}
return oc.OrganizationGroup.BeginValueProposals(groups)
func (aog *ApplicationOrgGroup) Allocate() Values {
return NewApplicationOrgConfig(aog)
}

// RollbackProposals is used to abandon a new config proposal
func (oc *ApplicationOrgConfig) RollbackProposals() {
logger.Debugf("Rolling back proposed org config")
oc.pendingConfig = nil
oc.OrganizationGroup.RollbackProposals()
func (aoc *ApplicationOrgConfig) Commit() {
aoc.applicationOrgGroup.ApplicationOrgConfig = aoc
aoc.OrganizationConfig.Commit()
}

// CommitProposals is used to commit a new config proposal
func (oc *ApplicationOrgConfig) CommitProposals() {
logger.Debugf("Committing new org config")
if oc.pendingConfig == nil {
logger.Panicf("Programming error, cannot call commit without an existing proposal")
}
oc.config = oc.pendingConfig
oc.pendingConfig = nil
oc.OrganizationGroup.CommitProposals()
}
func NewApplicationOrgConfig(aog *ApplicationOrgGroup) *ApplicationOrgConfig {
aoc := &ApplicationOrgConfig{
protos: &ApplicationOrgProtos{},
OrganizationConfig: NewOrganizationConfig(aog.OrganizationGroup),

// ProposeValue is used to add new config to the config proposal
func (oc *ApplicationOrgConfig) ProposeValue(key string, configValue *cb.ConfigValue) error {
switch key {
case AnchorPeersKey:
anchorPeers := &pb.AnchorPeers{}
if err := proto.Unmarshal(configValue.Value, anchorPeers); err != nil {
return fmt.Errorf("Unmarshaling error for %s: %s", key, err)
}
if logger.IsEnabledFor(logging.DEBUG) {
logger.Debugf("Setting %s to %v", key, anchorPeers.AnchorPeers)
}
oc.pendingConfig.anchorPeers = anchorPeers.AnchorPeers
default:
return oc.OrganizationGroup.ProposeValue(key, configValue)
applicationOrgGroup: aog,
}
var err error
aoc.standardValues, err = NewStandardValues(aoc.protos, aoc.OrganizationConfig.protos)
if err != nil {
logger.Panicf("Programming error: %s", err)
}

return nil
return aoc
}

// PreCommit returns nil
func (c *ApplicationOrgConfig) PreCommit() error { return nil }
func (aoc *ApplicationOrgConfig) Validate(groups map[string]api.ValueProposer) error {
if logger.IsEnabledFor(logging.DEBUG) {
logger.Debugf("Anchor peers for org %s are %v", aoc.applicationOrgGroup.name, aoc.protos.AnchorPeers)
}
return aoc.OrganizationConfig.Validate(groups)
}
61 changes: 1 addition & 60 deletions common/configvalues/root/applicationorg_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,67 +20,8 @@ import (
"testing"

api "github.com/hyperledger/fabric/common/configvalues"
cb "github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"

logging "github.com/op/go-logging"
"github.com/stretchr/testify/assert"
)

func init() {
logging.SetLevel(logging.DEBUG, "")
}

func makeInvalidConfigValue() *cb.ConfigValue {
return &cb.ConfigValue{
Value: []byte("Garbage Data"),
}
}

func groupToKeyValue(configGroup *cb.ConfigGroup) (string, *cb.ConfigValue) {
for _, group := range configGroup.Groups[ApplicationGroupKey].Groups {
for key, value := range group.Values {
return key, value
}
}
panic("No value encoded")
}

func TestApplicationOrgInterface(t *testing.T) {
_ = api.ValueProposer(NewApplicationOrgConfig("id", nil))
}

func TestApplicationOrgDoubleBegin(t *testing.T) {
m := NewApplicationOrgConfig("id", nil)
m.BeginValueProposals(nil)
assert.Panics(t, func() { m.BeginValueProposals(nil) }, "Two begins back to back should have caused a panic")
}

func TestApplicationOrgCommitWithoutBegin(t *testing.T) {
m := NewApplicationOrgConfig("id", nil)
assert.Panics(t, m.CommitProposals, "Committing without beginning should have caused a panic")
}

func TestApplicationOrgRollback(t *testing.T) {
m := NewApplicationOrgConfig("id", nil)
m.pendingConfig = &applicationOrgConfig{}
m.RollbackProposals()
assert.Nil(t, m.pendingConfig, "Should have cleared pending config on rollback")
}

func TestApplicationOrgAnchorPeers(t *testing.T) {
endVal := []*pb.AnchorPeer{
&pb.AnchorPeer{Host: "foo", Port: 234},
&pb.AnchorPeer{Host: "bar", Port: 237},
}
invalidMessage := makeInvalidConfigValue()
validMessage := TemplateAnchorPeers("id", endVal)
m := NewApplicationOrgConfig("id", nil)
m.BeginValueProposals(nil)

assert.Error(t, m.ProposeValue(AnchorPeersKey, invalidMessage), "Should have failed on invalid message")
assert.NoError(t, m.ProposeValue(groupToKeyValue(validMessage)), "Should not have failed on invalid message")
m.CommitProposals()

assert.Equal(t, m.AnchorPeers(), endVal, "Did not set updated anchor peers")
_ = api.ValueProposer(NewApplicationOrgGroup("id", nil))
}
3 changes: 2 additions & 1 deletion common/configvalues/root/standardvalues.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func NewStandardValues(protosStructs ...interface{}) (*standardValues, error) {
}

for _, protosStruct := range protosStructs {
logger.Debugf("Initializing protos for %T\n", protosStruct)
if err := sv.initializeProtosStruct(reflect.ValueOf(protosStruct)); err != nil {
return nil, err
}
Expand All @@ -63,7 +64,7 @@ func (sv *standardValues) initializeProtosStruct(objValue reflect.Value) error {
numFields := objValue.Elem().NumField()
for i := 0; i < numFields; i++ {
structField := objType.Elem().Field(i)
fmt.Printf("Processing field: %s\n", structField.Name)
logger.Debugf("Processing field: %s\n", structField.Name)
switch structField.Type.Kind() {
case reflect.Ptr:
fieldPtr := objValue.Elem().Field(i)
Expand Down

0 comments on commit efa8237

Please sign in to comment.