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  }