forked from hyperledger/fabric-sdk-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbase_test_setup.go
322 lines (276 loc) · 11.9 KB
/
base_test_setup.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/*
Copyright SecureKey Technologies Inc. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package integration
import (
"os"
"path"
"time"
mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
fabAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context"
"github.com/hyperledger/fabric-sdk-go/pkg/fab"
packager "github.com/hyperledger/fabric-sdk-go/pkg/fab/ccpackager/gopackager"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/comm"
"github.com/hyperledger/fabric-sdk-go/pkg/fab/resource"
"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
"github.com/hyperledger/fabric-sdk-go/pkg/util/test"
"github.com/hyperledger/fabric-sdk-go/test/metadata"
"github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/common/cauthdsl"
cb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common"
"github.com/pkg/errors"
)
// BaseSetupImpl implementation of BaseTestSetup
type BaseSetupImpl struct {
Identity msp.Identity
Targets []string
ConfigFile string
OrgID string
ChannelID string
ChannelConfigFile string
}
// Initial B values for ExampleCC
const (
ExampleCCInitB = "200"
ExampleCCUpgradeB = "400"
AdminUser = "Admin"
OrdererOrgName = "ordererorg"
)
// ExampleCC query and transaction arguments
var queryArgs = [][]byte{[]byte("query"), []byte("b")}
var txArgs = [][]byte{[]byte("move"), []byte("a"), []byte("b"), []byte("1")}
// ExampleCC init and upgrade args
var initArgs = [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte(ExampleCCInitB)}
var upgradeArgs = [][]byte{[]byte("init"), []byte("a"), []byte("100"), []byte("b"), []byte(ExampleCCUpgradeB)}
// ExampleCCQueryArgs returns example cc query args
func ExampleCCQueryArgs() [][]byte {
return queryArgs
}
// ExampleCCTxArgs returns example cc move funds args
func ExampleCCTxArgs() [][]byte {
return txArgs
}
//ExampleCCInitArgs returns example cc initialization args
func ExampleCCInitArgs() [][]byte {
return initArgs
}
//ExampleCCUpgradeArgs returns example cc upgrade args
func ExampleCCUpgradeArgs() [][]byte {
return upgradeArgs
}
// IsJoinedChannel returns true if the given peer has joined the given channel
func IsJoinedChannel(channelID string, resMgmtClient *resmgmt.Client, peer fabAPI.Peer) (bool, error) {
resp, err := resMgmtClient.QueryChannels(resmgmt.WithTargets(peer))
if err != nil {
return false, err
}
for _, chInfo := range resp.Channels {
if chInfo.ChannelId == channelID {
return true, nil
}
}
return false, nil
}
// Initialize reads configuration from file and sets up client, channel and event hub
func (setup *BaseSetupImpl) Initialize(sdk *fabsdk.FabricSDK) error {
mspClient, err := mspclient.New(sdk.Context(), mspclient.WithOrg(setup.OrgID))
adminIdentity, err := mspClient.GetSigningIdentity(AdminUser)
if err != nil {
return errors.WithMessage(err, "failed to get client context")
}
setup.Identity = adminIdentity
var cfgBackends []core.ConfigBackend
configBackend, err := sdk.Config()
if err != nil {
//For some tests SDK may not have backend set, try with config file if backend is missing
cfgBackends, err = ConfigBackend()
if err != nil {
return errors.Wrapf(err, "failed to get config backend from config: %s", err)
}
} else {
cfgBackends = append(cfgBackends, configBackend)
}
targets, err := OrgTargetPeers([]string{setup.OrgID}, cfgBackends...)
if err != nil {
return errors.Wrapf(err, "loading target peers from config failed")
}
setup.Targets = targets
r, err := os.Open(setup.ChannelConfigFile)
if err != nil {
return errors.Wrapf(err, "opening channel config file failed")
}
defer func() {
if err = r.Close(); err != nil {
test.Logf("close error %v", err)
}
}()
// Create channel for tests
req := resmgmt.SaveChannelRequest{ChannelID: setup.ChannelID, ChannelConfig: r, SigningIdentities: []msp.SigningIdentity{adminIdentity}}
if err = InitializeChannel(sdk, setup.OrgID, req, targets); err != nil {
return errors.WithMessage(err, "failed to initialize channel")
}
return nil
}
// GetDeployPath ..
func GetDeployPath() string {
pwd, _ := os.Getwd()
return path.Join(pwd, "../../fixtures/testdata")
}
// InstallAndInstantiateExampleCC install and instantiate using resource management client
func InstallAndInstantiateExampleCC(sdk *fabsdk.FabricSDK, user fabsdk.ContextOption, orgName string, chainCodeID string) (resmgmt.InstantiateCCResponse, error) {
return InstallAndInstantiateCC(sdk, user, orgName, chainCodeID, "github.com/example_cc", "v0", GetDeployPath(), initArgs)
}
// InstallAndInstantiateCC install and instantiate using resource management client
func InstallAndInstantiateCC(sdk *fabsdk.FabricSDK, user fabsdk.ContextOption, orgName string, ccName, ccPath, ccVersion, goPath string, ccArgs [][]byte) (resmgmt.InstantiateCCResponse, error) {
ccPkg, err := packager.NewCCPackage(ccPath, goPath)
if err != nil {
return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "creating chaincode package failed")
}
configBackend, err := sdk.Config()
if err != nil {
return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "failed to get config backend")
}
endpointConfig, err := fab.ConfigFromBackend(configBackend)
if err != nil {
return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "failed to get endpoint config")
}
mspID, ok := comm.MSPID(endpointConfig, orgName)
if !ok {
return resmgmt.InstantiateCCResponse{}, errors.New("looking up MSP ID failed")
}
//prepare context
clientContext := sdk.Context(user, fabsdk.WithOrg(orgName))
// Resource management client is responsible for managing resources (joining channels, install/instantiate/upgrade chaincodes)
resMgmtClient, err := resmgmt.New(clientContext)
if err != nil {
return resmgmt.InstantiateCCResponse{}, errors.WithMessage(err, "Failed to create new resource management client")
}
_, err = resMgmtClient.InstallCC(resmgmt.InstallCCRequest{Name: ccName, Path: ccPath, Version: ccVersion, Package: ccPkg}, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
if err != nil {
return resmgmt.InstantiateCCResponse{}, err
}
ccPolicy := cauthdsl.SignedByMspMember(mspID)
return resMgmtClient.InstantiateCC("mychannel", resmgmt.InstantiateCCRequest{Name: ccName, Path: ccPath, Version: ccVersion, Args: ccArgs, Policy: ccPolicy}, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
}
// OrgContext provides SDK client context for a given org
type OrgContext struct {
OrgID string
CtxProvider contextAPI.ClientProvider
SigningIdentity msp.SigningIdentity
ResMgmt *resmgmt.Client
Peers []fabAPI.Peer
AnchorPeerConfigFile string
}
// CreateChannelAndUpdateAnchorPeers creates the channel and updates all of the anchor peers for all orgs
func CreateChannelAndUpdateAnchorPeers(sdk *fabsdk.FabricSDK, channelID string, channelConfigFile string, orgsContext []*OrgContext) error {
ordererCtx := sdk.Context(fabsdk.WithUser(AdminUser), fabsdk.WithOrg(OrdererOrgName))
// Channel management client is responsible for managing channels (create/update channel)
chMgmtClient, err := resmgmt.New(ordererCtx)
if err != nil {
return errors.New("failed to get a new resmgmt client for orderer")
}
var signingIdentities []msp.SigningIdentity
for _, orgCtx := range orgsContext {
signingIdentities = append(signingIdentities, orgCtx.SigningIdentity)
}
req := resmgmt.SaveChannelRequest{
ChannelID: channelID,
ChannelConfigPath: path.Join("../../../", metadata.ChannelConfigPath, channelConfigFile),
SigningIdentities: signingIdentities,
}
_, err = chMgmtClient.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com"))
if err != nil {
return err
}
for _, orgCtx := range orgsContext {
req := resmgmt.SaveChannelRequest{
ChannelID: channelID,
ChannelConfigPath: path.Join("../../../", metadata.ChannelConfigPath, orgCtx.AnchorPeerConfigFile),
SigningIdentities: []msp.SigningIdentity{orgCtx.SigningIdentity},
}
if _, err := orgCtx.ResMgmt.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return err
}
}
return nil
}
// JoinPeersToChannel joins all peers in all of the given orgs to the given channel
func JoinPeersToChannel(channelID string, orgsContext []*OrgContext) error {
for _, orgCtx := range orgsContext {
err := orgCtx.ResMgmt.JoinChannel(
channelID,
resmgmt.WithRetry(retry.DefaultResMgmtOpts),
resmgmt.WithOrdererEndpoint("orderer.example.com"),
resmgmt.WithTargets(orgCtx.Peers...),
)
if err != nil {
return errors.Wrapf(err, "failed to join peers in org [%s] to channel [%s]", orgCtx.OrgID, channelID)
}
}
return nil
}
// InstallAndInstantiateChaincode installs the given chaincode to all peers in the given orgs and instantiates it on the given channel
func InstallAndInstantiateChaincode(channelID string, ccPkg *resource.CCPackage, ccID, ccVersion, ccPolicy string, orgs []*OrgContext, collConfigs ...*cb.CollectionConfig) error {
for _, orgCtx := range orgs {
if err := InstallChaincode(orgCtx.ResMgmt, orgCtx.CtxProvider, ccPkg, ccID, ccVersion, orgCtx.Peers); err != nil {
return errors.Wrapf(err, "failed to install chaincode to peers in org [%s]", orgCtx.OrgID)
}
}
_, err := InstantiateChaincode(orgs[0].ResMgmt, channelID, ccID, ccVersion, ccPolicy, collConfigs...)
return err
}
// InstallChaincode installs the given chaincode to the given peers
func InstallChaincode(resMgmt *resmgmt.Client, ctxProvider contextAPI.ClientProvider, ccPkg *resource.CCPackage, ccName, ccVersion string, localPeers []fabAPI.Peer) error {
installCCReq := resmgmt.InstallCCRequest{Name: ccName, Path: "github.com/example_cc", Version: ccVersion, Package: ccPkg}
_, err := resMgmt.InstallCC(installCCReq, resmgmt.WithRetry(retry.DefaultResMgmtOpts))
return err
}
// InstantiateChaincode instantiates the given chaincode to the given channel
func InstantiateChaincode(resMgmt *resmgmt.Client, channelID, ccName, ccVersion string, ccPolicyStr string, collConfigs ...*cb.CollectionConfig) (resmgmt.InstantiateCCResponse, error) {
ccPolicy, err := cauthdsl.FromString(ccPolicyStr)
if err != nil {
return resmgmt.InstantiateCCResponse{}, errors.Wrapf(err, "error creating CC policy [%s]", ccPolicyStr)
}
return resMgmt.InstantiateCC(
channelID,
resmgmt.InstantiateCCRequest{
Name: ccName,
Path: "github.com/example_cc",
Version: ccVersion,
Args: ExampleCCInitArgs(),
Policy: ccPolicy,
CollConfig: collConfigs,
},
resmgmt.WithRetry(retry.DefaultResMgmtOpts),
)
}
// DiscoverLocalPeers queries the local peers for the given MSP context and returns all of the peers. If
// the number of peers does not match the expected number then an error is returned.
func DiscoverLocalPeers(ctxProvider contextAPI.ClientProvider, expectedPeers int) ([]fabAPI.Peer, error) {
ctx, err := contextImpl.NewLocal(ctxProvider)
if err != nil {
return nil, errors.Wrap(err, "error creating local context")
}
var peers []fabAPI.Peer
for i := 0; i < 10; i++ {
peers, err = ctx.LocalDiscoveryService().GetPeers()
if err != nil {
return nil, errors.Wrapf(err, "error getting peers for MSP [%s]", ctx.Identifier().MSPID)
}
if len(peers) >= expectedPeers {
break
}
// wait some time to allow the gossip to propagate the peers discovery
time.Sleep(3 * time.Second)
}
if expectedPeers != len(peers) {
return nil, errors.Errorf("Expecting %d peers but got %d", expectedPeers, len(peers))
}
return peers, nil
}