Skip to content

Commit eb048ef

Browse files
committed
[FAB-1237] chaincode upgrade cli
This commit can be divided into two parts. One implements chaincode upgrade cli. Another is a refactor of chaincode cmd package. The main idea is extract endorserClient/broadcastClient/signer to be holded by ChaincodeCmdFactory, then we can get clients needed from ChaincodeCmdFactory in cmd implements. Thus in unit-tests, we can construct mock clients for tests. If this refactor looks good, we can extend it to other cmd tests. Change-Id: I1a44e347009fc645b2e97cd6d65efde5fb229257 Signed-off-by: jiangyaoguo <[email protected]>
1 parent 62e16f9 commit eb048ef

13 files changed

+554
-129
lines changed

core/chaincode/exectransaction_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ func endTxSimulationCDS(chainID string, txid string, txsim ledger.TxSimulator, p
136136
return err
137137
}
138138
// get a proposal - we need it to get a transaction
139-
prop, err := putils.CreateProposalFromCDS(txid, chainID, cds, ss)
139+
prop, err := putils.CreateDeployProposalFromCDS(txid, chainID, cds, ss)
140140
if err != nil {
141141
return err
142142
}

peer/chaincode/chaincode.go

+11-6
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,8 @@ const (
3131

3232
var logger = logging.MustGetLogger("chaincodeCmd")
3333

34-
// Cmd returns the cobra command for Chaincode
35-
func Cmd() *cobra.Command {
36-
flags := chaincodeCmd.PersistentFlags()
34+
func AddFlags(cmd *cobra.Command) {
35+
flags := cmd.PersistentFlags()
3736

3837
flags.StringVarP(&chaincodeLang, "lang", "l", "golang",
3938
fmt.Sprintf("Language the %s is written in", chainFuncName))
@@ -51,10 +50,16 @@ func Cmd() *cobra.Command {
5150
fmt.Sprint("Name of a custom ID generation algorithm (hashing and decoding) e.g. sha256base64"))
5251
flags.StringVarP(&chainID, "chainID", "C", util.GetTestChainID(),
5352
fmt.Sprint("The chain on which this command should be executed"))
53+
}
54+
55+
// Cmd returns the cobra command for Chaincode
56+
func Cmd(cf *ChaincodeCmdFactory) *cobra.Command {
57+
AddFlags(chaincodeCmd)
5458

55-
chaincodeCmd.AddCommand(deployCmd())
56-
chaincodeCmd.AddCommand(invokeCmd())
57-
chaincodeCmd.AddCommand(queryCmd())
59+
chaincodeCmd.AddCommand(deployCmd(cf))
60+
chaincodeCmd.AddCommand(invokeCmd(cf))
61+
chaincodeCmd.AddCommand(queryCmd(cf))
62+
chaincodeCmd.AddCommand(upgradeCmd(cf))
5863

5964
return chaincodeCmd
6065
}

peer/chaincode/common.go

+32-27
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ import (
3232
"github.com/hyperledger/fabric/msp"
3333
"github.com/hyperledger/fabric/peer/common"
3434
"github.com/hyperledger/fabric/peer/util"
35-
protcommon "github.com/hyperledger/fabric/protos/common"
3635
pb "github.com/hyperledger/fabric/protos/peer"
3736
putils "github.com/hyperledger/fabric/protos/utils"
3837
"github.com/spf13/cobra"
@@ -155,7 +154,7 @@ func getChaincodeSpecification(cmd *cobra.Command) (*pb.ChaincodeSpec, error) {
155154
//
156155
// NOTE - Query will likely go away as all interactions with the endorser are
157156
// Proposal and ProposalResponses
158-
func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err error) {
157+
func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *ChaincodeCmdFactory) (err error) {
159158
spec, err := getChaincodeSpecification(cmd)
160159
if err != nil {
161160
return err
@@ -167,19 +166,9 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
167166
invocation.IdGenerationAlg = customIDGenAlg
168167
}
169168

170-
endorserClient, err := common.GetEndorserClient(cmd)
169+
creator, err := cf.Signer.Serialize()
171170
if err != nil {
172-
return fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
173-
}
174-
175-
signer, err := msp.GetLocalMSP().GetDefaultSigningIdentity()
176-
if err != nil {
177-
return fmt.Errorf("Error obtaining the default signing identity, err %s", err)
178-
}
179-
180-
creator, err := signer.Serialize()
181-
if err != nil {
182-
return fmt.Errorf("Error serializing the default signing identity, err %s", err)
171+
return fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.Identifier(), err)
183172
}
184173

185174
uuid := cutil.GenerateUUID()
@@ -191,27 +180,27 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
191180
}
192181

193182
var signedProp *pb.SignedProposal
194-
signedProp, err = putils.GetSignedProposal(prop, signer)
183+
signedProp, err = putils.GetSignedProposal(prop, cf.Signer)
195184
if err != nil {
196185
return fmt.Errorf("Error creating signed proposal %s: %s\n", chainFuncName, err)
197186
}
198187

199188
var proposalResp *pb.ProposalResponse
200-
proposalResp, err = endorserClient.ProcessProposal(context.Background(), signedProp)
189+
proposalResp, err = cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
201190
if err != nil {
202191
return fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err)
203192
}
204193

205194
if invoke {
206195
if proposalResp != nil {
207196
// assemble a signed transaction (it's an Envelope message)
208-
env, err := putils.CreateSignedTx(prop, signer, proposalResp)
197+
env, err := putils.CreateSignedTx(prop, cf.Signer, proposalResp)
209198
if err != nil {
210199
return fmt.Errorf("Could not assemble transaction, err %s", err)
211200
}
212201

213202
// send the envelope for ordering
214-
if err = sendTransaction(env); err != nil {
203+
if err = cf.BroadcastClient.Send(env); err != nil {
215204
return fmt.Errorf("Error sending transaction %s: %s\n", chainFuncName, err)
216205
}
217206
}
@@ -241,7 +230,6 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool) (err
241230
}
242231

243232
func checkChaincodeCmdParams(cmd *cobra.Command) error {
244-
245233
//we need chaincode name for everything, including deploy
246234
if chaincodeName == common.UndefinedParamValue {
247235
return fmt.Errorf("Must supply value for %s name parameter.\n", chainFuncName)
@@ -283,16 +271,33 @@ func checkChaincodeCmdParams(cmd *cobra.Command) error {
283271
return nil
284272
}
285273

286-
//sendTransactions sends a serialize Envelop to the orderer
287-
func sendTransaction(env *protcommon.Envelope) error {
288-
var orderer string
289-
if viper.GetBool("peer.committer.enabled") {
290-
orderer = viper.GetString("peer.committer.ledger.orderer")
274+
// ChaincodeCmdFactory holds the clients used by ChaincodeCmd
275+
type ChaincodeCmdFactory struct {
276+
EndorserClient pb.EndorserClient
277+
Signer msp.SigningIdentity
278+
BroadcastClient common.BroadcastClient
279+
}
280+
281+
// InitCmdFactory init the ChaincodeCmdFactory with default clients
282+
func InitCmdFactory() (*ChaincodeCmdFactory, error) {
283+
endorserClient, err := common.GetEndorserClient()
284+
if err != nil {
285+
return nil, fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
291286
}
292287

293-
if orderer == "" {
294-
return nil
288+
signer, err := common.GetDefaultSigner()
289+
if err != nil {
290+
return nil, fmt.Errorf("Error getting default signer: %s", err)
291+
}
292+
293+
broadcastClient, err := common.GetBroadcastClient()
294+
if err != nil {
295+
return nil, fmt.Errorf("Error getting broadcast client: %s", err)
295296
}
296297

297-
return Send(orderer, env)
298+
return &ChaincodeCmdFactory{
299+
EndorserClient: endorserClient,
300+
Signer: signer,
301+
BroadcastClient: broadcastClient,
302+
}, nil
298303
}

peer/chaincode/deploy.go

+32-33
Original file line numberDiff line numberDiff line change
@@ -22,31 +22,31 @@ import (
2222
"golang.org/x/net/context"
2323

2424
"github.com/hyperledger/fabric/core/util"
25-
"github.com/hyperledger/fabric/msp"
26-
"github.com/hyperledger/fabric/peer/common"
2725
protcommon "github.com/hyperledger/fabric/protos/common"
2826
pb "github.com/hyperledger/fabric/protos/peer"
2927
"github.com/hyperledger/fabric/protos/utils"
3028
"github.com/spf13/cobra"
3129
)
3230

33-
// Cmd returns the cobra command for Chaincode Deploy
34-
func deployCmd() *cobra.Command {
35-
return chaincodeDeployCmd
36-
}
31+
var chaincodeDeployCmd *cobra.Command
32+
33+
// deployCmd returns the cobra command for Chaincode Deploy
34+
func deployCmd(cf *ChaincodeCmdFactory) *cobra.Command {
35+
chaincodeDeployCmd = &cobra.Command{
36+
Use: "deploy",
37+
Short: fmt.Sprintf("Deploy the specified chaincode to the network."),
38+
Long: fmt.Sprintf(`Deploy the specified chaincode to the network.`),
39+
ValidArgs: []string{"1"},
40+
RunE: func(cmd *cobra.Command, args []string) error {
41+
return chaincodeDeploy(cmd, args, cf)
42+
},
43+
}
3744

38-
var chaincodeDeployCmd = &cobra.Command{
39-
Use: "deploy",
40-
Short: fmt.Sprintf("Deploy the specified chaincode to the network."),
41-
Long: fmt.Sprintf(`Deploy the specified chaincode to the network.`),
42-
ValidArgs: []string{"1"},
43-
RunE: func(cmd *cobra.Command, args []string) error {
44-
return chaincodeDeploy(cmd, args)
45-
},
45+
return chaincodeDeployCmd
4646
}
4747

4848
//deploy the command via Endorser
49-
func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
49+
func deploy(cmd *cobra.Command, cf *ChaincodeCmdFactory) (*protcommon.Envelope, error) {
5050
spec, err := getChaincodeSpecification(cmd)
5151
if err != nil {
5252
return nil, err
@@ -57,41 +57,32 @@ func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
5757
return nil, fmt.Errorf("Error getting chaincode code %s: %s", chainFuncName, err)
5858
}
5959

60-
endorserClient, err := common.GetEndorserClient(cmd)
61-
if err != nil {
62-
return nil, fmt.Errorf("Error getting endorser client %s: %s", chainFuncName, err)
63-
}
64-
signer, err := msp.GetLocalMSP().GetDefaultSigningIdentity()
65-
if err != nil {
66-
return nil, fmt.Errorf("Error obtaining the default signing identity, err %s", err)
67-
}
68-
69-
creator, err := signer.Serialize()
60+
creator, err := cf.Signer.Serialize()
7061
if err != nil {
71-
return nil, fmt.Errorf("Error serializing the default signing identity, err %s", err)
62+
return nil, fmt.Errorf("Error serializing identity for %s: %s\n", cf.Signer.Identifier(), err)
7263
}
7364

7465
uuid := util.GenerateUUID()
7566

76-
prop, err := utils.CreateProposalFromCDS(uuid, chainID, cds, creator)
67+
prop, err := utils.CreateDeployProposalFromCDS(uuid, chainID, cds, creator)
7768
if err != nil {
7869
return nil, fmt.Errorf("Error creating proposal %s: %s\n", chainFuncName, err)
7970
}
8071

8172
var signedProp *pb.SignedProposal
82-
signedProp, err = utils.GetSignedProposal(prop, signer)
73+
signedProp, err = utils.GetSignedProposal(prop, cf.Signer)
8374
if err != nil {
8475
return nil, fmt.Errorf("Error creating signed proposal %s: %s\n", chainFuncName, err)
8576
}
8677

87-
proposalResponse, err := endorserClient.ProcessProposal(context.Background(), signedProp)
78+
proposalResponse, err := cf.EndorserClient.ProcessProposal(context.Background(), signedProp)
8879
if err != nil {
8980
return nil, fmt.Errorf("Error endorsing %s: %s\n", chainFuncName, err)
9081
}
9182

9283
if proposalResponse != nil {
9384
// assemble a signed transaction (it's an Envelope message)
94-
env, err := utils.CreateSignedTx(prop, signer, proposalResponse)
85+
env, err := utils.CreateSignedTx(prop, cf.Signer, proposalResponse)
9586
if err != nil {
9687
return nil, fmt.Errorf("Could not assemble transaction, err %s", err)
9788
}
@@ -105,14 +96,22 @@ func deploy(cmd *cobra.Command) (*protcommon.Envelope, error) {
10596
// chaincodeDeploy deploys the chaincode. On success, the chaincode name
10697
// (hash) is printed to STDOUT for use by subsequent chaincode-related CLI
10798
// commands.
108-
func chaincodeDeploy(cmd *cobra.Command, args []string) error {
109-
env, err := deploy(cmd)
99+
func chaincodeDeploy(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
100+
var err error
101+
if cf == nil {
102+
cf, err = InitCmdFactory()
103+
if err != nil {
104+
return err
105+
}
106+
}
107+
defer cf.BroadcastClient.Close()
108+
env, err := deploy(cmd, cf)
110109
if err != nil {
111110
return err
112111
}
113112

114113
if env != nil {
115-
err = sendTransaction(env)
114+
err = cf.BroadcastClient.Send(env)
116115
}
117116

118117
return err

peer/chaincode/invoke.go

+25-13
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,32 @@ import (
2222
"github.com/spf13/cobra"
2323
)
2424

25-
func invokeCmd() *cobra.Command {
26-
return chaincodeInvokeCmd
27-
}
25+
var chaincodeInvokeCmd *cobra.Command
26+
27+
// invokeCmd returns the cobra command for Chaincode Invoke
28+
func invokeCmd(cf *ChaincodeCmdFactory) *cobra.Command {
29+
chaincodeInvokeCmd = &cobra.Command{
30+
Use: "invoke",
31+
Short: fmt.Sprintf("Invoke the specified %s.", chainFuncName),
32+
Long: fmt.Sprintf(`Invoke the specified %s.`, chainFuncName),
33+
ValidArgs: []string{"1"},
34+
RunE: func(cmd *cobra.Command, args []string) error {
35+
return chaincodeInvoke(cmd, args, cf)
36+
},
37+
}
2838

29-
var chaincodeInvokeCmd = &cobra.Command{
30-
Use: "invoke",
31-
Short: fmt.Sprintf("Invoke the specified %s.", chainFuncName),
32-
Long: fmt.Sprintf(`Invoke the specified %s.`, chainFuncName),
33-
ValidArgs: []string{"1"},
34-
RunE: func(cmd *cobra.Command, args []string) error {
35-
return chaincodeInvoke(cmd, args)
36-
},
39+
return chaincodeInvokeCmd
3740
}
3841

39-
func chaincodeInvoke(cmd *cobra.Command, args []string) error {
40-
return chaincodeInvokeOrQuery(cmd, args, true)
42+
func chaincodeInvoke(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
43+
var err error
44+
if cf == nil {
45+
cf, err = InitCmdFactory()
46+
if err != nil {
47+
return err
48+
}
49+
}
50+
defer cf.BroadcastClient.Close()
51+
52+
return chaincodeInvokeOrQuery(cmd, args, true, cf)
4153
}

peer/chaincode/query.go

+25-13
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,20 @@ import (
2222
"github.com/spf13/cobra"
2323
)
2424

25-
func queryCmd() *cobra.Command {
25+
var chaincodeQueryCmd *cobra.Command
26+
27+
// queryCmd returns the cobra command for Chaincode Query
28+
func queryCmd(cf *ChaincodeCmdFactory) *cobra.Command {
29+
chaincodeQueryCmd = &cobra.Command{
30+
Use: "query",
31+
Short: fmt.Sprintf("Query using the specified %s.", chainFuncName),
32+
Long: fmt.Sprintf(`Query using the specified %s.`, chainFuncName),
33+
ValidArgs: []string{"1"},
34+
RunE: func(cmd *cobra.Command, args []string) error {
35+
return chaincodeQuery(cmd, args, cf)
36+
},
37+
}
38+
2639
chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryRaw, "raw", "r", false,
2740
"If true, output the query value as raw bytes, otherwise format as a printable string")
2841
chaincodeQueryCmd.Flags().BoolVarP(&chaincodeQueryHex, "hex", "x", false,
@@ -31,16 +44,15 @@ func queryCmd() *cobra.Command {
3144
return chaincodeQueryCmd
3245
}
3346

34-
var chaincodeQueryCmd = &cobra.Command{
35-
Use: "query",
36-
Short: fmt.Sprintf("Query using the specified %s.", chainFuncName),
37-
Long: fmt.Sprintf(`Query using the specified %s.`, chainFuncName),
38-
ValidArgs: []string{"1"},
39-
RunE: func(cmd *cobra.Command, args []string) error {
40-
return chaincodeQuery(cmd, args)
41-
},
42-
}
43-
44-
func chaincodeQuery(cmd *cobra.Command, args []string) error {
45-
return chaincodeInvokeOrQuery(cmd, args, false)
47+
func chaincodeQuery(cmd *cobra.Command, args []string, cf *ChaincodeCmdFactory) error {
48+
var err error
49+
if cf == nil {
50+
cf, err = InitCmdFactory()
51+
if err != nil {
52+
return err
53+
}
54+
}
55+
defer cf.BroadcastClient.Close()
56+
57+
return chaincodeInvokeOrQuery(cmd, args, false, cf)
4658
}

0 commit comments

Comments
 (0)