Skip to content

Commit 3e92a81

Browse files
committed
etcdctl: refactor global flags management and simplify command initialization
Signed-off-by: hwdef <[email protected]>
1 parent 7b1f0f2 commit 3e92a81

File tree

2 files changed

+57
-130
lines changed

2 files changed

+57
-130
lines changed

etcdctl/ctlv3/command/global.go

Lines changed: 51 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,34 @@ type discoveryCfg struct {
7171

7272
var display printer = &simplePrinter{}
7373

74+
var globalFlags GlobalFlags
75+
76+
func RegisterGlobalFlags(cmd *cobra.Command) {
77+
cmd.PersistentFlags().StringSliceVar(&globalFlags.Endpoints, "endpoints", []string{"127.0.0.1:2379"}, "gRPC endpoints")
78+
cmd.PersistentFlags().BoolVar(&globalFlags.Debug, "debug", false, "enable client-side debug logging")
79+
cmd.PersistentFlags().StringVarP(&globalFlags.OutputFormat, "write-out", "w", "simple", "set the output format (fields, json, protobuf, simple, table)")
80+
cmd.PersistentFlags().BoolVar(&globalFlags.IsHex, "hex", false, "print byte strings as hex encoded strings")
81+
cmd.PersistentFlags().DurationVar(&globalFlags.DialTimeout, "dial-timeout", 2*time.Second, "dial timeout for client connections")
82+
cmd.PersistentFlags().DurationVar(&globalFlags.CommandTimeOut, "command-timeout", 5*time.Second, "timeout for short running command (excluding dial timeout)")
83+
cmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTime, "keepalive-time", 2*time.Second, "keepalive time for client connections")
84+
cmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTimeout, "keepalive-timeout", 6*time.Second, "keepalive timeout for client connections")
85+
cmd.PersistentFlags().IntVar(&globalFlags.MaxCallSendMsgSize, "max-request-bytes", 0, "client-side request send limit in bytes (if 0, it defaults to 2.0 MiB (2 * 1024 * 1024).)")
86+
cmd.PersistentFlags().IntVar(&globalFlags.MaxCallRecvMsgSize, "max-recv-bytes", 0, "client-side response receive limit in bytes (if 0, it defaults to \"math.MaxInt32\")")
87+
cmd.PersistentFlags().BoolVar(&globalFlags.Insecure, "insecure-transport", true, "disable transport security for client connections")
88+
cmd.PersistentFlags().BoolVar(&globalFlags.InsecureDiscovery, "insecure-discovery", true, "accept insecure SRV records describing cluster endpoints")
89+
cmd.PersistentFlags().BoolVar(&globalFlags.InsecureSkipVerify, "insecure-skip-tls-verify", false, "skip server certificate verification (CAUTION: this option should be enabled only for testing purposes)")
90+
cmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
91+
cmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
92+
cmd.PersistentFlags().StringVar(&globalFlags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
93+
cmd.PersistentFlags().StringVar(&globalFlags.Token, "auth-jwt-token", "", "JWT token used for authentication (if this option is used, --user and --password should not be set)")
94+
cmd.PersistentFlags().StringVar(&globalFlags.User, "user", "", "username[:password] for authentication (prompt if password is not supplied)")
95+
cmd.PersistentFlags().StringVar(&globalFlags.Password, "password", "", "password for authentication (if this option is used, --user option shouldn't include password)")
96+
cmd.PersistentFlags().StringVarP(&globalFlags.TLS.ServerName, "discovery-srv", "d", "", "domain name to query for SRV records describing cluster endpoints")
97+
cmd.PersistentFlags().StringVar(&globalFlags.DNSClusterServiceName, "discovery-srv-name", "", "service name to query when using DNS discovery")
98+
}
99+
74100
func initDisplayFromCmd(cmd *cobra.Command) {
75-
isHex, err := cmd.Flags().GetBool("hex")
76-
if err != nil {
77-
cobrautl.ExitWithError(cobrautl.ExitError, err)
78-
}
79-
outputType, err := cmd.Flags().GetString("write-out")
80-
if err != nil {
81-
cobrautl.ExitWithError(cobrautl.ExitError, err)
82-
}
83-
if display = NewPrinter(outputType, isHex); display == nil {
101+
if display = NewPrinter(globalFlags.OutputFormat, globalFlags.IsHex); display == nil {
84102
cobrautl.ExitWithError(cobrautl.ExitBadFeature, errors.New("unsupported output format"))
85103
}
86104
}
@@ -105,11 +123,7 @@ func clientConfigFromCmd(cmd *cobra.Command) *clientv3.ConfigSpec {
105123
}
106124
flags.SetPflagsFromEnv(lg, "ETCDCTL", fs)
107125

108-
debug, err := cmd.Flags().GetBool("debug")
109-
if err != nil {
110-
cobrautl.ExitWithError(cobrautl.ExitError, err)
111-
}
112-
if debug {
126+
if globalFlags.Debug {
113127
grpclog.SetLoggerV2(grpclog.NewLoggerV2WithVerbosity(os.Stderr, os.Stderr, os.Stderr, 4))
114128
fs.VisitAll(func(f *pflag.Flag) {
115129
fmt.Fprintf(os.Stderr, "%s=%v\n", flags.FlagToEnv("ETCDCTL", f.Name), f.Value)
@@ -183,43 +197,23 @@ func argOrStdin(args []string, stdin io.Reader, i int) (string, error) {
183197
}
184198

185199
func dialTimeoutFromCmd(cmd *cobra.Command) time.Duration {
186-
dialTimeout, err := cmd.Flags().GetDuration("dial-timeout")
187-
if err != nil {
188-
cobrautl.ExitWithError(cobrautl.ExitError, err)
189-
}
190-
return dialTimeout
200+
return globalFlags.DialTimeout
191201
}
192202

193203
func keepAliveTimeFromCmd(cmd *cobra.Command) time.Duration {
194-
keepAliveTime, err := cmd.Flags().GetDuration("keepalive-time")
195-
if err != nil {
196-
cobrautl.ExitWithError(cobrautl.ExitError, err)
197-
}
198-
return keepAliveTime
204+
return globalFlags.KeepAliveTime
199205
}
200206

201207
func keepAliveTimeoutFromCmd(cmd *cobra.Command) time.Duration {
202-
keepAliveTimeout, err := cmd.Flags().GetDuration("keepalive-timeout")
203-
if err != nil {
204-
cobrautl.ExitWithError(cobrautl.ExitError, err)
205-
}
206-
return keepAliveTimeout
208+
return globalFlags.KeepAliveTimeout
207209
}
208210

209211
func maxCallSendMsgSizeFromCmd(cmd *cobra.Command) int {
210-
maxRequestBytes, err := cmd.Flags().GetInt("max-request-bytes")
211-
if err != nil {
212-
cobrautl.ExitWithError(cobrautl.ExitError, err)
213-
}
214-
return maxRequestBytes
212+
return globalFlags.MaxCallSendMsgSize
215213
}
216214

217215
func maxCallRecvMsgSizeFromCmd(cmd *cobra.Command) int {
218-
maxReceiveBytes, err := cmd.Flags().GetInt("max-recv-bytes")
219-
if err != nil {
220-
cobrautl.ExitWithError(cobrautl.ExitError, err)
221-
}
222-
return maxReceiveBytes
216+
return globalFlags.MaxCallRecvMsgSize
223217
}
224218

225219
func secureCfgFromCmd(cmd *cobra.Command) *clientv3.SecureConfig {
@@ -244,57 +238,37 @@ func secureCfgFromCmd(cmd *cobra.Command) *clientv3.SecureConfig {
244238
}
245239

246240
func insecureTransportFromCmd(cmd *cobra.Command) bool {
247-
insecureTr, err := cmd.Flags().GetBool("insecure-transport")
248-
if err != nil {
249-
cobrautl.ExitWithError(cobrautl.ExitError, err)
250-
}
251-
return insecureTr
241+
return globalFlags.Insecure
252242
}
253243

254244
func insecureSkipVerifyFromCmd(cmd *cobra.Command) bool {
255-
skipVerify, err := cmd.Flags().GetBool("insecure-skip-tls-verify")
256-
if err != nil {
257-
cobrautl.ExitWithError(cobrautl.ExitError, err)
258-
}
259-
return skipVerify
245+
return globalFlags.InsecureSkipVerify
260246
}
261247

262248
func keyAndCertFromCmd(cmd *cobra.Command) (cert, key, cacert string) {
263-
var err error
264-
if cert, err = cmd.Flags().GetString("cert"); err != nil {
265-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
266-
} else if cert == "" && cmd.Flags().Changed("cert") {
249+
cert = globalFlags.TLS.CertFile
250+
if cert == "" && cmd.Flags().Changed("cert") {
267251
cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("empty string is passed to --cert option"))
268252
}
269253

270-
if key, err = cmd.Flags().GetString("key"); err != nil {
271-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
272-
} else if key == "" && cmd.Flags().Changed("key") {
254+
key = globalFlags.TLS.KeyFile
255+
if key == "" && cmd.Flags().Changed("key") {
273256
cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("empty string is passed to --key option"))
274257
}
275258

276-
if cacert, err = cmd.Flags().GetString("cacert"); err != nil {
277-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
278-
} else if cacert == "" && cmd.Flags().Changed("cacert") {
259+
cacert = globalFlags.TLS.TrustedCAFile
260+
if cacert == "" && cmd.Flags().Changed("cacert") {
279261
cobrautl.ExitWithError(cobrautl.ExitBadArgs, errors.New("empty string is passed to --cacert option"))
280262
}
281263

282264
return cert, key, cacert
283265
}
284266

285267
func authCfgFromCmd(cmd *cobra.Command) *clientv3.AuthConfig {
286-
userFlag, err := cmd.Flags().GetString("user")
287-
if err != nil {
288-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
289-
}
290-
passwordFlag, err := cmd.Flags().GetString("password")
291-
if err != nil {
292-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
293-
}
294-
tokenFlag, err := cmd.Flags().GetString("auth-jwt-token")
295-
if err != nil {
296-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
297-
}
268+
userFlag := globalFlags.User
269+
passwordFlag := globalFlags.Password
270+
tokenFlag := globalFlags.Token
271+
var err error
298272

299273
if userFlag == "" && tokenFlag == "" {
300274
return nil
@@ -328,27 +302,15 @@ func authCfgFromCmd(cmd *cobra.Command) *clientv3.AuthConfig {
328302
}
329303

330304
func insecureDiscoveryFromCmd(cmd *cobra.Command) bool {
331-
discovery, err := cmd.Flags().GetBool("insecure-discovery")
332-
if err != nil {
333-
cobrautl.ExitWithError(cobrautl.ExitError, err)
334-
}
335-
return discovery
305+
return globalFlags.InsecureDiscovery
336306
}
337307

338308
func discoverySrvFromCmd(cmd *cobra.Command) string {
339-
domainStr, err := cmd.Flags().GetString("discovery-srv")
340-
if err != nil {
341-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
342-
}
343-
return domainStr
309+
return globalFlags.TLS.ServerName
344310
}
345311

346312
func discoveryDNSClusterServiceNameFromCmd(cmd *cobra.Command) string {
347-
serviceNameStr, err := cmd.Flags().GetString("discovery-srv-name")
348-
if err != nil {
349-
cobrautl.ExitWithError(cobrautl.ExitBadArgs, err)
350-
}
351-
return serviceNameStr
313+
return globalFlags.DNSClusterServiceName
352314
}
353315

354316
func discoveryCfgFromCmd(cmd *cobra.Command) *discoveryCfg {
@@ -366,11 +328,9 @@ func endpointsFromCmd(cmd *cobra.Command) ([]string, error) {
366328
}
367329
// If domain discovery returns no endpoints, check endpoints flag
368330
if len(eps) == 0 {
369-
eps, err = cmd.Flags().GetStringSlice("endpoints")
370-
if err == nil {
371-
for i, ip := range eps {
372-
eps[i] = strings.TrimSpace(ip)
373-
}
331+
eps = globalFlags.Endpoints
332+
for i, ip := range eps {
333+
eps[i] = strings.TrimSpace(ip)
374334
}
375335
}
376336
return eps, err

etcdctl/ctlv3/ctl.go

Lines changed: 6 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package ctlv3
1818
import (
1919
"fmt"
2020
"os"
21-
"time"
2221

2322
"github.com/spf13/cobra"
2423
"github.com/spf13/pflag"
@@ -30,52 +29,20 @@ import (
3029
const (
3130
cliName = "etcdctl"
3231
cliDescription = "A simple command line client for etcd3."
33-
34-
defaultDialTimeout = 2 * time.Second
35-
defaultCommandTimeOut = 5 * time.Second
36-
defaultKeepAliveTime = 2 * time.Second
37-
defaultKeepAliveTimeOut = 6 * time.Second
3832
)
3933

40-
var (
41-
globalFlags = command.GlobalFlags{}
42-
rootCmd = &cobra.Command{
43-
Use: cliName,
44-
Short: cliDescription,
45-
SuggestFor: []string{"etcdctl"},
46-
}
47-
)
34+
var rootCmd = &cobra.Command{
35+
Use: cliName,
36+
Short: cliDescription,
37+
SuggestFor: []string{"etcdctl"},
38+
}
4839

4940
func init() {
50-
rootCmd.PersistentFlags().StringSliceVar(&globalFlags.Endpoints, "endpoints", []string{"127.0.0.1:2379"}, "gRPC endpoints")
51-
rootCmd.PersistentFlags().BoolVar(&globalFlags.Debug, "debug", false, "enable client-side debug logging")
52-
53-
rootCmd.PersistentFlags().StringVarP(&globalFlags.OutputFormat, "write-out", "w", "simple", "set the output format (fields, json, protobuf, simple, table)")
54-
rootCmd.PersistentFlags().BoolVar(&globalFlags.IsHex, "hex", false, "print byte strings as hex encoded strings")
41+
command.RegisterGlobalFlags(rootCmd)
5542
rootCmd.RegisterFlagCompletionFunc("write-out", func(_ *cobra.Command, _ []string, _ string) ([]string, cobra.ShellCompDirective) {
5643
return []string{"fields", "json", "protobuf", "simple", "table"}, cobra.ShellCompDirectiveDefault
5744
})
5845

59-
rootCmd.PersistentFlags().DurationVar(&globalFlags.DialTimeout, "dial-timeout", defaultDialTimeout, "dial timeout for client connections")
60-
rootCmd.PersistentFlags().DurationVar(&globalFlags.CommandTimeOut, "command-timeout", defaultCommandTimeOut, "timeout for short running command (excluding dial timeout)")
61-
rootCmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTime, "keepalive-time", defaultKeepAliveTime, "keepalive time for client connections")
62-
rootCmd.PersistentFlags().DurationVar(&globalFlags.KeepAliveTimeout, "keepalive-timeout", defaultKeepAliveTimeOut, "keepalive timeout for client connections")
63-
rootCmd.PersistentFlags().IntVar(&globalFlags.MaxCallSendMsgSize, "max-request-bytes", 0, "client-side request send limit in bytes (if 0, it defaults to 2.0 MiB (2 * 1024 * 1024).)")
64-
rootCmd.PersistentFlags().IntVar(&globalFlags.MaxCallRecvMsgSize, "max-recv-bytes", 0, "client-side response receive limit in bytes (if 0, it defaults to \"math.MaxInt32\")")
65-
66-
// TODO: secure by default when etcd enables secure gRPC by default.
67-
rootCmd.PersistentFlags().BoolVar(&globalFlags.Insecure, "insecure-transport", true, "disable transport security for client connections")
68-
rootCmd.PersistentFlags().BoolVar(&globalFlags.InsecureDiscovery, "insecure-discovery", true, "accept insecure SRV records describing cluster endpoints")
69-
rootCmd.PersistentFlags().BoolVar(&globalFlags.InsecureSkipVerify, "insecure-skip-tls-verify", false, "skip server certificate verification (CAUTION: this option should be enabled only for testing purposes)")
70-
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
71-
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
72-
rootCmd.PersistentFlags().StringVar(&globalFlags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
73-
rootCmd.PersistentFlags().StringVar(&globalFlags.Token, "auth-jwt-token", "", "JWT token used for authentication (if this option is used, --user and --password should not be set)")
74-
rootCmd.PersistentFlags().StringVar(&globalFlags.User, "user", "", "username[:password] for authentication (prompt if password is not supplied)")
75-
rootCmd.PersistentFlags().StringVar(&globalFlags.Password, "password", "", "password for authentication (if this option is used, --user option shouldn't include password)")
76-
rootCmd.PersistentFlags().StringVarP(&globalFlags.TLS.ServerName, "discovery-srv", "d", "", "domain name to query for SRV records describing cluster endpoints")
77-
rootCmd.PersistentFlags().StringVarP(&globalFlags.DNSClusterServiceName, "discovery-srv-name", "", "", "service name to query when using DNS discovery")
78-
7946
rootCmd.AddGroup(
8047
command.NewKVGroup(),
8148
command.NewClusterMaintenanceGroup(),

0 commit comments

Comments
 (0)