Skip to content

Commit

Permalink
[ioctl] Refactor aliasimport command in new ioctl (#3350)
Browse files Browse the repository at this point in the history
* [ioctl] refactor aliasimport command in new ioctl
  • Loading branch information
LuckyPigeon authored May 12, 2022
1 parent 9844fac commit de09d24
Show file tree
Hide file tree
Showing 12 changed files with 156 additions and 158 deletions.
26 changes: 17 additions & 9 deletions ioctl/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@ type (
DecryptPrivateKey(string, string) (*ecdsa.PrivateKey, error)
// AliasMap returns the alias map: accountAddr-aliasName
AliasMap() map[string]string
// SetAlias write alias and account address to the default config file
SetAlias(string, string) error
// SetAlias updates aliasname and account address and not write them into the default config file
SetAlias(string, string)
// SetAliasAndSave updates aliasname and account address and write them into the default config file
SetAliasAndSave(string, string) error
// DeleteAlias delete alias from the default config file
DeleteAlias(string) error
// WriteConfig write config datas to the default config file
WriteConfig() error
// IsCryptoSm2 return true if use sm2 cryptographic algorithm, false if not use
IsCryptoSm2() bool
// QueryAnalyser sends request to Analyser endpoint
Expand Down Expand Up @@ -242,22 +246,26 @@ func (c *client) AliasMap() map[string]string {
return aliases
}

func (c *client) SetAlias(alias string, addr string) error {
func (c *client) SetAlias(aliasName string, addr string) {
for k, v := range c.cfg.Aliases {
if v == addr {
delete(c.cfg.Aliases, k)
}
}
c.cfg.Aliases[alias] = addr
return c.writeAlias()
c.cfg.Aliases[aliasName] = addr
}

func (c *client) DeleteAlias(alias string) error {
delete(c.cfg.Aliases, alias)
return c.writeAlias()
func (c *client) SetAliasAndSave(aliasName string, addr string) error {
c.SetAlias(aliasName, addr)
return c.WriteConfig()
}

func (c *client) writeAlias() error {
func (c *client) DeleteAlias(aliasName string) error {
delete(c.cfg.Aliases, aliasName)
return c.WriteConfig()
}

func (c *client) WriteConfig() error {
out, err := yaml.Marshal(&c.cfg)
if err != nil {
return errors.Wrapf(err, "failed to marshal config to config file %s", c.configFilePath)
Expand Down
4 changes: 2 additions & 2 deletions ioctl/client_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand Down Expand Up @@ -249,7 +249,7 @@ func TestSetAlias(t *testing.T) {
for _, test := range tests {
configFilePath := testPathd + "/config.default"
c := NewClient(test.cfg, configFilePath)
r.NoError(c.SetAlias(test.alias, test.addr))
r.NoError(c.SetAliasAndSave(test.alias, test.addr))
cfgload := loadTempConfig(t, configFilePath)
count := 0
for _, v := range cfgload.Aliases {
Expand Down
2 changes: 1 addition & 1 deletion ioctl/newcmd/account/accountcreateadd.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func NewAccountCreateAdd(client ioctl.Client) *cobra.Command {
return errors.Wrap(err, failToGenerateNewPrivateKeySm2)
}
}
if err := client.SetAlias(args[0], addr); err != nil {
if err := client.SetAliasAndSave(args[0], addr); err != nil {
return errors.Wrapf(err, failToWriteToConfigFile)
}
cmd.Println(fmt.Sprintf(_outputMessage, args[0]))
Expand Down
2 changes: 1 addition & 1 deletion ioctl/newcmd/account/accountcreateadd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func TestNewAccountCreateAdd(t *testing.T) {
},
}).Times(4)
client.EXPECT().NewKeyStore().Return(ks).Times(2)
client.EXPECT().SetAlias(gomock.Any(), gomock.Any()).Return(nil).Times(2)
client.EXPECT().SetAliasAndSave(gomock.Any(), gomock.Any()).Return(nil).Times(2)

t.Run("CryptoSm2 is true", func(t *testing.T) {
client.EXPECT().IsCryptoSm2().Return(true)
Expand Down
6 changes: 3 additions & 3 deletions ioctl/newcmd/account/accountimport.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func NewAccountImportKeyCmd(client ioctl.Client) *cobra.Command {
if err != nil {
return err
}
return client.SetAlias(alias, addr)
return client.SetAliasAndSave(alias, addr)
},
}
}
Expand Down Expand Up @@ -131,7 +131,7 @@ func NewAccountImportKeyStoreCmd(client ioctl.Client) *cobra.Command {
if err != nil {
return err
}
return client.SetAlias(alias, addr)
return client.SetAliasAndSave(alias, addr)
},
}
}
Expand Down Expand Up @@ -165,7 +165,7 @@ func NewAccountImportPemCmd(client ioctl.Client) *cobra.Command {
if err != nil {
return err
}
return client.SetAlias(alias, addr)
return client.SetAliasAndSave(alias, addr)
},
}
}
Expand Down
6 changes: 3 additions & 3 deletions ioctl/newcmd/account/accountimport_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestNewAccountImportKeyCmd(t *testing.T) {
client.EXPECT().ReadSecret().Return(prvKey.HexString(), nil).AnyTimes()
client.EXPECT().NewKeyStore().Return(ks).Times(1)
client.EXPECT().Config().Return(config.Config{Wallet: testWallet}).Times(1)
client.EXPECT().SetAlias(gomock.Any(), gomock.Any()).Return(nil).Times(1)
client.EXPECT().SetAliasAndSave(gomock.Any(), gomock.Any()).Return(nil).Times(1)

cmd := NewAccountImportKeyCmd(client)
result, err := util.ExecuteCmd(cmd, "hhalias")
Expand All @@ -74,7 +74,7 @@ func TestNewAccountImportKeyStoreCmd(t *testing.T) {
client.EXPECT().ReadSecret().Return(passwd, nil).AnyTimes()
client.EXPECT().NewKeyStore().Return(ks).Times(1)
client.EXPECT().Config().Return(config.Config{Wallet: testWallet}).Times(1)
client.EXPECT().SetAlias(gomock.Any(), gomock.Any()).Return(nil).Times(1)
client.EXPECT().SetAliasAndSave(gomock.Any(), gomock.Any()).Return(nil).Times(1)

client.EXPECT().DecryptPrivateKey(gomock.Any(), gomock.Any()).DoAndReturn(
func(passwordOfKeyStore, keyStorePath string) (*ecdsa.PrivateKey, error) {
Expand Down Expand Up @@ -110,7 +110,7 @@ func TestNewAccountImportPemCmd(t *testing.T) {
require.NoError(crypto.WritePrivateKeyToPem(pemFilePath, priKey2.(*crypto.P256sm2PrvKey), passwd))

client.EXPECT().ReadSecret().Return(passwd, nil).AnyTimes()
client.EXPECT().SetAlias(gomock.Any(), gomock.Any()).Return(nil).Times(1)
client.EXPECT().SetAliasAndSave(gomock.Any(), gomock.Any()).Return(nil).Times(1)

cmd := NewAccountImportPemCmd(client)
result, err := util.ExecuteCmd(cmd, "hhalias", pemFilePath)
Expand Down
54 changes: 10 additions & 44 deletions ioctl/newcmd/alias/alias.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand All @@ -9,14 +9,11 @@ package alias
import (
"github.com/ethereum/go-ethereum/common"
"github.com/iotexproject/iotex-address/address"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/iotexproject/iotex-core/ioctl"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
"github.com/iotexproject/iotex-core/ioctl/util"
"github.com/iotexproject/iotex-core/ioctl/validator"
"github.com/iotexproject/iotex-core/pkg/util/addrutil"
)

Expand All @@ -32,68 +29,37 @@ var (
}
)

// Errors
var (
ErrNoAliasFound = errors.New("no alias is found")
)

// Flags
var (
_format string
_forceImport bool
)

//type alias struct {
// Name string `json:"name" yaml:"name"`
// Address string `json:"address" yaml:"address"`
//}
//
//type aliases struct {
// Aliases []alias `json:"aliases" yaml:"aliases"`
//}

// NewAliasCmd represents the alias command
func NewAliasCmd(client ioctl.Client) *cobra.Command {
aliasShorts, _ := client.SelectTranslation(_aliasCmdShorts)
aliasUses, _ := client.SelectTranslation(_aliasCmdUses)

ec := &cobra.Command{
ac := &cobra.Command{
Use: aliasUses,
Short: aliasShorts,
}

ec.AddCommand(NewAliasImportCmd(client))
ac.AddCommand(NewAliasImport(client))
ac.AddCommand(NewAliasExport(client))
ac.AddCommand(NewAliasRemove(client))

return ec
return ac
}

// IOAddress returns the address in IoTeX address _format
// IOAddress returns the address in IoTeX address format
func IOAddress(in string) (address.Address, error) {
addr, err := util.Address(in)
if err != nil {
return nil, output.NewError(output.AddressError, "", err)
return nil, err
}
return address.FromString(addr)
}

// EtherAddress returns the address in ether _format
// EtherAddress returns the address in ether format
func EtherAddress(in string) (common.Address, error) {
addr, err := util.Address(in)
if err != nil {
return common.Address{}, output.NewError(output.AddressError, "", err)
return common.Address{}, err
}
return addrutil.IoAddrToEvmAddr(addr)
}

// Alias returns the alias corresponding to address
func Alias(address string) (string, error) {
if err := validator.ValidateAddress(address); err != nil {
return "", output.NewError(output.ValidationError, "", err)
}
for alias, addr := range config.ReadConfig.Aliases {
if addr == address {
return alias, nil
}
}
return "", output.NewError(output.AddressError, ErrNoAliasFound.Error(), nil)
}
73 changes: 33 additions & 40 deletions ioctl/newcmd/alias/aliasimport.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019 IoTeX Foundation
// Copyright (c) 2022 IoTeX Foundation
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
Expand All @@ -9,14 +9,13 @@ package alias
import (
"encoding/json"
"fmt"
"os"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"

"github.com/iotexproject/iotex-core/ioctl"
"github.com/iotexproject/iotex-core/ioctl/config"
"github.com/iotexproject/iotex-core/ioctl/output"
)

// Multi-language support
Expand All @@ -30,13 +29,17 @@ var (
config.Chinese: "import '数据'",
}
_flagImportFormatUsages = map[config.Language]string{
config.English: "set _format: json/yaml",
config.English: "set format: json/yaml",
config.Chinese: "设置格式:json/yaml",
}
_flagForceImportUsages = map[config.Language]string{
config.English: "override existing aliases",
config.Chinese: "覆盖现有别名",
}
_failToWriteToConfigFile = map[config.Language]string{
config.English: "Failed to write to config file.",
config.Chinese: "写入配置文件失败",
}
)

type importMessage struct {
Expand All @@ -46,77 +49,67 @@ type importMessage struct {
Unimported []alias `json:"unimported"`
}

// NewAliasImportCmd represents the alias import command
func NewAliasImportCmd(c ioctl.Client) *cobra.Command {
// NewAliasImport represents the alias import command
func NewAliasImport(c ioctl.Client) *cobra.Command {
var (
format string
forceImport bool
)

use, _ := c.SelectTranslation(_importUses)
short, _ := c.SelectTranslation(_importShorts)
flagImportFormatUsage, _ := c.SelectTranslation(_flagImportFormatUsages)
flagForceImportUsage, _ := c.SelectTranslation(_flagForceImportUsages)
failToWriteToConfigFile, _ := c.SelectTranslation(_failToWriteToConfigFile)

ec := &cobra.Command{
Use: use,
Short: short,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
var err error
var importedAliases aliases
switch _format {
default:
return output.NewError(output.FlagError, fmt.Sprintf("invalid format flag%s", _format), nil)

switch format {
case "json":
if err := json.Unmarshal([]byte(args[0]), &importedAliases); err != nil {
return output.NewError(output.SerializationError, "failed to unmarshal imported aliases", err)
return errors.Wrap(err, "failed to unmarshal imported aliases")
}
case "yaml":
if err := yaml.Unmarshal([]byte(args[0]), &importedAliases); err != nil {
return output.NewError(output.SerializationError, "failed to unmarshal imported aliases", err)
return errors.Wrap(err, "failed to unmarshal imported aliases")
}
default:
return errors.New(fmt.Sprintf("invalid flag%s", format))
}
aliases := c.AliasMap()

message := importMessage{TotalNumber: len(importedAliases.Aliases), ImportedNumber: 0}
for _, importedAlias := range importedAliases.Aliases {
if !_forceImport && config.ReadConfig.Aliases[importedAlias.Name] != "" {
if !forceImport && c.Config().Aliases[importedAlias.Name] != "" {
message.Unimported = append(message.Unimported, importedAlias)
continue
}
for aliases[importedAlias.Address] != "" {
delete(config.ReadConfig.Aliases, aliases[importedAlias.Address])
aliases = c.AliasMap()
}
config.ReadConfig.Aliases[importedAlias.Name] = importedAlias.Address
c.SetAlias(args[0], importedAlias.Address)
message.Imported = append(message.Imported, importedAlias)
message.ImportedNumber++
}
out, err := yaml.Marshal(&config.ReadConfig)
if err != nil {
return output.NewError(output.SerializationError, "failed to marshal config", err)
if err := c.WriteConfig(); err != nil {
return errors.Wrapf(err, failToWriteToConfigFile)
}
if err := os.WriteFile(config.DefaultConfigFile, out, 0600); err != nil {
return output.NewError(output.WriteFileError,
fmt.Sprintf("failed to write to config file %s", config.DefaultConfigFile), err)

line := fmt.Sprintf("%d/%d aliases imported\nExisted aliases:", message.ImportedNumber, message.TotalNumber)
for _, alias := range message.Unimported {
line += fmt.Sprint(" " + alias.Name)
}
fmt.Println(message.String())
cmd.Println(line)
return nil

},
}

ec.Flags().StringVarP(&_format,
ec.Flags().StringVarP(&format,
"format=", "f", "json", flagImportFormatUsage)
ec.Flags().BoolVarP(&_forceImport,
ec.Flags().BoolVarP(&forceImport,
"force-import", "F", false, flagForceImportUsage)

return ec
}

func (m *importMessage) String() string {
if output.Format == "" {
line := fmt.Sprintf("%d/%d aliases imported\nExisted aliases:", m.ImportedNumber, m.TotalNumber)
for _, alias := range m.Unimported {
line += fmt.Sprint(" " + alias.Name)
}
return line
}
return output.FormatString(output.Result, m)
}
Loading

0 comments on commit de09d24

Please sign in to comment.