From dd63d013f43c82bf226af52e1688ca5e38197f2e Mon Sep 17 00:00:00 2001 From: Sandra Vrtikapa Date: Fri, 24 Nov 2017 11:33:16 -0500 Subject: [PATCH] [FAB-7101] Resource Management Client - Install CC Change-Id: Ic1944f769b9888541c20f3254f385236dd232300 Signed-off-by: Sandra Vrtikapa --- Makefile | 2 +- api/apifabclient/fabricclient.go | 22 +- api/apitxn/resmgmtclient/resmgmt.go | 28 ++ def/fabapi/context/defprovider/session.go | 2 +- .../gopackager/packager.go} | 37 +- .../gopackager/packager_test.go} | 22 +- pkg/fabric-client/client.go | 31 +- pkg/fabric-client/mocks/mockclient.go | 27 +- pkg/fabric-client/packager/packager.go | 35 -- pkg/fabric-client/packager/packager_test.go | 83 ----- pkg/fabric-txn/admin/transactionconfig.go | 33 -- .../staticdiscovery/staticdiscovery.go | 4 +- pkg/fabric-txn/mocks/mockdiscovery.go | 2 +- pkg/fabric-txn/resmgmtclient/resmgmt.go | 124 ++++++- pkg/fabric-txn/resmgmtclient/resmgmt_test.go | 321 +++++++++++++++++- test/integration/base_test_setup.go | 38 ++- test/integration/events_test.go | 8 +- test/integration/install_chaincode_test.go | 34 +- test/integration/orgs/test_setup.go | 23 +- 19 files changed, 627 insertions(+), 249 deletions(-) rename pkg/fabric-client/{packager/golang.go => ccpackager/gopackager/packager.go} (84%) rename pkg/fabric-client/{packager/golang_test.go => ccpackager/gopackager/packager_test.go} (78%) delete mode 100644 pkg/fabric-client/packager/packager.go delete mode 100644 pkg/fabric-client/packager/packager_test.go diff --git a/Makefile b/Makefile index e2184d3b68..12555d988a 100644 --- a/Makefile +++ b/Makefile @@ -155,6 +155,6 @@ populate-clean: clean: -$(GO_CMD) clean - -rm -Rf /tmp/enroll_user /tmp/msp /tmp/keyvaluestore /tmp/hfc-kvs + -rm -Rf /tmp/enroll_user /tmp/msp /tmp/keyvaluestore /tmp/hfc-kvs /tmp/state -rm -f integration-report.xml report.xml -FIXTURE_PROJECT_NAME=$(FIXTURE_PROJECT_NAME) DOCKER_REMOVE_FORCE=$(FIXTURE_DOCKER_REMOVE_FORCE) test/scripts/clean_integration.sh \ No newline at end of file diff --git a/api/apifabclient/fabricclient.go b/api/apifabclient/fabricclient.go index 6e2f20ce6c..336312b501 100644 --- a/api/apifabclient/fabricclient.go +++ b/api/apifabclient/fabricclient.go @@ -43,7 +43,7 @@ type FabricClient interface { CryptoSuite() apicryptosuite.CryptoSuite SaveUserToStateStore(user User, skipPersistence bool) error LoadUserFromStateStore(name string) (User, error) - InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, chaincodePackage []byte, targets []txn.ProposalProcessor) ([]*txn.TransactionProposalResponse, string, error) + InstallChaincode(request InstallChaincodeRequest) ([]*txn.TransactionProposalResponse, string, error) QueryChannels(peer Peer) (*pb.ChannelQueryResponse, error) QueryInstalledChaincodes(peer Peer) (*pb.ChaincodeQueryResponse, error) UserContext() User @@ -75,3 +75,23 @@ type CreateChannelRequest struct { // This request struct also has the field for consistency but perhaps it should be removed. TxnID txn.TransactionID } + +// InstallChaincodeRequest requests chaincode installation on the network +type InstallChaincodeRequest struct { + // required - name of the chaincode + Name string + // required - path to the location of chaincode sources (path from GOPATH/src folder) + Path string + // chaincodeVersion: required - version of the chaincode + Version string + // required - package (chaincode package type and bytes) + Package *CCPackage + // required - proposal processor list + Targets []txn.ProposalProcessor +} + +// CCPackage contains package type and bytes required to create CDS +type CCPackage struct { + Type pb.ChaincodeSpec_Type + Code []byte +} diff --git a/api/apitxn/resmgmtclient/resmgmt.go b/api/apitxn/resmgmtclient/resmgmt.go index 411022699f..69ac1c51e6 100644 --- a/api/apitxn/resmgmtclient/resmgmt.go +++ b/api/apitxn/resmgmtclient/resmgmt.go @@ -20,9 +20,37 @@ type JoinChannelOpts struct { TargetFilter TargetFilter // peer filter } +// InstallCCRequest contains install chaincode request parameters +type InstallCCRequest struct { + Name string + Path string + Version string + Package *fab.CCPackage +} + +// InstallCCResponse contains install chaincode response status +type InstallCCResponse struct { + Target string + Status int32 + Info string + Err error +} + +// InstallCCOpts contains options for installing chaincode +type InstallCCOpts struct { + Targets []fab.Peer // target peers + TargetFilter TargetFilter // target filter +} + // ResourceMgmtClient is responsible for managing resources: peers joining channels, and installing and instantiating chaincodes(TODO). type ResourceMgmtClient interface { + // InstallCC - install chaincode + InstallCC(req InstallCCRequest) ([]InstallCCResponse, error) + + // InstallCCWithOpts installs chaincode with custom options (specific peers, filtered peers) + InstallCCWithOpts(req InstallCCRequest, opts InstallCCOpts) ([]InstallCCResponse, error) + // JoinChannel allows for peers to join existing channel JoinChannel(channelID string) error diff --git a/def/fabapi/context/defprovider/session.go b/def/fabapi/context/defprovider/session.go index 253a29060b..8208e965a2 100644 --- a/def/fabapi/context/defprovider/session.go +++ b/def/fabapi/context/defprovider/session.go @@ -55,7 +55,7 @@ func (f *SessionClientFactory) NewChannelMgmtClient(sdk context.SDK, session con return chmgmtImpl.NewChannelMgmtClient(client, config) } -// NewResourceMgmtClient returns a client that manager resources +// NewResourceMgmtClient returns a client that manages resources func (f *SessionClientFactory) NewResourceMgmtClient(sdk context.SDK, session context.Session, config apiconfig.Config, filter resmgmt.TargetFilter) (resmgmt.ResourceMgmtClient, error) { // For now settings are the same as for system client diff --git a/pkg/fabric-client/packager/golang.go b/pkg/fabric-client/ccpackager/gopackager/packager.go similarity index 84% rename from pkg/fabric-client/packager/golang.go rename to pkg/fabric-client/ccpackager/gopackager/packager.go index 0bbccc7c72..fb6082f1b8 100644 --- a/pkg/fabric-client/packager/golang.go +++ b/pkg/fabric-client/ccpackager/gopackager/packager.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package packager +package gopackager import ( "archive/tar" @@ -18,6 +18,9 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/errors" "github.com/hyperledger/fabric-sdk-go/pkg/logging" + + fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient" + pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" ) // Descriptor ... @@ -33,18 +36,25 @@ var keep = []string{".go", ".c", ".h"} var logger = logging.NewLogger("fabric_sdk_go") -// PackageGoLangCC ... -func PackageGoLangCC(chaincodePath string) ([]byte, error) { +// NewCCPackage creates new go lang chaincode package +func NewCCPackage(chaincodePath string, goPath string) (*fab.CCPackage, error) { + + if chaincodePath == "" { + return nil, errors.New("chaincode path must be provided") + } - // Determine the user's $GOPATH - goPath := os.Getenv("GOPATH") - if goPath == "" { - return nil, errors.New("GOPATH not defined") + var projDir string + gp := goPath + if gp == "" { + // TODO: for now use env variable + gp = os.Getenv("GOPATH") + if gp == "" { + return nil, errors.New("GOPATH not defined") + } + logger.Debugf("Default GOPATH=%s", gp) } - logger.Debugf("GOPATH environment variable=%s", goPath) - // Compose the path to the chaincode project directory - projDir := path.Join(goPath, "src", chaincodePath) + projDir = path.Join(gp, "src", chaincodePath) logger.Debugf("projDir variable=%s", projDir) @@ -52,7 +62,7 @@ func PackageGoLangCC(chaincodePath string) ([]byte, error) { // and then pack them into an archive. While the two phases aren't // strictly necessary yet, they pave the way for the future where we // will need to assemble sources from multiple packages - descriptors, err := findSource(goPath, projDir) + descriptors, err := findSource(gp, projDir) if err != nil { return nil, err } @@ -60,7 +70,10 @@ func PackageGoLangCC(chaincodePath string) ([]byte, error) { if err != nil { return nil, err } - return tarBytes, nil + + ccPkg := &fab.CCPackage{Type: pb.ChaincodeSpec_GOLANG, Code: tarBytes} + + return ccPkg, nil } // ------------------------------------------------------------------------- diff --git a/pkg/fabric-client/packager/golang_test.go b/pkg/fabric-client/ccpackager/gopackager/packager_test.go similarity index 78% rename from pkg/fabric-client/packager/golang_test.go rename to pkg/fabric-client/ccpackager/gopackager/packager_test.go index d8e3b7bcc8..f9648621ef 100644 --- a/pkg/fabric-client/packager/golang_test.go +++ b/pkg/fabric-client/ccpackager/gopackager/packager_test.go @@ -4,7 +4,7 @@ Copyright SecureKey Technologies Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package packager +package gopackager import ( "archive/tar" @@ -17,19 +17,18 @@ import ( ) // Test golang ChainCode packaging -func TestPackageGoLangCC(t *testing.T) { +func TestNewCCPackage(t *testing.T) { pwd, err := os.Getwd() if err != nil { t.Fatalf("error from os.Getwd %v", err) } - os.Setenv("GOPATH", path.Join(pwd, "../../../test/fixtures/testdata")) - ccPackage, err := PackageGoLangCC("github.com") + ccPackage, err := NewCCPackage("github.com", path.Join(pwd, "../../../../test/fixtures/testdata")) if err != nil { - t.Fatalf("error from PackageGoLangCC %v", err) + t.Fatalf("error from Create %v", err) } - r := bytes.NewReader(ccPackage) + r := bytes.NewReader(ccPackage.Code) gzf, err := gzip.NewReader(r) if err != nil { t.Fatalf("error from gzip.NewReader %v", err) @@ -61,9 +60,9 @@ func TestPackageGoLangCC(t *testing.T) { } // Test Package Go ChainCode -func TestEmptyPackageGoLangCC(t *testing.T) { - os.Setenv("GOPATH", "") - _, err := PackageGoLangCC("") +func TestEmptyCreate(t *testing.T) { + + _, err := NewCCPackage("", "") if err == nil { t.Fatalf("Package Empty GoLang CC must return an error.") } @@ -75,11 +74,10 @@ func TestBadPackagePathGoLangCC(t *testing.T) { if err != nil { t.Fatalf("error from os.Getwd %v", err) } - os.Setenv("GOPATH", path.Join(pwd, "../../../test/fixturesABC")) - _, err = PackageGoLangCC("github.com") + _, err = NewCCPackage("github.com", path.Join(pwd, "../../../../test/fixturesABC")) if err == nil { - t.Fatalf("error expected from PackageGoLangCC %v", err) + t.Fatalf("error expected from Create %v", err) } } diff --git a/pkg/fabric-client/client.go b/pkg/fabric-client/client.go index 96b05ae5c0..54e99f518a 100644 --- a/pkg/fabric-client/client.go +++ b/pkg/fabric-client/client.go @@ -28,7 +28,6 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/identity" fc "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal" "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/internal/txnproc" - packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/packager" "github.com/hyperledger/fabric-sdk-go/pkg/logging" ) @@ -480,31 +479,25 @@ func (c *Client) QueryInstalledChaincodes(peer fab.Peer) (*pb.ChaincodeQueryResp } // InstallChaincode sends an install proposal to one or more endorsing peers. -func (c *Client) InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, - chaincodePackage []byte, targets []apitxn.ProposalProcessor) ([]*apitxn.TransactionProposalResponse, string, error) { +func (c *Client) InstallChaincode(req fab.InstallChaincodeRequest) ([]*apitxn.TransactionProposalResponse, string, error) { - if chaincodeName == "" { - return nil, "", errors.New("chaincodeName required") + if req.Name == "" { + return nil, "", errors.New("chaincode name required") } - if chaincodePath == "" { - return nil, "", errors.New("chaincodePath required") + if req.Path == "" { + return nil, "", errors.New("chaincode path required") } - if chaincodeVersion == "" { - return nil, "", errors.New("chaincodeVersion required") + if req.Version == "" { + return nil, "", errors.New("chaincode version required") } - - if chaincodePackage == nil { - var err error - chaincodePackage, err = packager.PackageCC(chaincodePath, "") - if err != nil { - return nil, "", errors.WithMessage(err, "PackageCC failed") - } + if req.Package == nil { + return nil, "", errors.New("chaincode package is required") } now := time.Now() cds := &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ - Type: pb.ChaincodeSpec_GOLANG, ChaincodeId: &pb.ChaincodeID{Name: chaincodeName, Path: chaincodePath, Version: chaincodeVersion}}, - CodePackage: chaincodePackage, EffectiveDate: &google_protobuf.Timestamp{Seconds: int64(now.Second()), Nanos: int32(now.Nanosecond())}} + Type: req.Package.Type, ChaincodeId: &pb.ChaincodeID{Name: req.Name, Path: req.Path, Version: req.Version}}, + CodePackage: req.Package.Code, EffectiveDate: &google_protobuf.Timestamp{Seconds: int64(now.Second()), Nanos: int32(now.Nanosecond())}} if c.userContext == nil { return nil, "", errors.New("user context required") @@ -546,7 +539,7 @@ func (c *Client) InstallChaincode(chaincodeName string, chaincodePath string, ch SignedProposal: signedProposal, Proposal: proposal, TxnID: txnID, - }, targets) + }, req.Targets) return transactionProposalResponse, txID, err } diff --git a/pkg/fabric-client/mocks/mockclient.go b/pkg/fabric-client/mocks/mockclient.go index c7a267d4ce..489916a8f5 100644 --- a/pkg/fabric-client/mocks/mockclient.go +++ b/pkg/fabric-client/mocks/mockclient.go @@ -150,16 +150,31 @@ func (c *MockClient) QueryChannels(peer fab.Peer) (*pb.ChannelQueryResponse, err return nil, errors.New("Not implemented yet") } -//QueryInstalledChaincodes ... +//QueryInstalledChaincodes mocks query installed chaincodes func (c *MockClient) QueryInstalledChaincodes(peer fab.Peer) (*pb.ChaincodeQueryResponse, error) { - return nil, errors.New("Not implemented yet") + if peer == nil { + return nil, errors.New("Generate Error") + } + ci := &pb.ChaincodeInfo{Name: "name", Version: "version", Path: "path"} + response := &pb.ChaincodeQueryResponse{Chaincodes: []*pb.ChaincodeInfo{ci}} + return response, nil } -// InstallChaincode ... -func (c *MockClient) InstallChaincode(chaincodeName string, chaincodePath string, chaincodeVersion string, - chaincodePackage []byte, targets []apitxn.ProposalProcessor) ([]*apitxn.TransactionProposalResponse, string, error) { - return nil, "", errors.New("Not implemented yet") +// InstallChaincode mocks install chaincode +func (c *MockClient) InstallChaincode(req fab.InstallChaincodeRequest) ([]*apitxn.TransactionProposalResponse, string, error) { + if req.Name == "error" { + return nil, "", errors.New("Generate Error") + } + + if req.Name == "errorInResponse" { + result := apitxn.TransactionProposalResult{Endorser: "http://peer1.com", Status: 10} + response := &apitxn.TransactionProposalResponse{TransactionProposalResult: result, Err: errors.New("Generate Response Error")} + return []*apitxn.TransactionProposalResponse{response}, "1234", nil + } + result := apitxn.TransactionProposalResult{Endorser: "http://peer1.com", Status: 0} + response := &apitxn.TransactionProposalResponse{TransactionProposalResult: result} + return []*apitxn.TransactionProposalResponse{response}, "1234", nil } // UserContext ... diff --git a/pkg/fabric-client/packager/packager.go b/pkg/fabric-client/packager/packager.go deleted file mode 100644 index 10e6208b93..0000000000 --- a/pkg/fabric-client/packager/packager.go +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package packager - -import "github.com/hyperledger/fabric-sdk-go/pkg/errors" - -// PackageCC ... -/** - * Utility function to package a chaincode. The contents will be returned as a byte array. - * - * @param {string} chaincodePath required - String of the path to location of - * the source code of the chaincode - * @param {string} chaincodeType optional - String of the type of chaincode - * ['golang', 'car', 'java'] (default 'golang') - * @returns {[]byte} byte array - */ -func PackageCC(chaincodePath string, chaincodeType string) ([]byte, error) { - logger.Debugf("packager: chaincodePath: %s, chaincodeType: %s", chaincodePath, chaincodeType) - if chaincodePath == "" { - return nil, errors.New("chaincodePath is required") - } - if chaincodeType == "" { - chaincodeType = "golang" - } - logger.Debugf("packager: type %s ", chaincodeType) - switch chaincodeType { - case "golang": - return PackageGoLangCC(chaincodePath) - } - return nil, errors.New("chaincodeType is required") -} diff --git a/pkg/fabric-client/packager/packager_test.go b/pkg/fabric-client/packager/packager_test.go deleted file mode 100644 index e5472c73a9..0000000000 --- a/pkg/fabric-client/packager/packager_test.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright SecureKey Technologies Inc. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ -package packager - -import ( - "archive/tar" - "bytes" - "compress/gzip" - "io" - "os" - "path" - "testing" -) - -// Test Packager wrapper ChainCode packaging -func TestPackageCC(t *testing.T) { - pwd, err := os.Getwd() - if err != nil { - t.Fatalf("error from os.Getwd %v", err) - } - os.Setenv("GOPATH", path.Join(pwd, "../../../test/fixtures/testdata")) - - ccPackage, err := PackageCC("github.com", "") - if err != nil { - t.Fatalf("error from PackageGoLangCC %v", err) - } - - r := bytes.NewReader(ccPackage) - gzf, err := gzip.NewReader(r) - if err != nil { - t.Fatalf("error from gzip.NewReader %v", err) - } - tarReader := tar.NewReader(gzf) - i := 0 - exampleccExist := false - for { - header, err := tarReader.Next() - if err == io.EOF { - break - } - - if err != nil { - t.Fatalf("error from tarReader.Next() %v", err) - } - - if header.Name == "src/github.com/example_cc/example_cc.go" { - exampleccExist = true - } - i++ - } - - if !exampleccExist { - t.Fatalf("src/github.com/example_cc/example_cc.go not exist in tar file") - } - -} - -// Test Package Go ChainCode -func TestEmptyPackageCC(t *testing.T) { - os.Setenv("GOPATH", "") - - _, err := PackageCC("", "") - if err == nil { - t.Fatalf("Package Empty GoLang CC must return an error.") - } -} - -// Test Package Go ChainCode -func TestUndefinedPackageCC(t *testing.T) { - pwd, err := os.Getwd() - if err != nil { - t.Fatalf("error from os.Getwd %v", err) - } - os.Setenv("GOPATH", path.Join(pwd, "../../../test/fixtures/testdata")) - - _, err = PackageCC("github.com", "UndefinedCCType") - if err == nil { - t.Fatalf("Undefined package UndefinedCCType GoLang CC must return an error.") - } -} diff --git a/pkg/fabric-txn/admin/transactionconfig.go b/pkg/fabric-txn/admin/transactionconfig.go index c245c7df98..1487918354 100644 --- a/pkg/fabric-txn/admin/transactionconfig.go +++ b/pkg/fabric-txn/admin/transactionconfig.go @@ -7,7 +7,6 @@ SPDX-License-Identifier: Apache-2.0 package admin import ( - "os" "time" fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient" @@ -21,28 +20,6 @@ import ( ) var logger = logging.NewLogger("fabric_sdk_go") -var origGoPath = os.Getenv("GOPATH") - -// SendInstallCC Sends an install proposal to one or more endorsing peers. -func SendInstallCC(client fab.FabricClient, chainCodeID string, chainCodePath string, - chainCodeVersion string, chaincodePackage []byte, targets []apitxn.ProposalProcessor, deployPath string) error { - - changeGOPATHToDeploy(deployPath) - transactionProposalResponse, _, err := client.InstallChaincode(chainCodeID, chainCodePath, chainCodeVersion, chaincodePackage, targets) - resetGOPATH() - if err != nil { - return errors.WithMessage(err, "InstallChaincode failed") - } - for _, v := range transactionProposalResponse { - if v.Err != nil { - logger.Debugf("InstallChaincode endorser %s returned error", v.Endorser) - return errors.WithMessage(v.Err, "InstallChaincode endorser failed") - } - logger.Debugf("InstallChaincode endorser '%s' returned ProposalResponse status:%v", v.Endorser, v.Status) - } - - return nil -} // SendInstantiateCC Sends instantiate CC proposal to one or more endorsing peers func SendInstantiateCC(channel fab.Channel, chainCodeID string, args [][]byte, @@ -119,13 +96,3 @@ func SendUpgradeCC(channel fab.Channel, chainCodeID string, args [][]byte, return errors.New("upgradeCC timeout") } } - -// ChangeGOPATHToDeploy changes go path to fixtures folder -func changeGOPATHToDeploy(deployPath string) { - os.Setenv("GOPATH", deployPath) -} - -// ResetGOPATH resets go path to original -func resetGOPATH() { - os.Setenv("GOPATH", origGoPath) -} diff --git a/pkg/fabric-txn/discovery/staticdiscovery/staticdiscovery.go b/pkg/fabric-txn/discovery/staticdiscovery/staticdiscovery.go index 80b793bc35..b8844199be 100644 --- a/pkg/fabric-txn/discovery/staticdiscovery/staticdiscovery.go +++ b/pkg/fabric-txn/discovery/staticdiscovery/staticdiscovery.go @@ -66,8 +66,8 @@ func (dp *DiscoveryProvider) NewDiscoveryService(channelID string) (apifabclient for _, p := range netPeers { newPeer, err := peer.NewPeerFromConfig(&p, dp.config) - if err != nil || newPeer == nil { - return nil, errors.WithMessage(err, "NewPeer failed") + if err != nil { + return nil, errors.WithMessage(err, "NewPeerFromConfig failed") } peers = append(peers, newPeer) diff --git a/pkg/fabric-txn/mocks/mockdiscovery.go b/pkg/fabric-txn/mocks/mockdiscovery.go index 88821fdb46..13ec4f5674 100644 --- a/pkg/fabric-txn/mocks/mockdiscovery.go +++ b/pkg/fabric-txn/mocks/mockdiscovery.go @@ -45,7 +45,7 @@ func (ds *MockStaticDiscoveryService) GetPeers() ([]apifabclient.Peer, error) { } if ds.Peers == nil { - mockPeer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil} + mockPeer := mocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, MockMSP: "Org1MSP"} peers := make([]apifabclient.Peer, 0) peers = append(peers, &mockPeer) ds.Peers = peers diff --git a/pkg/fabric-txn/resmgmtclient/resmgmt.go b/pkg/fabric-txn/resmgmtclient/resmgmt.go index bd44ec0dcb..2c72ec2d3a 100644 --- a/pkg/fabric-txn/resmgmtclient/resmgmt.go +++ b/pkg/fabric-txn/resmgmtclient/resmgmt.go @@ -14,6 +14,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/pkg/errors" "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/orderer" + "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/peer" "github.com/hyperledger/fabric-sdk-go/pkg/logging" ) @@ -47,6 +48,10 @@ func NewResourceMgmtClient(client fab.FabricClient, discovery fab.DiscoveryServi rcFilter := filter if rcFilter == nil { // Default target filter is based on user msp + if client.UserContext().MspID() == "" { + return nil, errors.New("mspID not available in user context") + } + rcFilter = &MSPFilter{mspID: client.UserContext().MspID()} } @@ -66,6 +71,10 @@ func (rc *ResourceMgmtClient) JoinChannel(channelID string) error { return errors.WithMessage(err, "failed to get default targets for JoinChannel") } + if len(targets) == 0 { + return errors.New("No default targets available") + } + return rc.JoinChannelWithOpts(channelID, resmgmt.JoinChannelOpts{Targets: targets}) } @@ -81,6 +90,10 @@ func (rc *ResourceMgmtClient) JoinChannelWithOpts(channelID string, opts resmgmt return errors.WithMessage(err, "failed to determine target peers for JoinChannel") } + if len(targets) == 0 { + return errors.New("No targets available") + } + txnid, err := rc.client.NewTxnID() if err != nil { return errors.WithMessage(err, "NewTxnID failed") @@ -178,7 +191,116 @@ func (rc *ResourceMgmtClient) calculateTargets(peers []fab.Peer, filter resmgmt. return targets, nil } -// getChannel is helper method for creating channel. If channel is not configured it will use random orderer from global orderer configuration +// IsChaincodeInstalled verify if chaincode is installed on peer +func (rc *ResourceMgmtClient) IsChaincodeInstalled(req resmgmt.InstallCCRequest, peer fab.Peer) (bool, error) { + chaincodeQueryResponse, err := rc.client.QueryInstalledChaincodes(peer) + if err != nil { + return false, err + } + + for _, chaincode := range chaincodeQueryResponse.Chaincodes { + if chaincode.Name == req.Name && chaincode.Version == req.Version && chaincode.Path == req.Path { + return true, nil + } + } + + return false, nil +} + +// InstallCC - install chaincode +func (rc *ResourceMgmtClient) InstallCC(req resmgmt.InstallCCRequest) ([]resmgmt.InstallCCResponse, error) { + + if err := checkRequiredInstallCCParams(req); err != nil { + return nil, err + } + + targets, err := rc.getDefaultTargets() + if err != nil { + return nil, errors.WithMessage(err, "failed to get default targets for InstallCC") + } + + if len(targets) == 0 { + return nil, errors.New("No default targets available for install cc") + } + + return rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: targets}) +} + +// InstallCCWithOpts installs chaincode with custom options +func (rc *ResourceMgmtClient) InstallCCWithOpts(req resmgmt.InstallCCRequest, opts resmgmt.InstallCCOpts) ([]resmgmt.InstallCCResponse, error) { + + // For each peer query if chaincode installed. If cc is installed treat as success with message 'already installed'. + // If cc is not installed try to install, and if that fails add to the list with error and peer name. + + err := checkRequiredInstallCCParams(req) + if err != nil { + return nil, err + } + + targets, err := rc.calculateTargets(opts.Targets, opts.TargetFilter) + if err != nil { + return nil, errors.WithMessage(err, "failed to determine target peers for install cc") + } + + if len(targets) == 0 { + return nil, errors.New("No targets available for install cc") + } + + responses := make([]resmgmt.InstallCCResponse, 0) + + // Targets will be adjusted if cc has already been installed + newTargets := make([]fab.Peer, 0) + + for _, target := range targets { + installed, err := rc.IsChaincodeInstalled(req, target) + if err != nil { + // Add to responses with unable to verify error message + response := resmgmt.InstallCCResponse{Target: target.URL(), Err: errors.Errorf("unable to verify if cc is installed on %s", target.URL())} + responses = append(responses, response) + continue + } + if installed { + // Nothing to do - add info message to response + response := resmgmt.InstallCCResponse{Target: target.URL(), Info: "already installed"} + responses = append(responses, response) + } else { + // Not installed - add for processing + newTargets = append(newTargets, target) + } + } + + if len(newTargets) == 0 { + // CC is already installed on all targets and/or + // we are unable to verify if cc is installed on target(s) + return responses, nil + } + + icr := fab.InstallChaincodeRequest{Name: req.Name, Path: req.Path, Version: req.Version, Package: req.Package, Targets: peer.PeersToTxnProcessors(newTargets)} + transactionProposalResponse, _, err := rc.client.InstallChaincode(icr) + if err != nil { + return nil, errors.WithMessage(err, "InstallChaincode failed") + } + + for _, v := range transactionProposalResponse { + + logger.Infof("Install chaincode '%s' endorser '%s' returned ProposalResponse status:%v, error:'%s'", req.Name, v.Endorser, v.Status, v.Err) + + response := resmgmt.InstallCCResponse{Target: v.Endorser, Status: v.Status, Err: v.Err} + responses = append(responses, response) + } + + return responses, nil + +} + +func checkRequiredInstallCCParams(req resmgmt.InstallCCRequest) error { + if req.Name == "" || req.Version == "" || req.Path == "" || req.Package == nil { + return errors.New("Chaincode name(ID), version, path and chaincode package are required") + } + return nil +} + +// getChannel is helper method for instantiating channel. If channel is not configured it will use random orderer from global orderer configuration func (rc *ResourceMgmtClient) getChannel(channelID string) (fab.Channel, error) { channel := rc.client.Channel(channelID) diff --git a/pkg/fabric-txn/resmgmtclient/resmgmt_test.go b/pkg/fabric-txn/resmgmtclient/resmgmt_test.go index a87bcf49a7..98f60c7614 100644 --- a/pkg/fabric-txn/resmgmtclient/resmgmt_test.go +++ b/pkg/fabric-txn/resmgmtclient/resmgmt_test.go @@ -8,6 +8,7 @@ package resmgmtclient import ( "net" + "strings" "testing" "time" @@ -35,7 +36,7 @@ func TestJoinChannel(t *testing.T) { endorserServer, addr := startEndorserServer(t, grpcServer) time.Sleep(2 * time.Second) - client := setupTestClient() + client := setupTestClient("test", "Org1MSP") // Create test channel and add it to the client (no added orderer yet) channel, _ := channel.NewChannel("mychannel", client) @@ -111,6 +112,14 @@ func TestNoSigningUserFailure(t *testing.T) { t.Fatal("Should have failed due to missing signing user") } + user := fcmocks.NewMockUserWithMSPID("test", "") + client.SetUserContext(user) + + _, err = NewResourceMgmtClient(client, discovery, nil, config) + if err == nil { + t.Fatal("Should have failed due to missing msp") + } + } func TestJoinChannelRequiredParameters(t *testing.T) { @@ -129,6 +138,19 @@ func TestJoinChannelRequiredParameters(t *testing.T) { t.Fatalf("Should have failed with generated error in NewChannel") } + // Setup test client with different msp (default targets cannot be calculated) + client := setupTestClient("test", "otherMSP") + config := getNetworkConfig(t) + + // Create new resource management client ("otherMSP") + rc = setupResMgmtClient(client, nil, config, t) + + // Test missing default targets + err = rc.JoinChannel("mychannel") + if err == nil { + t.Fatalf("InstallCC should have failed with no default targets error") + } + } func TestJoinChannelWithOptsRequiredParameters(t *testing.T) { @@ -151,12 +173,18 @@ func TestJoinChannelWithOptsRequiredParameters(t *testing.T) { t.Fatalf("Should have failed if both target and filter provided") } + // Test missing default targets + err = rc.JoinChannelWithOpts("mychannel", resmgmt.JoinChannelOpts{TargetFilter: &MSPFilter{mspID: "MspID"}}) + if err == nil { + t.Fatalf("InstallCC should have failed with no targets error") + } + } func TestJoinChannelDiscoveryError(t *testing.T) { // Setup test client and config - client := setupTestClient() + client := setupTestClient("test", "Org1MSP") config := getNetworkConfig(t) // Create resource management client with discovery service that will generate an error @@ -177,7 +205,7 @@ func TestJoinChannelDiscoveryError(t *testing.T) { func TestJoinChannelNoOrdererConfig(t *testing.T) { - client := setupTestClient() + client := setupTestClient("test", "Org1MSP") // No channel orderer, no global orderer noOrdererConfig, err := config.InitConfig("./testdata/noorderer_test.yaml") @@ -217,6 +245,287 @@ func TestJoinChannelNoOrdererConfig(t *testing.T) { } +func TestIsChaincodeInstalled(t *testing.T) { + + rc := setupDefaultResMgmtClient(t) + + peer := &fcmocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, MockMSP: "Org1MSP"} + + // Chaincode found request + req := resmgmt.InstallCCRequest{Name: "name", Version: "version", Path: "path"} + + // Test chaincode installed (valid peer) + installed, err := rc.IsChaincodeInstalled(req, peer) + if err != nil { + t.Fatal(err) + } + if !installed { + t.Fatalf("CC should have been installed: %s", req) + } + + // Chaincode not found request + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path"} + + // Test chaincode installed + installed, err = rc.IsChaincodeInstalled(req, peer) + if err != nil { + t.Fatal(err) + } + if installed { + t.Fatalf("CC should NOT have been installed: %s", req) + } + + // Test error retrieving installed cc info (peer is nil) + _, err = rc.IsChaincodeInstalled(req, nil) + if err == nil { + t.Fatalf("Should have failed with error in get installed chaincodes") + } + +} + +func TestInstallCCWithOpts(t *testing.T) { + + rc := setupDefaultResMgmtClient(t) + + // Setup targets + var peers []fab.Peer + peer := fcmocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, MockMSP: "Org1MSP"} + peers = append(peers, &peer) + + // Already installed chaincode request + req := resmgmt.InstallCCRequest{Name: "name", Version: "version", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + responses, err := rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: peers}) + if err != nil { + t.Fatal(err) + } + + if responses == nil || len(responses) != 1 { + t.Fatal("Should have one 'already installed' response") + } + + if !strings.Contains(responses[0].Info, "already installed") { + t.Fatal("Should have 'already installed' info set") + } + + if responses[0].Target != peer.MockURL { + t.Fatalf("Expecting %s target URL, got %s", peer.MockURL, responses[0].Target) + } + + // Chaincode not found request (it will be installed) + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + responses, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: peers}) + if err != nil { + t.Fatal(err) + } + + if responses[0].Target != peer.MockURL { + t.Fatal("Wrong target URL set") + } + + if strings.Contains(responses[0].Info, "already installed") { + t.Fatal("Should not have 'already installed' info set since it was not previously installed") + } + + // Chaincode that causes generic (system) error in installed chaincodes + req = resmgmt.InstallCCRequest{Name: "error", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + _, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: peers}) + if err == nil { + t.Fatalf("Should have failed since install cc returns an error in the client") + } + + // Chaincode that causes response error in installed chaincodes + req = resmgmt.InstallCCRequest{Name: "errorInResponse", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + responses, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: peers}) + if err != nil { + t.Fatal(err) + } +} + +func TestInstallCC(t *testing.T) { + + rc := setupDefaultResMgmtClient(t) + + // Chaincode that is not installed already (it will be installed) + req := resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + responses, err := rc.InstallCC(req) + if err != nil { + t.Fatal(err) + } + if responses == nil || len(responses) != 1 { + t.Fatal("Should have one successful response") + } + + expected := "http://peer1.com" + if responses[0].Target != expected { + t.Fatalf("Expecting %s target URL, got %s", expected, responses[0].Target) + } + + if responses[0].Status != 0 { + t.Fatalf("Expecting %d status, got %d", 0, responses[0].Status) + } + + // Chaincode that causes generic (system) error in installed chaincodes + req = resmgmt.InstallCCRequest{Name: "error", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("Should have failed since install cc returns an error in the client") + } +} + +func TestInstallCCRequiredParameters(t *testing.T) { + + rc := setupDefaultResMgmtClient(t) + + // Test missing required parameters + req := resmgmt.InstallCCRequest{} + _, err := rc.InstallCC(req) + if err == nil { + t.Fatalf("Should have failed for empty install cc request") + } + + // Test missing chaincode ID + req = resmgmt.InstallCCRequest{Name: "", Version: "v0", Path: "path"} + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("Should have failed for empty cc ID") + } + + // Test missing chaincode version + req = resmgmt.InstallCCRequest{Name: "ID", Version: "", Path: "path"} + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("Should have failed for empty cc version") + } + + // Test missing chaincode path + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: ""} + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("InstallCC should have failed for empty cc path") + } + + // Test missing chaincode package + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path"} + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("InstallCC should have failed for nil chaincode package") + } + + // Setup test client with different msp (default targets cannot be calculated) + client := setupTestClient("test", "otherMSP") + config := getNetworkConfig(t) + + // Create new resource management client ("otherMSP") + rc = setupResMgmtClient(client, nil, config, t) + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + + // Test missing default targets + _, err = rc.InstallCC(req) + if err == nil { + t.Fatalf("InstallCC should have failed with no default targets error") + } + +} + +func TestInstallCCWithOptsRequiredParameters(t *testing.T) { + + rc := setupDefaultResMgmtClient(t) + + // Test missing required parameters + req := resmgmt.InstallCCRequest{} + opts := resmgmt.InstallCCOpts{} + _, err := rc.InstallCCWithOpts(req, opts) + if err == nil { + t.Fatalf("Should have failed for empty install cc request") + } + + // Test missing chaincode ID + req = resmgmt.InstallCCRequest{Name: "", Version: "v0", Path: "path"} + _, err = rc.InstallCCWithOpts(req, opts) + if err == nil { + t.Fatalf("Should have failed for empty cc ID") + } + + // Test missing chaincode version + req = resmgmt.InstallCCRequest{Name: "ID", Version: "", Path: "path"} + _, err = rc.InstallCCWithOpts(req, opts) + if err == nil { + t.Fatalf("Should have failed for empty cc version") + } + + // Test missing chaincode path + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: ""} + _, err = rc.InstallCCWithOpts(req, opts) + if err == nil { + t.Fatalf("InstallCC should have failed for empty cc path") + } + + // Test missing chaincode package + req = resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path"} + _, err = rc.InstallCCWithOpts(req, opts) + if err == nil { + t.Fatalf("InstallCC should have failed for nil chaincode package") + } + + // Valid request + req = resmgmt.InstallCCRequest{Name: "name", Version: "version", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + + // Setup targets + var peers []fab.Peer + peer := fcmocks.MockPeer{MockName: "Peer1", MockURL: "http://peer1.com", MockRoles: []string{}, MockCert: nil, MockMSP: "Org1MSP"} + peers = append(peers, &peer) + + // Test both targets and filter provided (error condition) + _, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{Targets: peers, TargetFilter: &MSPFilter{mspID: "Org1MSP"}}) + if err == nil { + t.Fatalf("Should have failed if both target and filter provided") + } + + // Setup test client with different msp + client := setupTestClient("test", "otherMSP") + config := getNetworkConfig(t) + + // Create new resource management client ("otherMSP") + rc = setupResMgmtClient(client, nil, config, t) + + // No targets and no filter -- default filter msp doesn't match discovery service peer msp + _, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{}) + if err == nil { + t.Fatalf("Should have failed with no targets error") + } + + // Test filter only provided (filter rejects discovery service peer msp) + _, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{TargetFilter: &MSPFilter{mspID: "Org2MSP"}}) + if err == nil { + t.Fatalf("Should have failed with no targets since filter rejected all discovery targets") + } +} + +func TestInstallCCDiscoveryError(t *testing.T) { + + // Setup test client and config + client := setupTestClient("test", "Org1MSP") + config := getNetworkConfig(t) + + // Create resource management client with discovery service that will generate an error + rc := setupResMgmtClient(client, errors.New("Test Error"), config, t) + + // Test InstallCC discovery service error + req := resmgmt.InstallCCRequest{Name: "ID", Version: "v0", Path: "path", Package: &fab.CCPackage{Type: 1, Code: []byte("code")}} + _, err := rc.InstallCC(req) + if err == nil { + t.Fatalf("Should have failed to install cc with discovery error") + } + + // Test InstallCC discovery service error + // if targets are not provided discovery service is used + _, err = rc.InstallCCWithOpts(req, resmgmt.InstallCCOpts{}) + if err == nil { + t.Fatalf("Should have failed to install cc with opts with discovery error") + } + +} + func setupTestDiscovery(discErr error, peers []fab.Peer) (fab.DiscoveryService, error) { mockDiscovery, err := txnmocks.NewMockDiscoveryProvider(discErr, peers) @@ -237,7 +546,7 @@ func getNetworkConfig(t *testing.T) *config.Config { } func setupDefaultResMgmtClient(t *testing.T) *ResourceMgmtClient { - client := setupTestClient() + client := setupTestClient("test", "Org1MSP") network := getNetworkConfig(t) return setupResMgmtClient(client, nil, network, t) } @@ -257,9 +566,9 @@ func setupResMgmtClient(client *fcmocks.MockClient, discErr error, config *confi return resClient } -func setupTestClient() *fcmocks.MockClient { +func setupTestClient(userName string, mspID string) *fcmocks.MockClient { client := fcmocks.NewMockClient() - user := fcmocks.NewMockUser("test") + user := fcmocks.NewMockUserWithMSPID(userName, mspID) cryptoSuite := &fcmocks.MockCryptoSuite{} client.SaveUserToStateStore(user, true) client.SetUserContext(user) diff --git a/test/integration/base_test_setup.go b/test/integration/base_test_setup.go index 6e03a93e68..2c272d3c87 100644 --- a/test/integration/base_test_setup.go +++ b/test/integration/base_test_setup.go @@ -18,6 +18,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/api/apitxn" chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient" resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/ccpackager/gopackager" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" deffab "github.com/hyperledger/fabric-sdk-go/def/fabapi" @@ -195,11 +196,20 @@ func (setup *BaseSetupImpl) UpgradeCC(chainCodeID string, chainCodePath string, return admin.SendUpgradeCC(setup.Channel, chainCodeID, args, chainCodePath, chainCodeVersion, chaincodePolicy, []apitxn.ProposalProcessor{setup.Channel.PrimaryPeer()}, setup.EventHub) } -// InstallCC ... -func (setup *BaseSetupImpl) InstallCC(chainCodeID string, chainCodePath string, chainCodeVersion string, chaincodePackage []byte) error { +// InstallCC use low level client to install chaincode +func (setup *BaseSetupImpl) InstallCC(name string, path string, version string, ccPackage *fab.CCPackage) error { - if err := admin.SendInstallCC(setup.Client, chainCodeID, chainCodePath, chainCodeVersion, chaincodePackage, peer.PeersToTxnProcessors(setup.Channel.Peers()), setup.GetDeployPath()); err != nil { - return errors.WithMessage(err, "SendInstallProposal failed") + icr := fab.InstallChaincodeRequest{Name: name, Path: path, Version: version, Package: ccPackage, Targets: peer.PeersToTxnProcessors(setup.Channel.Peers())} + + transactionProposalResponse, _, err := setup.Client.InstallChaincode(icr) + + if err != nil { + return errors.WithMessage(err, "InstallChaincode failed") + } + for _, v := range transactionProposalResponse { + if v.Err != nil { + return errors.WithMessage(v.Err, "InstallChaincode endorser failed") + } } return nil @@ -211,7 +221,7 @@ func (setup *BaseSetupImpl) GetDeployPath() string { return path.Join(pwd, "../fixtures/testdata") } -// InstallAndInstantiateExampleCC .. +// InstallAndInstantiateExampleCC install and instantiate using resource management client func (setup *BaseSetupImpl) InstallAndInstantiateExampleCC() error { chainCodePath := "github.com/example_cc" @@ -221,14 +231,20 @@ func (setup *BaseSetupImpl) InstallAndInstantiateExampleCC() error { setup.ChainCodeID = GenerateRandomID() } - if err := setup.InstallCC(setup.ChainCodeID, chainCodePath, chainCodeVersion, nil); err != nil { + ccPkg, err := packager.NewCCPackage(chainCodePath, setup.GetDeployPath()) + if err != nil { + return err + } + + _, err = resMgmtClient.InstallCC(resmgmt.InstallCCRequest{Name: setup.ChainCodeID, Path: chainCodePath, Version: chainCodeVersion, Package: ccPkg}) + if err != nil { return err } return setup.InstantiateCC(setup.ChainCodeID, chainCodePath, chainCodeVersion, initArgs) } -// UpgradeExampleCC .. +// UpgradeExampleCC upgrade example CC func (setup *BaseSetupImpl) UpgradeExampleCC() error { chainCodePath := "github.com/example_cc" @@ -238,7 +254,13 @@ func (setup *BaseSetupImpl) UpgradeExampleCC() error { setup.ChainCodeID = GenerateRandomID() } - if err := setup.InstallCC(setup.ChainCodeID, chainCodePath, chainCodeVersion, nil); err != nil { + ccPkg, err := packager.NewCCPackage(chainCodePath, setup.GetDeployPath()) + if err != nil { + return err + } + + _, err = resMgmtClient.InstallCC(resmgmt.InstallCCRequest{Name: setup.ChainCodeID, Path: chainCodePath, Version: chainCodeVersion, Package: ccPkg}) + if err != nil { return err } diff --git a/test/integration/events_test.go b/test/integration/events_test.go index fecdd5c186..18471dc485 100644 --- a/test/integration/events_test.go +++ b/test/integration/events_test.go @@ -13,6 +13,7 @@ import ( "github.com/hyperledger/fabric-sdk-go/api/apitxn" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/ccpackager/gopackager" "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/common" pb "github.com/hyperledger/fabric-sdk-go/third_party/github.com/hyperledger/fabric/protos/peer" ) @@ -48,8 +49,13 @@ func initializeTests(t *testing.T) BaseSetupImpl { testSetup.ChainCodeID = GenerateRandomID() + ccPkg, err := packager.NewCCPackage("github.com/events_cc", testSetup.GetDeployPath()) + if err != nil { + t.Fatalf("Failed to package chaincode") + } + // Install and Instantiate Events CC - if err := testSetup.InstallCC(testSetup.ChainCodeID, "github.com/events_cc", "v0", nil); err != nil { + if err := testSetup.InstallCC(testSetup.ChainCodeID, "github.com/events_cc", "v0", ccPkg); err != nil { t.Fatalf("installCC return error: %v", err) } diff --git a/test/integration/install_chaincode_test.go b/test/integration/install_chaincode_test.go index 8bb8e92454..12def59d97 100644 --- a/test/integration/install_chaincode_test.go +++ b/test/integration/install_chaincode_test.go @@ -8,13 +8,12 @@ package integration import ( "math/rand" - "os" "strconv" "strings" "testing" "time" - packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/packager" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/ccpackager/gopackager" ) const ( @@ -22,8 +21,6 @@ const ( chainCodePath = "github.com/example_cc" ) -var origGoPath = os.Getenv("GOPATH") - func TestChaincodeInstal(t *testing.T) { testSetup := &BaseSetupImpl{ @@ -51,7 +48,12 @@ func testChaincodeInstallUsingChaincodePath(t *testing.T, testSetup *BaseSetupIm // Retrieve installed chaincodes client := testSetup.Client - if err := testSetup.InstallCC(chainCodeName, chainCodePath, chainCodeVersion, nil); err != nil { + ccPkg, err := packager.NewCCPackage(chainCodePath, testSetup.GetDeployPath()) + if err != nil { + t.Fatalf("Failed to package chaincode") + } + + if err := testSetup.InstallCC(chainCodeName, chainCodePath, chainCodeVersion, ccPkg); err != nil { t.Fatalf("installCC return error: %v", err) } @@ -71,7 +73,7 @@ func testChaincodeInstallUsingChaincodePath(t *testing.T, testSetup *BaseSetupIm t.Fatalf("Failed to retrieve installed chaincode.") } //Install same chaincode again, should fail - err = testSetup.InstallCC(chainCodeName, chainCodePath, chainCodeVersion, nil) + err = testSetup.InstallCC(chainCodeName, chainCodePath, chainCodeVersion, ccPkg) if err == nil { t.Fatalf("install same chaincode didn't return error") } @@ -84,19 +86,19 @@ func testChaincodeInstallUsingChaincodePath(t *testing.T, testSetup *BaseSetupIm func testChaincodeInstallUsingChaincodePackage(t *testing.T, testSetup *BaseSetupImpl) { chainCodeVersion := getRandomCCVersion() - changeGOPATHToDeploy(testSetup.GetDeployPath()) - chaincodePackage, err := packager.PackageCC(chainCodePath, "") - resetGOPATH() + + ccPkg, err := packager.NewCCPackage(chainCodePath, testSetup.GetDeployPath()) if err != nil { t.Fatalf("PackageCC return error: %s", err) } - err = testSetup.InstallCC("install", "github.com/example_cc_pkg", chainCodeVersion, chaincodePackage) + err = testSetup.InstallCC("install", "github.com/example_cc_pkg", chainCodeVersion, ccPkg) if err != nil { t.Fatalf("installCC return error: %v", err) } + //Install same chaincode again, should fail - err = testSetup.InstallCC("install", chainCodePath, chainCodeVersion, chaincodePackage) + err = testSetup.InstallCC("install", chainCodePath, chainCodeVersion, ccPkg) if err == nil { t.Fatalf("install same chaincode didn't return error") } @@ -109,13 +111,3 @@ func getRandomCCVersion() string { rand.Seed(time.Now().UnixNano()) return "v0" + strconv.Itoa(rand.Intn(10000000)) } - -// ChangeGOPATHToDeploy changes go path to fixtures folder -func changeGOPATHToDeploy(deployPath string) { - os.Setenv("GOPATH", deployPath) -} - -// ResetGOPATH resets go path to original -func resetGOPATH() { - os.Setenv("GOPATH", origGoPath) -} diff --git a/test/integration/orgs/test_setup.go b/test/integration/orgs/test_setup.go index eaa10d3975..aec3a77b57 100644 --- a/test/integration/orgs/test_setup.go +++ b/test/integration/orgs/test_setup.go @@ -15,6 +15,8 @@ import ( fab "github.com/hyperledger/fabric-sdk-go/api/apifabclient" "github.com/hyperledger/fabric-sdk-go/api/apitxn" + packager "github.com/hyperledger/fabric-sdk-go/pkg/fabric-client/ccpackager/gopackager" + chmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/chmgmtclient" resmgmt "github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient" deffab "github.com/hyperledger/fabric-sdk-go/def/fabapi" @@ -173,13 +175,21 @@ func installAndInstantiate(t *testing.T) { return } - orgTestClient.SetUserContext(org1AdminUser) - admin.SendInstallCC(orgTestClient, "exampleCC", - "github.com/example_cc", "0", nil, []apitxn.ProposalProcessor{orgTestPeer0}, "../../fixtures/testdata") + ccPkg, err := packager.NewCCPackage("github.com/example_cc", "../../fixtures/testdata") + if err != nil { + t.Fatal(err) + } + + req := resmgmt.InstallCCRequest{Name: "exampleCC", Path: "github.com/example_cc", Version: "0", Package: ccPkg} - orgTestClient.SetUserContext(org2AdminUser) - err := admin.SendInstallCC(orgTestClient, "exampleCC", - "github.com/example_cc", "0", nil, []apitxn.ProposalProcessor{orgTestPeer1}, "../../fixtures/testdata") + // Install example cc for Org1 + _, err = org1ResMgmt.InstallCC(req) + if err != nil { + t.Fatal(err) + } + + // Install example cc for Org2 + _, err = org2ResMgmt.InstallCC(req) if err != nil { t.Fatal(err) } @@ -187,6 +197,7 @@ func installAndInstantiate(t *testing.T) { chaincodePolicy := cauthdsl.SignedByAnyMember([]string{ org1AdminUser.MspID(), org2AdminUser.MspID()}) + orgTestClient.SetUserContext(org2AdminUser) err = admin.SendInstantiateCC(orgTestChannel, "exampleCC", integration.ExampleCCInitArgs(), "github.com/example_cc", "0", chaincodePolicy, []apitxn.ProposalProcessor{orgTestPeer1}, peer1EventHub) if err != nil {