From 2541878d7217b91d0e0353beb42625397079cf2a Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Mon, 20 Feb 2017 23:18:51 -0500 Subject: [PATCH] [FAB-2397] Move org config to common Proposer https://jira.hyperledger.org/browse/FAB-2397 This is the another in a series of changesets migrating the individual config handlers to the common Proposer root structure to eliminate duplicated code. Change-Id: I0836d019e58a0e8edc9ab236480be2f1571b81f6 Signed-off-by: Jason Yellick --- .../common/organization/organization.go | 148 ------------------ .../common/organization/organization_test.go | 65 -------- common/configvalues/root/applicationorg.go | 15 +- common/configvalues/root/orderer.go | 3 +- common/configvalues/root/organization.go | 133 ++++++++++++++++ 5 files changed, 141 insertions(+), 223 deletions(-) delete mode 100644 common/configvalues/channel/common/organization/organization.go delete mode 100644 common/configvalues/channel/common/organization/organization_test.go create mode 100644 common/configvalues/root/organization.go diff --git a/common/configvalues/channel/common/organization/organization.go b/common/configvalues/channel/common/organization/organization.go deleted file mode 100644 index f4863532d26..00000000000 --- a/common/configvalues/channel/common/organization/organization.go +++ /dev/null @@ -1,148 +0,0 @@ -/* -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 organization - -import ( - "fmt" - - "github.com/hyperledger/fabric/common/configvalues" - mspconfig "github.com/hyperledger/fabric/common/configvalues/msp" - "github.com/hyperledger/fabric/msp" - cb "github.com/hyperledger/fabric/protos/common" - mspprotos "github.com/hyperledger/fabric/protos/msp" - - "github.com/golang/protobuf/proto" - "github.com/op/go-logging" -) - -// Org config keys -const ( - // MSPKey is value key for marshaled *mspconfig.MSPConfig - MSPKey = "MSP" -) - -var logger = logging.MustGetLogger("common/configtx/handlers") - -type orgConfig struct { - msp msp.MSP -} - -// SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler -// In general, it should only be referenced as an Impl for the configtx.Manager -type OrgConfig struct { - id string - mspID string - pendingConfig *orgConfig - config *orgConfig - - mspConfig *mspconfig.MSPConfigHandler -} - -// NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper -func NewOrgConfig(id string, mspConfig *mspconfig.MSPConfigHandler) *OrgConfig { - return &OrgConfig{ - id: id, - config: &orgConfig{}, - mspConfig: mspConfig, - } -} - -// BeginValueProposals is used to start a new config proposal -func (oc *OrgConfig) BeginValueProposals(groups []string) ([]config.ValueProposer, error) { - logger.Debugf("Beginning a possible new org config") - if len(groups) != 0 { - return nil, fmt.Errorf("Orgs do not support sub-groups") - } - - if oc.pendingConfig != nil { - logger.Panicf("Programming error, cannot call begin in the middle of a proposal") - } - oc.pendingConfig = &orgConfig{} - return nil, nil -} - -// RollbackProposals is used to abandon a new config proposal -func (oc *OrgConfig) RollbackProposals() { - logger.Debugf("Rolling back proposed org config") - oc.pendingConfig = nil -} - -// CommitProposals is used to commit a new config proposal -func (oc *OrgConfig) 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 -} - -// Name returns the name this org is referred to in config -func (oc *OrgConfig) Name() string { - return oc.id -} - -// MSPID returns the MSP ID associated with this org -func (oc *OrgConfig) MSPID() string { - return oc.mspID -} - -// ProposeValue is used to add new config to the config proposal -func (oc *OrgConfig) ProposeValue(key string, configValue *cb.ConfigValue) error { - switch key { - case MSPKey: - logger.Debugf("Initializing org MSP for id %s", oc.id) - - mspconfig := &mspprotos.MSPConfig{} - err := proto.Unmarshal(configValue.Value, mspconfig) - if err != nil { - return fmt.Errorf("Error unmarshalling msp config for org %s, err %s", oc.id, err) - } - - logger.Debugf("Setting up MSP") - msp, err := oc.mspConfig.ProposeMSP(mspconfig) - if err != nil { - return err - } - - mspID, err := msp.GetIdentifier() - if err != nil { - return fmt.Errorf("Could not extract msp identifier for org %s, err %s", oc.id, err) - } - - if mspID == "" { - return fmt.Errorf("MSP for org %s has empty MSP ID", oc.id) - } - - // If the mspID has never been initialized, store it to ensure immutability - if oc.mspID == "" { - oc.mspID = mspID - } - - if mspID != oc.mspID { - return fmt.Errorf("MSP for org %s attempted to change its identifier from %s to %s", oc.id, oc.mspID, mspID) - } - - oc.pendingConfig.msp = msp - default: - logger.Warningf("Uknown org config item with key %s", key) - } - return nil -} - -// PreCommit returns nil -func (oc *OrgConfig) PreCommit() error { return nil } diff --git a/common/configvalues/channel/common/organization/organization_test.go b/common/configvalues/channel/common/organization/organization_test.go deleted file mode 100644 index 4dba25fe6fc..00000000000 --- a/common/configvalues/channel/common/organization/organization_test.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -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 organization - -import ( - "testing" - - api "github.com/hyperledger/fabric/common/configvalues" - - logging "github.com/op/go-logging" -) - -func init() { - logging.SetLevel(logging.DEBUG, "") -} - -func TestInterface(t *testing.T) { - _ = api.ValueProposer(NewOrgConfig("id", nil)) -} - -func TestDoubleBegin(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Fatalf("Should have panicked on multiple begin configs") - } - }() - - m := NewOrgConfig("id", nil) - m.BeginValueProposals(nil) - m.BeginValueProposals(nil) -} - -func TestCommitWithoutBegin(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Fatalf("Should have panicked on multiple begin configs") - } - }() - - m := NewOrgConfig("id", nil) - m.CommitProposals() -} - -func TestRollback(t *testing.T) { - m := NewOrgConfig("id", nil) - m.pendingConfig = &orgConfig{} - m.RollbackProposals() - if m.pendingConfig != nil { - t.Fatalf("Should have cleared pending config on rollback") - } -} diff --git a/common/configvalues/root/applicationorg.go b/common/configvalues/root/applicationorg.go index ca6600a70d4..1560af24e76 100644 --- a/common/configvalues/root/applicationorg.go +++ b/common/configvalues/root/applicationorg.go @@ -20,7 +20,6 @@ import ( "fmt" api "github.com/hyperledger/fabric/common/configvalues" - "github.com/hyperledger/fabric/common/configvalues/channel/common/organization" mspconfig "github.com/hyperledger/fabric/common/configvalues/msp" cb "github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric/protos/peer" @@ -42,7 +41,7 @@ type applicationOrgConfig struct { // 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 { - *organization.OrgConfig + *OrganizationGroup pendingConfig *applicationOrgConfig config *applicationOrgConfig @@ -52,8 +51,8 @@ type ApplicationOrgConfig struct { // NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper func NewApplicationOrgConfig(id string, mspConfig *mspconfig.MSPConfigHandler) *ApplicationOrgConfig { return &ApplicationOrgConfig{ - OrgConfig: organization.NewOrgConfig(id, mspConfig), - config: &applicationOrgConfig{}, + OrganizationGroup: NewOrganizationGroup(id, mspConfig), + config: &applicationOrgConfig{}, } } @@ -72,14 +71,14 @@ func (oc *ApplicationOrgConfig) BeginValueProposals(groups []string) ([]api.Valu logger.Panicf("Programming error, cannot call begin in the middle of a proposal") } oc.pendingConfig = &applicationOrgConfig{} - return oc.OrgConfig.BeginValueProposals(groups) + return oc.OrganizationGroup.BeginValueProposals(groups) } // RollbackProposals is used to abandon a new config proposal func (oc *ApplicationOrgConfig) RollbackProposals() { logger.Debugf("Rolling back proposed org config") oc.pendingConfig = nil - oc.OrgConfig.RollbackProposals() + oc.OrganizationGroup.RollbackProposals() } // CommitProposals is used to commit a new config proposal @@ -90,7 +89,7 @@ func (oc *ApplicationOrgConfig) CommitProposals() { } oc.config = oc.pendingConfig oc.pendingConfig = nil - oc.OrgConfig.CommitProposals() + oc.OrganizationGroup.CommitProposals() } // ProposeValue is used to add new config to the config proposal @@ -106,7 +105,7 @@ func (oc *ApplicationOrgConfig) ProposeValue(key string, configValue *cb.ConfigV } oc.pendingConfig.anchorPeers = anchorPeers.AnchorPeers default: - return oc.OrgConfig.ProposeValue(key, configValue) + return oc.OrganizationGroup.ProposeValue(key, configValue) } return nil diff --git a/common/configvalues/root/orderer.go b/common/configvalues/root/orderer.go index 67ea6914827..50ab269bfa4 100644 --- a/common/configvalues/root/orderer.go +++ b/common/configvalues/root/orderer.go @@ -24,7 +24,6 @@ import ( "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" ) @@ -80,7 +79,7 @@ func NewOrdererGroup(mspConfig *msp.MSPConfigHandler) *OrdererGroup { // NewGroup returns an Org instance func (og *OrdererGroup) NewGroup(name string) (api.ValueProposer, error) { - return organization.NewOrgConfig(name, og.mspConfig), nil + return NewOrganizationGroup(name, og.mspConfig), nil } func (og *OrdererGroup) Allocate() Values { diff --git a/common/configvalues/root/organization.go b/common/configvalues/root/organization.go new file mode 100644 index 00000000000..b89cdee6978 --- /dev/null +++ b/common/configvalues/root/organization.go @@ -0,0 +1,133 @@ +/* +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 config + +import ( + "fmt" + + api "github.com/hyperledger/fabric/common/configvalues" + mspconfig "github.com/hyperledger/fabric/common/configvalues/msp" + "github.com/hyperledger/fabric/msp" + mspprotos "github.com/hyperledger/fabric/protos/msp" +) + +// Org config keys +const ( + // MSPKey is value key for marshaled *mspconfig.MSPConfig + MSPKey = "MSP" +) + +type OrganizationProtos struct { + MSP *mspprotos.MSPConfig +} + +type OrganizationConfig struct { + *standardValues + protos *OrganizationProtos + + organizationGroup *OrganizationGroup + + msp msp.MSP + mspID string +} + +// Config stores common configuration information for organizations +type OrganizationGroup struct { + *Proposer + *OrganizationConfig + name string + mspConfigHandler *mspconfig.MSPConfigHandler +} + +// NewConfig creates an instnace of the organization Config +func NewOrganizationGroup(name string, mspConfigHandler *mspconfig.MSPConfigHandler) *OrganizationGroup { + og := &OrganizationGroup{ + name: name, + mspConfigHandler: mspConfigHandler, + } + og.Proposer = NewProposer(og) + return og +} + +// Name returns the name this org is referred to in config +func (og *OrganizationGroup) Name() string { + return og.name +} + +// MSPID returns the MSP ID associated with this org +func (og *OrganizationGroup) MSPID() string { + return og.mspID +} + +// NewGroup always errors +func (og *OrganizationGroup) NewGroup(name string) (api.ValueProposer, error) { + return nil, fmt.Errorf("Organization does not support subgroups") +} + +// Allocate creates the proto resources neeeded for a proposal +func (og *OrganizationGroup) Allocate() Values { + return NewOrganizationConfig(og) +} + +func NewOrganizationConfig(og *OrganizationGroup) *OrganizationConfig { + oc := &OrganizationConfig{ + protos: &OrganizationProtos{}, + + organizationGroup: og, + } + + var err error + oc.standardValues, err = NewStandardValues(oc.protos) + if err != nil { + logger.Panicf("Programming error: %s", err) + } + return oc +} + +// Validate returns whether the configuration is valid +func (oc *OrganizationConfig) Validate(groups map[string]api.ValueProposer) error { + return oc.validateMSP() +} + +func (oc *OrganizationConfig) Commit() { + oc.organizationGroup.OrganizationConfig = oc +} + +func (oc *OrganizationConfig) validateMSP() error { + var err error + + logger.Debugf("Setting up MSP for org %s", oc.organizationGroup.name) + oc.msp, err = oc.organizationGroup.mspConfigHandler.ProposeMSP(oc.protos.MSP) + if err != nil { + return err + } + + oc.mspID, err = oc.msp.GetIdentifier() + if err != nil { + return fmt.Errorf("Could not extract msp identifier for org %s: %s", oc.organizationGroup.name, err) + } + + if oc.mspID == "" { + return fmt.Errorf("MSP for org %s has empty MSP ID", oc.organizationGroup.name) + } + + if oc.organizationGroup.OrganizationConfig != nil && oc.organizationGroup.mspID != oc.mspID { + return fmt.Errorf("Organization %s attempted to change its MSP ID from %s to %s", oc.organizationGroup.name, oc.organizationGroup.mspID, oc.mspID) + } + + return nil +}