bc29610124
* Updates Raft library to get new snapshot/restore API. * Basic backup and restore working, but need some cleanup. * Breaks out a snapshot module and adds a SHA256 integrity check. * Adds snapshot ACL and fills in some missing comments. * Require a consistent read for snapshots. * Make sure snapshot works if ACLs aren't enabled. * Adds a bit of package documentation. * Returns an empty response from restore to avoid EOF errors. * Adds API client support for snapshots. * Makes internal file names match on-disk file snapshots. * Adds DC and token coverage for snapshot API test. * Adds missing documentation. * Adds a unit test for the snapshot client endpoint. * Moves the connection pool out of the client for easier testing. * Fixes an incidental issue in the prepared query unit test. I realized I had two servers in bootstrap mode so this wasn't a good setup. * Adds a half close to the TCP stream and fixes panic on error. * Adds client and endpoint tests for snapshots. * Moves the pool back into the snapshot RPC client. * Adds a TLS test and fixes half-closes for TLS connections. * Tweaks some comments. * Adds a low-level snapshot test. This is independent of Consul so we can pull this out into a library later if we want to. * Cleans up snapshot and archive and completes archive tests. * Sends a clear error for snapshot operations in dev mode. Snapshots require the Raft snapshots to be readable, which isn't supported in dev mode. Send a clear error instead of a deep-down Raft one. * Adds docs for the snapshot endpoint. * Adds a stale mode and index feedback for snapshot saves. This gives folks a way to extract data even if the cluster has no leader. * Changes the internal format of a snapshot from zip to tgz. * Pulls in Raft fix to cancel inflight before a restore. * Pulls in new Raft restore interface. * Adds metadata to snapshot saves and a verify function. * Adds basic save and restore snapshot CLI commands. * Gets rid of tarball extensions and adds restore message. * Fixes an incidental bad link in the KV docs. * Adds documentation for the snapshot CLI commands. * Scuttle any request body when a snapshot is saved. * Fixes archive unit test error message check. * Allows for nil output writers in snapshot RPC handlers. * Renames hash list Decode to DecodeAndVerify. * Closes the client connection for snapshot ops. * Lowers timeout for restore ops. * Updates Raft vendor to get new Restore signature and integrates with Consul. * Bounces the leader's internal state when we do a restore.
95 lines
1.7 KiB
Go
95 lines
1.7 KiB
Go
package command
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/mitchellh/cli"
|
|
)
|
|
|
|
func TestSnapshotSaveCommand_implements(t *testing.T) {
|
|
var _ cli.Command = &SnapshotSaveCommand{}
|
|
}
|
|
|
|
func TestSnapshotSaveCommand_noTabs(t *testing.T) {
|
|
assertNoTabs(t, new(SnapshotSaveCommand))
|
|
}
|
|
|
|
func TestSnapshotSaveCommand_Validation(t *testing.T) {
|
|
ui := new(cli.MockUi)
|
|
c := &SnapshotSaveCommand{Ui: ui}
|
|
|
|
cases := map[string]struct {
|
|
args []string
|
|
output string
|
|
}{
|
|
"no file": {
|
|
[]string{},
|
|
"Missing FILE argument",
|
|
},
|
|
"extra args": {
|
|
[]string{"foo", "bar", "baz"},
|
|
"Too many arguments",
|
|
},
|
|
}
|
|
|
|
for name, tc := range cases {
|
|
// Ensure our buffer is always clear
|
|
if ui.ErrorWriter != nil {
|
|
ui.ErrorWriter.Reset()
|
|
}
|
|
if ui.OutputWriter != nil {
|
|
ui.OutputWriter.Reset()
|
|
}
|
|
|
|
code := c.Run(tc.args)
|
|
if code == 0 {
|
|
t.Errorf("%s: expected non-zero exit", name)
|
|
}
|
|
|
|
output := ui.ErrorWriter.String()
|
|
if !strings.Contains(output, tc.output) {
|
|
t.Errorf("%s: expected %q to contain %q", name, output, tc.output)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSnapshotSaveCommand_Run(t *testing.T) {
|
|
srv, client := testAgentWithAPIClient(t)
|
|
defer srv.Shutdown()
|
|
waitForLeader(t, srv.httpAddr)
|
|
|
|
ui := new(cli.MockUi)
|
|
c := &SnapshotSaveCommand{Ui: ui}
|
|
|
|
dir, err := ioutil.TempDir("", "snapshot")
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
file := path.Join(dir, "backup.tgz")
|
|
args := []string{
|
|
"-http-addr=" + srv.httpAddr,
|
|
file,
|
|
}
|
|
|
|
code := c.Run(args)
|
|
if code != 0 {
|
|
t.Fatalf("bad: %d. %#v", code, ui.ErrorWriter.String())
|
|
}
|
|
|
|
f, err := os.Open(file)
|
|
if err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
if err := client.Snapshot().Restore(nil, f); err != nil {
|
|
t.Fatalf("err: %v", err)
|
|
}
|
|
}
|