Skip to content
This repository was archived by the owner on Apr 25, 2025. It is now read-only.

Commit e9fa53a

Browse files
committed
[FAB-7047] Resource Mgmt Client - Join Channel
Change-Id: Ied8c821efa9631e450ebb911945404f238d424fe Signed-off-by: Sandra Vrtikapa <sandra.vrtikapa@securekey.com>
1 parent 59a0a8e commit e9fa53a

File tree

27 files changed

+1098
-88
lines changed

27 files changed

+1098
-88
lines changed

api/apiconfig/configprovider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ type Config interface {
2020
CAClientCertFile(org string) (string, error)
2121
TimeoutOrDefault(TimeoutType) time.Duration
2222
MspID(org string) (string, error)
23+
PeerMspID(name string) (string, error)
2324
OrderersConfig() ([]OrdererConfig, error)
2425
RandomOrdererConfig() (*OrdererConfig, error)
2526
OrdererConfig(name string) (*OrdererConfig, error)
2627
PeersConfig(org string) ([]PeerConfig, error)
2728
PeerConfig(org string, name string) (*PeerConfig, error)
2829
NetworkConfig() (*NetworkConfig, error)
30+
NetworkPeers() ([]NetworkPeer, error)
2931
ChannelConfig(name string) (*ChannelConfig, error)
3032
ChannelPeers(name string) ([]ChannelPeer, error)
3133
ChannelOrderers(name string) ([]OrdererConfig, error)

api/apiconfig/mocks/mockconfig.gen.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/apiconfig/network.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ type PeerChannelConfig struct {
7676
// ChannelPeer combines channel peer info with raw peerConfig info
7777
type ChannelPeer struct {
7878
PeerChannelConfig
79+
NetworkPeer
80+
}
81+
82+
// NetworkPeer combines peer info with MSP info
83+
type NetworkPeer struct {
7984
PeerConfig
8085
MspID string
8186
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
Copyright SecureKey Technologies Inc. All Rights Reserved.
3+
4+
SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package resmgmt
8+
9+
import fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
10+
11+
// TargetFilter allows for filtering target peers
12+
type TargetFilter interface {
13+
// Accept returns true if peer should be included in the list of target peers
14+
Accept(peer fab.Peer) bool
15+
}
16+
17+
// JoinChannelOpts contains options for peers joining channel
18+
type JoinChannelOpts struct {
19+
Targets []fab.Peer // target peers
20+
TargetFilter TargetFilter // peer filter
21+
}
22+
23+
// ResourceMgmtClient is responsible for managing resources: peers joining channels, and installing and instantiating chaincodes(TODO).
24+
type ResourceMgmtClient interface {
25+
26+
// JoinChannel allows for peers to join existing channel
27+
JoinChannel(channelID string) error
28+
29+
//JoinChannelWithOpts allows for customizing set of peers about to join the channel (specific peers/filtered peers)
30+
JoinChannelWithOpts(channelID string, opts JoinChannelOpts) error
31+
}

def/fabapi/context/defprovider/session.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ import (
1010
"github.com/hyperledger/fabric-sdk-go/api/apiconfig"
1111
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
1212
"github.com/hyperledger/fabric-sdk-go/api/apitxn"
13+
1314
chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient"
15+
resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient"
1416
"github.com/hyperledger/fabric-sdk-go/def/fabapi/context"
1517

1618
"github.com/hyperledger/fabric-sdk-go/pkg/errors"
@@ -19,6 +21,7 @@ import (
1921
"github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/orderer"
2022
chImpl "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/chclient"
2123
chmgmtImpl "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/chmgmtclient"
24+
resmgmtImpl "github.com/hyperledger/fabric-sdk-go/pkg/fabric-txn/resmgmtclient"
2225
)
2326

2427
// SessionClientFactory represents the default implementation of a session client.
@@ -52,6 +55,23 @@ func (f *SessionClientFactory) NewChannelMgmtClient(sdk context.SDK, session con
5255
return chmgmtImpl.NewChannelMgmtClient(client, config)
5356
}
5457

58+
// NewResourceMgmtClient returns a client that manager resources
59+
func (f *SessionClientFactory) NewResourceMgmtClient(sdk context.SDK, session context.Session, config apiconfig.Config, filter resmgmt.TargetFilter) (resmgmt.ResourceMgmtClient, error) {
60+
61+
// For now settings are the same as for system client
62+
client, err := f.NewSystemClient(sdk, session, config)
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
discovery, err := sdk.DiscoveryProvider().NewDiscoveryService("")
68+
if err != nil {
69+
return nil, errors.WithMessage(err, "create discovery service failed")
70+
}
71+
72+
return resmgmtImpl.NewResourceMgmtClient(client, discovery, filter, config)
73+
}
74+
5575
// NewChannelClient returns a client that can execute transactions on specified channel
5676
func (f *SessionClientFactory) NewChannelClient(sdk context.SDK, session context.Session, config apiconfig.Config, channelID string) (apitxn.ChannelClient, error) {
5777

def/fabapi/context/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient"
1414
txn "github.com/hyperledger/fabric-sdk-go/api/apitxn"
1515
chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient"
16+
resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient"
1617
"github.com/hyperledger/fabric-sdk-go/def/fabapi/opt"
1718
)
1819

@@ -37,5 +38,6 @@ type OrgClientFactory interface {
3738
type SessionClientFactory interface {
3839
NewSystemClient(context SDK, session Session, config apiconfig.Config) (fab.FabricClient, error)
3940
NewChannelMgmtClient(context SDK, session Session, config apiconfig.Config) (chmgmt.ChannelMgmtClient, error)
41+
NewResourceMgmtClient(context SDK, session Session, config apiconfig.Config, filter resmgmt.TargetFilter) (resmgmt.ResourceMgmtClient, error)
4042
NewChannelClient(context SDK, session Session, config apiconfig.Config, channelID string) (txn.ChannelClient, error)
4143
}

def/fabapi/fabapi.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/hyperledger/fabric-sdk-go/pkg/logging/deflogger"
2222

2323
chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient"
24+
resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient"
2425
)
2526

2627
// Options encapsulates configuration for the SDK
@@ -66,6 +67,13 @@ type ChannelMgmtClientOpts struct {
6667
ConfigProvider apiconfig.Config
6768
}
6869

70+
// ResourceMgmtClientOpts provides options for creating resource management client
71+
type ResourceMgmtClientOpts struct {
72+
OrgName string
73+
TargetFilter resmgmt.TargetFilter
74+
ConfigProvider apiconfig.Config
75+
}
76+
6977
// ProviderInit interface allows for initializing providers
7078
type ProviderInit interface {
7179
Initialize(sdk *FabricSDK) error
@@ -246,6 +254,49 @@ func (sdk *FabricSDK) NewChannelMgmtClientWithOpts(userName string, opt *Channel
246254
return client, nil
247255
}
248256

257+
// NewResourceMgmtClient returns a new client for managing system resources
258+
func (sdk *FabricSDK) NewResourceMgmtClient(userName string) (resmgmt.ResourceMgmtClient, error) {
259+
260+
// Read default org name from configuration
261+
client, err := sdk.configProvider.Client()
262+
if err != nil {
263+
return nil, errors.WithMessage(err, "unable to retrieve client from network config")
264+
}
265+
266+
if client.Organization == "" {
267+
return nil, errors.New("must provide default organisation name in configuration")
268+
}
269+
270+
opt := &ResourceMgmtClientOpts{OrgName: client.Organization, ConfigProvider: sdk.configProvider}
271+
272+
return sdk.NewResourceMgmtClientWithOpts(userName, opt)
273+
}
274+
275+
// NewResourceMgmtClientWithOpts returns a new resource management client (user has to be pre-enrolled)
276+
func (sdk *FabricSDK) NewResourceMgmtClientWithOpts(userName string, opt *ResourceMgmtClientOpts) (resmgmt.ResourceMgmtClient, error) {
277+
278+
if opt == nil || opt.OrgName == "" {
279+
return nil, errors.New("organization name must be provided")
280+
}
281+
282+
session, err := sdk.NewPreEnrolledUserSession(opt.OrgName, userName)
283+
if err != nil {
284+
return nil, errors.WithMessage(err, "failed to get pre-enrolled user session")
285+
}
286+
287+
configProvider := sdk.ConfigProvider()
288+
if opt.ConfigProvider != nil {
289+
configProvider = opt.ConfigProvider
290+
}
291+
292+
client, err := sdk.SessionFactory.NewResourceMgmtClient(sdk, session, configProvider, opt.TargetFilter)
293+
if err != nil {
294+
return nil, errors.WithMessage(err, "failed to created new resource management client")
295+
}
296+
297+
return client, nil
298+
}
299+
249300
// NewChannelClient returns a new client for a channel
250301
func (sdk *FabricSDK) NewChannelClient(channelID string, userName string) (apitxn.ChannelClient, error) {
251302

def/fabapi/fabapi_test.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ func TestNewDefaultSDK(t *testing.T) {
5252
t.Fatalf("Failed to create new channel client: %s", err)
5353
}
5454

55+
}
56+
57+
func TestNewChannelMgmtClient(t *testing.T) {
58+
59+
setup := Options{
60+
ConfigFile: "../../test/fixtures/config/config_test.yaml",
61+
StateStoreOpts: opt.StateStoreOpts{Path: "/tmp/state"},
62+
}
63+
64+
sdk, err := NewSDK(setup)
65+
if err != nil {
66+
t.Fatalf("Error initializing SDK: %s", err)
67+
}
68+
5569
// Test configuration failure for channel management client (invalid user/default organisation)
5670
_, err = sdk.NewChannelMgmtClient("Invalid")
5771
if err == nil {
@@ -78,6 +92,43 @@ func TestNewDefaultSDK(t *testing.T) {
7892

7993
}
8094

95+
func TestNewResourceMgmtClient(t *testing.T) {
96+
97+
setup := Options{
98+
ConfigFile: "../../test/fixtures/config/config_test.yaml",
99+
StateStoreOpts: opt.StateStoreOpts{Path: "/tmp/state"},
100+
}
101+
102+
sdk, err := NewSDK(setup)
103+
if err != nil {
104+
t.Fatalf("Error initializing SDK: %s", err)
105+
}
106+
107+
// Test configuration failure for resource management client (invalid user/default organisation)
108+
_, err = sdk.NewResourceMgmtClient("Invalid")
109+
if err == nil {
110+
t.Fatalf("Should have failed to create resource management client due to invalid user")
111+
}
112+
113+
// Test valid configuration for resource management client
114+
_, err = sdk.NewResourceMgmtClient("Admin")
115+
if err != nil {
116+
t.Fatalf("Failed to create new resource management client: %s", err)
117+
}
118+
119+
// Test configuration failure for new resource management client with options (invalid org)
120+
_, err = sdk.NewResourceMgmtClientWithOpts("Admin", &ResourceMgmtClientOpts{OrgName: "Invalid"})
121+
if err == nil {
122+
t.Fatalf("Should have failed to create resource management client due to invalid organization")
123+
}
124+
125+
// Test new resource management client with options (Org2 configuration)
126+
_, err = sdk.NewResourceMgmtClientWithOpts("Admin", &ResourceMgmtClientOpts{OrgName: "Org2"})
127+
if err != nil {
128+
t.Fatalf("Failed to create new resource management client with opts: %s", err)
129+
}
130+
}
131+
81132
func TestNewDefaultTwoValidSDK(t *testing.T) {
82133
setup := Options{
83134
ConfigFile: "../../test/fixtures/config/config_test.yaml",

def/fabapi/pkgfactory.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ func NewPeer(url string, certificate string, serverHostOverride string, config c
176176
}
177177

178178
// NewPeerFromConfig returns a new default implementation of Peer based configuration
179-
func NewPeerFromConfig(peerCfg *config.PeerConfig, config config.Config) (fab.Peer, error) {
179+
func NewPeerFromConfig(peerCfg *config.NetworkPeer, config config.Config) (fab.Peer, error) {
180180
return peerImpl.NewPeerFromConfig(peerCfg, config)
181181
}
182182

pkg/config/config.go

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -487,20 +487,14 @@ func (c *Config) ChannelPeers(name string) ([]apiconfig.ChannelPeer, error) {
487487
p.TLSCACerts.Path = strings.Replace(p.TLSCACerts.Path, "$GOPATH", os.Getenv("GOPATH"), -1)
488488
}
489489

490-
var mspID string
491-
492-
// Find organisation/msp that peer belongs to
493-
for _, org := range netConfig.Organizations {
494-
for i := 0; i < len(org.Peers); i++ {
495-
if strings.EqualFold(org.Peers[i], peerName) {
496-
// peer belongs to this org add org msp
497-
mspID = org.MspID
498-
break
499-
}
500-
}
490+
mspID, err := c.PeerMspID(peerName)
491+
if err != nil {
492+
return nil, errors.Errorf("failed to retrieve msp id for peer %s", peerName)
501493
}
502494

503-
peer := apiconfig.ChannelPeer{PeerChannelConfig: chPeerConfig, PeerConfig: p, MspID: mspID}
495+
networkPeer := apiconfig.NetworkPeer{PeerConfig: p, MspID: mspID}
496+
497+
peer := apiconfig.ChannelPeer{PeerChannelConfig: chPeerConfig, NetworkPeer: networkPeer}
504498

505499
peers = append(peers, peer)
506500
}
@@ -509,6 +503,61 @@ func (c *Config) ChannelPeers(name string) ([]apiconfig.ChannelPeer, error) {
509503

510504
}
511505

506+
// NetworkPeers returns the network peers configuration
507+
func (c *Config) NetworkPeers() ([]apiconfig.NetworkPeer, error) {
508+
netConfig, err := c.NetworkConfig()
509+
if err != nil {
510+
return nil, err
511+
}
512+
513+
netPeers := []apiconfig.NetworkPeer{}
514+
515+
for name, p := range netConfig.Peers {
516+
517+
if err = verifyPeerConfig(p, name, urlutil.IsTLSEnabled(p.URL)); err != nil {
518+
return nil, err
519+
}
520+
521+
if p.TLSCACerts.Path != "" {
522+
p.TLSCACerts.Path = strings.Replace(p.TLSCACerts.Path, "$GOPATH", os.Getenv("GOPATH"), -1)
523+
}
524+
525+
mspID, err := c.PeerMspID(name)
526+
if err != nil {
527+
return nil, errors.Errorf("failed to retrieve msp id for peer %s", name)
528+
}
529+
530+
netPeer := apiconfig.NetworkPeer{PeerConfig: p, MspID: mspID}
531+
netPeers = append(netPeers, netPeer)
532+
}
533+
534+
return netPeers, nil
535+
}
536+
537+
// PeerMspID returns msp that peer belongs to
538+
func (c *Config) PeerMspID(name string) (string, error) {
539+
netConfig, err := c.NetworkConfig()
540+
if err != nil {
541+
return "", err
542+
}
543+
544+
var mspID string
545+
546+
// Find organisation/msp that peer belongs to
547+
for _, org := range netConfig.Organizations {
548+
for i := 0; i < len(org.Peers); i++ {
549+
if strings.EqualFold(org.Peers[i], name) {
550+
// peer belongs to this org add org msp
551+
mspID = org.MspID
552+
break
553+
}
554+
}
555+
}
556+
557+
return mspID, nil
558+
559+
}
560+
512561
func verifyPeerConfig(p apiconfig.PeerConfig, peerName string, tlsEnabled bool) error {
513562
if p.URL == "" {
514563
return errors.Errorf("URL does not exist or empty for peer %s", peerName)

0 commit comments

Comments
 (0)