Skip to content

Commit dace3b2

Browse files
guogerwlahti
authored andcommitted
[FAB-2167] Categorize peer CLI flags
This patch categorizes flags associated to `peer [CMD]` so that CLI help message is more expressive. With this change, only neccessary flags for a individual sub-command are listed, instead of all flags available for root command, i.e. `chaincode`, `channel`. PersistentFlags are removed in favor of local flags. To facilitate flag sharing, e.g. `peer channel create` and `peer channel udpate` share the flag `--channelID`, all available flags are maintained in a map, and could be simply looked up and attached to specific sub-command. We avoid duplicating code when adding new flags to individual sub-commands. Change-Id: I11217e567a345417ebaf66d315d6dcaa1176e0f1 Signed-off-by: Jay Guo <[email protected]>
1 parent f5dbbaf commit dace3b2

25 files changed

+310
-194
lines changed

peer/chaincode/chaincode.go

+52-28
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/hyperledger/fabric/common/util"
2424
"github.com/hyperledger/fabric/peer/common"
2525
"github.com/spf13/cobra"
26+
"github.com/spf13/pflag"
2627
)
2728

2829
const (
@@ -33,47 +34,25 @@ const (
3334

3435
var logger = flogging.MustGetLogger("chaincodeCmd")
3536

36-
func AddFlags(cmd *cobra.Command) {
37+
func addFlags(cmd *cobra.Command) {
3738
flags := cmd.PersistentFlags()
3839

39-
flags.StringVarP(&chaincodeLang, "lang", "l", "golang",
40-
fmt.Sprintf("Language the %s is written in", chainFuncName))
41-
flags.StringVarP(&chaincodeCtorJSON, "ctor", "c", "{}",
42-
fmt.Sprintf("Constructor message for the %s in JSON format", chainFuncName))
43-
flags.StringVarP(&chaincodePath, "path", "p", common.UndefinedParamValue,
44-
fmt.Sprintf("Path to %s", chainFuncName))
45-
flags.StringVarP(&chaincodeName, "name", "n", common.UndefinedParamValue,
46-
fmt.Sprint("Name of the chaincode"))
47-
flags.StringVarP(&chaincodeVersion, "version", "v", common.UndefinedParamValue,
48-
fmt.Sprint("Version of the chaincode specified in install/instantiate/upgrade commands"))
49-
flags.StringVarP(&chaincodeUsr, "username", "u", common.UndefinedParamValue,
50-
fmt.Sprint("Username for chaincode operations when security is enabled"))
51-
flags.StringVarP(&customIDGenAlg, "tid", "t", common.UndefinedParamValue,
52-
fmt.Sprint("Name of a custom ID generation algorithm (hashing and decoding) e.g. sha256base64"))
53-
flags.StringVarP(&chainID, "chainID", "C", util.GetTestChainID(),
54-
fmt.Sprint("The chain on which this command should be executed"))
55-
flags.StringVarP(&policy, "policy", "P", common.UndefinedParamValue,
56-
fmt.Sprint("The endorsement policy associated to this chaincode"))
57-
flags.StringVarP(&escc, "escc", "E", common.UndefinedParamValue,
58-
fmt.Sprint("The name of the endorsement system chaincode to be used for this chaincode"))
59-
flags.StringVarP(&vscc, "vscc", "V", common.UndefinedParamValue,
60-
fmt.Sprint("The name of the verification system chaincode to be used for this chaincode"))
6140
flags.StringVarP(&orderingEndpoint, "orderer", "o", "", "Ordering service endpoint")
6241
flags.BoolVarP(&tls, "tls", "", false, "Use TLS when communicating with the orderer endpoint")
6342
flags.StringVarP(&caFile, "cafile", "", "", "Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint")
6443
}
6544

6645
// Cmd returns the cobra command for Chaincode
6746
func Cmd(cf *ChaincodeCmdFactory) *cobra.Command {
68-
AddFlags(chaincodeCmd)
47+
addFlags(chaincodeCmd)
6948

49+
chaincodeCmd.AddCommand(installCmd(cf))
7050
chaincodeCmd.AddCommand(instantiateCmd(cf))
7151
chaincodeCmd.AddCommand(invokeCmd(cf))
72-
chaincodeCmd.AddCommand(queryCmd(cf))
73-
chaincodeCmd.AddCommand(upgradeCmd(cf))
7452
chaincodeCmd.AddCommand(packageCmd(cf, nil))
75-
chaincodeCmd.AddCommand(installCmd(cf))
53+
chaincodeCmd.AddCommand(queryCmd(cf))
7654
chaincodeCmd.AddCommand(signpackageCmd(cf))
55+
chaincodeCmd.AddCommand(upgradeCmd(cf))
7756

7857
return chaincodeCmd
7958
}
@@ -84,7 +63,7 @@ var (
8463
chaincodeCtorJSON string
8564
chaincodePath string
8665
chaincodeName string
87-
chaincodeUsr string
66+
chaincodeUsr string // Not used
8867
chaincodeQueryRaw bool
8968
chaincodeQueryHex bool
9069
customIDGenAlg string
@@ -104,3 +83,48 @@ var chaincodeCmd = &cobra.Command{
10483
Short: fmt.Sprint(shortDes),
10584
Long: fmt.Sprint(longDes),
10685
}
86+
87+
var flags *pflag.FlagSet
88+
89+
func init() {
90+
resetFlags()
91+
}
92+
93+
// Explicitly define a method to facilitate tests
94+
func resetFlags() {
95+
flags = &pflag.FlagSet{}
96+
97+
flags.StringVarP(&chaincodeLang, "lang", "l", "golang",
98+
fmt.Sprintf("Language the %s is written in", chainFuncName))
99+
flags.StringVarP(&chaincodeCtorJSON, "ctor", "c", "{}",
100+
fmt.Sprintf("Constructor message for the %s in JSON format", chainFuncName))
101+
flags.StringVarP(&chaincodePath, "path", "p", common.UndefinedParamValue,
102+
fmt.Sprintf("Path to %s", chainFuncName))
103+
flags.StringVarP(&chaincodeName, "name", "n", common.UndefinedParamValue,
104+
fmt.Sprint("Name of the chaincode"))
105+
flags.StringVarP(&chaincodeVersion, "version", "v", common.UndefinedParamValue,
106+
fmt.Sprint("Version of the chaincode specified in install/instantiate/upgrade commands"))
107+
flags.StringVarP(&chaincodeUsr, "username", "u", common.UndefinedParamValue,
108+
fmt.Sprint("Username for chaincode operations when security is enabled"))
109+
flags.StringVarP(&customIDGenAlg, "tid", "t", common.UndefinedParamValue,
110+
fmt.Sprint("Name of a custom ID generation algorithm (hashing and decoding) e.g. sha256base64"))
111+
flags.StringVarP(&chainID, "channelID", "C", util.GetTestChainID(),
112+
fmt.Sprint("The channel on which this command should be executed"))
113+
flags.StringVarP(&policy, "policy", "P", common.UndefinedParamValue,
114+
fmt.Sprint("The endorsement policy associated to this chaincode"))
115+
flags.StringVarP(&escc, "escc", "E", common.UndefinedParamValue,
116+
fmt.Sprint("The name of the endorsement system chaincode to be used for this chaincode"))
117+
flags.StringVarP(&vscc, "vscc", "V", common.UndefinedParamValue,
118+
fmt.Sprint("The name of the verification system chaincode to be used for this chaincode"))
119+
}
120+
121+
func attachFlags(cmd *cobra.Command, names []string) {
122+
cmdFlags := cmd.Flags()
123+
for _, name := range names {
124+
if flag := flags.Lookup(name); flag != nil {
125+
cmdFlags.AddFlag(flag)
126+
} else {
127+
logger.Fatalf("Could not find flag '%s' to attach to commond '%s'", name, cmd.Name())
128+
}
129+
}
130+
}

peer/chaincode/common.go

+36-40
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,14 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *
102102
return err
103103
}
104104

105-
proposalResp, err := ChaincodeInvokeOrQuery(spec, chainID, invoke,
106-
cf.Signer, cf.EndorserClient, cf.BroadcastClient)
105+
proposalResp, err := ChaincodeInvokeOrQuery(
106+
spec,
107+
chainID,
108+
invoke,
109+
cf.Signer,
110+
cf.EndorserClient,
111+
cf.BroadcastClient)
112+
107113
if err != nil {
108114
return fmt.Errorf("%s - %v", err, proposalResp)
109115
}
@@ -139,8 +145,7 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *
139145

140146
if chaincodeQueryRaw {
141147
if chaincodeQueryHex {
142-
err = errors.New("Options --raw (-r) and --hex (-x) are not compatible")
143-
return
148+
return fmt.Errorf("Options --raw (-r) and --hex (-x) are not compatible")
144149
}
145150
fmt.Print("Query Result (Raw): ")
146151
os.Stdout.Write(proposalResp.Response.Payload)
@@ -152,7 +157,7 @@ func chaincodeInvokeOrQuery(cmd *cobra.Command, args []string, invoke bool, cf *
152157
}
153158
}
154159
}
155-
return err
160+
return nil
156161
}
157162

158163
func checkChaincodeCmdParams(cmd *cobra.Command) error {
@@ -161,48 +166,33 @@ func checkChaincodeCmdParams(cmd *cobra.Command) error {
161166
return fmt.Errorf("Must supply value for %s name parameter.", chainFuncName)
162167
}
163168

164-
if cmd.Name() == instantiate_cmdname || cmd.Name() == install_cmdname ||
165-
cmd.Name() == upgrade_cmdname || cmd.Name() == package_cmdname {
169+
if cmd.Name() == instantiateCmdName || cmd.Name() == installCmdName ||
170+
cmd.Name() == upgradeCmdName || cmd.Name() == packageCmdName {
166171
if chaincodeVersion == common.UndefinedParamValue {
167172
return fmt.Errorf("Chaincode version is not provided for %s", cmd.Name())
168173
}
169174
}
170175

171-
// if it's not a deploy or an upgrade we don't need policy, escc and vscc
172-
if cmd.Name() != instantiate_cmdname && cmd.Name() != upgrade_cmdname {
173-
if escc != common.UndefinedParamValue {
174-
return errors.New("escc should be supplied only to chaincode deploy requests")
175-
}
176-
177-
if vscc != common.UndefinedParamValue {
178-
return errors.New("vscc should be supplied only to chaincode deploy requests")
179-
}
180-
181-
if policy != common.UndefinedParamValue {
182-
return errors.New("policy should be supplied only to chaincode deploy requests")
183-
}
176+
if escc != common.UndefinedParamValue {
177+
logger.Infof("Using escc %s", escc)
184178
} else {
185-
if escc != common.UndefinedParamValue {
186-
logger.Infof("Using escc %s", escc)
187-
} else {
188-
logger.Info("Using default escc")
189-
escc = "escc"
190-
}
179+
logger.Info("Using default escc")
180+
escc = "escc"
181+
}
191182

192-
if vscc != common.UndefinedParamValue {
193-
logger.Infof("Using vscc %s", vscc)
194-
} else {
195-
logger.Info("Using default vscc")
196-
vscc = "vscc"
197-
}
183+
if vscc != common.UndefinedParamValue {
184+
logger.Infof("Using vscc %s", vscc)
185+
} else {
186+
logger.Info("Using default vscc")
187+
vscc = "vscc"
188+
}
198189

199-
if policy != common.UndefinedParamValue {
200-
p, err := cauthdsl.FromString(policy)
201-
if err != nil {
202-
return fmt.Errorf("Invalid policy %s", policy)
203-
}
204-
policyMarhsalled = putils.MarshalOrPanic(p)
190+
if policy != common.UndefinedParamValue {
191+
p, err := cauthdsl.FromString(policy)
192+
if err != nil {
193+
return fmt.Errorf("Invalid policy %s", policy)
205194
}
195+
policyMarhsalled = putils.MarshalOrPanic(p)
206196
}
207197

208198
// Check that non-empty chaincode parameters contain only Args as a key.
@@ -294,8 +284,14 @@ func InitCmdFactory(isEndorserRequired, isOrdererRequired bool) (*ChaincodeCmdFa
294284
//
295285
// NOTE - Query will likely go away as all interactions with the endorser are
296286
// Proposal and ProposalResponses
297-
func ChaincodeInvokeOrQuery(spec *pb.ChaincodeSpec, cID string, invoke bool,
298-
signer msp.SigningIdentity, endorserClient pb.EndorserClient, bc common.BroadcastClient) (*pb.ProposalResponse, error) {
287+
func ChaincodeInvokeOrQuery(
288+
spec *pb.ChaincodeSpec,
289+
cID string,
290+
invoke bool,
291+
signer msp.SigningIdentity,
292+
endorserClient pb.EndorserClient,
293+
bc common.BroadcastClient,
294+
) (*pb.ProposalResponse, error) {
299295
// Build the ChaincodeInvocationSpec message
300296
invocation := &pb.ChaincodeInvocationSpec{ChaincodeSpec: spec}
301297
if customIDGenAlg != common.UndefinedParamValue {

peer/chaincode/install.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@ import (
3535

3636
var chaincodeInstallCmd *cobra.Command
3737

38-
const install_cmdname = "install"
38+
const installCmdName = "install"
3939

40-
const install_desc = "Package the specified chaincode into a deployment spec and save it on the peer's path."
40+
const installDesc = "Package the specified chaincode into a deployment spec and save it on the peer's path."
4141

4242
// installCmd returns the cobra command for Chaincode Deploy
4343
func installCmd(cf *ChaincodeCmdFactory) *cobra.Command {
4444
chaincodeInstallCmd = &cobra.Command{
4545
Use: "install",
46-
Short: fmt.Sprint(install_desc),
47-
Long: fmt.Sprint(install_desc),
46+
Short: fmt.Sprint(installDesc),
47+
Long: fmt.Sprint(installDesc),
4848
ValidArgs: []string{"1"},
4949
RunE: func(cmd *cobra.Command, args []string) error {
5050
var ccpackfile string
@@ -54,6 +54,14 @@ func installCmd(cf *ChaincodeCmdFactory) *cobra.Command {
5454
return chaincodeInstall(cmd, ccpackfile, cf)
5555
},
5656
}
57+
flagList := []string{
58+
"lang",
59+
"ctor",
60+
"path",
61+
"name",
62+
"version",
63+
}
64+
attachFlags(chaincodeInstallCmd, flagList)
5765

5866
return chaincodeInstallCmd
5967
}

peer/chaincode/install_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func initInstallTest(fsPath string, t *testing.T) (*cobra.Command, *ChaincodeCmd
5050
}
5151

5252
cmd := installCmd(mockCF)
53-
AddFlags(cmd)
53+
addFlags(cmd)
5454

5555
return cmd, mockCF
5656
}
@@ -179,7 +179,7 @@ func installEx02() error {
179179
}
180180

181181
cmd := installCmd(mockCF)
182-
AddFlags(cmd)
182+
addFlags(cmd)
183183

184184
args := []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02", "-v", "anotherversion"}
185185
cmd.SetArgs(args)

peer/chaincode/instantiate.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,32 @@ import (
2828

2929
var chaincodeInstantiateCmd *cobra.Command
3030

31-
const instantiate_cmdname = "instantiate"
31+
const instantiateCmdName = "instantiate"
3232

33-
const instantiate_desc = "Deploy the specified chaincode to the network."
33+
const instantiateDesc = "Deploy the specified chaincode to the network."
3434

3535
// instantiateCmd returns the cobra command for Chaincode Deploy
3636
func instantiateCmd(cf *ChaincodeCmdFactory) *cobra.Command {
3737
chaincodeInstantiateCmd = &cobra.Command{
38-
Use: instantiate_cmdname,
39-
Short: fmt.Sprint(instantiate_desc),
40-
Long: fmt.Sprint(instantiate_desc),
38+
Use: instantiateCmdName,
39+
Short: fmt.Sprint(instantiateDesc),
40+
Long: fmt.Sprint(instantiateDesc),
4141
ValidArgs: []string{"1"},
4242
RunE: func(cmd *cobra.Command, args []string) error {
4343
return chaincodeDeploy(cmd, args, cf)
4444
},
4545
}
46+
flagList := []string{
47+
"lang",
48+
"ctor",
49+
"name",
50+
"channelID",
51+
"version",
52+
"policy",
53+
"escc",
54+
"vscc",
55+
}
56+
attachFlags(chaincodeInstantiateCmd, flagList)
4657

4758
return chaincodeInstantiateCmd
4859
}

peer/chaincode/instantiate_test.go

+18-13
Original file line numberDiff line numberDiff line change
@@ -30,46 +30,51 @@ func TestInstantiateCmd(t *testing.T) {
3030

3131
// basic function tests
3232
var tests = []struct {
33+
name string
3334
args []string
3435
errorExpected bool
3536
errMsg string
3637
}{
3738
{
38-
args: []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02",
39-
"-v", "anotherversion", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
39+
name: "successful",
40+
args: []string{"-n", "example02", "-v", "anotherversion", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
4041
errorExpected: false,
4142
errMsg: "Run chaincode instantiate cmd error",
4243
},
4344
{
45+
name: "no option",
4446
args: []string{},
4547
errorExpected: true,
4648
errMsg: "Expected error executing instantiate command without required options",
4749
},
4850
{
49-
args: []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02",
50-
"-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
51+
name: "missing version",
52+
args: []string{"-n", "example02", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
5153
errorExpected: true,
5254
errMsg: "Expected error executing instantiate command without the -v option",
5355
},
5456
{
55-
args: []string{"-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02",
56-
"-v", "anotherversion", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
57+
name: "missing name",
58+
args: []string{"-v", "anotherversion", "-c", "{\"Args\": [\"init\",\"a\",\"100\",\"b\",\"200\"]}"},
5759
errorExpected: true,
5860
errMsg: "Expected error executing instantiate command without the -n option",
5961
},
6062
{
61-
args: []string{"-n", "example02", "-p", "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02",
62-
"-v", "anotherversion"},
63+
name: "missing ctor",
64+
args: []string{"-n", "example02", "-v", "anotherversion"},
6365
errorExpected: true,
6466
errMsg: "Expected error executing instantiate command without the -c option",
6567
},
6668
}
6769
for _, test := range tests {
68-
cmd := instantiateCmd(mockCF)
69-
AddFlags(cmd)
70-
cmd.SetArgs(test.args)
71-
err = cmd.Execute()
72-
checkError(t, err, test.errorExpected, test.errMsg)
70+
t.Run(test.name, func(t *testing.T) {
71+
resetFlags()
72+
cmd := instantiateCmd(mockCF)
73+
addFlags(cmd)
74+
cmd.SetArgs(test.args)
75+
err = cmd.Execute()
76+
checkError(t, err, test.errorExpected, test.errMsg)
77+
})
7378
}
7479
}
7580

0 commit comments

Comments
 (0)