Skip to content

Commit 06f125d

Browse files
wlahtiale-linux
authored andcommitted
Refactor _lifecycle CLI query + tests
Initial refactoring of code and rewrite of unit tests in ginkgo. FAB-14299 #done Change-Id: I36de0ec19137759d6eca3541e19062abd76cbc14 Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
1 parent 0d3ea8f commit 06f125d

File tree

7 files changed

+628
-115
lines changed

7 files changed

+628
-115
lines changed

internal/peer/lifecycle/chaincode/chaincode.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ func Cmd(cf *CmdFactory) *cobra.Command {
3939

4040
chaincodeCmd.AddCommand(PackageCmd(nil))
4141
chaincodeCmd.AddCommand(InstallCmd(nil))
42-
chaincodeCmd.AddCommand(queryInstalledCmd(cf))
42+
chaincodeCmd.AddCommand(QueryInstalledCmd(nil))
4343
chaincodeCmd.AddCommand(approveForMyOrgCmd(cf, nil))
4444
chaincodeCmd.AddCommand(commitCmd(cf, nil))
45-
chaincodeCmd.AddCommand(queryCommittedCmd(cf))
4645
chaincodeCmd.AddCommand(queryApprovalStatusCmd(cf, nil))
46+
chaincodeCmd.AddCommand(QueryCommittedCmd(nil))
4747

4848
return chaincodeCmd
4949
}

internal/peer/lifecycle/chaincode/common.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,33 @@ SPDX-License-Identifier: Apache-2.0
77
package chaincode
88

99
import (
10+
"context"
1011
"crypto/tls"
1112
"fmt"
1213

14+
"github.com/golang/protobuf/proto"
1315
"github.com/hyperledger/fabric/internal/peer/common"
1416
"github.com/hyperledger/fabric/internal/peer/common/api"
1517
"github.com/hyperledger/fabric/internal/pkg/identity"
18+
"github.com/hyperledger/fabric/protos/peer"
1619
pb "github.com/hyperledger/fabric/protos/peer"
1720
"github.com/pkg/errors"
1821
"github.com/spf13/viper"
22+
"google.golang.org/grpc"
1923
)
2024

