From 553983432877a459888b6f551329956780c3c4b4 Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Wed, 18 Sep 2024 17:17:05 +0300 Subject: [PATCH 1/5] cmd: add custom error and exit func from program For all cobra-based programs add custom error with code and cause of error and exit func from programs. Refs #2890. Signed-off-by: Andrey Butusov --- cmd/internal/cmderr/errors.go | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 cmd/internal/cmderr/errors.go diff --git a/cmd/internal/cmderr/errors.go b/cmd/internal/cmderr/errors.go new file mode 100644 index 0000000000..61effc54ff --- /dev/null +++ b/cmd/internal/cmderr/errors.go @@ -0,0 +1,28 @@ +package cmderr + +import ( + "errors" + "fmt" + "os" +) + +// ExitErr specific error for ExitOnErr function that passes the exit code and error caused. +type ExitErr struct { + Code int + Cause error +} + +func (x ExitErr) Error() string { return x.Cause.Error() } + +// ExitOnErr writes error to os.Stderr and calls os.Exit with passed exit code or by default 1. +// Does nothing if err is nil. +func ExitOnErr(err error) { + if err != nil { + var e ExitErr + if !errors.As(err, &e) { + e.Code = 1 + } + fmt.Fprintln(os.Stderr, err) + os.Exit(e.Code) + } +} From bbc433de78bd85c89ca9b0c7e32424d6a0cd7a6a Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Wed, 18 Sep 2024 17:26:33 +0300 Subject: [PATCH 2/5] cmd/neofs-adm: 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. Refs #2890. Signed-off-by: Andrey Butusov --- .../internal/modules/storagecfg/root.go | 203 ++++++++++++------ cmd/neofs-adm/main.go | 8 +- 2 files changed, 143 insertions(+), 68 deletions(-) diff --git a/cmd/neofs-adm/internal/modules/storagecfg/root.go b/cmd/neofs-adm/internal/modules/storagecfg/root.go index b5b519cec1..745ea856b8 100644 --- a/cmd/neofs-adm/internal/modules/storagecfg/root.go +++ b/cmd/neofs-adm/internal/modules/storagecfg/root.go @@ -48,7 +48,7 @@ const ( var RootCmd = &cobra.Command{ Use: "storage-config [-w wallet] [-a acccount] []", Short: "Section for storage node configuration commands", - Run: storageConfig, + RunE: storageConfig, } func init() { @@ -79,12 +79,17 @@ type config struct { MetabasePath string } -func storageConfig(cmd *cobra.Command, args []string) { +func storageConfig(cmd *cobra.Command, args []string) error { var outPath string + var err error + if len(args) != 0 { outPath = args[0] } else { - outPath = getPath("File to write config at [./config.yml]: ") + outPath, err = getPath("File to write config at [./config.yml]: ") + if err != nil { + return err + } if outPath == "" { outPath = "./config.yml" } @@ -97,40 +102,57 @@ func storageConfig(cmd *cobra.Command, args []string) { c.Wallet.Path, _ = cmd.Flags().GetString(walletFlag) if c.Wallet.Path == "" { - c.Wallet.Path = getPath("Path to the storage node wallet: ") + c.Wallet.Path, err = getPath("Path to the storage node wallet: ") + if err != nil { + return err + } } w, err := wallet.NewWalletFromFile(c.Wallet.Path) - fatalOnErr(err) + if err != nil { + return err + } c.Wallet.Account, _ = cmd.Flags().GetString(accountFlag) if c.Wallet.Account == "" { addr := address.Uint160ToString(w.GetChangeAddress()) - c.Wallet.Account = getWalletAccount(w, fmt.Sprintf("Wallet account [%s]: ", addr)) + c.Wallet.Account, err = getWalletAccount(w, fmt.Sprintf("Wallet account [%s]: ", addr)) + if err != nil { + return err + } if c.Wallet.Account == "" { c.Wallet.Account = addr } } accH, err := flags.ParseAddress(c.Wallet.Account) - fatalOnErr(err) + if err != nil { + return err + } acc := w.GetAccount(accH) if acc == nil { - fatalOnErr(errors.New("can't find account in wallet")) + return errors.New("can't find account in wallet") } c.Wallet.Password, err = input.ReadPassword(fmt.Sprintf("Account password for %s: ", c.Wallet.Account)) - fatalOnErr(err) + if err != nil { + return err + } err = acc.Decrypt(c.Wallet.Password, keys.NEP2ScryptParams()) - fatalOnErr(err) + if err != nil { + return err + } c.AuthorizedKeys = append(c.AuthorizedKeys, acc.PublicKey().StringCompressed()) var network string for { - network = getString("Choose network [mainnet]/testnet: ") + network, err = getString("Choose network [mainnet]/testnet: ") + if err != nil { + return err + } switch network { case "": network = "mainnet" @@ -144,12 +166,20 @@ func storageConfig(cmd *cobra.Command, args []string) { c.MorphRPC = n3config[network].MorphRPC - depositGas(cmd, acc, network) + if err := depositGas(cmd, acc, network); err != nil { + return err + } - c.Attribute.Locode = getString("UN-LOCODE attribute in [XX YYY] format: ") + c.Attribute.Locode, err = getString("UN-LOCODE attribute in [XX YYY] format: ") + if err != nil { + return err + } var addr, port string for { - c.AnnouncedAddress = getString("Publicly announced address: ") + c.AnnouncedAddress, err = getString("Publicly announced address: ") + if err != nil { + return err + } validator := netutil.Address{} err := validator.FromString(c.AnnouncedAddress) if err != nil { @@ -184,35 +214,60 @@ func storageConfig(cmd *cobra.Command, args []string) { } defaultAddr := net.JoinHostPort(defaultDataEndpoint, port) - c.Endpoint = getString(fmt.Sprintf("Listening address [%s]: ", defaultAddr)) + c.Endpoint, err = getString(fmt.Sprintf("Listening address [%s]: ", defaultAddr)) + if err != nil { + return err + } if c.Endpoint == "" { c.Endpoint = defaultAddr } - c.ControlEndpoint = getString(fmt.Sprintf("Listening address (control endpoint) [%s]: ", defaultControlEndpoint)) + c.ControlEndpoint, err = getString(fmt.Sprintf("Listening address (control endpoint) [%s]: ", defaultControlEndpoint)) + if err != nil { + return err + } if c.ControlEndpoint == "" { c.ControlEndpoint = defaultControlEndpoint } - c.TLSCert = getPath("TLS Certificate (optional): ") + c.TLSCert, err = getPath("TLS Certificate (optional): ") + if err != nil { + return err + } if c.TLSCert != "" { - c.TLSKey = getPath("TLS Key: ") + c.TLSKey, err = getPath("TLS Key: ") + if err != nil { + return err + } } - c.Relay = getConfirmation(false, "Use node as a relay? yes/[no]: ") + c.Relay, err = getConfirmation(false, "Use node as a relay? yes/[no]: ") + if err != nil { + return err + } if !c.Relay { - p := getPath("Path to the storage directory (all available storage will be used): ") + p, err := getPath("Path to the storage directory (all available storage will be used): ") + if err != nil { + return err + } c.BlobstorPath = filepath.Join(p, "blob") c.MetabasePath = filepath.Join(p, "meta") } - out := applyTemplate(c) - fatalOnErr(os.WriteFile(outPath, out, 0o644)) + out, err := applyTemplate(c) + if err != nil { + return err + } + if err := os.WriteFile(outPath, out, 0o644); err != nil { + return err + } cmd.Println("Node is ready for work! Run `neofs-node -config " + outPath + "`") + + return nil } -func getWalletAccount(w *wallet.Wallet, prompt string) string { +func getWalletAccount(w *wallet.Wallet, prompt string) (string, error) { addrs := make([]readline.PrefixCompleterInterface, len(w.Accounts)) for i := range w.Accounts { addrs[i] = readline.PcItem(w.Accounts[i].Address) @@ -222,17 +277,21 @@ func getWalletAccount(w *wallet.Wallet, prompt string) string { defer readline.SetAutoComplete(nil) s, err := readline.Line(prompt) - fatalOnErr(err) - return strings.TrimSpace(s) // autocompleter can return a string with a trailing space + if err != nil { + return "", err + } + return strings.TrimSpace(s), nil // autocompleter can return a string with a trailing space } -func getString(prompt string) string { +func getString(prompt string) (string, error) { s, err := readline.Line(prompt) - fatalOnErr(err) + if err != nil { + return "", err + } if s != "" { _ = readline.AddHistory(s) } - return s + return s, nil } type filenameCompleter struct{} @@ -261,69 +320,73 @@ func (filenameCompleter) Do(line []rune, pos int) (newLine [][]rune, length int) return newLine, 0 } -func getPath(prompt string) string { +func getPath(prompt string) (string, error) { readline.SetAutoComplete(filenameCompleter{}) defer readline.SetAutoComplete(nil) p, err := readline.Line(prompt) - fatalOnErr(err) + if err != nil { + return "", err + } if p == "" { - return p + return p, nil } _ = readline.AddHistory(p) abs, err := filepath.Abs(p) if err != nil { - fatalOnErr(fmt.Errorf("can't create an absolute path: %w", err)) + return "", fmt.Errorf("can't create an absolute path: %w", err) } - return abs + return abs, nil } -func getConfirmation(def bool, prompt string) bool { +func getConfirmation(def bool, prompt string) (bool, error) { for { s, err := readline.Line(prompt) - fatalOnErr(err) + if err != nil { + return false, err + } switch strings.ToLower(s) { case "y", "yes": - return true + return true, nil case "n", "no": - return false + return false, nil default: if len(s) == 0 { - return def + return def, nil } } } } -func applyTemplate(c config) []byte { +func applyTemplate(c config) ([]byte, error) { tmpl, err := template.New("config").Parse(configTemplate) - fatalOnErr(err) + if err != nil { + return nil, err + } b := bytes.NewBuffer(nil) - fatalOnErr(tmpl.Execute(b, c)) + if err := tmpl.Execute(b, c); err != nil { + return nil, err + } - return b.Bytes() + return b.Bytes(), nil } -func fatalOnErr(err error) { +func depositGas(cmd *cobra.Command, acc *wallet.Account, network string) error { + sideClient, err := initClient(n3config[network].MorphRPC) if err != nil { - _, _ = fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) + return err } -} - -func depositGas(cmd *cobra.Command, acc *wallet.Account, network string) { - sideClient := initClient(n3config[network].MorphRPC) balanceHash, _ := util.Uint160DecodeStringLE(n3config[network].BalanceContract) sideActor, err := actor.NewSimple(sideClient, acc) if err != nil { - fatalOnErr(fmt.Errorf("creating actor over side chain client: %w", err)) + return fmt.Errorf("creating actor over side chain client: %w", err) } sideGas := nep17.NewReader(sideActor, balanceHash) @@ -331,34 +394,44 @@ func depositGas(cmd *cobra.Command, acc *wallet.Account, network string) { balance, err := sideGas.BalanceOf(accSH) if err != nil { - fatalOnErr(fmt.Errorf("side chain balance: %w", err)) + return fmt.Errorf("side chain balance: %w", err) } - ok := getConfirmation(false, fmt.Sprintf("Current NeoFS balance is %s, make a deposit? y/[n]: ", + ok, err := getConfirmation(false, fmt.Sprintf("Current NeoFS balance is %s, make a deposit? y/[n]: ", fixedn.ToString(balance, 12))) + if err != nil { + return err + } if !ok { - return + return nil + } + + amountStr, err := getString("Enter amount in GAS: ") + if err != nil { + return err } - amountStr := getString("Enter amount in GAS: ") amount, err := fixedn.FromString(amountStr, 8) if err != nil { - fatalOnErr(fmt.Errorf("invalid amount: %w", err)) + return fmt.Errorf("invalid amount: %w", err) } - mainClient := initClient(n3config[network].RPC) + mainClient, err := initClient(n3config[network].RPC) + if err != nil { + return err + } neofsHash, _ := util.Uint160DecodeStringLE(n3config[network].NeoFSContract) mainActor, err := actor.NewSimple(mainClient, acc) if err != nil { - fatalOnErr(fmt.Errorf("creating actor over main chain client: %w", err)) + return fmt.Errorf("creating actor over main chain client: %w", err) } mainGas := gas.New(mainActor) txHash, _, err := mainGas.Transfer(accSH, neofsHash, amount, nil) if err != nil { - fatalOnErr(fmt.Errorf("sending TX to the NeoFS contract: %w", err)) + return fmt.Errorf("sending TX to the NeoFS contract: %w", err) } cmd.Print("Waiting for transactions to persist.") @@ -382,15 +455,17 @@ loop: cmd.Print(".") case <-timer.C: cmd.Printf("\nTimeout while waiting for transaction to persist.\n") - if getConfirmation(false, "Continue configuration? yes/[no]: ") { - return + if flag, err := getConfirmation(false, "Continue configuration? yes/[no]: "); flag || err != nil { + return err } os.Exit(1) } } + + return nil } -func initClient(rpc []string) *rpcclient.Client { +func initClient(rpc []string) (*rpcclient.Client, error) { var c *rpcclient.Client var err error @@ -408,9 +483,11 @@ func initClient(rpc []string) *rpcclient.Client { if err = c.Init(); err != nil { continue } - return c + return c, nil } - fatalOnErr(fmt.Errorf("can't create N3 client: %w", err)) + if err != nil { + return nil, fmt.Errorf("can't create N3 client: %w", err) + } panic("unreachable") } diff --git a/cmd/neofs-adm/main.go b/cmd/neofs-adm/main.go index be009dc0d0..b8dae5d8be 100644 --- a/cmd/neofs-adm/main.go +++ b/cmd/neofs-adm/main.go @@ -1,13 +1,11 @@ package main import ( - "os" - + "github.com/nspcc-dev/neofs-node/cmd/internal/cmderr" "github.com/nspcc-dev/neofs-node/cmd/neofs-adm/internal/modules" ) func main() { - if err := modules.Execute(); err != nil { - os.Exit(1) - } + err := modules.Execute() + cmderr.ExitOnErr(err) } From 9ac84e30c21d61640d81409d860fb103a40f6d1e Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Wed, 18 Sep 2024 17:29:04 +0300 Subject: [PATCH 3/5] cmd/neofs-cli: add error handler after execution command Use `RunE` instead of `Run` and throw an error to main function. Wrap error with `common.WrapError` to specify the status code. Then handle error with custom error handler. Refs #2890. Signed-off-by: Andrey Butusov --- cmd/neofs-cli/internal/client/sdk.go | 8 +- cmd/neofs-cli/internal/common/eacl.go | 15 +- cmd/neofs-cli/internal/common/exit.go | 18 +- cmd/neofs-cli/internal/common/token.go | 14 +- cmd/neofs-cli/internal/key/raw.go | 16 +- cmd/neofs-cli/main.go | 9 +- cmd/neofs-cli/modules/accounting/balance.go | 21 ++- cmd/neofs-cli/modules/acl/basic/print.go | 13 +- cmd/neofs-cli/modules/acl/extended/create.go | 37 +++-- cmd/neofs-cli/modules/acl/extended/print.go | 20 ++- cmd/neofs-cli/modules/bearer/create.go | 45 +++-- cmd/neofs-cli/modules/bearer/print.go | 23 ++- cmd/neofs-cli/modules/container/create.go | 58 +++++-- cmd/neofs-cli/modules/container/delete.go | 50 ++++-- cmd/neofs-cli/modules/container/get.go | 57 +++++-- cmd/neofs-cli/modules/container/get_eacl.go | 28 +++- cmd/neofs-cli/modules/container/list.go | 24 ++- .../modules/container/list_objects.go | 34 +++- cmd/neofs-cli/modules/container/nodes.go | 24 ++- cmd/neofs-cli/modules/container/set_eacl.go | 52 ++++-- cmd/neofs-cli/modules/container/util.go | 21 ++- cmd/neofs-cli/modules/control/drop_objects.go | 29 +++- .../modules/control/evacuate_shard.go | 38 +++-- cmd/neofs-cli/modules/control/flush_cache.go | 38 +++-- cmd/neofs-cli/modules/control/healthcheck.go | 51 ++++-- cmd/neofs-cli/modules/control/object_list.go | 38 +++-- .../modules/control/object_status.go | 20 ++- .../modules/control/set_netmap_status.go | 32 +++- cmd/neofs-cli/modules/control/shards_dump.go | 36 ++-- cmd/neofs-cli/modules/control/shards_list.go | 42 +++-- .../modules/control/shards_restore.go | 39 +++-- .../modules/control/shards_set_mode.go | 60 ++++--- .../modules/control/synchronize_tree.go | 35 ++-- cmd/neofs-cli/modules/control/util.go | 35 ++-- cmd/neofs-cli/modules/netmap/get_epoch.go | 15 +- cmd/neofs-cli/modules/netmap/netinfo.go | 14 +- cmd/neofs-cli/modules/netmap/nodeinfo.go | 13 +- cmd/neofs-cli/modules/netmap/snapshot.go | 15 +- cmd/neofs-cli/modules/object/delete.go | 43 +++-- cmd/neofs-cli/modules/object/get.go | 50 ++++-- cmd/neofs-cli/modules/object/hash.go | 58 +++++-- cmd/neofs-cli/modules/object/head.go | 44 +++-- cmd/neofs-cli/modules/object/lock.go | 37 ++++- cmd/neofs-cli/modules/object/nodes.go | 38 ++++- cmd/neofs-cli/modules/object/put.go | 59 +++++-- cmd/neofs-cli/modules/object/range.go | 63 ++++--- cmd/neofs-cli/modules/object/search.go | 42 +++-- cmd/neofs-cli/modules/object/util.go | 156 ++++++++++++------ cmd/neofs-cli/modules/root.go | 16 +- cmd/neofs-cli/modules/session/create.go | 38 +++-- cmd/neofs-cli/modules/storagegroup/delete.go | 33 +++- cmd/neofs-cli/modules/storagegroup/get.go | 35 +++- cmd/neofs-cli/modules/storagegroup/list.go | 33 +++- cmd/neofs-cli/modules/storagegroup/put.go | 59 +++++-- cmd/neofs-cli/modules/storagegroup/util.go | 37 +++-- cmd/neofs-cli/modules/tree/add.go | 34 ++-- cmd/neofs-cli/modules/tree/add_by_path.go | 36 ++-- cmd/neofs-cli/modules/tree/get_by_path.go | 32 +++- cmd/neofs-cli/modules/tree/list.go | 31 +++- cmd/neofs-cli/modules/util/convert_eacl.go | 23 ++- cmd/neofs-cli/modules/util/keyer.go | 13 +- cmd/neofs-cli/modules/util/sign_bearer.go | 33 +++- cmd/neofs-cli/modules/util/sign_session.go | 33 ++-- pkg/services/control/rpc.go | 8 +- 64 files changed, 1567 insertions(+), 654 deletions(-) diff --git a/cmd/neofs-cli/internal/client/sdk.go b/cmd/neofs-cli/internal/client/sdk.go index efcb5a4872..617910dc7c 100644 --- a/cmd/neofs-cli/internal/client/sdk.go +++ b/cmd/neofs-cli/internal/client/sdk.go @@ -6,10 +6,8 @@ import ( "fmt" "time" - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/pkg/network" "github.com/nspcc-dev/neofs-sdk-go/client" - "github.com/spf13/cobra" "github.com/spf13/viper" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -19,12 +17,12 @@ var errInvalidEndpoint = errors.New("provided RPC endpoint is incorrect") // GetSDKClientByFlag returns default neofs-sdk-go client using the specified flag for the address. // On error, outputs to stderr of cmd and exits with non-zero code. -func GetSDKClientByFlag(ctx context.Context, cmd *cobra.Command, endpointFlag string) *client.Client { +func GetSDKClientByFlag(ctx context.Context, endpointFlag string) (*client.Client, error) { cli, err := getSDKClientByFlag(ctx, endpointFlag) if err != nil { - common.ExitOnErr(cmd, "can't create API client: %w", err) + return nil, fmt.Errorf("can't create API client: %w", err) } - return cli + return cli, nil } func getSDKClientByFlag(ctx context.Context, endpointFlag string) (*client.Client, error) { diff --git a/cmd/neofs-cli/internal/common/eacl.go b/cmd/neofs-cli/internal/common/eacl.go index f60da4c0cf..3c4e20f5d4 100644 --- a/cmd/neofs-cli/internal/common/eacl.go +++ b/cmd/neofs-cli/internal/common/eacl.go @@ -14,33 +14,34 @@ import ( var errUnsupportedEACLFormat = fmt.Errorf("%w: unsupported eACL format", errors.ErrUnsupported) // ReadEACL reads extended ACL table from eaclPath. -func ReadEACL(cmd *cobra.Command, eaclPath string) eacl.Table { +func ReadEACL(cmd *cobra.Command, eaclPath string) (eacl.Table, error) { _, err := os.Stat(eaclPath) // check if `eaclPath` is an existing file if err != nil { - ExitOnErr(cmd, "", errors.New("incorrect path to file with EACL")) + return eacl.Table{}, errors.New("incorrect path to file with EACL") } PrintVerbose(cmd, "Reading EACL from file: %s", eaclPath) data, err := os.ReadFile(eaclPath) - ExitOnErr(cmd, "can't read file with EACL: %w", err) + if err != nil { + return eacl.Table{}, fmt.Errorf("can't read file with EACL: %w", err) + } table, err := eacl.UnmarshalJSON(data) if err == nil { validateAndFixEACLVersion(table) PrintVerbose(cmd, "Parsed JSON encoded EACL table") - return table + return table, nil } table, err = eacl.Unmarshal(data) if err == nil { validateAndFixEACLVersion(table) PrintVerbose(cmd, "Parsed binary encoded EACL table") - return table + return table, nil } - ExitOnErr(cmd, "", errUnsupportedEACLFormat) - return eacl.Table{} + return eacl.Table{}, errUnsupportedEACLFormat } func validateAndFixEACLVersion(table eacl.Table) { diff --git a/cmd/neofs-cli/internal/common/exit.go b/cmd/neofs-cli/internal/common/exit.go index 6df1d34313..5dee3478e9 100644 --- a/cmd/neofs-cli/internal/common/exit.go +++ b/cmd/neofs-cli/internal/common/exit.go @@ -3,29 +3,24 @@ package common import ( "errors" "fmt" - "os" + "github.com/nspcc-dev/neofs-node/cmd/internal/cmderr" sdkstatus "github.com/nspcc-dev/neofs-sdk-go/client/status" - "github.com/spf13/cobra" ) // ErrAwaitTimeout represents the expiration of a polling interval // while awaiting a certain condition. var ErrAwaitTimeout = errors.New("await timeout expired") -// ExitOnErr prints error and exits with a code depending on the error type +// WrapError wrap error to cmderr.ExitErr, if it not nil, and add a code depending on the error type +// Codes: // -// 0 if nil // 1 if [sdkstatus.ErrServerInternal] or untyped // 2 if [sdkstatus.ErrObjectAccessDenied] // 3 if [ErrAwaitTimeout] -func ExitOnErr(cmd *cobra.Command, errFmt string, err error) { +func WrapError(err error) error { if err == nil { - return - } - - if errFmt != "" { - err = fmt.Errorf(errFmt, err) + return nil } const ( @@ -54,6 +49,5 @@ func ExitOnErr(cmd *cobra.Command, errFmt string, err error) { code = internal } - cmd.PrintErrln(err) - os.Exit(code) + return cmderr.ExitErr{Code: code, Cause: err} } diff --git a/cmd/neofs-cli/internal/common/token.go b/cmd/neofs-cli/internal/common/token.go index 27e9422023..5bb5fc955c 100644 --- a/cmd/neofs-cli/internal/common/token.go +++ b/cmd/neofs-cli/internal/common/token.go @@ -11,12 +11,14 @@ import ( ) // ReadBearerToken reads bearer token from the path provided in a specified flag. -func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token { +func ReadBearerToken(cmd *cobra.Command, flagname string) (*bearer.Token, error) { path, err := cmd.Flags().GetString(flagname) - ExitOnErr(cmd, "", err) + if err != nil { + return nil, err + } if len(path) == 0 { - return nil + return nil, nil } PrintVerbose(cmd, "Reading bearer token from file [%s]...", path) @@ -24,9 +26,11 @@ func ReadBearerToken(cmd *cobra.Command, flagname string) *bearer.Token { var tok bearer.Token err = ReadBinaryOrJSON(cmd, &tok, path) - ExitOnErr(cmd, "invalid bearer token: %v", err) + if err != nil { + return nil, fmt.Errorf("invalid bearer token: %v", err) + } - return &tok + return &tok, nil } // BinaryOrJSON is an interface of entities which provide json.Unmarshaler diff --git a/cmd/neofs-cli/internal/key/raw.go b/cmd/neofs-cli/internal/key/raw.go index 988df33569..50f72bdce1 100644 --- a/cmd/neofs-cli/internal/key/raw.go +++ b/cmd/neofs-cli/internal/key/raw.go @@ -19,10 +19,12 @@ var errCantGenerateKey = errors.New("can't generate new private key") // Get returns private key from wallet or binary file. // Ideally we want to touch file-system on the last step. // This function assumes that all flags were bind to viper in a `PersistentPreRun`. -func Get(cmd *cobra.Command) *ecdsa.PrivateKey { +func Get(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { pk, err := get(cmd) - common.ExitOnErr(cmd, "can't fetch private key: %w", err) - return pk + if err != nil { + return nil, fmt.Errorf("can't fetch private key: %w", err) + } + return pk, nil } var errMissingFlag = errors.New("missing key flag") @@ -47,10 +49,12 @@ func get(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { } // GetOrGenerate is similar to get but generates a new key if commonflags.GenerateKey is set. -func GetOrGenerate(cmd *cobra.Command) *ecdsa.PrivateKey { +func GetOrGenerate(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { pk, err := getOrGenerate(cmd) - common.ExitOnErr(cmd, "can't fetch private key: %w", err) - return pk + if err != nil { + return nil, fmt.Errorf("can't fetch private key: %w", err) + } + return pk, nil } func getOrGenerate(cmd *cobra.Command) (*ecdsa.PrivateKey, error) { diff --git a/cmd/neofs-cli/main.go b/cmd/neofs-cli/main.go index abdf9a4d58..03ff5d6b9a 100644 --- a/cmd/neofs-cli/main.go +++ b/cmd/neofs-cli/main.go @@ -1,7 +1,12 @@ package main -import cmd "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules" +import ( + "github.com/nspcc-dev/neofs-node/cmd/internal/cmderr" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + cmd "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules" +) func main() { - cmd.Execute() + err := cmd.Execute() + cmderr.ExitOnErr(common.WrapError(err)) } diff --git a/cmd/neofs-cli/modules/accounting/balance.go b/cmd/neofs-cli/modules/accounting/balance.go index a931a4ac83..2f8181d530 100644 --- a/cmd/neofs-cli/modules/accounting/balance.go +++ b/cmd/neofs-cli/modules/accounting/balance.go @@ -2,11 +2,11 @@ package accounting import ( "context" + "fmt" "math/big" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/util/precision" @@ -25,31 +25,40 @@ var accountingBalanceCmd = &cobra.Command{ Short: "Get internal balance of NeoFS account", Long: `Get internal balance of NeoFS account`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx := context.Background() var idUser user.ID - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } balanceOwner, _ := cmd.Flags().GetString(ownerFlag) if balanceOwner == "" { idUser = user.ResolveFromECDSAPublicKey(pk.PublicKey) } else { - common.ExitOnErr(cmd, "can't decode owner ID wallet address: %w", idUser.DecodeString(balanceOwner)) + return fmt.Errorf("can't decode owner ID wallet address: %w", idUser.DecodeString(balanceOwner)) } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.BalanceOfPrm prm.SetClient(cli) prm.SetAccount(idUser) res, err := internalclient.BalanceOf(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } // print to stdout prettyPrintDecimal(cmd, res.Balance()) + return nil }, } diff --git a/cmd/neofs-cli/modules/acl/basic/print.go b/cmd/neofs-cli/modules/acl/basic/print.go index 40ddf5ddd7..1397c21a7f 100644 --- a/cmd/neofs-cli/modules/acl/basic/print.go +++ b/cmd/neofs-cli/modules/acl/basic/print.go @@ -1,7 +1,8 @@ package basic import ( - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" + "fmt" + "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/util" "github.com/nspcc-dev/neofs-sdk-go/container/acl" "github.com/spf13/cobra" @@ -17,12 +18,16 @@ Container have access to the operations of the data replication mechanism: Get, Head, Put, Search, Hash. InnerRing members are allowed to data audit ops only: Get, Head, Hash, Search.`, - Run: printACL, + RunE: printACL, Args: cobra.ExactArgs(1), } -func printACL(cmd *cobra.Command, args []string) { +func printACL(cmd *cobra.Command, args []string) error { var bacl acl.Basic - common.ExitOnErr(cmd, "unable to parse basic acl: %w", bacl.DecodeString(args[0])) + if err := bacl.DecodeString(args[0]); err != nil { + return fmt.Errorf("unable to parse basic acl: %w", err) + } + util.PrettyPrintTableBACL(cmd, &bacl) + return nil } diff --git a/cmd/neofs-cli/modules/acl/extended/create.go b/cmd/neofs-cli/modules/acl/extended/create.go index 8f72eadf02..d2cd5f2a30 100644 --- a/cmd/neofs-cli/modules/acl/extended/create.go +++ b/cmd/neofs-cli/modules/acl/extended/create.go @@ -3,10 +3,11 @@ package extended import ( "bytes" "encoding/json" + "errors" + "fmt" "os" "strings" - "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/modules/util" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -49,7 +50,7 @@ When both '--rule' and '--file' arguments are used, '--rule' records will be pla Example: `neofs-cli acl extended create --cid EutHBsdT1YCzHxjCfQHnLPL1vFrkSyLSio4vkphfnEk -f rules.txt --out table.json neofs-cli acl extended create --cid EutHBsdT1YCzHxjCfQHnLPL1vFrkSyLSio4vkphfnEk -r 'allow get obj:Key=Value others' -r 'deny put others' -r 'deny put obj:$Object:payloadLength<4096 others' -r 'deny get obj:Quality>=100 others'`, Args: cobra.NoArgs, - Run: createEACL, + RunE: createEACL, } func init() { @@ -62,7 +63,7 @@ func init() { _ = cobra.MarkFlagFilename(createCmd.Flags(), "out") } -func createEACL(cmd *cobra.Command, _ []string) { +func createEACL(cmd *cobra.Command, _ []string) error { rules, _ := cmd.Flags().GetStringArray("rule") fileArg, _ := cmd.Flags().GetString("file") outArg, _ := cmd.Flags().GetString("out") @@ -71,54 +72,54 @@ func createEACL(cmd *cobra.Command, _ []string) { var containerID cid.ID if cidArg != "" { if err := containerID.DecodeString(cidArg); err != nil { - cmd.PrintErrf("invalid container ID: %v\n", err) - os.Exit(1) + return fmt.Errorf("invalid container ID: %v\n", err) } } rulesFile, err := getRulesFromFile(fileArg) if err != nil { - cmd.PrintErrf("can't read rules from file: %v\n", err) - os.Exit(1) + return fmt.Errorf("can't read rules from file: %v\n", err) } rules = append(rules, rulesFile...) if len(rules) == 0 { - cmd.PrintErrln("no extended ACL rules has been provided") - os.Exit(1) + return errors.New("no extended ACL rules has been provided") } var tb eacl.Table - common.ExitOnErr(cmd, "unable to parse provided rules: %w", util.ParseEACLRules(&tb, rules)) + if err := util.ParseEACLRules(&tb, rules); err != nil { + return fmt.Errorf("unable to parse provided rules: %w", err) + } err = util.ValidateEACLTable(tb) - common.ExitOnErr(cmd, "table validation: %w", err) + if err != nil { + return fmt.Errorf("table validation: %w", err) + } tb.SetCID(containerID) data, err := tb.MarshalJSON() if err != nil { - cmd.PrintErrln(err) - os.Exit(1) + return err } buf := new(bytes.Buffer) err = json.Indent(buf, data, "", " ") if err != nil { - cmd.PrintErrln(err) - os.Exit(1) + return err } if len(outArg) == 0 { cmd.Println(buf) - return + return nil } err = os.WriteFile(outArg, buf.Bytes(), 0o644) if err != nil { - cmd.PrintErrln(err) - os.Exit(1) + return err } + + return nil } func getRulesFromFile(filename string) ([]string, error) { diff --git a/cmd/neofs-cli/modules/acl/extended/print.go b/cmd/neofs-cli/modules/acl/extended/print.go index 6f380d026b..e534a95207 100644 --- a/cmd/neofs-cli/modules/acl/extended/print.go +++ b/cmd/neofs-cli/modules/acl/extended/print.go @@ -1,10 +1,10 @@ package extended import ( + "fmt" "os" "strings" - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/util" "github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/spf13/cobra" @@ -14,7 +14,7 @@ var printEACLCmd = &cobra.Command{ Use: "print", Short: "Pretty print extended ACL from the file(in text or json format) or for given container.", Args: cobra.NoArgs, - Run: printEACL, + RunE: printEACL, } func init() { @@ -24,16 +24,24 @@ func init() { _ = printEACLCmd.MarkFlagRequired("file") } -func printEACL(cmd *cobra.Command, _ []string) { +func printEACL(cmd *cobra.Command, _ []string) error { file, _ := cmd.Flags().GetString("file") eaclTable := new(eacl.Table) data, err := os.ReadFile(file) - common.ExitOnErr(cmd, "can't read file with EACL: %w", err) + if err != nil { + return fmt.Errorf("can't read file with EACL: %w", err) + } + if strings.HasSuffix(file, ".json") { - common.ExitOnErr(cmd, "unable to parse json: %w", eaclTable.UnmarshalJSON(data)) + if err := eaclTable.UnmarshalJSON(data); err != nil { + return fmt.Errorf("unable to parse json: %w", err) + } } else { rules := strings.Split(strings.TrimSpace(string(data)), "\n") - common.ExitOnErr(cmd, "can't parse file with EACL: %w", util.ParseEACLRules(eaclTable, rules)) + if err := util.ParseEACLRules(eaclTable, rules); err != nil { + return fmt.Errorf("can't parse file with EACL: %w", err) + } } util.PrettyPrintTableEACL(cmd, eaclTable) + return nil } diff --git a/cmd/neofs-cli/modules/bearer/create.go b/cmd/neofs-cli/modules/bearer/create.go index da37f92696..00edbdce6a 100644 --- a/cmd/neofs-cli/modules/bearer/create.go +++ b/cmd/neofs-cli/modules/bearer/create.go @@ -35,7 +35,7 @@ In this case --` + commonflags.RPC + ` flag should be specified and the epoch in is set to current epoch + n. `, Args: cobra.NoArgs, - Run: createToken, + RunE: createToken, } func init() { @@ -58,16 +58,22 @@ func init() { createCmd.MarkFlagsOneRequired(commonflags.ExpireAt, commonflags.Lifetime) } -func createToken(cmd *cobra.Command, _ []string) { +func createToken(cmd *cobra.Command, _ []string) error { iat, iatRelative, err := common.ParseEpoch(cmd, issuedAtFlag) - common.ExitOnErr(cmd, "can't parse --"+issuedAtFlag+" flag: %w", err) + if err != nil { + return fmt.Errorf("can't parse --"+issuedAtFlag+" flag: %w", err) + } lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime) exp, expRelative, err := common.ParseEpoch(cmd, commonflags.ExpireAt) - common.ExitOnErr(cmd, "can't parse --"+commonflags.ExpireAt+" flag: %w", err) + if err != nil { + return fmt.Errorf("can't parse --"+commonflags.ExpireAt+" flag: %w", err) + } nvb, nvbRelative, err := common.ParseEpoch(cmd, notValidBeforeFlag) - common.ExitOnErr(cmd, "can't parse --"+notValidBeforeFlag+" flag: %w", err) + if err != nil { + return fmt.Errorf("can't parse --"+notValidBeforeFlag+" flag: %w", err) + } if iatRelative || expRelative || nvbRelative || lifetime != 0 { ctx, cancel := context.WithTimeout(context.Background(), time.Second*30) @@ -75,7 +81,9 @@ func createToken(cmd *cobra.Command, _ []string) { endpoint, _ := cmd.Flags().GetString(commonflags.RPC) currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint) - common.ExitOnErr(cmd, "can't fetch current epoch: %w", err) + if err != nil { + return fmt.Errorf("can't fetch current epoch: %w", err) + } if iatRelative { iat += currEpoch @@ -91,14 +99,15 @@ func createToken(cmd *cobra.Command, _ []string) { } } if exp < nvb { - common.ExitOnErr(cmd, "", - fmt.Errorf("expiration epoch is less than not-valid-before epoch: %d < %d", exp, nvb)) + return fmt.Errorf("expiration epoch is less than not-valid-before epoch: %d < %d", exp, nvb) } ownerStr, _ := cmd.Flags().GetString(ownerFlag) var ownerID user.ID - common.ExitOnErr(cmd, "can't parse recipient: %w", ownerID.DecodeString(ownerStr)) + if err := ownerID.DecodeString(ownerStr); err != nil { + return fmt.Errorf("can't parse recipient: %w", err) + } var b bearer.Token b.SetExp(exp) @@ -109,9 +118,13 @@ func createToken(cmd *cobra.Command, _ []string) { eaclPath, _ := cmd.Flags().GetString(eaclFlag) if eaclPath != "" { raw, err := os.ReadFile(eaclPath) - common.ExitOnErr(cmd, "can't read extended ACL file: %w", err) + if err != nil { + return fmt.Errorf("can't read extended ACL file: %w", err) + } table, err := eaclSDK.UnmarshalJSON(raw) - common.ExitOnErr(cmd, "can't parse extended ACL: %w", err) + if err != nil { + return fmt.Errorf("can't parse extended ACL: %w", err) + } b.SetEACLTable(table) } @@ -120,12 +133,18 @@ func createToken(cmd *cobra.Command, _ []string) { toJSON, _ := cmd.Flags().GetBool(jsonFlag) if toJSON { data, err = json.Marshal(b) - common.ExitOnErr(cmd, "can't mashal token to JSON: %w", err) + if err != nil { + return fmt.Errorf("can't marshal token to JSON: %w", err) + } } else { data = b.Marshal() } out, _ := cmd.Flags().GetString(outFlag) err = os.WriteFile(out, data, 0o644) - common.ExitOnErr(cmd, "can't write token to file: %w", err) + if err != nil { + return fmt.Errorf("can't write token to file: %w", err) + } + + return nil } diff --git a/cmd/neofs-cli/modules/bearer/print.go b/cmd/neofs-cli/modules/bearer/print.go index ad600430ad..1483de27d0 100644 --- a/cmd/neofs-cli/modules/bearer/print.go +++ b/cmd/neofs-cli/modules/bearer/print.go @@ -1,10 +1,10 @@ package bearer import ( + "fmt" "io" "os" - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-sdk-go/bearer" "github.com/spf13/cobra" ) @@ -15,30 +15,39 @@ var printCmd = &cobra.Command{ Long: `neofs-cli bearer print [FILE] With no FILE, or when FILE is -, read standard input.`, Args: cobra.MaximumNArgs(1), - Run: printToken, + RunE: printToken, } -func printToken(cmd *cobra.Command, arg []string) { +func printToken(cmd *cobra.Command, arg []string) error { var reader io.Reader if len(arg) == 1 && arg[0] != "-" { var err error reader, err = os.Open(arg[0]) - common.ExitOnErr(cmd, "opening file: %w", err) + if err != nil { + return fmt.Errorf("opening file: %w", err) + } } else { reader = cmd.InOrStdin() } raw, err := io.ReadAll(reader) - common.ExitOnErr(cmd, "reading input data failed: %w", err) + if err != nil { + return fmt.Errorf("reading input data failed: %w", err) + } var token bearer.Token err = token.Unmarshal(raw) - common.ExitOnErr(cmd, "invalid binary token: %w", err) + if err != nil { + return fmt.Errorf("invalid binary token: %w", err) + } rawJSON, err := token.MarshalJSON() - common.ExitOnErr(cmd, "marshaling read token in JSON format: %w", err) + if err != nil { + return fmt.Errorf("marshaling read token in JSON format: %w", err) + } cmd.Print(string(rawJSON)) + return nil } diff --git a/cmd/neofs-cli/modules/container/create.go b/cmd/neofs-cli/modules/container/create.go index 7f86717b39..3c81418887 100644 --- a/cmd/neofs-cli/modules/container/create.go +++ b/cmd/neofs-cli/modules/container/create.go @@ -35,36 +35,48 @@ var createContainerCmd = &cobra.Command{ Long: `Create new container and register it in the NeoFS. It will be stored in sidechain when inner ring will accepts it.`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := getAwaitContext(cmd) defer cancel() placementPolicy, err := parseContainerPolicy(cmd, containerPolicy) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } - key := key.Get(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + key, err := key.Get(cmd) + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } if !force { var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) resmap, err := internalclient.NetMapSnapshot(ctx, prm) - common.ExitOnErr(cmd, "unable to get netmap snapshot to validate container placement, "+ - "use --force option to skip this check: %w", err) + if err != nil { + return fmt.Errorf("unable to get netmap snapshot to validate container placement, "+ + "use --force option to skip this check: %w", err) + } nodesByRep, err := resmap.NetMap().ContainerNodes(*placementPolicy, cid.ID{}) - common.ExitOnErr(cmd, "could not build container nodes based on given placement policy, "+ - "use --force option to skip this check: %w", err) + if err != nil { + return fmt.Errorf("could not build container nodes based on given placement policy, "+ + "use --force option to skip this check: %w", err) + } for i, nodes := range nodesByRep { if placementPolicy.ReplicaNumberByIndex(i) > uint32(len(nodes)) { - common.ExitOnErr(cmd, "", fmt.Errorf( + return fmt.Errorf( "the number of nodes '%d' in selector is not enough for the number of replicas '%d', "+ "use --force option to skip this check", len(nodes), placementPolicy.ReplicaNumberByIndex(i), - )) + ) } } } @@ -73,12 +85,19 @@ It will be stored in sidechain when inner ring will accepts it.`, cnr.Init() err = parseAttributes(&cnr, containerAttributes) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } var basicACL acl.Basic - common.ExitOnErr(cmd, "decode basic ACL string: %w", basicACL.DecodeString(containerACL)) + if err := basicACL.DecodeString(containerACL); err != nil { + return fmt.Errorf("decode basic ACL string: %w", err) + } - tok := getSession(cmd) + tok, err := getSession(cmd) + if err != nil { + return err + } if tok != nil { issuer := tok.Issuer() @@ -95,7 +114,9 @@ It will be stored in sidechain when inner ring will accepts it.`, syncContainerPrm.SetContainer(&cnr) _, err = internalclient.SyncContainerSettings(ctx, syncContainerPrm) - common.ExitOnErr(cmd, "syncing container's settings rpc error: %w", err) + if err != nil { + return fmt.Errorf("syncing container's settings rpc error: %w", err) + } var putPrm internalclient.PutContainerPrm putPrm.SetClient(cli) @@ -107,7 +128,9 @@ It will be stored in sidechain when inner ring will accepts it.`, } res, err := internalclient.PutContainer(ctx, putPrm) - common.ExitOnErr(cmd, "put container rpc error: %w", err) + if err != nil { + return fmt.Errorf("put container rpc error: %w", err) + } id := res.ID() @@ -129,17 +152,18 @@ It will be stored in sidechain when inner ring will accepts it.`, for ; ; t.Reset(waitInterval) { select { case <-ctx.Done(): - common.ExitOnErr(cmd, "container creation: %s", common.ErrAwaitTimeout) + return fmt.Errorf("container creation: %s", common.ErrAwaitTimeout) case <-t.C: } _, err := internalclient.GetContainer(ctx, getPrm) if err == nil { cmd.Println("container has been persisted on sidechain") - return + return nil } } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/delete.go b/cmd/neofs-cli/modules/container/delete.go index a9c8413c60..43406634ed 100644 --- a/cmd/neofs-cli/modules/container/delete.go +++ b/cmd/neofs-cli/modules/container/delete.go @@ -19,16 +19,28 @@ var deleteContainerCmd = &cobra.Command{ Long: `Delete existing container. Only owner of the container has a permission to remove container.`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := getAwaitContext(cmd) defer cancel() - id := parseContainerID(cmd) + id, err := parseContainerID() + if err != nil { + return err + } - tok := getSession(cmd) + tok, err := getSession(cmd) + if err != nil { + return err + } - pk := key.Get(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + pk, err := key.Get(cmd) + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } if force, _ := cmd.Flags().GetBool(commonflags.ForceFlag); !force { common.PrintVerbose(cmd, "Reading the container to check ownership...") @@ -38,7 +50,9 @@ Only owner of the container has a permission to remove container.`, getPrm.SetContainer(id) resGet, err := internalclient.GetContainer(ctx, getPrm) - common.ExitOnErr(cmd, "can't get the container: %w", err) + if err != nil { + return fmt.Errorf("can't get the container: %w", err) + } owner := resGet.Container().Owner() @@ -46,7 +60,7 @@ Only owner of the container has a permission to remove container.`, common.PrintVerbose(cmd, "Checking session issuer...") if !tok.Issuer().Equals(owner) { - common.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())) + return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer()) } } else { common.PrintVerbose(cmd, "Checking provided account...") @@ -54,7 +68,7 @@ Only owner of the container has a permission to remove container.`, acc := user.ResolveFromECDSAPublicKey(pk.PublicKey) if !acc.Equals(owner) { - common.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc)) + return fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc) } } @@ -76,12 +90,13 @@ Only owner of the container has a permission to remove container.`, common.PrintVerbose(cmd, "Searching for LOCK objects...") res, err := internalclient.SearchObjects(ctx, searchPrm) - common.ExitOnErr(cmd, "can't search for LOCK objects: %w", err) + if err != nil { + return fmt.Errorf("can't search for LOCK objects: %w", err) + } if len(res.IDList()) != 0 { - common.ExitOnErr(cmd, "", - fmt.Errorf("Container wasn't removed because LOCK objects were found.\n"+ - "Use --%s flag to remove anyway.", commonflags.ForceFlag)) + return fmt.Errorf("Container wasn't removed because LOCK objects were found.\n"+ + "Use --%s flag to remove anyway.", commonflags.ForceFlag) } } } @@ -95,8 +110,10 @@ Only owner of the container has a permission to remove container.`, delPrm.WithinSession(*tok) } - _, err := internalclient.DeleteContainer(ctx, delPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + _, err = internalclient.DeleteContainer(ctx, delPrm) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmd.Println("container removal request accepted for processing (the operation may not be completed yet)") @@ -115,17 +132,18 @@ Only owner of the container has a permission to remove container.`, for ; ; t.Reset(waitInterval) { select { case <-ctx.Done(): - common.ExitOnErr(cmd, "container deletion: %s", common.ErrAwaitTimeout) + return fmt.Errorf("container deletion: %s", common.ErrAwaitTimeout) case <-t.C: } _, err := internalclient.GetContainer(ctx, getPrm) if err != nil { cmd.Println("container has been removed:", containerID) - return + return nil } } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/get.go b/cmd/neofs-cli/modules/container/get.go index 67b44f69f5..50d65b1c12 100644 --- a/cmd/neofs-cli/modules/container/get.go +++ b/cmd/neofs-cli/modules/container/get.go @@ -2,6 +2,7 @@ package container import ( "context" + "fmt" "os" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" @@ -31,13 +32,19 @@ var getContainerInfoCmd = &cobra.Command{ Short: "Get container field info", Long: `Get container field info`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cnr := getContainer(ctx, cmd) + cnr, err := getContainer(ctx, cmd) + if err != nil { + return err + } - prettyPrintContainer(cmd, cnr, containerJSON) + err = prettyPrintContainer(cmd, cnr, containerJSON) + if err != nil { + return err + } if containerPathTo != "" { var ( @@ -47,14 +54,19 @@ var getContainerInfoCmd = &cobra.Command{ if containerJSON { data, err = cnr.MarshalJSON() - common.ExitOnErr(cmd, "can't JSON encode container: %w", err) + if err != nil { + return fmt.Errorf("can't JSON encode container: %w", err) + } } else { data = cnr.Marshal() } err = os.WriteFile(containerPathTo, data, 0644) - common.ExitOnErr(cmd, "can't write container to file: %w", err) + if err != nil { + return fmt.Errorf("can't write container to file: %w", err) + } } + return nil }, } @@ -76,10 +88,10 @@ func (x *stringWriter) WriteString(s string) (n int, err error) { return len(s), nil } -func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncoding bool) { +func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncoding bool) error { if jsonEncoding { common.PrettyPrintJSON(cmd, cnr, "container") - return + return nil } var id cid.ID @@ -99,8 +111,11 @@ func prettyPrintContainer(cmd *cobra.Command, cnr container.Container, jsonEncod }) cmd.Println("placement policy:") - common.ExitOnErr(cmd, "write policy: %w", cnr.PlacementPolicy().WriteStringTo((*stringWriter)(cmd))) + if err := cnr.PlacementPolicy().WriteStringTo((*stringWriter)(cmd)); err != nil { + return fmt.Errorf("write policy: %w", err) + } cmd.Println() + return nil } func prettyPrintBasicACL(cmd *cobra.Command, basicACL acl.Basic) { @@ -135,26 +150,38 @@ func prettyPrintBasicACL(cmd *cobra.Command, basicACL acl.Basic) { util.PrettyPrintTableBACL(cmd, &basicACL) } -func getContainer(ctx context.Context, cmd *cobra.Command) container.Container { +func getContainer(ctx context.Context, cmd *cobra.Command) (container.Container, error) { var cnr container.Container if containerPathFrom != "" { data, err := os.ReadFile(containerPathFrom) - common.ExitOnErr(cmd, "can't read file: %w", err) + if err != nil { + return container.Container{}, fmt.Errorf("can't read file: %w", err) + } err = cnr.Unmarshal(data) - common.ExitOnErr(cmd, "can't unmarshal container: %w", err) + if err != nil { + return container.Container{}, fmt.Errorf("can't unmarshal container: %w", err) + } } else { - id := parseContainerID(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + id, err := parseContainerID() + if err != nil { + return container.Container{}, err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return container.Container{}, err + } var prm internalclient.GetContainerPrm prm.SetClient(cli) prm.SetContainer(id) res, err := internalclient.GetContainer(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return container.Container{}, fmt.Errorf("rpc error: %w", err) + } cnr = res.Container() } - return cnr + return cnr, nil } diff --git a/cmd/neofs-cli/modules/container/get_eacl.go b/cmd/neofs-cli/modules/container/get_eacl.go index 8777488657..87dc9b8c60 100644 --- a/cmd/neofs-cli/modules/container/get_eacl.go +++ b/cmd/neofs-cli/modules/container/get_eacl.go @@ -1,6 +1,7 @@ package container import ( + "fmt" "os" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" @@ -14,19 +15,27 @@ var getExtendedACLCmd = &cobra.Command{ Short: "Get extended ACL table of container", Long: `Get extended ACL table of container`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - id := parseContainerID(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + id, err := parseContainerID() + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var eaclPrm internalclient.EACLPrm eaclPrm.SetClient(cli) eaclPrm.SetContainer(id) res, err := internalclient.EACL(ctx, eaclPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } eaclTable := res.EACL() @@ -34,14 +43,16 @@ var getExtendedACLCmd = &cobra.Command{ cmd.Println("eACL: ") common.PrettyPrintJSON(cmd, &eaclTable, "eACL") - return + return nil } var data []byte if containerJSON { data, err = eaclTable.MarshalJSON() - common.ExitOnErr(cmd, "can't encode to JSON: %w", err) + if err != nil { + return fmt.Errorf("can't encode to JSON: %w", err) + } } else { data = eaclTable.Marshal() } @@ -49,7 +60,10 @@ var getExtendedACLCmd = &cobra.Command{ cmd.Println("dumping data to file:", containerPathTo) err = os.WriteFile(containerPathTo, data, 0644) - common.ExitOnErr(cmd, "could not write eACL to file: %w", err) + if err != nil { + return fmt.Errorf("could not write eACL to file: %w", err) + } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/list.go b/cmd/neofs-cli/modules/container/list.go index 5787748d7c..a876f629d8 100644 --- a/cmd/neofs-cli/modules/container/list.go +++ b/cmd/neofs-cli/modules/container/list.go @@ -1,8 +1,9 @@ package container 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-sdk-go/user" @@ -26,29 +27,39 @@ var listContainersCmd = &cobra.Command{ Short: "List all created containers", Long: "List all created containers", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var idUser user.ID - key := key.GetOrGenerate(cmd) + key, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } if flagVarListContainerOwner == "" { idUser = user.ResolveFromECDSAPublicKey(key.PublicKey) } else { err := idUser.DecodeString(flagVarListContainerOwner) - common.ExitOnErr(cmd, "invalid user ID: %w", err) + if err != nil { + return fmt.Errorf("invalid user ID: %w", err) + } } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.ListContainersPrm prm.SetClient(cli) prm.SetAccount(idUser) res, err := internalclient.ListContainers(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } var prmGet internalclient.GetContainerPrm prmGet.SetClient(cli) @@ -70,6 +81,7 @@ var listContainersCmd = &cobra.Command{ } } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/list_objects.go b/cmd/neofs-cli/modules/container/list_objects.go index a713f68d03..9aff8e2b45 100644 --- a/cmd/neofs-cli/modules/container/list_objects.go +++ b/cmd/neofs-cli/modules/container/list_objects.go @@ -1,6 +1,8 @@ package container 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" @@ -26,17 +28,26 @@ var listContainerObjectsCmd = &cobra.Command{ Short: "List existing objects in container", Long: `List existing objects in container`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - id := parseContainerID(cmd) + id, err := parseContainerID() + if err != nil { + return err + } filters := new(object.SearchFilters) filters.AddRootFilter() // search only user created objects - pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prmSearch internalclient.SearchObjectsPrm var prmHead internalclient.HeadObjectPrm @@ -46,9 +57,15 @@ var listContainerObjectsCmd = &cobra.Command{ if flagVarListObjectsPrintAttr { prmHead.SetClient(cli) prmHead.SetPrivateKey(*pk) - objectCli.Prepare(cmd, &prmSearch, &prmHead) + err = objectCli.Prepare(cmd, &prmSearch, &prmHead) + if err != nil { + return err + } } else { - objectCli.Prepare(cmd, &prmSearch) + err = objectCli.Prepare(cmd, &prmSearch) + if err != nil { + return err + } } prmSearch.SetPrivateKey(*pk) @@ -56,7 +73,9 @@ var listContainerObjectsCmd = &cobra.Command{ prmSearch.SetFilters(*filters) res, err := internalclient.SearchObjects(ctx, prmSearch) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } objectIDs := res.IDList() @@ -88,6 +107,7 @@ var listContainerObjectsCmd = &cobra.Command{ } } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/nodes.go b/cmd/neofs-cli/modules/container/nodes.go index e5794443bc..7d90b8480c 100644 --- a/cmd/neofs-cli/modules/container/nodes.go +++ b/cmd/neofs-cli/modules/container/nodes.go @@ -1,9 +1,10 @@ package container import ( + "fmt" + "github.com/nspcc-dev/neofs-node/cmd/internal/cmdprinter" 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" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/netmap" @@ -17,19 +18,27 @@ var containerNodesCmd = &cobra.Command{ Short: "Show nodes for container", Long: "Show nodes taking part in a container at the current epoch.", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cnr := getContainer(ctx, cmd) + cnr, err := getContainer(ctx, cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) resmap, err := internalclient.NetMapSnapshot(ctx, prm) - common.ExitOnErr(cmd, "unable to get netmap snapshot", err) + if err != nil { + return fmt.Errorf("unable to get netmap snapshot: %w", err) + } var id cid.ID cnr.CalculateID(&id) @@ -38,7 +47,9 @@ var containerNodesCmd = &cobra.Command{ var cnrNodes [][]netmap.NodeInfo cnrNodes, err = resmap.NetMap().ContainerNodes(policy, id) - common.ExitOnErr(cmd, "could not build container nodes for given container: %w", err) + if err != nil { + return fmt.Errorf("could not build container nodes for given container: %w", err) + } for i := range cnrNodes { cmd.Printf("Descriptor #%d, REP %d:\n", i+1, policy.ReplicaNumberByIndex(i)) @@ -46,6 +57,7 @@ var containerNodesCmd = &cobra.Command{ cmdprinter.PrettyPrintNodeInfo(cmd, cnrNodes[i][j], j, "\t", short) } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/set_eacl.go b/cmd/neofs-cli/modules/container/set_eacl.go index 51dd119f07..330210e39d 100644 --- a/cmd/neofs-cli/modules/container/set_eacl.go +++ b/cmd/neofs-cli/modules/container/set_eacl.go @@ -25,24 +25,41 @@ var setExtendedACLCmd = &cobra.Command{ Long: `Set new extended ACL table for container. Container ID in EACL table will be substituted with ID from the CLI.`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := getAwaitContext(cmd) defer cancel() - id := parseContainerID(cmd) - eaclTable := common.ReadEACL(cmd, flagVarsSetEACL.srcPath) + id, err := parseContainerID() + if err != nil { + return err + } + eaclTable, err := common.ReadEACL(cmd, flagVarsSetEACL.srcPath) + if err != nil { + return err + } - tok := getSession(cmd) + tok, err := getSession(cmd) + if err != nil { + return err + } eaclTable.SetCID(id) - pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } force, _ := cmd.Flags().GetBool(commonflags.ForceFlag) if !force { common.PrintVerbose(cmd, "Validating eACL table...") err := util.ValidateEACLTable(eaclTable) - common.ExitOnErr(cmd, "table validation: %w", err) + if err != nil { + return fmt.Errorf("table validation: %w", err) + } cmd.Println("Checking the ability to modify access rights in the container...") common.PrintVerbose(cmd, "Reading the container to check ownership...") @@ -52,7 +69,9 @@ Container ID in EACL table will be substituted with ID from the CLI.`, getPrm.SetContainer(id) resGet, err := internalclient.GetContainer(ctx, getPrm) - common.ExitOnErr(cmd, "can't get the container: %w", err) + if err != nil { + return fmt.Errorf("can't get the container: %w", err) + } cnr := resGet.Container() owner := cnr.Owner() @@ -61,7 +80,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, common.PrintVerbose(cmd, "Checking session issuer...") if !tok.Issuer().Equals(owner) { - common.ExitOnErr(cmd, "", fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())) + return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer()) } } else { common.PrintVerbose(cmd, "Checking provided account...") @@ -69,7 +88,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, acc := user.ResolveFromECDSAPublicKey(pk.PublicKey) if !acc.Equals(owner) { - common.ExitOnErr(cmd, "", fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc)) + return fmt.Errorf("provided account differs with the container owner: expected %s, has %s", owner, acc) } } @@ -78,7 +97,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, extendable := cnr.BasicACL().Extendable() if !extendable { - common.ExitOnErr(cmd, "", errors.New("container ACL is immutable")) + return errors.New("container ACL is immutable") } cmd.Println("ACL extension is enabled in the container, continue processing.") @@ -93,8 +112,10 @@ Container ID in EACL table will be substituted with ID from the CLI.`, setEACLPrm.WithinSession(*tok) } - _, err := internalclient.SetEACL(ctx, setEACLPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + _, err = internalclient.SetEACL(ctx, setEACLPrm) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmd.Println("eACL modification request accepted for processing (the operation may not be completed yet)") @@ -115,7 +136,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`, for ; ; t.Reset(waitInterval) { select { case <-ctx.Done(): - common.ExitOnErr(cmd, "eACL setting: %s", common.ErrAwaitTimeout) + return fmt.Errorf("eACL setting: %s", common.ErrAwaitTimeout) case <-t.C: } @@ -127,12 +148,13 @@ Container ID in EACL table will be substituted with ID from the CLI.`, if bytes.Equal(exp, got) { cmd.Println("EACL has been persisted on sidechain") - return + return nil } } } } + return nil }, } diff --git a/cmd/neofs-cli/modules/container/util.go b/cmd/neofs-cli/modules/container/util.go index a6c3685246..c984d5cd60 100644 --- a/cmd/neofs-cli/modules/container/util.go +++ b/cmd/neofs-cli/modules/container/util.go @@ -3,6 +3,7 @@ package container import ( "context" "errors" + "fmt" "time" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -18,26 +19,28 @@ const ( awaitTimeout = time.Minute ) -func parseContainerID(cmd *cobra.Command) cid.ID { +func parseContainerID() (cid.ID, error) { if containerID == "" { - common.ExitOnErr(cmd, "", errors.New("container ID is not set")) + return cid.ID{}, errors.New("container ID is not set") } var id cid.ID err := id.DecodeString(containerID) - common.ExitOnErr(cmd, "can't decode container ID value: %w", err) - return id + if err != nil { + return cid.ID{}, fmt.Errorf("can't decode container ID value: %w", err) + } + return id, nil } // decodes session.Container from the file by path provided in // commonflags.SessionToken flag. Returns nil if the path is not specified. -func getSession(cmd *cobra.Command) *session.Container { +func getSession(cmd *cobra.Command) (*session.Container, error) { common.PrintVerbose(cmd, "Reading container session...") path, _ := cmd.Flags().GetString(commonflags.SessionToken) if path == "" { common.PrintVerbose(cmd, "Session not provided.") - return nil + return nil, nil } common.PrintVerbose(cmd, "Reading container session from the file [%s]...", path) @@ -45,11 +48,13 @@ func getSession(cmd *cobra.Command) *session.Container { var res session.Container err := common.ReadBinaryOrJSON(cmd, &res, path) - common.ExitOnErr(cmd, "read container session: %v", err) + if err != nil { + return nil, fmt.Errorf("read container session: %v", err) + } common.PrintVerbose(cmd, "Session successfully read.") - return &res + return &res, err } func getAwaitContext(cmd *cobra.Command) (context.Context, context.CancelFunc) { diff --git a/cmd/neofs-cli/modules/control/drop_objects.go b/cmd/neofs-cli/modules/control/drop_objects.go index 501c97c5f9..47d0122421 100644 --- a/cmd/neofs-cli/modules/control/drop_objects.go +++ b/cmd/neofs-cli/modules/control/drop_objects.go @@ -2,7 +2,6 @@ package control 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" @@ -16,11 +15,14 @@ var dropObjectsCmd = &cobra.Command{ Short: "Drop objects from the node's local storage", Long: "Drop objects from the node's local storage", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } dropObjectsList, _ := cmd.Flags().GetStringSlice(dropObjectsFlag) binAddrList := make([][]byte, len(dropObjectsList)) @@ -35,21 +37,32 @@ var dropObjectsCmd = &cobra.Command{ req := new(control.DropObjectsRequest) req.SetBody(body) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.DropObjectsResponse - var err error err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.DropObjects(client, req) return err }) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Objects were successfully marked to be removed.") + return nil }, } diff --git a/cmd/neofs-cli/modules/control/evacuate_shard.go b/cmd/neofs-cli/modules/control/evacuate_shard.go index 03eea8f117..a30c323cc6 100644 --- a/cmd/neofs-cli/modules/control/evacuate_shard.go +++ b/cmd/neofs-cli/modules/control/evacuate_shard.go @@ -1,8 +1,9 @@ package control import ( + "fmt" + "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" @@ -14,36 +15,53 @@ var evacuateShardCmd = &cobra.Command{ Short: "Evacuate objects from shard", Long: "Evacuate objects from shard to other shards", Args: cobra.NoArgs, - Run: evacuateShard, + RunE: evacuateShard, } -func evacuateShard(cmd *cobra.Command, _ []string) { +func evacuateShard(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } req := &control.EvacuateShardRequest{Body: new(control.EvacuateShardRequest_Body)} - req.Body.Shard_ID = getShardIDList(cmd) + req.Body.Shard_ID, err = getShardIDList(cmd) + if err != nil { + return err + } req.Body.IgnoreErrors, _ = cmd.Flags().GetBool(dumpIgnoreErrorsFlag) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.EvacuateShardResponse - var err error err = cli.ExecRaw(func(client *client.Client) error { resp, err = control.EvacuateShard(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmd.Printf("Objects moved: %d\n", resp.GetBody().GetCount()) - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Shard has successfully been evacuated.") + return nil } func initControlEvacuateShardCmd() { diff --git a/cmd/neofs-cli/modules/control/flush_cache.go b/cmd/neofs-cli/modules/control/flush_cache.go index c1d7e741ec..58d3ad5f8a 100644 --- a/cmd/neofs-cli/modules/control/flush_cache.go +++ b/cmd/neofs-cli/modules/control/flush_cache.go @@ -1,8 +1,9 @@ package control import ( + "fmt" + "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" @@ -14,33 +15,50 @@ var flushCacheCmd = &cobra.Command{ Short: "Flush objects from the write-cache to the main storage", Long: "Flush objects from the write-cache to the main storage", Args: cobra.NoArgs, - Run: flushCache, + RunE: flushCache, } -func flushCache(cmd *cobra.Command, _ []string) { +func flushCache(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } req := &control.FlushCacheRequest{Body: new(control.FlushCacheRequest_Body)} - req.Body.Shard_ID = getShardIDList(cmd) + req.Body.Shard_ID, err = getShardIDList(cmd) + if err != nil { + return err + } - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.FlushCacheResponse - var err error err = cli.ExecRaw(func(client *client.Client) error { resp, err = control.FlushCache(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Write-cache has been flushed.") + return nil } func initControlFlushCacheCmd() { diff --git a/cmd/neofs-cli/modules/control/healthcheck.go b/cmd/neofs-cli/modules/control/healthcheck.go index 4cd4f1c49a..2e4206e0cc 100644 --- a/cmd/neofs-cli/modules/control/healthcheck.go +++ b/cmd/neofs-cli/modules/control/healthcheck.go @@ -2,10 +2,10 @@ package control import ( "crypto/ecdsa" + "fmt" "os" 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" @@ -24,7 +24,7 @@ var healthCheckCmd = &cobra.Command{ Short: "Health check of the NeoFS node", Long: "Health check of the NeoFS node. Checks storage node by default, use --ir flag to work with Inner Ring.", Args: cobra.NoArgs, - Run: healthCheck, + RunE: healthCheck, } func initControlHealthCheckCmd() { @@ -34,33 +34,45 @@ func initControlHealthCheckCmd() { flags.Bool(healthcheckIRFlag, false, "Communicate with IR node") } -func healthCheck(cmd *cobra.Command, _ []string) { +func healthCheck(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } if isIR, _ := cmd.Flags().GetBool(healthcheckIRFlag); isIR { - healthCheckIR(cmd, pk, cli) - return + return healthCheckIR(cmd, pk, cli) } req := new(control.HealthCheckRequest) req.SetBody(new(control.HealthCheckRequest_Body)) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } var resp *control.HealthCheckResponse - var err error err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.HealthCheck(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } healthStatus := resp.GetBody().GetHealthStatus() @@ -70,24 +82,32 @@ func healthCheck(cmd *cobra.Command, _ []string) { if healthStatus != control.HealthStatus_READY { os.Exit(1) } + return nil } -func healthCheckIR(cmd *cobra.Command, key *ecdsa.PrivateKey, c *client.Client) { +func healthCheckIR(cmd *cobra.Command, key *ecdsa.PrivateKey, c *client.Client) error { req := new(ircontrol.HealthCheckRequest) req.SetBody(new(ircontrol.HealthCheckRequest_Body)) err := ircontrolsrv.SignMessage(key, req) - common.ExitOnErr(cmd, "could not sign request: %w", err) + if err != nil { + return fmt.Errorf("could not sign request: %w", err) + } var resp *ircontrol.HealthCheckResponse err = c.ExecRaw(func(client *rawclient.Client) error { resp, err = ircontrol.HealthCheck(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } healthStatus := resp.GetBody().GetHealthStatus() @@ -96,4 +116,5 @@ func healthCheckIR(cmd *cobra.Command, key *ecdsa.PrivateKey, c *client.Client) if healthStatus != ircontrol.HealthStatus_READY { os.Exit(1) } + return nil } diff --git a/cmd/neofs-cli/modules/control/object_list.go b/cmd/neofs-cli/modules/control/object_list.go index 73a8f3cc20..4e08e59c1f 100644 --- a/cmd/neofs-cli/modules/control/object_list.go +++ b/cmd/neofs-cli/modules/control/object_list.go @@ -1,8 +1,9 @@ package control import ( + "fmt" + 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" @@ -14,34 +15,51 @@ var listObjectsCmd = &cobra.Command{ Short: "Get list of all objects in the storage node", Long: "Get list of all objects in the storage node", Args: cobra.NoArgs, - Run: listObjects, + RunE: listObjects, } func initControlObjectsListCmd() { initControlFlags(listObjectsCmd) } -func listObjects(cmd *cobra.Command, _ []string) { +func listObjects(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } req := &control.ListObjectsRequest{ Body: &control.ListObjectsRequest_Body{}, } - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } - err := cli.ExecRaw(func(client *rawclient.Client) error { - return control.ListObjects(client, req, func(r *control.ListObjectsResponse) { - verifyResponse(cmd, r.GetSignature(), r.GetBody()) + err = cli.ExecRaw(func(client *rawclient.Client) error { + return control.ListObjects(client, req, func(r *control.ListObjectsResponse) error { + err := verifyResponse(r.GetSignature(), r.GetBody()) + if err != nil { + return err + } for _, address := range r.GetBody().GetObjectAddress() { cmd.Println(string(address)) } + return nil }) }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } + + return nil } diff --git a/cmd/neofs-cli/modules/control/object_status.go b/cmd/neofs-cli/modules/control/object_status.go index 9394975542..5eed21e866 100644 --- a/cmd/neofs-cli/modules/control/object_status.go +++ b/cmd/neofs-cli/modules/control/object_status.go @@ -25,7 +25,10 @@ func objectStatus(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } addressRaw, err := cmd.Flags().GetString(objectFlag) if err != nil { return fmt.Errorf("reading %s flag: %w", objectFlag, err) @@ -43,9 +46,15 @@ func objectStatus(cmd *cobra.Command, _ []string) error { ObjectAddress: addressRaw, }, } - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.ObjectStatus(client, req) @@ -55,7 +64,10 @@ func objectStatus(cmd *cobra.Command, _ []string) error { return fmt.Errorf("rpc error: %w", err) } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } shards := resp.GetBody().GetShards() if len(shards) == 0 { diff --git a/cmd/neofs-cli/modules/control/set_netmap_status.go b/cmd/neofs-cli/modules/control/set_netmap_status.go index 06b7d6dc2a..2c23d1a3e6 100644 --- a/cmd/neofs-cli/modules/control/set_netmap_status.go +++ b/cmd/neofs-cli/modules/control/set_netmap_status.go @@ -24,7 +24,7 @@ var setNetmapStatusCmd = &cobra.Command{ Short: "Set status of the storage node in NeoFS network map", Long: "Set status of the storage node in NeoFS network map", Args: cobra.NoArgs, - Run: setNetmapStatus, + RunE: setNetmapStatus, } func initControlSetNetmapStatusCmd() { @@ -45,11 +45,14 @@ func initControlSetNetmapStatusCmd() { "Force turning to local maintenance") } -func setNetmapStatus(cmd *cobra.Command, _ []string) { +func setNetmapStatus(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } body := new(control.SetNetmapStatusRequest_Body) force, _ := cmd.Flags().GetBool(commonflags.ForceFlag) @@ -61,7 +64,7 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { switch st, _ := cmd.Flags().GetString(netmapStatusFlag); st { default: - common.ExitOnErr(cmd, "", fmt.Errorf("unsupported status %s", st)) + return fmt.Errorf("unsupported status %s", st) case netmapStatusOnline: body.SetStatus(control.NetmapStatus_ONLINE) printIgnoreForce(control.NetmapStatus_ONLINE) @@ -80,19 +83,30 @@ func setNetmapStatus(cmd *cobra.Command, _ []string) { req := new(control.SetNetmapStatusRequest) req.SetBody(body) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.SetNetmapStatusResponse - var err error err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.SetNetmapStatus(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Network status update request successfully sent.") + return nil } diff --git a/cmd/neofs-cli/modules/control/shards_dump.go b/cmd/neofs-cli/modules/control/shards_dump.go index 1f7dd0ea9e..aa76843586 100644 --- a/cmd/neofs-cli/modules/control/shards_dump.go +++ b/cmd/neofs-cli/modules/control/shards_dump.go @@ -1,8 +1,9 @@ package control import ( + "fmt" + "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" @@ -19,17 +20,24 @@ var dumpShardCmd = &cobra.Command{ Short: "Dump objects from shard", Long: "Dump objects from shard to a file", Args: cobra.NoArgs, - Run: dumpShard, + RunE: dumpShard, } -func dumpShard(cmd *cobra.Command, _ []string) { +func dumpShard(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } body := new(control.DumpShardRequest_Body) - body.SetShardID(getShardID(cmd)) + id, err := getShardID(cmd) + if err != nil { + return err + } + body.SetShardID(id) p, _ := cmd.Flags().GetString(dumpFilepathFlag) body.SetFilepath(p) @@ -40,21 +48,29 @@ func dumpShard(cmd *cobra.Command, _ []string) { req := new(control.DumpShardRequest) req.SetBody(body) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.DumpShardResponse - var err error err = cli.ExecRaw(func(client *client.Client) error { resp, err = control.DumpShard(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) cmd.Println("Shard has been dumped successfully.") + return nil } func initControlDumpShardCmd() { diff --git a/cmd/neofs-cli/modules/control/shards_list.go b/cmd/neofs-cli/modules/control/shards_list.go index 3fdc744bd5..5e8500917c 100644 --- a/cmd/neofs-cli/modules/control/shards_list.go +++ b/cmd/neofs-cli/modules/control/shards_list.go @@ -8,7 +8,6 @@ import ( "github.com/mr-tron/base58" 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" @@ -20,7 +19,7 @@ var listShardsCmd = &cobra.Command{ Short: "List shards of the storage node", Long: "List shards of the storage node", Args: cobra.NoArgs, - Run: listShards, + RunE: listShards, } func initControlShardsListCmd() { @@ -30,38 +29,54 @@ func initControlShardsListCmd() { flags.Bool(commonflags.JSON, false, "Print shard info as a JSON array") } -func listShards(cmd *cobra.Command, _ []string) { +func listShards(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } req := new(control.ListShardsRequest) req.SetBody(new(control.ListShardsRequest_Body)) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.ListShardsResponse - var err error err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.ListShards(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } isJSON, _ := cmd.Flags().GetBool(commonflags.JSON) if isJSON { - prettyPrintShardsJSON(cmd, resp.GetBody().GetShards()) + if err := prettyPrintShardsJSON(cmd, resp.GetBody().GetShards()); err != nil { + return err + } } else { prettyPrintShards(cmd, resp.GetBody().GetShards()) } + return nil } -func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { +func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) error { out := make([]map[string]any, 0, len(ii)) for _, i := range ii { out = append(out, map[string]any{ @@ -77,9 +92,12 @@ func prettyPrintShardsJSON(cmd *cobra.Command, ii []*control.ShardInfo) { buf := bytes.NewBuffer(nil) enc := json.NewEncoder(buf) enc.SetIndent("", " ") - common.ExitOnErr(cmd, "cannot shard info to JSON: %w", enc.Encode(out)) + if err := enc.Encode(out); err != nil { + return fmt.Errorf("cannot shard info to JSON: %w", err) + } cmd.Print(buf.String()) // pretty printer emits newline, to no need for Println + return nil } func prettyPrintShards(cmd *cobra.Command, ii []*control.ShardInfo) { diff --git a/cmd/neofs-cli/modules/control/shards_restore.go b/cmd/neofs-cli/modules/control/shards_restore.go index 036771e730..dee5b3d96e 100644 --- a/cmd/neofs-cli/modules/control/shards_restore.go +++ b/cmd/neofs-cli/modules/control/shards_restore.go @@ -1,8 +1,9 @@ package control import ( + "fmt" + "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" @@ -19,17 +20,24 @@ var restoreShardCmd = &cobra.Command{ Short: "Restore objects from shard", Long: "Restore objects from shard to a file", Args: cobra.NoArgs, - Run: restoreShard, + RunE: restoreShard, } -func restoreShard(cmd *cobra.Command, _ []string) { +func restoreShard(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } body := new(control.RestoreShardRequest_Body) - body.SetShardID(getShardID(cmd)) + id, err := getShardID(cmd) + if err != nil { + return err + } + body.SetShardID(id) p, _ := cmd.Flags().GetString(restoreFilepathFlag) body.SetFilepath(p) @@ -40,21 +48,32 @@ func restoreShard(cmd *cobra.Command, _ []string) { req := new(control.RestoreShardRequest) req.SetBody(body) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.RestoreShardResponse - var err error err = cli.ExecRaw(func(client *client.Client) error { resp, err = control.RestoreShard(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Shard has been restored successfully.") + return nil } func initControlRestoreShardCmd() { diff --git a/cmd/neofs-cli/modules/control/shards_set_mode.go b/cmd/neofs-cli/modules/control/shards_set_mode.go index 6ca8326e65..5901ed67fd 100644 --- a/cmd/neofs-cli/modules/control/shards_set_mode.go +++ b/cmd/neofs-cli/modules/control/shards_set_mode.go @@ -7,7 +7,6 @@ import ( "github.com/mr-tron/base58" 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" @@ -77,7 +76,7 @@ var setShardModeCmd = &cobra.Command{ Short: "Set work mode of the shard", Long: "Set work mode of the shard", Args: cobra.NoArgs, - Run: setShardMode, + RunE: setShardMode, } func initControlSetShardModeCmd() { @@ -101,17 +100,20 @@ func initControlSetShardModeCmd() { setShardModeCmd.MarkFlagsOneRequired(shardIDFlag, shardAllFlag) } -func setShardMode(cmd *cobra.Command, _ []string) { +func setShardMode(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) + if err != nil { + return err + } strMode, _ := cmd.Flags().GetString(shardModeFlag) mode, ok := lookUpShardModeFromString(strMode) if !ok { - common.ExitOnErr(cmd, "", fmt.Errorf("%w: setting %s mode", errors.ErrUnsupported, strMode)) + return fmt.Errorf("%w: setting %s mode", errors.ErrUnsupported, strMode) } req := new(control.SetShardModeRequest) @@ -120,39 +122,57 @@ func setShardMode(cmd *cobra.Command, _ []string) { req.SetBody(body) body.SetMode(mode) - body.SetShardIDList(getShardIDList(cmd)) + + list, err := getShardIDList(cmd) + if err != nil { + return err + } + body.SetShardIDList(list) reset, _ := cmd.Flags().GetBool(shardClearErrorsFlag) body.ClearErrorCounter(reset) - signRequest(cmd, pk, req) + err = signRequest(pk, req) + if err != nil { + return err + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.SetShardModeResponse - var err error err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.SetShardMode(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Shard mode update request successfully sent.") + return nil } -func getShardID(cmd *cobra.Command) []byte { +func getShardID(cmd *cobra.Command) ([]byte, error) { sid, _ := cmd.Flags().GetString(shardIDFlag) raw, err := base58.Decode(sid) - common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err) - return raw + if err != nil { + return nil, fmt.Errorf("incorrect shard ID encoding: %w", err) + } + return raw, nil } -func getShardIDList(cmd *cobra.Command) [][]byte { +func getShardIDList(cmd *cobra.Command) ([][]byte, error) { all, _ := cmd.Flags().GetBool(shardAllFlag) if all { - return nil + return nil, nil } sidList, _ := cmd.Flags().GetStringSlice(shardIDFlag) @@ -165,7 +185,7 @@ func getShardIDList(cmd *cobra.Command) [][]byte { seen := make(map[string]struct{}) for i := range sidList { if _, ok := seen[sidList[i]]; ok { - common.ExitOnErr(cmd, "", fmt.Errorf("duplicated shard IDs: %s", sidList[i])) + return nil, fmt.Errorf("duplicated shard IDs: %s", sidList[i]) } seen[sidList[i]] = struct{}{} } @@ -173,10 +193,12 @@ func getShardIDList(cmd *cobra.Command) [][]byte { res := make([][]byte, 0, len(sidList)) for i := range sidList { raw, err := base58.Decode(sidList[i]) - common.ExitOnErr(cmd, "incorrect shard ID encoding: %w", err) + if err != nil { + return nil, fmt.Errorf("incorrect shard ID encoding: %w", err) + } res = append(res, raw) } - return res + return res, nil } diff --git a/cmd/neofs-cli/modules/control/synchronize_tree.go b/cmd/neofs-cli/modules/control/synchronize_tree.go index e883fff56c..f2e1540974 100644 --- a/cmd/neofs-cli/modules/control/synchronize_tree.go +++ b/cmd/neofs-cli/modules/control/synchronize_tree.go @@ -3,9 +3,9 @@ package control import ( "crypto/sha256" "errors" + "fmt" 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" @@ -24,7 +24,7 @@ var synchronizeTreeCmd = &cobra.Command{ Short: "Synchronize log for the tree", Long: "Synchronize log for the tree in an object tree service.", Args: cobra.NoArgs, - Run: synchronizeTree, + RunE: synchronizeTree, } func initControlSynchronizeTreeCmd() { @@ -36,19 +36,21 @@ func initControlSynchronizeTreeCmd() { flags.Uint64(synchronizeTreeHeightFlag, 0, "Starting height") } -func synchronizeTree(cmd *cobra.Command, _ []string) { +func synchronizeTree(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.Get(cmd) + pk, err := key.Get(cmd) var cnr cid.ID cidStr, _ := cmd.Flags().GetString(commonflags.CIDFlag) - common.ExitOnErr(cmd, "can't decode container ID: %w", cnr.DecodeString(cidStr)) + if err := cnr.DecodeString(cidStr); err != nil { + return fmt.Errorf("can't decode container ID: %w", err) + } treeID, _ := cmd.Flags().GetString("tree-id") if treeID == "" { - common.ExitOnErr(cmd, "", errors.New("tree ID must not be empty")) + return errors.New("tree ID must not be empty") } height, _ := cmd.Flags().GetUint64("height") @@ -64,19 +66,30 @@ func synchronizeTree(cmd *cobra.Command, _ []string) { }, } - err := controlSvc.SignMessage(pk, req) - common.ExitOnErr(cmd, "could not sign request: %w", err) + err = controlSvc.SignMessage(pk, req) + if err != nil { + return fmt.Errorf("could not sign request: %w", err) + } - cli := getClient(ctx, cmd) + cli, err := getClient(ctx) + if err != nil { + return err + } var resp *control.SynchronizeTreeResponse err = cli.ExecRaw(func(client *rawclient.Client) error { resp, err = control.SynchronizeTree(client, req) return err }) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } - verifyResponse(cmd, resp.GetSignature(), resp.GetBody()) + err = verifyResponse(resp.GetSignature(), resp.GetBody()) + if err != nil { + return err + } cmd.Println("Tree has been synchronized successfully.") + return nil } diff --git a/cmd/neofs-cli/modules/control/util.go b/cmd/neofs-cli/modules/control/util.go index c006691a16..ec01353681 100644 --- a/cmd/neofs-cli/modules/control/util.go +++ b/cmd/neofs-cli/modules/control/util.go @@ -4,9 +4,9 @@ import ( "context" "crypto/ecdsa" "errors" + "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" controlSvc "github.com/nspcc-dev/neofs-node/pkg/services/control/server" "github.com/nspcc-dev/neofs-sdk-go/client" @@ -23,34 +23,35 @@ func initControlFlags(cmd *cobra.Command) { ff.DurationP(commonflags.Timeout, commonflags.TimeoutShorthand, commonflags.TimeoutDefault, commonflags.TimeoutUsage) } -func signRequest(cmd *cobra.Command, pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) { +func signRequest(pk *ecdsa.PrivateKey, req controlSvc.SignedMessage) error { err := controlSvc.SignMessage(pk, req) - common.ExitOnErr(cmd, "could not sign request: %w", err) + if err != nil { + return fmt.Errorf("could not sign request: %w", err) + } + return nil } -func verifyResponse(cmd *cobra.Command, - sigControl interface { - GetKey() []byte - GetSign() []byte - }, - body interface { - StableMarshal([]byte) []byte - }, -) { +func verifyResponse(sigControl interface { + GetKey() []byte + GetSign() []byte +}, body interface{ StableMarshal([]byte) []byte }) error { if sigControl == nil { - common.ExitOnErr(cmd, "", errors.New("missing response signature")) + return errors.New("missing response signature") } var pubKey neofsecdsa.PublicKey - common.ExitOnErr(cmd, "decode public key from signature: %w", pubKey.Decode(sigControl.GetKey())) + if err := pubKey.Decode(sigControl.GetKey()); err != nil { + return fmt.Errorf("decode public key from signature: %w", err) + } sig := neofscrypto.NewSignature(neofscrypto.ECDSA_SHA512, &pubKey, sigControl.GetSign()) if !sig.Verify(body.StableMarshal(nil)) { - common.ExitOnErr(cmd, "", errors.New("invalid response signature")) + return errors.New("invalid response signature") } + return nil } -func getClient(ctx context.Context, cmd *cobra.Command) *client.Client { - return internalclient.GetSDKClientByFlag(ctx, cmd, controlRPC) +func getClient(ctx context.Context) (*client.Client, error) { + return internalclient.GetSDKClientByFlag(ctx, controlRPC) } diff --git a/cmd/neofs-cli/modules/netmap/get_epoch.go b/cmd/neofs-cli/modules/netmap/get_epoch.go index 6975b299c6..b28376a393 100644 --- a/cmd/neofs-cli/modules/netmap/get_epoch.go +++ b/cmd/neofs-cli/modules/netmap/get_epoch.go @@ -1,8 +1,9 @@ package netmap 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" "github.com/spf13/cobra" ) @@ -12,21 +13,27 @@ var getEpochCmd = &cobra.Command{ Short: "Get current epoch number", Long: "Get current epoch number", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.NetworkInfoPrm prm.SetClient(cli) res, err := internalclient.NetworkInfo(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } netInfo := res.NetworkInfo() cmd.Println(netInfo.CurrentEpoch()) + return nil }, } diff --git a/cmd/neofs-cli/modules/netmap/netinfo.go b/cmd/neofs-cli/modules/netmap/netinfo.go index 62c98c50a9..4085b81653 100644 --- a/cmd/neofs-cli/modules/netmap/netinfo.go +++ b/cmd/neofs-cli/modules/netmap/netinfo.go @@ -2,11 +2,11 @@ package netmap import ( "encoding/hex" + "fmt" "time" "github.com/nspcc-dev/neo-go/pkg/config/netmode" 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" "github.com/spf13/cobra" ) @@ -17,17 +17,22 @@ var netInfoCmd = &cobra.Command{ Long: `Get information about NeoFS network. Unknown configuration settings are displayed in hexadecimal format.`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.NetworkInfoPrm prm.SetClient(cli) res, err := internalclient.NetworkInfo(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } netInfo := res.NetworkInfo() @@ -58,6 +63,7 @@ var netInfoCmd = &cobra.Command{ netInfo.IterateRawNetworkParameters(func(name string, value []byte) { cmd.Printf(format, name, hex.EncodeToString(value)) }) + return nil }, } diff --git a/cmd/neofs-cli/modules/netmap/nodeinfo.go b/cmd/neofs-cli/modules/netmap/nodeinfo.go index eded4e3083..c6d3f9b52e 100644 --- a/cmd/neofs-cli/modules/netmap/nodeinfo.go +++ b/cmd/neofs-cli/modules/netmap/nodeinfo.go @@ -2,6 +2,7 @@ package netmap import ( "encoding/hex" + "fmt" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -17,19 +18,25 @@ var nodeInfoCmd = &cobra.Command{ Short: "Get target node info", Long: `Get target node info`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.NodeInfoPrm prm.SetClient(cli) res, err := internalclient.NodeInfo(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } prettyPrintNodeInfo(cmd, res.NodeInfo()) + return nil }, } diff --git a/cmd/neofs-cli/modules/netmap/snapshot.go b/cmd/neofs-cli/modules/netmap/snapshot.go index 01479f544b..664e1a7750 100644 --- a/cmd/neofs-cli/modules/netmap/snapshot.go +++ b/cmd/neofs-cli/modules/netmap/snapshot.go @@ -1,9 +1,10 @@ package netmap import ( + "fmt" + "github.com/nspcc-dev/neofs-node/cmd/internal/cmdprinter" 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" "github.com/spf13/cobra" ) @@ -13,19 +14,25 @@ var snapshotCmd = &cobra.Command{ Short: "Request current local snapshot of the network map", Long: `Request current local snapshot of the network map`, Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.NetMapSnapshotPrm prm.SetClient(cli) res, err := internalclient.NetMapSnapshot(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmdprinter.PrettyPrintNetMap(cmd, res.NetMap()) + return nil }, } diff --git a/cmd/neofs-cli/modules/object/delete.go b/cmd/neofs-cli/modules/object/delete.go index 8f22d957c3..f0615df98a 100644 --- a/cmd/neofs-cli/modules/object/delete.go +++ b/cmd/neofs-cli/modules/object/delete.go @@ -4,7 +4,6 @@ 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -18,7 +17,7 @@ var objectDelCmd = &cobra.Command{ Short: "Delete object from NeoFS", Long: "Delete object from NeoFS", Args: cobra.NoArgs, - Run: deleteObject, + RunE: deleteObject, } func initObjectDeleteCmd() { @@ -36,7 +35,7 @@ func initObjectDeleteCmd() { _ = objectDelCmd.MarkFlagRequired(commonflags.OIDFlag) } -func deleteObject(cmd *cobra.Command, _ []string) { +func deleteObject(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() @@ -47,17 +46,23 @@ func deleteObject(cmd *cobra.Command, _ []string) { if binary { filename, _ := cmd.Flags().GetString(fileFlag) if filename == "" { - common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", fileFlag)) + return fmt.Errorf("required flag \"%s\" not set", fileFlag) } var obj oid.ID - objAddr := readObjectAddressBin(cmd, &cnr, &obj, filename) + objAddr, err := readObjectAddressBin(&cnr, &obj, filename) + if err != nil { + return err + } objAddrs = []oid.Address{objAddr} } else { - readCID(cmd, &cnr) + err := readCID(cmd, &cnr) + if err != nil { + return err + } oIDVals, _ := cmd.Flags().GetStringSlice(commonflags.OIDFlag) if len(oIDVals) == 0 { - common.ExitOnErr(cmd, "", fmt.Errorf("provide at least one object via %s flag", commonflags.OIDFlag)) + return fmt.Errorf("provide at least one object via %s flag", commonflags.OIDFlag) } var obj oid.ID @@ -66,29 +71,43 @@ func deleteObject(cmd *cobra.Command, _ []string) { for _, oIDraw := range oIDVals { err := obj.DecodeString(oIDraw) - common.ExitOnErr(cmd, "decode object ID ("+oIDraw+") string: %w", err) + if err != nil { + return fmt.Errorf("decode object ID (\"+oIDraw+\") string: %w", err) + } objAddr.SetObject(obj) objAddrs = append(objAddrs, objAddr) } } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } var prm internalclient.DeleteObjectPrm prm.SetPrivateKey(*pk) - Prepare(cmd, &prm) + err = Prepare(cmd, &prm) + if err != nil { + return err + } for _, addr := range objAddrs { - ReadOrOpenSession(ctx, cmd, &prm, pk, cnr, addr.Object()) + err := ReadOrOpenSession(ctx, cmd, &prm, pk, cnr, addr.Object()) + if err != nil { + return err + } prm.SetAddress(addr) res, err := internalclient.DeleteObject(ctx, prm) - common.ExitOnErr(cmd, "rpc error: deleting "+addr.Object().String()+" object: %w", err) + if err != nil { + return fmt.Errorf("rpc error: deleting \"+addr.Object().String()+\" object: %w", err) + } tomb := res.Tombstone() cmd.Printf("Object %s removed successfully.\n", addr.Object()) cmd.Printf(" ID: %s\n CID: %s\n", tomb, cnr) } + return nil } diff --git a/cmd/neofs-cli/modules/object/get.go b/cmd/neofs-cli/modules/object/get.go index 81b8fbc4db..c8091fd668 100644 --- a/cmd/neofs-cli/modules/object/get.go +++ b/cmd/neofs-cli/modules/object/get.go @@ -8,7 +8,6 @@ import ( "github.com/cheggaaa/pb" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -22,7 +21,7 @@ var objectGetCmd = &cobra.Command{ Short: "Get object from NeoFS", Long: "Get object from NeoFS", Args: cobra.NoArgs, - Run: getObject, + RunE: getObject, } func initObjectGetCmd() { @@ -43,14 +42,17 @@ func initObjectGetCmd() { flags.Bool(binaryFlag, false, "Serialize whole object structure into given file(id + signature + header + payload).") } -func getObject(cmd *cobra.Command, _ []string) { +func getObject(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } var out io.Writer filename := cmd.Flag(fileFlag).Value.String() @@ -59,7 +61,7 @@ func getObject(cmd *cobra.Command, _ []string) { } else { f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0o644) if err != nil { - common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err)) + return fmt.Errorf("can't open file '%s': %w", filename, err) } defer f.Close() @@ -67,15 +69,27 @@ func getObject(cmd *cobra.Command, _ []string) { out = f } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.GetObjectPrm prm.SetClient(cli) prm.SetPrivateKey(*pk) - Prepare(cmd, &prm) - readSession(cmd, &prm, pk, cnr, obj) + err = Prepare(cmd, &prm) + if err != nil { + return err + } + err = readSession(cmd, &prm, pk, cnr, obj) + if err != nil { + return err + } raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) @@ -111,11 +125,12 @@ func getObject(cmd *cobra.Command, _ []string) { p.Finish() } if err != nil { - if ok := printSplitInfoErr(cmd, err); ok { - return + if ok, err := printSplitInfoErr(cmd, err); ok { + return err + } + if err != nil { + return fmt.Errorf("rpc error: %w", err) } - - common.ExitOnErr(cmd, "rpc error: %w", err) } if binary { @@ -124,7 +139,9 @@ func getObject(cmd *cobra.Command, _ []string) { objToStore.SetPayload(payloadBuffer.Bytes()) objBytes := objToStore.Marshal() _, err = out.Write(objBytes) - common.ExitOnErr(cmd, "unable to write binary object in out: %w ", err) + if err != nil { + return fmt.Errorf("unable to write binary object in out: %w", err) + } } if filename != "" && !strictOutput(cmd) { @@ -134,8 +151,11 @@ func getObject(cmd *cobra.Command, _ []string) { // Print header only if file is not streamed to stdout. if filename != "" { err = printHeader(cmd, res.Header()) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } } + return nil } func strictOutput(cmd *cobra.Command) bool { diff --git a/cmd/neofs-cli/modules/object/hash.go b/cmd/neofs-cli/modules/object/hash.go index 066e57b220..45dc968bbe 100644 --- a/cmd/neofs-cli/modules/object/hash.go +++ b/cmd/neofs-cli/modules/object/hash.go @@ -6,7 +6,6 @@ import ( "strings" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-sdk-go/checksum" @@ -28,7 +27,7 @@ var objectHashCmd = &cobra.Command{ Short: "Get object hash", Long: "Get object hash", Args: cobra.NoArgs, - Run: getObjectHash, + RunE: getObjectHash, } func initObjectHashCmd() { @@ -48,27 +47,42 @@ func initObjectHashCmd() { flags.String(getRangeHashSaltFlag, "", "Salt in hex format") } -func getObjectHash(cmd *cobra.Command, _ []string) { +func getObjectHash(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } ranges, err := getRangeList(cmd) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } typ, err := getHashType(cmd) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } strSalt := strings.TrimPrefix(cmd.Flag(getRangeHashSaltFlag).Value.String(), "0x") salt, err := hex.DecodeString(strSalt) - common.ExitOnErr(cmd, "could not decode salt: %w", err) + if err != nil { + return fmt.Errorf("could not decode salt: %w", err) + } - pk := key.GetOrGenerate(cmd) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } tz := typ == hashTz fullHash := len(ranges) == 0 @@ -76,12 +90,17 @@ func getObjectHash(cmd *cobra.Command, _ []string) { var headPrm internalclient.HeadObjectPrm headPrm.SetPrivateKey(*pk) headPrm.SetClient(cli) - Prepare(cmd, &headPrm) + err = Prepare(cmd, &headPrm) + if err != nil { + return err + } headPrm.SetAddress(objAddr) // get hash of full payload through HEAD (may be user can do it through dedicated command?) res, err := internalclient.HeadObject(ctx, headPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } var cs checksum.Checksum var csSet bool @@ -98,14 +117,20 @@ func getObjectHash(cmd *cobra.Command, _ []string) { cmd.Println("Missing checksum in object header.") } - return + return nil } var hashPrm internalclient.HashPayloadRangesPrm hashPrm.SetClient(cli) hashPrm.SetPrivateKey(*pk) - Prepare(cmd, &hashPrm) - readSession(cmd, &hashPrm, pk, cnr, obj) + err = Prepare(cmd, &hashPrm) + if err != nil { + return err + } + err = readSession(cmd, &hashPrm, pk, cnr, obj) + if err != nil { + return err + } hashPrm.SetAddress(objAddr) hashPrm.SetSalt(salt) hashPrm.SetRanges(ranges) @@ -115,7 +140,9 @@ func getObjectHash(cmd *cobra.Command, _ []string) { } res, err := internalclient.HashPayloadRanges(ctx, hashPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } hs := res.HashList() @@ -123,6 +150,7 @@ func getObjectHash(cmd *cobra.Command, _ []string) { cmd.Printf("Offset=%d (Length=%d)\t: %s\n", ranges[i].GetOffset(), ranges[i].GetLength(), hex.EncodeToString(hs[i])) } + return nil } func getHashType(cmd *cobra.Command) (string, error) { diff --git a/cmd/neofs-cli/modules/object/head.go b/cmd/neofs-cli/modules/object/head.go index 170487379a..5494ca9e2a 100644 --- a/cmd/neofs-cli/modules/object/head.go +++ b/cmd/neofs-cli/modules/object/head.go @@ -21,7 +21,7 @@ var objectHeadCmd = &cobra.Command{ Short: "Get object header", Long: "Get object header", Args: cobra.NoArgs, - Run: getObjectHeader, + RunE: getObjectHeader, } func initObjectHeadCmd() { @@ -43,24 +43,39 @@ func initObjectHeadCmd() { flags.Bool(rawFlag, false, rawFlagDesc) } -func getObjectHeader(cmd *cobra.Command, _ []string) { +func getObjectHeader(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } mainOnly, _ := cmd.Flags().GetBool("main-only") - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.HeadObjectPrm prm.SetClient(cli) prm.SetPrivateKey(*pk) - Prepare(cmd, &prm) - readSession(cmd, &prm, pk, cnr, obj) + err = Prepare(cmd, &prm) + if err != nil { + return err + } + err = readSession(cmd, &prm, pk, cnr, obj) + if err != nil { + return err + } raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) @@ -69,15 +84,20 @@ func getObjectHeader(cmd *cobra.Command, _ []string) { res, err := internalclient.HeadObject(ctx, prm) if err != nil { - if ok := printSplitInfoErr(cmd, err); ok { - return + if ok, err := printSplitInfoErr(cmd, err); ok { + return err + } + if err != nil { + return fmt.Errorf("rpc error: %w", err) } - - common.ExitOnErr(cmd, "rpc error: %w", err) } err = saveAndPrintHeader(cmd, res.Header(), cmd.Flag(fileFlag).Value.String()) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } + + return nil } func saveAndPrintHeader(cmd *cobra.Command, obj *object.Object, filename string) error { diff --git a/cmd/neofs-cli/modules/object/lock.go b/cmd/neofs-cli/modules/object/lock.go index 2d623855a1..4b0e597a22 100644 --- a/cmd/neofs-cli/modules/object/lock.go +++ b/cmd/neofs-cli/modules/object/lock.go @@ -23,7 +23,7 @@ var objectLockCmd = &cobra.Command{ Short: "Lock object in container", Long: "Lock object in container", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() @@ -31,7 +31,9 @@ var objectLockCmd = &cobra.Command{ var cnr cid.ID err := cnr.DecodeString(cidRaw) - common.ExitOnErr(cmd, "Incorrect container arg: %v", err) + if err != nil { + return fmt.Errorf("Incorrect container arg: %v", err) + } oidsRaw, _ := cmd.Flags().GetStringSlice(commonflags.OIDFlag) @@ -39,10 +41,15 @@ var objectLockCmd = &cobra.Command{ for i := range oidsRaw { err = lockList[i].DecodeString(oidsRaw[i]) - common.ExitOnErr(cmd, fmt.Sprintf("Incorrect object arg #%d: %%v", i+1), err) + if err != nil { + return fmt.Errorf(fmt.Sprintf("Incorrect object arg #%d: %%v", i+1), err) + } } - key := key.GetOrGenerate(cmd) + key, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } idOwner := user.ResolveFromECDSAPublicKey(key.PublicKey) @@ -59,7 +66,9 @@ var objectLockCmd = &cobra.Command{ endpoint, _ := cmd.Flags().GetString(commonflags.RPC) currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint) - common.ExitOnErr(cmd, "Request current epoch: %w", err) + if err != nil { + return fmt.Errorf("Request current epoch: %w", err) + } exp = currEpoch + lifetime } @@ -79,15 +88,27 @@ var objectLockCmd = &cobra.Command{ var prm internalclient.PutObjectPrm prm.SetPrivateKey(*key) - ReadOrOpenSession(ctx, cmd, &prm, key, cnr) - Prepare(cmd, &prm) + + err = ReadOrOpenSession(ctx, cmd, &prm, key, cnr) + if err != nil { + return err + } + + err = Prepare(cmd, &prm) + if err != nil { + return err + } prm.SetHeader(obj) res, err := internalclient.PutObject(ctx, prm) - common.ExitOnErr(cmd, "Store lock object in NeoFS: %w", err) + if err != nil { + return fmt.Errorf("Store lock object in NeoFS: %w", err) + } cmd.Printf("Lock object ID: %s\n", res.ID()) cmd.Println("Objects successfully locked.") + + return nil }, } diff --git a/cmd/neofs-cli/modules/object/nodes.go b/cmd/neofs-cli/modules/object/nodes.go index 190f12cd8f..7fbd068f5e 100644 --- a/cmd/neofs-cli/modules/object/nodes.go +++ b/cmd/neofs-cli/modules/object/nodes.go @@ -1,9 +1,10 @@ package object import ( + "fmt" + "github.com/nspcc-dev/neofs-node/cmd/internal/cmdprinter" 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" "github.com/nspcc-dev/neofs-node/pkg/morph/client/netmap" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -22,40 +23,57 @@ var objectNodesCmd = &cobra.Command{ Short: "Show nodes for an object", Long: "Show nodes taking part in an object placement at the current epoch.", Args: cobra.NoArgs, - Run: func(cmd *cobra.Command, _ []string) { + RunE: func(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnrID cid.ID - readCID(cmd, &cnrID) + err := readCID(cmd, &cnrID) + if err != nil { + return err + } var oID oid.ID - readOID(cmd, &oID) + err = readOID(cmd, &oID) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prmSnap internalclient.NetMapSnapshotPrm prmSnap.SetClient(cli) resmap, err := internalclient.NetMapSnapshot(ctx, prmSnap) - common.ExitOnErr(cmd, "could not get netmap snapshot", err) + if err != nil { + return fmt.Errorf("could not get netmap snapshot: %w", err) + } var prmCnr internalclient.GetContainerPrm prmCnr.SetClient(cli) prmCnr.SetContainer(cnrID) res, err := internalclient.GetContainer(ctx, prmCnr) - common.ExitOnErr(cmd, "could not get container: %w", err) + if err != nil { + return fmt.Errorf("could not get container: %w", err) + } cnr := res.Container() policy := cnr.PlacementPolicy() var cnrNodes [][]netmap.NodeInfo cnrNodes, err = resmap.NetMap().ContainerNodes(policy, cnrID) - common.ExitOnErr(cmd, "could not build container nodes for the given container: %w", err) + if err != nil { + return fmt.Errorf("could not build container nodes for the given container: %w", err) + } placementNodes, err := resmap.NetMap().PlacementVectors(cnrNodes, oID) - common.ExitOnErr(cmd, "could not build placement nodes for the given container: %w", err) + if err != nil { + return fmt.Errorf("could not build placement nodes for the given container: %w", err) + } short, _ := cmd.Flags().GetBool(shortFlag) @@ -65,6 +83,8 @@ var objectNodesCmd = &cobra.Command{ cmdprinter.PrettyPrintNodeInfo(cmd, placementNodes[i][j], j, "\t", short) } } + + return nil }, } diff --git a/cmd/neofs-cli/modules/object/put.go b/cmd/neofs-cli/modules/object/put.go index 49ee1c5063..e3176d0f1d 100644 --- a/cmd/neofs-cli/modules/object/put.go +++ b/cmd/neofs-cli/modules/object/put.go @@ -12,7 +12,6 @@ import ( "github.com/cheggaaa/pb" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -32,7 +31,7 @@ var objectPutCmd = &cobra.Command{ Short: "Put object to NeoFS", Long: "Put object to NeoFS", Args: cobra.NoArgs, - Run: putObject, + RunE: putObject, } func initObjectPutCmd() { @@ -58,7 +57,7 @@ func initObjectPutCmd() { objectPutCmd.MarkFlagsMutuallyExclusive(commonflags.ExpireAt, commonflags.Lifetime) } -func putObject(cmd *cobra.Command, _ []string) { +func putObject(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() @@ -66,9 +65,12 @@ func putObject(cmd *cobra.Command, _ []string) { cidVal, _ := cmd.Flags().GetString(commonflags.CIDFlag) if !binary && cidVal == "" { - common.ExitOnErr(cmd, "", fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag)) + return fmt.Errorf("required flag \"%s\" not set", commonflags.CIDFlag) + } + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err } - pk := key.GetOrGenerate(cmd) var ownerID user.ID var cnr cid.ID @@ -76,39 +78,52 @@ func putObject(cmd *cobra.Command, _ []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)) + return 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) + if err != nil { + return fmt.Errorf("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)) + if err := objTemp.Unmarshal(buf); err != nil { + return fmt.Errorf("can't unmarshal object from given file: %w", err) + } payloadReader = bytes.NewReader(objTemp.Payload()) cnr, _ = objTemp.ContainerID() ownerID = *objTemp.OwnerID() } else { fi, err := f.Stat() - common.ExitOnErr(cmd, "read file stat: %w", err) + if err != nil { + return fmt.Errorf("read file stat: %w", err) + } obj.SetPayloadSize(uint64(fi.Size())) - readCID(cmd, &cnr) + err = readCID(cmd, &cnr) + if err != nil { + return err + } ownerID = user.ResolveFromECDSAPublicKey(pk.PublicKey) } attrs, err := parseObjectAttrs(cmd) - common.ExitOnErr(cmd, "can't parse object attributes: %w", err) + if err != nil { + return fmt.Errorf("can't parse object attributes: %w", err) + } expiresOn, _ := cmd.Flags().GetUint64(commonflags.ExpireAt) lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime) if lifetime > 0 { endpoint, _ := cmd.Flags().GetString(commonflags.RPC) currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint) - common.ExitOnErr(cmd, "Request current epoch: %w", err) + if err != nil { + return fmt.Errorf("Request current epoch: %w", err) + } expiresOn = currEpoch + lifetime } @@ -139,8 +154,14 @@ func putObject(cmd *cobra.Command, _ []string) { var prm internalclient.PutObjectPrm prm.SetPrivateKey(*pk) - ReadOrOpenSession(ctx, cmd, &prm, pk, cnr) - Prepare(cmd, &prm) + err = ReadOrOpenSession(ctx, cmd, &prm, pk, cnr) + if err != nil { + return err + } + err = Prepare(cmd, &prm) + if err != nil { + return err + } prm.SetHeader(obj) var p *pb.ProgressBar @@ -174,17 +195,23 @@ func putObject(cmd *cobra.Command, _ []string) { if p != nil { p.Finish() } - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmd.Printf("[%s] Object successfully stored\n", filename) cmd.Printf(" OID: %s\n CID: %s\n", res.ID(), cnr) + + return nil } func parseObjectAttrs(cmd *cobra.Command) ([]object.Attribute, error) { var rawAttrs []string rawAttrs, err := cmd.Flags().GetStringSlice("attributes") - common.ExitOnErr(cmd, "can't get attributes: %w", err) + if err != nil { + return nil, fmt.Errorf("can't get attributes: %w", err) + } attrs := make([]object.Attribute, len(rawAttrs), len(rawAttrs)+2) // name + timestamp attributes for i := range rawAttrs { diff --git a/cmd/neofs-cli/modules/object/range.go b/cmd/neofs-cli/modules/object/range.go index bbe216679c..96fbd2b0a4 100644 --- a/cmd/neofs-cli/modules/object/range.go +++ b/cmd/neofs-cli/modules/object/range.go @@ -10,7 +10,6 @@ import ( "strings" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -24,7 +23,7 @@ var objectRangeCmd = &cobra.Command{ Short: "Get payload range data of an object", Long: "Get payload range data of an object", Args: cobra.NoArgs, - Run: getObjectRange, + RunE: getObjectRange, } func initObjectRangeCmd() { @@ -44,20 +43,25 @@ func initObjectRangeCmd() { flags.Bool(rawFlag, false, rawFlagDesc) } -func getObjectRange(cmd *cobra.Command, _ []string) { +func getObjectRange(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID var obj oid.ID - objAddr := readObjectAddress(cmd, &cnr, &obj) + objAddr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } ranges, err := getRangeList(cmd) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } if len(ranges) != 1 { - common.ExitOnErr(cmd, "", fmt.Errorf("exactly one range must be specified, got: %d", len(ranges))) + return fmt.Errorf("exactly one range must be specified, got: %d", len(ranges)) } var out io.Writer @@ -68,7 +72,7 @@ func getObjectRange(cmd *cobra.Command, _ []string) { } else { f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm) if err != nil { - common.ExitOnErr(cmd, "", fmt.Errorf("can't open file '%s': %w", filename, err)) + return fmt.Errorf("can't open file '%s': %w", filename, err) } defer f.Close() @@ -76,15 +80,27 @@ func getObjectRange(cmd *cobra.Command, _ []string) { out = f } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.PayloadRangePrm prm.SetClient(cli) prm.SetPrivateKey(*pk) - Prepare(cmd, &prm) - readSession(cmd, &prm, pk, cnr, obj) + err = Prepare(cmd, &prm) + if err != nil { + return err + } + err = readSession(cmd, &prm, pk, cnr, obj) + if err != nil { + return err + } raw, _ := cmd.Flags().GetBool(rawFlag) prm.SetRawFlag(raw) @@ -94,36 +110,45 @@ func getObjectRange(cmd *cobra.Command, _ []string) { _, err = internalclient.PayloadRange(ctx, prm) if err != nil { - if ok := printSplitInfoErr(cmd, err); ok { - return + if ok, err := printSplitInfoErr(cmd, err); ok { + return err } - common.ExitOnErr(cmd, "can't get object payload range: %w", err) + if err != nil { + return fmt.Errorf("can't get object payload range: %w", err) + } } if filename != "" { cmd.Printf("[%s] Payload successfully saved\n", filename) } + + return nil } -func printSplitInfoErr(cmd *cobra.Command, err error) bool { +func printSplitInfoErr(cmd *cobra.Command, err error) (bool, error) { var errSplitInfo *object.SplitInfoError ok := errors.As(err, &errSplitInfo) if ok { cmd.PrintErrln("Object is complex, split information received.") - printSplitInfo(cmd, errSplitInfo.SplitInfo()) + if err := printSplitInfo(cmd, errSplitInfo.SplitInfo()); err != nil { + return false, err + } } - return ok + return ok, nil } -func printSplitInfo(cmd *cobra.Command, info *object.SplitInfo) { +func printSplitInfo(cmd *cobra.Command, info *object.SplitInfo) error { bs, err := marshalSplitInfo(cmd, info) - common.ExitOnErr(cmd, "can't marshal split info: %w", err) + if err != nil { + return fmt.Errorf("can't marshal split info: %w", err) + } cmd.Println(string(bs)) + return nil } func marshalSplitInfo(cmd *cobra.Command, info *object.SplitInfo) ([]byte, error) { diff --git a/cmd/neofs-cli/modules/object/search.go b/cmd/neofs-cli/modules/object/search.go index 3059db53e2..6cb208f28f 100644 --- a/cmd/neofs-cli/modules/object/search.go +++ b/cmd/neofs-cli/modules/object/search.go @@ -7,7 +7,6 @@ import ( "strings" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" @@ -24,7 +23,7 @@ var ( Short: "Search object", Long: "Search object", Args: cobra.NoArgs, - Run: searchObject, + RunE: searchObject, } ) @@ -45,30 +44,51 @@ func initObjectSearchCmd() { flags.String(commonflags.OIDFlag, "", "Search object by identifier") } -func searchObject(cmd *cobra.Command, _ []string) { +func searchObject(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID - readCID(cmd, &cnr) + err := readCID(cmd, &cnr) + if err != nil { + return err + } sf, err := parseSearchFilters(cmd) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.SearchObjectsPrm prm.SetClient(cli) prm.SetPrivateKey(*pk) - Prepare(cmd, &prm) - readSessionGlobal(cmd, &prm, pk, cnr) + err = Prepare(cmd, &prm) + if err != nil { + return err + } + + err = readSessionGlobal(cmd, &prm, pk, cnr) + if err != nil { + return err + } + prm.SetContainerID(cnr) prm.SetFilters(sf) res, err := internalclient.SearchObjects(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } ids := res.IDList() @@ -76,6 +96,8 @@ func searchObject(cmd *cobra.Command, _ []string) { for i := range ids { cmd.Println(ids[i].String()) } + + return nil } var searchUnaryOpVocabulary = map[string]object.SearchMatchType{ diff --git a/cmd/neofs-cli/modules/object/util.go b/cmd/neofs-cli/modules/object/util.go index 38deaa0015..2b9b372232 100644 --- a/cmd/neofs-cli/modules/object/util.go +++ b/cmd/neofs-cli/modules/object/util.go @@ -46,17 +46,21 @@ func InitBearer(cmd *cobra.Command) { } // Prepare prepares object-related parameters for a command. -func Prepare(cmd *cobra.Command, prms ...RPCParameters) { +func Prepare(cmd *cobra.Command, prms ...RPCParameters) error { ttl := viper.GetUint32(commonflags.TTL) common.PrintVerbose(cmd, "TTL: %d", ttl) for i := range prms { - btok := common.ReadBearerToken(cmd, bearerTokenFlag) + btok, err := common.ReadBearerToken(cmd, bearerTokenFlag) + if err != nil { + return err + } prms[i].SetBearerToken(btok) prms[i].SetTTL(ttl) prms[i].SetXHeaders(parseXHeaders(cmd)) } + return nil } func parseXHeaders(cmd *cobra.Command) []string { @@ -75,38 +79,53 @@ func parseXHeaders(cmd *cobra.Command) []string { return xs } -func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address { - readCID(cmd, cnr) - readOID(cmd, obj) +func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) (oid.Address, error) { + err := readCID(cmd, cnr) + if err != nil { + return oid.Address{}, err + } + err = readOID(cmd, obj) + if err != nil { + return oid.Address{}, err + } var addr oid.Address addr.SetContainer(*cnr) addr.SetObject(*obj) - return addr + return addr, nil } -func readObjectAddressBin(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID, filename string) oid.Address { +func readObjectAddressBin(cnr *cid.ID, obj *oid.ID, filename string) (oid.Address, error) { buf, err := os.ReadFile(filename) - common.ExitOnErr(cmd, "unable to read given file: %w", err) + if err != nil { + return oid.Address{}, fmt.Errorf("unable to read given file: %w", err) + } objTemp := object.New() - common.ExitOnErr(cmd, "can't unmarshal object from given file: %w", objTemp.Unmarshal(buf)) + if err := objTemp.Unmarshal(buf); err != nil { + return oid.Address{}, fmt.Errorf("can't unmarshal object from given file: %w", err) + } var addr oid.Address *cnr, _ = objTemp.ContainerID() *obj, _ = objTemp.ID() addr.SetContainer(*cnr) addr.SetObject(*obj) - return addr + return addr, nil } -func readCID(cmd *cobra.Command, id *cid.ID) { +func readCID(cmd *cobra.Command, id *cid.ID) error { err := id.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String()) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } + return nil } -func readOID(cmd *cobra.Command, id *oid.ID) { - err := id.DecodeString(cmd.Flag(commonflags.OIDFlag).Value.String()) - common.ExitOnErr(cmd, "decode object ID string: %w", err) +func readOID(cmd *cobra.Command, id *oid.ID) error { + if err := id.DecodeString(cmd.Flag(commonflags.OIDFlag).Value.String()); err != nil { + return fmt.Errorf("decode object ID string: %w", err) + } + return nil } // SessionPrm is a common interface of object operation's input which supports @@ -117,24 +136,24 @@ type SessionPrm interface { } // forwards all parameters to _readVerifiedSession and object as nil. -func readSessionGlobal(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID) { - _readVerifiedSession(cmd, dst, key, cnr, nil) +func readSessionGlobal(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID) error { + return _readVerifiedSession(cmd, dst, key, cnr, nil) } // forwards all parameters to _readVerifiedSession. -func readSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj oid.ID) { - _readVerifiedSession(cmd, dst, key, cnr, &obj) +func readSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj oid.ID) error { + return _readVerifiedSession(cmd, dst, key, cnr, &obj) } // decodes session.Object from the file by path specified in the // commonflags.SessionToken flag. Returns nil if flag is not set. -func getSession(cmd *cobra.Command) *session.Object { +func getSession(cmd *cobra.Command) (*session.Object, error) { common.PrintVerbose(cmd, "Trying to read session from the file...") path, _ := cmd.Flags().GetString(commonflags.SessionToken) if path == "" { common.PrintVerbose(cmd, "File with session token is not provided.") - return nil + return nil, nil } common.PrintVerbose(cmd, "Reading session from the file [%s]...", path) @@ -142,9 +161,11 @@ func getSession(cmd *cobra.Command) *session.Object { var tok session.Object err := common.ReadBinaryOrJSON(cmd, &tok, path) - common.ExitOnErr(cmd, "read session: %v", err) + if err != nil { + return nil, fmt.Errorf("read session: %v", err) + } - return &tok + return &tok, nil } // decodes object session from JSON file from commonflags.SessionToken command @@ -164,7 +185,7 @@ func getSession(cmd *cobra.Command) *session.Object { // *internal.SearchObjectsPrm // *internal.PayloadRangePrm // *internal.HashPayloadRangesPrm -func _readVerifiedSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) { +func _readVerifiedSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, obj *oid.ID) error { var cmdVerb session.ObjectVerb switch dst.(type) { @@ -182,56 +203,84 @@ func _readVerifiedSession(cmd *cobra.Command, dst SessionPrm, key *ecdsa.Private cmdVerb = session.VerbObjectRangeHash } - tok := getSession(cmd) + tok, err := getSession(cmd) + if err != nil { + return err + } if tok == nil { - return + return nil } common.PrintVerbose(cmd, "Checking session correctness...") switch false { case tok.AssertContainer(cnr): - common.ExitOnErr(cmd, "", errors.New("unrelated container in the session")) + return errors.New("unrelated container in the session") case obj == nil || tok.AssertObject(*obj): - common.ExitOnErr(cmd, "", errors.New("unrelated object in the session")) + return errors.New("unrelated object in the session") case tok.AssertVerb(cmdVerb): - common.ExitOnErr(cmd, "", errors.New("wrong verb of the session")) + return errors.New("wrong verb of the session") case tok.AssertAuthKey((*neofsecdsa.PublicKey)(&key.PublicKey)): - common.ExitOnErr(cmd, "", errors.New("unrelated key in the session")) + return errors.New("unrelated key in the session") case tok.VerifySignature(): - common.ExitOnErr(cmd, "", errors.New("invalid signature of the session data")) + return errors.New("invalid signature of the session data") } common.PrintVerbose(cmd, "Session is correct.") dst.SetSessionToken(tok) + return nil } // ReadOrOpenSession opens client connection and calls ReadOrOpenSessionViaClient with it. -func ReadOrOpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) { - cli := internal.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) - ReadOrOpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) +func ReadOrOpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) error { + cli, err := internal.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } + err = ReadOrOpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) + if err != nil { + return err + } + return nil } // ReadOrOpenSessionViaClient tries to read session from the file specified in // commonflags.SessionToken flag, finalizes structures of the decoded token // and write the result into provided SessionPrm. If file is missing, // ReadOrOpenSessionViaClient calls OpenSessionViaClient. -func ReadOrOpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) { - tok := getSession(cmd) +func ReadOrOpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) error { + tok, err := getSession(cmd) + if err != nil { + return err + } if tok == nil { - OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) - return + err = OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) + if err != nil { + return err + } + return nil } - finalizeSession(cmd, dst, tok, key, cnr, objs...) + err = finalizeSession(cmd, dst, tok, key, cnr, objs...) + if err != nil { + return err + } dst.SetClient(cli) + return nil } // OpenSession opens client connection and calls OpenSessionViaClient with it. -func OpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) { - cli := internal.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) - OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) +func OpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) error { + cli, err := internal.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } + err = OpenSessionViaClient(ctx, cmd, dst, cli, key, cnr, objs...) + if err != nil { + return err + } + return nil } // OpenSessionViaClient opens object session with the remote node, finalizes @@ -242,23 +291,31 @@ func OpenSession(ctx context.Context, cmd *cobra.Command, dst SessionPrm, key *e // // *internal.PutObjectPrm // *internal.DeleteObjectPrm -func OpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) { +func OpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPrm, cli *client.Client, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) error { var tok session.Object const sessionLifetime = 10 // in NeoFS epochs common.PrintVerbose(cmd, "Opening remote session with the node...") currEpoch, err := internal.GetCurrentEpoch(ctx, viper.GetString(commonflags.RPC)) - common.ExitOnErr(cmd, "can't fetch current epoch: %w", err) + if err != nil { + return fmt.Errorf("can't fetch current epoch: %w", err) + } exp := currEpoch + sessionLifetime err = sessionCli.CreateSession(ctx, &tok, cli, *key, exp, currEpoch) - common.ExitOnErr(cmd, "open remote session: %w", err) + if err != nil { + return fmt.Errorf("open remote session: %w", err) + } common.PrintVerbose(cmd, "Session successfully opened.") - finalizeSession(cmd, dst, &tok, key, cnr, objs...) + err = finalizeSession(cmd, dst, &tok, key, cnr, objs...) + if err != nil { + return err + } dst.SetClient(cli) + return nil } // specifies session verb, binds the session to the given container and limits @@ -270,7 +327,7 @@ func OpenSessionViaClient(ctx context.Context, cmd *cobra.Command, dst SessionPr // // *internal.PutObjectPrm // *internal.DeleteObjectPrm -func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) { +func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, key *ecdsa.PrivateKey, cnr cid.ID, objs ...oid.ID) error { common.PrintVerbose(cmd, "Finalizing session token...") switch dst.(type) { @@ -295,11 +352,14 @@ func finalizeSession(cmd *cobra.Command, dst SessionPrm, tok *session.Object, ke common.PrintVerbose(cmd, "Signing session...") err := tok.Sign(user.NewAutoIDSigner(*key)) - common.ExitOnErr(cmd, "sign session: %w", err) + if err != nil { + return fmt.Errorf("sign session: %w", err) + } common.PrintVerbose(cmd, "Session token successfully formed and attached to the request.") dst.SetSessionToken(tok) + return nil } // calls commonflags.InitSession with "object " name. diff --git a/cmd/neofs-cli/modules/root.go b/cmd/neofs-cli/modules/root.go index 7c93b397a2..34b7f1e5dc 100644 --- a/cmd/neofs-cli/modules/root.go +++ b/cmd/neofs-cli/modules/root.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/mitchellh/go-homedir" + "github.com/nspcc-dev/neofs-node/cmd/internal/cmderr" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags" accountingCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/accounting" @@ -44,14 +45,13 @@ of neofs-api and some useful utilities for compiling ACL rules from JSON notation, managing container access through protocol gates, querying network map and much more!`, Args: cobra.NoArgs, - Run: entryPoint, + RunE: entryPoint, } // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - err := rootCmd.Execute() - common.ExitOnErr(rootCmd, "", err) +func Execute() error { + return rootCmd.Execute() } func init() { @@ -87,15 +87,15 @@ func init() { rootCmd.AddCommand(gendoc.Command(rootCmd)) } -func entryPoint(cmd *cobra.Command, _ []string) { +func entryPoint(cmd *cobra.Command, _ []string) error { printVersion, _ := cmd.Flags().GetBool("version") if printVersion { cmd.Print(misc.BuildInfo("NeoFS CLI")) - return + return nil } - _ = cmd.Usage() + return cmd.Usage() } // initConfig reads in config file and ENV variables if set. @@ -106,7 +106,7 @@ func initConfig() { } else { // Find home directory. home, err := homedir.Dir() - common.ExitOnErr(rootCmd, "", err) + cmderr.ExitOnErr(err) // Search config in `$HOME/.config/neofs-cli/` with name "config.yaml" viper.AddConfigPath(filepath.Join(home, ".config", "neofs-cli")) diff --git a/cmd/neofs-cli/modules/session/create.go b/cmd/neofs-cli/modules/session/create.go index c30fe781af..943fb3b6d5 100644 --- a/cmd/neofs-cli/modules/session/create.go +++ b/cmd/neofs-cli/modules/session/create.go @@ -10,7 +10,6 @@ import ( "github.com/google/uuid" 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" "github.com/nspcc-dev/neofs-node/pkg/network" @@ -37,7 +36,7 @@ Default lifetime of session token is ` + strconv.Itoa(defaultLifetime) + ` epoch if none of --` + commonflags.ExpireAt + ` or --` + commonflags.Lifetime + ` flags is specified. `, Args: cobra.NoArgs, - Run: createSession, + RunE: createSession, PersistentPreRun: func(cmd *cobra.Command, _ []string) { _ = viper.BindPFlag(commonflags.WalletPath, cmd.Flags().Lookup(commonflags.WalletPath)) _ = viper.BindPFlag(commonflags.Account, cmd.Flags().Lookup(commonflags.Account)) @@ -59,21 +58,30 @@ func init() { createCmd.MarkFlagsOneRequired(commonflags.ExpireAt, commonflags.Lifetime) } -func createSession(cmd *cobra.Command, _ []string) { +func createSession(cmd *cobra.Command, _ []string) error { ctx := context.Background() - privKey := key.Get(cmd) + privKey, err := key.Get(cmd) + if err != nil { + return err + } var netAddr network.Address addrStr, _ := cmd.Flags().GetString(commonflags.RPC) - common.ExitOnErr(cmd, "can't parse endpoint: %w", netAddr.FromString(addrStr)) + if err := netAddr.FromString(addrStr); err != nil { + return fmt.Errorf("can't parse endpoint: %w", err) + } c, err := internalclient.GetSDKClient(ctx, netAddr) - common.ExitOnErr(cmd, "can't create client: %w", err) + if err != nil { + return fmt.Errorf("can't create client: %w", err) + } endpoint, _ := cmd.Flags().GetString(commonflags.RPC) currEpoch, err := internalclient.GetCurrentEpoch(ctx, endpoint) - common.ExitOnErr(cmd, "can't get current epoch: %w", err) + if err != nil { + return fmt.Errorf("can't get current epoch: %w", err) + } var exp uint64 if exp, _ = cmd.Flags().GetUint64(commonflags.ExpireAt); exp == 0 { @@ -81,24 +89,32 @@ func createSession(cmd *cobra.Command, _ []string) { exp = currEpoch + lifetime } if exp <= currEpoch { - common.ExitOnErr(cmd, "", errors.New("expiration epoch must be greater than current epoch")) + return errors.New("expiration epoch must be greater than current epoch") } var tok session.Object err = CreateSession(ctx, &tok, c, *privKey, exp, currEpoch) - common.ExitOnErr(cmd, "can't create session: %w", err) + if err != nil { + return fmt.Errorf("can't create session: %w", err) + } var data []byte if toJSON, _ := cmd.Flags().GetBool(jsonFlag); toJSON { data, err = tok.MarshalJSON() - common.ExitOnErr(cmd, "can't decode session token JSON: %w", err) + if err != nil { + return fmt.Errorf("can't decode session token JSON: %w", err) + } } else { data = tok.Marshal() } filename, _ := cmd.Flags().GetString(outFlag) err = os.WriteFile(filename, data, 0o644) - common.ExitOnErr(cmd, "can't write token to file: %w", err) + if err != nil { + return fmt.Errorf("can't write token to file: %w", err) + } + + return nil } // CreateSession opens a new communication with NeoFS storage node using client connection. diff --git a/cmd/neofs-cli/modules/storagegroup/delete.go b/cmd/neofs-cli/modules/storagegroup/delete.go index 270f80f941..bea792c4ac 100644 --- a/cmd/neofs-cli/modules/storagegroup/delete.go +++ b/cmd/neofs-cli/modules/storagegroup/delete.go @@ -1,8 +1,9 @@ package storagegroup 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object" @@ -16,7 +17,7 @@ var sgDelCmd = &cobra.Command{ Short: "Delete storage group from NeoFS", Long: "Delete storage group from NeoFS", Args: cobra.NoArgs, - Run: delSG, + RunE: delSG, } func initSGDeleteCmd() { @@ -31,28 +32,44 @@ func initSGDeleteCmd() { _ = sgDelCmd.MarkFlagRequired(sgIDFlag) } -func delSG(cmd *cobra.Command, _ []string) { +func delSG(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } var cnr cid.ID var obj oid.ID - addr := readObjectAddress(cmd, &cnr, &obj) + addr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } var prm internalclient.DeleteObjectPrm prm.SetPrivateKey(*pk) - objectCli.OpenSession(ctx, cmd, &prm, pk, cnr, obj) - objectCli.Prepare(cmd, &prm) + err = objectCli.OpenSession(ctx, cmd, &prm, pk, cnr, obj) + if err != nil { + return err + } + err = objectCli.Prepare(cmd, &prm) + if err != nil { + return err + } prm.SetAddress(addr) res, err := internalclient.DeleteObject(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } tombstone := res.Tombstone() cmd.Println("Storage group removed successfully.") cmd.Printf(" Tombstone: %s\n", tombstone) + + return nil } diff --git a/cmd/neofs-cli/modules/storagegroup/get.go b/cmd/neofs-cli/modules/storagegroup/get.go index 2c3c492f51..f399f7d9e4 100644 --- a/cmd/neofs-cli/modules/storagegroup/get.go +++ b/cmd/neofs-cli/modules/storagegroup/get.go @@ -2,6 +2,7 @@ package storagegroup import ( "bytes" + "fmt" internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -21,7 +22,7 @@ var sgGetCmd = &cobra.Command{ Short: "Get storage group from NeoFS", Long: "Get storage group from NeoFS", Args: cobra.NoArgs, - Run: getSG, + RunE: getSG, } func initSGGetCmd() { @@ -38,21 +39,33 @@ func initSGGetCmd() { flags.Bool(sgRawFlag, false, "Set raw request option") } -func getSG(cmd *cobra.Command, _ []string) { +func getSG(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID var obj oid.ID - addr := readObjectAddress(cmd, &cnr, &obj) - pk := key.GetOrGenerate(cmd) + addr, err := readObjectAddress(cmd, &cnr, &obj) + if err != nil { + return err + } + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } buf := bytes.NewBuffer(nil) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.GetObjectPrm - objectCli.Prepare(cmd, &prm) + err = objectCli.Prepare(cmd, &prm) + if err != nil { + return err + } prm.SetClient(cli) prm.SetPrivateKey(*pk) @@ -62,7 +75,9 @@ func getSG(cmd *cobra.Command, _ []string) { prm.SetPayloadWriter(buf) res, err := internalclient.GetObject(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } rawObj := res.Header() rawObj.SetPayload(buf.Bytes()) @@ -70,7 +85,9 @@ func getSG(cmd *cobra.Command, _ []string) { var sg storagegroupSDK.StorageGroup err = storagegroupSDK.ReadFromObject(&sg, *rawObj) - common.ExitOnErr(cmd, "could not read storage group from the obj: %w", err) + if err != nil { + return fmt.Errorf("could not read storage group from the obj: %w", err) + } cmd.Printf("The last active epoch: %d\n", sg.ExpirationEpoch()) cmd.Printf("Group size: %d\n", sg.ValidationDataSize()) @@ -83,4 +100,6 @@ func getSG(cmd *cobra.Command, _ []string) { cmd.Printf("\t%s\n", members[i].String()) } } + + return nil } diff --git a/cmd/neofs-cli/modules/storagegroup/list.go b/cmd/neofs-cli/modules/storagegroup/list.go index ad7cd9ff49..c543eddffc 100644 --- a/cmd/neofs-cli/modules/storagegroup/list.go +++ b/cmd/neofs-cli/modules/storagegroup/list.go @@ -1,8 +1,9 @@ package storagegroup 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object" @@ -16,7 +17,7 @@ var sgListCmd = &cobra.Command{ Short: "List storage groups in NeoFS container", Long: "List storage groups in NeoFS container", Args: cobra.NoArgs, - Run: listSG, + RunE: listSG, } func initSGListCmd() { @@ -26,26 +27,40 @@ func initSGListCmd() { _ = sgListCmd.MarkFlagRequired(commonflags.CIDFlag) } -func listSG(cmd *cobra.Command, _ []string) { +func listSG(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() var cnr cid.ID - readCID(cmd, &cnr) + err := readCID(cmd, &cnr) + if err != nil { + return err + } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } var prm internalclient.SearchObjectsPrm - objectCli.Prepare(cmd, &prm) + err = objectCli.Prepare(cmd, &prm) + if err != nil { + return err + } prm.SetClient(cli) prm.SetPrivateKey(*pk) prm.SetContainerID(cnr) prm.SetFilters(storagegroup.SearchQuery()) res, err := internalclient.SearchObjects(ctx, prm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } ids := res.IDList() @@ -54,4 +69,6 @@ func listSG(cmd *cobra.Command, _ []string) { for i := range ids { cmd.Println(ids[i].String()) } + + return nil } diff --git a/cmd/neofs-cli/modules/storagegroup/put.go b/cmd/neofs-cli/modules/storagegroup/put.go index fa4ddc492f..b19eec9311 100644 --- a/cmd/neofs-cli/modules/storagegroup/put.go +++ b/cmd/neofs-cli/modules/storagegroup/put.go @@ -7,7 +7,6 @@ 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" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key" objectCli "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/object" @@ -30,7 +29,7 @@ var sgPutCmd = &cobra.Command{ Short: "Put storage group to NeoFS", Long: "Put storage group to NeoFS", Args: cobra.NoArgs, - Run: putSG, + RunE: putSG, } func initSGPutCmd() { @@ -49,29 +48,37 @@ func initSGPutCmd() { sgPutCmd.MarkFlagsOneRequired(commonflags.ExpireAt, commonflags.Lifetime) } -func putSG(cmd *cobra.Command, _ []string) { +func putSG(cmd *cobra.Command, _ []string) error { // Track https://github.com/nspcc-dev/neofs-node/issues/2595. exp, _ := cmd.Flags().GetUint64(commonflags.ExpireAt) lifetime, _ := cmd.Flags().GetUint64(commonflags.Lifetime) ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } ownerID := user.ResolveFromECDSAPublicKey(pk.PublicKey) var cnr cid.ID - readCID(cmd, &cnr) + err = readCID(cmd, &cnr) + if err != nil { + return err + } members := make([]oid.ID, len(sgMembers)) uniqueFilter := make(map[oid.ID]struct{}, len(sgMembers)) for i := range sgMembers { err := members[i].DecodeString(sgMembers[i]) - common.ExitOnErr(cmd, "could not parse object ID: %w", err) + if err != nil { + return fmt.Errorf("could not parse object ID: %w", err) + } if _, alreadyExists := uniqueFilter[members[i]]; alreadyExists { - common.ExitOnErr(cmd, "", fmt.Errorf("%s member in not unique", members[i])) + return fmt.Errorf("%s member in not unique", members[i]) } uniqueFilter[members[i]] = struct{}{} @@ -84,15 +91,26 @@ func putSG(cmd *cobra.Command, _ []string) { getPrm internalclient.GetObjectPrm ) - cli := internalclient.GetSDKClientByFlag(ctx, cmd, commonflags.RPC) + cli, err := internalclient.GetSDKClientByFlag(ctx, commonflags.RPC) + if err != nil { + return err + } getCnrPrm.SetClient(cli) getCnrPrm.SetContainer(cnr) resGetCnr, err := internalclient.GetContainer(ctx, getCnrPrm) - common.ExitOnErr(cmd, "get container RPC call: %w", err) + if err != nil { + return fmt.Errorf("get container RPC call: %w", err) + } - objectCli.OpenSessionViaClient(ctx, cmd, &putPrm, cli, pk, cnr) - objectCli.Prepare(cmd, &headPrm, &putPrm) + err = objectCli.OpenSessionViaClient(ctx, cmd, &putPrm, cli, pk, cnr) + if err != nil { + return err + } + err = objectCli.Prepare(cmd, &headPrm, &putPrm) + if err != nil { + return err + } headPrm.SetRawFlag(true) headPrm.SetClient(cli) @@ -101,7 +119,10 @@ func putSG(cmd *cobra.Command, _ []string) { headPrm.SetRawFlag(true) getPrm.SetClient(cli) getPrm.SetPrivateKey(*pk) - objectCli.Prepare(cmd, &getPrm) + err = objectCli.Prepare(cmd, &getPrm) + if err != nil { + return err + } sg, err := storagegroup.CollectMembers(sgHeadReceiver{ ctx: ctx, @@ -112,14 +133,18 @@ func putSG(cmd *cobra.Command, _ []string) { cli: cli, getPrm: getPrm, }, cnr, members, !resGetCnr.Container().IsHomomorphicHashingDisabled()) - common.ExitOnErr(cmd, "could not collect storage group members: %w", err) + if err != nil { + return fmt.Errorf("could not collect storage group members: %w", err) + } if lifetime != 0 { var netInfoPrm internalclient.NetworkInfoPrm netInfoPrm.SetClient(cli) ni, err := internalclient.NetworkInfo(ctx, netInfoPrm) - common.ExitOnErr(cmd, "can't fetch network info: %w", err) + if err != nil { + return fmt.Errorf("can't fetch network info: %w", err) + } currEpoch := ni.NetworkInfo().CurrentEpoch() exp = currEpoch + lifetime } @@ -136,10 +161,14 @@ func putSG(cmd *cobra.Command, _ []string) { putPrm.SetHeader(obj) res, err := internalclient.PutObject(ctx, putPrm) - common.ExitOnErr(cmd, "rpc error: %w", err) + if err != nil { + return fmt.Errorf("rpc error: %w", err) + } cmd.Println("Storage group successfully stored") cmd.Printf(" ID: %s\n CID: %s\n", res.ID(), cnr) + + return nil } type sgHeadReceiver struct { diff --git a/cmd/neofs-cli/modules/storagegroup/util.go b/cmd/neofs-cli/modules/storagegroup/util.go index da97198df2..3a6dcdffa6 100644 --- a/cmd/neofs-cli/modules/storagegroup/util.go +++ b/cmd/neofs-cli/modules/storagegroup/util.go @@ -3,43 +3,54 @@ package storagegroup 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" ) -func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) oid.Address { - readCID(cmd, cnr) - readSGID(cmd, obj) +func readObjectAddress(cmd *cobra.Command, cnr *cid.ID, obj *oid.ID) (oid.Address, error) { + err := readCID(cmd, cnr) + if err != nil { + return oid.Address{}, err + } + err = readSGID(cmd, obj) + if err != nil { + return oid.Address{}, err + } var addr oid.Address addr.SetContainer(*cnr) addr.SetObject(*obj) - return addr + return addr, nil } -func readCID(cmd *cobra.Command, id *cid.ID) { +func readCID(cmd *cobra.Command, id *cid.ID) error { f := cmd.Flag(commonflags.CIDFlag) if f == nil { - common.ExitOnErr(cmd, "", fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag)) - return + return fmt.Errorf("missing container flag (%s)", commonflags.CIDFlag) } err := id.DecodeString(f.Value.String()) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } + + return nil } -func readSGID(cmd *cobra.Command, id *oid.ID) { +func readSGID(cmd *cobra.Command, id *oid.ID) error { const flag = "id" f := cmd.Flag(flag) if f == nil { - common.ExitOnErr(cmd, "", fmt.Errorf("missing storage group flag (%s)", flag)) - return + return fmt.Errorf("missing storage group flag (%s)", flag) } err := id.DecodeString(f.Value.String()) - common.ExitOnErr(cmd, "decode storage group ID string: %w", err) + if err != nil { + return fmt.Errorf("decode storage group ID string: %w", err) + } + + return nil } diff --git a/cmd/neofs-cli/modules/tree/add.go b/cmd/neofs-cli/modules/tree/add.go index d2a778fef4..464a39dea5 100644 --- a/cmd/neofs-cli/modules/tree/add.go +++ b/cmd/neofs-cli/modules/tree/add.go @@ -5,7 +5,6 @@ import ( "fmt" "strings" - "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/tree" @@ -16,7 +15,7 @@ import ( var addCmd = &cobra.Command{ Use: "add", Short: "Add a node to the tree service", - Run: add, + RunE: add, Args: cobra.NoArgs, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) @@ -34,24 +33,33 @@ func initAddCmd() { _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } -func add(cmd *cobra.Command, _ []string) { +func add(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } var cnr cid.ID - err := cnr.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String()) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + err = cnr.DecodeString(cmd.Flag(commonflags.CIDFlag).Value.String()) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } tid, _ := cmd.Flags().GetString(treeIDFlagKey) pid, _ := cmd.Flags().GetUint64(parentIDFlagKey) meta, err := parseMeta(cmd) - common.ExitOnErr(cmd, "meta data parsing: %w", err) + if err != nil { + return fmt.Errorf("meta data parsing: %w", err) + } cli, err := _client() - common.ExitOnErr(cmd, "client: %w", err) + if err != nil { + return fmt.Errorf("client: %w", err) + } rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) @@ -65,12 +73,18 @@ func add(cmd *cobra.Command, _ []string) { BearerToken: nil, // TODO: #1891 add token handling } - common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk)) + if err := tree.SignMessage(req, pk); err != nil { + return fmt.Errorf("message signing: %w", err) + } resp, err := cli.Add(ctx, req) - common.ExitOnErr(cmd, "rpc call: %w", err) + if err != nil { + return fmt.Errorf("rpc call: %w", err) + } cmd.Println("Node ID: ", resp.Body.NodeId) + + return nil } func parseMeta(cmd *cobra.Command) ([]*tree.KeyValue, error) { diff --git a/cmd/neofs-cli/modules/tree/add_by_path.go b/cmd/neofs-cli/modules/tree/add_by_path.go index a4c22b3366..8d080063dc 100644 --- a/cmd/neofs-cli/modules/tree/add_by_path.go +++ b/cmd/neofs-cli/modules/tree/add_by_path.go @@ -2,6 +2,7 @@ package tree import ( "crypto/sha256" + "fmt" "strings" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -17,7 +18,7 @@ var addByPathCmd = &cobra.Command{ Use: "add-by-path", Short: "Add a node by the path", Args: cobra.NoArgs, - Run: addByPath, + RunE: addByPath, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) }, @@ -40,28 +41,37 @@ func initAddByPathCmd() { _ = cobra.MarkFlagRequired(ff, pathFlagKey) } -func addByPath(cmd *cobra.Command, _ []string) { +func addByPath(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID - err := cnr.DecodeString(cidRaw) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + err = cnr.DecodeString(cidRaw) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } tid, _ := cmd.Flags().GetString(treeIDFlagKey) cli, err := _client() - common.ExitOnErr(cmd, "client: %w", err) + if err != nil { + return fmt.Errorf("client: %w", err) + } rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) meta, err := parseMeta(cmd) - common.ExitOnErr(cmd, "meta data parsing: %w", err) + if err != nil { + return fmt.Errorf("meta data parsing: %w", err) + } path, _ := cmd.Flags().GetString(pathFlagKey) //pAttr, _ := cmd.Flags().GetString(pathAttributeFlagKey) @@ -77,21 +87,27 @@ func addByPath(cmd *cobra.Command, _ []string) { BearerToken: nil, // TODO: #1891 add token handling } - common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk)) + if err := tree.SignMessage(req, pk); err != nil { + return fmt.Errorf("message signing: %w", err) + } resp, err := cli.AddByPath(ctx, req) - common.ExitOnErr(cmd, "rpc call: %w", err) + if err != nil { + return fmt.Errorf("rpc call: %w", err) + } cmd.Printf("Parent ID: %d\n", resp.GetBody().GetParentId()) nn := resp.GetBody().GetNodes() if len(nn) == 0 { common.PrintVerbose(cmd, "No new nodes were created") - return + return nil } cmd.Println("Created nodes:") for _, node := range resp.GetBody().GetNodes() { cmd.Printf("\t%d\n", node) } + + return nil } diff --git a/cmd/neofs-cli/modules/tree/get_by_path.go b/cmd/neofs-cli/modules/tree/get_by_path.go index b0a0f9af1c..9e1c981bfd 100644 --- a/cmd/neofs-cli/modules/tree/get_by_path.go +++ b/cmd/neofs-cli/modules/tree/get_by_path.go @@ -2,6 +2,7 @@ package tree import ( "crypto/sha256" + "fmt" "strings" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -17,7 +18,7 @@ var getByPathCmd = &cobra.Command{ Use: "get-by-path", Short: "Get a node by its path", Args: cobra.NoArgs, - Run: getByPath, + RunE: getByPath, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) }, @@ -40,22 +41,29 @@ func initGetByPathCmd() { _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } -func getByPath(cmd *cobra.Command, _ []string) { +func getByPath(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } cidRaw, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID - err := cnr.DecodeString(cidRaw) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + err = cnr.DecodeString(cidRaw) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } tid, _ := cmd.Flags().GetString(treeIDFlagKey) cli, err := _client() - common.ExitOnErr(cmd, "client: %w", err) + if err != nil { + return fmt.Errorf("client: %w", err) + } rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) @@ -76,15 +84,19 @@ func getByPath(cmd *cobra.Command, _ []string) { BearerToken: nil, // TODO: #1891 add token handling } - common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk)) + if err := tree.SignMessage(req, pk); err != nil { + return fmt.Errorf("message signing: %w", err) + } resp, err := cli.GetNodeByPath(ctx, req) - common.ExitOnErr(cmd, "rpc call: %w", err) + if err != nil { + return fmt.Errorf("rpc call: %w", err) + } nn := resp.GetBody().GetNodes() if len(nn) == 0 { common.PrintVerbose(cmd, "The node is not found") - return + return nil } for _, n := range nn { @@ -98,4 +110,6 @@ func getByPath(cmd *cobra.Command, _ []string) { cmd.Printf("\t\t%s: %s\n", kv.GetKey(), string(kv.GetValue())) } } + + return nil } diff --git a/cmd/neofs-cli/modules/tree/list.go b/cmd/neofs-cli/modules/tree/list.go index b4ef8d0d35..c6eec1f57f 100644 --- a/cmd/neofs-cli/modules/tree/list.go +++ b/cmd/neofs-cli/modules/tree/list.go @@ -2,8 +2,8 @@ package tree import ( "crypto/sha256" + "fmt" - "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/tree" @@ -15,7 +15,7 @@ var listCmd = &cobra.Command{ Use: "list", Short: "Get tree IDs", Args: cobra.NoArgs, - Run: list, + RunE: list, PersistentPreRun: func(cmd *cobra.Command, _ []string) { commonflags.Bind(cmd) }, @@ -31,19 +31,26 @@ func initListCmd() { _ = cobra.MarkFlagRequired(ff, commonflags.RPC) } -func list(cmd *cobra.Command, _ []string) { +func list(cmd *cobra.Command, _ []string) error { ctx, cancel := commonflags.GetCommandContext(cmd) defer cancel() - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } cidString, _ := cmd.Flags().GetString(commonflags.CIDFlag) var cnr cid.ID - err := cnr.DecodeString(cidString) - common.ExitOnErr(cmd, "decode container ID string: %w", err) + err = cnr.DecodeString(cidString) + if err != nil { + return fmt.Errorf("decode container ID string: %w", err) + } cli, err := _client() - common.ExitOnErr(cmd, "client: %w", err) + if err != nil { + return fmt.Errorf("client: %w", err) + } rawCID := make([]byte, sha256.Size) cnr.Encode(rawCID) @@ -54,12 +61,18 @@ func list(cmd *cobra.Command, _ []string) { }, } - common.ExitOnErr(cmd, "message signing: %w", tree.SignMessage(req, pk)) + if err := tree.SignMessage(req, pk); err != nil { + return fmt.Errorf("message signing: %w", err) + } resp, err := cli.TreeList(ctx, req) - common.ExitOnErr(cmd, "rpc call: %w", err) + if err != nil { + return fmt.Errorf("rpc call: %w", err) + } for _, treeID := range resp.GetBody().GetIds() { cmd.Println(treeID) } + + return nil } diff --git a/cmd/neofs-cli/modules/util/convert_eacl.go b/cmd/neofs-cli/modules/util/convert_eacl.go index 8b66c6d54b..00523f2fb2 100644 --- a/cmd/neofs-cli/modules/util/convert_eacl.go +++ b/cmd/neofs-cli/modules/util/convert_eacl.go @@ -1,6 +1,7 @@ package util import ( + "fmt" "os" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -12,7 +13,7 @@ var convertEACLCmd = &cobra.Command{ Use: "eacl", Short: "Convert representation of extended ACL table", Args: cobra.NoArgs, - Run: convertEACLTable, + RunE: convertEACLTable, } func initConvertEACLCmd() { @@ -26,29 +27,37 @@ func initConvertEACLCmd() { flags.Bool(commonflags.JSON, false, "Dump extended ACL table in JSON encoding") } -func convertEACLTable(cmd *cobra.Command, _ []string) { +func convertEACLTable(cmd *cobra.Command, _ []string) error { pathFrom := cmd.Flag("from").Value.String() to := cmd.Flag("to").Value.String() jsonFlag, _ := cmd.Flags().GetBool(commonflags.JSON) - table := common.ReadEACL(cmd, pathFrom) + table, err := common.ReadEACL(cmd, pathFrom) + if err != nil { + return err + } var data []byte - var err error if jsonFlag || len(to) == 0 { data, err = table.MarshalJSON() - common.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err) + if err != nil { + return fmt.Errorf("can't JSON encode extended ACL table: %w", err) + } } else { data = table.Marshal() } if len(to) == 0 { common.PrettyPrintJSON(cmd, table, "eACL") - return + return nil } err = os.WriteFile(to, data, 0o644) - common.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err) + if err != nil { + return fmt.Errorf("can't write exteded ACL table to file: %w", err) + } cmd.Printf("extended ACL table was successfully dumped to %s\n", to) + + return nil } diff --git a/cmd/neofs-cli/modules/util/keyer.go b/cmd/neofs-cli/modules/util/keyer.go index 693d3fccd8..f44ddfaf44 100644 --- a/cmd/neofs-cli/modules/util/keyer.go +++ b/cmd/neofs-cli/modules/util/keyer.go @@ -7,7 +7,6 @@ import ( "io/fs" "os" - "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" "github.com/nspcc-dev/neofs-node/pkg/util/keyer" "github.com/spf13/cobra" ) @@ -15,7 +14,7 @@ import ( var keyerCmd = &cobra.Command{ Use: "keyer", Short: "Generate or print information about keys", - Run: processKeyer, + RunE: processKeyer, } var errKeyerSingleArgument = errors.New("pass only one argument at a time") @@ -27,7 +26,7 @@ func initKeyerCmd() { keyerCmd.Flags().BoolP("multisig", "m", false, "Calculate multisig address from public keys") } -func processKeyer(cmd *cobra.Command, args []string) { +func processKeyer(cmd *cobra.Command, args []string) error { var ( err error @@ -42,7 +41,7 @@ func processKeyer(cmd *cobra.Command, args []string) { err = result.ParseMultiSig(args) } else { if len(args) > 1 { - common.ExitOnErr(cmd, "", errKeyerSingleArgument) + return errKeyerSingleArgument } var argument string @@ -60,9 +59,13 @@ func processKeyer(cmd *cobra.Command, args []string) { } } - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } result.PrettyPrint(uncompressed, useHex) + + return nil } func keyerGenerate(filename string, d *keyer.Dashboard) error { diff --git a/cmd/neofs-cli/modules/util/sign_bearer.go b/cmd/neofs-cli/modules/util/sign_bearer.go index b609c4fdda..e94aa09848 100644 --- a/cmd/neofs-cli/modules/util/sign_bearer.go +++ b/cmd/neofs-cli/modules/util/sign_bearer.go @@ -1,6 +1,7 @@ package util import ( + "fmt" "os" "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common" @@ -18,7 +19,7 @@ var signBearerCmd = &cobra.Command{ Use: "bearer-token", Short: "Sign bearer token to use it in requests", Args: cobra.NoArgs, - Run: signBearerToken, + RunE: signBearerToken, } func initSignBearerCmd() { @@ -34,9 +35,15 @@ func initSignBearerCmd() { flags.Bool(signBearerJSONFlag, false, "Dump bearer token in JSON encoding") } -func signBearerToken(cmd *cobra.Command, _ []string) { - btok := common.ReadBearerToken(cmd, signFromFlag) - pk := key.GetOrGenerate(cmd) +func signBearerToken(cmd *cobra.Command, _ []string) error { + btok, err := common.ReadBearerToken(cmd, signFromFlag) + if err != nil { + return err + } + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } signer := user.NewAutoIDSignerRFC6979(*pk) var zeroUsr user.ID @@ -45,8 +52,10 @@ func signBearerToken(cmd *cobra.Command, _ []string) { signer = user.NewSigner(signer, issuer) } - err := btok.Sign(signer) - common.ExitOnErr(cmd, "", err) + err = btok.Sign(signer) + if err != nil { + return err + } to := cmd.Flag(signToFlag).Value.String() jsonFlag, _ := cmd.Flags().GetBool(signBearerJSONFlag) @@ -54,18 +63,24 @@ func signBearerToken(cmd *cobra.Command, _ []string) { var data []byte if jsonFlag || len(to) == 0 { data, err = btok.MarshalJSON() - common.ExitOnErr(cmd, "can't JSON encode bearer token: %w", err) + if err != nil { + return fmt.Errorf("can't JSON encode bearer token: %w", err) + } } else { data = btok.Marshal() } if len(to) == 0 { common.PrettyPrintJSON(cmd, btok, "bearer token") - return + return nil } err = os.WriteFile(to, data, 0o644) - common.ExitOnErr(cmd, "can't write signed bearer token to file: %w", err) + if err != nil { + return fmt.Errorf("can't write signed bearer token to file: %w", err) + } cmd.Printf("signed bearer token was successfully dumped to %s\n", to) + + return nil } diff --git a/cmd/neofs-cli/modules/util/sign_session.go b/cmd/neofs-cli/modules/util/sign_session.go index dc2a811779..92341b7125 100644 --- a/cmd/neofs-cli/modules/util/sign_session.go +++ b/cmd/neofs-cli/modules/util/sign_session.go @@ -18,7 +18,7 @@ var signSessionCmd = &cobra.Command{ Use: "session-token", Short: "Sign session token to use it in requests", Args: cobra.NoArgs, - Run: signSessionToken, + RunE: signSessionToken, } func initSignSessionCmd() { @@ -33,12 +33,14 @@ func initSignSessionCmd() { flags.String(signToFlag, "", "File to save signed session token (optional)") } -func signSessionToken(cmd *cobra.Command, _ []string) { +func signSessionToken(cmd *cobra.Command, _ []string) error { fPath, err := cmd.Flags().GetString(signFromFlag) - common.ExitOnErr(cmd, "", err) + if err != nil { + return err + } if fPath == "" { - common.ExitOnErr(cmd, "", errors.New("missing session token flag")) + return errors.New("missing session token flag") } type iTokenSession interface { @@ -60,26 +62,37 @@ func signSessionToken(cmd *cobra.Command, _ []string) { } } - common.ExitOnErr(cmd, "decode session: %v", errLast) + if errLast != nil { + return fmt.Errorf("decode session: %v", errLast) + } - pk := key.GetOrGenerate(cmd) + pk, err := key.GetOrGenerate(cmd) + if err != nil { + return err + } err = stok.Sign(user.NewAutoIDSignerRFC6979(*pk)) - common.ExitOnErr(cmd, "can't sign token: %w", err) + if err != nil { + return fmt.Errorf("can't sign token: %w", err) + } data, err := stok.MarshalJSON() - common.ExitOnErr(cmd, "can't encode session token: %w", err) + if err != nil { + return fmt.Errorf("can't encode session token: %w", err) + } to := cmd.Flag(signToFlag).Value.String() if len(to) == 0 { common.PrettyPrintJSON(cmd, stok, "session token") - return + return nil } err = os.WriteFile(to, data, 0o644) if err != nil { - common.ExitOnErr(cmd, "", fmt.Errorf("can't write signed session token to %s: %w", to, err)) + return fmt.Errorf("can't write signed session token to %s: %w", to, err) } cmd.Printf("signed session token saved in %s\n", to) + + return nil } diff --git a/pkg/services/control/rpc.go b/pkg/services/control/rpc.go index 0ff002dd38..088122de9f 100644 --- a/pkg/services/control/rpc.go +++ b/pkg/services/control/rpc.go @@ -115,7 +115,7 @@ func ListShards( func ListObjects( cli *client.Client, req *ListObjectsRequest, - handleResp func(*ListObjectsResponse), + handleResp func(*ListObjectsResponse) error, opts ...client.CallOption, ) error { wReq := &requestWrapper{ @@ -138,7 +138,11 @@ func ListObjects( if err != nil { return err } - handleResp(wResp.m) + + err = handleResp(wResp.m) + if err != nil { + return err + } } return nil From bc942ff2053898ed757fb03e2dec7832ccd176d1 Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Wed, 18 Sep 2024 17:31:04 +0300 Subject: [PATCH 4/5] 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. Signed-off-by: Andrey Butusov --- CHANGELOG.md | 2 + cmd/neofs-lens/internal/errors.go | 31 ------------- cmd/neofs-lens/internal/meta/get.go | 25 ++++++++--- cmd/neofs-lens/internal/meta/id.go | 17 +++++-- cmd/neofs-lens/internal/meta/list-garbage.go | 19 +++++--- .../internal/meta/list-graveyard.go | 19 +++++--- cmd/neofs-lens/internal/meta/list.go | 17 ++++--- cmd/neofs-lens/internal/meta/put.go | 34 +++++++++----- cmd/neofs-lens/internal/meta/root.go | 14 +++--- cmd/neofs-lens/internal/meta/status.go | 20 ++++++--- cmd/neofs-lens/internal/object/link.go | 25 +++++++---- cmd/neofs-lens/internal/peapod/get.go | 31 +++++++++---- cmd/neofs-lens/internal/peapod/list.go | 16 ++++--- cmd/neofs-lens/internal/peapod/root.go | 15 ++++--- cmd/neofs-lens/internal/printers.go | 14 +++--- cmd/neofs-lens/internal/storage/get.go | 31 +++++++++---- cmd/neofs-lens/internal/storage/list.go | 20 ++++++--- cmd/neofs-lens/internal/storage/root.go | 31 ++++++++----- cmd/neofs-lens/internal/storage/sanity.go | 44 ++++++++++++++----- cmd/neofs-lens/internal/storage/status.go | 20 ++++++--- cmd/neofs-lens/internal/writecache/get.go | 26 ++++++----- cmd/neofs-lens/internal/writecache/list.go | 16 ++++--- cmd/neofs-lens/internal/writecache/root.go | 11 +++-- cmd/neofs-lens/root.go | 5 +-- 24 files changed, 331 insertions(+), 172 deletions(-) delete mode 100644 cmd/neofs-lens/internal/errors.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 8653d42829..32d595491b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,10 +11,12 @@ Changelog for NeoFS Node ### Fixed - Do not search for tombstones when handling their expiration, use local indexes instead (#2929) +- `defer` func is not skipped in cobra-based programs (#2942) ### Changed - `ObjectService`'s `Put` RPC handler caches up to 10K lists of per-object sorted container nodes (#2901) - Metabase graveyard scheme (#2929) +- When an error is returned, no additional help output is displayed in cobra-based programs (#2942) ### Removed diff --git a/cmd/neofs-lens/internal/errors.go b/cmd/neofs-lens/internal/errors.go deleted file mode 100644 index 536ba20318..0000000000 --- a/cmd/neofs-lens/internal/errors.go +++ /dev/null @@ -1,31 +0,0 @@ -package common - -import ( - "fmt" - "os" - - "github.com/spf13/cobra" -) - -// Errf returns formatted error in errFmt format if err is not nil. -func Errf(errFmt string, err error) error { - if err == nil { - return nil - } - - 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..fd52d632b8 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 fmt.Errorf("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 fmt.Errorf("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 fmt.Errorf("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..1d6517cce2 100644 --- a/cmd/neofs-lens/internal/meta/id.go +++ b/cmd/neofs-lens/internal/meta/id.go @@ -1,6 +1,8 @@ package meta import ( + "fmt" + "github.com/mr-tron/base58" common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" "github.com/spf13/cobra" @@ -10,19 +12,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 fmt.Errorf("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..915971fdb3 100644 --- a/cmd/neofs-lens/internal/meta/list-garbage.go +++ b/cmd/neofs-lens/internal/meta/list-garbage.go @@ -1,6 +1,8 @@ package meta import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" "github.com/spf13/cobra" @@ -11,15 +13,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 +34,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 fmt.Errorf("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 a73833e62e..8cf5528854 100644 --- a/cmd/neofs-lens/internal/meta/list-graveyard.go +++ b/cmd/neofs-lens/internal/meta/list-graveyard.go @@ -1,6 +1,8 @@ package meta import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" "github.com/spf13/cobra" @@ -11,15 +13,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 @@ -35,6 +40,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 fmt.Errorf("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..82c6512290 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 fmt.Errorf("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..622b99e116 100644 --- a/cmd/neofs-lens/internal/meta/put.go +++ b/cmd/neofs-lens/internal/meta/put.go @@ -2,6 +2,7 @@ package meta import ( "errors" + "fmt" "os" common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" @@ -15,7 +16,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 +24,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 fmt.Errorf("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 fmt.Errorf("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 fmt.Errorf("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 fmt.Errorf("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..6858081f9b 100644 --- a/cmd/neofs-lens/internal/meta/root.go +++ b/cmd/neofs-lens/internal/meta/root.go @@ -1,10 +1,10 @@ package meta import ( + "fmt" "os" "time" - common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" meta "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/metabase" "github.com/spf13/cobra" "go.etcd.io/bbolt" @@ -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, fmt.Errorf("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..412e18a33b 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 fmt.Errorf("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 fmt.Errorf("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..dcfd341186 100644 --- a/cmd/neofs-lens/internal/object/link.go +++ b/cmd/neofs-lens/internal/object/link.go @@ -5,7 +5,6 @@ import ( "fmt" "os" - common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/spf13/cobra" ) @@ -14,16 +13,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 fmt.Errorf("reading file: %w", err) + } var link object.Link err = link.Unmarshal(raw) @@ -32,18 +33,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 fmt.Errorf("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 fmt.Errorf("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 +56,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..03825c0075 100644 --- a/cmd/neofs-lens/internal/peapod/get.go +++ b/cmd/neofs-lens/internal/peapod/get.go @@ -1,6 +1,8 @@ package peapod import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" blobstorcommon "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/common" "github.com/spf13/cobra" @@ -11,7 +13,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 +23,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 fmt.Errorf("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 fmt.Errorf("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 + } + if err := common.WriteObjectToFile(cmd, vOut, res.RawData, false); err != nil { + return err } - common.WriteObjectToFile(cmd, vOut, res.RawData, false) + + return nil } diff --git a/cmd/neofs-lens/internal/peapod/list.go b/cmd/neofs-lens/internal/peapod/list.go index 95f95203e5..9dc7bdd4e2 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 fmt.Errorf("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..2b0ad1fd62 100644 --- a/cmd/neofs-lens/internal/peapod/root.go +++ b/cmd/neofs-lens/internal/peapod/root.go @@ -1,7 +1,8 @@ package peapod import ( - common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" + "fmt" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/compression" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/blobstor/peapod" "github.com/spf13/cobra" @@ -26,18 +27,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, fmt.Errorf("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, fmt.Errorf("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..52b9bfbcf2 100644 --- a/cmd/neofs-lens/internal/printers.go +++ b/cmd/neofs-lens/internal/printers.go @@ -1,6 +1,7 @@ package common import ( + "fmt" "os" "strings" @@ -55,19 +56,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 fmt.Errorf("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..e8b96f4f61 100644 --- a/cmd/neofs-lens/internal/storage/get.go +++ b/cmd/neofs-lens/internal/storage/get.go @@ -1,6 +1,8 @@ package storage import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" @@ -12,7 +14,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 +24,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 fmt.Errorf("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 fmt.Errorf("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..86fb48494c 100644 --- a/cmd/neofs-lens/internal/storage/list.go +++ b/cmd/neofs-lens/internal/storage/list.go @@ -2,6 +2,7 @@ package storage import ( "errors" + "fmt" "io" common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" @@ -14,18 +15,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 +38,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 fmt.Errorf("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 fmt.Errorf("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..7e47d4e88b 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 fmt.Errorf("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 fmt.Errorf("open metabase: %w", err) + } + if err := sh.p.Open(true); err != nil { + return fmt.Errorf("open peapod: %w", err) + } + if err := sh.fsT.Open(true); err != nil { + return fmt.Errorf("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 fmt.Errorf("moving metabase in readonly mode: %w", 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 fmt.Errorf("init metabase: %w", err) + } + if err := sh.p.Init(); err != nil { + return fmt.Errorf("init peapod: %w", err) + } + if err := sh.fsT.Init(); err != nil { + return fmt.Errorf("init fstree: %w", err) + } shards = append(shards, sh) return nil }) - common.ExitOnErr(cmd, common.Errf("reading config: %w", err)) + if err != nil { + return fmt.Errorf("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..a4fa6ce61d 100644 --- a/cmd/neofs-lens/internal/storage/status.go +++ b/cmd/neofs-lens/internal/storage/status.go @@ -1,6 +1,8 @@ package storage import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" oid "github.com/nspcc-dev/neofs-sdk-go/object/id" "github.com/spf13/cobra" @@ -11,7 +13,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 +21,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 fmt.Errorf("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 fmt.Errorf("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..4b94d4a3e7 100644 --- a/cmd/neofs-lens/internal/writecache/get.go +++ b/cmd/neofs-lens/internal/writecache/get.go @@ -1,6 +1,8 @@ package writecache import ( + "fmt" + common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache" "github.com/nspcc-dev/neofs-sdk-go/object" @@ -12,7 +14,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 +24,24 @@ 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 fmt.Errorf("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 fmt.Errorf("could not unmarshal object: %w", err) + } common.PrintObjectHeader(cmd, o) - if vPayloadOnly { - common.WriteObjectToFile(cmd, vOut, data, true) - return - } - common.WriteObjectToFile(cmd, vOut, data, false) + + return common.WriteObjectToFile(cmd, vOut, data, vPayloadOnly) } diff --git a/cmd/neofs-lens/internal/writecache/list.go b/cmd/neofs-lens/internal/writecache/list.go index 9d92cebe28..5f91a4cd10 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 fmt.Errorf("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..d8ac40dffe 100644 --- a/cmd/neofs-lens/internal/writecache/root.go +++ b/cmd/neofs-lens/internal/writecache/root.go @@ -1,7 +1,8 @@ package writecache import ( - common "github.com/nspcc-dev/neofs-node/cmd/neofs-lens/internal" + "fmt" + "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/writecache" "github.com/spf13/cobra" "go.etcd.io/bbolt" @@ -25,9 +26,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, fmt.Errorf("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..b9db8ab6d3 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/cmderr" "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" @@ -48,7 +49,5 @@ func init() { func main() { err := command.Execute() - if err != nil { - os.Exit(1) - } + cmderr.ExitOnErr(err) } From fc291a2eaee17e21684d743b4670308ed11bcb7d Mon Sep 17 00:00:00 2001 From: Andrey Butusov Date: Mon, 23 Sep 2024 19:02:05 +0300 Subject: [PATCH 5/5] cmd: silence errors and usage for cobra commands Closes #623. Refs #2890. Signed-off-by: Andrey Butusov --- cmd/neofs-adm/internal/modules/root.go | 5 +++-- cmd/neofs-cli/modules/root.go | 6 ++++-- cmd/neofs-lens/root.go | 11 ++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/cmd/neofs-adm/internal/modules/root.go b/cmd/neofs-adm/internal/modules/root.go index 6dd6221eef..d52e74804e 100644 --- a/cmd/neofs-adm/internal/modules/root.go +++ b/cmd/neofs-adm/internal/modules/root.go @@ -19,8 +19,9 @@ var ( Short: "NeoFS Administrative Tool", Long: `NeoFS Administrative Tool provides functions to setup and manage NeoFS network deployment.`, - RunE: entryPoint, - SilenceUsage: true, + RunE: entryPoint, + SilenceUsage: true, + SilenceErrors: true, } configFlag = "config" diff --git a/cmd/neofs-cli/modules/root.go b/cmd/neofs-cli/modules/root.go index 34b7f1e5dc..a02f184fa3 100644 --- a/cmd/neofs-cli/modules/root.go +++ b/cmd/neofs-cli/modules/root.go @@ -44,8 +44,10 @@ It contains commands for interaction with NeoFS nodes using different versions of neofs-api and some useful utilities for compiling ACL rules from JSON notation, managing container access through protocol gates, querying network map and much more!`, - Args: cobra.NoArgs, - RunE: entryPoint, + Args: cobra.NoArgs, + RunE: entryPoint, + SilenceErrors: true, + SilenceUsage: true, } // Execute adds all child commands to the root command and sets flags appropriately. diff --git a/cmd/neofs-lens/root.go b/cmd/neofs-lens/root.go index b9db8ab6d3..dc0096b2ce 100644 --- a/cmd/neofs-lens/root.go +++ b/cmd/neofs-lens/root.go @@ -15,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 {