mirror of https://github.com/status-im/consul.git
Enable snapshots in dev mode (#2453)
This commit is contained in:
parent
dce6702268
commit
3be132863f
|
@ -386,7 +386,7 @@ func (s *Server) setupRaft() error {
|
|||
s.raftInmem = store
|
||||
stable = store
|
||||
log = store
|
||||
snap = raft.NewDiscardSnapshotStore()
|
||||
snap = raft.NewInmemSnapshotStore()
|
||||
} else {
|
||||
// Create the base raft path.
|
||||
path := filepath.Join(s.config.DataDir, raftState)
|
||||
|
|
|
@ -20,12 +20,6 @@ import (
|
|||
"github.com/hashicorp/go-msgpack/codec"
|
||||
)
|
||||
|
||||
const (
|
||||
// noSnapshotsInDevMode indicates that snapshots aren't available for a
|
||||
// server in dev mode.
|
||||
noSnapshotsInDevMode = "Snapshot operations not available in dev mode"
|
||||
)
|
||||
|
||||
// dispatchSnapshotRequest takes an incoming request structure with possibly some
|
||||
// streaming data (for a restore) and returns possibly some streaming data (for
|
||||
// a snapshot save). We can't use the normal RPC mechanism in a streaming manner
|
||||
|
@ -52,13 +46,6 @@ func (s *Server) dispatchSnapshotRequest(args *structs.SnapshotRequest, in io.Re
|
|||
}
|
||||
}
|
||||
|
||||
// Snapshots don't work in dev mode because we need Raft's snapshots to
|
||||
// be readable. Better to present a clear error than one from deep down
|
||||
// in the Raft snapshot store.
|
||||
if s.config.DevMode {
|
||||
return nil, errors.New(noSnapshotsInDevMode)
|
||||
}
|
||||
|
||||
// Verify token is allowed to operate on snapshots. There's only a
|
||||
// single ACL sense here (not read and write) since reading gets you
|
||||
// all the ACLs and you could escalate from there.
|
||||
|
|
|
@ -391,26 +391,3 @@ func TestSnapshot_AllowStale(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSnapshot_DevMode(t *testing.T) {
|
||||
dir1, s1 := testServerWithConfig(t, func(c *Config) {
|
||||
c.DevMode = true
|
||||
})
|
||||
defer os.RemoveAll(dir1)
|
||||
defer s1.Shutdown()
|
||||
codec := rpcClient(t, s1)
|
||||
defer codec.Close()
|
||||
|
||||
testutil.WaitForLeader(t, s1.RPC, "dc1")
|
||||
|
||||
args := structs.SnapshotRequest{
|
||||
Datacenter: s1.config.Datacenter,
|
||||
Op: structs.SnapshotSave,
|
||||
}
|
||||
var reply structs.SnapshotResponse
|
||||
_, err := SnapshotRPC(s1.connPool, s1.config.Datacenter, s1.config.RPCAddr,
|
||||
&args, bytes.NewReader([]byte("")), &reply)
|
||||
if err == nil || !strings.Contains(err.Error(), noSnapshotsInDevMode) {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package raft
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
// InmemSnapshotStore implements the SnapshotStore interface and
|
||||
// retains only the most recent snapshot
|
||||
type InmemSnapshotStore struct {
|
||||
latest *InmemSnapshotSink
|
||||
hasSnapshot bool
|
||||
}
|
||||
|
||||
// InmemSnapshotSink implements SnapshotSink in memory
|
||||
type InmemSnapshotSink struct {
|
||||
meta SnapshotMeta
|
||||
contents *bytes.Buffer
|
||||
}
|
||||
|
||||
// NewInmemSnapshotStore creates a blank new InmemSnapshotStore
|
||||
func NewInmemSnapshotStore() *InmemSnapshotStore {
|
||||
return &InmemSnapshotStore{
|
||||
latest: &InmemSnapshotSink{
|
||||
contents: &bytes.Buffer{},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Create replaces the stored snapshot with a new one using the given args
|
||||
func (m *InmemSnapshotStore) Create(version SnapshotVersion, index, term uint64,
|
||||
configuration Configuration, configurationIndex uint64, trans Transport) (SnapshotSink, error) {
|
||||
// We only support version 1 snapshots at this time.
|
||||
if version != 1 {
|
||||
return nil, fmt.Errorf("unsupported snapshot version %d", version)
|
||||
}
|
||||
|
||||
name := snapshotName(term, index)
|
||||
|
||||
sink := m.latest
|
||||
sink.meta = SnapshotMeta{
|
||||
Version: version,
|
||||
ID: name,
|
||||
Index: index,
|
||||
Term: term,
|
||||
Peers: encodePeers(configuration, trans),
|
||||
Configuration: configuration,
|
||||
ConfigurationIndex: configurationIndex,
|
||||
}
|
||||
sink.contents = &bytes.Buffer{}
|
||||
m.hasSnapshot = true
|
||||
|
||||
return sink, nil
|
||||
}
|
||||
|
||||
// List returns the latest snapshot taken
|
||||
func (m *InmemSnapshotStore) List() ([]*SnapshotMeta, error) {
|
||||
if !m.hasSnapshot {
|
||||
return []*SnapshotMeta{}, nil
|
||||
}
|
||||
return []*SnapshotMeta{&m.latest.meta}, nil
|
||||
}
|
||||
|
||||
// Open wraps an io.ReadCloser around the snapshot contents
|
||||
func (m *InmemSnapshotStore) Open(id string) (*SnapshotMeta, io.ReadCloser, error) {
|
||||
if m.latest.meta.ID != id {
|
||||
return nil, nil, fmt.Errorf("[ERR] snapshot: failed to open snapshot id: %s", id)
|
||||
}
|
||||
|
||||
return &m.latest.meta, ioutil.NopCloser(m.latest.contents), nil
|
||||
}
|
||||
|
||||
// Write appends the given bytes to the snapshot contents
|
||||
func (s *InmemSnapshotSink) Write(p []byte) (n int, err error) {
|
||||
written, err := io.Copy(s.contents, bytes.NewReader(p))
|
||||
s.meta.Size += written
|
||||
return int(written), err
|
||||
}
|
||||
|
||||
// Close updates the Size and is otherwise a no-op
|
||||
func (s *InmemSnapshotSink) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *InmemSnapshotSink) ID() string {
|
||||
return s.meta.ID
|
||||
}
|
||||
|
||||
func (s *InmemSnapshotSink) Cancel() error {
|
||||
return nil
|
||||
}
|
|
@ -350,10 +350,10 @@
|
|||
"revisionTime": "2015-11-16T02:03:38Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "tHzyGCXkf8PnmBrTk1Z01JIv/5Q=",
|
||||
"checksumSHA1": "ed1YY/S0BSb57IRRSDUbFp7r0IE=",
|
||||
"path": "github.com/hashicorp/raft",
|
||||
"revision": "e1d3debe52b9152e8db5c3a77b7f7cf9b2a8b404",
|
||||
"revisionTime": "2016-10-26T00:17:15Z"
|
||||
"revision": "def7451ceceb8a919cbb1f6d1c0f7648e9311879",
|
||||
"revisionTime": "2016-10-31T16:57:40Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "QAxukkv54/iIvLfsUP6IK4R0m/A=",
|
||||
|
|
|
@ -34,9 +34,6 @@ The endpoints support the use of ACL Tokens. Because snapshots contain all
|
|||
server state, including ACLs, a management token is required to perform snapshot
|
||||
operations is ACLs are enabled.
|
||||
|
||||
-> Snapshot operations are not available for servers running in
|
||||
[dev mode](/docs/agent/options.html#_dev).
|
||||
|
||||
### <a name="snapshot"></a> /v1/snapshot
|
||||
|
||||
The snapshot endpoint supports the `GET` and `PUT` methods.
|
||||
|
|
Loading…
Reference in New Issue