diff --git a/cmd/frostfs-adm/internal/modules/morph/config.go b/cmd/frostfs-adm/internal/modules/morph/config/config.go similarity index 94% rename from cmd/frostfs-adm/internal/modules/morph/config.go rename to cmd/frostfs-adm/internal/modules/morph/config/config.go index 2cff322d..b1ed1cc2 100644 --- a/cmd/frostfs-adm/internal/modules/morph/config.go +++ b/cmd/frostfs-adm/internal/modules/morph/config/config.go @@ -1,4 +1,4 @@ -package morph +package config import ( "bytes" @@ -51,7 +51,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { buf := bytes.NewBuffer(nil) tw := tabwriter.NewWriter(buf, 0, 2, 2, ' ', 0) - m, err := parseConfigFromNetmapContract(arr) + m, err := util.ParseConfigFromNetmapContract(arr) if err != nil { return err } @@ -66,7 +66,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%d (int)\n", k, n))) case netmap.HomomorphicHashingDisabledKey, netmap.MaintenanceModeAllowedConfig: if len(v) == 0 || len(v) > 1 { - return invalidConfigValueErr(k) + return util.InvalidConfigValueErr(k) } _, _ = tw.Write([]byte(fmt.Sprintf("%s:\t%t (bool)\n", k, v[0] == 1))) default: @@ -80,7 +80,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error { return nil } -func setConfigCmd(cmd *cobra.Command, args []string) error { +func SetConfigCmd(cmd *cobra.Command, args []string) error { if len(args) == 0 { return errors.New("empty config pairs") } @@ -162,7 +162,3 @@ func parseConfigPair(kvStr string, force bool) (key string, val any, err error) return } - -func invalidConfigValueErr(key string) error { - return fmt.Errorf("invalid %s config value from netmap contract", key) -} diff --git a/cmd/frostfs-adm/internal/modules/morph/config/root.go b/cmd/frostfs-adm/internal/modules/morph/config/root.go new file mode 100644 index 00000000..4b536622 --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/config/root.go @@ -0,0 +1,46 @@ +package config + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + SetCmd = &cobra.Command{ + Use: "set-config key1=val1 [key2=val2 ...]", + DisableFlagsInUseLine: true, + Short: "Add/update global config value in the FrostFS network", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + Args: cobra.MinimumNArgs(1), + RunE: SetConfigCmd, + } + + DumpCmd = &cobra.Command{ + Use: "dump-config", + Short: "Dump FrostFS network config", + PreRun: func(cmd *cobra.Command, _ []string) { + _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) + }, + RunE: dumpNetworkConfig, + } +) + +func initSetConfigCmd() { + SetCmd.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) + SetCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) + SetCmd.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") + SetCmd.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") +} + +func initDumpNetworkConfigCmd() { + DumpCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) +} + +func init() { + initSetConfigCmd() + initDumpNetworkConfigCmd() +} diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go index 50427c93..3a78f604 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_deploy.go @@ -372,7 +372,7 @@ func getContractDeployData(c *morphUtil.InitializeContext, ctrName string, keysP items = append(items, c.Contracts[morphUtil.ProxyContract].Hash) } case morphUtil.NetmapContract: - md := getDefaultNetmapContractConfigMap() + md := morphUtil.GetDefaultNetmapContractConfigMap() if method == updateMethodName { if err := mergeNetmapConfig(c.ReadOnlyInvoker, md); err != nil { return nil, err @@ -450,7 +450,7 @@ func mergeNetmapConfig(roInvoker *invoker.Invoker, md map[string]any) error { if err != nil { return err } - m, err := parseConfigFromNetmapContract(arr) + m, err := morphUtil.ParseConfigFromNetmapContract(arr) if err != nil { return err } diff --git a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go index e9571e50..f0ad8044 100644 --- a/cmd/frostfs-adm/internal/modules/morph/initialize_test.go +++ b/cmd/frostfs-adm/internal/modules/morph/initialize_test.go @@ -9,6 +9,7 @@ import ( "testing" "time" + cmdConfig "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/innerring" @@ -75,8 +76,8 @@ func testInitialize(t *testing.T, committeeSize int) { require.NoError(t, forceNewEpochCmd(forceNewEpoch, nil)) }) t.Run("set-config", func(t *testing.T) { - require.NoError(t, setConfig.Flags().Set(util.LocalDumpFlag, dumpPath)) - require.NoError(t, setConfigCmd(setConfig, []string{"MaintenanceModeAllowed=true"})) + require.NoError(t, cmdConfig.SetCmd.Flags().Set(util.LocalDumpFlag, dumpPath)) + require.NoError(t, cmdConfig.SetConfigCmd(cmdConfig.SetCmd, []string{"MaintenanceModeAllowed=true"})) }) t.Run("set-policy", func(t *testing.T) { require.NoError(t, policy.Set.Flags().Set(util.LocalDumpFlag, dumpPath)) diff --git a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go b/cmd/frostfs-adm/internal/modules/morph/netmap_util.go deleted file mode 100644 index 3cf853cc..00000000 --- a/cmd/frostfs-adm/internal/modules/morph/netmap_util.go +++ /dev/null @@ -1,45 +0,0 @@ -package morph - -import ( - "errors" - - "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/util" - "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "github.com/spf13/viper" -) - -func getDefaultNetmapContractConfigMap() map[string]any { - m := make(map[string]any) - m[netmap.EpochDurationConfig] = viper.GetInt64(util.EpochDurationInitFlag) - m[netmap.MaxObjectSizeConfig] = viper.GetInt64(util.MaxObjectSizeInitFlag) - m[netmap.ContainerFeeConfig] = viper.GetInt64(containerFeeInitFlag) - m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(containerAliasFeeInitFlag) - m[netmap.IrCandidateFeeConfig] = viper.GetInt64(candidateFeeInitFlag) - m[netmap.WithdrawFeeConfig] = viper.GetInt64(withdrawFeeInitFlag) - m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(homomorphicHashDisabledInitFlag) - m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(maintenanceModeAllowedInitFlag) - return m -} - -func parseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, error) { - m := make(map[string][]byte, len(arr)) - for _, param := range arr { - tuple, ok := param.Value().([]stackitem.Item) - if !ok || len(tuple) != 2 { - return nil, errors.New("invalid ListConfig response from netmap contract") - } - - k, err := tuple[0].TryBytes() - if err != nil { - return nil, errors.New("invalid config key from netmap contract") - } - - v, err := tuple[1].TryBytes() - if err != nil { - return nil, invalidConfigValueErr(string(k)) - } - m[string(k)] = v - } - return m, nil -} diff --git a/cmd/frostfs-adm/internal/modules/morph/root.go b/cmd/frostfs-adm/internal/modules/morph/root.go index fdc9bb32..f0e47bc7 100644 --- a/cmd/frostfs-adm/internal/modules/morph/root.go +++ b/cmd/frostfs-adm/internal/modules/morph/root.go @@ -3,6 +3,7 @@ package morph import ( "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/ape" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/balance" + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/config" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/notary" "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/modules/morph/policy" @@ -21,21 +22,19 @@ const ( maxObjectSizeCLIFlag = "max-object-size" - epochDurationCLIFlag = "epoch-duration" - containerFeeInitFlag = "network.fee.container" - containerAliasFeeInitFlag = "network.fee.container_alias" - containerFeeCLIFlag = "container-fee" - containerAliasFeeCLIFlag = "container-alias-fee" - candidateFeeInitFlag = "network.fee.candidate" - candidateFeeCLIFlag = "candidate-fee" - homomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" - maintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" - homomorphicHashDisabledCLIFlag = "homomorphic-disabled" - withdrawFeeInitFlag = "network.fee.withdraw" - withdrawFeeCLIFlag = "withdraw-fee" - containerDumpFlag = "dump" - containerContractFlag = "container-contract" - containerIDsFlag = "cid" + epochDurationCLIFlag = "epoch-duration" + + containerFeeCLIFlag = "container-fee" + containerAliasFeeCLIFlag = "container-alias-fee" + + candidateFeeCLIFlag = "candidate-fee" + + homomorphicHashDisabledCLIFlag = "homomorphic-disabled" + + withdrawFeeCLIFlag = "withdraw-fee" + containerDumpFlag = "dump" + containerContractFlag = "container-contract" + containerIDsFlag = "cid" walletAddressFlag = "wallet-address" ) @@ -65,11 +64,11 @@ var ( _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) _ = viper.BindPFlag(util.EpochDurationInitFlag, cmd.Flags().Lookup(epochDurationCLIFlag)) _ = viper.BindPFlag(util.MaxObjectSizeInitFlag, cmd.Flags().Lookup(maxObjectSizeCLIFlag)) - _ = viper.BindPFlag(homomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) - _ = viper.BindPFlag(candidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) - _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) - _ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) - _ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) + _ = viper.BindPFlag(util.HomomorphicHashDisabledInitFlag, cmd.Flags().Lookup(homomorphicHashDisabledCLIFlag)) + _ = viper.BindPFlag(util.CandidateFeeInitFlag, cmd.Flags().Lookup(candidateFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) + _ = viper.BindPFlag(util.ContainerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) + _ = viper.BindPFlag(util.WithdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) _ = viper.BindPFlag(util.ProtoConfigPath, cmd.Flags().Lookup(util.ProtoConfigPath)) }, RunE: initializeSideChainCmd, @@ -120,18 +119,6 @@ var ( RunE: removeNodesCmd, } - setConfig = &cobra.Command{ - Use: "set-config key1=val1 [key2=val2 ...]", - DisableFlagsInUseLine: true, - Short: "Add/update global config value in the FrostFS network", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.AlphabetWalletsFlag, cmd.Flags().Lookup(util.AlphabetWalletsFlag)) - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - Args: cobra.MinimumNArgs(1), - RunE: setConfigCmd, - } - dumpContractHashesCmd = &cobra.Command{ Use: "dump-hashes", Short: "Dump deployed contract hashes", @@ -141,15 +128,6 @@ var ( RunE: dumpContractHashes, } - dumpNetworkConfigCmd = &cobra.Command{ - Use: "dump-config", - Short: "Dump FrostFS network config", - PreRun: func(cmd *cobra.Command, _ []string) { - _ = viper.BindPFlag(util.EndpointFlag, cmd.Flags().Lookup(util.EndpointFlag)) - }, - RunE: dumpNetworkConfig, - } - updateContractsCmd = &cobra.Command{ Use: "update-contracts", Short: "Update FrostFS contracts", @@ -209,8 +187,8 @@ func init() { RootCmd.AddCommand(policy.Set) RootCmd.AddCommand(policy.Dump) initDumpContractHashesCmd() - initDumpNetworkConfigCmd() - initSetConfigCmd() + RootCmd.AddCommand(config.SetCmd) + RootCmd.AddCommand(config.DumpCmd) RootCmd.AddCommand(balance.DumpCmd) initUpdateContractsCmd() initDumpContainersCmd() @@ -273,19 +251,6 @@ func initUpdateContractsCmd() { updateContractsCmd.MarkFlagsMutuallyExclusive(util.ContractsInitFlag, util.ContractsURLFlag) } -func initSetConfigCmd() { - RootCmd.AddCommand(setConfig) - setConfig.Flags().String(util.AlphabetWalletsFlag, "", util.AlphabetWalletsFlagDesc) - setConfig.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) - setConfig.Flags().Bool(forceConfigSet, false, "Force setting not well-known configuration key") - setConfig.Flags().String(util.LocalDumpFlag, "", "Path to the blocks dump file") -} - -func initDumpNetworkConfigCmd() { - RootCmd.AddCommand(dumpNetworkConfigCmd) - dumpNetworkConfigCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) -} - func initDumpContractHashesCmd() { RootCmd.AddCommand(dumpContractHashesCmd) dumpContractHashesCmd.Flags().StringP(util.EndpointFlag, util.EndpointFlagShort, "", util.EndpointFlagDesc) diff --git a/cmd/frostfs-adm/internal/modules/morph/util/const.go b/cmd/frostfs-adm/internal/modules/morph/util/const.go index a532eb2a..c4a674bd 100644 --- a/cmd/frostfs-adm/internal/modules/morph/util/const.go +++ b/cmd/frostfs-adm/internal/modules/morph/util/const.go @@ -11,20 +11,26 @@ const ( // See: https://github.com/nspcc-dev/neo-go/blob/740488f7f35e367eaa99a71c0a609c315fe2b0fc/pkg/core/transaction/witness.go#L10 MaxAlphabetNodes = 22 - EndpointFlag = "rpc-endpoint" - EndpointFlagDesc = "N3 RPC node endpoint" - EndpointFlagShort = "r" - AlphabetWalletsFlag = "alphabet-wallets" - AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" - LocalDumpFlag = "local-dump" - ContractsInitFlag = "contracts" + EndpointFlag = "rpc-endpoint" + EndpointFlagDesc = "N3 RPC node endpoint" + EndpointFlagShort = "r" + AlphabetWalletsFlag = "alphabet-wallets" + AlphabetWalletsFlagDesc = "Path to alphabet wallets dir" + LocalDumpFlag = "local-dump" + ContractsInitFlag = "contracts" ContractsInitFlagDesc = "Path to archive with compiled FrostFS contracts (the default is to fetch the latest release from the official repository)" ContractsURLFlag = "contracts-url" ContractsURLFlagDesc = "URL to archive with compiled FrostFS contracts" - EpochDurationInitFlag = "network.epoch_duration" - MaxObjectSizeInitFlag = "network.max_object_size" - RefillGasAmountFlag = "gas" - StorageWalletFlag = "storage-wallet" + EpochDurationInitFlag = "network.epoch_duration" + MaxObjectSizeInitFlag = "network.max_object_size" + RefillGasAmountFlag = "gas" + StorageWalletFlag = "storage-wallet" + ContainerFeeInitFlag = "network.fee.container" + ContainerAliasFeeInitFlag = "network.fee.container_alias" + CandidateFeeInitFlag = "network.fee.candidate" + WithdrawFeeInitFlag = "network.fee.withdraw" + MaintenanceModeAllowedInitFlag = "network.maintenance_mode_allowed" + HomomorphicHashDisabledInitFlag = "network.homomorphic_hash_disabled" SingleAccountName = "single" CommitteeAccountName = "committee" diff --git a/cmd/frostfs-adm/internal/modules/morph/util/netmap.go b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go new file mode 100644 index 00000000..c9dc2e3b --- /dev/null +++ b/cmd/frostfs-adm/internal/modules/morph/util/netmap.go @@ -0,0 +1,49 @@ +package util + +import ( + "errors" + "fmt" + + "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/netmap" + "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/spf13/viper" +) + +func GetDefaultNetmapContractConfigMap() map[string]any { + m := make(map[string]any) + m[netmap.EpochDurationConfig] = viper.GetInt64(EpochDurationInitFlag) + m[netmap.MaxObjectSizeConfig] = viper.GetInt64(MaxObjectSizeInitFlag) + m[netmap.ContainerFeeConfig] = viper.GetInt64(ContainerFeeInitFlag) + m[netmap.ContainerAliasFeeConfig] = viper.GetInt64(ContainerAliasFeeInitFlag) + m[netmap.IrCandidateFeeConfig] = viper.GetInt64(CandidateFeeInitFlag) + m[netmap.WithdrawFeeConfig] = viper.GetInt64(WithdrawFeeInitFlag) + m[netmap.HomomorphicHashingDisabledKey] = viper.GetBool(HomomorphicHashDisabledInitFlag) + m[netmap.MaintenanceModeAllowedConfig] = viper.GetBool(MaintenanceModeAllowedInitFlag) + return m +} + +func ParseConfigFromNetmapContract(arr []stackitem.Item) (map[string][]byte, error) { + m := make(map[string][]byte, len(arr)) + for _, param := range arr { + tuple, ok := param.Value().([]stackitem.Item) + if !ok || len(tuple) != 2 { + return nil, errors.New("invalid ListConfig response from netmap contract") + } + + k, err := tuple[0].TryBytes() + if err != nil { + return nil, errors.New("invalid config key from netmap contract") + } + + v, err := tuple[1].TryBytes() + if err != nil { + return nil, InvalidConfigValueErr(string(k)) + } + m[string(k)] = v + } + return m, nil +} + +func InvalidConfigValueErr(key string) error { + return fmt.Errorf("invalid %s config value from netmap contract", key) +}