Skip to content

Commit

Permalink
cmd/neofs-lens: add error handler after execution command
Browse files Browse the repository at this point in the history
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 <andrey@nspcc.io>
  • Loading branch information
End-rey committed Sep 19, 2024
1 parent bce4dfe commit 85bf87d
Show file tree
Hide file tree
Showing 24 changed files with 322 additions and 157 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
17 changes: 0 additions & 17 deletions cmd/neofs-lens/internal/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
}
}
25 changes: 18 additions & 7 deletions cmd/neofs-lens/internal/meta/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,35 @@ var getCMD = &cobra.Command{
Short: "Object inspection",
Long: `Get specific object from a metabase.`,
Args: cobra.NoArgs,
Run: getFunc,
RunE: getFunc,
}

func init() {
common.AddAddressFlag(getCMD, &vAddress)
common.AddComponentPathFlag(getCMD, &vPath)
}

func getFunc(cmd *cobra.Command, _ []string) {
func getFunc(cmd *cobra.Command, _ []string) error {

Check warning on line 27 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L27

Added line #L27 was not covered by tests
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)

Check warning on line 32 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L31-L32

Added lines #L31 - L32 were not covered by tests
}

db := openMeta(cmd, true)
db, err := openMeta(true)
if err != nil {
return err

Check warning on line 37 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L35-L37

Added lines #L35 - L37 were not covered by tests
}
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)

Check warning on line 46 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L45-L46

Added lines #L45 - L46 were not covered by tests
}

if id := resStorageID.StorageID(); id != nil {
cmd.Printf("Object storageID: %x (%q)\n\n", id, id)
Expand Down Expand Up @@ -66,9 +73,13 @@ func getFunc(cmd *cobra.Command, _ []string) {
cmd.Println("\tLast:", last)
}

return
return nil

Check warning on line 76 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L76

Added line #L76 was not covered by tests
}
if err != nil {
return common.Errf("could not get object: %w", err)

Check warning on line 79 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L78-L79

Added lines #L78 - L79 were not covered by tests
}
common.ExitOnErr(cmd, common.Errf("could not get object: %w", err))

common.PrintObjectHeader(cmd, *res.Header())

return nil

Check warning on line 84 in cmd/neofs-lens/internal/meta/get.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/get.go#L84

Added line #L84 was not covered by tests
}
15 changes: 11 additions & 4 deletions cmd/neofs-lens/internal/meta/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check warning on line 23 in cmd/neofs-lens/internal/meta/id.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/id.go#L20-L23

Added lines #L20 - L23 were not covered by tests
}
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)

Check warning on line 29 in cmd/neofs-lens/internal/meta/id.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/id.go#L28-L29

Added lines #L28 - L29 were not covered by tests
}

cmd.Println(base58.Encode(idRaw))

return nil

Check warning on line 34 in cmd/neofs-lens/internal/meta/id.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/id.go#L34

Added line #L34 was not covered by tests
}
17 changes: 12 additions & 5 deletions cmd/neofs-lens/internal/meta/list-garbage.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check warning on line 24 in cmd/neofs-lens/internal/meta/list-garbage.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-garbage.go#L21-L24

Added lines #L21 - L24 were not covered by tests
}
defer db.Close()

var garbPrm meta.GarbageIterationPrm
Expand All @@ -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)

Check warning on line 37 in cmd/neofs-lens/internal/meta/list-garbage.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-garbage.go#L35-L37

Added lines #L35 - L37 were not covered by tests
}

return nil

Check warning on line 40 in cmd/neofs-lens/internal/meta/list-garbage.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-garbage.go#L40

Added line #L40 was not covered by tests
}
17 changes: 12 additions & 5 deletions cmd/neofs-lens/internal/meta/list-graveyard.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check warning on line 24 in cmd/neofs-lens/internal/meta/list-graveyard.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-graveyard.go#L21-L24

Added lines #L21 - L24 were not covered by tests
}
defer db.Close()

var gravePrm meta.GraveyardIterationPrm
Expand All @@ -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)

Check warning on line 42 in cmd/neofs-lens/internal/meta/list-graveyard.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-graveyard.go#L40-L42

Added lines #L40 - L42 were not covered by tests
}

return nil

Check warning on line 45 in cmd/neofs-lens/internal/meta/list-graveyard.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list-graveyard.go#L45

Added line #L45 was not covered by tests
}
17 changes: 12 additions & 5 deletions cmd/neofs-lens/internal/meta/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Check warning on line 35 in cmd/neofs-lens/internal/meta/list.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list.go#L32-L35

Added lines #L32 - L35 were not covered by tests
}
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)

Check warning on line 40 in cmd/neofs-lens/internal/meta/list.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list.go#L40

