forked from TrueCloudLab/frostfs-node
[#1185] neofs-cli: Add progress bar to object put/get
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
c3db12d71b
commit
ad4583fe85
4 changed files with 65 additions and 2 deletions
|
@ -464,6 +464,13 @@ type GetObjectPrm struct {
|
||||||
objectAddressPrm
|
objectAddressPrm
|
||||||
rawPrm
|
rawPrm
|
||||||
payloadWriterPrm
|
payloadWriterPrm
|
||||||
|
headerCallback func(*object.Object)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHeaderCallback sets callback which is called on the object after the header is received,
|
||||||
|
// but before the payload is written.
|
||||||
|
func (p *GetObjectPrm) SetHeaderCallback(f func(*object.Object)) {
|
||||||
|
p.headerCallback = f
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectRes groups resulting values of GetObject operation.
|
// GetObjectRes groups resulting values of GetObject operation.
|
||||||
|
@ -527,6 +534,9 @@ func GetObject(prm GetObjectPrm) (*GetObjectRes, error) {
|
||||||
_, err = rdr.Close()
|
_, err = rdr.Close()
|
||||||
return nil, fmt.Errorf("read object header: %w", err)
|
return nil, fmt.Errorf("read object header: %w", err)
|
||||||
}
|
}
|
||||||
|
if prm.headerCallback != nil {
|
||||||
|
prm.headerCallback(&hdr)
|
||||||
|
}
|
||||||
|
|
||||||
sz := hdr.PayloadSize()
|
sz := hdr.PayloadSize()
|
||||||
if sz > maxPayloadBufferSize {
|
if sz > maxPayloadBufferSize {
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/cheggaaa/pb"
|
||||||
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client"
|
internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
"github.com/nspcc-dev/neofs-sdk-go/checksum"
|
||||||
|
@ -123,6 +124,8 @@ const (
|
||||||
|
|
||||||
const putExpiresOnFlag = "expires-on"
|
const putExpiresOnFlag = "expires-on"
|
||||||
|
|
||||||
|
const noProgressFlag = "no-progress"
|
||||||
|
|
||||||
var putExpiredOn uint64
|
var putExpiredOn uint64
|
||||||
|
|
||||||
func initObjectPutCmd() {
|
func initObjectPutCmd() {
|
||||||
|
@ -141,6 +144,7 @@ func initObjectPutCmd() {
|
||||||
flags.Bool("disable-filename", false, "Do not set well-known filename attribute")
|
flags.Bool("disable-filename", false, "Do not set well-known filename attribute")
|
||||||
flags.Bool("disable-timestamp", false, "Do not set well-known timestamp attribute")
|
flags.Bool("disable-timestamp", false, "Do not set well-known timestamp attribute")
|
||||||
flags.Uint64VarP(&putExpiredOn, putExpiresOnFlag, "e", 0, "Last epoch in the life of the object")
|
flags.Uint64VarP(&putExpiredOn, putExpiresOnFlag, "e", 0, "Last epoch in the life of the object")
|
||||||
|
flags.Bool(noProgressFlag, false, "Do not show progress bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initObjectDeleteCmd() {
|
func initObjectDeleteCmd() {
|
||||||
|
@ -169,6 +173,7 @@ func initObjectGetCmd() {
|
||||||
flags.String("file", "", "File to write object payload to. Default: stdout.")
|
flags.String("file", "", "File to write object payload to. Default: stdout.")
|
||||||
flags.String("header", "", "File to write header to. Default: stdout.")
|
flags.String("header", "", "File to write header to. Default: stdout.")
|
||||||
flags.Bool(rawFlag, false, rawFlagDesc)
|
flags.Bool(rawFlag, false, rawFlagDesc)
|
||||||
|
flags.Bool(noProgressFlag, false, "Do not show progress bar")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initObjectSearchCmd() {
|
func initObjectSearchCmd() {
|
||||||
|
@ -446,11 +451,31 @@ func putObject(cmd *cobra.Command, _ []string) {
|
||||||
prepareSessionPrmWithOwner(cmd, sessionObjectCtxAddress, key, ownerID, &prm)
|
prepareSessionPrmWithOwner(cmd, sessionObjectCtxAddress, key, ownerID, &prm)
|
||||||
prepareObjectPrm(cmd, &prm)
|
prepareObjectPrm(cmd, &prm)
|
||||||
prm.SetHeader(obj)
|
prm.SetHeader(obj)
|
||||||
|
|
||||||
|
var p *pb.ProgressBar
|
||||||
|
|
||||||
|
noProgress, _ := cmd.Flags().GetBool(noProgressFlag)
|
||||||
|
if noProgress {
|
||||||
prm.SetPayloadReader(f)
|
prm.SetPayloadReader(f)
|
||||||
|
} else {
|
||||||
|
fi, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
cmd.PrintErrf("Failed to get file size, progress bar is disabled: %v\n", err)
|
||||||
|
prm.SetPayloadReader(f)
|
||||||
|
} else {
|
||||||
|
p = pb.New64(fi.Size())
|
||||||
|
p.Output = cmd.OutOrStdout()
|
||||||
|
prm.SetPayloadReader(p.NewProxyReader(f))
|
||||||
|
p.Start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
res, err := internalclient.PutObject(prm)
|
res, err := internalclient.PutObject(prm)
|
||||||
exitOnErr(cmd, errf("rpc error: %w", err))
|
exitOnErr(cmd, errf("rpc error: %w", err))
|
||||||
|
|
||||||
|
if p != nil {
|
||||||
|
p.Finish()
|
||||||
|
}
|
||||||
cmd.Printf("[%s] Object successfully stored\n", filename)
|
cmd.Printf("[%s] Object successfully stored\n", filename)
|
||||||
cmd.Printf(" ID: %s\n CID: %s\n", res.ID(), cid)
|
cmd.Printf(" ID: %s\n CID: %s\n", res.ID(), cid)
|
||||||
}
|
}
|
||||||
|
@ -498,7 +523,21 @@ func getObject(cmd *cobra.Command, _ []string) {
|
||||||
prepareSessionPrm(cmd, objAddr, &prm)
|
prepareSessionPrm(cmd, objAddr, &prm)
|
||||||
prepareObjectPrmRaw(cmd, &prm)
|
prepareObjectPrmRaw(cmd, &prm)
|
||||||
prm.SetAddress(objAddr)
|
prm.SetAddress(objAddr)
|
||||||
|
|
||||||
|
var p *pb.ProgressBar
|
||||||
|
noProgress, _ := cmd.Flags().GetBool(noProgressFlag)
|
||||||
|
|
||||||
|
if filename == "" || noProgress {
|
||||||
prm.SetPayloadWriter(out)
|
prm.SetPayloadWriter(out)
|
||||||
|
} else {
|
||||||
|
p = pb.New64(0)
|
||||||
|
p.Output = cmd.OutOrStdout()
|
||||||
|
prm.SetPayloadWriter(p.NewProxyWriter(out))
|
||||||
|
prm.SetHeaderCallback(func(o *object.Object) {
|
||||||
|
p.SetTotal64(int64(o.PayloadSize()))
|
||||||
|
p.Start()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
res, err := internalclient.GetObject(prm)
|
res, err := internalclient.GetObject(prm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -510,6 +549,9 @@ func getObject(cmd *cobra.Command, _ []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if filename != "" {
|
if filename != "" {
|
||||||
|
if p != nil {
|
||||||
|
p.Finish()
|
||||||
|
}
|
||||||
cmd.Printf("[%s] Object successfully saved\n", filename)
|
cmd.Printf("[%s] Object successfully saved\n", filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/nspcc-dev/neofs-node
|
||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/cheggaaa/pb v1.0.29
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e
|
||||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||||
github.com/golang/snappy v0.0.3 // indirect
|
github.com/golang/snappy v0.0.3 // indirect
|
||||||
|
|
10
go.sum
10
go.sum
|
@ -90,6 +90,8 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf
|
||||||
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
|
github.com/cheggaaa/pb v1.0.29 h1:FckUN5ngEk2LpvuG0fw1GEFx6LtyY2pWI/Z2QgCnEYo=
|
||||||
|
github.com/cheggaaa/pb v1.0.29/go.mod h1:W40334L7FMC5JKWldsTWbdGjLo0RxUKK73K+TuPxX30=
|
||||||
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
|
||||||
|
@ -128,6 +130,8 @@ github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
|
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
|
||||||
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
|
||||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI=
|
||||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||||
|
@ -306,12 +310,17 @@ github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPK
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
|
github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
|
||||||
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
|
@ -701,6 +710,7 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
|
Loading…
Reference in a new issue