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 bc090b38..b3f7a396 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 16a2353a..810e6210 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 baef71ff..7add3ec5 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 53d7e83b..f4311d9b 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 9655fc63..7959c662 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 2967efb0..482977b1 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 cfabfabc..74c1f955 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 acc8bf5b..b142154f 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 953d9804..fb5f39e6 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 fcbd08cb..2bf45151 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 82e2e713..6bf06c66 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 2ed4b95b..6c2e09fa 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 9ab76d3d..a947cac8 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 5fce730f..41736285 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 9f952d4d..1e148275 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 e8f57983..337e6c0d 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 3d5ecf8b..effb0d67 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 681bacb6..a6c09905 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 1139aa7e..3b62974b 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 531fa17d..10f7bde7 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 238c82e0..d7e3aea6 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 9be954ca..0d5be94d 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 d22c1bd5..aacc49ed 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 3a784b8e..926a6e1e 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 3e9093d8..da97198d 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 03a49adb..22307333 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 1ca9ec46..756e42ff 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 f49e2b4c..2546f88c 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 03500d15..076cf1f1 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 dbd2a5ec..a59ef417 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)