diff --git a/command/commands.go b/command/commands.go index 0cc3c89a4..f044a2ffd 100644 --- a/command/commands.go +++ b/command/commands.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul/command/info" "github.com/hashicorp/consul/command/join" "github.com/hashicorp/consul/command/keygen" + "github.com/hashicorp/consul/command/keyring" "github.com/hashicorp/consul/command/kv" "github.com/hashicorp/consul/command/kvdel" "github.com/hashicorp/consul/command/kvexp" @@ -111,12 +112,7 @@ func init() { }, "keyring": func() (cli.Command, error) { - return &KeyringCommand{ - BaseCommand: BaseCommand{ - Flags: FlagSetClientHTTP, - UI: ui, - }, - }, nil + return keyring.New(ui), nil }, "kv": func() (cli.Command, error) { diff --git a/command/keyring.go b/command/keyring/keyring.go similarity index 79% rename from command/keyring.go rename to command/keyring/keyring.go index 33f98c566..a5bf5662f 100644 --- a/command/keyring.go +++ b/command/keyring/keyring.go @@ -1,17 +1,25 @@ -package command +package keyring import ( + "flag" "fmt" "github.com/hashicorp/consul/agent" consulapi "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/command/flags" "github.com/mitchellh/cli" ) -// KeyringCommand is a Command implementation that handles querying, installing, -// and removing gossip encryption keys from a keyring. -type KeyringCommand struct { - BaseCommand +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.initFlags() + return c +} + +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags // flags installKey string @@ -21,29 +29,32 @@ type KeyringCommand struct { relay int } -func (c *KeyringCommand) initFlags() { - c.InitFlagSet() - c.FlagSet.StringVar(&c.installKey, "install", "", +func (c *cmd) initFlags() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.installKey, "install", "", "Install a new encryption key. This will broadcast the new key to "+ "all members in the cluster.") - c.FlagSet.StringVar(&c.useKey, "use", "", + c.flags.StringVar(&c.useKey, "use", "", "Change the primary encryption key, which is used to encrypt "+ "messages. The key must already be installed before this operation "+ "can succeed.") - c.FlagSet.StringVar(&c.removeKey, "remove", "", + c.flags.StringVar(&c.removeKey, "remove", "", "Remove the given key from the cluster. This operation may only be "+ "performed on keys which are not currently the primary key.") - c.FlagSet.BoolVar(&c.listKeys, "list", false, + c.flags.BoolVar(&c.listKeys, "list", false, "List all keys currently in use within the cluster.") - c.FlagSet.IntVar(&c.relay, "relay-factor", 0, + c.flags.IntVar(&c.relay, "relay-factor", 0, "Setting this to a non-zero value will cause nodes to relay their response "+ "to the operation through this many randomly-chosen other nodes in the "+ "cluster. The maximum allowed value is 5.") + + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) } -func (c *KeyringCommand) Run(args []string) int { - c.initFlags() - if err := c.FlagSet.Parse(args); err != nil { +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { return 1 } @@ -78,7 +89,7 @@ func (c *KeyringCommand) Run(args []string) int { } // All other operations will require a client connection - client, err := c.HTTPClient() + client, err := c.http.APIClient() if err != nil { c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) return 1 @@ -130,7 +141,7 @@ func (c *KeyringCommand) Run(args []string) int { return 0 } -func (c *KeyringCommand) handleList(responses []*consulapi.KeyringResponse) { +func (c *cmd) handleList(responses []*consulapi.KeyringResponse) { for _, response := range responses { pool := response.Datacenter + " (LAN)" if response.Segment != "" { @@ -148,10 +159,12 @@ func (c *KeyringCommand) handleList(responses []*consulapi.KeyringResponse) { } } -func (c *KeyringCommand) Help() string { - c.initFlags() - return c.HelpCommand(` -Usage: consul keyring [options] +func (c *cmd) Synopsis() string { + return "Manages gossip layer encryption keys" +} + +func (c *cmd) Help() string { + s := `Usage: consul keyring [options] Manages encryption keys used for gossip messages. Gossip encryption is optional. When enabled, this command may be used to examine active encryption @@ -164,11 +177,6 @@ Usage: consul keyring [options] All variations of the keyring command return 0 if all nodes reply and there are no errors. If any node fails to reply or reports failure, the exit code - will be 1. - -`) -} - -func (c *KeyringCommand) Synopsis() string { - return "Manages gossip layer encryption keys" + will be 1.` + return flags.Usage(s, c.flags, c.http.ClientFlags(), c.http.ServerFlags()) } diff --git a/command/keyring_test.go b/command/keyring/keyring_test.go similarity index 86% rename from command/keyring_test.go rename to command/keyring/keyring_test.go index 6746a719f..9b01c4c59 100644 --- a/command/keyring_test.go +++ b/command/keyring/keyring_test.go @@ -1,4 +1,4 @@ -package command +package keyring import ( "strings" @@ -8,19 +8,11 @@ import ( "github.com/mitchellh/cli" ) -func testKeyringCommand(t *testing.T) (*cli.MockUi, *KeyringCommand) { - ui := cli.NewMockUi() - return ui, &KeyringCommand{ - BaseCommand: BaseCommand{ - UI: ui, - Flags: FlagSetClientHTTP, - }, - } -} - -func TestKeyringCommand_implements(t *testing.T) { +func TestKeyringCommand_noTabs(t *testing.T) { t.Parallel() - var _ cli.Command = &KeyringCommand{} + if strings.ContainsRune(New(nil).Help(), '\t') { + t.Fatal("usage has tabs") + } } func TestKeyringCommandRun(t *testing.T) { @@ -76,7 +68,8 @@ func TestKeyringCommandRun(t *testing.T) { func TestKeyringCommandRun_help(t *testing.T) { t.Parallel() - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) code := c.Run(nil) if code != 1 { t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String()) @@ -90,7 +83,8 @@ func TestKeyringCommandRun_help(t *testing.T) { func TestKeyringCommandRun_failedConnection(t *testing.T) { t.Parallel() - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-list", "-http-addr=127.0.0.1:0"} code := c.Run(args) if code != 1 { @@ -103,7 +97,8 @@ func TestKeyringCommandRun_failedConnection(t *testing.T) { func TestKeyringCommandRun_invalidRelayFactor(t *testing.T) { t.Parallel() - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-list", "-relay-factor=6"} code := c.Run(args) @@ -113,7 +108,8 @@ func TestKeyringCommandRun_invalidRelayFactor(t *testing.T) { } func listKeys(t *testing.T, addr string) string { - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-list", "-http-addr=" + addr} code := c.Run(args) @@ -125,7 +121,8 @@ func listKeys(t *testing.T, addr string) string { } func installKey(t *testing.T, addr string, key string) { - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-install=" + key, "-http-addr=" + addr} code := c.Run(args) @@ -135,7 +132,8 @@ func installKey(t *testing.T, addr string, key string) { } func useKey(t *testing.T, addr string, key string) { - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-use=" + key, "-http-addr=" + addr} code := c.Run(args) @@ -145,7 +143,8 @@ func useKey(t *testing.T, addr string, key string) { } func removeKey(t *testing.T, addr string, key string) { - ui, c := testKeyringCommand(t) + ui := cli.NewMockUi() + c := New(ui) args := []string{"-remove=" + key, "-http-addr=" + addr} code := c.Run(args)