github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/cmd/commands/config/command.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package config 19 20 import ( 21 "fmt" 22 "sort" 23 "strings" 24 25 "github.com/urfave/cli/v2" 26 27 "github.com/mysteriumnetwork/node/cmd/commands/cli/clio" 28 "github.com/mysteriumnetwork/node/config" 29 "github.com/mysteriumnetwork/node/tequilapi/client" 30 ) 31 32 // CommandName is the name which is used to call this command 33 const CommandName = "config" 34 35 // NewCommand function creates license command. 36 func NewCommand() *cli.Command { 37 cmd := &command{} 38 return &cli.Command{ 39 Name: CommandName, 40 Usage: "Manage your node config", 41 Description: "Using config subcommands you can view and manage your current node config", 42 Flags: []cli.Flag{&config.FlagTequilapiAddress, &config.FlagTequilapiPort}, 43 Before: func(ctx *cli.Context) error { 44 var err error 45 cmd.tc, err = clio.NewTequilApiClient(ctx) 46 return err 47 }, 48 Subcommands: []*cli.Command{ 49 { 50 Name: "show", 51 Usage: "Show current node config", 52 Action: func(ctx *cli.Context) error { 53 cmd.show() 54 return nil 55 }, 56 }, 57 { 58 Name: "set", 59 Usage: "Set node config value", 60 Action: cmd.set, 61 }, 62 }, 63 } 64 } 65 66 type command struct { 67 tc *client.Client 68 } 69 70 func (c *command) show() { 71 config, err := c.tc.FetchConfig() 72 if err != nil { 73 clio.Error("Failed to fetch current config") 74 return 75 } 76 77 dest := map[string]string{} 78 squishMap(config, dest) 79 80 if len(dest) == 0 { 81 clio.Error("Config is empty or impossible to parse") 82 return 83 } 84 85 printMapOrdered(dest) 86 } 87 88 func (c *command) set(ctx *cli.Context) error { 89 if ctx.Args().Len() != 2 { 90 clio.Error("Exactly 2 arguments required, got:", ctx.Args().Len()) 91 return fmt.Errorf("wrong number of arguments") 92 } 93 94 config := map[string]interface{}{ctx.Args().Get(0): ctx.Args().Get(1)} 95 96 err := c.tc.SetConfig(config) 97 if err != nil { 98 clio.Error("Failed to set user config", err) 99 return err 100 } 101 102 return nil 103 } 104 105 // Orders keys alphabetically and prints a given map. 106 func printMapOrdered(m map[string]string) { 107 keys := make([]string, 0, len(m)) 108 for k := range m { 109 keys = append(keys, k) 110 } 111 sort.Strings(keys) 112 113 for _, k := range keys { 114 fmt.Println(k+":", m[k]) 115 } 116 } 117 118 // squishMap squishMap a given `source` map by checking every map 119 // value and converting it to a string. 120 // If a map value is another map, it will also be parsed and will gain 121 // a key which is equal to both map keys joined with a `.` symbol. 122 func squishMap(source map[string]interface{}, dest map[string]string, prefix ...string) { 123 keyPrefix := "" 124 if len(prefix) != 0 { 125 keyPrefix = strings.Join(prefix, ".") 126 } 127 128 for k, v := range source { 129 if nm, ok := v.(map[string]interface{}); ok { 130 squishMap(nm, dest, k) 131 } else { 132 if keyPrefix != "" { 133 k = keyPrefix + "." + k 134 } 135 136 dest[k] = fmt.Sprint(v) 137 } 138 } 139 }