diff --git a/command/commands.go b/command/commands.go index 21b7e1f468..a28f7d49de 100644 --- a/command/commands.go +++ b/command/commands.go @@ -38,6 +38,7 @@ import ( "github.com/hashicorp/consul/command/rtt" "github.com/hashicorp/consul/command/snapshot" "github.com/hashicorp/consul/command/snapshotinspect" + "github.com/hashicorp/consul/command/snapshotrestore" "github.com/hashicorp/consul/command/validate" versioncmd "github.com/hashicorp/consul/command/version" "github.com/hashicorp/consul/version" @@ -194,12 +195,7 @@ func init() { }, "snapshot restore": func() (cli.Command, error) { - return &SnapshotRestoreCommand{ - BaseCommand: BaseCommand{ - Flags: FlagSetHTTP, - UI: ui, - }, - }, nil + return snapshotrestore.New(ui), nil }, "snapshot save": func() (cli.Command, error) { diff --git a/command/snapshot_restore.go b/command/snapshotrestore/snapshot_restore.go similarity index 64% rename from command/snapshot_restore.go rename to command/snapshotrestore/snapshot_restore.go index 59c522a889..2ef79774db 100644 --- a/command/snapshot_restore.go +++ b/command/snapshotrestore/snapshot_restore.go @@ -1,51 +1,51 @@ -package command +package snapshotrestore import ( + "flag" "fmt" "os" + + "github.com/hashicorp/consul/command/flags" + "github.com/mitchellh/cli" ) -// SnapshotRestoreCommand is a Command implementation that is used to restore -// the state of the Consul servers for disaster recovery. -type SnapshotRestoreCommand struct { - BaseCommand +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.init() + return c } -func (c *SnapshotRestoreCommand) Help() string { - c.InitFlagSet() - return c.HelpCommand(` -Usage: consul snapshot restore [options] FILE - - Restores an atomic, point-in-time snapshot of the state of the Consul servers - which includes key/value entries, service catalog, prepared queries, sessions, - and ACLs. - - Restores involve a potentially dangerous low-level Raft operation that is not - designed to handle server failures during a restore. This command is primarily - intended to be used when recovering from a disaster, restoring into a fresh - cluster of Consul servers. - - If ACLs are enabled, a management token must be supplied in order to perform - snapshot operations. - - To restore a snapshot from the file "backup.snap": - - $ consul snapshot restore backup.snap - - For a full list of options and examples, please see the Consul documentation. - -`) +type cmd struct { + UI cli.Ui + flags *flag.FlagSet + http *flags.HTTPFlags + usage string } -func (c *SnapshotRestoreCommand) Run(args []string) int { - c.InitFlagSet() - if err := c.FlagSet.Parse(args); err != nil { +func (c *cmd) init() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.http = &flags.HTTPFlags{} + flags.Merge(c.flags, c.http.ClientFlags()) + flags.Merge(c.flags, c.http.ServerFlags()) + c.usage = flags.Usage(usage, c.flags, c.http.ClientFlags(), c.http.ServerFlags()) +} + +func (c *cmd) Synopsis() string { + return "Restores snapshot of Consul server state" +} + +func (c *cmd) Help() string { + return c.usage +} + +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { return 1 } var file string - args = c.FlagSet.Args() + args = c.flags.Args() switch len(args) { case 0: c.UI.Error("Missing FILE argument") @@ -58,7 +58,7 @@ func (c *SnapshotRestoreCommand) Run(args []string) int { } // Create and test the HTTP client - 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 @@ -83,6 +83,22 @@ func (c *SnapshotRestoreCommand) Run(args []string) int { return 0 } -func (c *SnapshotRestoreCommand) Synopsis() string { - return "Restores snapshot of Consul server state" -} +const usage = `Usage: consul snapshot restore [options] FILE + + Restores an atomic, point-in-time snapshot of the state of the Consul servers + which includes key/value entries, service catalog, prepared queries, sessions, + and ACLs. + + Restores involve a potentially dangerous low-level Raft operation that is not + designed to handle server failures during a restore. This command is primarily + intended to be used when recovering from a disaster, restoring into a fresh + cluster of Consul servers. + + If ACLs are enabled, a management token must be supplied in order to perform + snapshot operations. + + To restore a snapshot from the file "backup.snap": + + $ consul snapshot restore backup.snap + + For a full list of options and examples, please see the Consul documentation.` diff --git a/command/snapshot_restore_test.go b/command/snapshotrestore/snapshot_restore_test.go similarity index 79% rename from command/snapshot_restore_test.go rename to command/snapshotrestore/snapshot_restore_test.go index f886cf4414..33c821a246 100644 --- a/command/snapshot_restore_test.go +++ b/command/snapshotrestore/snapshot_restore_test.go @@ -1,4 +1,4 @@ -package command +package snapshotrestore import ( "io" @@ -12,29 +12,17 @@ import ( "github.com/mitchellh/cli" ) -func testSnapshotRestoreCommand(t *testing.T) (*cli.MockUi, *SnapshotRestoreCommand) { - ui := cli.NewMockUi() - return ui, &SnapshotRestoreCommand{ - BaseCommand: BaseCommand{ - UI: ui, - Flags: FlagSetHTTP, - }, - } -} - -func TestSnapshotRestoreCommand_implements(t *testing.T) { - t.Parallel() - var _ cli.Command = &SnapshotRestoreCommand{} -} - func TestSnapshotRestoreCommand_noTabs(t *testing.T) { t.Parallel() - assertNoTabs(t, new(SnapshotRestoreCommand)) + if strings.ContainsRune(New(cli.NewMockUi()).Help(), '\t') { + t.Fatal("usage has tabs") + } } func TestSnapshotRestoreCommand_Validation(t *testing.T) { t.Parallel() - ui, c := testSnapshotRestoreCommand(t) + ui := cli.NewMockUi() + c := New(ui) cases := map[string]struct { args []string @@ -77,7 +65,8 @@ func TestSnapshotRestoreCommand_Run(t *testing.T) { defer a.Shutdown() client := a.Client() - ui, c := testSnapshotRestoreCommand(t) + ui := cli.NewMockUi() + c := New(ui) dir := testutil.TempDir(t, "snapshot") defer os.RemoveAll(dir)