Skip to content

Commit

Permalink
[FAB-3720]Add chaincode list cmd
Browse files Browse the repository at this point in the history
Add cmd "peer chaincode list --installed" to get installed
chaincodes on the peer. Use "peer chaincode list --instantiated
-C <channelID>" to get intantiated chaincodes on the channel.
Get these infos from lscc "getinstalledchaincodes"
and "getchaincodes" interfaces.

Change-Id: I1db548bde55388e518e383ec46de25b237c0b318
Signed-off-by: jiangyaoguo <jiangyaoguo@gmail.com>
  • Loading branch information
jiangyaoguo committed Sep 1, 2017
1 parent 283eb0e commit b48178c
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 35 deletions.
21 changes: 8 additions & 13 deletions peer/chaincode/chaincode.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package chaincode
Expand All @@ -28,8 +18,8 @@ import (

const (
chainFuncName = "chaincode"
shortDes = "Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade."
longDes = "Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade."
shortDes = "Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade|list."
longDes = "Operate a chaincode: install|instantiate|invoke|package|query|signpackage|upgrade|list."
)

var logger = flogging.MustGetLogger("chaincodeCmd")
Expand All @@ -53,6 +43,7 @@ func Cmd(cf *ChaincodeCmdFactory) *cobra.Command {
chaincodeCmd.AddCommand(queryCmd(cf))
chaincodeCmd.AddCommand(signpackageCmd(cf))
chaincodeCmd.AddCommand(upgradeCmd(cf))
chaincodeCmd.AddCommand(listCmd(cf))

return chaincodeCmd
}
Expand Down Expand Up @@ -116,6 +107,10 @@ func resetFlags() {
fmt.Sprint("The name of the endorsement system chaincode to be used for this chaincode"))
flags.StringVarP(&vscc, "vscc", "V", common.UndefinedParamValue,
fmt.Sprint("The name of the verification system chaincode to be used for this chaincode"))
flags.BoolVarP(&getInstalledChaincodes, "installed", "", false,
"Get the installed chaincodes on a peer")
flags.BoolVarP(&getInstantiatedChaincodes, "instantiated", "", false,
"Get the instantiated chaincodes on a channel")
}

func attachFlags(cmd *cobra.Command, names []string) {
Expand Down
12 changes: 1 addition & 11 deletions peer/chaincode/install.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2016-2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package chaincode
Expand Down
100 changes: 100 additions & 0 deletions peer/chaincode/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
"fmt"

"github.com/golang/protobuf/proto"
"golang.org/x/net/context"

pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/spf13/cobra"
)

var getInstalledChaincodes bool
var getInstantiatedChaincodes bool
var chaincodeListCmd *cobra.Command

const list_cmdname = "list"

// installCmd returns the cobra command for Chaincode Deploy
func listCmd(cf *ChaincodeCmdFactory) *cobra.Command {
chaincodeListCmd = &cobra.Command{
Use: "list",
Short: "Get the instantiated chaincodes on a channel or installed chaincodes on a peer.",
Long: "Get the instantiated chaincodes in the channel if specify channel, or get installed chaincodes on the peer",
RunE: func(cmd *cobra.Command, args []string) error {
return getChaincodes(cmd, cf)
},
}

flagList := []string{
"channelID",
"installed",
"instantiated",
}
attachFlags(chaincodeListCmd, flagList)

return chaincodeListCmd
}

func getChaincodes(cmd *cobra.Command, cf *ChaincodeCmdFactory) error {
var err error
if cf == nil {
cf, err = InitCmdFactory(true, false)
if err != nil {
return err
}
}

creator, err := cf.Signer.Serialize()
if err != nil {
return fmt.Errorf("Error serializing identity for %s: %s", cf.Signer.GetIdentifier(), err)
}

var prop *pb.Proposal
if getInstalledChaincodes && (!getInstantiatedChaincodes) {
prop, _, err = utils.CreateGetInstalledChaincodesProposal(creator)
} else if getInstantiatedChaincodes && (!getInstalledChaincodes) {
prop, _, err = utils.CreateGetChaincodesProposal(chainID, creator)
} else {
return fmt.Errorf("Must explicitly specify \"--installed\" or \"--instantiated\"")
}

if err != nil {
return fmt.Errorf("Error creating proposal %s: %s", chainFuncName, err)
}

var signedProp *pb.SignedProposal
signedProp, err = utils.GetSignedProposal(prop, cf.Signer)
if err != nil {
return fmt.Errorf("Error creating signed proposal %s: %s", chainFuncName, err)
}

proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
if err != nil {
return fmt.Errorf("Error endorsing %s: %s", chainFuncName, err)
}

cqr := &pb.ChaincodeQueryResponse{}
err = proto.Unmarshal(proposalResponse.Response.Payload, cqr)
if err != nil {
return err
}

if getInstalledChaincodes {
fmt.Println("Get installed chaincodes on peer:")
} else {
fmt.Printf("Get instantiated chaincodes on channel %s:\n", chainID)
}
for _, chaincode := range cqr.Chaincodes {
fmt.Printf("%v\n", chaincode)
}
return nil
}
99 changes: 99 additions & 0 deletions peer/chaincode/list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
Copyright IBM Corp. 2017 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/