Added line #L40 was not covered by tests
}

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)

Check warning on line 48 in cmd/neofs-lens/internal/meta/list.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list.go#L47-L48

Added lines #L47 - L48 were not covered by tests
}

for _, addressWithType := range res.AddressList() {
cmd.Printf("%s, Type: %s\n", addressWithType.Address, addressWithType.Type)
}

return nil

Check warning on line 55 in cmd/neofs-lens/internal/meta/list.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/list.go#L55

Added line #L55 was not covered by tests
}
33 changes: 23 additions & 10 deletions cmd/neofs-lens/internal/meta/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,56 @@ 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() {
common.AddComponentPathFlag(writeObjectCMD, &vPath)
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

Check warning on line 29 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L26-L29

Added lines #L26 - L29 were not covered by tests
}
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)

Check warning on line 35 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L33-L35

Added lines #L33 - L35 were not covered by tests
}

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)

Check warning on line 40 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L39-L40

Added lines #L39 - L40 were not covered by tests
}

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)

Check warning on line 45 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L44-L45

Added lines #L44 - L45 were not covered by tests
}

id, ok := obj.ID()
if !ok {
common.ExitOnErr(cmd, errors.New("missing ID in object"))
return errors.New("missing ID in object")

Check warning on line 50 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L50

Added line #L50 was not covered by tests
}

cnr, ok := obj.ContainerID()
if !ok {
common.ExitOnErr(cmd, errors.New("missing container ID in object"))
return errors.New("missing container ID in object")

Check warning on line 55 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L55

Added line #L55 was not covered by tests
}

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)

Check warning on line 63 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L62-L63

Added lines #L62 - L63 were not covered by tests
}

cmd.Printf("[%s] Object successfully stored\n", vInputObj)
cmd.Printf(" OID: %s\n CID: %s\n", id, cnr)

return nil

Check warning on line 69 in cmd/neofs-lens/internal/meta/put.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/put.go#L69

Added line #L69 was not covered by tests
}
12 changes: 8 additions & 4 deletions cmd/neofs-lens/internal/meta/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@ func init() {
)
}

func openMeta(cmd *cobra.Command, readOnly bool) *meta.DB {
func openMeta(readOnly bool) (*meta.DB, error) {

Check warning on line 42 in cmd/neofs-lens/internal/meta/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/root.go#L42

Added line #L42 was not covered by tests
_, err := os.Stat(vPath)
common.ExitOnErr(cmd, err)
if err != nil {
return nil, err

Check warning on line 45 in cmd/neofs-lens/internal/meta/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/root.go#L44-L45

Added lines #L44 - L45 were not covered by tests
}

db := meta.New(
meta.WithPath(vPath),
Expand All @@ -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)

Check warning on line 57 in cmd/neofs-lens/internal/meta/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/root.go#L56-L57

Added lines #L56 - L57 were not covered by tests
}

return db
return db, nil

Check warning on line 60 in cmd/neofs-lens/internal/meta/root.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/root.go#L60

Added line #L60 was not covered by tests
}
20 changes: 15 additions & 5 deletions cmd/neofs-lens/internal/meta/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,33 @@ 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() {
common.AddAddressFlag(statCMD, &vAddress)
common.AddComponentPathFlag(statCMD, &vPath)
}

func statusFunc(cmd *cobra.Command, _ []string) {
func statusFunc(cmd *cobra.Command, _ []string) error {

Check warning on line 24 in cmd/neofs-lens/internal/meta/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/status.go#L24

Added line #L24 was not covered by tests
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)

Check warning on line 29 in cmd/neofs-lens/internal/meta/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/status.go#L28-L29

Added lines #L28 - L29 were not covered by tests
}

db, err := openMeta(true)
if err != nil {
return err

Check warning on line 34 in cmd/neofs-lens/internal/meta/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/status.go#L32-L34

Added lines #L32 - L34 were not covered by tests
}

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)

Check warning on line 41 in cmd/neofs-lens/internal/meta/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/status.go#L40-L41

Added lines #L40 - L41 were not covered by tests
}

const emptyValPlaceholder = "<empty>"
storageID := res.StorageID
Expand All @@ -52,4 +60,6 @@ func statusFunc(cmd *cobra.Command, _ []string) {
cmd.Printf("\tBucket: %d\n"+
"\tValue (HEX): %s\n", bucket.BucketIndex, valStr)
}

return nil

Check warning on line 64 in cmd/neofs-lens/internal/meta/status.go

View check run for this annotation

Codecov / codecov/patch

cmd/neofs-lens/internal/meta/status.go#L64

Added line #L64 was not covered by tests
}
Loading

0 comments on commit 85bf87d

Please sign in to comment.