[#1338] neofs-cli: Add support to store/restore/delete binary objects

Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
Anton Nikiforov 2022-10-18 14:43:04 +03:00 committed by fyrchik
parent 1f82c583e3
commit bb52857b2b
30 changed files with 193 additions and 101 deletions

View file

@ -5,6 +5,7 @@ Changelog for NeoFS Node
### Added ### Added
- `morph list-containers` in `neofs-adm` (#1689) - `morph list-containers` in `neofs-adm` (#1689)
- `--binary` flag in `neofs-cli object put/get/delete` commands (#1338)
### Changed ### Changed
- `object lock` command reads CID and OID the same way other commands do (#1971) - `object lock` command reads CID and OID the same way other commands do (#1971)

View file

@ -41,6 +41,12 @@ const (
ForceFlag = "force" ForceFlag = "force"
ForceFlagShorthand = "f" ForceFlagShorthand = "f"
CIDFlag = "cid"
CIDFlagUsage = "Container ID."
OIDFlag = "oid"
OIDFlagUsage = "Object ID."
) )
// Init adds common flags to the command: // Init adds common flags to the command:

View file

@ -11,6 +11,7 @@ import (
"github.com/flynn-archive/go-shlex" "github.com/flynn-archive/go-shlex"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -53,7 +54,7 @@ func init() {
createCmd.Flags().StringArrayP("rule", "r", nil, "Extended ACL table record to apply") createCmd.Flags().StringArrayP("rule", "r", nil, "Extended ACL table record to apply")
createCmd.Flags().StringP("file", "f", "", "Read list of extended ACL table records from from text file") createCmd.Flags().StringP("file", "f", "", "Read list of extended ACL table records from from text file")
createCmd.Flags().StringP("out", "o", "", "Save JSON formatted extended ACL table in file") createCmd.Flags().StringP("out", "o", "", "Save JSON formatted extended ACL table in file")
createCmd.Flags().StringP("cid", "", "", "Container ID") createCmd.Flags().StringP(commonflags.CIDFlag, "", "", commonflags.CIDFlagUsage)
_ = cobra.MarkFlagFilename(createCmd.Flags(), "file") _ = cobra.MarkFlagFilename(createCmd.Flags(), "file")
_ = cobra.MarkFlagFilename(createCmd.Flags(), "out") _ = cobra.MarkFlagFilename(createCmd.Flags(), "out")
@ -63,7 +64,7 @@ func createEACL(cmd *cobra.Command, _ []string) {
rules, _ := cmd.Flags().GetStringArray("rule") rules, _ := cmd.Flags().GetStringArray("rule")
fileArg, _ := cmd.Flags().GetString("file") fileArg, _ := cmd.Flags().GetString("file")
outArg, _ := cmd.Flags().GetString("out") outArg, _ := cmd.Flags().GetString("out")
cidArg, _ := cmd.Flags().GetString("cid") cidArg, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var containerID cid.ID var containerID cid.ID
if cidArg != "" { if cidArg != "" {

View file

@ -89,7 +89,7 @@ func initContainerDeleteCmd() {
flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage) flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage)
flags.StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage) flags.StringP(commonflags.RPC, commonflags.RPCShorthand, commonflags.RPCDefault, commonflags.RPCUsage)
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.BoolVar(&containerAwait, "await", false, "Block execution until container is removed") flags.BoolVar(&containerAwait, "await", false, "Block execution until container is removed")
flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Do not check whether container contains locks and remove immediately") flags.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Do not check whether container contains locks and remove immediately")
} }

View file

@ -17,9 +17,6 @@ import (
) )
const ( const (
cidFlag = "cid"
cidFlagUsage = "Container ID"
fromFlag = "from" fromFlag = "from"
fromFlagUsage = "Path to file with encoded container" fromFlagUsage = "Path to file with encoded container"
) )
@ -64,7 +61,7 @@ func initContainerInfoCmd() {
flags := getContainerInfoCmd.Flags() flags := getContainerInfoCmd.Flags()
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.StringVar(&containerPathTo, "to", "", "Path to dump encoded container") flags.StringVar(&containerPathTo, "to", "", "Path to dump encoded container")
flags.StringVar(&containerPathFrom, fromFlag, "", fromFlagUsage) flags.StringVar(&containerPathFrom, fromFlag, "", fromFlagUsage)
flags.BoolVar(&containerJSON, commonflags.JSON, false, "Print or dump container in JSON format") flags.BoolVar(&containerJSON, commonflags.JSON, false, "Print or dump container in JSON format")

View file

@ -57,7 +57,7 @@ func initContainerGetEACLCmd() {
flags := getExtendedACLCmd.Flags() flags := getExtendedACLCmd.Flags()
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.StringVar(&containerPathTo, "to", "", "Path to dump encoded container (default: binary encoded)") flags.StringVar(&containerPathTo, "to", "", "Path to dump encoded container (default: binary encoded)")
flags.BoolVar(&containerJSON, commonflags.JSON, false, "Encode EACL table in json format") flags.BoolVar(&containerJSON, commonflags.JSON, false, "Encode EACL table in json format")
} }

View file

@ -89,7 +89,7 @@ func initContainerListObjectsCmd() {
flags := listContainerObjectsCmd.Flags() flags := listContainerObjectsCmd.Flags()
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.BoolVar(&flagVarListObjectsPrintAttr, flagListObjectPrintAttr, false, flags.BoolVar(&flagVarListObjectsPrintAttr, flagListObjectPrintAttr, false,
"Request and print user attributes of each object", "Request and print user attributes of each object",
) )

View file

@ -58,7 +58,7 @@ func initContainerNodesCmd() {
commonflags.Init(containerNodesCmd) commonflags.Init(containerNodesCmd)
flags := containerNodesCmd.Flags() flags := containerNodesCmd.Flags()
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.StringVar(&containerPathFrom, fromFlag, "", fromFlagUsage) flags.StringVar(&containerPathFrom, fromFlag, "", fromFlagUsage)
flags.BoolVar(&short, "short", false, "Shortens output of node info") flags.BoolVar(&short, "short", false, "Shortens output of node info")
} }

View file

@ -96,7 +96,7 @@ func initContainerSetEACLCmd() {
commonflags.Init(setExtendedACLCmd) commonflags.Init(setExtendedACLCmd)
flags := setExtendedACLCmd.Flags() flags := setExtendedACLCmd.Flags()
flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.StringVar(&flagVarsSetEACL.srcPath, "table", "", "path to file with JSON or binary encoded EACL table") flags.StringVar(&flagVarsSetEACL.srcPath, "table", "", "path to file with JSON or binary encoded EACL table")
flags.BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted") flags.BoolVar(&containerAwait, "await", false, "block execution until EACL is persisted")
flags.BoolVar(&flagVarsSetEACL.noPreCheck, "no-precheck", false, "do not pre-check the extensibility of the container ACL") flags.BoolVar(&flagVarsSetEACL.noPreCheck, "no-precheck", false, "do not pre-check the extensibility of the container ACL")

View file

@ -6,6 +6,7 @@ import (
rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client" rawclient "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
"github.com/nspcc-dev/neofs-node/pkg/services/control" "github.com/nspcc-dev/neofs-node/pkg/services/control"
controlSvc "github.com/nspcc-dev/neofs-node/pkg/services/control/server" controlSvc "github.com/nspcc-dev/neofs-node/pkg/services/control/server"
@ -29,7 +30,7 @@ func initControlSynchronizeTreeCmd() {
initControlFlags(synchronizeTreeCmd) initControlFlags(synchronizeTreeCmd)
flags := synchronizeTreeCmd.Flags() flags := synchronizeTreeCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
flags.String(synchronizeTreeIDFlag, "", "Tree ID") flags.String(synchronizeTreeIDFlag, "", "Tree ID")
flags.Uint64(synchronizeTreeHeightFlag, 0, "Starting height") flags.Uint64(synchronizeTreeHeightFlag, 0, "Starting height")
} }
@ -38,7 +39,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) {
pk := key.Get(cmd) pk := key.Get(cmd)
var cnr cid.ID var cnr cid.ID
cidStr, _ := cmd.Flags().GetString("cid") cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag)
common.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) common.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr))
treeID, _ := cmd.Flags().GetString("tree-id") treeID, _ := cmd.Flags().GetString("tree-id")

