mirror of https://github.com/status-im/consul.git
commands: move flag handling into flags pkg
This commit is contained in:
parent
366ec9a565
commit
cef6a80ae6
|
@ -9,7 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/configutil"
|
"github.com/hashicorp/consul/command/flags"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
text "github.com/tonnerre/golang-text"
|
text "github.com/tonnerre/golang-text"
|
||||||
)
|
)
|
||||||
|
@ -39,16 +39,16 @@ type BaseCommand struct {
|
||||||
hidden *flag.FlagSet
|
hidden *flag.FlagSet
|
||||||
|
|
||||||
// These are the options which correspond to the HTTP API options
|
// These are the options which correspond to the HTTP API options
|
||||||
httpAddr configutil.StringValue
|
httpAddr flags.StringValue
|
||||||
token configutil.StringValue
|
token flags.StringValue
|
||||||
caFile configutil.StringValue
|
caFile flags.StringValue
|
||||||
caPath configutil.StringValue
|
caPath flags.StringValue
|
||||||
certFile configutil.StringValue
|
certFile flags.StringValue
|
||||||
keyFile configutil.StringValue
|
keyFile flags.StringValue
|
||||||
tlsServerName configutil.StringValue
|
tlsServerName flags.StringValue
|
||||||
|
|
||||||
datacenter configutil.StringValue
|
datacenter flags.StringValue
|
||||||
stale configutil.BoolValue
|
stale flags.BoolValue
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPClient returns a client with the parsed flags. It panics if the command
|
// HTTPClient returns a client with the parsed flags. It panics if the command
|
||||||
|
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/configutil"
|
"github.com/hashicorp/consul/command/flags"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/ryanuber/columnize"
|
"github.com/ryanuber/columnize"
|
||||||
)
|
)
|
||||||
|
@ -31,7 +31,7 @@ func (c *CatalogListNodesCommand) initFlags() {
|
||||||
c.FlagSet.StringVar(&c.near, "near", "", "Node name to sort the node list in ascending "+
|
c.FlagSet.StringVar(&c.near, "near", "", "Node name to sort the node list in ascending "+
|
||||||
"order based on estimated round-trip time from that node. "+
|
"order based on estimated round-trip time from that node. "+
|
||||||
"Passing \"_agent\" will use this agent's node for sorting.")
|
"Passing \"_agent\" will use this agent's node for sorting.")
|
||||||
c.FlagSet.Var((*configutil.FlagMapValue)(&c.nodeMeta), "node-meta", "Metadata to "+
|
c.FlagSet.Var((*flags.FlagMapValue)(&c.nodeMeta), "node-meta", "Metadata to "+
|
||||||
"filter nodes with the given `key=value` pairs. This flag may be "+
|
"filter nodes with the given `key=value` pairs. This flag may be "+
|
||||||
"specified multiple times to filter on multiple sources of metadata.")
|
"specified multiple times to filter on multiple sources of metadata.")
|
||||||
c.FlagSet.StringVar(&c.service, "service", "", "Service `id or name` to filter nodes. "+
|
c.FlagSet.StringVar(&c.service, "service", "", "Service `id or name` to filter nodes. "+
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/configutil"
|
"github.com/hashicorp/consul/command/flags"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ func (c *CatalogListServicesCommand) initFlags() {
|
||||||
c.InitFlagSet()
|
c.InitFlagSet()
|
||||||
c.FlagSet.StringVar(&c.node, "node", "",
|
c.FlagSet.StringVar(&c.node, "node", "",
|
||||||
"Node `id or name` for which to list services.")
|
"Node `id or name` for which to list services.")
|
||||||
c.FlagSet.Var((*configutil.FlagMapValue)(&c.nodeMeta), "node-meta", "Metadata to "+
|
c.FlagSet.Var((*flags.FlagMapValue)(&c.nodeMeta), "node-meta", "Metadata to "+
|
||||||
"filter nodes with the given `key=value` pairs. If specified, only "+
|
"filter nodes with the given `key=value` pairs. If specified, only "+
|
||||||
"services running on nodes matching the given metadata will be returned. "+
|
"services running on nodes matching the given metadata will be returned. "+
|
||||||
"This flag may be specified multiple times to filter on multiple sources "+
|
"This flag may be specified multiple times to filter on multiple sources "+
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,14 +1,13 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
@ -108,7 +107,7 @@ func TestConfigUtil_Visit(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
basePath := "../test/command/merge"
|
basePath := "../../test/command/merge"
|
||||||
if err := Visit(basePath, visitor); err != nil {
|
if err := Visit(basePath, visitor); err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
|
@ -1,4 +1,4 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package configutil
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
|
@ -0,0 +1,92 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPFlags struct {
|
||||||
|
// client api flags
|
||||||
|
address StringValue
|
||||||
|
token StringValue
|
||||||
|
caFile StringValue
|
||||||
|
caPath StringValue
|
||||||
|
certFile StringValue
|
||||||
|
keyFile StringValue
|
||||||
|
tlsServerName StringValue
|
||||||
|
|
||||||
|
// server flags
|
||||||
|
datacenter StringValue
|
||||||
|
stale BoolValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *HTTPFlags) ClientFlags() *flag.FlagSet {
|
||||||
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
fs.Var(&f.address, "http-addr",
|
||||||
|
"The `address` and port of the Consul HTTP agent. The value can be an IP "+
|
||||||
|
"address or DNS address, but it must also include the port. This can "+
|
||||||
|
"also be specified via the CONSUL_HTTP_ADDR environment variable. The "+
|
||||||
|
"default value is http://127.0.0.1:8500. The scheme can also be set to "+
|
||||||
|
"HTTPS by setting the environment variable CONSUL_HTTP_SSL=true.")
|
||||||
|
fs.Var(&f.token, "token",
|
||||||
|
"ACL token to use in the request. This can also be specified via the "+
|
||||||
|
"CONSUL_HTTP_TOKEN environment variable. If unspecified, the query will "+
|
||||||
|
"default to the token of the Consul agent at the HTTP address.")
|
||||||
|
fs.Var(&f.caFile, "ca-file",
|
||||||
|
"Path to a CA file to use for TLS when communicating with Consul. This "+
|
||||||
|
"can also be specified via the CONSUL_CACERT environment variable.")
|
||||||
|
fs.Var(&f.caPath, "ca-path",
|
||||||
|
"Path to a directory of CA certificates to use for TLS when communicating "+
|
||||||
|
"with Consul. This can also be specified via the CONSUL_CAPATH environment variable.")
|
||||||
|
fs.Var(&f.certFile, "client-cert",
|
||||||
|
"Path to a client cert file to use for TLS when 'verify_incoming' is enabled. This "+
|
||||||
|
"can also be specified via the CONSUL_CLIENT_CERT environment variable.")
|
||||||
|
fs.Var(&f.keyFile, "client-key",
|
||||||
|
"Path to a client key file to use for TLS when 'verify_incoming' is enabled. This "+
|
||||||
|
"can also be specified via the CONSUL_CLIENT_KEY environment variable.")
|
||||||
|
fs.Var(&f.tlsServerName, "tls-server-name",
|
||||||
|
"The server name to use as the SNI host when connecting via TLS. This "+
|
||||||
|
"can also be specified via the CONSUL_TLS_SERVER_NAME environment variable.")
|
||||||
|
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *HTTPFlags) ServerFlags() *flag.FlagSet {
|
||||||
|
fs := flag.NewFlagSet("", flag.ContinueOnError)
|
||||||
|
fs.Var(&f.datacenter, "datacenter",
|
||||||
|
"Name of the datacenter to query. If unspecified, this will default to "+
|
||||||
|
"the datacenter of the queried agent.")
|
||||||
|
fs.Var(&f.stale, "stale",
|
||||||
|
"Permit any Consul server (non-leader) to respond to this request. This "+
|
||||||
|
"allows for lower latency and higher throughput, but can result in "+
|
||||||
|
"stale data. This option has no effect on non-read operations. The "+
|
||||||
|
"default value is false.")
|
||||||
|
return fs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *HTTPFlags) Datacenter() string {
|
||||||
|
return f.datacenter.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *HTTPFlags) Stale() bool {
|
||||||
|
if f.stale.v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *f.stale.v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *HTTPFlags) APIClient() (*api.Client, error) {
|
||||||
|
c := api.DefaultConfig()
|
||||||
|
|
||||||
|
f.address.Merge(&c.Address)
|
||||||
|
f.token.Merge(&c.Token)
|
||||||
|
f.caFile.Merge(&c.TLSConfig.CAFile)
|
||||||
|
f.caPath.Merge(&c.TLSConfig.CAPath)
|
||||||
|
f.certFile.Merge(&c.TLSConfig.CertFile)
|
||||||
|
f.keyFile.Merge(&c.TLSConfig.KeyFile)
|
||||||
|
f.tlsServerName.Merge(&c.TLSConfig.Address)
|
||||||
|
f.datacenter.Merge(&c.Datacenter)
|
||||||
|
|
||||||
|
return api.NewClient(c)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import "flag"
|
||||||
|
|
||||||
|
func Merge(dst, src *flag.FlagSet) {
|
||||||
|
if dst == nil {
|
||||||
|
panic("dst cannot be nil")
|
||||||
|
}
|
||||||
|
if src == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
src.VisitAll(func(f *flag.Flag) {
|
||||||
|
dst.Var(f.Value, f.Name, f.DefValue)
|
||||||
|
})
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
text "github.com/tonnerre/golang-text"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Usage(txt string, cmdFlags, clientFlags, serverFlags *flag.FlagSet) string {
|
||||||
|
u := &Usager{
|
||||||
|
Usage: txt,
|
||||||
|
CmdFlags: cmdFlags,
|
||||||
|
HTTPClientFlags: clientFlags,
|
||||||
|
HTTPServerFlags: serverFlags,
|
||||||
|
}
|
||||||
|
return u.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Usager struct {
|
||||||
|
Usage string
|
||||||
|
CmdFlags *flag.FlagSet
|
||||||
|
HTTPClientFlags *flag.FlagSet
|
||||||
|
HTTPServerFlags *flag.FlagSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *Usager) String() string {
|
||||||
|
out := new(bytes.Buffer)
|
||||||
|
out.WriteString(strings.TrimSpace(u.Usage))
|
||||||
|
out.WriteString("\n")
|
||||||
|
out.WriteString("\n")
|
||||||
|
|
||||||
|
httpFlags := u.HTTPClientFlags
|
||||||
|
if httpFlags == nil {
|
||||||
|
httpFlags = u.HTTPServerFlags
|
||||||
|
} else {
|
||||||
|
Merge(httpFlags, u.HTTPServerFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpFlags != nil {
|
||||||
|
printTitle(out, "HTTP API Options")
|
||||||
|
httpFlags.VisitAll(func(f *flag.Flag) {
|
||||||
|
printFlag(out, f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.CmdFlags != nil {
|
||||||
|
printTitle(out, "Command Options")
|
||||||
|
u.CmdFlags.VisitAll(func(f *flag.Flag) {
|
||||||
|
if flagContains(httpFlags, f) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
printFlag(out, f)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimRight(out.String(), "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// printTitle prints a consistently-formatted title to the given writer.
|
||||||
|
func printTitle(w io.Writer, s string) {
|
||||||
|
fmt.Fprintf(w, "%s\n\n", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// printFlag prints a single flag to the given writer.
|
||||||
|
func printFlag(w io.Writer, f *flag.Flag) {
|
||||||
|
example, _ := flag.UnquoteUsage(f)
|
||||||
|
if example != "" {
|
||||||
|
fmt.Fprintf(w, " -%s=<%s>\n", f.Name, example)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, " -%s\n", f.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
indented := wrapAtLength(f.Usage, 5)
|
||||||
|
fmt.Fprintf(w, "%s\n\n", indented)
|
||||||
|
}
|
||||||
|
|
||||||
|
// flagContains returns true if the given flag is contained in the given flag
|
||||||
|
// set or false otherwise.
|
||||||
|
func flagContains(fs *flag.FlagSet, f *flag.Flag) bool {
|
||||||
|
if fs == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var skip bool
|
||||||
|
fs.VisitAll(func(hf *flag.Flag) {
|
||||||
|
if skip {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if f.Name == hf.Name {
|
||||||
|
skip = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return skip
|
||||||
|
}
|
||||||
|
|
||||||
|
// maxLineLength is the maximum width of any line.
|
||||||
|
const maxLineLength int = 72
|
||||||
|
|
||||||
|
// wrapAtLength wraps the given text at the maxLineLength, taking into account
|
||||||
|
// any provided left padding.
|
||||||
|
func wrapAtLength(s string, pad int) string {
|
||||||
|
wrapped := text.Wrap(s, maxLineLength-pad)
|
||||||
|
lines := strings.Split(wrapped, "\n")
|
||||||
|
for i, line := range lines {
|
||||||
|
lines[i] = strings.Repeat(" ", pad) + line
|
||||||
|
}
|
||||||
|
return strings.Join(lines, "\n")
|
||||||
|
}
|
|
@ -6,20 +6,20 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/hashicorp/consul/configutil"
|
"github.com/hashicorp/consul/command/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OperatorAutopilotSetCommand struct {
|
type OperatorAutopilotSetCommand struct {
|
||||||
BaseCommand
|
BaseCommand
|
||||||
|
|
||||||
// flags
|
// flags
|
||||||
cleanupDeadServers configutil.BoolValue
|
cleanupDeadServers flags.BoolValue
|
||||||
maxTrailingLogs configutil.UintValue
|
maxTrailingLogs flags.UintValue
|
||||||
lastContactThreshold configutil.DurationValue
|
lastContactThreshold flags.DurationValue
|
||||||
serverStabilizationTime configutil.DurationValue
|
serverStabilizationTime flags.DurationValue
|
||||||
redundancyZoneTag configutil.StringValue
|
redundancyZoneTag flags.StringValue
|
||||||
disableUpgradeMigration configutil.BoolValue
|
disableUpgradeMigration flags.BoolValue
|
||||||
upgradeVersionTag configutil.StringValue
|
upgradeVersionTag flags.StringValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OperatorAutopilotSetCommand) initFlags() {
|
func (c *OperatorAutopilotSetCommand) initFlags() {
|
||||||
|
|
Loading…
Reference in New Issue