Update to make full use of new tmlibs/cli helpers

This commit is contained in:
Ethan Frey
2017-05-05 19:25:44 +02:00
parent 524ba917a3
commit e71bbb2509
9 changed files with 55 additions and 189 deletions
-120
View File
@@ -1,120 +0,0 @@
package cmd
import (
"fmt"
"os"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
data "github.com/tendermint/go-wire/data"
"github.com/tendermint/go-wire/data/base58"
)
/*******
TODO
This file should move into go-common or the like as a basis for all cli tools.
It is here for experimentation of re-use between go-keys and light-client.
*********/
const (
RootFlag = "root"
OutputFlag = "output"
EncodingFlag = "encoding"
)
func PrepareMainCmd(cmd *cobra.Command, envPrefix, defautRoot string) func() {
cobra.OnInitialize(func() { initEnv(envPrefix) })
cmd.PersistentFlags().StringP(RootFlag, "r", defautRoot, "root directory for config and data")
cmd.PersistentFlags().StringP(EncodingFlag, "e", "hex", "Binary encoding (hex|b64|btc)")
cmd.PersistentFlags().StringP(OutputFlag, "o", "text", "Output format (text|json)")
cmd.PersistentPreRunE = multiE(bindFlags, setEncoding, validateOutput, cmd.PersistentPreRunE)
return func() { execute(cmd) }
}
// initEnv sets to use ENV variables if set.
func initEnv(prefix string) {
// env variables with TM prefix (eg. TM_ROOT)
viper.SetEnvPrefix(prefix)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
}
// execute adds all child commands to the root command sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func execute(cmd *cobra.Command) {
if err := cmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(-1)
}
}
type wrapE func(cmd *cobra.Command, args []string) error
func multiE(fs ...wrapE) wrapE {
return func(cmd *cobra.Command, args []string) error {
for _, f := range fs {
if f != nil {
if err := f(cmd, args); err != nil {
return err
}
}
}
return nil
}
}
func bindFlags(cmd *cobra.Command, args []string) error {
// cmd.Flags() includes flags from this command and all persistent flags from the parent
if err := viper.BindPFlags(cmd.Flags()); err != nil {
return err
}
// rootDir is command line flag, env variable, or default $HOME/.tlc
rootDir := viper.GetString("root")
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath(rootDir) // search root directory
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
// stderr, so if we redirect output to json file, this doesn't appear
// fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
} else if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
// we ignore not found error, only parse error
// stderr, so if we redirect output to json file, this doesn't appear
fmt.Fprintf(os.Stderr, "%#v", err)
}
return nil
}
// setEncoding reads the encoding flag
func setEncoding(cmd *cobra.Command, args []string) error {
// validate and set encoding
enc := viper.GetString("encoding")
switch enc {
case "hex":
data.Encoder = data.HexEncoder
case "b64":
data.Encoder = data.B64Encoder
case "btc":
data.Encoder = base58.BTCEncoder
default:
return errors.Errorf("Unsupported encoding: %s", enc)
}
return nil
}
func validateOutput(cmd *cobra.Command, args []string) error {
// validate output format
output := viper.GetString(OutputFlag)
switch output {
case "text", "json":
default:
return errors.Errorf("Unsupported output format: %s", output)
}
return nil
}
+6 -9
View File
@@ -15,7 +15,7 @@
package cmd
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -25,20 +25,17 @@ var getCmd = &cobra.Command{
Use: "get <name>",
Short: "Get details of one key",
Long: `Return public details of one local key.`,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 || len(args[0]) == 0 {
fmt.Println("You must provide a name for the key")
return
return errors.New("You must provide a name for the key")
}
name := args[0]
info, err := GetKeyManager().Get(name)
if err != nil {
fmt.Println(err.Error())
return
if err == nil {
printInfo(info)
}
printInfo(info)
return err
},
}
+2 -3
View File
@@ -22,7 +22,6 @@ import (
)
func main() {
cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc"))
cmd.RootCmd.Execute()
// exec()
root := cli.PrepareMainCmd(cmd.RootCmd, "TM", os.ExpandEnv("$HOME/.tlc"))
root.Execute()
}
+5 -11
View File
@@ -14,11 +14,7 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
import "github.com/spf13/cobra"
// listCmd represents the list command
var listCmd = &cobra.Command{
@@ -26,14 +22,12 @@ var listCmd = &cobra.Command{
Short: "List all keys",
Long: `Return a list of all public keys stored by this key manager
along with their associated name and address.`,
Run: func(cmd *cobra.Command, args []string) {
RunE: func(cmd *cobra.Command, args []string) error {
infos, err := GetKeyManager().List()
if err != nil {
fmt.Println(err.Error())
return
if err == nil {
printInfos(infos)
}
printInfos(infos)
return err
},
}
+8 -12
View File
@@ -15,7 +15,7 @@
package cmd
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@@ -28,7 +28,7 @@ var newCmd = &cobra.Command{
Long: `Add a public/private key pair to the key store.
The password muts be entered in the terminal and not
passed as a command line argument for security.`,
Run: newPassword,
RunE: newPassword,
}
func init() {
@@ -36,25 +36,21 @@ func init() {
newCmd.Flags().StringP("type", "t", "ed25519", "Type of key (ed25519|secp256k1)")
}
func newPassword(cmd *cobra.Command, args []string) {
func newPassword(cmd *cobra.Command, args []string) error {
if len(args) != 1 || len(args[0]) == 0 {
fmt.Println("You must provide a name for the key")
return
return errors.New("You must provide a name for the key")
}
name := args[0]
algo := viper.GetString("type")
pass, err := getCheckPassword("Enter a passphrase:", "Repeat the passphrase:")
if err != nil {
fmt.Println(err.Error())
return
return err
}
info, err := GetKeyManager().Create(name, pass, algo)
if err != nil {
fmt.Println(err.Error())
return
if err == nil {
printInfo(info)
}
printInfo(info)
return err
}
+2 -1
View File
@@ -22,6 +22,7 @@ import (
keys "github.com/tendermint/go-crypto/keys"
"github.com/tendermint/go-crypto/keys/cryptostore"
"github.com/tendermint/go-crypto/keys/storage/filestorage"
"github.com/tendermint/tmlibs/cli"
)
const KeySubdir = "keys"
@@ -45,7 +46,7 @@ needs to sign with a private key.`,
func GetKeyManager() keys.Manager {
if manager == nil {
// store the keys directory
rootDir := viper.GetString("root")
rootDir := viper.GetString(cli.HomeFlag)
keyDir := filepath.Join(rootDir, KeySubdir)
// and construct the key manager
manager = cryptostore.New(
+10 -11
View File
@@ -17,6 +17,8 @@ package cmd
import (
"fmt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -25,35 +27,32 @@ var updateCmd = &cobra.Command{
Use: "update <name>",
Short: "Change the password for a private key",
Long: `Change the password for a private key.`,
Run: updatePassword,
RunE: updatePassword,
}
func init() {
RootCmd.AddCommand(updateCmd)
}
func updatePassword(cmd *cobra.Command, args []string) {
func updatePassword(cmd *cobra.Command, args []string) error {
if len(args) != 1 || len(args[0]) == 0 {
fmt.Println("You must provide a name for the key")
return
return errors.New("You must provide a name for the key")
}
name := args[0]
oldpass, err := getPassword("Enter the current passphrase:")
if err != nil {
fmt.Println(err.Error())
return
return err
}
newpass, err := getCheckPassword("Enter the new passphrase:", "Repeat the new passphrase:")
if err != nil {
fmt.Println(err.Error())
return
return err
}
err = GetKeyManager().Update(name, oldpass, newpass)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("Password successfully updated!")
return err
}
fmt.Println("Password successfully updated!")
return nil
}
+3 -2
View File
@@ -8,6 +8,7 @@ import (
"github.com/spf13/viper"
keys "github.com/tendermint/go-crypto/keys"
data "github.com/tendermint/go-wire/data"
"github.com/tendermint/tmlibs/cli"
)
const PassLength = 10
@@ -40,7 +41,7 @@ func getCheckPassword(prompt, prompt2 string) (string, error) {
}
func printInfo(info keys.Info) {
switch viper.Get(OutputFlag) {
switch viper.Get(cli.OutputFlag) {
case "text":
addr, err := data.ToText(info.Address)
if err != nil {
@@ -61,7 +62,7 @@ func printInfo(info keys.Info) {
}
func printInfos(infos keys.Infos) {
switch viper.Get(OutputFlag) {
switch viper.Get(cli.OutputFlag) {
case "text":
fmt.Println("All keys:")
for _, i := range infos {