Skip to content

Commit

Permalink
[FAB-17638] Support retrieving application configuration from an exis…
Browse files Browse the repository at this point in the history
…ting config

Signed-off-by: xu wu <[email protected]>
  • Loading branch information
wuxuer authored and sykesm committed Mar 30, 2020
1 parent 84e2338 commit 4d7d4ac
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 12 deletions.
51 changes: 42 additions & 9 deletions pkg/config/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ SPDX-License-Identifier: Apache-2.0
package config

import (
"errors"
"fmt"

"github.com/golang/protobuf/proto"
Expand All @@ -23,19 +24,46 @@ type Application struct {
ACLs map[string]string
}

// AddApplicationOrg adds an organization to an existing config's Application configuration.
// Will not error if organization already exists.
func AddApplicationOrg(config *cb.Config, org Organization) error {
appGroup := config.ChannelGroup.Groups[ApplicationGroupKey]
// GetApplicationConfiguration returns the existing application configuration values from a config
// transaction as an Application type. This can be used to retrieve existing values for the application
// prior to updating the application configuration.
func (c *ConfigTx) GetApplicationConfiguration() (Application, error) {
applicationGroup, ok := c.base.ChannelGroup.Groups[ApplicationGroupKey]
if !ok {
return Application{}, errors.New("config does not contain application group")
}

orgGroup, err := newOrgConfigGroup(org)
var applicationOrgs []Organization
for orgName := range applicationGroup.Groups {
orgConfig, err := c.GetApplicationOrg(orgName)
if err != nil {
return Application{}, fmt.Errorf("retrieving application org %s: %v", orgName, err)
}

applicationOrgs = append(applicationOrgs, orgConfig)
}

capabilities, err := c.GetApplicationCapabilities()
if err != nil {
return fmt.Errorf("failed to create application org %s: %v", org.Name, err)
return Application{}, fmt.Errorf("retrieving application capabilities: %v", err)
}

appGroup.Groups[org.Name] = orgGroup
policies, err := c.GetPoliciesForApplication()
if err != nil {
return Application{}, fmt.Errorf("retrieving application policies: %v", err)
}

return nil
acls, err := c.GetApplicationACLs()
if err != nil {
return Application{}, fmt.Errorf("retrieving application acls: %v", err)
}

return Application{
Organizations: applicationOrgs,
Capabilities: capabilities,
Policies: policies,
ACLs: acls,
}, nil
}

// AddAnchorPeer adds an anchor peer to an existing channel config transaction.
Expand Down Expand Up @@ -166,6 +194,11 @@ func (c *ConfigTx) RemoveACLs(acls []string) error {
return nil
}

// GetApplicationACLs returns a map of application acls from a config transaction.
func (c *ConfigTx) GetApplicationACLs() (map[string]string, error) {
return getACLs(c.base)
}

// getACLs returns a map of ACLS for given config application.
func getACLs(config *cb.Config) (map[string]string, error) {
applicationGroup, ok := config.ChannelGroup.Groups[ApplicationGroupKey]
Expand Down Expand Up @@ -217,7 +250,7 @@ func (c *ConfigTx) GetAnchorPeers(orgName string) ([]Address, error) {
return anchorPeers, nil
}

// AddApplicationOrg adds an organization to an existing config's Application configuration.
// AddApplicationOrg adds an organization to an existing Application configuration.
// Will not error if organization already exists.
func (c *ConfigTx) AddApplicationOrg(org Organization) error {
appGroup := c.updated.ChannelGroup.Groups[ApplicationGroupKey]
Expand Down
146 changes: 143 additions & 3 deletions pkg/config/application_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ import (
"fmt"
"testing"

"github.com/hyperledger/fabric/common/tools/protolator"
"github.com/hyperledger/fabric/common/tools/protolator/protoext/peerext"

"github.com/golang/protobuf/proto"
cb "github.com/hyperledger/fabric-protos-go/common"
pb "github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/common/tools/protolator"
"github.com/hyperledger/fabric/common/tools/protolator/protoext/peerext"
. "github.com/onsi/gomega"
)

Expand Down Expand Up @@ -1017,6 +1016,147 @@ func TestAddApplicationOrgFailures(t *testing.T) {
gt.Expect(err).To(MatchError("failed to create application org Org3: no policies defined"))
}

func TestGetApplicationConfiguration(t *testing.T) {
t.Parallel()
gt := NewGomegaWithT(t)

baseApplicationConf := baseApplication(t)
applicationGroup, err := newApplicationGroup(baseApplicationConf)
gt.Expect(err).NotTo(HaveOccurred())

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
ApplicationGroupKey: applicationGroup,
},
},
}

c := &ConfigTx{
base: config,
updated: config,
}
for _, org := range baseApplicationConf.Organizations {
err = c.AddApplicationOrg(org)
gt.Expect(err).NotTo(HaveOccurred())
}

applicationConfig, err := c.GetApplicationConfiguration()
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(applicationConfig.ACLs).To(Equal(baseApplicationConf.ACLs))
gt.Expect(applicationConfig.Capabilities).To(Equal(baseApplicationConf.Capabilities))
gt.Expect(applicationConfig.Policies).To(Equal(baseApplicationConf.Policies))
gt.Expect(applicationConfig.Organizations).To(ContainElements(baseApplicationConf.Organizations))
}

func TestGetApplicationConfigurationFailure(t *testing.T) {
t.Parallel()

tests := []struct {
testName string
configMod func(*ConfigTx, Application, *GomegaWithT)
expectedErr string
}{
{
testName: "When the application group does not exist",
configMod: func(ct *ConfigTx, appOrg Application, gt *GomegaWithT) {
delete(ct.base.ChannelGroup.Groups, ApplicationGroupKey)
},
expectedErr: "config does not contain application group",
},
{
testName: "Retrieving application org failed",
configMod: func(ct *ConfigTx, appOrg Application, gt *GomegaWithT) {
for _, org := range appOrg.Organizations {
if org.Name == "Org2" {
err := ct.AddApplicationOrg(org)
gt.Expect(err).NotTo(HaveOccurred())
}
}
},
expectedErr: "retrieving application org Org1: config does not contain value for MSP",
},
}

for _, tt := range tests {
tt := tt
t.Run(tt.testName, func(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)

baseApplicationConf := baseApplication(t)
applicationGroup, err := newApplicationGroup(baseApplicationConf)
gt.Expect(err).NotTo(HaveOccurred())

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
ApplicationGroupKey: applicationGroup,
},
},
}

c := &ConfigTx{
base: config,
updated: config,
}
if tt.configMod != nil {
tt.configMod(c, baseApplicationConf, gt)
}

_, err = c.GetApplicationConfiguration()
gt.Expect(err).To(MatchError(tt.expectedErr))
})
}
}

func TestGetApplicationACLs(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)

baseApplicationConf := baseApplication(t)
applicationGroup, err := newApplicationGroup(baseApplicationConf)
gt.Expect(err).NotTo(HaveOccurred())

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
ApplicationGroupKey: applicationGroup,
},
},
}

c := &ConfigTx{
base: config,
}

applicationACLs, err := c.GetApplicationACLs()
gt.Expect(err).NotTo(HaveOccurred())
gt.Expect(applicationACLs).To(Equal(baseApplicationConf.ACLs))
}

func TestGetApplicationACLsFailure(t *testing.T) {
t.Parallel()

gt := NewGomegaWithT(t)

config := &cb.Config{
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{},
},
}

c := &ConfigTx{
base: config,
}

applicationACLs, err := c.GetApplicationACLs()
gt.Expect(err).To(MatchError("application does not exist in channel config"))
gt.Expect(applicationACLs).To(BeNil())
}

func baseApplication(t *testing.T) Application {
return Application{
Policies: standardPolicies(),
Expand Down

0 comments on commit 4d7d4ac

Please sign in to comment.