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 bc090b3897..b3f7a39690 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 16a2353a06..810e621072 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 baef71ffb2..7add3ec5ec 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 53d7e83bdb..f4311d9b1d 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 9655fc63a1..7959c66247 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 2967efb03c..482977b17f 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 cfabfabce9..74c1f955f8 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 acc8bf5b56..b142154fbf 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 953d9804a4..fb5f39e695 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 fcbd08cb64..2bf4515196 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 82e2e7134e..6bf06c662b 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 2ed4b95b18..6c2e09fa91 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 9ab76d3d16..a947cac808 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 5fce730f3f..417362856f 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 9f952d4d19..1e14827564 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 e8f579832f..337e6c0d5a 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 3d5ecf8b02..effb0d67fa 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 681bacb6bf..a6c0990573 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 1139aa7e69..3b62974b3c 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 531fa17d2c..10f7bde7b9 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 238c82e0e4..d7e3aea60c 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 9be954ca04..0d5be94d66 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 d22c1bd5a6..aacc49edee 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 3a784b8e3b..926a6e1ef6 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 3e9093d8df..da97198df2 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 03a49adb2d..2230733346 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 1ca9ec46b3..756e42ffd8 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 f49e2b4c97..2546f88ced 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 03500d154a..076cf1f1dd 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 dbd2a5ec37..a59ef4177b 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)