diff --git a/CHANGELOG/CHANGELOG-3.6.md b/CHANGELOG/CHANGELOG-3.6.md index 08924e1cd1f..defb4da8823 100644 --- a/CHANGELOG/CHANGELOG-3.6.md +++ b/CHANGELOG/CHANGELOG-3.6.md @@ -28,6 +28,7 @@ See [code changes](https://github.com/etcd-io/etcd/compare/v3.5.0...v3.6.0). ### etcdctl v3 - Add command to generate [shell completion](https://github.com/etcd-io/etcd/pull/13133). +- Add command [snapshot pipe](https://github.com/etcd-io/etcd/pull/16243). - When print endpoint status, [show db size in use](https://github.com/etcd-io/etcd/pull/13639) - [Always print the raft_term in decimal](https://github.com/etcd-io/etcd/pull/13711) when displaying member list in json. - [Add one more field `storageVersion`](https://github.com/etcd-io/etcd/pull/13773) into the response of command `etcdctl endpoint status`. diff --git a/client/v3/snapshot/v3_snapshot.go b/client/v3/snapshot/v3_snapshot.go index b2db5f0c137..ac1d1046630 100644 --- a/client/v3/snapshot/v3_snapshot.go +++ b/client/v3/snapshot/v3_snapshot.go @@ -37,15 +37,14 @@ func hasChecksum(n int64) bool { return (n % 512) == sha256.Size } -// SaveWithVersion fetches snapshot from remote etcd server, saves data +// WriteSnapshotWithVersion fetches snapshot from remote etcd server, saves data // to target path and returns server version. If the context "ctx" is canceled or timed out, // snapshot save stream will error out (e.g. context.Canceled, // context.DeadlineExceeded). Make sure to specify only one endpoint // in client configuration. Snapshot API must be requested to a // selected node, and saved snapshot is the point-in-time state of -// the selected node. -// Etcd snapshot.db +``` + ### SNAPSHOT SAVE \ SNAPSHOT SAVE writes a point-in-time snapshot of the etcd backend database to a file. diff --git a/etcdctl/ctlv3/command/snapshot_command.go b/etcdctl/ctlv3/command/snapshot_command.go index df317e23cc7..818c17f76e8 100644 --- a/etcdctl/ctlv3/command/snapshot_command.go +++ b/etcdctl/ctlv3/command/snapshot_command.go @@ -33,6 +33,7 @@ func NewSnapshotCommand() *cobra.Command { Short: "Manages etcd node snapshots", } cmd.AddCommand(NewSnapshotSaveCommand()) + cmd.AddCommand(NewSnapshotPipeCommand()) return cmd } @@ -44,6 +45,14 @@ func NewSnapshotSaveCommand() *cobra.Command { } } +func NewSnapshotPipeCommand() *cobra.Command { + return &cobra.Command{ + Use: "pipe", + Short: "Streams an etcd node backend snapshot to stdout", + Run: snapshotPipeCommandFunc, + } +} + func snapshotSaveCommandFunc(cmd *cobra.Command, args []string) { if len(args) != 1 { err := fmt.Errorf("snapshot save expects one argument") @@ -73,3 +82,24 @@ func snapshotSaveCommandFunc(cmd *cobra.Command, args []string) { fmt.Printf("Server version %s\n", version) } } + +func snapshotPipeCommandFunc(cmd *cobra.Command, args []string) { + + lg, err := logutil.CreateDefaultZapLogger(zap.InfoLevel) + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitError, err) + } + cfg := mustClientCfgFromCmd(cmd) + + // if user does not specify "--command-timeout" flag, there will be no timeout for snapshot pipe command + ctx, cancel := context.WithCancel(context.Background()) + if isCommandTimeoutFlagSet(cmd) { + ctx, cancel = commandCtx(cmd) + } + defer cancel() + + _, err = snapshot.PipeWithVersion(ctx, lg, *cfg) + if err != nil { + cobrautl.ExitWithError(cobrautl.ExitInterrupted, err) + } +}