25+
// EndorserClient defines the interface for sending a proposal
26+
// to an endorser
27+
type EndorserClient interface {
28+
ProcessProposal(ctx context.Context, in *pb.SignedProposal, opts ...grpc.CallOption) (*pb.ProposalResponse, error)
29+
}
30+
31+
// Signer defines the interface needed for signing messages
32+
type Signer interface {
33+
Sign(msg []byte) ([]byte, error)
34+
Serialize() ([]byte, error)
35+
}
36+
2137
// CmdFactory holds the clients used by ChaincodeCmd
2238
type CmdFactory struct {
2339
EndorserClients []pb.EndorserClient
@@ -148,3 +164,29 @@ func validatePeerConnectionParameters(cmdName string) error {
148164

149165
return nil
150166
}
167+
168+
func signProposal(proposal *peer.Proposal, signer Signer) (*peer.SignedProposal, error) {
169+
// check for nil argument
170+
if proposal == nil {
171+
return nil, errors.New("proposal cannot be nil")
172+
}
173+
174+
if signer == nil {
175+
return nil, errors.New("signer cannot be nil")
176+
}
177+
178+
proposalBytes, err := proto.Marshal(proposal)
179+
if err != nil {
180+
return nil, errors.Wrap(err, "error marshaling Proposal")
181+
}
182+
183+
signature, err := signer.Sign(proposalBytes)
184+
if err != nil {
185+
return nil, err
186+
}
187+
188+
return &peer.SignedProposal{
189+
ProposalBytes: proposalBytes,
190+
Signature: signature,
191+
}, nil
192+
}

internal/peer/lifecycle/chaincode/install.go

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,19 @@ import (
1212
"github.com/gogo/protobuf/proto"
1313
"github.com/hyperledger/fabric/core/chaincode/persistence"
1414
cb "github.com/hyperledger/fabric/protos/common"
15-
"github.com/hyperledger/fabric/protos/peer"
1615
pb "github.com/hyperledger/fabric/protos/peer"
1716
lb "github.com/hyperledger/fabric/protos/peer/lifecycle"
1817
"github.com/hyperledger/fabric/protoutil"
1918
"github.com/pkg/errors"
2019
"github.com/spf13/cobra"
2120
"github.com/spf13/viper"
22-
"google.golang.org/grpc"
2321
)
2422

2523
// Reader defines the interface needed for reading a file.
2624
type Reader interface {
2725
ReadFile(string) ([]byte, error)
2826
}
2927

30-
// EndorserClient defines the interface for sending a proposal
31-
// to an endorser.
32-
type EndorserClient interface {
33-
ProcessProposal(ctx context.Context, in *pb.SignedProposal, opts ...grpc.CallOption) (*pb.ProposalResponse, error)
34-
}
35-
36-
// Signer defines the interface needed for signing messages.
37-
type Signer interface {
38-
Sign(msg []byte) ([]byte, error)
39-
Serialize() ([]byte, error)
40-
}
41-
4228
// Installer holds the dependencies needed to install
4329
// a chaincode.
4430
type Installer struct {
@@ -152,7 +138,7 @@ func (i *Installer) Install() error {
152138
return err
153139
}
154140

155-
signedProposal, err := i.signProposal(proposal)
141+
signedProposal, err := signProposal(proposal, i.Signer)
156142
if err != nil {
157143
return errors.WithMessage(err, "failed to create signed proposal for chaincode install")
158144
}
@@ -215,22 +201,3 @@ func (i *Installer) createInstallProposal(pkgBytes []byte, creatorBytes []byte)
215201

216202
return proposal, nil
217203
}
218-
219-
func (i *Installer) signProposal(proposal *peer.Proposal) (*peer.SignedProposal, error) {
220-
// check for nil argument
221-
if proposal == nil {
222-
return nil, errors.New("proposal cannot be nil")
223-
}
224-
225-
proposalBytes, err := proto.Marshal(proposal)
226-
if err != nil {
227-
return nil, errors.Wrap(err, "failed to marshal proposal")
228-
}
229-
230-
signature, err := i.Signer.Sign(proposalBytes)
231-
if err != nil {
232-
return nil, err
233-
}
234-
235-
return &peer.SignedProposal{ProposalBytes: proposalBytes, Signature: signature}, nil
236-
}

internal/peer/lifecycle/chaincode/querycommitted.go

Lines changed: 94 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,61 @@ import (
1717
"github.com/hyperledger/fabric/protoutil"
1818
"github.com/pkg/errors"
1919
"github.com/spf13/cobra"
20+
"github.com/spf13/viper"
2021
)
2122

22-
var (
23-
chaincodeQueryCommittedCmd *cobra.Command
24-
)
23+
// CommittedQuerier holds the dependencies needed to query
24+
// the committed chaincode definitions
25+
type CommittedQuerier struct {
26+
Command *cobra.Command
27+
Input *CommittedQueryInput
28+
EndorserClient EndorserClient
29+
Signer Signer
30+
}
2531

26-
// queryCommittedCmd returns the cobra command for
32+
type CommittedQueryInput struct {
33+
ChannelID string
34+
Name string
35+
}
36+
37+
// QueryCommittedCmd returns the cobra command for
2738
// querying a committed chaincode definition given
2839
// the chaincode name
29-
func queryCommittedCmd(cf *CmdFactory) *cobra.Command {
30-
chaincodeQueryCommittedCmd = &cobra.Command{
40+
func QueryCommittedCmd(c *CommittedQuerier) *cobra.Command {
41+
chaincodeQueryCommittedCmd := &cobra.Command{
3142
Use: "querycommitted",
32-
Short: "Query a committed chaincode definition by name on a peer.",
33-
Long: "Query a committed chaincode definition by name on a peer.",
43+
Short: "Query a committed chaincode definition by channel and name on a peer.",
44+
Long: "Query a committed chaincode definition by channel and name on a peer.",
3445
RunE: func(cmd *cobra.Command, args []string) error {
35-
return queryCommitted(cmd, cf)
46+
if c == nil {
47+
ccInput := &ClientConnectionsInput{
48+
CommandName: cmd.Name(),
49+
EndorserRequired: true,
50+
ChannelID: channelID,
51+
PeerAddresses: peerAddresses,
52+
TLSRootCertFiles: tlsRootCertFiles,
53+
ConnectionProfilePath: connectionProfilePath,
54+
TLSEnabled: viper.GetBool("peer.tls.enabled"),
55+
}
56+
57+
cc, err := NewClientConnections(ccInput)
58+
if err != nil {
59+
return err
60+
}
61+
62+
cqInput := &CommittedQueryInput{
63+
ChannelID: channelID,
64+
Name: chaincodeName,
65+
}
66+
67+
c = &CommittedQuerier{
68+
Command: cmd,
69+
EndorserClient: cc.EndorserClients[0],
70+
Input: cqInput,
71+
Signer: cc.Signer,
72+
}
73+
}
74+
return c.Query()
3675
},
3776
}
3877

@@ -48,72 +87,84 @@ func queryCommittedCmd(cf *CmdFactory) *cobra.Command {
4887
return chaincodeQueryCommittedCmd
4988
}
5089

51-
func queryCommitted(cmd *cobra.Command, cf *CmdFactory) error {
52-
// Parsing of the command line is done so silence cmd usage
53-
cmd.SilenceUsage = true
54-
55-
var err error
56-
if cf == nil {
57-
cf, err = InitCmdFactory(cmd.Name(), true, false)
58-
if err != nil {
59-
return err
60-
}
90+
// Query returns the committed chaincode definition
91+
// for a given channel and chaincode name
92+
func (c *CommittedQuerier) Query() error {
93+
if c.Command != nil {
94+
// Parsing of the command line is done so silence cmd usage
95+
c.Command.SilenceUsage = true
6196
}
6297

63-
creator, err := cf.Signer.Serialize()
98+
err := c.validateInput()
6499
if err != nil {
65-
return fmt.Errorf("Error serializing identity: %s", err)
100+
return err
66101
}
67102

68-
proposal, err := createQueryCommittedChaincodeDefinitionProposal(channelID, chaincodeName, creator)
103+
proposal, err := c.createProposal()
69104
if err != nil {
70-
return errors.WithMessage(err, "error creating proposal")
105+
return errors.WithMessage(err, "failed to create proposal")
71106
}
72107

73-
signedProposal, err := protoutil.GetSignedProposal(proposal, cf.Signer)
108+
signedProposal, err := signProposal(proposal, c.Signer)
74109
if err != nil {
75-
return errors.WithMessage(err, "error creating signed proposal")
110+
return errors.WithMessage(err, "failed to create signed proposal")
76111
}
77112

78-
// QueryCommittedChaincodeDefinition is currently only supported for one peer
79-
proposalResponse, err := cf.EndorserClients[0].ProcessProposal(context.Background(), signedProposal)
113+
proposalResponse, err := c.EndorserClient.ProcessProposal(context.Background(), signedProposal)
80114
if err != nil {
81-
return errors.WithMessage(err, "error endorsing proposal")
115+
return errors.WithMessage(err, "failed to endorse proposal")
116+
}
117+
118+
if proposalResponse == nil {
119+
return errors.New("received nil proposal response")
82120
}
83121

84122
if proposalResponse.Response == nil {
85-
return errors.Errorf("proposal response had nil response")
123+
return errors.New("received proposal response with nil response")
86124
}
87125

88126
if proposalResponse.Response.Status != int32(cb.Status_SUCCESS) {
89-
return errors.Errorf("bad response: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message)
127+
return errors.Errorf("query failed with status: %d - %s", proposalResponse.Response.Status, proposalResponse.Response.Message)
90128
}
91129

92-
return printQueryCommittedResponse(proposalResponse)
130+
return c.printResponse(proposalResponse)
93131
}
94132

95133
// printResponse prints the information included in the response
96134
// from the server.
97-
func printQueryCommittedResponse(proposalResponse *pb.ProposalResponse) error {
135+
func (c *CommittedQuerier) printResponse(proposalResponse *pb.ProposalResponse) error {
98136
qdcr := &lb.QueryChaincodeDefinitionResult{}
99137
err := proto.Unmarshal(proposalResponse.Response.Payload, qdcr)
100138
if err != nil {
101-
return err
139+
return errors.Wrap(err, "failed to unmarshal proposal response's response payload")
102140
}
103141
fmt.Printf("Committed chaincode definition for chaincode '%s' on channel '%s':\n", chaincodeName, channelID)
104142
fmt.Printf("Version: %s, Sequence: %d, Endorsement Plugin: %s, Validation Plugin: %s\n", qdcr.Version, qdcr.Sequence, qdcr.EndorsementPlugin, qdcr.ValidationPlugin)
143+
105144
return nil
106145

107146
}
108147

109-
func createQueryCommittedChaincodeDefinitionProposal(channelID, chaincodeName string, creatorBytes []byte) (*pb.Proposal, error) {
148+
func (c *CommittedQuerier) validateInput() error {
149+
if c.Input.ChannelID == "" {
150+
return errors.New("channel name must be specified")
151+
}
152+
153+
if c.Input.Name == "" {
154+
return errors.New("chaincode name must be specified")
155+
}
156+
157+
return nil
158+
}
159+
160+
func (c *CommittedQuerier) createProposal() (*pb.Proposal, error) {
110161
args := &lb.QueryChaincodeDefinitionArgs{
111-
Name: chaincodeName,
162+
Name: c.Input.Name,
112163
}
113164

114165
argsBytes, err := proto.Marshal(args)
115166
if err != nil {
116-
return nil, err
167+
return nil, errors.Wrap(err, "failed to marshal args")
117168
}
118169
ccInput := &pb.ChaincodeInput{Args: [][]byte{[]byte("QueryChaincodeDefinition"), argsBytes}}
119170

@@ -124,9 +175,14 @@ func createQueryCommittedChaincodeDefinitionProposal(channelID, chaincodeName st
124175
},
125176
}
126177

127-
proposal, _, err := protoutil.CreateProposalFromCIS(cb.HeaderType_ENDORSER_TRANSACTION, channelID, cis, creatorBytes)
178+
signerSerialized, err := c.Signer.Serialize()
179+
if err != nil {
180+
return nil, errors.WithMessage(err, "failed to serialize identity")
181+
}
182+
183+
proposal, _, err := protoutil.CreateProposalFromCIS(cb.HeaderType_ENDORSER_TRANSACTION, c.Input.ChannelID, cis, signerSerialized)
128184
if err != nil {
129-
return nil, errors.WithMessage(err, "error creating proposal for ChaincodeInvocationSpec")
185+
return nil, errors.WithMessage(err, "failed to create ChaincodeInvocationSpec proposal")
130186
}
131187

132188
return proposal, nil

0 commit comments

Comments
 (0)