From b609bf0f3b5abc83d3cb9d09446a8e3059b173dc Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Fri, 24 Feb 2017 16:51:06 -0500 Subject: [PATCH] [FAB-2477] Move application config to Proposer https://jira.hyperledger.org/browse/FAB-2477 This CR continues the cleanup of the assorted config handlers, this time for the application config. There is a noticable reduction in code complexity as the application config currently has no values, only sub-groups. Change-Id: I40295c7c46a51284ddbaca317bc8ba494c04a628 Signed-off-by: Jason Yellick --- common/configtx/test/helper.go | 3 +- .../configtx/tool/provisional/provisional.go | 13 +- .../channel/application/sharedconfig.go | 126 ------------------ common/configvalues/root/application.go | 97 ++++++++++++++ .../application_test.go} | 36 +---- .../application_util.go} | 12 +- .../applicationorg.go} | 6 +- .../applicationorg_test.go} | 4 +- common/configvalues/root/channel.go | 13 +- common/configvalues/root/root.go | 3 +- peer/node/start.go | 7 +- 11 files changed, 127 insertions(+), 193 deletions(-) delete mode 100644 common/configvalues/channel/application/sharedconfig.go create mode 100644 common/configvalues/root/application.go rename common/configvalues/{channel/application/sharedconfig_test.go => root/application_test.go} (50%) rename common/configvalues/{channel/application/sharedconfig_util.go => root/application_util.go} (69%) rename common/configvalues/{channel/application/organization.go => root/applicationorg.go} (97%) rename common/configvalues/{channel/application/organization_test.go => root/applicationorg_test.go} (96%) diff --git a/common/configtx/test/helper.go b/common/configtx/test/helper.go index a17313463e1..2583469fe75 100644 --- a/common/configtx/test/helper.go +++ b/common/configtx/test/helper.go @@ -23,7 +23,6 @@ import ( "github.com/hyperledger/fabric/common/configtx" genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig" "github.com/hyperledger/fabric/common/configtx/tool/provisional" - configtxapplication "github.com/hyperledger/fabric/common/configvalues/channel/application" configtxmsp "github.com/hyperledger/fabric/common/configvalues/msp" config "github.com/hyperledger/fabric/common/configvalues/root" "github.com/hyperledger/fabric/common/genesis" @@ -95,7 +94,7 @@ func ApplicationOrgTemplate() configtx.Template { if err != nil { logger.Panicf("Could not load sample MSP config: %s", err) } - return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{configtxapplication.GroupKey, sampleOrgID}, mspConf)) + return configtx.NewSimpleTemplate(configtxmsp.TemplateGroupMSP([]string{config.ApplicationGroupKey, sampleOrgID}, mspConf)) } // OrdererOrgTemplate returns the SAMPLE org with MSP template diff --git a/common/configtx/tool/provisional/provisional.go b/common/configtx/tool/provisional/provisional.go index e2189177e62..0e09f9cff67 100644 --- a/common/configtx/tool/provisional/provisional.go +++ b/common/configtx/tool/provisional/provisional.go @@ -22,7 +22,6 @@ import ( "github.com/hyperledger/fabric/common/cauthdsl" "github.com/hyperledger/fabric/common/configtx" genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig" - configtxapplication "github.com/hyperledger/fabric/common/configvalues/channel/application" configvaluesmsp "github.com/hyperledger/fabric/common/configvalues/msp" config "github.com/hyperledger/fabric/common/configvalues/root" "github.com/hyperledger/fabric/common/genesis" @@ -140,26 +139,26 @@ func New(conf *genesisconfig.Profile) Generator { bs.applicationGroups = []*cb.ConfigGroup{ // Initialize the default Reader/Writer/Admins application policies - policies.TemplateImplicitMetaAnyPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.ReadersPolicyKey), - policies.TemplateImplicitMetaAnyPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.WritersPolicyKey), - policies.TemplateImplicitMetaMajorityPolicy([]string{configtxapplication.GroupKey}, configvaluesmsp.AdminsPolicyKey), + policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.ReadersPolicyKey), + policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.WritersPolicyKey), + policies.TemplateImplicitMetaMajorityPolicy([]string{config.ApplicationGroupKey}, configvaluesmsp.AdminsPolicyKey), } for _, org := range conf.Application.Organizations { mspConfig, err := msp.GetVerifyingMspConfig(org.MSPDir, org.BCCSP, org.ID) if err != nil { logger.Panicf("Error loading MSP configuration for org %s: %s", org.Name, err) } - bs.applicationGroups = append(bs.applicationGroups, configvaluesmsp.TemplateGroupMSP([]string{configtxapplication.GroupKey, org.Name}, mspConfig)) + bs.applicationGroups = append(bs.applicationGroups, configvaluesmsp.TemplateGroupMSP([]string{config.ApplicationGroupKey, org.Name}, mspConfig)) var anchorProtos []*pb.AnchorPeer for _, anchorPeer := range org.AnchorPeers { anchorProtos = append(anchorProtos, &pb.AnchorPeer{ Host: anchorPeer.Host, Port: int32(anchorPeer.Port), }) - } - bs.applicationGroups = append(bs.applicationGroups, configtxapplication.TemplateAnchorPeers(org.Name, anchorProtos)) + bs.applicationGroups = append(bs.applicationGroups, config.TemplateAnchorPeers(org.Name, anchorProtos)) + } } } diff --git a/common/configvalues/channel/application/sharedconfig.go b/common/configvalues/channel/application/sharedconfig.go deleted file mode 100644 index bca0d788107..00000000000 --- a/common/configvalues/channel/application/sharedconfig.go +++ /dev/null @@ -1,126 +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 application - -import ( - api "github.com/hyperledger/fabric/common/configvalues" - "github.com/hyperledger/fabric/common/configvalues/channel/common/organization" - "github.com/hyperledger/fabric/common/configvalues/msp" - cb "github.com/hyperledger/fabric/protos/common" - - "github.com/op/go-logging" -) - -const ( - // GroupKey is the group name for the Application config - GroupKey = "Application" -) - -var orgSchema = &cb.ConfigGroupSchema{ - Groups: map[string]*cb.ConfigGroupSchema{}, - Values: map[string]*cb.ConfigValueSchema{ - AnchorPeersKey: nil, - organization.MSPKey: nil, // TODO, consolidate into a constant once common org code exists - }, - Policies: map[string]*cb.ConfigPolicySchema{ - // TODO, set appropriately once hierarchical policies are implemented - }, -} - -var Schema = &cb.ConfigGroupSchema{ - Groups: map[string]*cb.ConfigGroupSchema{ - "": orgSchema, - }, - Values: map[string]*cb.ConfigValueSchema{}, - Policies: map[string]*cb.ConfigPolicySchema{ - // TODO, set appropriately once hierarchical policies are implemented - }, -} - -var logger = logging.MustGetLogger("common/configtx/handlers/application") - -type sharedConfig struct { - orgs map[string]api.ApplicationOrg -} - -// SharedConfigImpl is an implementation of Manager and configtx.ConfigHandler -// In general, it should only be referenced as an Impl for the configtx.Manager -type SharedConfigImpl struct { - pendingConfig *sharedConfig - config *sharedConfig - - mspConfig *msp.MSPConfigHandler -} - -// NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper -func NewSharedConfigImpl(mspConfig *msp.MSPConfigHandler) *SharedConfigImpl { - return &SharedConfigImpl{ - config: &sharedConfig{}, - mspConfig: mspConfig, - } -} - -// BeginValueProposals is used to start a new config proposal -func (di *SharedConfigImpl) BeginValueProposals(groups []string) ([]api.ValueProposer, error) { - logger.Debugf("Beginning a possible new peer shared config") - if di.pendingConfig != nil { - logger.Panicf("Programming error, cannot call begin in the middle of a proposal") - } - di.pendingConfig = &sharedConfig{ - orgs: make(map[string]api.ApplicationOrg), - } - orgHandlers := make([]api.ValueProposer, len(groups)) - for i, group := range groups { - org, ok := di.pendingConfig.orgs[group] - if !ok { - org = NewApplicationOrgConfig(group, di.mspConfig) - di.pendingConfig.orgs[group] = org - } - orgHandlers[i] = org.(*ApplicationOrgConfig) - } - return orgHandlers, nil -} - -// RollbackProposals is used to abandon a new config proposal -func (di *SharedConfigImpl) RollbackProposals() { - logger.Debugf("Rolling back proposed peer shared config") - di.pendingConfig = nil -} - -// CommitProposals is used to commit a new config proposal -func (di *SharedConfigImpl) CommitProposals() { - logger.Debugf("Committing new peer shared config") - if di.pendingConfig == nil { - logger.Panicf("Programming error, cannot call commit without an existing proposal") - } - di.config = di.pendingConfig - di.pendingConfig = nil -} - -// ProposeValue is used to add new config to the config proposal -func (di *SharedConfigImpl) ProposeValue(key string, configValue *cb.ConfigValue) error { - logger.Warningf("Uknown Peer config item with key %s", key) - return nil -} - -// Organizations returns a map of org ID to ApplicationOrg -func (di *SharedConfigImpl) Organizations() map[string]api.ApplicationOrg { - return di.config.orgs -} - -// PreCommit returns nil -func (di *SharedConfigImpl) PreCommit() error { return nil } diff --git a/common/configvalues/root/application.go b/common/configvalues/root/application.go new file mode 100644 index 00000000000..711a4da59f8 --- /dev/null +++ b/common/configvalues/root/application.go @@ -0,0 +1,97 @@ +/* +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" + "github.com/hyperledger/fabric/common/configvalues/msp" +) + +const ( + // ApplicationGroupKey is the group name for the Application config + ApplicationGroupKey = "Application" +) + +// ApplicationGroup represents the application config group +type ApplicationGroup struct { + *Proposer + *ApplicationConfig + mspConfig *msp.MSPConfigHandler +} + +type ApplicationConfig struct { + *standardValues + + applicationGroup *ApplicationGroup + applicationOrgs map[string]api.ApplicationOrg +} + +// NewSharedConfigImpl creates a new SharedConfigImpl with the given CryptoHelper +func NewApplicationGroup(mspConfig *msp.MSPConfigHandler) *ApplicationGroup { + ag := &ApplicationGroup{ + mspConfig: mspConfig, + } + ag.Proposer = NewProposer(ag) + + return ag +} + +func (ag *ApplicationGroup) NewGroup(name string) (api.ValueProposer, error) { + return NewApplicationOrgConfig(name, ag.mspConfig), nil +} + +// Allocate returns the +func (ag *ApplicationGroup) Allocate() Values { + return NewApplicationConfig(ag) +} + +func NewApplicationConfig(ag *ApplicationGroup) *ApplicationConfig { + sv, err := NewStandardValues(&(struct{}{})) + if err != nil { + logger.Panicf("Programming error: %s", err) + } + + return &ApplicationConfig{ + applicationGroup: ag, + + // Currently there are no config values + standardValues: sv, + } +} + +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) + if !ok { + return fmt.Errorf("Application sub-group %s was not an ApplicationOrgGroup, actually %T", key, value) + } + } + return nil +} + +func (ac *ApplicationConfig) Commit() { + ac.applicationGroup.ApplicationConfig = ac +} + +// Organizations returns a map of org ID to ApplicationOrg +func (ac *ApplicationConfig) Organizations() map[string]api.ApplicationOrg { + return ac.applicationOrgs +} diff --git a/common/configvalues/channel/application/sharedconfig_test.go b/common/configvalues/root/application_test.go similarity index 50% rename from common/configvalues/channel/application/sharedconfig_test.go rename to common/configvalues/root/application_test.go index 7e03036f86e..9e0ab9e1663 100644 --- a/common/configvalues/channel/application/sharedconfig_test.go +++ b/common/configvalues/root/application_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package application +package config import ( "testing" @@ -29,37 +29,5 @@ func init() { } func TestApplicationInterface(t *testing.T) { - _ = api.Application(NewSharedConfigImpl(nil)) -} - -func TestApplicationDoubleBegin(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Fatalf("Should have panicked on multiple begin configs") - } - }() - - m := NewSharedConfigImpl(nil) - m.BeginValueProposals(nil) - m.BeginValueProposals(nil) -} - -func TestApplicationCommitWithoutBegin(t *testing.T) { - defer func() { - if err := recover(); err == nil { - t.Fatalf("Should have panicked on multiple begin configs") - } - }() - - m := NewSharedConfigImpl(nil) - m.CommitProposals() -} - -func TestApplicationRollback(t *testing.T) { - m := NewSharedConfigImpl(nil) - m.pendingConfig = &sharedConfig{} - m.RollbackProposals() - if m.pendingConfig != nil { - t.Fatalf("Should have cleared pending config on rollback") - } + _ = api.Application((*ApplicationGroup)(nil)) } diff --git a/common/configvalues/channel/application/sharedconfig_util.go b/common/configvalues/root/application_util.go similarity index 69% rename from common/configvalues/channel/application/sharedconfig_util.go rename to common/configvalues/root/application_util.go index ea4689a78dd..94d34753f75 100644 --- a/common/configvalues/channel/application/sharedconfig_util.go +++ b/common/configvalues/root/application_util.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package application +package config import ( cb "github.com/hyperledger/fabric/protos/common" @@ -22,11 +22,11 @@ import ( "github.com/hyperledger/fabric/protos/utils" ) -func configGroup(orgID string, key string, value []byte) *cb.ConfigGroup { +func applicationConfigGroup(orgID string, key string, value []byte) *cb.ConfigGroup { result := cb.NewConfigGroup() - result.Groups[GroupKey] = cb.NewConfigGroup() - result.Groups[GroupKey].Groups[orgID] = cb.NewConfigGroup() - result.Groups[GroupKey].Groups[orgID].Values[key] = &cb.ConfigValue{ + result.Groups[ApplicationGroupKey] = cb.NewConfigGroup() + result.Groups[ApplicationGroupKey].Groups[orgID] = cb.NewConfigGroup() + result.Groups[ApplicationGroupKey].Groups[orgID].Values[key] = &cb.ConfigValue{ Value: value, } return result @@ -34,5 +34,5 @@ func configGroup(orgID string, key string, value []byte) *cb.ConfigGroup { // TemplateAnchorPeers creates a headerless config item representing the anchor peers func TemplateAnchorPeers(orgID string, anchorPeers []*pb.AnchorPeer) *cb.ConfigGroup { - return configGroup(orgID, AnchorPeersKey, utils.MarshalOrPanic(&pb.AnchorPeers{AnchorPeers: anchorPeers})) + return applicationConfigGroup(orgID, AnchorPeersKey, utils.MarshalOrPanic(&pb.AnchorPeers{AnchorPeers: anchorPeers})) } diff --git a/common/configvalues/channel/application/organization.go b/common/configvalues/root/applicationorg.go similarity index 97% rename from common/configvalues/channel/application/organization.go rename to common/configvalues/root/applicationorg.go index 2f6e6574b87..ca6600a70d4 100644 --- a/common/configvalues/channel/application/organization.go +++ b/common/configvalues/root/applicationorg.go @@ -14,12 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package application +package config import ( "fmt" - "github.com/hyperledger/fabric/common/configvalues" + 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" @@ -63,7 +63,7 @@ func (oc *ApplicationOrgConfig) AnchorPeers() []*pb.AnchorPeer { } // BeginValueProposals is used to start a new config proposal -func (oc *ApplicationOrgConfig) BeginValueProposals(groups []string) ([]config.ValueProposer, error) { +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") diff --git a/common/configvalues/channel/application/organization_test.go b/common/configvalues/root/applicationorg_test.go similarity index 96% rename from common/configvalues/channel/application/organization_test.go rename to common/configvalues/root/applicationorg_test.go index db1178fda38..c715263cbf6 100644 --- a/common/configvalues/channel/application/organization_test.go +++ b/common/configvalues/root/applicationorg_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package application +package config import ( "testing" @@ -38,7 +38,7 @@ func makeInvalidConfigValue() *cb.ConfigValue { } func groupToKeyValue(configGroup *cb.ConfigGroup) (string, *cb.ConfigValue) { - for _, group := range configGroup.Groups[GroupKey].Groups { + for _, group := range configGroup.Groups[ApplicationGroupKey].Groups { for key, value := range group.Values { return key, value } diff --git a/common/configvalues/root/channel.go b/common/configvalues/root/channel.go index 1462fbe7894..31a2fc99ff4 100644 --- a/common/configvalues/root/channel.go +++ b/common/configvalues/root/channel.go @@ -22,7 +22,6 @@ import ( "github.com/hyperledger/fabric/bccsp" api "github.com/hyperledger/fabric/common/configvalues" - "github.com/hyperledger/fabric/common/configvalues/channel/application" "github.com/hyperledger/fabric/common/configvalues/msp" "github.com/hyperledger/fabric/common/util" cb "github.com/hyperledger/fabric/protos/common" @@ -103,15 +102,15 @@ func (cg *ChannelGroup) OrdererConfig() *OrdererGroup { } // ApplicationConfig returns the application config associated with this channel -func (cg *ChannelGroup) ApplicationConfig() *application.SharedConfigImpl { +func (cg *ChannelGroup) ApplicationConfig() *ApplicationGroup { return cg.ChannelConfig.appConfig } // NewGroup instantiates either a new application or orderer config func (cg *ChannelGroup) NewGroup(group string) (api.ValueProposer, error) { switch group { - case application.GroupKey: - return application.NewSharedConfigImpl(cg.mspConfigHandler), nil + case ApplicationGroupKey: + return NewApplicationGroup(cg.mspConfigHandler), nil case OrdererGroupKey: return NewOrdererGroup(cg.mspConfigHandler), nil default: @@ -126,7 +125,7 @@ type ChannelConfig struct { hashingAlgorithm func(input []byte) []byte - appConfig *application.SharedConfigImpl + appConfig *ApplicationGroup ordererConfig *OrdererGroup } @@ -175,8 +174,8 @@ func (cc *ChannelConfig) Validate(groups map[string]api.ValueProposer) error { var ok bool for key, value := range groups { switch key { - case application.GroupKey: - cc.appConfig, ok = value.(*application.SharedConfigImpl) + case ApplicationGroupKey: + cc.appConfig, ok = value.(*ApplicationGroup) if !ok { return fmt.Errorf("Application group was not Application config") } diff --git a/common/configvalues/root/root.go b/common/configvalues/root/root.go index f064228ef1a..dc442c7f022 100644 --- a/common/configvalues/root/root.go +++ b/common/configvalues/root/root.go @@ -20,7 +20,6 @@ import ( "fmt" configvaluesapi "github.com/hyperledger/fabric/common/configvalues" - "github.com/hyperledger/fabric/common/configvalues/channel/application" "github.com/hyperledger/fabric/common/configvalues/msp" cb "github.com/hyperledger/fabric/protos/common" ) @@ -84,6 +83,6 @@ func (r *Root) Orderer() *OrdererGroup { } // Application returns the associated Application level config -func (r *Root) Application() *application.SharedConfigImpl { +func (r *Root) Application() *ApplicationGroup { return r.channel.ApplicationConfig() } diff --git a/peer/node/start.go b/peer/node/start.go index 24b4c35a8a0..333279fcc6e 100644 --- a/peer/node/start.go +++ b/peer/node/start.go @@ -30,7 +30,6 @@ import ( "github.com/hyperledger/fabric/common/configtx" "github.com/hyperledger/fabric/common/configtx/test" - "github.com/hyperledger/fabric/common/configvalues/channel/application" "github.com/hyperledger/fabric/common/configvalues/msp" config "github.com/hyperledger/fabric/common/configvalues/root" "github.com/hyperledger/fabric/common/genesis" @@ -183,9 +182,9 @@ func serve(args []string) error { // add readers, writers and admin policies for the default chain policyTemplate := configtx.NewSimpleTemplate( - policies.TemplateImplicitMetaAnyPolicy([]string{application.GroupKey}, msp.ReadersPolicyKey), - policies.TemplateImplicitMetaAnyPolicy([]string{application.GroupKey}, msp.WritersPolicyKey), - policies.TemplateImplicitMetaMajorityPolicy([]string{application.GroupKey}, msp.AdminsPolicyKey), + policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, msp.ReadersPolicyKey), + policies.TemplateImplicitMetaAnyPolicy([]string{config.ApplicationGroupKey}, msp.WritersPolicyKey), + policies.TemplateImplicitMetaMajorityPolicy([]string{config.ApplicationGroupKey}, msp.AdminsPolicyKey), ) // We create a genesis block for the test