Merge branch 'master' into f-cli-rework-3
This commit is contained in:
commit
955d1b983d
|
@ -14,6 +14,8 @@ IMPROVEMENTS:
|
|||
|
||||
BUG FIXES:
|
||||
|
||||
* cli: Fixed `kv` commands not reading the `CONSUL_HTTP_TOKEN` environment variable. [GH-2566]
|
||||
|
||||
## 0.7.4 (February 6, 2017)
|
||||
|
||||
IMPROVEMENTS:
|
||||
|
|
16
api/api.go
16
api/api.go
|
@ -79,6 +79,11 @@ type QueryOptions struct {
|
|||
// metadata key/value pairs. Currently, only one key/value pair can
|
||||
// be provided for filtering.
|
||||
NodeMeta map[string]string
|
||||
|
||||
// RelayFactor is used in keyring operations to cause reponses to be
|
||||
// relayed back to the sender through N other random nodes. Must be
|
||||
// a value from 0 to 5 (inclusive).
|
||||
RelayFactor uint8
|
||||
}
|
||||
|
||||
// WriteOptions are used to parameterize a write
|
||||
|
@ -90,6 +95,11 @@ type WriteOptions struct {
|
|||
// Token is used to provide a per-request ACL token
|
||||
// which overrides the agent's default token.
|
||||
Token string
|
||||
|
||||
// RelayFactor is used in keyring operations to cause reponses to be
|
||||
// relayed back to the sender through N other random nodes. Must be
|
||||
// a value from 0 to 5 (inclusive).
|
||||
RelayFactor uint8
|
||||
}
|
||||
|
||||
// QueryMeta is used to return meta data about a query
|
||||
|
@ -396,6 +406,9 @@ func (r *request) setQueryOptions(q *QueryOptions) {
|
|||
r.params.Add("node-meta", key+":"+value)
|
||||
}
|
||||
}
|
||||
if q.RelayFactor != 0 {
|
||||
r.params.Set("relay-factor", strconv.Itoa(int(q.RelayFactor)))
|
||||
}
|
||||
}
|
||||
|
||||
// durToMsec converts a duration to a millisecond specified string. If the
|
||||
|
@ -437,6 +450,9 @@ func (r *request) setWriteOptions(q *WriteOptions) {
|
|||
if q.Token != "" {
|
||||
r.header.Set("X-Consul-Token", q.Token)
|
||||
}
|
||||
if q.RelayFactor != 0 {
|
||||
r.params.Set("relay-factor", strconv.Itoa(int(q.RelayFactor)))
|
||||
}
|
||||
}
|
||||
|
||||
// toHTTP converts the request to an HTTP request
|
||||
|
|
|
@ -154,7 +154,14 @@ func keyringErrorsOrNil(responses []*structs.KeyringResponse) error {
|
|||
var errs error
|
||||
for _, response := range responses {
|
||||
if response.Error != "" {
|
||||
errs = multierror.Append(errs, fmt.Errorf(response.Error))
|
||||
pool := response.Datacenter + " (LAN)"
|
||||
if response.WAN {
|
||||
pool = "WAN"
|
||||
}
|
||||
errs = multierror.Append(errs, fmt.Errorf("%s error: %s", pool, response.Error))
|
||||
for key, message := range response.Messages {
|
||||
errs = multierror.Append(errs, fmt.Errorf("%s: %s", key, message))
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
|
|
|
@ -83,7 +83,7 @@ func (c *Command) httpFlagsClient(f *flag.FlagSet) *flag.FlagSet {
|
|||
}
|
||||
|
||||
f.Var(&c.httpAddr, "http-addr",
|
||||
"Address and port to the Consul HTTP agent. The value can be an IP "+
|
||||
"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 127.0.0.1:8500.")
|
||||
|
@ -148,6 +148,8 @@ func (c *Command) Parse(args []string) error {
|
|||
|
||||
// Help returns the help for this flagSet.
|
||||
func (c *Command) Help() string {
|
||||
// Some commands with subcommands (kv/snapshot) call this without initializing
|
||||
// any flags first, so exit early to avoid a panic
|
||||
if c.flagSet == nil {
|
||||
return ""
|
||||
}
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// EventCommand is a Command implementation that is used to
|
||||
// fire new events
|
||||
type EventCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *EventCommand) Help() string {
|
||||
|
@ -24,33 +23,25 @@ Usage: consul event [options] [payload]
|
|||
a name, but a payload is optional. Events support filtering using
|
||||
regular expressions on node name, service, and tag definitions.
|
||||
|
||||
Options:
|
||||
` + c.Command.Help()
|
||||
|
||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
||||
-datacenter="" Datacenter to dispatch in. Defaults to that of agent.
|
||||
-name="" Name of the event.
|
||||
-node="" Regular expression to filter on node names
|
||||
-service="" Regular expression to filter on service instances
|
||||
-tag="" Regular expression to filter on service tags. Must be used
|
||||
with -service.
|
||||
-token="" ACL token to use during requests. Defaults to that
|
||||
of the agent.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *EventCommand) Run(args []string) int {
|
||||
var datacenter, name, node, service, tag, token string
|
||||
cmdFlags := flag.NewFlagSet("event", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
cmdFlags.StringVar(&datacenter, "datacenter", "", "")
|
||||
cmdFlags.StringVar(&name, "name", "", "")
|
||||
cmdFlags.StringVar(&node, "node", "", "")
|
||||
cmdFlags.StringVar(&service, "service", "", "")
|
||||
cmdFlags.StringVar(&tag, "tag", "", "")
|
||||
cmdFlags.StringVar(&token, "token", "", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
var name, node, service, tag string
|
||||
|
||||
f := c.Command.NewFlagSet(c)
|
||||
f.StringVar(&name, "name", "",
|
||||
"Name of the event.")
|
||||
f.StringVar(&node, "node", "",
|
||||
"Regular expression to filter on node names.")
|
||||
f.StringVar(&service, "service", "",
|
||||
"Regular expression to filter on service instances.")
|
||||
f.StringVar(&tag, "tag", "",
|
||||
"Regular expression to filter on service tags. Must be used with -service.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -88,7 +79,7 @@ func (c *EventCommand) Run(args []string) int {
|
|||
|
||||
// Check for a payload
|
||||
var payload []byte
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
case 1:
|
||||
|
@ -101,7 +92,7 @@ func (c *EventCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
client, err := HTTPClient(*httpAddr)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -121,13 +112,9 @@ func (c *EventCommand) Run(args []string) int {
|
|||
ServiceFilter: service,
|
||||
TagFilter: tag,
|
||||
}
|
||||
opts := &consulapi.WriteOptions{
|
||||
Datacenter: datacenter,
|
||||
Token: token,
|
||||
}
|
||||
|
||||
// Fire the event
|
||||
id, _, err := event.Fire(params, opts)
|
||||
id, _, err := event.Fire(params, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error firing event: %s", err))
|
||||
return 1
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEventCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &WatchCommand{}
|
||||
var _ cli.Command = &EventCommand{}
|
||||
}
|
||||
|
||||
func TestEventCommandRun(t *testing.T) {
|
||||
|
@ -15,7 +16,12 @@ func TestEventCommandRun(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &EventCommand{Ui: ui}
|
||||
c := &EventCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}
|
||||
args := []string{"-http-addr=" + a1.httpAddr, "-name=cmd"}
|
||||
|
||||
code := c.Run(args)
|
||||
|
|
|
@ -3,7 +3,6 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -15,6 +14,7 @@ import (
|
|||
"unicode"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -53,9 +53,7 @@ const (
|
|||
|
||||
// rExecConf is used to pass around configuration
|
||||
type rExecConf struct {
|
||||
datacenter string
|
||||
prefix string
|
||||
token string
|
||||
prefix string
|
||||
|
||||
foreignDC bool
|
||||
localDC string
|
||||
|
@ -118,8 +116,9 @@ type rExecExit struct {
|
|||
// ExecCommand is a Command implementation that is used to
|
||||
// do remote execution of commands
|
||||
type ExecCommand struct {
|
||||
base.Command
|
||||
|
||||
ShutdownCh <-chan struct{}
|
||||
Ui cli.Ui
|
||||
conf rExecConf
|
||||
client *consulapi.Client
|
||||
sessionID string
|
||||
|
@ -127,24 +126,29 @@ type ExecCommand struct {
|
|||
}
|
||||
|
||||
func (c *ExecCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("exec", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
cmdFlags.StringVar(&c.conf.datacenter, "datacenter", "", "")
|
||||
cmdFlags.StringVar(&c.conf.node, "node", "", "")
|
||||
cmdFlags.StringVar(&c.conf.service, "service", "", "")
|
||||
cmdFlags.StringVar(&c.conf.tag, "tag", "", "")
|
||||
cmdFlags.StringVar(&c.conf.prefix, "prefix", rExecPrefix, "")
|
||||
cmdFlags.DurationVar(&c.conf.replWait, "wait-repl", rExecReplicationWait, "")
|
||||
cmdFlags.DurationVar(&c.conf.wait, "wait", rExecQuietWait, "")
|
||||
cmdFlags.BoolVar(&c.conf.verbose, "verbose", false, "")
|
||||
cmdFlags.StringVar(&c.conf.token, "token", "", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
f.StringVar(&c.conf.node, "node", "",
|
||||
"Regular expression to filter on node names.")
|
||||
f.StringVar(&c.conf.service, "service", "",
|
||||
"Regular expression to filter on service instances.")
|
||||
f.StringVar(&c.conf.tag, "tag", "",
|
||||
"Regular expression to filter on service tags. Must be used with -service.")
|
||||
f.StringVar(&c.conf.prefix, "prefix", rExecPrefix,
|
||||
"Prefix in the KV store to use for request data.")
|
||||
f.DurationVar(&c.conf.wait, "wait", rExecQuietWait,
|
||||
"Period to wait with no responses before terminating execution.")
|
||||
f.DurationVar(&c.conf.replWait, "wait-repl", rExecReplicationWait,
|
||||
"Period to wait for replication before firing event. This is an "+
|
||||
"optimization to allow stale reads to be performed.")
|
||||
f.BoolVar(&c.conf.verbose, "verbose", false,
|
||||
"Enables verbose output.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Join the commands to execute
|
||||
c.conf.cmd = strings.Join(cmdFlags.Args(), " ")
|
||||
c.conf.cmd = strings.Join(f.Args(), " ")
|
||||
|
||||
// If there is no command, read stdin for a script input
|
||||
if c.conf.cmd == "-" {
|
||||
|
@ -175,11 +179,7 @@ func (c *ExecCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
client, err := HTTPClientConfig(func(clientConf *consulapi.Config) {
|
||||
clientConf.Address = *httpAddr
|
||||
clientConf.Datacenter = c.conf.datacenter
|
||||
clientConf.Token = c.conf.token
|
||||
})
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -192,7 +192,7 @@ func (c *ExecCommand) Run(args []string) int {
|
|||
c.client = client
|
||||
|
||||
// Check if this is a foreign datacenter
|
||||
if c.conf.datacenter != "" && c.conf.datacenter != info["Config"]["Datacenter"] {
|
||||
if c.Command.HTTPDatacenter() != "" && c.Command.HTTPDatacenter() != info["Config"]["Datacenter"] {
|
||||
if c.conf.verbose {
|
||||
c.Ui.Info("Remote exec in foreign datacenter, using Session TTL")
|
||||
}
|
||||
|
@ -489,7 +489,7 @@ func (c *ExecCommand) createSessionForeign() (string, error) {
|
|||
node := services[0].Node.Node
|
||||
if c.conf.verbose {
|
||||
c.Ui.Info(fmt.Sprintf("Binding session to remote node %s@%s",
|
||||
node, c.conf.datacenter))
|
||||
node, c.Command.HTTPDatacenter()))
|
||||
}
|
||||
|
||||
session := c.client.Session()
|
||||
|
@ -618,22 +618,8 @@ Usage: consul exec [options] [-|command...]
|
|||
definitions. If a command is '-', stdin will be read until EOF
|
||||
and used as a script input.
|
||||
|
||||
Options:
|
||||
` + c.Command.Help()
|
||||
|
||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
||||
-datacenter="" Datacenter to dispatch in. Defaults to that of agent.
|
||||
-prefix="_rexec" Prefix in the KV store to use for request data
|
||||
-node="" Regular expression to filter on node names
|
||||
-service="" Regular expression to filter on service instances
|
||||
-tag="" Regular expression to filter on service tags. Must be used
|
||||
with -service.
|
||||
-wait=2s Period to wait with no responses before terminating execution.
|
||||
-wait-repl=200ms Period to wait for replication before firing event. This is an
|
||||
optimization to allow stale reads to be performed.
|
||||
-verbose Enables verbose output
|
||||
-token="" ACL token to use during requests. Defaults to that
|
||||
of the agent.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,10 +8,21 @@ import (
|
|||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/agent"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/hashicorp/consul/testutil"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testExecCommand(t *testing.T) (*cli.MockUi, *ExecCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &ExecCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &ExecCommand{}
|
||||
}
|
||||
|
@ -21,8 +32,7 @@ func TestExecCommandRun(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
waitForLeader(t, a1.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{Ui: ui}
|
||||
ui, c := testExecCommand(t)
|
||||
args := []string{"-http-addr=" + a1.httpAddr, "-wait=10s", "uptime"}
|
||||
|
||||
code := c.Run(args)
|
||||
|
@ -57,8 +67,7 @@ func TestExecCommandRun_CrossDC(t *testing.T) {
|
|||
waitForLeader(t, a1.httpAddr)
|
||||
waitForLeader(t, a2.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{Ui: ui}
|
||||
ui, c := testExecCommand(t)
|
||||
args := []string{"-http-addr=" + a1.httpAddr,
|
||||
"-wait=400ms", "-datacenter=dc2", "uptime"}
|
||||
|
||||
|
@ -130,11 +139,8 @@ func TestExecCommand_Sessions(t *testing.T) {
|
|||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{
|
||||
Ui: ui,
|
||||
client: client,
|
||||
}
|
||||
_, c := testExecCommand(t)
|
||||
c.client = client
|
||||
|
||||
id, err := c.createSession()
|
||||
if err != nil {
|
||||
|
@ -174,11 +180,8 @@ func TestExecCommand_Sessions_Foreign(t *testing.T) {
|
|||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{
|
||||
Ui: ui,
|
||||
client: client,
|
||||
}
|
||||
_, c := testExecCommand(t)
|
||||
c.client = client
|
||||
|
||||
c.conf.foreignDC = true
|
||||
c.conf.localDC = "dc1"
|
||||
|
@ -228,11 +231,8 @@ func TestExecCommand_UploadDestroy(t *testing.T) {
|
|||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{
|
||||
Ui: ui,
|
||||
client: client,
|
||||
}
|
||||
_, c := testExecCommand(t)
|
||||
c.client = client
|
||||
|
||||
id, err := c.createSession()
|
||||
if err != nil {
|
||||
|
@ -288,11 +288,8 @@ func TestExecCommand_StreamResults(t *testing.T) {
|
|||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &ExecCommand{
|
||||
Ui: ui,
|
||||
client: client,
|
||||
}
|
||||
_, c := testExecCommand(t)
|
||||
c.client = client
|
||||
c.conf.prefix = "_rexec"
|
||||
|
||||
id, err := c.createSession()
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
@ -11,7 +10,7 @@ import (
|
|||
// InfoCommand is a Command implementation that queries a running
|
||||
// Consul agent for various debugging statistics for operators
|
||||
type InfoCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (i *InfoCommand) Help() string {
|
||||
|
@ -20,33 +19,34 @@ Usage: consul info [options]
|
|||
|
||||
Provides debugging information for operators
|
||||
|
||||
Options:
|
||||
` + i.Command.Help()
|
||||
|
||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (i *InfoCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("info", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { i.Ui.Output(i.Help()) }
|
||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
i.Command.NewFlagSet(i)
|
||||
|
||||
if err := i.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := RPCClient(*rpcAddr)
|
||||
client, err := i.Command.HTTPClient()
|
||||
if err != nil {
|
||||
i.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
stats, err := client.Stats()
|
||||
self, err := client.Agent().Self()
|
||||
if err != nil {
|
||||
i.Ui.Error(fmt.Sprintf("Error querying agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
stats, ok := self["Stats"]
|
||||
if !ok {
|
||||
i.Ui.Error(fmt.Sprintf("Agent response did not contain 'Stats' key: %v", self))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Get the keys in sorted order
|
||||
keys := make([]string, 0, len(stats))
|
||||
|
@ -60,7 +60,11 @@ func (i *InfoCommand) Run(args []string) int {
|
|||
i.Ui.Output(key + ":")
|
||||
|
||||
// Sort the sub-keys
|
||||
subvals := stats[key]
|
||||
subvals, ok := stats[key].(map[string]interface{})
|
||||
if !ok {
|
||||
i.Ui.Error(fmt.Sprintf("Got invalid subkey in stats: %v", subvals))
|
||||
return 1
|
||||
}
|
||||
subkeys := make([]string, 0, len(subvals))
|
||||
for k := range subvals {
|
||||
subkeys = append(subkeys, k)
|
||||
|
@ -77,5 +81,5 @@ func (i *InfoCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
func (i *InfoCommand) Synopsis() string {
|
||||
return "Provides debugging information for operators"
|
||||
return "Provides debugging information for operators."
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -15,8 +16,13 @@ func TestInfoCommandRun(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &InfoCommand{Ui: ui}
|
||||
args := []string{"-rpc-addr=" + a1.addr}
|
||||
c := &InfoCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}
|
||||
args := []string{"-http-addr=" + a1.httpAddr}
|
||||
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// JoinCommand is a Command implementation that tells a running Consul
|
||||
// agent to join another.
|
||||
type JoinCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *JoinCommand) Help() string {
|
||||
|
@ -20,26 +19,21 @@ Usage: consul join [options] address ...
|
|||
Tells a running Consul agent (with "consul agent") to join the cluster
|
||||
by specifying at least one existing member.
|
||||
|
||||
Options:
|
||||
` + c.Command.Help()
|
||||
|
||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
||||
-wan Joins a server to another server in the WAN pool
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *JoinCommand) Run(args []string) int {
|
||||
var wan bool
|
||||
|
||||
cmdFlags := flag.NewFlagSet("join", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
cmdFlags.BoolVar(&wan, "wan", false, "wan")
|
||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
f.BoolVar(&wan, "wan", false, "Joins a server to another server in the WAN pool.")
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
addrs := cmdFlags.Args()
|
||||
addrs := f.Args()
|
||||
if len(addrs) == 0 {
|
||||
c.Ui.Error("At least one address to join must be specified.")
|
||||
c.Ui.Error("")
|
||||
|
@ -47,21 +41,29 @@ func (c *JoinCommand) Run(args []string) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
client, err := RPCClient(*rpcAddr)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
n, err := client.Join(addrs, wan)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error joining the cluster: %s", err))
|
||||
joins := 0
|
||||
for _, addr := range addrs {
|
||||
err := client.Agent().Join(addr, wan)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error joining address '%s': %s", addr, err))
|
||||
} else {
|
||||
joins++
|
||||
}
|
||||
}
|
||||
|
||||
if joins == 0 {
|
||||
c.Ui.Error("Failed to join any nodes.")
|
||||
return 1
|
||||
}
|
||||
|
||||
c.Ui.Output(fmt.Sprintf(
|
||||
"Successfully joined cluster by contacting %d nodes.", n))
|
||||
"Successfully joined cluster by contacting %d nodes.", joins))
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,20 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testJoinCommand(t *testing.T) (*cli.MockUi, *JoinCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &JoinCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestJoinCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &JoinCommand{}
|
||||
}
|
||||
|
@ -18,10 +29,9 @@ func TestJoinCommandRun(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
defer a2.Shutdown()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &JoinCommand{Ui: ui}
|
||||
ui, c := testJoinCommand(t)
|
||||
args := []string{
|
||||
"-rpc-addr=" + a1.addr,
|
||||
"-http-addr=" + a1.httpAddr,
|
||||
fmt.Sprintf("127.0.0.1:%d", a2.config.Ports.SerfLan),
|
||||
}
|
||||
|
||||
|
@ -41,10 +51,9 @@ func TestJoinCommandRun_wan(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
defer a2.Shutdown()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &JoinCommand{Ui: ui}
|
||||
ui, c := testJoinCommand(t)
|
||||
args := []string{
|
||||
"-rpc-addr=" + a1.addr,
|
||||
"-http-addr=" + a1.httpAddr,
|
||||
"-wan",
|
||||
fmt.Sprintf("127.0.0.1:%d", a2.config.Ports.SerfWan),
|
||||
}
|
||||
|
@ -60,9 +69,8 @@ func TestJoinCommandRun_wan(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestJoinCommandRun_noAddrs(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &JoinCommand{Ui: ui}
|
||||
args := []string{"-rpc-addr=foo"}
|
||||
ui, c := testJoinCommand(t)
|
||||
args := []string{"-http-addr=foo"}
|
||||
|
||||
code := c.Run(args)
|
||||
if code != 1 {
|
||||
|
|
|
@ -6,16 +6,21 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KeygenCommand is a Command implementation that generates an encryption
|
||||
// key for use in `consul agent`.
|
||||
type KeygenCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KeygenCommand) Run(_ []string) int {
|
||||
func (c *KeygenCommand) Run(args []string) int {
|
||||
c.Command.NewFlagSet(c)
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := make([]byte, 16)
|
||||
n, err := rand.Reader.Read(key)
|
||||
if err != nil {
|
||||
|
@ -42,6 +47,8 @@ Usage: consul keygen
|
|||
Generates a new encryption key that can be used to configure the
|
||||
agent to encrypt traffic. The output of this command is already
|
||||
in the proper format that the agent expects.
|
||||
`
|
||||
|
||||
` + c.Command.Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
"testing"
|
||||
)
|
||||
|
@ -12,7 +13,12 @@ func TestKeygenCommand_implements(t *testing.T) {
|
|||
|
||||
func TestKeygenCommand(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeygenCommand{Ui: ui}
|
||||
c := &KeygenCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetNone,
|
||||
},
|
||||
}
|
||||
code := c.Run(nil)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d", code)
|
||||
|
|
|
@ -1,37 +1,46 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/agent"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// KeyringCommand is a Command implementation that handles querying, installing,
|
||||
// and removing gossip encryption keys from a keyring.
|
||||
type KeyringCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KeyringCommand) Run(args []string) int {
|
||||
var installKey, useKey, removeKey, token string
|
||||
var installKey, useKey, removeKey string
|
||||
var listKeys bool
|
||||
var relay int
|
||||
|
||||
cmdFlags := flag.NewFlagSet("keys", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
f := c.Command.NewFlagSet(c)
|
||||
|
||||
cmdFlags.StringVar(&installKey, "install", "", "install key")
|
||||
cmdFlags.StringVar(&useKey, "use", "", "use key")
|
||||
cmdFlags.StringVar(&removeKey, "remove", "", "remove key")
|
||||
cmdFlags.BoolVar(&listKeys, "list", false, "list keys")
|
||||
cmdFlags.StringVar(&token, "token", "", "acl token")
|
||||
cmdFlags.IntVar(&relay, "relay-factor", 0, "relay factor")
|
||||
f.StringVar(&installKey, "install", "",
|
||||
"Install a new encryption key. This will broadcast the new key to "+
|
||||
"all members in the cluster.")
|
||||
f.StringVar(&useKey, "use", "",
|
||||
"Change the primary encryption key, which is used to encrypt "+
|
||||
"messages. The key must already be installed before this operation "+
|
||||
"can succeed.")
|
||||
f.StringVar(&removeKey, "remove", "",
|
||||
"Remove the given key from the cluster. This operation may only be "+
|
||||
"performed on keys which are not currently the primary key.")
|
||||
f.BoolVar(&listKeys, "list", false,
|
||||
"List all keys currently in use within the cluster.")
|
||||
f.IntVar(&relay, "relay-factor", 0,
|
||||
"Setting this to a non-zero value will cause nodes to relay their response "+
|
||||
"to the operation through this many randomly-chosen other nodes in the "+
|
||||
"cluster. The maximum allowed value is 5.")
|
||||
|
||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
|
@ -66,124 +75,69 @@ func (c *KeyringCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// All other operations will require a client connection
|
||||
client, err := RPCClient(*rpcAddr)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
if listKeys {
|
||||
c.Ui.Info("Gathering installed encryption keys...")
|
||||
r, err := client.ListKeys(token, relayFactor)
|
||||
responses, err := client.Operator().KeyringList(&consulapi.QueryOptions{RelayFactor: relayFactor})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("error: %s", err))
|
||||
return 1
|
||||
}
|
||||
if rval := c.handleResponse(r.Info, r.Messages); rval != 0 {
|
||||
return rval
|
||||
}
|
||||
c.handleList(r.Info, r.Keys)
|
||||
c.handleList(responses)
|
||||
return 0
|
||||
}
|
||||
|
||||
opts := &consulapi.WriteOptions{RelayFactor: relayFactor}
|
||||
if installKey != "" {
|
||||
c.Ui.Info("Installing new gossip encryption key...")
|
||||
r, err := client.InstallKey(installKey, token, relayFactor)
|
||||
err := client.Operator().KeyringInstall(installKey, opts)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("error: %s", err))
|
||||
return 1
|
||||
}
|
||||
return c.handleResponse(r.Info, r.Messages)
|
||||
return 0
|
||||
}
|
||||
|
||||
if useKey != "" {
|
||||
c.Ui.Info("Changing primary gossip encryption key...")
|
||||
r, err := client.UseKey(useKey, token, relayFactor)
|
||||
err := client.Operator().KeyringUse(useKey, opts)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("error: %s", err))
|
||||
return 1
|
||||
}
|
||||
return c.handleResponse(r.Info, r.Messages)
|
||||
return 0
|
||||
}
|
||||
|
||||
if removeKey != "" {
|
||||
c.Ui.Info("Removing gossip encryption key...")
|
||||
r, err := client.RemoveKey(removeKey, token, relayFactor)
|
||||
err := client.Operator().KeyringRemove(removeKey, opts)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("error: %s", err))
|
||||
return 1
|
||||
}
|
||||
return c.handleResponse(r.Info, r.Messages)
|
||||
return 0
|
||||
}
|
||||
|
||||
// Should never make it here
|
||||
return 0
|
||||
}
|
||||
|
||||
func (c *KeyringCommand) handleResponse(
|
||||
info []agent.KeyringInfo,
|
||||
messages []agent.KeyringMessage) int {
|
||||
|
||||
var rval int
|
||||
|
||||
for _, i := range info {
|
||||
if i.Error != "" {
|
||||
pool := i.Pool
|
||||
if pool != "WAN" {
|
||||
pool = i.Datacenter + " (LAN)"
|
||||
}
|
||||
|
||||
c.Ui.Error("")
|
||||
c.Ui.Error(fmt.Sprintf("%s error: %s", pool, i.Error))
|
||||
|
||||
for _, msg := range messages {
|
||||
if msg.Datacenter != i.Datacenter || msg.Pool != i.Pool {
|
||||
continue
|
||||
}
|
||||
c.Ui.Error(fmt.Sprintf(" %s: %s", msg.Node, msg.Message))
|
||||
}
|
||||
rval = 1
|
||||
}
|
||||
}
|
||||
|
||||
if rval == 0 {
|
||||
c.Ui.Info("Done!")
|
||||
}
|
||||
|
||||
return rval
|
||||
}
|
||||
|
||||
func (c *KeyringCommand) handleList(
|
||||
info []agent.KeyringInfo,
|
||||
keys []agent.KeyringEntry) {
|
||||
|
||||
installed := make(map[string]map[string][]int)
|
||||
for _, key := range keys {
|
||||
var nodes int
|
||||
for _, i := range info {
|
||||
if i.Datacenter == key.Datacenter && i.Pool == key.Pool {
|
||||
nodes = i.NumNodes
|
||||
}
|
||||
func (c *KeyringCommand) handleList(responses []*consulapi.KeyringResponse) {
|
||||
for _, response := range responses {
|
||||
pool := response.Datacenter + " (LAN)"
|
||||
if response.WAN {
|
||||
pool = "WAN"
|
||||
}
|
||||
|
||||
pool := key.Pool
|
||||
if pool != "WAN" {
|
||||
pool = key.Datacenter + " (LAN)"
|
||||
}
|
||||
|
||||
if _, ok := installed[pool]; !ok {
|
||||
installed[pool] = map[string][]int{key.Key: []int{key.Count, nodes}}
|
||||
} else {
|
||||
installed[pool][key.Key] = []int{key.Count, nodes}
|
||||
}
|
||||
}
|
||||
|
||||
for pool, keys := range installed {
|
||||
c.Ui.Output("")
|
||||
c.Ui.Output(pool + ":")
|
||||
for key, num := range keys {
|
||||
c.Ui.Output(fmt.Sprintf(" %s [%d/%d]", key, num[0], num[1]))
|
||||
for key, num := range response.Keys {
|
||||
c.Ui.Output(fmt.Sprintf(" %s [%d/%d]", key, num, response.NumNodes))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,26 +159,8 @@ Usage: consul keyring [options]
|
|||
are no errors. If any node fails to reply or reports failure, the exit code
|
||||
will be 1.
|
||||
|
||||
Options:
|
||||
` + c.Command.Help()
|
||||
|
||||
-install=<key> Install a new encryption key. This will broadcast
|
||||
the new key to all members in the cluster.
|
||||
-list List all keys currently in use within the cluster.
|
||||
-remove=<key> Remove the given key from the cluster. This
|
||||
operation may only be performed on keys which are
|
||||
not currently the primary key.
|
||||
-token="" ACL token to use during requests. Defaults to that
|
||||
of the agent.
|
||||
-relay-factor Added in Consul 0.7.4, setting this to a non-zero
|
||||
value will cause nodes to relay their response to
|
||||
the operation through this many randomly-chosen
|
||||
other nodes in the cluster. The maximum allowed
|
||||
value is 5.
|
||||
-use=<key> Change the primary encryption key, which is used to
|
||||
encrypt messages. The key must already be installed
|
||||
before this operation can succeed.
|
||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,20 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/agent"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKeyringCommand(t *testing.T) (*cli.MockUi, *KeyringCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KeyringCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyringCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KeyringCommand{}
|
||||
}
|
||||
|
@ -23,7 +34,7 @@ func TestKeyringCommandRun(t *testing.T) {
|
|||
defer a1.Shutdown()
|
||||
|
||||
// The LAN and WAN keyrings were initialized with key1
|
||||
out := listKeys(t, a1.addr)
|
||||
out := listKeys(t, a1.httpAddr)
|
||||
if !strings.Contains(out, "dc1 (LAN):\n "+key1) {
|
||||
t.Fatalf("bad: %#v", out)
|
||||
}
|
||||
|
@ -35,10 +46,10 @@ func TestKeyringCommandRun(t *testing.T) {
|
|||
}
|
||||
|
||||
// Install the second key onto the keyring
|
||||
installKey(t, a1.addr, key2)
|
||||
installKey(t, a1.httpAddr, key2)
|
||||
|
||||
// Both keys should be present
|
||||
out = listKeys(t, a1.addr)
|
||||
out = listKeys(t, a1.httpAddr)
|
||||
for _, key := range []string{key1, key2} {
|
||||
if !strings.Contains(out, key) {
|
||||
t.Fatalf("bad: %#v", out)
|
||||
|
@ -46,11 +57,11 @@ func TestKeyringCommandRun(t *testing.T) {
|
|||
}
|
||||
|
||||
// Rotate to key2, remove key1
|
||||
useKey(t, a1.addr, key2)
|
||||
removeKey(t, a1.addr, key1)
|
||||
useKey(t, a1.httpAddr, key2)
|
||||
removeKey(t, a1.httpAddr, key1)
|
||||
|
||||
// Only key2 is present now
|
||||
out = listKeys(t, a1.addr)
|
||||
out = listKeys(t, a1.httpAddr)
|
||||
if !strings.Contains(out, "dc1 (LAN):\n "+key2) {
|
||||
t.Fatalf("bad: %#v", out)
|
||||
}
|
||||
|
@ -63,8 +74,7 @@ func TestKeyringCommandRun(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKeyringCommandRun_help(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
code := c.Run(nil)
|
||||
if code != 1 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
|
@ -77,9 +87,8 @@ func TestKeyringCommandRun_help(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKeyringCommandRun_failedConnection(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
args := []string{"-list", "-rpc-addr=127.0.0.1:0"}
|
||||
ui, c := testKeyringCommand(t)
|
||||
args := []string{"-list", "-http-addr=127.0.0.1:0"}
|
||||
code := c.Run(args)
|
||||
if code != 1 {
|
||||
t.Fatalf("bad: %d, %#v", code, ui.ErrorWriter.String())
|
||||
|
@ -90,8 +99,7 @@ func TestKeyringCommandRun_failedConnection(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKeyringCommandRun_invalidRelayFactor(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
|
||||
args := []string{"-list", "-relay-factor=6"}
|
||||
code := c.Run(args)
|
||||
|
@ -101,10 +109,9 @@ func TestKeyringCommandRun_invalidRelayFactor(t *testing.T) {
|
|||
}
|
||||
|
||||
func listKeys(t *testing.T, addr string) string {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
|
||||
args := []string{"-list", "-rpc-addr=" + addr}
|
||||
args := []string{"-list", "-http-addr=" + addr}
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
|
@ -114,10 +121,9 @@ func listKeys(t *testing.T, addr string) string {
|
|||
}
|
||||
|
||||
func installKey(t *testing.T, addr string, key string) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
|
||||
args := []string{"-install=" + key, "-rpc-addr=" + addr}
|
||||
args := []string{"-install=" + key, "-http-addr=" + addr}
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
|
@ -125,10 +131,9 @@ func installKey(t *testing.T, addr string, key string) {
|
|||
}
|
||||
|
||||
func useKey(t *testing.T, addr string, key string) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
|
||||
args := []string{"-use=" + key, "-rpc-addr=" + addr}
|
||||
args := []string{"-use=" + key, "-http-addr=" + addr}
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
|
@ -136,10 +141,9 @@ func useKey(t *testing.T, addr string, key string) {
|
|||
}
|
||||
|
||||
func removeKey(t *testing.T, addr string, key string) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KeyringCommand{Ui: ui}
|
||||
ui, c := testKeyringCommand(t)
|
||||
|
||||
args := []string{"-remove=" + key, "-rpc-addr=" + addr}
|
||||
args := []string{"-remove=" + key, "-http-addr=" + addr}
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
|
|
|
@ -3,13 +3,14 @@ package command
|
|||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// KVCommand is a Command implementation that just shows help for
|
||||
// the subcommands nested below it.
|
||||
type KVCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVCommand) Run(args []string) int {
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVDeleteCommand is a Command implementation that is used to delete a key or
|
||||
// prefix of keys from the key-value store.
|
||||
type KVDeleteCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVDeleteCommand) Help() string {
|
||||
|
@ -33,40 +32,30 @@ Usage: consul kv delete [options] KEY_OR_PREFIX
|
|||
This will delete the keys named "foo", "food", and "foo/bar/zip" if they
|
||||
existed.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Delete Options:
|
||||
|
||||
-cas Perform a Check-And-Set operation. Specifying this
|
||||
value also requires the -modify-index flag to be set.
|
||||
The default value is false.
|
||||
|
||||
-modify-index=<int> Unsigned integer representing the ModifyIndex of the
|
||||
key. This is used in combination with the -cas flag.
|
||||
|
||||
-recurse Recursively delete all keys with the path. The default
|
||||
value is false.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVDeleteCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
cas := cmdFlags.Bool("cas", false, "")
|
||||
modifyIndex := cmdFlags.Uint64("modify-index", 0, "")
|
||||
recurse := cmdFlags.Bool("recurse", false, "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
cas := f.Bool("cas", false,
|
||||
"Perform a Check-And-Set operation. Specifying this value also requires "+
|
||||
"the -modify-index flag to be set. The default value is false.")
|
||||
modifyIndex := f.Uint64("modify-index", 0,
|
||||
"Unsigned integer representing the ModifyIndex of the key. This is "+
|
||||
"used in combination with the -cas flag.")
|
||||
recurse := f.Bool("recurse", false,
|
||||
"Recursively delete all keys with the path. The default value is false.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -109,22 +98,15 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
}
|
||||
|
||||
switch {
|
||||
case *recurse:
|
||||
if _, err := client.KV().DeleteTree(key, wo); err != nil {
|
||||
if _, err := client.KV().DeleteTree(key, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not delete prefix %s: %s", key, err))
|
||||
return 1
|
||||
}
|
||||
|
@ -137,7 +119,7 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
ModifyIndex: *modifyIndex,
|
||||
}
|
||||
|
||||
success, _, err := client.KV().DeleteCAS(pair, wo)
|
||||
success, _, err := client.KV().DeleteCAS(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not delete key %s: %s", key, err))
|
||||
return 1
|
||||
|
@ -150,7 +132,7 @@ func (c *KVDeleteCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Deleted key: %s", key))
|
||||
return 0
|
||||
default:
|
||||
if _, err := client.KV().Delete(key, wo); err != nil {
|
||||
if _, err := client.KV().Delete(key, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error deleting key %s: %s", key, err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -6,9 +6,20 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVDeleteCommand(t *testing.T) (*cli.MockUi, *KVDeleteCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVDeleteCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVDeleteCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVDeleteCommand{}
|
||||
}
|
||||
|
@ -18,8 +29,7 @@ func TestKVDeleteCommand_noTabs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVDeleteCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -73,8 +83,7 @@ func TestKVDeleteCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -109,8 +118,7 @@ func TestKVDeleteCommand_Recurse(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
keys := []string{"foo/a", "foo/b", "food"}
|
||||
|
||||
|
@ -152,8 +160,7 @@ func TestKVDeleteCommand_CAS(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVDeleteCommand{Ui: ui}
|
||||
ui, c := testKVDeleteCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
|
|
@ -3,18 +3,17 @@ package command
|
|||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVExportCommand is a Command implementation that is used to export
|
||||
// a KV tree as JSON
|
||||
type KVExportCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVExportCommand) Synopsis() string {
|
||||
|
@ -33,29 +32,20 @@ Usage: consul kv export [KEY_OR_PREFIX]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Export Options:
|
||||
|
||||
None.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVExportCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("export", flag.ContinueOnError)
|
||||
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
stale := cmdFlags.Bool("stale", false, "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -74,18 +64,14 @@ func (c *KVExportCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
pairs, _, err := client.KV().List(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -15,7 +16,12 @@ func TestKVExportCommand_Run(t *testing.T) {
|
|||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVExportCommand{Ui: ui}
|
||||
c := KVExportCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "a",
|
||||
|
|
|
@ -3,20 +3,19 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVGetCommand is a Command implementation that is used to fetch the value of
|
||||
// a key from the key-value store.
|
||||
type KVGetCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *KVGetCommand) Help() string {
|
||||
|
@ -51,54 +50,39 @@ Usage: consul kv get [options] [KEY_OR_PREFIX]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Get Options:
|
||||
|
||||
-base64 Base64 encode the value. The default value is false.
|
||||
|
||||
-detailed Provide additional metadata about the key in addition
|
||||
to the value such as the ModifyIndex and any flags
|
||||
that may have been set on the key. The default value
|
||||
is false.
|
||||
|
||||
-keys List keys which start with the given prefix, but not
|
||||
their values. This is especially useful if you only
|
||||
need the key names themselves. This option is commonly
|
||||
combined with the -separator option. The default value
|
||||
is false.
|
||||
|
||||
-recurse Recursively look at all keys prefixed with the given
|
||||
path. The default value is false.
|
||||
|
||||
-separator=<string> String to use as a separator between keys. The default
|
||||
value is "/", but this option is only taken into
|
||||
account when paired with the -keys flag.
|
||||
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVGetCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
stale := cmdFlags.Bool("stale", false, "")
|
||||
detailed := cmdFlags.Bool("detailed", false, "")
|
||||
keys := cmdFlags.Bool("keys", false, "")
|
||||
base64encode := cmdFlags.Bool("base64", false, "")
|
||||
recurse := cmdFlags.Bool("recurse", false, "")
|
||||
separator := cmdFlags.String("separator", "/", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
base64encode := f.Bool("base64", false,
|
||||
"Base64 encode the value. The default value is false.")
|
||||
detailed := f.Bool("detailed", false,
|
||||
"Provide additional metadata about the key in addition to the value such "+
|
||||
"as the ModifyIndex and any flags that may have been set on the key. "+
|
||||
"The default value is false.")
|
||||
keys := f.Bool("keys", false,
|
||||
"List keys which start with the given prefix, but not their values. "+
|
||||
"This is especially useful if you only need the key names themselves. "+
|
||||
"This option is commonly combined with the -separator option. The default "+
|
||||
"value is false.")
|
||||
recurse := f.Bool("recurse", false,
|
||||
"Recursively look at all keys prefixed with the given path. The default "+
|
||||
"value is false.")
|
||||
separator := f.String("separator", "/",
|
||||
"String to use as a separator between keys. The default value is \"/\", "+
|
||||
"but this option is only taken into account when paired with the -keys flag.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
key := ""
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
switch len(args) {
|
||||
case 0:
|
||||
key = ""
|
||||
|
@ -124,10 +108,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -136,8 +117,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
switch {
|
||||
case *keys:
|
||||
keys, _, err := client.KV().Keys(key, *separator, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
@ -151,8 +131,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
return 0
|
||||
case *recurse:
|
||||
pairs, _, err := client.KV().List(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
@ -184,8 +163,7 @@ func (c *KVGetCommand) Run(args []string) int {
|
|||
return 0
|
||||
default:
|
||||
pair, _, err := client.KV().Get(key, &api.QueryOptions{
|
||||
Datacenter: *datacenter,
|
||||
AllowStale: *stale,
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
})
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||
|
|
|
@ -6,9 +6,20 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVGetCommand(t *testing.T) (*cli.MockUi, *KVGetCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVGetCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVGetCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVGetCommand{}
|
||||
}
|
||||
|
@ -18,8 +29,7 @@ func TestKVGetCommand_noTabs(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVGetCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -61,8 +71,7 @@ func TestKVGetCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -94,8 +103,7 @@ func TestKVGetCommand_Missing(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
_, c := testKVGetCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -113,8 +121,7 @@ func TestKVGetCommand_Empty(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "empty",
|
||||
|
@ -141,8 +148,7 @@ func TestKVGetCommand_Detailed(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
@ -184,8 +190,7 @@ func TestKVGetCommand_Keys(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := []string{"foo/bar", "foo/baz", "foo/zip"}
|
||||
for _, key := range keys {
|
||||
|
@ -218,8 +223,7 @@ func TestKVGetCommand_Recurse(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "a",
|
||||
|
@ -257,8 +261,7 @@ func TestKVGetCommand_RecurseBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
keys := map[string]string{
|
||||
"foo/a": "Hello World 1",
|
||||
|
@ -297,8 +300,7 @@ func TestKVGetCommand_DetailedBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVGetCommand{Ui: ui}
|
||||
ui, c := testKVGetCommand(t)
|
||||
|
||||
pair := &api.KVPair{
|
||||
Key: "foo",
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -13,13 +12,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVImportCommand is a Command implementation that is used to import
|
||||
// a KV tree stored as JSON
|
||||
type KVImportCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
|
||||
// testStdin is the input for testing.
|
||||
testStdin io.Reader
|
||||
|
@ -50,27 +49,20 @@ Usage: consul kv import [DATA]
|
|||
|
||||
For a full list of options and examples, please see the Consul documentation.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Import Options:
|
||||
|
||||
None.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVImportCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("import", flag.ContinueOnError)
|
||||
f := c.Command.NewFlagSet(c)
|
||||
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
data, err := c.dataFromArgs(args)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! %s", err))
|
||||
|
@ -78,10 +70,7 @@ func (c *KVImportCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -106,12 +95,7 @@ func (c *KVImportCommand) Run(args []string) int {
|
|||
Value: value,
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
Token: *token,
|
||||
}
|
||||
|
||||
if _, err := client.KV().Put(pair, wo); err != nil {
|
||||
if _, err := client.KV().Put(pair, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data for key %s: %s", pair.Key, err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -27,7 +28,10 @@ func TestKVImportCommand_Run(t *testing.T) {
|
|||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVImportCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
testStdin: strings.NewReader(json),
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package command
|
|||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -11,13 +10,13 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
// KVPutCommand is a Command implementation that is used to write data to the
|
||||
// key-value store.
|
||||
type KVPutCommand struct {
|
||||
Ui cli.Ui
|
||||
base.Command
|
||||
|
||||
// testStdin is the input for testing.
|
||||
testStdin io.Reader
|
||||
|
@ -57,62 +56,45 @@ Usage: consul kv put [options] KEY [DATA]
|
|||
|
||||
Additional flags and more advanced use cases are detailed below.
|
||||
|
||||
` + apiOptsText + `
|
||||
` + c.Command.Help()
|
||||
|
||||
KV Put Options:
|
||||
|
||||
-acquire Obtain a lock on the key. If the key does not exist,
|
||||
this operation will create the key and obtain the
|
||||
lock. The session must already exist and be specified
|
||||
via the -session flag. The default value is false.
|
||||
|
||||
-base64 Treat the data as base 64 encoded. The default value
|
||||
is false.
|
||||
|
||||
-cas Perform a Check-And-Set operation. Specifying this
|
||||
value also requires the -modify-index flag to be set.
|
||||
The default value is false.
|
||||
|
||||
-flags=<int> Unsigned integer value to assign to this key-value
|
||||
pair. This value is not read by Consul, so clients can
|
||||
use this value however makes sense for their use case.
|
||||
The default value is 0 (no flags).
|
||||
|
||||
-modify-index=<int> Unsigned integer representing the ModifyIndex of the
|
||||
key. This is used in combination with the -cas flag.
|
||||
|
||||
-release Forfeit the lock on the key at the given path. This
|
||||
requires the -session flag to be set. The key must be
|
||||
held by the session in order to be unlocked. The
|
||||
default value is false.
|
||||
|
||||
-session=<string> User-defined identifer for this session as a string.
|
||||
This is commonly used with the -acquire and -release
|
||||
operations to build robust locking, but it can be set
|
||||
on any key. The default value is empty (no session).
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *KVPutCommand) Run(args []string) int {
|
||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
||||
datacenter := cmdFlags.String("datacenter", "", "")
|
||||
token := cmdFlags.String("token", "", "")
|
||||
cas := cmdFlags.Bool("cas", false, "")
|
||||
flags := cmdFlags.Uint64("flags", 0, "")
|
||||
base64encoded := cmdFlags.Bool("base64", false, "")
|
||||
modifyIndex := cmdFlags.Uint64("modify-index", 0, "")
|
||||
session := cmdFlags.String("session", "", "")
|
||||
acquire := cmdFlags.Bool("acquire", false, "")
|
||||
release := cmdFlags.Bool("release", false, "")
|
||||
if err := cmdFlags.Parse(args); err != nil {
|
||||
f := c.Command.NewFlagSet(c)
|
||||
cas := f.Bool("cas", false,
|
||||
"Perform a Check-And-Set operation. Specifying this value also "+
|
||||
"requires the -modify-index flag to be set. The default value "+
|
||||
"is false.")
|
||||
flags := f.Uint64("flags", 0,
|
||||
"Unsigned integer value to assign to this key-value pair. This "+
|
||||
"value is not read by Consul, so clients can use this value however "+
|
||||
"makes sense for their use case. The default value is 0 (no flags).")
|
||||
base64encoded := f.Bool("base64", false,
|
||||
"Treat the data as base 64 encoded. The default value is false.")
|
||||
modifyIndex := f.Uint64("modify-index", 0,
|
||||
"Unsigned integer representing the ModifyIndex of the key. This is "+
|
||||
"used in combination with the -cas flag.")
|
||||
session := f.String("session", "",
|
||||
"User-defined identifer for this session as a string. This is commonly "+
|
||||
"used with the -acquire and -release operations to build robust locking, "+
|
||||
"but it can be set on any key. The default value is empty (no session).")
|
||||
acquire := f.Bool("acquire", false,
|
||||
"Obtain a lock on the key. If the key does not exist, this operation "+
|
||||
"will create the key and obtain the lock. The session must already "+
|
||||
"exist and be specified via the -session flag. The default value is false.")
|
||||
release := f.Bool("release", false,
|
||||
"Forfeit the lock on the key at the given path. This requires the "+
|
||||
"-session flag to be set. The key must be held by the session in order to "+
|
||||
"be unlocked. The default value is false.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
return 1
|
||||
}
|
||||
|
||||
// Check for arg validation
|
||||
args = cmdFlags.Args()
|
||||
args = f.Args()
|
||||
key, data, err := c.dataFromArgs(args)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! %s", err))
|
||||
|
@ -140,10 +122,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
}
|
||||
|
||||
// Create and test the HTTP client
|
||||
conf := api.DefaultConfig()
|
||||
conf.Address = *httpAddr
|
||||
conf.Token = *token
|
||||
client, err := api.NewClient(conf)
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||
return 1
|
||||
|
@ -157,14 +136,9 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
Session: *session,
|
||||
}
|
||||
|
||||
wo := &api.WriteOptions{
|
||||
Datacenter: *datacenter,
|
||||
Token: *token,
|
||||
}
|
||||
|
||||
switch {
|
||||
case *cas:
|
||||
ok, _, err := client.KV().CAS(pair, wo)
|
||||
ok, _, err := client.KV().CAS(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Did not write to %s: %s", key, err))
|
||||
return 1
|
||||
|
@ -177,7 +151,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Data written to: %s", key))
|
||||
return 0
|
||||
case *acquire:
|
||||
ok, _, err := client.KV().Acquire(pair, wo)
|
||||
ok, _, err := client.KV().Acquire(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", err))
|
||||
return 1
|
||||
|
@ -190,7 +164,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Lock acquired on: %s", key))
|
||||
return 0
|
||||
case *release:
|
||||
ok, _, err := client.KV().Release(pair, wo)
|
||||
ok, _, err := client.KV().Release(pair, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", key))
|
||||
return 1
|
||||
|
@ -203,7 +177,7 @@ func (c *KVPutCommand) Run(args []string) int {
|
|||
c.Ui.Info(fmt.Sprintf("Success! Lock released on: %s", key))
|
||||
return 0
|
||||
default:
|
||||
if _, err := client.KV().Put(pair, wo); err != nil {
|
||||
if _, err := client.KV().Put(pair, nil); err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error! Failed writing data: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
|
|
@ -11,20 +11,30 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func testKVPutCommand(t *testing.T) (*cli.MockUi, *KVPutCommand) {
|
||||
ui := new(cli.MockUi)
|
||||
return ui, &KVPutCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestKVPutCommand_implements(t *testing.T) {
|
||||
var _ cli.Command = &KVPutCommand{}
|
||||
}
|
||||
|
||||
func TestKVPutCommand_noTabs(t *testing.T) {
|
||||
assertNoTabs(t, new(KVPutCommand))
|
||||
assertNoTabs(t, new(KVDeleteCommand))
|
||||
}
|
||||
|
||||
func TestKVPutCommand_Validation(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
cases := map[string]struct {
|
||||
args []string
|
||||
|
@ -78,8 +88,7 @@ func TestKVPutCommand_Run(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -106,8 +115,7 @@ func TestKVPutCommand_RunEmptyDataQuoted(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -134,8 +142,7 @@ func TestKVPutCommand_RunBase64(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
const encodedString = "aGVsbG8gd29ybGQK"
|
||||
|
||||
|
@ -170,8 +177,7 @@ func TestKVPutCommand_File(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
f, err := ioutil.TempFile("", "kv-put-command-file")
|
||||
if err != nil {
|
||||
|
@ -203,8 +209,7 @@ func TestKVPutCommand_File(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestKVPutCommand_FileNoExist(t *testing.T) {
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"foo", "@/nope/definitely/not-a-real-file.txt",
|
||||
|
@ -228,11 +233,8 @@ func TestKVPutCommand_Stdin(t *testing.T) {
|
|||
|
||||
stdinR, stdinW := io.Pipe()
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{
|
||||
Ui: ui,
|
||||
testStdin: stdinR,
|
||||
}
|
||||
ui, c := testKVPutCommand(t)
|
||||
c.testStdin = stdinR
|
||||
|
||||
go func() {
|
||||
stdinW.Write([]byte("bar"))
|
||||
|
@ -264,8 +266,7 @@ func TestKVPutCommand_NegativeVal(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -292,8 +293,7 @@ func TestKVPutCommand_Flags(t *testing.T) {
|
|||
defer srv.Shutdown()
|
||||
waitForLeader(t, srv.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
@ -330,8 +330,7 @@ func TestKVPutCommand_CAS(t *testing.T) {
|
|||
t.Fatalf("err: %#v", err)
|
||||
}
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := &KVPutCommand{Ui: ui}
|
||||
ui, c := testKVPutCommand(t)
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + srv.httpAddr,
|
||||
|
|
124
commands.go
124
commands.go
|
@ -41,14 +41,20 @@ func init() {
|
|||
|
||||
"event": func() (cli.Command, error) {
|
||||
return &command.EventCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Flags: base.FlagSetHTTP,
|
||||
Ui: ui,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"exec": func() (cli.Command, error) {
|
||||
return &command.ExecCommand{
|
||||
ShutdownCh: makeShutdownCh(),
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Flags: base.FlagSetHTTP,
|
||||
Ui: ui,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
|
@ -61,57 +67,93 @@ func init() {
|
|||
}, nil
|
||||
},
|
||||
|
||||
"kv": func() (cli.Command, error) {
|
||||
return &command.KVCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv delete": func() (cli.Command, error) {
|
||||
return &command.KVDeleteCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv get": func() (cli.Command, error) {
|
||||
return &command.KVGetCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv put": func() (cli.Command, error) {
|
||||
return &command.KVPutCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv export": func() (cli.Command, error) {
|
||||
return &command.KVExportCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv import": func() (cli.Command, error) {
|
||||
return &command.KVImportCommand{
|
||||
Ui: ui,
|
||||
"info": func() (cli.Command, error) {
|
||||
return &command.InfoCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"join": func() (cli.Command, error) {
|
||||
return &command.JoinCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"keygen": func() (cli.Command, error) {
|
||||
return &command.KeygenCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetNone,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"keyring": func() (cli.Command, error) {
|
||||
return &command.KeyringCommand{
|
||||
Ui: ui,
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetClientHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv": func() (cli.Command, error) {
|
||||
return &command.KVCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetNone,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv delete": func() (cli.Command, error) {
|
||||
return &command.KVDeleteCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv get": func() (cli.Command, error) {
|
||||
return &command.KVGetCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv put": func() (cli.Command, error) {
|
||||
return &command.KVPutCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv export": func() (cli.Command, error) {
|
||||
return &command.KVExportCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"kv import": func() (cli.Command, error) {
|
||||
return &command.KVImportCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
|
@ -171,12 +213,6 @@ func init() {
|
|||
}, nil
|
||||
},
|
||||
|
||||
"info": func() (cli.Command, error) {
|
||||
return &command.InfoCommand{
|
||||
Ui: ui,
|
||||
}, nil
|
||||
},
|
||||
|
||||
"reload": func() (cli.Command, error) {
|
||||
return &command.ReloadCommand{
|
||||
Command: base.Command{
|
||||
|
|
|
@ -39,13 +39,12 @@ Usage: `consul event [options] [payload]`
|
|||
The only required option is `-name` which specifies the event name. An optional
|
||||
payload can be provided as the final argument.
|
||||
|
||||
The list of available flags are:
|
||||
#### API Options
|
||||
|
||||
* `-http-addr` - Address to the HTTP server of the agent you want to contact
|
||||
to send this command. If this isn't specified, the command will contact
|
||||
`127.0.0.1:8500` which is the default HTTP address of a Consul agent.
|
||||
<%= partial "docs/commands/http_api_options_client" %>
|
||||
<%= partial "docs/commands/http_api_options_server" %>
|
||||
|
||||
* `-datacenter` - Datacenter to query. Defaults to that of agent.
|
||||
#### Command Options
|
||||
|
||||
* `-name` - The name of the event.
|
||||
|
||||
|
@ -57,5 +56,3 @@ The list of available flags are:
|
|||
a matching tag. This must be used with `-service`. As an example, you may
|
||||
do `-service mysql -tag secondary`.
|
||||
|
||||
* `-token` - The ACL token to use when firing the event. This token must have
|
||||
write-level privileges for the event specified. Defaults to that of the agent.
|
|
@ -37,14 +37,12 @@ The only required option is a command to execute. This is either given
|
|||
as trailing arguments, or by specifying `-`; STDIN will be read to
|
||||
completion as a script to evaluate.
|
||||
|
||||
The list of available flags are:
|
||||
#### API Options
|
||||
|
||||
* `-http-addr` - Address to the HTTP server of the agent you want to contact
|
||||
to send this command. If this isn't specified, the command will contact
|
||||
`127.0.0.1:8500` which is the default HTTP address of a Consul agent.
|
||||
<%= partial "docs/commands/http_api_options_client" %>
|
||||
<%= partial "docs/commands/http_api_options_server" %>
|
||||
|
||||
* `-datacenter` - Datacenter to query. Defaults to that of agent. In version
|
||||
0.4, that is the only supported value.
|
||||
#### Command Options
|
||||
|
||||
* `-prefix` - Key prefix in the KV store to use for storing request data.
|
||||
Defaults to `_rexec`.
|
||||
|
@ -67,7 +65,3 @@ The list of available flags are:
|
|||
to 200 msec.
|
||||
|
||||
* `-verbose` - Enables verbose output.
|
||||
|
||||
* `-token` - The ACL token to use during requests. This token must have access
|
||||
to the prefix in the KV store as well as exec "write" access for the `_rexec`
|
||||
event. Defaults to that of the agent.
|
|
@ -72,10 +72,6 @@ serf_wan:
|
|||
|
||||
Usage: `consul info`
|
||||
|
||||
The command-line flags are all optional. The list of available flags are:
|
||||
|
||||
* `-rpc-addr` - Address to the RPC server of the agent you want to contact
|
||||
to send this command. If this isn't specified, the command checks the
|
||||
CONSUL_RPC_ADDR env variable. If this isn't set, the default RPC
|
||||
address will be set to "127.0.0.1:8400".
|
||||
#### API Options
|
||||
|
||||
<%= partial "docs/commands/http_api_options_client" %>
|
|
@ -31,14 +31,14 @@ You may call join with multiple addresses if you want to try to join
|
|||
multiple clusters. Consul will attempt to join all addresses, and the join
|
||||
command will fail only if Consul was unable to join with any.
|
||||
|
||||
The command-line flags are all optional. The list of available flags are:
|
||||
#### API Options
|
||||
|
||||
<%= partial "docs/commands/http_api_options_client" %>
|
||||
|
||||
#### Command Options
|
||||
|
||||
* `-wan` - For agents running in server mode, the agent will attempt to join
|
||||
other servers gossiping in a WAN cluster. This is used to form a bridge between
|
||||
multiple datacenters.
|
||||
|
||||
* `-rpc-addr` - Address to the RPC server of the agent you want to contact
|
||||
to send this command. If this isn't specified, the command checks the
|
||||
CONSUL_RPC_ADDR env variable. If this isn't set, the default RPC
|
||||
address will be set to "127.0.0.1:8400".
|
||||
|
|
@ -33,7 +33,11 @@ Usage: `consul keyring [options]`
|
|||
Only one actionable argument may be specified per run, including `-list`,
|
||||
`-install`, `-remove`, and `-use`.
|
||||
|
||||
The list of available flags are:
|
||||
#### API Options
|
||||
|
||||
<%= partial "docs/commands/http_api_options_client" %>
|
||||
|
||||
#### Command Options
|
||||
|
||||
* `-list` - List all keys currently in use within the cluster.
|
||||
|
||||
|
@ -46,16 +50,10 @@ The list of available flags are:
|
|||
* `-remove` - Remove the given key from the cluster. This operation may only be
|
||||
performed on keys which are not currently the primary key.
|
||||
|
||||
* `-token=""` - ACL token to use during requests. Defaults to that of the agent.
|
||||
|
||||
* `-relay-factor` - Added in Consul 0.7.4, setting this to a non-zero value will
|
||||
cause nodes to relay their response to the operation through this many
|
||||
randomly-chosen other nodes in the cluster. The maximum allowed value is 5.
|
||||
|
||||
* `-rpc-addr` - Address to the RPC server of the agent you want to contact
|
||||
to send this command. If this isn't specified, the command will contact
|
||||
"127.0.0.1:8400" which is the default RPC address of a Consul agent.
|
||||
|
||||
## Output
|
||||
|
||||
The output of the `consul keyring -list` command consolidates information from
|
|
@ -87,6 +87,10 @@
|
|||
<a href="/docs/commands/force-leave.html">force-leave</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-info") %>>
|
||||
<a href="/docs/commands/info.html">info</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-join") %>>
|
||||
<a href="/docs/commands/join.html">join</a>
|
||||
</li>
|
||||
|
@ -143,10 +147,6 @@
|
|||
<a href="/docs/commands/operator.html">operator</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-info") %>>
|
||||
<a href="/docs/commands/info.html">info</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-reload") %>>
|
||||
<a href="/docs/commands/reload.html">reload</a>
|
||||
</li>
|
||||
|
@ -174,8 +174,8 @@
|
|||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-version") %>>
|
||||
<a href="/docs/commands/version.html">version</a>
|
||||
</li>
|
||||
<a href="/docs/commands/version.html">version</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current("docs-commands-watch") %>>
|
||||
<a href="/docs/commands/watch.html">watch</a>
|
||||
|
|
Loading…
Reference in New Issue