From 85bf87d5e31facc7cf0c4be23089a26691287b09 Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Wed, 18 Sep 2024 17:31:04 +0300 Subject: [PATCH] cmd/neofs-lens: add error handler after execution command Use `RunE` instead of `Run` and throw an error to main function. Then handle error with custom error handler. Update CHANGELOG.md. Closes #2890, #623. Signed-off-by: Andrey Butusov --- CHANGELOG.md | 2 + cmd/neofs-lens/internal/errors.go | 17 ------- cmd/neofs-lens/internal/meta/get.go | 25 ++++++++--- cmd/neofs-lens/internal/meta/id.go | 15 +++++-- cmd/neofs-lens/internal/meta/list-garbage.go | 17 ++++--- .../internal/meta/list-graveyard.go | 17 ++++--- cmd/neofs-lens/internal/meta/list.go | 17 ++++--- cmd/neofs-lens/internal/meta/put.go | 33 +++++++++----- cmd/neofs-lens/internal/meta/root.go | 12 +++-- cmd/neofs-lens/internal/meta/status.go | 20 ++++++--- cmd/neofs-lens/internal/object/link.go | 24 ++++++---- cmd/neofs-lens/internal/peapod/get.go | 29 ++++++++---- cmd/neofs-lens/internal/peapod/list.go | 16 ++++--- cmd/neofs-lens/internal/peapod/root.go | 12 +++-- cmd/neofs-lens/internal/printers.go | 13 +++--- cmd/neofs-lens/internal/storage/get.go | 29 ++++++++---- cmd/neofs-lens/internal/storage/list.go | 19 +++++--- cmd/neofs-lens/internal/storage/root.go | 31 ++++++++----- cmd/neofs-lens/internal/storage/sanity.go | 44 ++++++++++++++----- cmd/neofs-lens/internal/storage/status.go | 18 +++++--- cmd/neofs-lens/internal/writecache/get.go | 29 ++++++++---- cmd/neofs-lens/internal/writecache/list.go | 16 ++++--- cmd/neofs-lens/internal/writecache/root.go | 8 ++-- cmd/neofs-lens/root.go | 16 +++---- 24 files changed, 322 insertions(+), 157 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82244af573..812c31b77f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,11 @@ Changelog for NeoFS Node - Expose health status of inner ring via Prometheus (#2934) ### Fixed +- `defer` func is not skipped in cobra-based programs (#2938) ### Changed - `ObjectService`'s `Put` RPC handler caches up to 10K lists of per-object sorted container nodes (#2901) +- When an error is returned, no additional help output is displayed in cobra-based programs (#2938) ### Removed diff --git a/cmd/neofs-lens/internal/errors.go b/cmd/neofs-lens/internal/errors.go index 536ba20318..155e034e16 100644 --- a/cmd/neofs-lens/internal/errors.go +++ b/cmd/neofs-lens/internal/errors.go @@ -2,9 +2,6 @@ package common import ( "fmt" - "os" - - "github.com/spf13/cobra" ) // Errf returns formatted error in errFmt format if err is not nil. @@ -15,17 +12,3 @@ func Errf(errFmt string, err error) error { return fmt.Errorf(errFmt, err) } - -// ExitOnErr calls exitOnErrCode with code 1. -func ExitOnErr(cmd *cobra.Command, err error) { - exitOnErrCode(cmd, err, 1) -} - -// exitOnErrCode prints error via cmd and calls os.Exit with passed exit code. -// Does nothing if err is nil. -func exitOnErrCode(cmd *cobra.Command, err error, code int) { - if err != nil { - cmd.PrintErrln(err) - os.Exit(code) - } -} diff --git a/cmd/neofs-lens/internal/meta/get.go b/cmd/neofs-lens/internal/meta/get.go index d6bc1bbcd0..6edb7d947e 100644 --- a/cmd/neofs-lens/internal/meta/get.go +++ b/cmd/neofs-lens/internal/meta/get.go @@ -16,7 +16,7 @@ var getCMD = &cobra.Command{ Short: "Object inspection", Long: `Get specific object from a metabase.`, Args: cobra.NoArgs, - Run: getFunc, + RunE: getFunc, } func init() { @@ -24,20 +24,27 @@ func init() { common.AddComponentPathFlag(getCMD, &vPath) } -func getFunc(cmd *cobra.Command, _ []string) { +func getFunc(cmd *cobra.Command, _ []string) error { var addr oid.Address err := addr.DecodeString(vAddress) - common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) + if err != nil { + return common.Errf("invalid address argument: %w", err) + } - db := openMeta(cmd, true) + db, err := openMeta(true) + if err != nil { + return err + } defer db.Close() storageID := meta.StorageIDPrm{} storageID.SetAddress(addr) resStorageID, err := db.StorageID(storageID) - common.ExitOnErr(cmd, common.Errf("could not check if the obj is small: %w", err)) + if err != nil { + return common.Errf("could not check if the obj is small: %w", err) + } if id := resStorageID.StorageID(); id != nil { cmd.Printf("Object storageID: %x (%q)\n\n", id, id) @@ -66,9 +73,13 @@ func getFunc(cmd *cobra.Command, _ []string) { cmd.Println("\tLast:", last) } - return + return nil + } + if err != nil { + return common.Errf("could not get object: %w", err) } - common.ExitOnErr(cmd, common.Errf("could not get object: %w", err)) common.PrintObjectHeader(cmd, *res.Header()) + + return nil } diff --git a/cmd/neofs-lens/internal/meta/id.go b/cmd/neofs-lens/internal/meta/id.go index ef6c3fb868..28e17f0602 100644 --- a/cmd/neofs-lens/internal/meta/id.go +++ b/cmd/neofs-lens/internal/meta/id.go @@ -10,19 +10,26 @@ var idCMD = &cobra.Command{ Use: "id", Short: "Read shard ID the metabase is attached to", Args: cobra.NoArgs, - Run: idFunc, + RunE: idFunc, } func init() { common.AddComponentPathFlag(idCMD, &vPath) } -func idFunc(cmd *cobra.Command, _ []string) { - db := openMeta(cmd, true) +func idFunc(cmd *cobra.Command, _ []string) error { + db, err := openMeta(true) + if err != nil { + return err + } defer db.Close() idRaw, err := db.ReadShardID() - common.ExitOnErr(cmd, common.Errf("metabase's `ReadShardID`: %w", err)) + if err != nil { + return common.Errf("metabase's `ReadShardID`: %w", err) + } cmd.Println(base58.Encode(idRaw)) + + return nil } diff --git a/cmd/neofs-lens/internal/meta/list-garbage.go b/cmd/neofs-lens/internal/meta/list-garbage.go index d2e4dffc73..94228c2080 100644 --- a/cmd/neofs-lens/internal/meta/list-garbage.go +++ b/cmd/neofs-lens/internal/meta/list-garbage.go @@ -11,15 +11,18 @@ var listGarbageCMD = &cobra.Command{ Short: "Garbage listing", Long: `List all the objects that have received GC Mark.`, Args: cobra.NoArgs, - Run: listGarbageFunc, + RunE: listGarbageFunc, } func init() { common.AddComponentPathFlag(listGarbageCMD, &vPath) } -func listGarbageFunc(cmd *cobra.Command, _ []string) { - db := openMeta(cmd, true) +func listGarbageFunc(cmd *cobra.Command, _ []string) error { + db, err := openMeta(true) + if err != nil { + return err + } defer db.Close() var garbPrm meta.GarbageIterationPrm @@ -29,6 +32,10 @@ func listGarbageFunc(cmd *cobra.Command, _ []string) { return nil }) - err := db.IterateOverGarbage(garbPrm) - common.ExitOnErr(cmd, common.Errf("could not iterate over garbage bucket: %w", err)) + err = db.IterateOverGarbage(garbPrm) + if err != nil { + return common.Errf("could not iterate over garbage bucket: %w", err) + } + + return nil } diff --git a/cmd/neofs-lens/internal/meta/list-graveyard.go b/cmd/neofs-lens/internal/meta/list-graveyard.go index 09457dfb3f..1ffc3b90d4 100644 --- a/cmd/neofs-lens/internal/meta/list-graveyard.go +++ b/cmd/neofs-lens/internal/meta/list-graveyard.go @@ -11,15 +11,18 @@ var listGraveyardCMD = &cobra.Command{ Short: "Graveyard listing", Long: `List all the objects that have been covered with a Tomb Stone.`, Args: cobra.NoArgs, - Run: listGraveyardFunc, + RunE: listGraveyardFunc, } func init() { common.AddComponentPathFlag(listGraveyardCMD, &vPath) } -func listGraveyardFunc(cmd *cobra.Command, _ []string) { - db := openMeta(cmd, true) +func listGraveyardFunc(cmd *cobra.Command, _ []string) error { + db, err := openMeta(true) + if err != nil { + return err + } defer db.Close() var gravePrm meta.GraveyardIterationPrm @@ -34,6 +37,10 @@ func listGraveyardFunc(cmd *cobra.Command, _ []string) { return nil }) - err := db.IterateOverGraveyard(gravePrm) - common.ExitOnErr(cmd, common.Errf("could not iterate over graveyard bucket: %w", err)) + err = db.IterateOverGraveyard(gravePrm) + if err != nil { + return common.Errf("could not iterate over graveyard bucket: %w", err) + } + + return nil } diff --git a/cmd/neofs-lens/internal/meta/list.go b/cmd/neofs-lens/internal/meta/list.go index eddc5c176a..81aaa9c2a4 100644 --- a/cmd/neofs-lens/internal/meta/list.go +++ b/cmd/neofs-lens/internal/meta/list.go @@ -12,7 +12,7 @@ var listCMD = &cobra.Command{ Use: "list", Short: "List objects in metabase (metabase's List method)", Args: cobra.NoArgs, - Run: listFunc, + RunE: listFunc, } var vLimit uint32 @@ -29,21 +29,28 @@ func init() { common.AddComponentPathFlag(listCMD, &vPath) } -func listFunc(cmd *cobra.Command, _ []string) { - db := openMeta(cmd, true) +func listFunc(cmd *cobra.Command, _ []string) error { + db, err := openMeta(true) + if err != nil { + return err + } defer db.Close() if vLimit == 0 { - common.ExitOnErr(cmd, fmt.Errorf("%s flag must be positive", limitFlagName)) + return fmt.Errorf("%s flag must be positive", limitFlagName) } var prm meta.ListPrm prm.SetCount(vLimit) res, err := db.ListWithCursor(prm) - common.ExitOnErr(cmd, common.Errf("metabase's `ListWithCursor`: %w", err)) + if err != nil { + return common.Errf("metabase's `ListWithCursor`: %w", err) + } for _, addressWithType := range res.AddressList() { cmd.Printf("%s, Type: %s\n", addressWithType.Address, addressWithType.Type) } + + return nil } diff --git a/cmd/neofs-lens/internal/meta/put.go b/cmd/neofs-lens/internal/meta/put.go index 1d3ac55254..f0496e218e 100644 --- a/cmd/neofs-lens/internal/meta/put.go +++ b/cmd/neofs-lens/internal/meta/put.go @@ -15,7 +15,7 @@ var writeObjectCMD = &cobra.Command{ Short: "Put object to metabase", Long: "Put object from file to metabase", Args: cobra.NoArgs, - Run: writeObject, + RunE: writeObject, } func init() { @@ -23,35 +23,48 @@ func init() { common.AddInputPathFile(writeObjectCMD, &vInputObj) } -func writeObject(cmd *cobra.Command, _ []string) { - db := openMeta(cmd, false) +func writeObject(cmd *cobra.Command, _ []string) error { + db, err := openMeta(false) + if err != nil { + return err + } defer db.Close() - err := db.Init() - common.ExitOnErr(cmd, common.Errf("can't init metabase: %w", err)) + err = db.Init() + if err != nil { + return common.Errf("can't init metabase: %w", err) + } buf, err := os.ReadFile(vInputObj) - common.ExitOnErr(cmd, common.Errf("unable to read given file: %w", err)) + if err != nil { + return common.Errf("unable to read given file: %w", err) + } obj := object.New() - common.ExitOnErr(cmd, common.Errf("can't unmarshal object from given file: %w", obj.Unmarshal(buf))) + if err := obj.Unmarshal(buf); err != nil { + return common.Errf("can't unmarshal object from given file: %w", err) + } id, ok := obj.ID() if !ok { - common.ExitOnErr(cmd, errors.New("missing ID in object")) + return errors.New("missing ID in object") } cnr, ok := obj.ContainerID() if !ok { - common.ExitOnErr(cmd, errors.New("missing container ID in object")) + return errors.New("missing container ID in object") } var pPrm meta.PutPrm pPrm.SetObject(obj) _, err = db.Put(pPrm) - common.ExitOnErr(cmd, common.Errf("can't put object: %w", err)) + if err != nil { + return common.Errf("can't put object: %w", err) + } cmd.Printf("[%s] Object successfully stored\n", vInputObj) cmd.Printf(" OID: %s\n CID: %s\n", id, cnr) + + return nil } diff --git a/cmd/neofs-lens/internal/meta/root.go b/cmd/neofs-lens/internal/meta/root.go index 79f575bb66..a7ef3f725f 100644 --- a/cmd/neofs-lens/internal/meta/root.go +++ b/cmd/neofs-lens/internal/meta/root.go @@ -39,9 +39,11 @@ func init() { ) } -func openMeta(cmd *cobra.Command, readOnly bool) *meta.DB { +func openMeta(readOnly bool) (*meta.DB, error) { _, err := os.Stat(vPath) - common.ExitOnErr(cmd, err) + if err != nil { + return nil, err + } db := meta.New( meta.WithPath(vPath), @@ -51,7 +53,9 @@ func openMeta(cmd *cobra.Command, readOnly bool) *meta.DB { }), meta.WithEpochState(epochState{}), ) - common.ExitOnErr(cmd, common.Errf("could not open metabase: %w", db.Open(readOnly))) + if err := db.Open(readOnly); err != nil { + return nil, common.Errf("could not open metabase: %w", err) + } - return db + return db, nil } diff --git a/cmd/neofs-lens/internal/meta/status.go b/cmd/neofs-lens/internal/meta/status.go index 2da737cadb..3b91eddd53 100644 --- a/cmd/neofs-lens/internal/meta/status.go +++ b/cmd/neofs-lens/internal/meta/status.go @@ -13,7 +13,7 @@ var statCMD = &cobra.Command{ Short: "Object status information", Long: `Get metabase's indexes related to an object.`, Args: cobra.NoArgs, - Run: statusFunc, + RunE: statusFunc, } func init() { @@ -21,17 +21,25 @@ func init() { common.AddComponentPathFlag(statCMD, &vPath) } -func statusFunc(cmd *cobra.Command, _ []string) { +func statusFunc(cmd *cobra.Command, _ []string) error { var addr oid.Address err := addr.DecodeString(vAddress) - common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) + if err != nil { + return common.Errf("invalid address argument: %w", err) + } + + db, err := openMeta(true) + if err != nil { + return err + } - db := openMeta(cmd, true) defer db.Close() res, err := db.ObjectStatus(addr) - common.ExitOnErr(cmd, common.Errf("reading object status: %w", err)) + if err != nil { + return common.Errf("reading object status: %w", err) + } const emptyValPlaceholder = "" storageID := res.StorageID @@ -52,4 +60,6 @@ func statusFunc(cmd *cobra.Command, _ []string) { cmd.Printf("\tBucket: %d\n"+ "\tValue (HEX): %s\n", bucket.BucketIndex, valStr) } + + return nil } diff --git a/cmd/neofs-lens/internal/object/link.go b/cmd/neofs-lens/internal/object/link.go index ec8f8297e4..d2ae69705c 100644 --- a/cmd/neofs-lens/internal/object/link.go +++ b/cmd/neofs-lens/internal/object/link.go @@ -14,16 +14,18 @@ var linkCMD = &cobra.Command{ Use: "link", Short: "Inspect link object", Args: cobra.NoArgs, - Run: linkFunc, + RunE: linkFunc, } -func linkFunc(cmd *cobra.Command, _ []string) { +func linkFunc(cmd *cobra.Command, _ []string) error { if vPath == "" { - common.ExitOnErr(cmd, errors.New("empty path to file")) + return errors.New("empty path to file") } raw, err := os.ReadFile(vPath) - common.ExitOnErr(cmd, common.Errf("reading file: %w", err)) + if err != nil { + return common.Errf("reading file: %w", err) + } var link object.Link err = link.Unmarshal(raw) @@ -32,18 +34,22 @@ func linkFunc(cmd *cobra.Command, _ []string) { var obj object.Object err = obj.Unmarshal(raw) - common.ExitOnErr(cmd, common.Errf("decoding NeoFS object: %w", err)) + if err != nil { + return common.Errf("decoding NeoFS object: %w", err) + } if typeGot := obj.Type(); typeGot != object.TypeLink { - common.ExitOnErr(cmd, fmt.Errorf("unexpected object type (not %s): %s", object.TypeLink, typeGot)) + return fmt.Errorf("unexpected object type (not %s): %s", object.TypeLink, typeGot) } err = obj.ReadLink(&link) } - common.ExitOnErr(cmd, common.Errf("decoding link object: %w", err)) + if err != nil { + return common.Errf("decoding link object: %w", err) + } if len(link.Objects()) == 0 { - common.ExitOnErr(cmd, errors.New("empty children list")) + return errors.New("empty children list") } cmd.Println("Children (sorted according to the read payload):") @@ -51,4 +57,6 @@ func linkFunc(cmd *cobra.Command, _ []string) { for _, measuredObject := range link.Objects() { cmd.Printf("Size: %d, object ID: %s\n", measuredObject.ObjectSize(), measuredObject.ObjectID()) } + + return nil } diff --git a/cmd/neofs-lens/internal/peapod/get.go b/cmd/neofs-lens/internal/peapod/get.go index 5fdd5edcec..0522cb9440 100644 --- a/cmd/neofs-lens/internal/peapod/get.go +++ b/cmd/neofs-lens/internal/peapod/get.go @@ -11,7 +11,7 @@ var getCMD = &cobra.Command{ Short: "Get object", Long: `Get specific object from a Peapod.`, Args: cobra.NoArgs, - Run: getFunc, + RunE: getFunc, } func init() { @@ -21,22 +21,35 @@ func init() { common.AddPayloadOnlyFlag(getCMD, &vPayloadOnly) } -func getFunc(cmd *cobra.Command, _ []string) { +func getFunc(cmd *cobra.Command, _ []string) error { var getPrm blobstorcommon.GetPrm err := getPrm.Address.DecodeString(vAddress) - common.ExitOnErr(cmd, common.Errf("failed to decode object address: %w", err)) + if err != nil { + return common.Errf("failed to decode object address: %w", err) + } - ppd := openPeapod(cmd) + ppd, err := openPeapod() + if err != nil { + return err + } defer ppd.Close() res, err := ppd.Get(getPrm) - common.ExitOnErr(cmd, common.Errf("failed to read object from Peapod: %w", err)) + if err != nil { + return common.Errf("failed to read object from Peapod: %w", err) + } common.PrintObjectHeader(cmd, *res.Object) if vPayloadOnly { - common.WriteObjectToFile(cmd, vOut, res.RawData, true) - return + if err := common.WriteObjectToFile(cmd, vOut, res.RawData, true); err != nil { + return err + } + return nil } - common.WriteObjectToFile(cmd, vOut, res.RawData, false) + if err := common.WriteObjectToFile(cmd, vOut, res.RawData, false); err != nil { + return err + } + + return nil } diff --git a/cmd/neofs-lens/internal/peapod/list.go b/cmd/neofs-lens/internal/peapod/list.go index 95f95203e5..f4ad6354e7 100644 --- a/cmd/neofs-lens/internal/peapod/list.go +++ b/cmd/neofs-lens/internal/peapod/list.go @@ -14,14 +14,14 @@ var listCMD = &cobra.Command{ Short: "Object listing", Long: `List all objects stored in a Peapod.`, Args: cobra.NoArgs, - Run: listFunc, + RunE: listFunc, } func init() { common.AddComponentPathFlag(listCMD, &vPath) } -func listFunc(cmd *cobra.Command, _ []string) { +func listFunc(cmd *cobra.Command, _ []string) error { // other targets can be supported w := cmd.OutOrStderr() @@ -30,9 +30,15 @@ func listFunc(cmd *cobra.Command, _ []string) { return err } - ppd := openPeapod(cmd) + ppd, err := openPeapod() + if err != nil { + return err + } defer ppd.Close() - err := ppd.IterateAddresses(wAddr) - common.ExitOnErr(cmd, common.Errf("Peapod iterator failure: %w", err)) + err = ppd.IterateAddresses(wAddr) + if err != nil { + return common.Errf("Peapod iterator failure: %w", err) + } + return nil } diff --git a/cmd/neofs-lens/internal/peapod/root.go b/cmd/neofs-lens/internal/peapod/root.go index 50cf84da50..36fd60339d 100644 --- a/cmd/neofs-lens/internal/peapod/root.go +++ b/cmd/neofs-lens/internal/peapod/root.go @@ -26,18 +26,22 @@ func init() { } // open and returns read-only peapod.Peapod located in vPath. -func openPeapod(cmd *cobra.Command) *peapod.Peapod { +func openPeapod() (*peapod.Peapod, error) { // interval prm doesn't matter for read-only usage, but must be positive ppd := peapod.New(vPath, 0400, 1) var compressCfg compression.Config err := compressCfg.Init() - common.ExitOnErr(cmd, common.Errf("failed to init compression config: %w", err)) + if err != nil { + return nil, common.Errf("failed to init compression config: %w", err) + } ppd.SetCompressor(&compressCfg) err = ppd.Open(true) - common.ExitOnErr(cmd, common.Errf("failed to open Peapod: %w", err)) + if err != nil { + return nil, common.Errf("failed to open Peapod: %w", err) + } - return ppd + return ppd, nil } diff --git a/cmd/neofs-lens/internal/printers.go b/cmd/neofs-lens/internal/printers.go index 2d41e04bbc..ca8aa41568 100644 --- a/cmd/neofs-lens/internal/printers.go +++ b/cmd/neofs-lens/internal/printers.go @@ -55,19 +55,22 @@ func printObjectID(cmd *cobra.Command, recv func() (oid.ID, bool)) { // WriteObjectToFile writes object to the provided path. Does nothing if // the path is empty. -func WriteObjectToFile(cmd *cobra.Command, path string, data []byte, payloadOnly bool) { +func WriteObjectToFile(cmd *cobra.Command, path string, data []byte, payloadOnly bool) error { if path == "" { - return + return nil } - ExitOnErr(cmd, Errf("could not write file: %w", - os.WriteFile(path, data, 0o644))) + if err := os.WriteFile(path, data, 0o644); err != nil { + return Errf("could not write file: %w", err) + } if payloadOnly { cmd.Printf("\nSaved payload to '%s' file\n", path) - return + return nil } cmd.Printf("\nSaved object to '%s' file\n", path) + + return nil } // PrintStorageObjectStatus prints object status. diff --git a/cmd/neofs-lens/internal/storage/get.go b/cmd/neofs-lens/internal/storage/get.go index 310bb58bb4..4ef27d1ff4 100644 --- a/cmd/neofs-lens/internal/storage/get.go +++ b/cmd/neofs-lens/internal/storage/get.go @@ -12,7 +12,7 @@ var storageGetObjCMD = &cobra.Command{ Short: "Get object from the NeoFS node's storage snapshot", Long: "Get object from the NeoFS node's storage snapshot", Args: cobra.NoArgs, - Run: getFunc, + RunE: getFunc, } func init() { @@ -22,23 +22,36 @@ func init() { common.AddPayloadOnlyFlag(storageGetObjCMD, &vPayloadOnly) } -func getFunc(cmd *cobra.Command, _ []string) { +func getFunc(cmd *cobra.Command, _ []string) error { var addr oid.Address err := addr.DecodeString(vAddress) - common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) + if err != nil { + return common.Errf("invalid address argument: %w", err) + } - storage := openEngine(cmd) + storage, err := openEngine() + if err != nil { + return err + } defer storage.Close() obj, err := engine.Get(storage, addr) - common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) + if err != nil { + return common.Errf("could not fetch object: %w", err) + } common.PrintObjectHeader(cmd, *obj) if vPayloadOnly { - common.WriteObjectToFile(cmd, vOut, obj.Payload(), true) - return + if err := common.WriteObjectToFile(cmd, vOut, obj.Payload(), true); err != nil { + return err + } + return nil } data := obj.Marshal() - common.WriteObjectToFile(cmd, vOut, data, false) + if err := common.WriteObjectToFile(cmd, vOut, data, false); err != nil { + return err + } + + return nil } diff --git a/cmd/neofs-lens/internal/storage/list.go b/cmd/neofs-lens/internal/storage/list.go index 47bf7f47f1..78a6eda6e1 100644 --- a/cmd/neofs-lens/internal/storage/list.go +++ b/cmd/neofs-lens/internal/storage/list.go @@ -14,18 +14,21 @@ var storageListObjsCMD = &cobra.Command{ Short: "Object listing", Long: `List all objects stored in a blobstor (as registered in metabase).`, Args: cobra.NoArgs, - Run: listFunc, + RunE: listFunc, } func init() { common.AddConfigFileFlag(storageListObjsCMD, &vConfig) } -func listFunc(cmd *cobra.Command, _ []string) { +func listFunc(cmd *cobra.Command, _ []string) error { // other targets can be supported w := cmd.OutOrStderr() - storage := openEngine(cmd) + storage, err := openEngine() + if err != nil { + return err + } defer storage.Close() var p engine.ListWithCursorPrm @@ -34,14 +37,18 @@ func listFunc(cmd *cobra.Command, _ []string) { r, err := storage.ListWithCursor(p) if err != nil { if errors.Is(err, engine.ErrEndOfListing) { - return + return nil + } + if err != nil { + return common.Errf("Storage iterator failure: %w", err) } - common.ExitOnErr(cmd, common.Errf("Storage iterator failure: %w", err)) } var addrs = r.AddressList() for _, at := range addrs { _, err = io.WriteString(w, at.Address.String()+"\n") - common.ExitOnErr(cmd, common.Errf("print failure: %w", err)) + if err != nil { + return common.Errf("print failure: %w", err) + } } p.WithCursor(r.Cursor()) } diff --git a/cmd/neofs-lens/internal/storage/root.go b/cmd/neofs-lens/internal/storage/root.go index 8101cc99b2..d72fe61c9f 100644 --- a/cmd/neofs-lens/internal/storage/root.go +++ b/cmd/neofs-lens/internal/storage/root.go @@ -4,7 +4,6 @@ import ( "fmt" "time" - common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config" engineconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine" shardconfig "github.com/nspcc-dev/neofs-node/cmd/neofs-node/config/engine/shard" @@ -60,7 +59,7 @@ func (e epochState) CurrentEpoch() uint64 { return 0 } -func openEngine(cmd *cobra.Command) *engine.StorageEngine { +func openEngine() (*engine.StorageEngine, error) { appCfg := config.New(config.Prm{}, config.WithConfigFile(vConfig)) ls := engine.New() @@ -157,7 +156,9 @@ func openEngine(cmd *cobra.Command) *engine.StorageEngine { return nil }) - common.ExitOnErr(cmd, err) + if err != nil { + return nil, err + } var shardsWithMeta []shardOptsWithID for _, shCfg := range shards { @@ -244,23 +245,33 @@ func openEngine(cmd *cobra.Command) *engine.StorageEngine { shard.WithRemoverBatchSize(shCfg.GcCfg.RemoverBatchSize), shard.WithGCRemoverSleepInterval(shCfg.GcCfg.RemoverSleepInterval), shard.WithGCWorkerPoolInitializer(func(sz int) util.WorkerPool { - pool, err := ants.NewPool(sz) - common.ExitOnErr(cmd, err) - + pool, poolErr := ants.NewPool(sz) + if poolErr != nil { + err = poolErr + } return pool }), } + if err != nil { + return nil, err + } shardsWithMeta = append(shardsWithMeta, sh) } for _, optsWithMeta := range shardsWithMeta { _, err := ls.AddShard(append(optsWithMeta.shOpts, shard.WithMode(mode.ReadOnly))...) - common.ExitOnErr(cmd, err) + if err != nil { + return nil, err + } } - common.ExitOnErr(cmd, ls.Open()) - common.ExitOnErr(cmd, ls.Init()) + if err := ls.Open(); err != nil { + return nil, err + } + if err := ls.Init(); err != nil { + return nil, err + } - return ls + return ls, nil } diff --git a/cmd/neofs-lens/internal/storage/sanity.go b/cmd/neofs-lens/internal/storage/sanity.go index 3209fecbd7..bde8f13847 100644 --- a/cmd/neofs-lens/internal/storage/sanity.go +++ b/cmd/neofs-lens/internal/storage/sanity.go @@ -31,7 +31,7 @@ var storageSanityCMD = &cobra.Command{ Use: "sanity", Short: "Check consistency of stored objects", Args: cobra.NoArgs, - Run: sanityCheck, + RunE: sanityCheck, } func init() { @@ -44,7 +44,7 @@ type storageShard struct { p *peapod.Peapod } -func sanityCheck(cmd *cobra.Command, _ []string) { +func sanityCheck(cmd *cobra.Command, _ []string) error { var shards []storageShard defer func() { for _, sh := range shards { @@ -80,7 +80,9 @@ func sanityCheck(cmd *cobra.Command, _ []string) { var compressCfg compression.Config err := compressCfg.Init() - common.ExitOnErr(cmd, common.Errf("failed to init compression config: %w", err)) + if err != nil { + return common.Errf("failed to init compression config: %w", err) + } sh.p.SetCompressor(&compressCfg) case fstree.Type: @@ -94,22 +96,38 @@ func sanityCheck(cmd *cobra.Command, _ []string) { } } - common.ExitOnErr(cmd, common.Errf("open metabase: %w", sh.m.Open(true))) - common.ExitOnErr(cmd, common.Errf("open peapod: %w", sh.p.Open(true))) - common.ExitOnErr(cmd, common.Errf("open fstree: %w", sh.fsT.Open(true))) + if err := sh.m.Open(true); err != nil { + return common.Errf("open metabase: %w", err) + } + if err := sh.p.Open(true); err != nil { + return common.Errf("open peapod: %w", err) + } + if err := sh.fsT.Open(true); err != nil { + return common.Errf("open fstree: %w", err) + } // metabase.Open(true) does not set it mode to RO somehow - common.ExitOnErr(cmd, common.Errf("moving metabase in readonly mode", sh.m.SetMode(mode.ReadOnly))) + if err := sh.m.SetMode(mode.ReadOnly); err != nil { + return common.Errf("moving metabase in readonly mode", err) + } - common.ExitOnErr(cmd, common.Errf("init metabase: %w", sh.m.Init())) - common.ExitOnErr(cmd, common.Errf("init peapod: %w", sh.p.Init())) - common.ExitOnErr(cmd, common.Errf("init fstree: %w", sh.fsT.Init())) + if err := sh.m.Init(); err != nil { + return common.Errf("init metabase: %w", err) + } + if err := sh.p.Init(); err != nil { + return common.Errf("init peapod: %w", err) + } + if err := sh.fsT.Init(); err != nil { + return common.Errf("init fstree: %w", err) + } shards = append(shards, sh) return nil }) - common.ExitOnErr(cmd, common.Errf("reading config: %w", err)) + if err != nil { + return common.Errf("reading config: %w", err) + } for _, sh := range shards { idRaw, err := sh.m.ReadShardID() @@ -124,7 +142,7 @@ func sanityCheck(cmd *cobra.Command, _ []string) { objsChecked, err := checkShard(cmd, sh) if err != nil { if errors.Is(err, context.Canceled) { - return + return nil } cmd.Printf("%d objects checked in %s shard, interrupted by error: %s\n", objsChecked, id, err) @@ -133,6 +151,8 @@ func sanityCheck(cmd *cobra.Command, _ []string) { cmd.Printf("Checked objects in %s shard: %d", id, objsChecked) } + + return nil } func checkShard(cmd *cobra.Command, sh storageShard) (int, error) { diff --git a/cmd/neofs-lens/internal/storage/status.go b/cmd/neofs-lens/internal/storage/status.go index cf5fb06abe..0419708167 100644 --- a/cmd/neofs-lens/internal/storage/status.go +++ b/cmd/neofs-lens/internal/storage/status.go @@ -11,7 +11,7 @@ var storageStatusObjCMD = &cobra.Command{ Short: "Get object from the NeoFS node's storage snapshot", Long: "Get object from the NeoFS node's storage snapshot", Args: cobra.NoArgs, - Run: statusObject, + RunE: statusObject, } func init() { @@ -19,16 +19,24 @@ func init() { common.AddConfigFileFlag(storageStatusObjCMD, &vConfig) } -func statusObject(cmd *cobra.Command, _ []string) { +func statusObject(cmd *cobra.Command, _ []string) error { var addr oid.Address err := addr.DecodeString(vAddress) - common.ExitOnErr(cmd, common.Errf("invalid address argument: %w", err)) + if err != nil { + return common.Errf("invalid address argument: %w", err) + } - storage := openEngine(cmd) + storage, err := openEngine() + if err != nil { + return err + } defer storage.Close() status, err := storage.ObjectStatus(addr) - common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) + if err != nil { + return common.Errf("could not fetch object: %w", err) + } common.PrintStorageObjectStatus(cmd, status) + return nil } diff --git a/cmd/neofs-lens/internal/writecache/get.go b/cmd/neofs-lens/internal/writecache/get.go index 0c125efe41..e15833c16b 100644 --- a/cmd/neofs-lens/internal/writecache/get.go +++ b/cmd/neofs-lens/internal/writecache/get.go @@ -12,7 +12,7 @@ var getCMD = &cobra.Command{ Short: "Object inspection", Long: `Get specific object from a write-cache.`, Args: cobra.NoArgs, - Run: getFunc, + RunE: getFunc, } func init() { @@ -22,20 +22,33 @@ func init() { common.AddPayloadOnlyFlag(getCMD, &vPayloadOnly) } -func getFunc(cmd *cobra.Command, _ []string) { - db := openWC(cmd) +func getFunc(cmd *cobra.Command, _ []string) error { + db, err := openWC() + if err != nil { + return err + } defer db.Close() data, err := writecache.Get(db, []byte(vAddress)) - common.ExitOnErr(cmd, common.Errf("could not fetch object: %w", err)) + if err != nil { + return common.Errf("could not fetch object: %w", err) + } var o object.Object - common.ExitOnErr(cmd, common.Errf("could not unmarshal object: %w", o.Unmarshal(data))) + if err := o.Unmarshal(data); err != nil { + return common.Errf("could not unmarshal object: %w", err) + } common.PrintObjectHeader(cmd, o) if vPayloadOnly { - common.WriteObjectToFile(cmd, vOut, data, true) - return + if err := common.WriteObjectToFile(cmd, vOut, data, true); err != nil { + return err + } + return nil } - common.WriteObjectToFile(cmd, vOut, data, false) + if err := common.WriteObjectToFile(cmd, vOut, data, false); err != nil { + return err + } + + return nil } diff --git a/cmd/neofs-lens/internal/writecache/list.go b/cmd/neofs-lens/internal/writecache/list.go index 9d92cebe28..464c4b592a 100644 --- a/cmd/neofs-lens/internal/writecache/list.go +++ b/cmd/neofs-lens/internal/writecache/list.go @@ -15,14 +15,14 @@ var listCMD = &cobra.Command{ Short: "Object listing", Long: `List all objects stored in a write-cache.`, Args: cobra.NoArgs, - Run: listFunc, + RunE: listFunc, } func init() { common.AddComponentPathFlag(listCMD, &vPath) } -func listFunc(cmd *cobra.Command, _ []string) { +func listFunc(cmd *cobra.Command, _ []string) error { // other targets can be supported w := cmd.OutOrStderr() @@ -31,9 +31,15 @@ func listFunc(cmd *cobra.Command, _ []string) { return err } - db := openWC(cmd) + db, err := openWC() + if err != nil { + return err + } defer db.Close() - err := writecache.IterateDB(db, wAddr) - common.ExitOnErr(cmd, common.Errf("write-cache iterator failure: %w", err)) + err = writecache.IterateDB(db, wAddr) + if err != nil { + return common.Errf("write-cache iterator failure: %w", err) + } + return nil } diff --git a/cmd/neofs-lens/internal/writecache/root.go b/cmd/neofs-lens/internal/writecache/root.go index c975f726c9..02ab03d606 100644 --- a/cmd/neofs-lens/internal/writecache/root.go +++ b/cmd/neofs-lens/internal/writecache/root.go @@ -25,9 +25,11 @@ func init() { Root.AddCommand(getCMD) } -func openWC(cmd *cobra.Command) *bbolt.DB { +func openWC() (*bbolt.DB, error) { db, err := writecache.OpenDB(vPath, true) - common.ExitOnErr(cmd, common.Errf("could not open write-cache db: %w", err)) + if err != nil { + return nil, common.Errf("could not open write-cache db: %w", err) + } - return db + return db, nil } diff --git a/cmd/neofs-lens/root.go b/cmd/neofs-lens/root.go index c0d200bf74..2627105511 100644 --- a/cmd/neofs-lens/root.go +++ b/cmd/neofs-lens/root.go @@ -3,6 +3,7 @@ package main import ( "os" + "github.com/nspcc-dev/neofs-node/cmd/internal/custom_errors" "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/meta" "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/object" "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal/peapod" @@ -14,11 +15,12 @@ import ( ) var command = &cobra.Command{ - Use: "neofs-lens", - Short: "NeoFS Storage Engine Lens", - Long: `NeoFS Storage Engine Lens provides tools to browse the contents of the NeoFS storage engine.`, - RunE: entryPoint, - SilenceUsage: true, + Use: "neofs-lens", + Short: "NeoFS Storage Engine Lens", + Long: `NeoFS Storage Engine Lens provides tools to browse the contents of the NeoFS storage engine.`, + RunE: entryPoint, + SilenceUsage: true, + SilenceErrors: true, } func entryPoint(cmd *cobra.Command, _ []string) error { @@ -48,7 +50,5 @@ func init() { func main() { err := command.Execute() - if err != nil { - os.Exit(1) - } + custom_errors.ExitOnErr(err) }