View file

@ -1,6 +1,8 @@
package object package object
import ( import (
"fmt"
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-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
@ -24,18 +26,38 @@ func initObjectDeleteCmd() {
flags := objectDelCmd.Flags() flags := objectDelCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectDelCmd.MarkFlagRequired("cid") flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
flags.Bool(binaryFlag, false, "Deserialize object structure from given file.")
flags.String("oid", "", "Object ID") flags.String(fileFlag, "", "File with object payload")
_ = objectDelCmd.MarkFlagRequired("oid")
} }
func deleteObject(cmd *cobra.Command, _ []string) { func deleteObject(cmd *cobra.Command, _ []string) {
var cnr cid.ID var cnr cid.ID
var obj oid.ID var obj oid.ID
var objAddr oid.Address
binary, _ := cmd.Flags().GetBool(binaryFlag)
if binary {
filename, _ := cmd.Flags().GetString(fileFlag)
if filename == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", fileFlag))
}
objAddr = readObjectAddressBin(cmd, &cnr, &obj, filename)
} else {
cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag)
if cidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
}
oidVal, _ := cmd.Flags().GetString(commonflags.OIDFlag)
if oidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.OIDFlag))
}
objAddr = readObjectAddress(cmd, &cnr, &obj)
}
objAddr := readObjectAddress(cmd, &cnr, &obj)
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
var prm internalclient.DeleteObjectPrm var prm internalclient.DeleteObjectPrm

