From 4b7cc6e293b1201adc1e52b1bc7bd4c7bde27778 Mon Sep 17 00:00:00 2001
From: Leonard Lyubich <leonard@nspcc.ru>
Date: Wed, 25 Aug 2021 10:35:16 +0300
Subject: [PATCH] [#758] cmd/neofs-adm: Implement command to refill storage
 node's GAS

Add `refill-gas` sub-command to `morph` command which provides the ability
to refill storage node's GAS.

Command performs some actions from `generate-storage-wallet` runner, so
common code is moved to a separate function `refillGas`.

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
---
 .../internal/modules/morph/generate.go        | 36 ++++++++++++-------
 cmd/neofs-adm/internal/modules/morph/root.go  | 20 +++++++++++
 2 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/cmd/neofs-adm/internal/modules/morph/generate.go b/cmd/neofs-adm/internal/modules/morph/generate.go
index 6dcc277358..88de253210 100644
--- a/cmd/neofs-adm/internal/modules/morph/generate.go
+++ b/cmd/neofs-adm/internal/modules/morph/generate.go
@@ -117,7 +117,11 @@ func addMultisigAccount(w *wallet.Wallet, m int, name, password string, pubs key
 	return nil
 }
 
-func generateStorageCreds(cmd *cobra.Command, args []string) error {
+func generateStorageCreds(cmd *cobra.Command, _ []string) error {
+	return refillGas(cmd, storageGasConfigFlag, true)
+}
+
+func refillGas(cmd *cobra.Command, gasFlag string, createWallet bool) error {
 	// storage wallet path is not part of the config
 	storageWalletPath, err := cmd.Flags().GetString(storageWalletFlag)
 	if err != nil {
@@ -127,24 +131,30 @@ func generateStorageCreds(cmd *cobra.Command, args []string) error {
 		return fmt.Errorf("missing wallet path (use '--%s <out.json>')", storageWalletFlag)
 	}
 
-	w, err := wallet.NewWallet(storageWalletPath)
+	var w *wallet.Wallet
+
+	if createWallet {
+		w, err = wallet.NewWallet(storageWalletPath)
+	} else {
+		w, err = wallet.NewWalletFromFile(storageWalletPath)
+	}
+
 	if err != nil {
 		return fmt.Errorf("can't create wallet: %w", err)
 	}
 
-	password, err := input.ReadPassword("New password > ")
-	if err != nil {
-		return fmt.Errorf("can't fetch password: %w", err)
+	if createWallet {
+		password, err := input.ReadPassword("New password > ")
+		if err != nil {
+			return fmt.Errorf("can't fetch password: %w", err)
+		}
+
+		if err := w.CreateAccount(singleAccountName, password); err != nil {
+			return fmt.Errorf("can't create account: %w", err)
+		}
 	}
 
-	if err := w.CreateAccount(singleAccountName, password); err != nil {
-		return fmt.Errorf("can't create account: %w", err)
-	}
-
-	gasStr := viper.GetString(storageGasConfigFlag)
-	if gasStr == "" {
-		return nil
-	}
+	gasStr := viper.GetString(gasFlag)
 
 	gasAmount, err := fixedn.Fixed8FromString(gasStr)
 	if err != nil {
diff --git a/cmd/neofs-adm/internal/modules/morph/root.go b/cmd/neofs-adm/internal/modules/morph/root.go
index 6f78bfb780..b671166cbc 100644
--- a/cmd/neofs-adm/internal/modules/morph/root.go
+++ b/cmd/neofs-adm/internal/modules/morph/root.go
@@ -30,6 +30,7 @@ const (
 	containerDumpFlag     = "dump"
 	containerContractFlag = "container-contract"
 	containerIDsFlag      = "cid"
+	refillGasAmountFlag   = "gas"
 )
 
 var (
@@ -77,6 +78,19 @@ var (
 		RunE: generateStorageCreds,
 	}
 
+	refillGasCmd = &cobra.Command{
+		Use:   "refill-gas",
+		Short: "Refill GAS of storage node's wallet in the morph network",
+		PreRun: func(cmd *cobra.Command, _ []string) {
+			_ = viper.BindPFlag(alphabetWalletsFlag, cmd.Flags().Lookup(alphabetWalletsFlag))
+			_ = viper.BindPFlag(endpointFlag, cmd.Flags().Lookup(endpointFlag))
+			_ = viper.BindPFlag(refillGasAmountFlag, cmd.Flags().Lookup(refillGasAmountFlag))
+		},
+		RunE: func(cmd *cobra.Command, args []string) error {
+			return refillGas(cmd, refillGasAmountFlag, false)
+		},
+	}
+
 	forceNewEpoch = &cobra.Command{
 		Use:   "force-new-epoch",
 		Short: "Create new NeoFS epoch event in the side chain",
@@ -179,4 +193,10 @@ func init() {
 	restoreContainersCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
 	restoreContainersCmd.Flags().String(containerDumpFlag, "", "file to restore containers from")
 	restoreContainersCmd.Flags().StringSlice(containerIDsFlag, nil, "containers to restore")
+
+	RootCmd.AddCommand(refillGasCmd)
+	refillGasCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir")
+	refillGasCmd.Flags().StringP(endpointFlag, "r", "", "N3 RPC node endpoint")
+	refillGasCmd.Flags().String(storageWalletFlag, "", "path to storage node wallet")
+	refillGasCmd.Flags().String(refillGasAmountFlag, "", "additional amount of GAS to transfer")
 }