mirror of https://github.com/status-im/consul.git
Merge pull request #2726 from hashicorp/f-cli-rework-3
Centralize command-line parsing part 3
This commit is contained in:
commit
93853340f0
|
@ -58,6 +58,14 @@ func (c *Command) HTTPClient() (*api.Client, error) {
|
||||||
return api.NewClient(config)
|
return api.NewClient(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Command) HTTPAddr() string {
|
||||||
|
return c.httpAddr.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Command) HTTPToken() string {
|
||||||
|
return c.token.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Command) HTTPDatacenter() string {
|
func (c *Command) HTTPDatacenter() string {
|
||||||
return c.datacenter.String()
|
return c.datacenter.String()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,11 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hashicorp/consul/command/base"
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testJoinCommand(t *testing.T) (*cli.MockUi, *JoinCommand) {
|
func testJoinCommand(t *testing.T) (*cli.MockUi, *JoinCommand) {
|
||||||
|
|
|
@ -1,53 +1,47 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LeaveCommand is a Command implementation that instructs
|
// LeaveCommand is a Command implementation that instructs
|
||||||
// the Consul agent to gracefully leave the cluster
|
// the Consul agent to gracefully leave the cluster
|
||||||
type LeaveCommand struct {
|
type LeaveCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LeaveCommand) Help() string {
|
func (c *LeaveCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: consul leave
|
Usage: consul leave [options]
|
||||||
|
|
||||||
Causes the agent to gracefully leave the Consul cluster and shutdown.
|
Causes the agent to gracefully leave the Consul cluster and shutdown.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *LeaveCommand) Run(args []string) int {
|
func (c *LeaveCommand) Run(args []string) int {
|
||||||
cmdFlags := flag.NewFlagSet("leave", flag.ContinueOnError)
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
if err := c.Command.Parse(args); err != nil {
|
||||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
nonFlagArgs := cmdFlags.Args()
|
nonFlagArgs := f.Args()
|
||||||
if len(nonFlagArgs) > 0 {
|
if len(nonFlagArgs) > 0 {
|
||||||
c.Ui.Error(fmt.Sprintf("Error found unexpected args: %v", nonFlagArgs))
|
c.Ui.Error(fmt.Sprintf("Error found unexpected args: %v", nonFlagArgs))
|
||||||
c.Ui.Output(c.Help())
|
c.Ui.Output(c.Help())
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := RPCClient(*rpcAddr)
|
client, err := c.Command.HTTPClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
if err := client.Leave(); err != nil {
|
if err := client.Agent().Leave(); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error leaving: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error leaving: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,22 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testLeaveCommand(t *testing.T) (*cli.MockUi, *LeaveCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &LeaveCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLeaveCommand_implements(t *testing.T) {
|
func TestLeaveCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &LeaveCommand{}
|
var _ cli.Command = &LeaveCommand{}
|
||||||
}
|
}
|
||||||
|
@ -14,9 +25,8 @@ func TestLeaveCommandRun(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testLeaveCommand(t)
|
||||||
c := &LeaveCommand{Ui: ui}
|
args := []string{"-http-addr=" + a1.httpAddr}
|
||||||
args := []string{"-rpc-addr=" + a1.addr}
|
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
|
@ -32,9 +42,8 @@ func TestLeaveCommandFailOnNonFlagArgs(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
_, c := testLeaveCommand(t)
|
||||||
c := &LeaveCommand{Ui: ui}
|
args := []string{"-http-addr=" + a1.httpAddr, "appserver1"}
|
||||||
args := []string{"-rpc-addr=" + a1.addr, "appserver1"}
|
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code == 0 {
|
if code == 0 {
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MaintCommand is a Command implementation that enables or disables
|
// MaintCommand is a Command implementation that enables or disables
|
||||||
// node or service maintenance mode.
|
// node or service maintenance mode.
|
||||||
type MaintCommand struct {
|
type MaintCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MaintCommand) Help() string {
|
func (c *MaintCommand) Help() string {
|
||||||
|
@ -40,15 +38,8 @@ Usage: consul maint [options]
|
||||||
If no arguments are given, the agent's maintenance status will be shown.
|
If no arguments are given, the agent's maintenance status will be shown.
|
||||||
This will return blank if nothing is currently under maintenance.
|
This will return blank if nothing is currently under maintenance.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-enable Enable maintenance mode.
|
|
||||||
-disable Disable maintenance mode.
|
|
||||||
-reason=<string> Text string describing the maintenance reason
|
|
||||||
-service=<serviceID> Control maintenance mode for a specific service ID
|
|
||||||
-token="" ACL token to use. Defaults to that of agent.
|
|
||||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,19 +48,15 @@ func (c *MaintCommand) Run(args []string) int {
|
||||||
var disable bool
|
var disable bool
|
||||||
var reason string
|
var reason string
|
||||||
var serviceID string
|
var serviceID string
|
||||||
var token string
|
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("maint", flag.ContinueOnError)
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
|
|
||||||
cmdFlags.BoolVar(&enable, "enable", false, "enable maintenance mode")
|
f.BoolVar(&enable, "enable", false, "Enable maintenance mode.")
|
||||||
cmdFlags.BoolVar(&disable, "disable", false, "disable maintenance mode")
|
f.BoolVar(&disable, "disable", false, "Disable maintenance mode.")
|
||||||
cmdFlags.StringVar(&reason, "reason", "", "maintenance reason")
|
f.StringVar(&reason, "reason", "", "Text describing the maintenance reason.")
|
||||||
cmdFlags.StringVar(&serviceID, "service", "", "service maintenance")
|
f.StringVar(&serviceID, "service", "", "Control maintenance mode for a specific service ID.")
|
||||||
cmdFlags.StringVar(&token, "token", "", "")
|
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
|
||||||
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,10 +75,7 @@ func (c *MaintCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and test the HTTP client
|
// Create and test the HTTP client
|
||||||
conf := api.DefaultConfig()
|
client, err := c.Command.HTTPClient()
|
||||||
conf.Address = *httpAddr
|
|
||||||
conf.Token = token
|
|
||||||
client, err := api.NewClient(conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -4,17 +4,27 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/consul/consul/structs"
|
"github.com/hashicorp/consul/consul/structs"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testMaintCommand(t *testing.T) (*cli.MockUi, *MaintCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &MaintCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMaintCommand_implements(t *testing.T) {
|
func TestMaintCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &MaintCommand{}
|
var _ cli.Command = &MaintCommand{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMaintCommandRun_ConflictingArgs(t *testing.T) {
|
func TestMaintCommandRun_ConflictingArgs(t *testing.T) {
|
||||||
ui := new(cli.MockUi)
|
_, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
if code := c.Run([]string{"-enable", "-disable"}); code != 1 {
|
if code := c.Run([]string{"-enable", "-disable"}); code != 1 {
|
||||||
t.Fatalf("expected return code 1, got %d", code)
|
t.Fatalf("expected return code 1, got %d", code)
|
||||||
|
@ -53,8 +63,7 @@ func TestMaintCommandRun_NoArgs(t *testing.T) {
|
||||||
a1.agent.EnableNodeMaintenance("broken 2", "")
|
a1.agent.EnableNodeMaintenance("broken 2", "")
|
||||||
|
|
||||||
// Run consul maint with no args (list mode)
|
// Run consul maint with no args (list mode)
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{"-http-addr=" + a1.httpAddr}
|
args := []string{"-http-addr=" + a1.httpAddr}
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
|
@ -84,8 +93,7 @@ func TestMaintCommandRun_EnableNodeMaintenance(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a1.httpAddr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
|
@ -106,8 +114,7 @@ func TestMaintCommandRun_DisableNodeMaintenance(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a1.httpAddr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
|
@ -136,8 +143,7 @@ func TestMaintCommandRun_EnableServiceMaintenance(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a1.httpAddr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
|
@ -168,8 +174,7 @@ func TestMaintCommandRun_DisableServiceMaintenance(t *testing.T) {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a1.httpAddr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
|
@ -190,8 +195,7 @@ func TestMaintCommandRun_ServiceMaintenance_NoService(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMaintCommand(t)
|
||||||
c := &MaintCommand{Ui: ui}
|
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a1.httpAddr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hashicorp/consul/command/agent"
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"github.com/ryanuber/columnize"
|
|
||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
consulapi "github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
|
"github.com/hashicorp/serf/serf"
|
||||||
|
"github.com/ryanuber/columnize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MembersCommand is a Command implementation that queries a running
|
// MembersCommand is a Command implementation that queries a running
|
||||||
// Consul agent what members are part of the cluster currently.
|
// Consul agent what members are part of the cluster currently.
|
||||||
type MembersCommand struct {
|
type MembersCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MembersCommand) Help() string {
|
func (c *MembersCommand) Help() string {
|
||||||
|
@ -24,18 +25,8 @@ Usage: consul members [options]
|
||||||
|
|
||||||
Outputs the members of a running Consul agent.
|
Outputs the members of a running Consul agent.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-detailed Provides detailed information about nodes
|
|
||||||
|
|
||||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
|
||||||
|
|
||||||
-status=<regexp> If provided, output is filtered to only nodes matching
|
|
||||||
the regular expression for status
|
|
||||||
|
|
||||||
-wan If the agent is in server mode, this can be used to return
|
|
||||||
the other peers in the WAN pool
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,13 +34,18 @@ func (c *MembersCommand) Run(args []string) int {
|
||||||
var detailed bool
|
var detailed bool
|
||||||
var wan bool
|
var wan bool
|
||||||
var statusFilter string
|
var statusFilter string
|
||||||
cmdFlags := flag.NewFlagSet("members", flag.ContinueOnError)
|
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.BoolVar(&detailed, "detailed", false, "detailed output")
|
f.BoolVar(&detailed, "detailed", false,
|
||||||
cmdFlags.BoolVar(&wan, "wan", false, "wan members")
|
"Provides detailed information about nodes.")
|
||||||
cmdFlags.StringVar(&statusFilter, "status", ".*", "status filter")
|
f.BoolVar(&wan, "wan", false,
|
||||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
"If the agent is in server mode, this can be used to return the other "+
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
"peers in the WAN pool.")
|
||||||
|
f.StringVar(&statusFilter, "status", ".*",
|
||||||
|
"If provided, output is filtered to only nodes matching the regular "+
|
||||||
|
"expression for status.")
|
||||||
|
|
||||||
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,19 +56,13 @@ func (c *MembersCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := RPCClient(*rpcAddr)
|
client, err := c.Command.HTTPClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
var members []agent.Member
|
members, err := client.Agent().Members(wan)
|
||||||
if wan {
|
|
||||||
members, err = client.WANMembers()
|
|
||||||
} else {
|
|
||||||
members, err = client.LANMembers()
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error retrieving members: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error retrieving members: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
@ -82,7 +72,8 @@ func (c *MembersCommand) Run(args []string) int {
|
||||||
n := len(members)
|
n := len(members)
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
member := members[i]
|
member := members[i]
|
||||||
if !statusRe.MatchString(member.Status) {
|
statusString := serf.MemberStatus(member.Status).String()
|
||||||
|
if !statusRe.MatchString(statusString) {
|
||||||
members[i], members[n-1] = members[n-1], members[i]
|
members[i], members[n-1] = members[n-1], members[i]
|
||||||
i--
|
i--
|
||||||
n--
|
n--
|
||||||
|
@ -114,7 +105,7 @@ func (c *MembersCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// so we can sort members by name
|
// so we can sort members by name
|
||||||
type ByMemberName []agent.Member
|
type ByMemberName []*consulapi.AgentMember
|
||||||
|
|
||||||
func (m ByMemberName) Len() int { return len(m) }
|
func (m ByMemberName) Len() int { return len(m) }
|
||||||
func (m ByMemberName) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
|
func (m ByMemberName) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
|
||||||
|
@ -122,12 +113,12 @@ func (m ByMemberName) Less(i, j int) bool { return m[i].Name < m[j].Name }
|
||||||
|
|
||||||
// standardOutput is used to dump the most useful information about nodes
|
// standardOutput is used to dump the most useful information about nodes
|
||||||
// in a more human-friendly format
|
// in a more human-friendly format
|
||||||
func (c *MembersCommand) standardOutput(members []agent.Member) []string {
|
func (c *MembersCommand) standardOutput(members []*consulapi.AgentMember) []string {
|
||||||
result := make([]string, 0, len(members))
|
result := make([]string, 0, len(members))
|
||||||
header := "Node|Address|Status|Type|Build|Protocol|DC"
|
header := "Node|Address|Status|Type|Build|Protocol|DC"
|
||||||
result = append(result, header)
|
result = append(result, header)
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
addr := net.TCPAddr{IP: member.Addr, Port: int(member.Port)}
|
addr := net.TCPAddr{IP: net.ParseIP(member.Addr), Port: int(member.Port)}
|
||||||
protocol := member.Tags["vsn"]
|
protocol := member.Tags["vsn"]
|
||||||
build := member.Tags["build"]
|
build := member.Tags["build"]
|
||||||
if build == "" {
|
if build == "" {
|
||||||
|
@ -137,18 +128,19 @@ func (c *MembersCommand) standardOutput(members []agent.Member) []string {
|
||||||
}
|
}
|
||||||
dc := member.Tags["dc"]
|
dc := member.Tags["dc"]
|
||||||
|
|
||||||
|
statusString := serf.MemberStatus(member.Status).String()
|
||||||
switch member.Tags["role"] {
|
switch member.Tags["role"] {
|
||||||
case "node":
|
case "node":
|
||||||
line := fmt.Sprintf("%s|%s|%s|client|%s|%s|%s",
|
line := fmt.Sprintf("%s|%s|%s|client|%s|%s|%s",
|
||||||
member.Name, addr.String(), member.Status, build, protocol, dc)
|
member.Name, addr.String(), statusString, build, protocol, dc)
|
||||||
result = append(result, line)
|
result = append(result, line)
|
||||||
case "consul":
|
case "consul":
|
||||||
line := fmt.Sprintf("%s|%s|%s|server|%s|%s|%s",
|
line := fmt.Sprintf("%s|%s|%s|server|%s|%s|%s",
|
||||||
member.Name, addr.String(), member.Status, build, protocol, dc)
|
member.Name, addr.String(), statusString, build, protocol, dc)
|
||||||
result = append(result, line)
|
result = append(result, line)
|
||||||
default:
|
default:
|
||||||
line := fmt.Sprintf("%s|%s|%s|unknown|||",
|
line := fmt.Sprintf("%s|%s|%s|unknown|||",
|
||||||
member.Name, addr.String(), member.Status)
|
member.Name, addr.String(), statusString)
|
||||||
result = append(result, line)
|
result = append(result, line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,7 +149,7 @@ func (c *MembersCommand) standardOutput(members []agent.Member) []string {
|
||||||
|
|
||||||
// detailedOutput is used to dump all known information about nodes in
|
// detailedOutput is used to dump all known information about nodes in
|
||||||
// their raw format
|
// their raw format
|
||||||
func (c *MembersCommand) detailedOutput(members []agent.Member) []string {
|
func (c *MembersCommand) detailedOutput(members []*consulapi.AgentMember) []string {
|
||||||
result := make([]string, 0, len(members))
|
result := make([]string, 0, len(members))
|
||||||
header := "Node|Address|Status|Tags"
|
header := "Node|Address|Status|Tags"
|
||||||
result = append(result, header)
|
result = append(result, header)
|
||||||
|
@ -177,9 +169,9 @@ func (c *MembersCommand) detailedOutput(members []agent.Member) []string {
|
||||||
|
|
||||||
tags := strings.Join(tagPairs, ",")
|
tags := strings.Join(tagPairs, ",")
|
||||||
|
|
||||||
addr := net.TCPAddr{IP: member.Addr, Port: int(member.Port)}
|
addr := net.TCPAddr{IP: net.ParseIP(member.Addr), Port: int(member.Port)}
|
||||||
line := fmt.Sprintf("%s|%s|%s|%s",
|
line := fmt.Sprintf("%s|%s|%s|%s",
|
||||||
member.Name, addr.String(), member.Status, tags)
|
member.Name, addr.String(), serf.MemberStatus(member.Status).String(), tags)
|
||||||
result = append(result, line)
|
result = append(result, line)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -2,11 +2,22 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testMembersCommand(t *testing.T) (*cli.MockUi, *MembersCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &MembersCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMembersCommand_implements(t *testing.T) {
|
func TestMembersCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &MembersCommand{}
|
var _ cli.Command = &MembersCommand{}
|
||||||
}
|
}
|
||||||
|
@ -15,9 +26,8 @@ func TestMembersCommandRun(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMembersCommand(t)
|
||||||
c := &MembersCommand{Ui: ui}
|
args := []string{"-http-addr=" + a1.httpAddr}
|
||||||
args := []string{"-rpc-addr=" + a1.addr}
|
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
|
@ -44,9 +54,8 @@ func TestMembersCommandRun_WAN(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMembersCommand(t)
|
||||||
c := &MembersCommand{Ui: ui}
|
args := []string{"-http-addr=" + a1.httpAddr, "-wan"}
|
||||||
args := []string{"-rpc-addr=" + a1.addr, "-wan"}
|
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
|
@ -62,10 +71,9 @@ func TestMembersCommandRun_statusFilter(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMembersCommand(t)
|
||||||
c := &MembersCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-rpc-addr=" + a1.addr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
"-status=a.*e",
|
"-status=a.*e",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,10 +91,9 @@ func TestMembersCommandRun_statusFilter_failed(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
a1 := testAgent(t)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testMembersCommand(t)
|
||||||
c := &MembersCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-rpc-addr=" + a1.addr,
|
"-http-addr=" + a1.httpAddr,
|
||||||
"-status=(fail|left)",
|
"-status=(fail|left)",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hashicorp/logutils"
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MonitorCommand is a Command implementation that queries a running
|
// MonitorCommand is a Command implementation that queries a running
|
||||||
// Consul agent what members are part of the cluster currently.
|
// Consul agent what members are part of the cluster currently.
|
||||||
type MonitorCommand struct {
|
type MonitorCommand struct {
|
||||||
|
base.Command
|
||||||
|
|
||||||
ShutdownCh <-chan struct{}
|
ShutdownCh <-chan struct{}
|
||||||
Ui cli.Ui
|
|
||||||
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
quitting bool
|
quitting bool
|
||||||
|
@ -29,40 +29,34 @@ Usage: consul monitor [options]
|
||||||
example your agent may only be logging at INFO level, but with the monitor
|
example your agent may only be logging at INFO level, but with the monitor
|
||||||
you can see the DEBUG level logs.
|
you can see the DEBUG level logs.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-log-level=info Log level of the agent.
|
|
||||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MonitorCommand) Run(args []string) int {
|
func (c *MonitorCommand) Run(args []string) int {
|
||||||
var logLevel string
|
var logLevel string
|
||||||
cmdFlags := flag.NewFlagSet("monitor", flag.ContinueOnError)
|
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.StringVar(&logLevel, "log-level", "INFO", "log level")
|
f.StringVar(&logLevel, "log-level", "INFO", "Log level of the agent.")
|
||||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := RPCClient(*rpcAddr)
|
client, err := c.Command.HTTPClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
logCh := make(chan string, 1024)
|
eventDoneCh := make(chan struct{})
|
||||||
monHandle, err := client.Monitor(logutils.LogLevel(logLevel), logCh)
|
logCh, err := client.Agent().Monitor(logLevel, eventDoneCh, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error starting monitor: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error starting monitor: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer client.Stop(monHandle)
|
|
||||||
|
|
||||||
eventDoneCh := make(chan struct{})
|
|
||||||
go func() {
|
go func() {
|
||||||
defer close(eventDoneCh)
|
defer close(eventDoneCh)
|
||||||
OUTER:
|
OUTER:
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"flag"
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/ryanuber/columnize"
|
"github.com/ryanuber/columnize"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OperatorCommand is used to provide various low-level tools for Consul
|
// OperatorCommand is used to provide various low-level tools for Consul
|
||||||
// operators.
|
// operators.
|
||||||
type OperatorCommand struct {
|
type OperatorCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OperatorCommand) Help() string {
|
func (c *OperatorCommand) Help() string {
|
||||||
helpText := `
|
helpText := `
|
||||||
Usage: consul operator <subcommand> [common options] [action] [options]
|
Usage: consul operator <subcommand> [action] [options]
|
||||||
|
|
||||||
Provides cluster-level tools for Consul operators, such as interacting with
|
Provides cluster-level tools for Consul operators, such as interacting with
|
||||||
the Raft subsystem. NOTE: Use this command with extreme caution, as improper
|
the Raft subsystem. NOTE: Use this command with extreme caution, as improper
|
||||||
|
@ -31,11 +31,6 @@ Usage: consul operator <subcommand> [common options] [action] [options]
|
||||||
Run consul operator <subcommand> with no arguments for help on that
|
Run consul operator <subcommand> with no arguments for help on that
|
||||||
subcommand.
|
subcommand.
|
||||||
|
|
||||||
Common Options:
|
|
||||||
|
|
||||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
|
||||||
-token="" ACL token to use. Defaults to that of agent.
|
|
||||||
|
|
||||||
Subcommands:
|
Subcommands:
|
||||||
|
|
||||||
raft View and modify Consul's Raft configuration.
|
raft View and modify Consul's Raft configuration.
|
||||||
|
@ -73,17 +68,15 @@ func (c *OperatorCommand) Synopsis() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
const raftHelp = `
|
const raftHelp = `
|
||||||
Raft Subcommand Actions:
|
Operator Raft Subcommand:
|
||||||
|
|
||||||
raft -list-peers -stale=[true|false]
|
The raft subcommand can be used in two modes:
|
||||||
|
|
||||||
|
consul operator raft -list-peers
|
||||||
|
|
||||||
Displays the current Raft peer configuration.
|
Displays the current Raft peer configuration.
|
||||||
|
|
||||||
The -stale argument defaults to "false" which means the leader provides the
|
consul operator raft -remove-peer -address="IP:port"
|
||||||
result. If the cluster is in an outage state without a leader, you may need
|
|
||||||
to set -stale to "true" to get the configuration from a non-leader server.
|
|
||||||
|
|
||||||
raft -remove-peer -address="IP:port"
|
|
||||||
|
|
||||||
Removes Consul server with given -address from the Raft configuration.
|
Removes Consul server with given -address from the Raft configuration.
|
||||||
|
|
||||||
|
@ -93,33 +86,39 @@ Raft Subcommand Actions:
|
||||||
affects the Raft quorum. If the server still shows in the output of the
|
affects the Raft quorum. If the server still shows in the output of the
|
||||||
"consul members" command, it is preferable to clean up by simply running
|
"consul members" command, it is preferable to clean up by simply running
|
||||||
"consul force-leave" instead of this command.
|
"consul force-leave" instead of this command.
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
// raft handles the raft subcommands.
|
// raft handles the raft subcommands.
|
||||||
func (c *OperatorCommand) raft(args []string) error {
|
func (c *OperatorCommand) raft(args []string) error {
|
||||||
cmdFlags := flag.NewFlagSet("raft", flag.ContinueOnError)
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
|
|
||||||
// Parse verb arguments.
|
// Parse verb arguments.
|
||||||
var listPeers, removePeer bool
|
var listPeers, removePeer bool
|
||||||
cmdFlags.BoolVar(&listPeers, "list-peers", false, "")
|
f.BoolVar(&listPeers, "list-peers", false,
|
||||||
cmdFlags.BoolVar(&removePeer, "remove-peer", false, "")
|
"If this flag is provided, the current Raft peer configuration will be "+
|
||||||
|
"displayed. If the cluster is in an outage state without a leader, you may need "+
|
||||||
|
"to set -stale to 'true' to get the configuration from a non-leader server.")
|
||||||
|
f.BoolVar(&removePeer, "remove-peer", false,
|
||||||
|
"If this flag is provided, the Consul server with the given -address will be "+
|
||||||
|
"removed from the Raft configuration.")
|
||||||
|
|
||||||
// Parse other arguments.
|
// Parse other arguments.
|
||||||
var stale bool
|
var address string
|
||||||
var address, token string
|
f.StringVar(&address, "address", "",
|
||||||
cmdFlags.StringVar(&address, "address", "", "")
|
"The address to remove from the Raft configuration.")
|
||||||
cmdFlags.BoolVar(&stale, "stale", false, "")
|
|
||||||
cmdFlags.StringVar(&token, "token", "", "")
|
if err := c.Command.Parse(args); err != nil {
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
if err == flag.ErrHelp {
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
c.Ui.Output("")
|
||||||
|
c.Ui.Output(strings.TrimSpace(raftHelp + c.Command.Help()))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up a client.
|
// Set up a client.
|
||||||
conf := api.DefaultConfig()
|
client, err := c.Command.HTTPClient()
|
||||||
conf.Address = *httpAddr
|
|
||||||
client, err := api.NewClient(conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error connecting to Consul agent: %s", err)
|
return fmt.Errorf("error connecting to Consul agent: %s", err)
|
||||||
}
|
}
|
||||||
|
@ -129,8 +128,7 @@ func (c *OperatorCommand) raft(args []string) error {
|
||||||
if listPeers {
|
if listPeers {
|
||||||
// Fetch the current configuration.
|
// Fetch the current configuration.
|
||||||
q := &api.QueryOptions{
|
q := &api.QueryOptions{
|
||||||
AllowStale: stale,
|
AllowStale: c.Command.HTTPStale(),
|
||||||
Token: token,
|
|
||||||
}
|
}
|
||||||
reply, err := operator.RaftGetConfiguration(q)
|
reply, err := operator.RaftGetConfiguration(q)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -156,17 +154,14 @@ func (c *OperatorCommand) raft(args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to kick the peer.
|
// Try to kick the peer.
|
||||||
w := &api.WriteOptions{
|
if err := operator.RaftRemovePeerByAddress(address, nil); err != nil {
|
||||||
Token: token,
|
|
||||||
}
|
|
||||||
if err := operator.RaftRemovePeerByAddress(address, w); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Ui.Output(fmt.Sprintf("Removed peer with address %q", address))
|
c.Ui.Output(fmt.Sprintf("Removed peer with address %q", address))
|
||||||
} else {
|
} else {
|
||||||
c.Ui.Output(c.Help())
|
c.Ui.Output(c.Help())
|
||||||
c.Ui.Output("")
|
c.Ui.Output("")
|
||||||
c.Ui.Output(strings.TrimSpace(raftHelp))
|
c.Ui.Output(strings.TrimSpace(raftHelp + c.Command.Help()))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -4,9 +4,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testOperatorCommand(t *testing.T) (*cli.MockUi, *OperatorCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &OperatorCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOperator_Implements(t *testing.T) {
|
func TestOperator_Implements(t *testing.T) {
|
||||||
var _ cli.Command = &OperatorCommand{}
|
var _ cli.Command = &OperatorCommand{}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +27,7 @@ func TestOperator_Raft_ListPeers(t *testing.T) {
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
waitForLeader(t, a1.httpAddr)
|
waitForLeader(t, a1.httpAddr)
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testOperatorCommand(t)
|
||||||
c := &OperatorCommand{Ui: ui}
|
|
||||||
args := []string{"raft", "-http-addr=" + a1.httpAddr, "-list-peers"}
|
args := []string{"raft", "-http-addr=" + a1.httpAddr, "-list-peers"}
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
|
@ -35,8 +45,7 @@ func TestOperator_Raft_RemovePeer(t *testing.T) {
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
waitForLeader(t, a1.httpAddr)
|
waitForLeader(t, a1.httpAddr)
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testOperatorCommand(t)
|
||||||
c := &OperatorCommand{Ui: ui}
|
|
||||||
args := []string{"raft", "-http-addr=" + a1.httpAddr, "-remove-peer", "-address=nope"}
|
args := []string{"raft", "-http-addr=" + a1.httpAddr, "-remove-peer", "-address=nope"}
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReloadCommand is a Command implementation that instructs
|
// ReloadCommand is a Command implementation that instructs
|
||||||
// the Consul agent to reload configurations
|
// the Consul agent to reload configurations
|
||||||
type ReloadCommand struct {
|
type ReloadCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ReloadCommand) Help() string {
|
func (c *ReloadCommand) Help() string {
|
||||||
|
@ -20,29 +19,25 @@ Usage: consul reload
|
||||||
Causes the agent to reload configurations. This can be used instead
|
Causes the agent to reload configurations. This can be used instead
|
||||||
of sending the SIGHUP signal to the agent.
|
of sending the SIGHUP signal to the agent.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-rpc-addr=127.0.0.1:8400 RPC address of the Consul agent.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ReloadCommand) Run(args []string) int {
|
func (c *ReloadCommand) Run(args []string) int {
|
||||||
cmdFlags := flag.NewFlagSet("reload", flag.ContinueOnError)
|
c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
rpcAddr := RPCAddrFlag(cmdFlags)
|
if err := c.Command.Parse(args); err != nil {
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := RPCClient(*rpcAddr)
|
client, err := c.Command.HTTPClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer client.Close()
|
|
||||||
|
|
||||||
if err := client.Reload(); err != nil {
|
if err := client.Agent().Reload(); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error reloading: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error reloading: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReloadCommand_implements(t *testing.T) {
|
func TestReloadCommand_implements(t *testing.T) {
|
||||||
|
@ -11,12 +13,24 @@ func TestReloadCommand_implements(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReloadCommandRun(t *testing.T) {
|
func TestReloadCommandRun(t *testing.T) {
|
||||||
a1 := testAgent(t)
|
reloadCh := make(chan chan error)
|
||||||
|
a1 := testAgentWithConfigReload(t, nil, reloadCh)
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
|
// Setup a dummy response to errCh to simulate a successful reload
|
||||||
|
go func() {
|
||||||
|
errCh := <-reloadCh
|
||||||
|
errCh <- nil
|
||||||
|
}()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &ReloadCommand{Ui: ui}
|
c := &ReloadCommand{
|
||||||
args := []string{"-rpc-addr=" + a1.addr}
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
args := []string{"-http-addr=" + a1.httpAddr}
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/serf/coordinate"
|
"github.com/hashicorp/serf/coordinate"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// RTTCommand is a Command implementation that allows users to query the
|
// RTTCommand is a Command implementation that allows users to query the
|
||||||
// estimated round trip time between nodes using network coordinates.
|
// estimated round trip time between nodes using network coordinates.
|
||||||
type RTTCommand struct {
|
type RTTCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RTTCommand) Help() string {
|
func (c *RTTCommand) Help() string {
|
||||||
|
@ -36,28 +34,24 @@ Usage: consul rtt [options] node1 [node2]
|
||||||
because they are maintained by independent Serf gossip pools, so they are
|
because they are maintained by independent Serf gossip pools, so they are
|
||||||
not compatible.
|
not compatible.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-wan Use WAN coordinates instead of LAN coordinates.
|
|
||||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RTTCommand) Run(args []string) int {
|
func (c *RTTCommand) Run(args []string) int {
|
||||||
var wan bool
|
var wan bool
|
||||||
|
|
||||||
cmdFlags := flag.NewFlagSet("rtt", flag.ContinueOnError)
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
|
|
||||||
cmdFlags.BoolVar(&wan, "wan", false, "wan")
|
f.BoolVar(&wan, "wan", false, "Use WAN coordinates instead of LAN coordinates.")
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// They must provide at least one node.
|
// They must provide at least one node.
|
||||||
nodes := cmdFlags.Args()
|
nodes := f.Args()
|
||||||
if len(nodes) < 1 || len(nodes) > 2 {
|
if len(nodes) < 1 || len(nodes) > 2 {
|
||||||
c.Ui.Error("One or two node names must be specified")
|
c.Ui.Error("One or two node names must be specified")
|
||||||
c.Ui.Error("")
|
c.Ui.Error("")
|
||||||
|
@ -66,9 +60,7 @@ func (c *RTTCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and test the HTTP client.
|
// Create and test the HTTP client.
|
||||||
conf := api.DefaultConfig()
|
client, err := c.Command.HTTPClient()
|
||||||
conf.Address = *httpAddr
|
|
||||||
client, err := api.NewClient(conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -7,19 +7,29 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/command/agent"
|
"github.com/hashicorp/consul/command/agent"
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/consul/consul/structs"
|
"github.com/hashicorp/consul/consul/structs"
|
||||||
"github.com/hashicorp/consul/testutil"
|
"github.com/hashicorp/consul/testutil"
|
||||||
"github.com/hashicorp/serf/coordinate"
|
"github.com/hashicorp/serf/coordinate"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testRTTCommand(t *testing.T) (*cli.MockUi, *RTTCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &RTTCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestRTTCommand_Implements(t *testing.T) {
|
func TestRTTCommand_Implements(t *testing.T) {
|
||||||
var _ cli.Command = &RTTCommand{}
|
var _ cli.Command = &RTTCommand{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRTTCommand_Run_BadArgs(t *testing.T) {
|
func TestRTTCommand_Run_BadArgs(t *testing.T) {
|
||||||
ui := new(cli.MockUi)
|
_, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
|
|
||||||
if code := c.Run([]string{}); code != 1 {
|
if code := c.Run([]string{}); code != 1 {
|
||||||
t.Fatalf("expected return code 1, got %d", code)
|
t.Fatalf("expected return code 1, got %d", code)
|
||||||
|
@ -90,8 +100,7 @@ func TestRTTCommand_Run_LAN(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ask for the RTT of two known nodes
|
// Ask for the RTT of two known nodes
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
a.config.NodeName,
|
a.config.NodeName,
|
||||||
|
@ -118,8 +127,7 @@ func TestRTTCommand_Run_LAN(t *testing.T) {
|
||||||
|
|
||||||
// Default to the agent's node.
|
// Default to the agent's node.
|
||||||
{
|
{
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
"dogs",
|
"dogs",
|
||||||
|
@ -138,8 +146,7 @@ func TestRTTCommand_Run_LAN(t *testing.T) {
|
||||||
|
|
||||||
// Try an unknown node.
|
// Try an unknown node.
|
||||||
{
|
{
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
a.config.NodeName,
|
a.config.NodeName,
|
||||||
|
@ -162,8 +169,7 @@ func TestRTTCommand_Run_WAN(t *testing.T) {
|
||||||
// We can't easily inject WAN coordinates, so we will just query the
|
// We can't easily inject WAN coordinates, so we will just query the
|
||||||
// node with itself.
|
// node with itself.
|
||||||
{
|
{
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-wan",
|
"-wan",
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
|
@ -183,8 +189,7 @@ func TestRTTCommand_Run_WAN(t *testing.T) {
|
||||||
|
|
||||||
// Default to the agent's node.
|
// Default to the agent's node.
|
||||||
{
|
{
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-wan",
|
"-wan",
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
|
@ -203,8 +208,7 @@ func TestRTTCommand_Run_WAN(t *testing.T) {
|
||||||
|
|
||||||
// Try an unknown node.
|
// Try an unknown node.
|
||||||
{
|
{
|
||||||
ui := new(cli.MockUi)
|
ui, c := testRTTCommand(t)
|
||||||
c := &RTTCommand{Ui: ui}
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"-wan",
|
"-wan",
|
||||||
"-http-addr=" + a.httpAddr,
|
"-http-addr=" + a.httpAddr,
|
||||||
|
|
|
@ -2,20 +2,19 @@ package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/consul/snapshot"
|
"github.com/hashicorp/consul/snapshot"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SnapshotInspectCommand is a Command implementation that is used to display
|
// SnapshotInspectCommand is a Command implementation that is used to display
|
||||||
// metadata about a snapshot file
|
// metadata about a snapshot file
|
||||||
type SnapshotInspectCommand struct {
|
type SnapshotInspectCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotInspectCommand) Help() string {
|
func (c *SnapshotInspectCommand) Help() string {
|
||||||
|
@ -35,15 +34,15 @@ Usage: consul snapshot inspect [options] FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotInspectCommand) Run(args []string) int {
|
func (c *SnapshotInspectCommand) Run(args []string) int {
|
||||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
flagSet := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var file string
|
var file string
|
||||||
|
|
||||||
args = cmdFlags.Args()
|
args = flagSet.Args()
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 0:
|
case 0:
|
||||||
c.Ui.Error("Missing FILE argument")
|
c.Ui.Error("Missing FILE argument")
|
||||||
|
|
|
@ -8,9 +8,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testSnapshotInspectCommand(t *testing.T) (*cli.MockUi, *SnapshotInspectCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &SnapshotInspectCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetNone,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSnapshotInspectCommand_implements(t *testing.T) {
|
func TestSnapshotInspectCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &SnapshotInspectCommand{}
|
var _ cli.Command = &SnapshotInspectCommand{}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +31,7 @@ func TestSnapshotInspectCommand_noTabs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnapshotInspectCommand_Validation(t *testing.T) {
|
func TestSnapshotInspectCommand_Validation(t *testing.T) {
|
||||||
ui := new(cli.MockUi)
|
ui, c := testSnapshotInspectCommand(t)
|
||||||
c := &SnapshotInspectCommand{Ui: ui}
|
|
||||||
|
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
args []string
|
args []string
|
||||||
|
@ -63,8 +73,6 @@ func TestSnapshotInspectCommand_Run(t *testing.T) {
|
||||||
defer srv.Shutdown()
|
defer srv.Shutdown()
|
||||||
waitForLeader(t, srv.httpAddr)
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "snapshot")
|
dir, err := ioutil.TempDir("", "snapshot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %v", err)
|
t.Fatalf("err: %v", err)
|
||||||
|
@ -93,10 +101,10 @@ func TestSnapshotInspectCommand_Run(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspect the snapshot
|
// Inspect the snapshot
|
||||||
inspect := &SnapshotInspectCommand{Ui: ui}
|
ui, c := testSnapshotInspectCommand(t)
|
||||||
args := []string{file}
|
args := []string{file}
|
||||||
|
|
||||||
code := inspect.Run(args)
|
code := c.Run(args)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SnapshotRestoreCommand is a Command implementation that is used to restore
|
// SnapshotRestoreCommand is a Command implementation that is used to restore
|
||||||
// the state of the Consul servers for disaster recovery.
|
// the state of the Consul servers for disaster recovery.
|
||||||
type SnapshotRestoreCommand struct {
|
type SnapshotRestoreCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotRestoreCommand) Help() string {
|
func (c *SnapshotRestoreCommand) Help() string {
|
||||||
|
@ -38,24 +36,21 @@ Usage: consul snapshot restore [options] FILE
|
||||||
|
|
||||||
For a full list of options and examples, please see the Consul documentation.
|
For a full list of options and examples, please see the Consul documentation.
|
||||||
|
|
||||||
` + apiOptsText
|
` + c.Command.Help()
|
||||||
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotRestoreCommand) Run(args []string) int {
|
func (c *SnapshotRestoreCommand) Run(args []string) int {
|
||||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
flagSet := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
datacenter := cmdFlags.String("datacenter", "", "")
|
if err := c.Command.Parse(args); err != nil {
|
||||||
token := cmdFlags.String("token", "", "")
|
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var file string
|
var file string
|
||||||
|
|
||||||
args = cmdFlags.Args()
|
args = flagSet.Args()
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 0:
|
case 0:
|
||||||
c.Ui.Error("Missing FILE argument")
|
c.Ui.Error("Missing FILE argument")
|
||||||
|
@ -68,11 +63,7 @@ func (c *SnapshotRestoreCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and test the HTTP client
|
// Create and test the HTTP client
|
||||||
conf := api.DefaultConfig()
|
client, err := c.Command.HTTPClient()
|
||||||
conf.Datacenter = *datacenter
|
|
||||||
conf.Address = *httpAddr
|
|
||||||
conf.Token = *token
|
|
||||||
client, err := api.NewClient(conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
|
|
@ -8,9 +8,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testSnapshotRestoreCommand(t *testing.T) (*cli.MockUi, *SnapshotRestoreCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &SnapshotRestoreCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSnapshotRestoreCommand_implements(t *testing.T) {
|
func TestSnapshotRestoreCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &SnapshotRestoreCommand{}
|
var _ cli.Command = &SnapshotRestoreCommand{}
|
||||||
}
|
}
|
||||||
|
@ -20,8 +31,7 @@ func TestSnapshotRestoreCommand_noTabs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnapshotRestoreCommand_Validation(t *testing.T) {
|
func TestSnapshotRestoreCommand_Validation(t *testing.T) {
|
||||||
ui := new(cli.MockUi)
|
ui, c := testSnapshotRestoreCommand(t)
|
||||||
c := &SnapshotRestoreCommand{Ui: ui}
|
|
||||||
|
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
args []string
|
args []string
|
||||||
|
@ -63,8 +73,7 @@ func TestSnapshotRestoreCommand_Run(t *testing.T) {
|
||||||
defer srv.Shutdown()
|
defer srv.Shutdown()
|
||||||
waitForLeader(t, srv.httpAddr)
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testSnapshotRestoreCommand(t)
|
||||||
c := &SnapshotSaveCommand{Ui: ui}
|
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "snapshot")
|
dir, err := ioutil.TempDir("", "snapshot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/api"
|
"github.com/hashicorp/consul/api"
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/consul/snapshot"
|
"github.com/hashicorp/consul/snapshot"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SnapshotSaveCommand is a Command implementation that is used to save the
|
// SnapshotSaveCommand is a Command implementation that is used to save the
|
||||||
// state of the Consul servers for disaster recovery.
|
// state of the Consul servers for disaster recovery.
|
||||||
type SnapshotSaveCommand struct {
|
type SnapshotSaveCommand struct {
|
||||||
Ui cli.Ui
|
base.Command
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotSaveCommand) Help() string {
|
func (c *SnapshotSaveCommand) Help() string {
|
||||||
|
@ -40,25 +39,21 @@ Usage: consul snapshot save [options] FILE
|
||||||
|
|
||||||
For a full list of options and examples, please see the Consul documentation.
|
For a full list of options and examples, please see the Consul documentation.
|
||||||
|
|
||||||
` + apiOptsText
|
` + c.Command.Help()
|
||||||
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *SnapshotSaveCommand) Run(args []string) int {
|
func (c *SnapshotSaveCommand) Run(args []string) int {
|
||||||
cmdFlags := flag.NewFlagSet("get", flag.ContinueOnError)
|
flagSet := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
|
||||||
datacenter := cmdFlags.String("datacenter", "", "")
|
if err := c.Command.Parse(args); err != nil {
|
||||||
token := cmdFlags.String("token", "", "")
|
|
||||||
stale := cmdFlags.Bool("stale", false, "")
|
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
var file string
|
var file string
|
||||||
|
|
||||||
args = cmdFlags.Args()
|
args = flagSet.Args()
|
||||||
switch len(args) {
|
switch len(args) {
|
||||||
case 0:
|
case 0:
|
||||||
c.Ui.Error("Missing FILE argument")
|
c.Ui.Error("Missing FILE argument")
|
||||||
|
@ -71,11 +66,7 @@ func (c *SnapshotSaveCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and test the HTTP client
|
// Create and test the HTTP client
|
||||||
conf := api.DefaultConfig()
|
client, err := c.Command.HTTPClient()
|
||||||
conf.Datacenter = *datacenter
|
|
||||||
conf.Address = *httpAddr
|
|
||||||
conf.Token = *token
|
|
||||||
client, err := api.NewClient(conf)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
@ -83,7 +74,7 @@ func (c *SnapshotSaveCommand) Run(args []string) int {
|
||||||
|
|
||||||
// Take the snapshot.
|
// Take the snapshot.
|
||||||
snap, qm, err := client.Snapshot().Save(&api.QueryOptions{
|
snap, qm, err := client.Snapshot().Save(&api.QueryOptions{
|
||||||
AllowStale: *stale,
|
AllowStale: c.Command.HTTPStale(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error saving snapshot: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error saving snapshot: %s", err))
|
||||||
|
|
|
@ -7,9 +7,20 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func testSnapshotSaveCommand(t *testing.T) (*cli.MockUi, *SnapshotSaveCommand) {
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
return ui, &SnapshotSaveCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSnapshotSaveCommand_implements(t *testing.T) {
|
func TestSnapshotSaveCommand_implements(t *testing.T) {
|
||||||
var _ cli.Command = &SnapshotSaveCommand{}
|
var _ cli.Command = &SnapshotSaveCommand{}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +30,7 @@ func TestSnapshotSaveCommand_noTabs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSnapshotSaveCommand_Validation(t *testing.T) {
|
func TestSnapshotSaveCommand_Validation(t *testing.T) {
|
||||||
ui := new(cli.MockUi)
|
ui, c := testSnapshotSaveCommand(t)
|
||||||
c := &SnapshotSaveCommand{Ui: ui}
|
|
||||||
|
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
args []string
|
args []string
|
||||||
|
@ -62,8 +72,7 @@ func TestSnapshotSaveCommand_Run(t *testing.T) {
|
||||||
defer srv.Shutdown()
|
defer srv.Shutdown()
|
||||||
waitForLeader(t, srv.httpAddr)
|
waitForLeader(t, srv.httpAddr)
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui, c := testSnapshotSaveCommand(t)
|
||||||
c := &SnapshotSaveCommand{Ui: ui}
|
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "snapshot")
|
dir, err := ioutil.TempDir("", "snapshot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -44,7 +44,7 @@ func (a *agentWrapper) Shutdown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAgent(t *testing.T) *agentWrapper {
|
func testAgent(t *testing.T) *agentWrapper {
|
||||||
return testAgentWithConfig(t, func(c *agent.Config) {})
|
return testAgentWithConfig(t, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAgentWithAPIClient(t *testing.T) (*agentWrapper, *api.Client) {
|
func testAgentWithAPIClient(t *testing.T) (*agentWrapper, *api.Client) {
|
||||||
|
@ -57,6 +57,10 @@ func testAgentWithAPIClient(t *testing.T) (*agentWrapper, *api.Client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAgentWithConfig(t *testing.T, cb func(c *agent.Config)) *agentWrapper {
|
func testAgentWithConfig(t *testing.T, cb func(c *agent.Config)) *agentWrapper {
|
||||||
|
return testAgentWithConfigReload(t, cb, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAgentWithConfigReload(t *testing.T, cb func(c *agent.Config), reloadCh chan chan error) *agentWrapper {
|
||||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %s", err)
|
t.Fatalf("err: %s", err)
|
||||||
|
@ -66,7 +70,9 @@ func testAgentWithConfig(t *testing.T, cb func(c *agent.Config)) *agentWrapper {
|
||||||
mult := io.MultiWriter(os.Stderr, lw)
|
mult := io.MultiWriter(os.Stderr, lw)
|
||||||
|
|
||||||
conf := nextConfig()
|
conf := nextConfig()
|
||||||
cb(conf)
|
if cb != nil {
|
||||||
|
cb(conf)
|
||||||
|
}
|
||||||
|
|
||||||
dir, err := ioutil.TempDir("", "agent")
|
dir, err := ioutil.TempDir("", "agent")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,7 +80,7 @@ func testAgentWithConfig(t *testing.T, cb func(c *agent.Config)) *agentWrapper {
|
||||||
}
|
}
|
||||||
conf.DataDir = dir
|
conf.DataDir = dir
|
||||||
|
|
||||||
a, err := agent.Create(conf, lw, nil, nil)
|
a, err := agent.Create(conf, lw, nil, reloadCh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.RemoveAll(dir)
|
os.RemoveAll(dir)
|
||||||
t.Fatalf(fmt.Sprintf("err: %v", err))
|
t.Fatalf(fmt.Sprintf("err: %v", err))
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVersionCommand_implements(t *testing.T) {
|
func TestVersionCommand_implements(t *testing.T) {
|
||||||
|
|
|
@ -3,22 +3,21 @@ package command
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/consul/command/agent"
|
"github.com/hashicorp/consul/command/agent"
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
"github.com/hashicorp/consul/watch"
|
"github.com/hashicorp/consul/watch"
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// WatchCommand is a Command implementation that is used to setup
|
// WatchCommand is a Command implementation that is used to setup
|
||||||
// a "watch" which uses a sub-process
|
// a "watch" which uses a sub-process
|
||||||
type WatchCommand struct {
|
type WatchCommand struct {
|
||||||
|
base.Command
|
||||||
ShutdownCh <-chan struct{}
|
ShutdownCh <-chan struct{}
|
||||||
Ui cli.Ui
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WatchCommand) Help() string {
|
func (c *WatchCommand) Help() string {
|
||||||
|
@ -32,49 +31,36 @@ Usage: consul watch [options] [child...]
|
||||||
Providing the watch type is required, and other parameters may be required
|
Providing the watch type is required, and other parameters may be required
|
||||||
or supported depending on the watch type.
|
or supported depending on the watch type.
|
||||||
|
|
||||||
Options:
|
` + c.Command.Help()
|
||||||
|
|
||||||
-http-addr=127.0.0.1:8500 HTTP address of the Consul agent.
|
|
||||||
-datacenter="" Datacenter to query. Defaults to that of agent.
|
|
||||||
-token="" ACL token to use. Defaults to that of agent.
|
|
||||||
-stale=[true|false] Specifies if watch data is permitted to be stale.
|
|
||||||
Defaults to false.
|
|
||||||
|
|
||||||
Watch Specification:
|
|
||||||
|
|
||||||
-key=val Specifies the key to watch. Only for 'key' type.
|
|
||||||
-name=val Specifies an event name to watch. Only for 'event' type.
|
|
||||||
-passingonly=[true|false] Specifies if only hosts passing all checks are displayed.
|
|
||||||
Optional for 'service' type. Defaults false.
|
|
||||||
-prefix=val Specifies the key prefix to watch. Only for 'keyprefix' type.
|
|
||||||
-service=val Specifies the service to watch. Required for 'service' type,
|
|
||||||
optional for 'checks' type.
|
|
||||||
-state=val Specifies the states to watch. Optional for 'checks' type.
|
|
||||||
-tag=val Specifies the service tag to filter on. Optional for 'service'
|
|
||||||
type.
|
|
||||||
-type=val Specifies the watch type. One of key, keyprefix
|
|
||||||
services, nodes, service, checks, or event.
|
|
||||||
`
|
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WatchCommand) Run(args []string) int {
|
func (c *WatchCommand) Run(args []string) int {
|
||||||
var watchType, datacenter, token, key, prefix, service, tag, passingOnly, stale, state, name string
|
var watchType, key, prefix, service, tag, passingOnly, state, name string
|
||||||
cmdFlags := flag.NewFlagSet("watch", flag.ContinueOnError)
|
|
||||||
cmdFlags.Usage = func() { c.Ui.Output(c.Help()) }
|
f := c.Command.NewFlagSet(c)
|
||||||
cmdFlags.StringVar(&watchType, "type", "", "")
|
f.StringVar(&watchType, "type", "",
|
||||||
cmdFlags.StringVar(&datacenter, "datacenter", "", "")
|
"Specifies the watch type. One of key, keyprefix services, nodes, "+
|
||||||
cmdFlags.StringVar(&token, "token", "", "")
|
"service, checks, or event.")
|
||||||
cmdFlags.StringVar(&key, "key", "", "")
|
f.StringVar(&key, "key", "",
|
||||||
cmdFlags.StringVar(&prefix, "prefix", "", "")
|
"Specifies the key to watch. Only for 'key' type.")
|
||||||
cmdFlags.StringVar(&service, "service", "", "")
|
f.StringVar(&prefix, "prefix", "",
|
||||||
cmdFlags.StringVar(&tag, "tag", "", "")
|
"Specifies the key prefix to watch. Only for 'keyprefix' type.")
|
||||||
cmdFlags.StringVar(&passingOnly, "passingonly", "", "")
|
f.StringVar(&service, "service", "",
|
||||||
cmdFlags.StringVar(&stale, "stale", "", "")
|
"Specifies the service to watch. Required for 'service' type, "+
|
||||||
cmdFlags.StringVar(&state, "state", "", "")
|
"optional for 'checks' type.")
|
||||||
cmdFlags.StringVar(&name, "name", "", "")
|
f.StringVar(&tag, "tag", "",
|
||||||
httpAddr := HTTPAddrFlag(cmdFlags)
|
"Specifies the service tag to filter on. Optional for 'service' type.")
|
||||||
if err := cmdFlags.Parse(args); err != nil {
|
f.StringVar(&passingOnly, "passingonly", "",
|
||||||
|
"Specifies if only hosts passing all checks are displayed. "+
|
||||||
|
"Optional for 'service' type, must be one of `[true|false]`. Defaults false.")
|
||||||
|
f.StringVar(&state, "state", "",
|
||||||
|
"Specifies the states to watch. Optional for 'checks' type.")
|
||||||
|
f.StringVar(&name, "name", "",
|
||||||
|
"Specifies an event name to watch. Only for 'event' type.")
|
||||||
|
|
||||||
|
if err := c.Command.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,18 +73,18 @@ func (c *WatchCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grab the script to execute if any
|
// Grab the script to execute if any
|
||||||
script := strings.Join(cmdFlags.Args(), " ")
|
script := strings.Join(f.Args(), " ")
|
||||||
|
|
||||||
// Compile the watch parameters
|
// Compile the watch parameters
|
||||||
params := make(map[string]interface{})
|
params := make(map[string]interface{})
|
||||||
if watchType != "" {
|
if watchType != "" {
|
||||||
params["type"] = watchType
|
params["type"] = watchType
|
||||||
}
|
}
|
||||||
if datacenter != "" {
|
if c.Command.HTTPDatacenter() != "" {
|
||||||
params["datacenter"] = datacenter
|
params["datacenter"] = c.Command.HTTPDatacenter()
|
||||||
}
|
}
|
||||||
if token != "" {
|
if c.Command.HTTPToken() != "" {
|
||||||
params["token"] = token
|
params["token"] = c.Command.HTTPToken()
|
||||||
}
|
}
|
||||||
if key != "" {
|
if key != "" {
|
||||||
params["key"] = key
|
params["key"] = key
|
||||||
|
@ -112,13 +98,8 @@ func (c *WatchCommand) Run(args []string) int {
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
params["tag"] = tag
|
params["tag"] = tag
|
||||||
}
|
}
|
||||||
if stale != "" {
|
if c.Command.HTTPStale() {
|
||||||
b, err := strconv.ParseBool(stale)
|
params["stale"] = c.Command.HTTPStale()
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf("Failed to parse stale flag: %s", err))
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
params["stale"] = b
|
|
||||||
}
|
}
|
||||||
if state != "" {
|
if state != "" {
|
||||||
params["state"] = state
|
params["state"] = state
|
||||||
|
@ -143,7 +124,7 @@ func (c *WatchCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create and test the HTTP client
|
// Create and test the HTTP client
|
||||||
client, err := HTTPClient(*httpAddr)
|
client, err := c.Command.HTTPClient()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
|
@ -213,7 +194,7 @@ func (c *WatchCommand) Run(args []string) int {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Run the watch
|
// Run the watch
|
||||||
if err := wp.Run(*httpAddr); err != nil {
|
if err := wp.Run(c.Command.HTTPAddr()); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error querying Consul agent: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/command/base"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWatchCommand_implements(t *testing.T) {
|
func TestWatchCommand_implements(t *testing.T) {
|
||||||
|
@ -15,7 +17,12 @@ func TestWatchCommandRun(t *testing.T) {
|
||||||
defer a1.Shutdown()
|
defer a1.Shutdown()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
c := &WatchCommand{Ui: ui}
|
c := &WatchCommand{
|
||||||
|
Command: base.Command{
|
||||||
|
Ui: ui,
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
},
|
||||||
|
}
|
||||||
args := []string{"-http-addr=" + a1.httpAddr, "-type=nodes"}
|
args := []string{"-http-addr=" + a1.httpAddr, "-type=nodes"}
|
||||||
|
|
||||||
code := c.Run(args)
|
code := c.Run(args)
|
||||||
|
|
55
commands.go
55
commands.go
|
@ -159,7 +159,10 @@ func init() {
|
||||||
|
|
||||||
"leave": func() (cli.Command, error) {
|
"leave": func() (cli.Command, error) {
|
||||||
return &command.LeaveCommand{
|
return &command.LeaveCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -175,38 +178,56 @@ func init() {
|
||||||
|
|
||||||
"maint": func() (cli.Command, error) {
|
"maint": func() (cli.Command, error) {
|
||||||
return &command.MaintCommand{
|
return &command.MaintCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"members": func() (cli.Command, error) {
|
"members": func() (cli.Command, error) {
|
||||||
return &command.MembersCommand{
|
return &command.MembersCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"monitor": func() (cli.Command, error) {
|
"monitor": func() (cli.Command, error) {
|
||||||
return &command.MonitorCommand{
|
return &command.MonitorCommand{
|
||||||
ShutdownCh: makeShutdownCh(),
|
ShutdownCh: makeShutdownCh(),
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"operator": func() (cli.Command, error) {
|
"operator": func() (cli.Command, error) {
|
||||||
return &command.OperatorCommand{
|
return &command.OperatorCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"reload": func() (cli.Command, error) {
|
"reload": func() (cli.Command, error) {
|
||||||
return &command.ReloadCommand{
|
return &command.ReloadCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"rtt": func() (cli.Command, error) {
|
"rtt": func() (cli.Command, error) {
|
||||||
return &command.RTTCommand{
|
return &command.RTTCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetClientHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -218,19 +239,28 @@ func init() {
|
||||||
|
|
||||||
"snapshot restore": func() (cli.Command, error) {
|
"snapshot restore": func() (cli.Command, error) {
|
||||||
return &command.SnapshotRestoreCommand{
|
return &command.SnapshotRestoreCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"snapshot save": func() (cli.Command, error) {
|
"snapshot save": func() (cli.Command, error) {
|
||||||
return &command.SnapshotSaveCommand{
|
return &command.SnapshotSaveCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
"snapshot inspect": func() (cli.Command, error) {
|
"snapshot inspect": func() (cli.Command, error) {
|
||||||
return &command.SnapshotInspectCommand{
|
return &command.SnapshotInspectCommand{
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetNone,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -244,7 +274,10 @@ func init() {
|
||||||
"watch": func() (cli.Command, error) {
|
"watch": func() (cli.Command, error) {
|
||||||
return &command.WatchCommand{
|
return &command.WatchCommand{
|
||||||
ShutdownCh: makeShutdownCh(),
|
ShutdownCh: makeShutdownCh(),
|
||||||
Ui: ui,
|
Command: base.Command{
|
||||||
|
Flags: base.FlagSetHTTP,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
}, nil
|
}, nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,8 @@ non-graceful leave can affect cluster availability.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Usage: `consul leave`
|
Usage: `consul leave [options]`
|
||||||
|
|
||||||
The command-line flags are all optional. The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
* `-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".
|
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options_client" %>
|
|
@ -24,9 +24,11 @@ health check.
|
||||||
|
|
||||||
Usage: `consul maint [options]`
|
Usage: `consul maint [options]`
|
||||||
|
|
||||||
All of the command line arguments are optional.
|
#### API Options
|
||||||
|
|
||||||
The list of available flags are:
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
|
||||||
|
#### Command Options
|
||||||
|
|
||||||
* `-enable` - Enable maintenance mode on a given service or node. If
|
* `-enable` - Enable maintenance mode on a given service or node. If
|
||||||
combined with the `-service` flag, we operate on a specific service ID.
|
combined with the `-service` flag, we operate on a specific service ID.
|
||||||
|
@ -44,12 +46,6 @@ The list of available flags are:
|
||||||
providing this flag, the `-enable` and `-disable` flags functionality is
|
providing this flag, the `-enable` and `-disable` flags functionality is
|
||||||
modified to operate on the given service ID.
|
modified to operate on the given service ID.
|
||||||
|
|
||||||
* `-token` - ACL token to use. Defaults to that of agent.
|
|
||||||
|
|
||||||
* `-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.
|
|
||||||
|
|
||||||
## List mode
|
## List mode
|
||||||
|
|
||||||
If neither `-enable` nor `-disable` are passed, the `maint` command will
|
If neither `-enable` nor `-disable` are passed, the `maint` command will
|
|
@ -22,16 +22,15 @@ that the failure is actually just a network partition.
|
||||||
|
|
||||||
Usage: `consul members [options]`
|
Usage: `consul members [options]`
|
||||||
|
|
||||||
The command-line flags are all optional. The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
|
||||||
|
#### Command Options
|
||||||
|
|
||||||
* `-detailed` - If provided, output shows more detailed information
|
* `-detailed` - If provided, output shows more detailed information
|
||||||
about each node.
|
about each node.
|
||||||
|
|
||||||
* `-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".
|
|
||||||
|
|
||||||
* `-status` - If provided, output is filtered to only nodes matching
|
* `-status` - If provided, output is filtered to only nodes matching
|
||||||
the regular expression for status
|
the regular expression for status
|
||||||
|
|
|
@ -22,14 +22,13 @@ logs and watch the debug logs if necessary.
|
||||||
|
|
||||||
Usage: `consul monitor [options]`
|
Usage: `consul monitor [options]`
|
||||||
|
|
||||||
The command-line flags are all optional. The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
|
||||||
|
#### Command Options
|
||||||
|
|
||||||
* `-log-level` - The log level of the messages to show. By default this
|
* `-log-level` - The log level of the messages to show. By default this
|
||||||
is "info". This log level can be more verbose than what the agent is
|
is "info". This log level can be more verbose than what the agent is
|
||||||
configured to run at. Available log levels are "trace", "debug", "info",
|
configured to run at. Available log levels are "trace", "debug", "info",
|
||||||
"warn", and "err".
|
"warn", and "err".
|
||||||
|
|
||||||
* `-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".
|
|
|
@ -28,20 +28,17 @@ endpoint.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Usage: `consul operator <subcommand> [common options] [action] [options]`
|
Usage: `consul operator <subcommand> [action] [options]`
|
||||||
|
|
||||||
Run `consul operator <subcommand>` with no arguments for help on that
|
Run `consul operator <subcommand>` with no arguments for help on that
|
||||||
subcommand. The following subcommands are available:
|
subcommand. The following subcommands are available:
|
||||||
|
|
||||||
* `raft` - View and modify Consul's Raft configuration.
|
* `raft` - View and modify Consul's Raft configuration.
|
||||||
|
|
||||||
Options common to all subcommands include:
|
#### API Options
|
||||||
|
|
||||||
* `-http-addr` - Address to the HTTP server of the agent you want to contact
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
to send this command. If this isn't specified, the command will contact
|
<%= partial "docs/commands/http_api_options_server" %>
|
||||||
"127.0.0.1:8500" which is the default HTTP address of a Consul agent.
|
|
||||||
|
|
||||||
* `-token` - ACL token to use. Defaults to that of agent.
|
|
||||||
|
|
||||||
## Raft Operations
|
## Raft Operations
|
||||||
|
|
|
@ -29,10 +29,6 @@ section on the agent options page for details on which options are supported.
|
||||||
|
|
||||||
Usage: `consul reload`
|
Usage: `consul reload`
|
||||||
|
|
||||||
The command-line flags are all optional. The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
* `-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".
|
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options_client" %>
|
|
@ -24,7 +24,11 @@ At least one node name is required. If the second node name isn't given, it
|
||||||
is set to the agent's node name. These are the node names as known to
|
is set to the agent's node name. These are the node names as known to
|
||||||
Consul as the `consul members` command would show, not IP addresses.
|
Consul as the `consul members` command would show, not IP addresses.
|
||||||
|
|
||||||
The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
|
||||||
|
#### Command Options
|
||||||
|
|
||||||
* `-wan` - Instructs the command to use WAN coordinates instead of LAN
|
* `-wan` - Instructs the command to use WAN coordinates instead of LAN
|
||||||
coordinates. By default, the two nodes are assumed to be nodes in the local
|
coordinates. By default, the two nodes are assumed to be nodes in the local
|
||||||
|
@ -33,11 +37,6 @@ The list of available flags are:
|
||||||
and the datacenter (eg. "myserver.dc1"). It is not possible to measure between
|
and the datacenter (eg. "myserver.dc1"). It is not possible to measure between
|
||||||
LAN coordinates and WAN coordinates, so both nodes must be in the same pool.
|
LAN coordinates and WAN coordinates, so both nodes must be in the same pool.
|
||||||
|
|
||||||
|
|
||||||
* `-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.
|
|
||||||
|
|
||||||
The following environment variables control accessing the HTTP server via SSL:
|
The following environment variables control accessing the HTTP server via SSL:
|
||||||
|
|
||||||
* `CONSUL_HTTP_SSL` Set this to enable SSL
|
* `CONSUL_HTTP_SSL` Set this to enable SSL
|
|
@ -28,6 +28,7 @@ Usage: `consul snapshot restore [options] FILE`
|
||||||
#### API Options
|
#### API Options
|
||||||
|
|
||||||
<%= partial "docs/commands/http_api_options_client" %>
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
<%= partial "docs/commands/http_api_options_server" %>
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ Usage: `consul snapshot save [options] FILE`
|
||||||
#### API Options
|
#### API Options
|
||||||
|
|
||||||
<%= partial "docs/commands/http_api_options_client" %>
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
|
<%= partial "docs/commands/http_api_options_server" %>
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ After the snapshot is written to the given file it is read back and verified for
|
||||||
integrity.
|
integrity.
|
||||||
|
|
||||||
To create a potentially stale snapshot from any available server, use the stale
|
To create a potentially stale snapshot from any available server, use the stale
|
||||||
consisentcy mode:
|
consistency mode:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
$ consul snapshot save -stale backup.snap
|
$ consul snapshot save -stale backup.snap
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
layout: "docs"
|
||||||
|
page_title: "Commands: Version"
|
||||||
|
sidebar_current: "docs-commands-version"
|
||||||
|
description: |-
|
||||||
|
The `version` command prints the version of Consul and the protocol versions it understands for speaking to other agents.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Consul Version
|
||||||
|
|
||||||
|
Command: `consul version`
|
||||||
|
|
||||||
|
The `version` command prints the version of Consul and the protocol versions it understands for speaking to other agents.
|
||||||
|
|
||||||
|
```text
|
||||||
|
$ consul version
|
||||||
|
Consul v0.7.4
|
||||||
|
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
|
||||||
|
```
|
|
@ -27,18 +27,12 @@ data view. Depending on the type, various options may be required
|
||||||
or optionally provided. There is more documentation on watch
|
or optionally provided. There is more documentation on watch
|
||||||
[specifications here](/docs/agent/watches.html).
|
[specifications here](/docs/agent/watches.html).
|
||||||
|
|
||||||
The list of available flags are:
|
#### API Options
|
||||||
|
|
||||||
* `-http-addr` - Address to the HTTP server of the agent you want to contact
|
<%= partial "docs/commands/http_api_options_client" %>
|
||||||
to send this command. If this isn't specified, the command will contact
|
<%= partial "docs/commands/http_api_options_server" %>
|
||||||
"127.0.0.1:8500" which is the default HTTP address of a Consul agent.
|
|
||||||
|
|
||||||
* `-datacenter` - Datacenter to query. Defaults to that of the agent.
|
#### Command Options
|
||||||
|
|
||||||
* `-token` - ACL token to use. Defaults to that of the agent.
|
|
||||||
|
|
||||||
* `-stale=[true|false]` - Specifies if watch data is permitted to be stale. Defaults
|
|
||||||
to false.
|
|
||||||
|
|
||||||
* `-key` - Key to watch. Only for `key` type.
|
* `-key` - Key to watch. Only for `key` type.
|
||||||
|
|
|
@ -173,6 +173,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<li<%= sidebar_current("docs-commands-version") %>>
|
||||||
|
<a href="/docs/commands/version.html">version</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
<li<%= sidebar_current("docs-commands-watch") %>>
|
<li<%= sidebar_current("docs-commands-watch") %>>
|
||||||
<a href="/docs/commands/watch.html">watch</a>
|
<a href="/docs/commands/watch.html">watch</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue