From 05714497dce5781a5f2552ddb802f5bd617cf346 Mon Sep 17 00:00:00 2001 From: Tatsuya Sato Date: Tue, 13 Oct 2020 08:30:56 -0700 Subject: [PATCH] [FAB-18268] Add SetPolicies() to easily replace multiple policies in an existing configuration with the given policies (#39) * [FAB-18268] Modify setPolicies() to replace all policies in an existing configuration with the given ones Currently, setPolicies() upserts policies in an existing configuration with the given ones. This speficifation makes it difficult to remove multiple policies that are not needed. In preparation for supporting SetPolicies() for groups and orgs, this patch modifies setPolicies() to clear all existing policies in an existing configuration and then replace them with the given policies. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to ChannelGroup This patch adds SetPolicies() to easily replace multiple policies for a channel group in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to ApplicationGroup This patch adds SetPolicies() to easily replace multiple policies for an application group in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to OrdererGroup This patch adds SetPolicies() to easily replace multiple policies for an orderer group in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to ApplicationOrg This patch adds SetPolicies() to easily replace multiple policies for an application org in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to OrdererOrg This patch adds SetPolicies() to easily replace multiple policies for an orderer org in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * [FAB-18268] Add SetPolicies() to ConsortiumOrg This patch adds SetPolicies() to easily replace multiple policies for a consortium org in an existing configuration with the given ones. Signed-off-by: Tatsuya Sato * Fix some typos in comments Signed-off-by: Tatsuya Sato --- configtx/application.go | 32 ++++- configtx/application_test.go | 208 +++++++++++++++++++++++++++++ configtx/channel.go | 10 +- configtx/channel_test.go | 83 ++++++++++++ configtx/consortiums.go | 15 ++- configtx/consortiums_test.go | 102 +++++++++++++++ configtx/orderer.go | 30 ++++- configtx/orderer_test.go | 246 +++++++++++++++++++++++++++++++++++ configtx/policies.go | 1 + 9 files changed, 714 insertions(+), 13 deletions(-) diff --git a/configtx/application.go b/configtx/application.go index 17bdeb8..e738770 100644 --- a/configtx/application.go +++ b/configtx/application.go @@ -139,7 +139,7 @@ func (a *ApplicationGroup) Capabilities() ([]string, error) { } // AddCapability sets capability to the provided channel config. -// If the provided capability already exist in current configuration, this action +// If the provided capability already exists in current configuration, this action // will be a no-op. func (a *ApplicationGroup) AddCapability(capability string) error { capabilities, err := a.Capabilities() @@ -177,7 +177,7 @@ func (a *ApplicationGroup) Policies() (map[string]Policy, error) { } // SetPolicy sets the specified policy in the application group's config policy map. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (a *ApplicationGroup) SetPolicy(modPolicy, policyName string, policy Policy) error { err := setPolicy(a.applicationGroup, modPolicy, policyName, policy) if err != nil { @@ -187,6 +187,17 @@ func (a *ApplicationGroup) SetPolicy(modPolicy, policyName string, policy Policy return nil } +// SetPolicies sets the specified policies in the application group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (a *ApplicationGroup) SetPolicies(modPolicy string, policies map[string]Policy) error { + err := setPolicies(a.applicationGroup, policies, modPolicy) + if err != nil { + return fmt.Errorf("failed to set policies: %v", err) + } + + return nil +} + // RemovePolicy removes an existing policy from an application's configuration. // Removal will panic if the application group does not exist. func (a *ApplicationGroup) RemovePolicy(policyName string) error { @@ -200,13 +211,13 @@ func (a *ApplicationGroup) RemovePolicy(policyName string) error { } // Policies returns the map of policies for a specific application org in -// the updated config.. +// the updated config. func (a *ApplicationOrg) Policies() (map[string]Policy, error) { return getPolicies(a.orgGroup.Policies) } // SetPolicy sets the specified policy in the application org group's config policy map. -// If an Organization policy already exist in current configuration, its value will be overwritten. +// If an Organization policy already exists in current configuration, its value will be overwritten. func (a *ApplicationOrg) SetPolicy(modPolicy, policyName string, policy Policy) error { err := setPolicy(a.orgGroup, modPolicy, policyName, policy) if err != nil { @@ -216,6 +227,17 @@ func (a *ApplicationOrg) SetPolicy(modPolicy, policyName string, policy Policy) return nil } +// SetPolicies sets the specified policies in the application org group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (a *ApplicationOrg) SetPolicies(modPolicy string, policies map[string]Policy) error { + err := setPolicies(a.orgGroup, policies, modPolicy) + if err != nil { + return fmt.Errorf("failed to set policies: %v", err) + } + + return nil +} + // RemovePolicy removes an existing policy from an application organization. func (a *ApplicationOrg) RemovePolicy(policyName string) error { policies, err := a.Policies() @@ -357,7 +379,7 @@ func (a *ApplicationGroup) ACLs() (map[string]string, error) { } // SetACLs sets ACLS to an existing channel config application. -// If an ACL already exist in current configuration, it will be replaced with new ACL. +// If an ACL already exists in current configuration, it will be replaced with new ACL. func (a *ApplicationGroup) SetACLs(acls map[string]string) error { err := setValue(a.applicationGroup, aclValues(acls), AdminsPolicyKey) if err != nil { diff --git a/configtx/application_test.go b/configtx/application_test.go index 7e50058..30f4e56 100644 --- a/configtx/application_test.go +++ b/configtx/application_test.go @@ -1760,6 +1760,124 @@ func TestSetApplicationOrgPolicyFailures(t *testing.T) { gt.Expect(err).To(MatchError("failed to set policy 'TestPolicy': unknown policy type: ")) } +func TestSetApplicationOrgPolicies(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channelGroup := newConfigGroup() + applicationGroup := newConfigGroup() + + application, _ := baseApplication(t) + + for _, org := range application.Organizations { + org.Policies = applicationOrgStandardPolicies() + org.Policies["TestPolicy_Remove"] = org.Policies[EndorsementPolicyKey] + + orgGroup, err := newOrgConfigGroup(org) + gt.Expect(err).NotTo(HaveOccurred()) + + applicationGroup.Groups[org.Name] = orgGroup + } + channelGroup.Groups[ApplicationGroupKey] = applicationGroup + config := &cb.Config{ + ChannelGroup: channelGroup, + } + + c := New(config) + + applicationOrg1 := c.Application().Organization("Org1") + policies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + LifecycleEndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + } + err := applicationOrg1.SetPolicies(AdminsPolicyKey, policies) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedPolicies, err := applicationOrg1.Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedPolicies).To(Equal(policies)) + + originalPolicies := c.original.ChannelGroup.Groups[ApplicationGroupKey].Groups["Org1"].Policies + gt.Expect(originalPolicies).To(Equal(applicationGroup.Groups["Org1"].Policies)) +} + +func TestSetApplicationOrgPoliciesFailures(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channelGroup := newConfigGroup() + applicationGroup := newConfigGroup() + + application, _ := baseApplication(t) + for _, org := range application.Organizations { + org.Policies = applicationOrgStandardPolicies() + + orgGroup, err := newOrgConfigGroup(org) + gt.Expect(err).NotTo(HaveOccurred()) + + applicationGroup.Groups[org.Name] = orgGroup + } + channelGroup.Groups[ApplicationGroupKey] = applicationGroup + config := &cb.Config{ + ChannelGroup: channelGroup, + } + + c := New(config) + + policies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + LifecycleEndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy": {}, + } + + err := c.Application().Organization("Org1").SetPolicies(AdminsPolicyKey, policies) + gt.Expect(err).To(MatchError("failed to set policies: unknown policy type: ")) +} + func TestSetApplicationPolicy(t *testing.T) { t.Parallel() gt := NewGomegaWithT(t) @@ -1829,6 +1947,96 @@ func TestSetApplicationPolicyFailures(t *testing.T) { gt.Expect(err).To(MatchError("failed to set policy 'TestPolicy': unknown policy type: ")) } +func TestSetApplicationPolicies(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channelGroup := newConfigGroup() + application, _ := baseApplication(t) + application.Policies["TestPolicy_Remove"] = application.Policies[ReadersPolicyKey] + + applicationGroup, err := newApplicationGroupTemplate(application) + gt.Expect(err).NotTo(HaveOccurred()) + + channelGroup.Groups[ApplicationGroupKey] = applicationGroup + config := &cb.Config{ + ChannelGroup: channelGroup, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + } + + a := c.Application() + err = a.SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedPolicies, err := a.Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedPolicies).To(Equal(newPolicies)) + + originalPolicies := c.original.ChannelGroup.Groups[ApplicationGroupKey].Policies + gt.Expect(originalPolicies).To(Equal(applicationGroup.Policies)) +} + +func TestSetApplicationPoliciesFailures(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channelGroup := newConfigGroup() + application, _ := baseApplication(t) + + applicationGroup, err := newApplicationGroupTemplate(application) + gt.Expect(err).NotTo(HaveOccurred()) + + channelGroup.Groups[ApplicationGroupKey] = applicationGroup + config := &cb.Config{ + ChannelGroup: channelGroup, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + "TestPolicy": {}, + } + + err = c.Application().SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).To(MatchError("failed to set policies: unknown policy type: ")) +} + func TestAppOrgRemoveApplicationPolicy(t *testing.T) { t.Parallel() gt := NewGomegaWithT(t) diff --git a/configtx/channel.go b/configtx/channel.go index 76bf833..b3ac783 100644 --- a/configtx/channel.go +++ b/configtx/channel.go @@ -84,11 +84,17 @@ func (c *ChannelGroup) Policies() (map[string]Policy, error) { } // SetPolicy sets the specified policy in the channel group's config policy map. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (c *ChannelGroup) SetPolicy(modPolicy, policyName string, policy Policy) error { return setPolicy(c.channelGroup, modPolicy, policyName, policy) } +// SetPolicies sets the specified policies in the channel group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (c *ChannelGroup) SetPolicies(modPolicy string, policies map[string]Policy) error { + return setPolicies(c.channelGroup, policies, modPolicy) +} + // RemovePolicy removes an existing channel level policy. func (c *ChannelGroup) RemovePolicy(policyName string) error { policies, err := c.Policies() @@ -112,7 +118,7 @@ func (c *ChannelGroup) Capabilities() ([]string, error) { } // AddCapability adds capability to the provided channel config. -// If the provided capability already exist in current configuration, this action +// If the provided capability already exists in current configuration, this action // will be a no-op. func (c *ChannelGroup) AddCapability(capability string) error { capabilities, err := c.Capabilities() diff --git a/configtx/channel_test.go b/configtx/channel_test.go index 4068fab..f9eb26d 100644 --- a/configtx/channel_test.go +++ b/configtx/channel_test.go @@ -258,6 +258,89 @@ func TestSetChannelPolicy(t *testing.T) { gt.Expect(baseChannel.Policies["TestPolicy"]).To(BeNil()) } +func TestSetChannelPolicies(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channel, _, err := baseApplicationChannelGroup(t) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: channel, + } + basePolicies := standardPolicies() + basePolicies["TestPolicy_Remove"] = Policy{Type: ImplicitMetaPolicyType, Rule: "ANY Readers"} + err = setPolicies(channel, basePolicies, AdminsPolicyKey) + gt.Expect(err).NotTo(HaveOccurred()) + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Admins", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + } + + err = c.Channel().SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedChannelPolicies, err := c.Channel().Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedChannelPolicies).To(Equal(newPolicies)) + + originalChannel := c.original.ChannelGroup + gt.Expect(originalChannel.Policies).To(Equal(config.ChannelGroup.Policies)) +} + +func TestSetChannelPoliciesFailures(t *testing.T) { + t.Parallel() + gt := NewGomegaWithT(t) + + channel, _, err := baseApplicationChannelGroup(t) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: channel, + } + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + "TestPolicy": {}, + } + + err = c.Channel().SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).To(MatchError("unknown policy type: ")) +} + func TestRemoveChannelPolicy(t *testing.T) { t.Parallel() gt := NewGomegaWithT(t) diff --git a/configtx/consortiums.go b/configtx/consortiums.go index 8ec5472..1ea7746 100644 --- a/configtx/consortiums.go +++ b/configtx/consortiums.go @@ -204,7 +204,7 @@ func (c *ConsortiumOrg) setMSPConfig(updatedMSP MSP) error { // SetChannelCreationPolicy sets the ConsortiumChannelCreationPolicy for // the given configuration Group. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (c *ConsortiumGroup) SetChannelCreationPolicy(policy Policy) error { imp, err := implicitMetaFromString(policy.Rule) if err != nil { @@ -230,7 +230,7 @@ func (c *ConsortiumOrg) Policies() (map[string]Policy, error) { } // SetPolicy sets the specified policy in the consortium org group's config policy map. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (c *ConsortiumOrg) SetPolicy(name string, policy Policy) error { err := setPolicy(c.orgGroup, AdminsPolicyKey, name, policy) if err != nil { @@ -240,6 +240,17 @@ func (c *ConsortiumOrg) SetPolicy(name string, policy Policy) error { return nil } +// SetPolicies sets the specified policies in the consortium org group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (c *ConsortiumOrg) SetPolicies(policies map[string]Policy) error { + err := setPolicies(c.orgGroup, policies, AdminsPolicyKey) + if err != nil { + return fmt.Errorf("failed to set policies to consortium org '%s': %v", c.name, err) + } + + return nil +} + // RemovePolicy removes an existing policy from a consortium's organization. // Removal will panic if either the consortiums group, consortium group, or consortium org group does not exist. func (c *ConsortiumOrg) RemovePolicy(name string) { diff --git a/configtx/consortiums_test.go b/configtx/consortiums_test.go index 9d2743b..6c8cc29 100644 --- a/configtx/consortiums_test.go +++ b/configtx/consortiums_test.go @@ -1578,6 +1578,108 @@ func TestSetConsortiumOrgPolicyFailures(t *testing.T) { } } +func TestSetConsortiumOrgPolicies(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + consortiums, _ := baseConsortiums(t) + consortiums[0].Organizations[0].Policies["TestPolicy_Remove"] = Policy{Type: ImplicitMetaPolicyType, Rule: "MAJORITY Endorsement"} + + consortiumsGroup, err := newConsortiumsGroup(consortiums) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + ConsortiumsGroupKey: consortiumsGroup, + }, + }, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + } + + consortium1Org1 := c.Consortium("Consortium1").Organization("Org1") + err = consortium1Org1.SetPolicies(newPolicies) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedPolicies, err := consortium1Org1.Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedPolicies).To(Equal(newPolicies)) +} + +func TestSetConsortiumOrgPoliciesFailures(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + consortiums, _ := baseConsortiums(t) + + consortiumsGroup, err := newConsortiumsGroup(consortiums) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + ConsortiumsGroupKey: consortiumsGroup, + }, + }, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy": {}, + } + + consortium1Org1 := c.Consortium("Consortium1").Organization("Org1") + err = consortium1Org1.SetPolicies(newPolicies) + gt.Expect(err).To(MatchError("failed to set policies to consortium org 'Org1': unknown policy type: ")) +} + func TestRemoveConsortiumOrgPolicy(t *testing.T) { t.Parallel() diff --git a/configtx/orderer.go b/configtx/orderer.go index 48c4917..ef731df 100644 --- a/configtx/orderer.go +++ b/configtx/orderer.go @@ -519,7 +519,7 @@ func (o *OrdererGroup) Capabilities() ([]string, error) { } // AddCapability adds capability to the provided channel config. -// If the provided capability already exist in current configuration, this action +// If the provided capability already exists in current configuration, this action // will be a no-op. func (o *OrdererGroup) AddCapability(capability string) error { capabilities, err := o.Capabilities() @@ -551,7 +551,7 @@ func (o *OrdererGroup) RemoveCapability(capability string) error { } // SetEndpoint adds an orderer's endpoint to an existing channel config transaction. -// If the same endpoint already exist in current configuration, this will be a no-op. +// If the same endpoint already exists in current configuration, this will be a no-op. func (o *OrdererOrg) SetEndpoint(endpoint Address) error { ordererAddrProto := &cb.OrdererAddresses{} @@ -613,7 +613,7 @@ func (o *OrdererOrg) RemoveEndpoint(endpoint Address) error { } // SetPolicy sets the specified policy in the orderer group's config policy map. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (o *OrdererGroup) SetPolicy(modPolicy, policyName string, policy Policy) error { err := setPolicy(o.ordererGroup, modPolicy, policyName, policy) if err != nil { @@ -623,6 +623,22 @@ func (o *OrdererGroup) SetPolicy(modPolicy, policyName string, policy Policy) er return nil } +// SetPolicies sets the specified policy in the orderer group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (o *OrdererGroup) SetPolicies(modPolicy string, policies map[string]Policy) error { + + if _, ok := policies[BlockValidationPolicyKey]; !ok { + return errors.New("BlockValidation policy must be defined") + } + + err := setPolicies(o.ordererGroup, policies, modPolicy) + if err != nil { + return fmt.Errorf("failed to set policies: %v", err) + } + + return nil +} + // RemovePolicy removes an existing orderer policy configuration. func (o *OrdererGroup) RemovePolicy(policyName string) error { if policyName == BlockValidationPolicyKey { @@ -670,11 +686,17 @@ func (o *OrdererOrg) SetMSP(updatedMSP MSP) error { } // SetPolicy sets the specified policy in the orderer org group's config policy map. -// If the policy already exist in current configuration, its value will be overwritten. +// If the policy already exists in current configuration, its value will be overwritten. func (o *OrdererOrg) SetPolicy(modPolicy, policyName string, policy Policy) error { return setPolicy(o.orgGroup, modPolicy, policyName, policy) } +// SetPolicies sets the specified policies in the orderer org group's config policy map. +// If the policies already exist in current configuration, the values will be replaced with new policies. +func (o *OrdererOrg) SetPolicies(modPolicy string, policies map[string]Policy) error { + return setPolicies(o.orgGroup, policies, modPolicy) +} + // RemovePolicy removes an existing policy from an orderer organization. func (o *OrdererOrg) RemovePolicy(policyName string) error { policies, err := o.Policies() diff --git a/configtx/orderer_test.go b/configtx/orderer_test.go index ef829e8..f082039 100644 --- a/configtx/orderer_test.go +++ b/configtx/orderer_test.go @@ -3341,6 +3341,148 @@ func TestSetOrdererPolicyFailures(t *testing.T) { gt.Expect(err).To(MatchError("failed to set policy 'TestPolicy': unknown policy type: ")) } +func TestSetOrdererPolicies(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + baseOrdererConf, _ := baseSoloOrderer(t) + baseOrdererConf.Policies["TestPolicy_Remove"] = baseOrdererConf.Policies[ReadersPolicyKey] + + ordererGroup, err := newOrdererGroup(baseOrdererConf) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + "Orderer": ordererGroup, + }, + }, + } + + c := New(config) + + newPolices := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + BlockValidationPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + } + + err = c.Orderer().SetPolicies(AdminsPolicyKey, newPolices) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedPolicies, err := c.Orderer().Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedPolicies).To(Equal(newPolices)) + + originalPolicies := c.original.ChannelGroup.Groups[OrdererGroupKey].Policies + gt.Expect(originalPolicies).To(Equal(ordererGroup.Policies)) +} + +func TestSetOrdererPoliciesFailures(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + baseOrdererConf, _ := baseSoloOrderer(t) + + ordererGroup, err := newOrdererGroup(baseOrdererConf) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + "Orderer": ordererGroup, + }, + }, + } + + c := New(config) + + newPolices := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + BlockValidationPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + "TestPolicy": {}, + } + + err = c.Orderer().SetPolicies(AdminsPolicyKey, newPolices) + gt.Expect(err).To(MatchError("failed to set policies: unknown policy type: ")) +} + +func TestSetOrdererPoliciesWithoutBlockValidationPolicyFailures(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + baseOrdererConf, _ := baseSoloOrderer(t) + + ordererGroup, err := newOrdererGroup(baseOrdererConf) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + "Orderer": ordererGroup, + }, + }, + } + + c := New(config) + + newPolices := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + } + + err = c.Orderer().SetPolicies(AdminsPolicyKey, newPolices) + gt.Expect(err).To(MatchError("BlockValidation policy must be defined")) +} + func TestRemoveOrdererPolicy(t *testing.T) { t.Parallel() @@ -3520,6 +3662,110 @@ func TestSetOrdererOrgPolicyFailures(t *testing.T) { gt.Expect(err).To(MatchError("unknown policy type: ")) } +func TestSetOrdererOrgPolicies(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + baseOrdererConf, _ := baseSoloOrderer(t) + baseOrdererConf.Organizations[0].Policies["TestPolicy_Remove"] = baseOrdererConf.Organizations[0].Policies[ReadersPolicyKey] + + ordererGroup, err := newOrdererGroup(baseOrdererConf) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + "Orderer": ordererGroup, + }, + }, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy_Add1": { + Type: ImplicitMetaPolicyType, + Rule: "ANY Endorsement", + }, + "TestPolicy_Add2": { + Type: ImplicitMetaPolicyType, + Rule: "ANY Endorsement", + }, + } + + ordererOrg := c.Orderer().Organization("OrdererOrg") + err = ordererOrg.SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).NotTo(HaveOccurred()) + + updatedPolicies, err := ordererOrg.Policies() + gt.Expect(err).NotTo(HaveOccurred()) + gt.Expect(updatedPolicies).To(Equal(newPolicies)) + + originalPolicies := c.original.ChannelGroup.Groups[OrdererGroupKey].Groups["OrdererOrg"].Policies + gt.Expect(originalPolicies).To(Equal(ordererGroup.Groups["OrdererOrg"].Policies)) +} + +func TestSetOrdererOrgPoliciesFailures(t *testing.T) { + t.Parallel() + + gt := NewGomegaWithT(t) + + baseOrdererConf, _ := baseSoloOrderer(t) + + ordererGroup, err := newOrdererGroup(baseOrdererConf) + gt.Expect(err).NotTo(HaveOccurred()) + + config := &cb.Config{ + ChannelGroup: &cb.ConfigGroup{ + Groups: map[string]*cb.ConfigGroup{ + "Orderer": ordererGroup, + }, + }, + } + + c := New(config) + + newPolicies := map[string]Policy{ + ReadersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Readers", + }, + WritersPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "ANY Writers", + }, + AdminsPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Admins", + }, + EndorsementPolicyKey: { + Type: ImplicitMetaPolicyType, + Rule: "MAJORITY Endorsement", + }, + "TestPolicy": {}, + } + + err = c.Orderer().Organization("OrdererOrg").SetPolicies(AdminsPolicyKey, newPolicies) + gt.Expect(err).To(MatchError("unknown policy type: ")) +} + func TestRemoveOrdererOrgPolicy(t *testing.T) { t.Parallel() diff --git a/configtx/policies.go b/configtx/policies.go index 8d39992..d15f92e 100644 --- a/configtx/policies.go +++ b/configtx/policies.go @@ -202,6 +202,7 @@ func setPolicies(cg *cb.ConfigGroup, policyMap map[string]Policy, modPolicy stri return errors.New("no Writers policy defined") } + cg.Policies = make(map[string]*cb.ConfigPolicy) for policyName, policy := range policyMap { err := setPolicy(cg, modPolicy, policyName, policy) if err != nil {