View file

@ -1,6 +1,7 @@
package object package object
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -29,16 +30,17 @@ func initObjectGetCmd() {
flags := objectGetCmd.Flags() flags := objectGetCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectGetCmd.MarkFlagRequired("cid") _ = objectGetCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.String("oid", "", "Object ID") flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
_ = objectGetCmd.MarkFlagRequired("oid") _ = objectGetCmd.MarkFlagRequired(commonflags.OIDFlag)
flags.String("file", "", "File to write object payload to. Default: stdout.") flags.String(fileFlag, "", "File to write object payload to(with -b together with signature and header). 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") flags.Bool(noProgressFlag, false, "Do not show progress bar")
flags.Bool(binaryFlag, false, "Serialize whole object structure into given file(id + signature + header + payload).")
} }
func getObject(cmd *cobra.Command, _ []string) { func getObject(cmd *cobra.Command, _ []string) {
@ -48,7 +50,7 @@ func getObject(cmd *cobra.Command, _ []string) {
objAddr := readObjectAddress(cmd, &cnr, &obj) objAddr := readObjectAddress(cmd, &cnr, &obj)
var out io.Writer var out io.Writer
filename := cmd.Flag("file").Value.String() filename := cmd.Flag(fileFlag).Value.String()
if filename == "" { if filename == "" {
out = os.Stdout out = os.Stdout
} else { } else {
@ -78,12 +80,22 @@ func getObject(cmd *cobra.Command, _ []string) {
var p *pb.ProgressBar var p *pb.ProgressBar
noProgress, _ := cmd.Flags().GetBool(noProgressFlag) noProgress, _ := cmd.Flags().GetBool(noProgressFlag)
var payloadWriter io.Writer
var payloadBuffer *bytes.Buffer
binary, _ := cmd.Flags().GetBool(binaryFlag)
if binary {
payloadBuffer = new(bytes.Buffer)
payloadWriter = payloadBuffer
} else {
payloadWriter = out
}
if filename == "" || noProgress { if filename == "" || noProgress {
prm.SetPayloadWriter(out) prm.SetPayloadWriter(payloadWriter)
} else { } else {
p = pb.New64(0) p = pb.New64(0)
p.Output = cmd.OutOrStdout() p.Output = cmd.OutOrStdout()
prm.SetPayloadWriter(p.NewProxyWriter(out)) prm.SetPayloadWriter(p.NewProxyWriter(payloadWriter))
prm.SetHeaderCallback(func(o *object.Object) { prm.SetHeaderCallback(func(o *object.Object) {
p.SetTotal64(int64(o.PayloadSize())) p.SetTotal64(int64(o.PayloadSize()))
p.Start() p.Start()
@ -102,6 +114,16 @@ func getObject(cmd *cobra.Command, _ []string) {
common.ExitOnErr(cmd, "rpc error: %w", err) common.ExitOnErr(cmd, "rpc error: %w", err)
} }
if binary {
objToStore := res.Header()
//TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload
objToStore.SetPayload(payloadBuffer.Bytes())
objBytes, err := objToStore.Marshal()
common.ExitOnErr(cmd, "", err)
_, err = out.Write(objBytes)
common.ExitOnErr(cmd, "unable to write binary object in out: %w ", err)
}
hdrFile := cmd.Flag("header").Value.String() hdrFile := cmd.Flag("header").Value.String()
if filename != "" { if filename != "" {
if hdrFile != "" || !strictOutput(cmd) { if hdrFile != "" || !strictOutput(cmd) {

View file

@ -35,11 +35,11 @@ func initObjectHashCmd() {
flags := objectHashCmd.Flags() flags := objectHashCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectHashCmd.MarkFlagRequired("cid") _ = objectHashCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.String("oid", "", "Object ID") flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
_ = objectHashCmd.MarkFlagRequired("oid") _ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag)
flags.String("range", "", "Range to take hash from in the form offset1:length1,...") flags.String("range", "", "Range to take hash from in the form offset1:length1,...")
flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'") flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'")

View file

@ -31,13 +31,13 @@ func initObjectHeadCmd() {
flags := objectHeadCmd.Flags() flags := objectHeadCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectHeadCmd.MarkFlagRequired("cid") _ = objectHeadCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.String("oid", "", "Object ID") flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
_ = objectHeadCmd.MarkFlagRequired("oid") _ = objectHeadCmd.MarkFlagRequired(commonflags.OIDFlag)
flags.String("file", "", "File to write header to. Default: stdout.") flags.String(fileFlag, "", "File to write header to. Default: stdout.")
flags.Bool("main-only", false, "Return only main fields") flags.Bool("main-only", false, "Return only main fields")
flags.Bool(commonflags.JSON, false, "Marshal output in JSON") flags.Bool(commonflags.JSON, false, "Marshal output in JSON")
flags.Bool("proto", false, "Marshal output in Protobuf") flags.Bool("proto", false, "Marshal output in Protobuf")
@ -73,7 +73,7 @@ func getObjectHeader(cmd *cobra.Command, _ []string) {
common.ExitOnErr(cmd, "rpc error: %w", err) common.ExitOnErr(cmd, "rpc error: %w", err)
} }
err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag("file").Value.String()) err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag(fileFlag).Value.String())
common.ExitOnErr(cmd, "", err) common.ExitOnErr(cmd, "", err)
} }

View file

@ -25,13 +25,13 @@ var objectLockCmd = &cobra.Command{
Short: "Lock object in container", Short: "Lock object in container",
Long: "Lock object in container", Long: "Lock object in container",
Run: func(cmd *cobra.Command, _ []string) { Run: func(cmd *cobra.Command, _ []string) {
cidRaw, _ := cmd.Flags().GetString("cid") cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cnr cid.ID var cnr cid.ID
err := cnr.DecodeString(cidRaw) err := cnr.DecodeString(cidRaw)
common.ExitOnErr(cmd, "Incorrect container arg: %v", err) common.ExitOnErr(cmd, "Incorrect container arg: %v", err)
oidsRaw, _ := cmd.Flags().GetStringSlice("oid") oidsRaw, _ := cmd.Flags().GetStringSlice(commonflags.OIDFlag)
lockList := make([]oid.ID, len(oidsRaw)) lockList := make([]oid.ID, len(oidsRaw))
@ -96,11 +96,11 @@ func initCommandObjectLock() {
ff := objectLockCmd.Flags() ff := objectLockCmd.Flags()
ff.String("cid", "", "Container ID") ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectLockCmd.MarkFlagRequired("cid") _ = objectLockCmd.MarkFlagRequired(commonflags.CIDFlag)
ff.StringSlice("oid", nil, "Object ID") ff.StringSlice(commonflags.OIDFlag, nil, commonflags.OIDFlagUsage)
_ = objectLockCmd.MarkFlagRequired("oid") _ = objectLockCmd.MarkFlagRequired(commonflags.OIDFlag)
ff.Uint64P(commonflags.ExpireAt, "e", 0, "Lock expiration epoch") ff.Uint64P(commonflags.ExpireAt, "e", 0, "Lock expiration epoch")

View file

@ -1,7 +1,9 @@
package object package object
import ( import (
"bytes"
"fmt" "fmt"
"io"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@ -40,12 +42,11 @@ func initObjectPutCmd() {
flags := objectPutCmd.Flags() flags := objectPutCmd.Flags()
flags.String("file", "", "File with object payload") flags.String(fileFlag, "", "File with object payload")
_ = objectPutCmd.MarkFlagFilename("file") _ = objectPutCmd.MarkFlagFilename(fileFlag)
_ = objectPutCmd.MarkFlagRequired("file") _ = objectPutCmd.MarkFlagRequired(fileFlag)
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectPutCmd.MarkFlagRequired("cid")
flags.String("attributes", "", "User attributes in form of Key1=Value1,Key2=Value2") flags.String("attributes", "", "User attributes in form of Key1=Value1,Key2=Value2")
flags.Bool("disable-filename", false, "Do not set well-known filename attribute") flags.Bool("disable-filename", false, "Do not set well-known filename attribute")
@ -54,22 +55,42 @@ func initObjectPutCmd() {
flags.Bool(noProgressFlag, false, "Do not show progress bar") flags.Bool(noProgressFlag, false, "Do not show progress bar")
flags.String(notificationFlag, "", "Object notification in the form of *epoch*:*topic*; '-' topic means using default") flags.String(notificationFlag, "", "Object notification in the form of *epoch*:*topic*; '-' topic means using default")
flags.Bool(binaryFlag, false, "Deserialize object structure from given file.")
} }
func putObject(cmd *cobra.Command, _ []string) { func putObject(cmd *cobra.Command, _ []string) {
binary, _ := cmd.Flags().GetBool(binaryFlag)
cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag)
if !binary && cidVal == "" {
common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag))
}
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
var ownerID user.ID var ownerID user.ID
user.IDFromKey(&ownerID, pk.PublicKey)
var cnr cid.ID var cnr cid.ID
readCID(cmd, &cnr)
filename := cmd.Flag("file").Value.String() filename, _ := cmd.Flags().GetString(fileFlag)
f, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm) f, err := os.OpenFile(filename, os.O_RDONLY, os.ModePerm)
if err != nil { if err != nil {
common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err)) common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err))
} }
var payloadReader io.Reader = f
obj := object.New()
if binary {
buf, err := os.ReadFile(filename)
common.ExitOnErr(cmd, "unable to read given file: %w", err)
objTemp := object.New()
//TODO(@acid-ant): #1932 Use streams to marshal/unmarshal payload
common.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
payloadReader = bytes.NewReader(objTemp.Payload())
cnr, _ = objTemp.ContainerID()
ownerID = *objTemp.OwnerID()
} else {
readCID(cmd, &cnr)
user.IDFromKey(&ownerID, pk.PublicKey)
}
attrs, err := parseObjectAttrs(cmd) attrs, err := parseObjectAttrs(cmd)
common.ExitOnErr(cmd, "can't parse object attributes: %w", err) common.ExitOnErr(cmd, "can't parse object attributes: %w", err)
@ -95,7 +116,6 @@ func putObject(cmd *cobra.Command, _ []string) {
} }
} }
obj := object.New()
obj.SetContainerID(cnr) obj.SetContainerID(cnr)
obj.SetOwnerID(&ownerID) obj.SetOwnerID(&ownerID)
obj.SetAttributes(attrs...) obj.SetAttributes(attrs...)
@ -116,19 +136,26 @@ func putObject(cmd *cobra.Command, _ []string) {
noProgress, _ := cmd.Flags().GetBool(noProgressFlag) noProgress, _ := cmd.Flags().GetBool(noProgressFlag)
if noProgress { if noProgress {
prm.SetPayloadReader(f) prm.SetPayloadReader(payloadReader)
} else { } else {
fi, err := f.Stat() if binary {
if err != nil { p = pb.New(len(obj.Payload()))
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() p.Output = cmd.OutOrStdout()
prm.SetPayloadReader(p.NewProxyReader(f)) prm.SetPayloadReader(p.NewProxyReader(payloadReader))
prm.SetHeaderCallback(func(o *object.Object) { prm.SetHeaderCallback(func(o *object.Object) { p.Start() })
p.Start() } 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))
prm.SetHeaderCallback(func(o *object.Object) {
p.Start()
})
}
} }
} }
@ -162,7 +189,7 @@ func parseObjectAttrs(cmd *cobra.Command) ([]object.Attribute, error) {
disableFilename, _ := cmd.Flags().GetBool("disable-filename") disableFilename, _ := cmd.Flags().GetBool("disable-filename")
if !disableFilename { if !disableFilename {
filename := filepath.Base(cmd.Flag("file").Value.String()) filename := filepath.Base(cmd.Flag(fileFlag).Value.String())
index := len(attrs) index := len(attrs)
attrs = append(attrs, object.Attribute{}) attrs = append(attrs, object.Attribute{})
attrs[index].SetKey(object.AttributeFileName) attrs[index].SetKey(object.AttributeFileName)

View file

@ -32,14 +32,14 @@ func initObjectRangeCmd() {
flags := objectRangeCmd.Flags() flags := objectRangeCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectRangeCmd.MarkFlagRequired("cid") _ = objectRangeCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.String("oid", "", "Object ID") flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage)
_ = objectRangeCmd.MarkFlagRequired("oid") _ = objectRangeCmd.MarkFlagRequired(commonflags.OIDFlag)
flags.String("range", "", "Range to take data from in the form offset:length") flags.String("range", "", "Range to take data from in the form offset:length")
flags.String("file", "", "File to write object payload to. Default: stdout.") flags.String(fileFlag, "", "File to write object payload to. Default: stdout.")
flags.Bool(rawFlag, false, rawFlagDesc) flags.Bool(rawFlag, false, rawFlagDesc)
} }
@ -58,7 +58,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) {
var out io.Writer var out io.Writer
filename := cmd.Flag("file").Value.String() filename := cmd.Flag(fileFlag).Value.String()
if filename == "" { if filename == "" {
out = os.Stdout out = os.Stdout
} else { } else {

View file

@ -15,8 +15,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
const searchOIDFlag = "oid"
var ( var (
searchFilters []string searchFilters []string
@ -34,15 +32,15 @@ func initObjectSearchCmd() {
flags := objectSearchCmd.Flags() flags := objectSearchCmd.Flags()
flags.String("cid", "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = objectSearchCmd.MarkFlagRequired("cid") _ = objectSearchCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.StringSliceVarP(&searchFilters, "filters", "f", nil, flags.StringSliceVarP(&searchFilters, "filters", "f", nil,
"Repeated filter expressions or files with protobuf JSON") "Repeated filter expressions or files with protobuf JSON")
flags.Bool("root", false, "Search for user objects") flags.Bool("root", false, "Search for user objects")
flags.Bool("phy", false, "Search physically stored objects") flags.Bool("phy", false, "Search physically stored objects")
flags.String(searchOIDFlag, "", "Search object by identifier") flags.String(commonflags.OIDFlag, "", "Search object by identifier")
} }
func searchObject(cmd *cobra.Command, _ []string) { func searchObject(cmd *cobra.Command, _ []string) {
@ -133,7 +131,7 @@ func parseSearchFilters(cmd *cobra.Command) (object.SearchFilters, error) {
fs.AddPhyFilter() fs.AddPhyFilter()
} }
oid, _ := cmd.Flags().GetString(searchOIDFlag) oid, _ := cmd.Flags().GetString(commonflags.OIDFlag)
if oid != "" { if oid != "" {
var id oidSDK.ID var id oidSDK.ID
if err := id.DecodeString(oid); err != nil { if err := id.DecodeString(oid); err != nil {

View file

@ -4,6 +4,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"errors" "errors"
"fmt" "fmt"
"os"
"strings" "strings"
internal "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" internal "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client"
@ -26,6 +27,8 @@ const (
rawFlag = "raw" rawFlag = "raw"
rawFlagDesc = "Set raw request option" rawFlagDesc = "Set raw request option"
fileFlag = "file"
binaryFlag = "binary"
) )
type RPCParameters interface { type RPCParameters interface {
@ -80,13 +83,27 @@ func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address
return addr return addr
} }
func readObjectAddressBin(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID, filename string) oid.Address {
buf, err := os.ReadFile(filename)
common.ExitOnErr(cmd, "unable to read given file: %w", err)
objTemp := object.New()
common.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf))
var addr oid.Address
*cnr, _ = objTemp.ContainerID()
*obj, _ = objTemp.ID()
addr.SetContainer(*cnr)
addr.SetObject(*obj)
return addr
}
func readCID(cmd *cobra.Command, id *cid.ID) { func readCID(cmd *cobra.Command, id *cid.ID) {
err := id.DecodeString(cmd.Flag("cid").Value.String()) err := id.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String())
common.ExitOnErr(cmd, "decode container ID string: %w", err) common.ExitOnErr(cmd, "decode container ID string: %w", err)
} }
func readOID(cmd *cobra.Command, id *oid.ID) { func readOID(cmd *cobra.Command, id *oid.ID) {
err := id.DecodeString(cmd.Flag("oid").Value.String()) err := id.DecodeString(cmd.Flag(commonflags.OIDFlag).Value.String())
common.ExitOnErr(cmd, "decode object ID string: %w", err) common.ExitOnErr(cmd, "decode object ID string: %w", err)
} }

View file

@ -23,8 +23,8 @@ func initSGDeleteCmd() {
flags := sgDelCmd.Flags() flags := sgDelCmd.Flags()
flags.String(cidFlag, "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = sgDelCmd.MarkFlagRequired(cidFlag) _ = sgDelCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier") flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier")
_ = sgDelCmd.MarkFlagRequired(sgIDFlag) _ = sgDelCmd.MarkFlagRequired(sgIDFlag)

View file

@ -28,8 +28,8 @@ func initSGGetCmd() {
flags := sgGetCmd.Flags() flags := sgGetCmd.Flags()
flags.String(cidFlag, "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = sgGetCmd.MarkFlagRequired(cidFlag) _ = sgGetCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier") flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier")
_ = sgGetCmd.MarkFlagRequired(sgIDFlag) _ = sgGetCmd.MarkFlagRequired(sgIDFlag)

View file

@ -21,8 +21,8 @@ var sgListCmd = &cobra.Command{
func initSGListCmd() { func initSGListCmd() {
commonflags.Init(sgListCmd) commonflags.Init(sgListCmd)
sgListCmd.Flags().String(cidFlag, "", "Container ID") sgListCmd.Flags().String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = sgListCmd.MarkFlagRequired(cidFlag) _ = sgListCmd.MarkFlagRequired(commonflags.CIDFlag)
} }
func listSG(cmd *cobra.Command, _ []string) { func listSG(cmd *cobra.Command, _ []string) {

View file

@ -36,8 +36,8 @@ func initSGPutCmd() {
flags := sgPutCmd.Flags() flags := sgPutCmd.Flags()
flags.String(cidFlag, "", "Container ID") flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = sgPutCmd.MarkFlagRequired(cidFlag) _ = sgPutCmd.MarkFlagRequired(commonflags.CIDFlag)
flags.StringSliceVarP(&sgMembers, sgMembersFlag, "m", nil, "ID list of storage group members") flags.StringSliceVarP(&sgMembers, sgMembersFlag, "m", nil, "ID list of storage group members")
_ = sgPutCmd.MarkFlagRequired(sgMembersFlag) _ = sgPutCmd.MarkFlagRequired(sgMembersFlag)

View file

@ -22,7 +22,6 @@ var Cmd = &cobra.Command{
const ( const (
sgIDFlag = "id" sgIDFlag = "id"
sgRawFlag = "raw" sgRawFlag = "raw"
cidFlag = "cid"
) )
func init() { func init() {

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -20,9 +21,9 @@ func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address
} }
func readCID(cmd *cobra.Command, id *cid.ID) { func readCID(cmd *cobra.Command, id *cid.ID) {
f := cmd.Flag(cidFlag) f := cmd.Flag(commonflags.CIDFlag)
if f == nil { if f == nil {
common.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", cidFlag)) common.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag))
return return
} }

View file

@ -37,7 +37,7 @@ func add(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
var cnr cid.ID var cnr cid.ID
err := cnr.DecodeString(cmd.Flag(containerIDFlagKey).Value.String()) err := cnr.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String())
common.ExitOnErr(cmd, "decode container ID string: %w", err) common.ExitOnErr(cmd, "decode container ID string: %w", err)
tid, _ := cmd.Flags().GetString(treeIDFlagKey) tid, _ := cmd.Flags().GetString(treeIDFlagKey)

View file

@ -42,7 +42,7 @@ func initAddByPathCmd() {
func addByPath(cmd *cobra.Command, _ []string) { func addByPath(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
cidRaw, _ := cmd.Flags().GetString(containerIDFlagKey) cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cnr cid.ID var cnr cid.ID
err := cnr.DecodeString(cidRaw) err := cnr.DecodeString(cidRaw)

View file

@ -42,7 +42,7 @@ func initGetByPathCmd() {
func getByPath(cmd *cobra.Command, _ []string) { func getByPath(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
cidRaw, _ := cmd.Flags().GetString(containerIDFlagKey) cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cnr cid.ID var cnr cid.ID
err := cnr.DecodeString(cidRaw) err := cnr.DecodeString(cidRaw)

View file

@ -24,15 +24,15 @@ func initListCmd() {
commonflags.Init(listCmd) commonflags.Init(listCmd)
ff := listCmd.Flags() ff := listCmd.Flags()
ff.String(containerIDFlagKey, "", "Container ID") ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = listCmd.MarkFlagRequired(containerIDFlagKey) _ = listCmd.MarkFlagRequired(commonflags.CIDFlag)
_ = cobra.MarkFlagRequired(ff, commonflags.RPC) _ = cobra.MarkFlagRequired(ff, commonflags.RPC)
} }
func list(cmd *cobra.Command, _ []string) { func list(cmd *cobra.Command, _ []string) {
pk := key.GetOrGenerate(cmd) pk := key.GetOrGenerate(cmd)
cidString, _ := cmd.Flags().GetString(containerIDFlagKey) cidString, _ := cmd.Flags().GetString(commonflags.CIDFlag)
var cnr cid.ID var cnr cid.ID
err := cnr.DecodeString(cidString) err := cnr.DecodeString(cidString)

View file

@ -1,6 +1,7 @@
package tree package tree
import ( import (
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -22,9 +23,8 @@ func init() {
} }
const ( const (
containerIDFlagKey = "cid" treeIDFlagKey = "tid"
treeIDFlagKey = "tid" parentIDFlagKey = "pid"
parentIDFlagKey = "pid"
metaFlagKey = "meta" metaFlagKey = "meta"
@ -37,8 +37,8 @@ const (
func initCTID(cmd *cobra.Command) { func initCTID(cmd *cobra.Command) {
ff := cmd.Flags() ff := cmd.Flags()
ff.String(containerIDFlagKey, "", "Container ID") ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage)
_ = cmd.MarkFlagRequired(containerIDFlagKey) _ = cmd.MarkFlagRequired(commonflags.CIDFlag)
ff.String(treeIDFlagKey, "", "Tree ID") ff.String(treeIDFlagKey, "", "Tree ID")
_ = cmd.MarkFlagRequired(treeIDFlagKey) _ = cmd.MarkFlagRequired(treeIDFlagKey)