Added operator autopilot subcommands
This commit is contained in:
parent
c9ddee1a79
commit
6168911200
|
@ -235,4 +235,4 @@ func (op *Operator) AutopilotCASConfiguration(conf *AutopilotConfiguration, q *W
|
|||
res := strings.Contains(string(buf.Bytes()), "true")
|
||||
|
||||
return res, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -177,4 +177,4 @@ func TestOperator_AutopilotCASConfiguration(t *testing.T) {
|
|||
t.Fatalf("bad: %v", resp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
32
command/operator_autopilot.go
Normal file
32
command/operator_autopilot.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
type OperatorAutopilotCommand struct {
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: consul operator autopilot <subcommand> [options]
|
||||
|
||||
The Autopilot operator command is used to interact with Consul's Autopilot
|
||||
subsystem. The command can be used to view or modify the current configuration.
|
||||
|
||||
`
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotCommand) Synopsis() string {
|
||||
return "Provides tools for modifying Autopilot configuration"
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotCommand) Run(args []string) int {
|
||||
return cli.RunResultHelp
|
||||
}
|
61
command/operator_autopilot_get.go
Normal file
61
command/operator_autopilot_get.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
type OperatorAutopilotGetCommand struct {
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotGetCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: consul operator autopilot get-config [options]
|
||||
|
||||
Displays the current Autopilot configuration.
|
||||
|
||||
` + c.Command.Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotGetCommand) Synopsis() string {
|
||||
return "Display the current Autopilot configuration"
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotGetCommand) Run(args []string) int {
|
||||
c.Command.NewFlagSet(c)
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
return 0
|
||||
}
|
||||
c.Ui.Error(fmt.Sprintf("Failed to parse args: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Set up a client.
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Fetch the current configuration.
|
||||
opts := &api.QueryOptions{
|
||||
AllowStale: c.Command.HTTPStale(),
|
||||
}
|
||||
config, err := client.Operator().AutopilotGetConfiguration(opts)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Autopilot configuration: %s", err))
|
||||
return 1
|
||||
}
|
||||
c.Ui.Output(fmt.Sprintf("DeadServerCleanup = %v", config.DeadServerCleanup))
|
||||
|
||||
return 0
|
||||
}
|
37
command/operator_autopilot_get_test.go
Normal file
37
command/operator_autopilot_get_test.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestOperator_Autopilot_Get_Implements(t *testing.T) {
|
||||
var _ cli.Command = &OperatorAutopilotGetCommand{}
|
||||
}
|
||||
|
||||
func TestOperator_Autopilot_Get(t *testing.T) {
|
||||
a1 := testAgent(t)
|
||||
defer a1.Shutdown()
|
||||
waitForLeader(t, a1.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := OperatorAutopilotGetCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
args := []string{"-http-addr=" + a1.httpAddr}
|
||||
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
}
|
||||
output := strings.TrimSpace(ui.OutputWriter.String())
|
||||
if !strings.Contains(output, "DeadServerCleanup = true") {
|
||||
t.Fatalf("bad: %s", output)
|
||||
}
|
||||
}
|
85
command/operator_autopilot_set.go
Normal file
85
command/operator_autopilot_set.go
Normal file
|
@ -0,0 +1,85 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
)
|
||||
|
||||
type OperatorAutopilotSetCommand struct {
|
||||
base.Command
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotSetCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: consul operator autopilot set-config [options]
|
||||
|
||||
Modifies the current Autopilot configuration.
|
||||
|
||||
` + c.Command.Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotSetCommand) Synopsis() string {
|
||||
return "Modify the current Autopilot configuration"
|
||||
}
|
||||
|
||||
func (c *OperatorAutopilotSetCommand) Run(args []string) int {
|
||||
var deadServerCleanup string
|
||||
|
||||
f := c.Command.NewFlagSet(c)
|
||||
|
||||
f.StringVar(&deadServerCleanup, "dead-server-cleanup", "",
|
||||
"Controls whether Consul will automatically remove dead servers "+
|
||||
"when new ones are successfully added. Must be one of `true|false`.")
|
||||
|
||||
if err := c.Command.Parse(args); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
return 0
|
||||
}
|
||||
c.Ui.Error(fmt.Sprintf("Failed to parse args: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Set up a client.
|
||||
client, err := c.Command.HTTPClient()
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
// Fetch the current configuration.
|
||||
operator := client.Operator()
|
||||
conf, err := operator.AutopilotGetConfiguration(nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error querying Autopilot configuration: %s", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
if deadServerCleanup != "" {
|
||||
switch deadServerCleanup {
|
||||
case "true":
|
||||
conf.DeadServerCleanup = true
|
||||
case "false":
|
||||
conf.DeadServerCleanup = false
|
||||
default:
|
||||
c.Ui.Error(fmt.Sprintf("Invalid value for dead-server-cleanup: %q", deadServerCleanup))
|
||||
}
|
||||
}
|
||||
|
||||
result, err := operator.AutopilotCASConfiguration(conf, nil)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf("Error setting Autopilot configuration: %s", err))
|
||||
return 1
|
||||
}
|
||||
if result {
|
||||
c.Ui.Output("Configuration updated")
|
||||
} else {
|
||||
c.Ui.Output("Configuration could not be atomically updated")
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
50
command/operator_autopilot_set_test.go
Normal file
50
command/operator_autopilot_set_test.go
Normal file
|
@ -0,0 +1,50 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/consul/command/base"
|
||||
"github.com/hashicorp/consul/consul/structs"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestOperator_Autopilot_Set_Implements(t *testing.T) {
|
||||
var _ cli.Command = &OperatorAutopilotSetCommand{}
|
||||
}
|
||||
|
||||
func TestOperator_Autopilot_Set(t *testing.T) {
|
||||
a1 := testAgent(t)
|
||||
defer a1.Shutdown()
|
||||
waitForLeader(t, a1.httpAddr)
|
||||
|
||||
ui := new(cli.MockUi)
|
||||
c := OperatorAutopilotSetCommand{
|
||||
Command: base.Command{
|
||||
Ui: ui,
|
||||
Flags: base.FlagSetHTTP,
|
||||
},
|
||||
}
|
||||
args := []string{"-http-addr=" + a1.httpAddr, "-dead-server-cleanup=false"}
|
||||
|
||||
code := c.Run(args)
|
||||
if code != 0 {
|
||||
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
||||
}
|
||||
output := strings.TrimSpace(ui.OutputWriter.String())
|
||||
if !strings.Contains(output, "Configuration updated") {
|
||||
t.Fatalf("bad: %s", output)
|
||||
}
|
||||
|
||||
req := structs.DCSpecificRequest{
|
||||
Datacenter: "dc1",
|
||||
}
|
||||
var reply structs.AutopilotConfig
|
||||
if err := a1.agent.RPC("Operator.AutopilotGetConfiguration", &req, &reply); err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if reply.DeadServerCleanup {
|
||||
t.Fatalf("bad: %#v", reply)
|
||||
}
|
||||
}
|
11
command/operator_autopilot_test.go
Normal file
11
command/operator_autopilot_test.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package command
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
func TestOperator_Autopilot_Implements(t *testing.T) {
|
||||
var _ cli.Command = &OperatorAutopilotCommand{}
|
||||
}
|
27
commands.go
27
commands.go
|
@ -213,6 +213,33 @@ func init() {
|
|||
}, nil
|
||||
},
|
||||
|
||||
"operator autopilot": func() (cli.Command, error) {
|
||||
return &command.OperatorAutopilotCommand{
|
||||
Command: base.Command{
|
||||
Flags: base.FlagSetNone,
|
||||
Ui: ui,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"operator autopilot get-config": func() (cli.Command, error) {
|
||||
return &command.OperatorAutopilotGetCommand{
|
||||
Command: base.Command{
|
||||
Flags: base.FlagSetHTTP,
|
||||
Ui: ui,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"operator autopilot set-config": func() (cli.Command, error) {
|
||||
return &command.OperatorAutopilotSetCommand{
|
||||
Command: base.Command{
|
||||
Flags: base.FlagSetHTTP,
|
||||
Ui: ui,
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
|
||||
"operator raft": func() (cli.Command, error) {
|
||||
return &command.OperatorRaftCommand{
|
||||
Command: base.Command{
|
||||
|
|
Loading…
Reference in a new issue