package chaincode

import (
"fmt"
"testing"

"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/peer/common"
pb "github.com/hyperledger/fabric/protos/peer"
)

func TestChaincodeListCmd(t *testing.T) {
InitMSP()

signer, err := common.GetDefaultSigner()
if err != nil {
t.Fatalf("Get default signer error: %s", err)
}

installedCqr := &pb.ChaincodeQueryResponse{
Chaincodes: []*pb.ChaincodeInfo{
&pb.ChaincodeInfo{Name: "mycc1", Version: "1.0", Path: "codePath1", Input: "input", Escc: "escc", Vscc: "vscc"},
&pb.ChaincodeInfo{Name: "mycc2", Version: "1.0", Path: "codePath2", Input: "input", Escc: "escc", Vscc: "vscc"},
},
}
installedCqrBytes, err := proto.Marshal(installedCqr)
if err != nil {
t.Fatalf("Marshale error: %s", err)
}

mockResponse := &pb.ProposalResponse{
Response: &pb.Response{Status: 200, Payload: installedCqrBytes},
Endorsement: &pb.Endorsement{},
}

mockEndorerClient := common.GetMockEndorserClient(mockResponse, nil)

mockBroadcastClient := common.GetMockBroadcastClient(nil)

mockCF := &ChaincodeCmdFactory{
EndorserClient: mockEndorerClient,
Signer: signer,
BroadcastClient: mockBroadcastClient,
}

// Get installed chaincodes
installedChaincodesCmd := listCmd(mockCF)

args := []string{"--installed"}
installedChaincodesCmd.SetArgs(args)

if err := installedChaincodesCmd.Execute(); err != nil {
t.Errorf("Run chaincode list cmd to get installed chaincodes error:%v", err)
}

resetFlags()

// Get instantiated chaincodes
instantiatedChaincodesCmd := listCmd(mockCF)

args = []string{"--instantiated"}
instantiatedChaincodesCmd.SetArgs(args)

if err := instantiatedChaincodesCmd.Execute(); err != nil {
t.Errorf("Run chaincode list cmd to get instantiated chaincodes error:%v", err)
}

resetFlags()

// Wrong case: Set both "--installed" and "--instantiated"
Cmd := listCmd(mockCF)

args = []string{"--installed", "--instantiated"}
Cmd.SetArgs(args)

expectErr := fmt.Errorf("Must explicitly specify \"--installed\" or \"--instantiated\"")
if err := Cmd.Execute(); err == nil || err.Error() != expectErr.Error() {
t.Errorf("Expect error: %s", expectErr)
}

resetFlags()

// Wrong case: Miss "--intsalled" and "--instantiated"
nilCmd := listCmd(mockCF)

args = []string{}
nilCmd.SetArgs(args)

expectErr = fmt.Errorf("Must explicitly specify \"--installed\" or \"--instantiated\"")
if err := nilCmd.Execute(); err == nil || err.Error() != expectErr.Error() {
t.Errorf("Expect error: %s", expectErr)
}
}
36 changes: 25 additions & 11 deletions protos/utils/proputils.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
SPDX-License-Identifier: Apache-2.0
*/

package utils
Expand Down Expand Up @@ -429,6 +419,30 @@ func CreateProposalFromCIS(typ common.HeaderType, chainID string, cis *peer.Chai
return CreateChaincodeProposal(typ, chainID, cis, creator)
}

// CreateGetChaincodesProposal returns a GETCHAINCODES proposal given a serialized identity
func CreateGetChaincodesProposal(chainID string, creator []byte) (*peer.Proposal, string, error) {
ccinp := &peer.ChaincodeInput{Args: [][]byte{[]byte("getchaincodes")}}
lsccSpec := &peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
Type: peer.ChaincodeSpec_GOLANG,
ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
Input: ccinp},
}
return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, chainID, lsccSpec, creator)
}

// CreateGetChaincodesProposal returns a GETINSTALLEDCHAINCODES proposal given a serialized identity
func CreateGetInstalledChaincodesProposal(creator []byte) (*peer.Proposal, string, error) {
ccinp := &peer.ChaincodeInput{Args: [][]byte{[]byte("getinstalledchaincodes")}}
lsccSpec := &peer.ChaincodeInvocationSpec{
ChaincodeSpec: &peer.ChaincodeSpec{
Type: peer.ChaincodeSpec_GOLANG,
ChaincodeId: &peer.ChaincodeID{Name: "lscc"},
Input: ccinp},
}
return CreateProposalFromCIS(common.HeaderType_ENDORSER_TRANSACTION, "", lsccSpec, creator)
}

// CreateInstallProposalFromCDS returns a install proposal given a serialized identity and a ChaincodeDeploymentSpec
func CreateInstallProposalFromCDS(ccpack proto.Message, creator []byte) (*peer.Proposal, string, error) {
return createProposalFromCDS("", ccpack, creator, nil, nil, nil, "install")
Expand Down

0 comments on commit b48178c

Please sign in to comment.