From bb52857b2b1a767f99e2ea963ab0000707bffa9e Mon Sep 17 00:00:00 2001 From: Anton Nikiforov Date: Tue, 18 Oct 2022 14:43:04 +0300 Subject: [PATCH] [#1338] neofs-cli: Add support to store/restore/delete binary objects Signed-off-by: Anton Nikiforov --- CHANGELOG.md | 1 + cmd/neofs-cli/internal/commonflags/flags.go | 6 ++ cmd/neofs-cli/modules/acl/extended/create.go | 5 +- cmd/neofs-cli/modules/container/delete.go | 2 +- cmd/neofs-cli/modules/container/get.go | 5 +- cmd/neofs-cli/modules/container/get_eacl.go | 2 +- .../modules/container/list_objects.go | 2 +- cmd/neofs-cli/modules/container/nodes.go | 2 +- cmd/neofs-cli/modules/container/set_eacl.go | 2 +- .../modules/control/synchronize_tree.go | 5 +- cmd/neofs-cli/modules/object/delete.go | 34 +++++++-- cmd/neofs-cli/modules/object/get.go | 38 +++++++--- cmd/neofs-cli/modules/object/hash.go | 8 +-- cmd/neofs-cli/modules/object/head.go | 12 ++-- cmd/neofs-cli/modules/object/lock.go | 12 ++-- cmd/neofs-cli/modules/object/put.go | 71 +++++++++++++------ cmd/neofs-cli/modules/object/range.go | 12 ++-- cmd/neofs-cli/modules/object/search.go | 10 ++- cmd/neofs-cli/modules/object/util.go | 21 +++++- cmd/neofs-cli/modules/storagegroup/delete.go | 4 +- cmd/neofs-cli/modules/storagegroup/get.go | 4 +- cmd/neofs-cli/modules/storagegroup/list.go | 4 +- cmd/neofs-cli/modules/storagegroup/put.go | 4 +- cmd/neofs-cli/modules/storagegroup/root.go | 1 - cmd/neofs-cli/modules/storagegroup/util.go | 5 +- cmd/neofs-cli/modules/tree/add.go | 2 +- cmd/neofs-cli/modules/tree/add_by_path.go | 2 +- cmd/neofs-cli/modules/tree/get_by_path.go | 2 +- cmd/neofs-cli/modules/tree/list.go | 6 +- cmd/neofs-cli/modules/tree/root.go | 10 +-- 30 files changed, 193 insertions(+), 101 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc090b389..b3f7a3969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Changelog for NeoFS Node ### Added - `morph list-containers` in `neofs-adm` (#1689) +- `--binary` flag in `neofs-cli object put/get/delete` commands (#1338) ### Changed - `object lock` command reads CID and OID the same way other commands do (#1971) diff --git a/cmd/neofs-cli/internal/commonflags/flags.go b/cmd/neofs-cli/internal/commonflags/flags.go index 16a2353a0..810e62107 100644 --- a/cmd/neofs-cli/internal/commonflags/flags.go +++ b/cmd/neofs-cli/internal/commonflags/flags.go @@ -41,6 +41,12 @@ const ( ForceFlag = "force" ForceFlagShorthand = "f" + + CIDFlag = "cid" + CIDFlagUsage = "Container ID." + + OIDFlag = "oid" + OIDFlagUsage = "Object ID." ) // Init adds common flags to the command: diff --git a/cmd/neofs-cli/modules/acl/extended/create.go b/cmd/neofs-cli/modules/acl/extended/create.go index baef71ffb..7add3ec5e 100644 --- a/cmd/neofs-cli/modules/acl/extended/create.go +++ b/cmd/neofs-cli/modules/acl/extended/create.go @@ -11,6 +11,7 @@ import ( "github.com/flynn-archive/go-shlex" "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" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/spf13/cobra" @@ -53,7 +54,7 @@ func init() { 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("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(), "out") @@ -63,7 +64,7 @@ func createEACL(cmd *cobra.Command, _ []string) { rules, _ := cmd.Flags().GetStringArray("rule") fileArg, _ := cmd.Flags().GetString("file") outArg, _ := cmd.Flags().GetString("out") - cidArg, _ := cmd.Flags().GetString("cid") + cidArg, _ := cmd.Flags().GetString(commonflags.CIDFlag) var containerID cid.ID if cidArg != "" { diff --git a/cmd/neofs-cli/modules/container/delete.go b/cmd/neofs-cli/modules/container/delete.go index 53d7e83bd..f4311d9b1 100644 --- a/cmd/neofs-cli/modules/container/delete.go +++ b/cmd/neofs-cli/modules/container/delete.go @@ -89,7 +89,7 @@ func initContainerDeleteCmd() { flags.StringP(commonflags.Account, commonflags.AccountShorthand, commonflags.AccountDefault, commonflags.AccountUsage) 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.BoolP(commonflags.ForceFlag, commonflags.ForceFlagShorthand, false, "Do not check whether container contains locks and remove immediately") } diff --git a/cmd/neofs-cli/modules/container/get.go b/cmd/neofs-cli/modules/container/get.go index 9655fc63a..7959c6624 100644 --- a/cmd/neofs-cli/modules/container/get.go +++ b/cmd/neofs-cli/modules/container/get.go @@ -17,9 +17,6 @@ import ( ) const ( - cidFlag = "cid" - cidFlagUsage = "Container ID" - fromFlag = "from" fromFlagUsage = "Path to file with encoded container" ) @@ -64,7 +61,7 @@ func initContainerInfoCmd() { 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(&containerPathFrom, fromFlag, "", fromFlagUsage) flags.BoolVar(&containerJSON, commonflags.JSON, false, "Print or dump container in JSON format") diff --git a/cmd/neofs-cli/modules/container/get_eacl.go b/cmd/neofs-cli/modules/container/get_eacl.go index 2967efb03..482977b17 100644 --- a/cmd/neofs-cli/modules/container/get_eacl.go +++ b/cmd/neofs-cli/modules/container/get_eacl.go @@ -57,7 +57,7 @@ func initContainerGetEACLCmd() { 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.BoolVar(&containerJSON, commonflags.JSON, false, "Encode EACL table in json format") } diff --git a/cmd/neofs-cli/modules/container/list_objects.go b/cmd/neofs-cli/modules/container/list_objects.go index cfabfabce..74c1f955f 100644 --- a/cmd/neofs-cli/modules/container/list_objects.go +++ b/cmd/neofs-cli/modules/container/list_objects.go @@ -89,7 +89,7 @@ func initContainerListObjectsCmd() { flags := listContainerObjectsCmd.Flags() - flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) + flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.BoolVar(&flagVarListObjectsPrintAttr, flagListObjectPrintAttr, false, "Request and print user attributes of each object", ) diff --git a/cmd/neofs-cli/modules/container/nodes.go b/cmd/neofs-cli/modules/container/nodes.go index acc8bf5b5..b142154fb 100644 --- a/cmd/neofs-cli/modules/container/nodes.go +++ b/cmd/neofs-cli/modules/container/nodes.go @@ -58,7 +58,7 @@ func initContainerNodesCmd() { commonflags.Init(containerNodesCmd) flags := containerNodesCmd.Flags() - flags.StringVar(&containerID, cidFlag, "", cidFlagUsage) + flags.StringVar(&containerID, commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.StringVar(&containerPathFrom, fromFlag, "", fromFlagUsage) flags.BoolVar(&short, "short", false, "Shortens output of node info") } diff --git a/cmd/neofs-cli/modules/container/set_eacl.go b/cmd/neofs-cli/modules/container/set_eacl.go index 953d9804a..fb5f39e69 100644 --- a/cmd/neofs-cli/modules/container/set_eacl.go +++ b/cmd/neofs-cli/modules/container/set_eacl.go @@ -96,7 +96,7 @@ func initContainerSetEACLCmd() { commonflags.Init(setExtendedACLCmd) 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.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") diff --git a/cmd/neofs-cli/modules/control/synchronize_tree.go b/cmd/neofs-cli/modules/control/synchronize_tree.go index fcbd08cb6..2bf451519 100644 --- a/cmd/neofs-cli/modules/control/synchronize_tree.go +++ b/cmd/neofs-cli/modules/control/synchronize_tree.go @@ -6,6 +6,7 @@ import ( 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/commonflags" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/services/control" controlSvc "github.com/nspcc-dev/neofs-node/pkg/services/control/server" @@ -29,7 +30,7 @@ func initControlSynchronizeTreeCmd() { initControlFlags(synchronizeTreeCmd) flags := synchronizeTreeCmd.Flags() - flags.String("cid", "", "Container ID") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.String(synchronizeTreeIDFlag, "", "Tree ID") flags.Uint64(synchronizeTreeHeightFlag, 0, "Starting height") } @@ -38,7 +39,7 @@ func synchronizeTree(cmd *cobra.Command, _ []string) { pk := key.Get(cmd) 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)) treeID, _ := cmd.Flags().GetString("tree-id") diff --git a/cmd/neofs-cli/modules/object/delete.go b/cmd/neofs-cli/modules/object/delete.go index 82e2e7134..6bf06c662 100644 --- a/cmd/neofs-cli/modules/object/delete.go +++ b/cmd/neofs-cli/modules/object/delete.go @@ -1,6 +1,8 @@ package object import ( + "fmt" + 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/commonflags" @@ -24,18 +26,38 @@ func initObjectDeleteCmd() { flags := objectDelCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectDelCmd.MarkFlagRequired("cid") - - flags.String("oid", "", "Object ID") - _ = objectDelCmd.MarkFlagRequired("oid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + flags.Bool(binaryFlag, false, "Deserialize object structure from given file.") + flags.String(fileFlag, "", "File with object payload") } func deleteObject(cmd *cobra.Command, _ []string) { var cnr cid.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) var prm internalclient.DeleteObjectPrm diff --git a/cmd/neofs-cli/modules/object/get.go b/cmd/neofs-cli/modules/object/get.go index 2ed4b95b1..6c2e09fa9 100644 --- a/cmd/neofs-cli/modules/object/get.go +++ b/cmd/neofs-cli/modules/object/get.go @@ -1,6 +1,7 @@ package object import ( + "bytes" "fmt" "io" "os" @@ -29,16 +30,17 @@ func initObjectGetCmd() { flags := objectGetCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectGetCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectGetCmd.MarkFlagRequired(commonflags.CIDFlag) - flags.String("oid", "", "Object ID") - _ = objectGetCmd.MarkFlagRequired("oid") + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = 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.Bool(rawFlag, false, rawFlagDesc) 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) { @@ -48,7 +50,7 @@ func getObject(cmd *cobra.Command, _ []string) { objAddr := readObjectAddress(cmd, &cnr, &obj) var out io.Writer - filename := cmd.Flag("file").Value.String() + filename := cmd.Flag(fileFlag).Value.String() if filename == "" { out = os.Stdout } else { @@ -78,12 +80,22 @@ func getObject(cmd *cobra.Command, _ []string) { var p *pb.ProgressBar 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 { - prm.SetPayloadWriter(out) + prm.SetPayloadWriter(payloadWriter) } else { p = pb.New64(0) p.Output = cmd.OutOrStdout() - prm.SetPayloadWriter(p.NewProxyWriter(out)) + prm.SetPayloadWriter(p.NewProxyWriter(payloadWriter)) prm.SetHeaderCallback(func(o *object.Object) { p.SetTotal64(int64(o.PayloadSize())) p.Start() @@ -102,6 +114,16 @@ func getObject(cmd *cobra.Command, _ []string) { 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() if filename != "" { if hdrFile != "" || !strictOutput(cmd) { diff --git a/cmd/neofs-cli/modules/object/hash.go b/cmd/neofs-cli/modules/object/hash.go index 9ab76d3d1..a947cac80 100644 --- a/cmd/neofs-cli/modules/object/hash.go +++ b/cmd/neofs-cli/modules/object/hash.go @@ -35,11 +35,11 @@ func initObjectHashCmd() { flags := objectHashCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectHashCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectHashCmd.MarkFlagRequired(commonflags.CIDFlag) - flags.String("oid", "", "Object ID") - _ = objectHashCmd.MarkFlagRequired("oid") + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = objectHashCmd.MarkFlagRequired(commonflags.OIDFlag) flags.String("range", "", "Range to take hash from in the form offset1:length1,...") flags.String("type", hashSha256, "Hash type. Either 'sha256' or 'tz'") diff --git a/cmd/neofs-cli/modules/object/head.go b/cmd/neofs-cli/modules/object/head.go index 5fce730f3..417362856 100644 --- a/cmd/neofs-cli/modules/object/head.go +++ b/cmd/neofs-cli/modules/object/head.go @@ -31,13 +31,13 @@ func initObjectHeadCmd() { flags := objectHeadCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectHeadCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectHeadCmd.MarkFlagRequired(commonflags.CIDFlag) - flags.String("oid", "", "Object ID") - _ = objectHeadCmd.MarkFlagRequired("oid") + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = 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(commonflags.JSON, false, "Marshal output in JSON") 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) } - err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag("file").Value.String()) + err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag(fileFlag).Value.String()) common.ExitOnErr(cmd, "", err) } diff --git a/cmd/neofs-cli/modules/object/lock.go b/cmd/neofs-cli/modules/object/lock.go index 9f952d4d1..1e1482756 100644 --- a/cmd/neofs-cli/modules/object/lock.go +++ b/cmd/neofs-cli/modules/object/lock.go @@ -25,13 +25,13 @@ var objectLockCmd = &cobra.Command{ Short: "Lock object in container", Long: "Lock object in container", Run: func(cmd *cobra.Command, _ []string) { - cidRaw, _ := cmd.Flags().GetString("cid") + cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID err := cnr.DecodeString(cidRaw) 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)) @@ -96,11 +96,11 @@ func initCommandObjectLock() { ff := objectLockCmd.Flags() - ff.String("cid", "", "Container ID") - _ = objectLockCmd.MarkFlagRequired("cid") + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectLockCmd.MarkFlagRequired(commonflags.CIDFlag) - ff.StringSlice("oid", nil, "Object ID") - _ = objectLockCmd.MarkFlagRequired("oid") + ff.StringSlice(commonflags.OIDFlag, nil, commonflags.OIDFlagUsage) + _ = objectLockCmd.MarkFlagRequired(commonflags.OIDFlag) ff.Uint64P(commonflags.ExpireAt, "e", 0, "Lock expiration epoch") diff --git a/cmd/neofs-cli/modules/object/put.go b/cmd/neofs-cli/modules/object/put.go index e8f579832..337e6c0d5 100644 --- a/cmd/neofs-cli/modules/object/put.go +++ b/cmd/neofs-cli/modules/object/put.go @@ -1,7 +1,9 @@ package object import ( + "bytes" "fmt" + "io" "os" "path/filepath" "strconv" @@ -40,12 +42,11 @@ func initObjectPutCmd() { flags := objectPutCmd.Flags() - flags.String("file", "", "File with object payload") - _ = objectPutCmd.MarkFlagFilename("file") - _ = objectPutCmd.MarkFlagRequired("file") + flags.String(fileFlag, "", "File with object payload") + _ = objectPutCmd.MarkFlagFilename(fileFlag) + _ = objectPutCmd.MarkFlagRequired(fileFlag) - flags.String("cid", "", "Container ID") - _ = objectPutCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) flags.String("attributes", "", "User attributes in form of Key1=Value1,Key2=Value2") 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.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) { + 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) var ownerID user.ID - user.IDFromKey(&ownerID, pk.PublicKey) - 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) if err != nil { 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) 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.SetOwnerID(&ownerID) obj.SetAttributes(attrs...) @@ -116,19 +136,26 @@ func putObject(cmd *cobra.Command, _ []string) { noProgress, _ := cmd.Flags().GetBool(noProgressFlag) if noProgress { - prm.SetPayloadReader(f) + prm.SetPayloadReader(payloadReader) } 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()) + if binary { + p = pb.New(len(obj.Payload())) p.Output = cmd.OutOrStdout() - prm.SetPayloadReader(p.NewProxyReader(f)) - prm.SetHeaderCallback(func(o *object.Object) { - p.Start() - }) + prm.SetPayloadReader(p.NewProxyReader(payloadReader)) + prm.SetHeaderCallback(func(o *object.Object) { 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") if !disableFilename { - filename := filepath.Base(cmd.Flag("file").Value.String()) + filename := filepath.Base(cmd.Flag(fileFlag).Value.String()) index := len(attrs) attrs = append(attrs, object.Attribute{}) attrs[index].SetKey(object.AttributeFileName) diff --git a/cmd/neofs-cli/modules/object/range.go b/cmd/neofs-cli/modules/object/range.go index 3d5ecf8b0..effb0d67f 100644 --- a/cmd/neofs-cli/modules/object/range.go +++ b/cmd/neofs-cli/modules/object/range.go @@ -32,14 +32,14 @@ func initObjectRangeCmd() { flags := objectRangeCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectRangeCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectRangeCmd.MarkFlagRequired(commonflags.CIDFlag) - flags.String("oid", "", "Object ID") - _ = objectRangeCmd.MarkFlagRequired("oid") + flags.String(commonflags.OIDFlag, "", commonflags.OIDFlagUsage) + _ = objectRangeCmd.MarkFlagRequired(commonflags.OIDFlag) 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) } @@ -58,7 +58,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { var out io.Writer - filename := cmd.Flag("file").Value.String() + filename := cmd.Flag(fileFlag).Value.String() if filename == "" { out = os.Stdout } else { diff --git a/cmd/neofs-cli/modules/object/search.go b/cmd/neofs-cli/modules/object/search.go index 681bacb6b..a6c099057 100644 --- a/cmd/neofs-cli/modules/object/search.go +++ b/cmd/neofs-cli/modules/object/search.go @@ -15,8 +15,6 @@ import ( "github.com/spf13/cobra" ) -const searchOIDFlag = "oid" - var ( searchFilters []string @@ -34,15 +32,15 @@ func initObjectSearchCmd() { flags := objectSearchCmd.Flags() - flags.String("cid", "", "Container ID") - _ = objectSearchCmd.MarkFlagRequired("cid") + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = objectSearchCmd.MarkFlagRequired(commonflags.CIDFlag) flags.StringSliceVarP(&searchFilters, "filters", "f", nil, "Repeated filter expressions or files with protobuf JSON") flags.Bool("root", false, "Search for user 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) { @@ -133,7 +131,7 @@ func parseSearchFilters(cmd *cobra.Command) (object.SearchFilters, error) { fs.AddPhyFilter() } - oid, _ := cmd.Flags().GetString(searchOIDFlag) + oid, _ := cmd.Flags().GetString(commonflags.OIDFlag) if oid != "" { var id oidSDK.ID if err := id.DecodeString(oid); err != nil { diff --git a/cmd/neofs-cli/modules/object/util.go b/cmd/neofs-cli/modules/object/util.go index 1139aa7e6..3b62974b3 100644 --- a/cmd/neofs-cli/modules/object/util.go +++ b/cmd/neofs-cli/modules/object/util.go @@ -4,6 +4,7 @@ import ( "crypto/ecdsa" "errors" "fmt" + "os" "strings" internal "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" @@ -26,6 +27,8 @@ const ( rawFlag = "raw" rawFlagDesc = "Set raw request option" + fileFlag = "file" + binaryFlag = "binary" ) type RPCParameters interface { @@ -80,13 +83,27 @@ func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address 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) { - 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) } 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) } diff --git a/cmd/neofs-cli/modules/storagegroup/delete.go b/cmd/neofs-cli/modules/storagegroup/delete.go index 531fa17d2..10f7bde7b 100644 --- a/cmd/neofs-cli/modules/storagegroup/delete.go +++ b/cmd/neofs-cli/modules/storagegroup/delete.go @@ -23,8 +23,8 @@ func initSGDeleteCmd() { flags := sgDelCmd.Flags() - flags.String(cidFlag, "", "Container ID") - _ = sgDelCmd.MarkFlagRequired(cidFlag) + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = sgDelCmd.MarkFlagRequired(commonflags.CIDFlag) flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier") _ = sgDelCmd.MarkFlagRequired(sgIDFlag) diff --git a/cmd/neofs-cli/modules/storagegroup/get.go b/cmd/neofs-cli/modules/storagegroup/get.go index 238c82e0e..d7e3aea60 100644 --- a/cmd/neofs-cli/modules/storagegroup/get.go +++ b/cmd/neofs-cli/modules/storagegroup/get.go @@ -28,8 +28,8 @@ func initSGGetCmd() { flags := sgGetCmd.Flags() - flags.String(cidFlag, "", "Container ID") - _ = sgGetCmd.MarkFlagRequired(cidFlag) + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = sgGetCmd.MarkFlagRequired(commonflags.CIDFlag) flags.StringVarP(&sgID, sgIDFlag, "", "", "Storage group identifier") _ = sgGetCmd.MarkFlagRequired(sgIDFlag) diff --git a/cmd/neofs-cli/modules/storagegroup/list.go b/cmd/neofs-cli/modules/storagegroup/list.go index 9be954ca0..0d5be94d6 100644 --- a/cmd/neofs-cli/modules/storagegroup/list.go +++ b/cmd/neofs-cli/modules/storagegroup/list.go @@ -21,8 +21,8 @@ var sgListCmd = &cobra.Command{ func initSGListCmd() { commonflags.Init(sgListCmd) - sgListCmd.Flags().String(cidFlag, "", "Container ID") - _ = sgListCmd.MarkFlagRequired(cidFlag) + sgListCmd.Flags().String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = sgListCmd.MarkFlagRequired(commonflags.CIDFlag) } func listSG(cmd *cobra.Command, _ []string) { diff --git a/cmd/neofs-cli/modules/storagegroup/put.go b/cmd/neofs-cli/modules/storagegroup/put.go index d22c1bd5a..aacc49ede 100644 --- a/cmd/neofs-cli/modules/storagegroup/put.go +++ b/cmd/neofs-cli/modules/storagegroup/put.go @@ -36,8 +36,8 @@ func initSGPutCmd() { flags := sgPutCmd.Flags() - flags.String(cidFlag, "", "Container ID") - _ = sgPutCmd.MarkFlagRequired(cidFlag) + flags.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = sgPutCmd.MarkFlagRequired(commonflags.CIDFlag) flags.StringSliceVarP(&sgMembers, sgMembersFlag, "m", nil, "ID list of storage group members") _ = sgPutCmd.MarkFlagRequired(sgMembersFlag) diff --git a/cmd/neofs-cli/modules/storagegroup/root.go b/cmd/neofs-cli/modules/storagegroup/root.go index 3a784b8e3..926a6e1ef 100644 --- a/cmd/neofs-cli/modules/storagegroup/root.go +++ b/cmd/neofs-cli/modules/storagegroup/root.go @@ -22,7 +22,6 @@ var Cmd = &cobra.Command{ const ( sgIDFlag = "id" sgRawFlag = "raw" - cidFlag = "cid" ) func init() { diff --git a/cmd/neofs-cli/modules/storagegroup/util.go b/cmd/neofs-cli/modules/storagegroup/util.go index 3e9093d8d..da97198df 100644 --- a/cmd/neofs-cli/modules/storagegroup/util.go +++ b/cmd/neofs-cli/modules/storagegroup/util.go @@ -4,6 +4,7 @@ import ( "fmt" "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" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "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) { - f := cmd.Flag(cidFlag) + f := cmd.Flag(commonflags.CIDFlag) 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 } diff --git a/cmd/neofs-cli/modules/tree/add.go b/cmd/neofs-cli/modules/tree/add.go index 03a49adb2..223073334 100644 --- a/cmd/neofs-cli/modules/tree/add.go +++ b/cmd/neofs-cli/modules/tree/add.go @@ -37,7 +37,7 @@ func add(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) 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) tid, _ := cmd.Flags().GetString(treeIDFlagKey) diff --git a/cmd/neofs-cli/modules/tree/add_by_path.go b/cmd/neofs-cli/modules/tree/add_by_path.go index 1ca9ec46b..756e42ffd 100644 --- a/cmd/neofs-cli/modules/tree/add_by_path.go +++ b/cmd/neofs-cli/modules/tree/add_by_path.go @@ -42,7 +42,7 @@ func initAddByPathCmd() { func addByPath(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cidRaw, _ := cmd.Flags().GetString(containerIDFlagKey) + cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID err := cnr.DecodeString(cidRaw) diff --git a/cmd/neofs-cli/modules/tree/get_by_path.go b/cmd/neofs-cli/modules/tree/get_by_path.go index f49e2b4c9..2546f88ce 100644 --- a/cmd/neofs-cli/modules/tree/get_by_path.go +++ b/cmd/neofs-cli/modules/tree/get_by_path.go @@ -42,7 +42,7 @@ func initGetByPathCmd() { func getByPath(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cidRaw, _ := cmd.Flags().GetString(containerIDFlagKey) + cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID err := cnr.DecodeString(cidRaw) diff --git a/cmd/neofs-cli/modules/tree/list.go b/cmd/neofs-cli/modules/tree/list.go index 03500d154..076cf1f1d 100644 --- a/cmd/neofs-cli/modules/tree/list.go +++ b/cmd/neofs-cli/modules/tree/list.go @@ -24,15 +24,15 @@ func initListCmd() { commonflags.Init(listCmd) ff := listCmd.Flags() - ff.String(containerIDFlagKey, "", "Container ID") - _ = listCmd.MarkFlagRequired(containerIDFlagKey) + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = listCmd.MarkFlagRequired(commonflags.CIDFlag) _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } func list(cmd *cobra.Command, _ []string) { pk := key.GetOrGenerate(cmd) - cidString, _ := cmd.Flags().GetString(containerIDFlagKey) + cidString, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID err := cnr.DecodeString(cidString) diff --git a/cmd/neofs-cli/modules/tree/root.go b/cmd/neofs-cli/modules/tree/root.go index dbd2a5ec3..a59ef4177 100644 --- a/cmd/neofs-cli/modules/tree/root.go +++ b/cmd/neofs-cli/modules/tree/root.go @@ -1,6 +1,7 @@ package tree import ( + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" "github.com/spf13/cobra" ) @@ -22,9 +23,8 @@ func init() { } const ( - containerIDFlagKey = "cid" - treeIDFlagKey = "tid" - parentIDFlagKey = "pid" + treeIDFlagKey = "tid" + parentIDFlagKey = "pid" metaFlagKey = "meta" @@ -37,8 +37,8 @@ const ( func initCTID(cmd *cobra.Command) { ff := cmd.Flags() - ff.String(containerIDFlagKey, "", "Container ID") - _ = cmd.MarkFlagRequired(containerIDFlagKey) + ff.String(commonflags.CIDFlag, "", commonflags.CIDFlagUsage) + _ = cmd.MarkFlagRequired(commonflags.CIDFlag) ff.String(treeIDFlagKey, "", "Tree ID") _ = cmd.MarkFlagRequired(treeIDFlagKey)