Skip to content

Commit

Permalink
refactor: Reorganize global CLI flags (#2615)
Browse files Browse the repository at this point in the history
## Relevant issue(s)

Resolves #2614
Resolves #2582

## Description

This PR moves the global CLI flags that only apply to the start command.
It also fixes the log color config issue above.

## Tasks

- [x] I made sure the code is well commented, particularly
hard-to-understand areas.
- [x] I made sure the repository-held documentation is changed
accordingly.
- [x] I made sure the pull request title adheres to the conventional
commit style (the subset used in the project can be found in
[tools/configs/chglog/config.yml](tools/configs/chglog/config.yml)).
- [x] I made sure to discuss its limitations such as threats to
validity, vulnerability to mistake and misuse, robustness to
invalidation of assumptions, resource requirements, ...

## How has this been tested?

`make test`

Specify the platform(s) on which this was tested:
- MacOS
  • Loading branch information
nasdf authored May 14, 2024
1 parent 575ea2a commit 530f21e
Show file tree
Hide file tree
Showing 62 changed files with 988 additions and 1,485 deletions.
73 changes: 38 additions & 35 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
package cli

import (
"errors"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -39,29 +40,29 @@ var configPaths = []string{
"keyring.path",
}

// configFlags is a mapping of config keys to cli flags to bind to.
// configFlags is a mapping of cli flag names to config keys to bind.
var configFlags = map[string]string{
"log.level": "log-level",
"log.output": "log-output",
"log.format": "log-format",
"log.stacktrace": "log-stacktrace",
"log.source": "log-source",
"log.overrides": "log-overrides",
"log.nocolor": "log-no-color",
"api.address": "url",
"datastore.maxtxnretries": "max-txn-retries",
"datastore.store": "store",
"datastore.badger.valuelogfilesize": "valuelogfilesize",
"net.peers": "peers",
"net.p2paddresses": "p2paddr",
"net.p2pdisabled": "no-p2p",
"api.allowed-origins": "allowed-origins",
"api.pubkeypath": "pubkeypath",
"api.privkeypath": "privkeypath",
"keyring.namespace": "keyring-namespace",
"keyring.backend": "keyring-backend",
"keyring.path": "keyring-path",
"keyring.disabled": "no-keyring",
"log-level": "log.level",
"log-output": "log.output",
"log-format": "log.format",
"log-stacktrace": "log.stacktrace",
"log-source": "log.source",
"log-overrides": "log.overrides",
"no-log-color": "log.colordisabled",
"url": "api.address",
"max-txn-retries": "datastore.maxtxnretries",
"store": "datastore.store",
"valuelogfilesize": "datastore.badger.valuelogfilesize",
"peers": "net.peers",
"p2paddr": "net.p2paddresses",
"no-p2p": "net.p2pdisabled",
"allowed-origins": "api.allowed-origins",
"pubkeypath": "api.pubkeypath",
"privkeypath": "api.privkeypath",
"keyring-namespace": "keyring.namespace",
"keyring-backend": "keyring.backend",
"keyring-path": "keyring.path",
"no-keyring": "keyring.disabled",
}

// defaultConfig returns a new config with default values.
Expand All @@ -84,11 +85,11 @@ func defaultConfig() *viper.Viper {
}

// createConfig writes the default config file if one does not exist.
func createConfig(rootdir string, flags *pflag.FlagSet) error {
func createConfig(rootdir string) error {
cfg := defaultConfig()
cfg.AddConfigPath(rootdir)

if err := bindConfigFlags(cfg, flags); err != nil {
if err := bindConfigFlags(cfg); err != nil {
return err
}
// make sure rootdir exists
Expand All @@ -106,7 +107,7 @@ func createConfig(rootdir string, flags *pflag.FlagSet) error {
}

// loadConfig returns a new config with values from the config in the given rootdir.
func loadConfig(rootdir string, flags *pflag.FlagSet) (*viper.Viper, error) {
func loadConfig(rootdir string) (*viper.Viper, error) {
cfg := defaultConfig()
cfg.AddConfigPath(rootdir)

Expand All @@ -119,7 +120,7 @@ func loadConfig(rootdir string, flags *pflag.FlagSet) (*viper.Viper, error) {
return nil, err
}
// bind cli flags to config keys
if err := bindConfigFlags(cfg, flags); err != nil {
if err := bindConfigFlags(cfg); err != nil {
return nil, err
}

Expand All @@ -131,13 +132,14 @@ func loadConfig(rootdir string, flags *pflag.FlagSet) (*viper.Viper, error) {
}
}

// set default logging config
// set logging config
corelog.SetConfig(corelog.Config{
Level: cfg.GetString("log.level"),
Format: cfg.GetString("log.format"),
Output: cfg.GetString("log.output"),
EnableStackTrace: cfg.GetBool("log.stacktrace"),
EnableSource: cfg.GetBool("log.source"),
DisableColor: cfg.GetBool("log.colordisabled"),
})

// set logging config overrides
Expand All @@ -147,12 +149,13 @@ func loadConfig(rootdir string, flags *pflag.FlagSet) (*viper.Viper, error) {
}

// bindConfigFlags binds the set of cli flags to config values.
func bindConfigFlags(cfg *viper.Viper, flags *pflag.FlagSet) error {
for key, flag := range configFlags {
err := cfg.BindPFlag(key, flags.Lookup(flag))
if err != nil {
return err
}
}
return nil
func bindConfigFlags(cfg *viper.Viper) error {
var errs []error
rootFlags.VisitAll(func(f *pflag.Flag) {
errs = append(errs, cfg.BindPFlag(configFlags[f.Name], f))
})
startFlags.VisitAll(func(f *pflag.Flag) {
errs = append(errs, cfg.BindPFlag(configFlags[f.Name], f))
})
return errors.Join(errs...)
}
8 changes: 4 additions & 4 deletions cli/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ import (

func TestCreateConfig(t *testing.T) {
rootdir := t.TempDir()
err := createConfig(rootdir, NewDefraCommand().PersistentFlags())
err := createConfig(rootdir)
require.NoError(t, err)

// ensure no errors when config already exists
err = createConfig(rootdir, NewDefraCommand().PersistentFlags())
err = createConfig(rootdir)
require.NoError(t, err)

assert.FileExists(t, filepath.Join(rootdir, "config.yaml"))
}

func TestLoadConfigNotExist(t *testing.T) {
rootdir := t.TempDir()
cfg, err := loadConfig(rootdir, NewDefraCommand().PersistentFlags())
cfg, err := loadConfig(rootdir)
require.NoError(t, err)

assert.Equal(t, 5, cfg.GetInt("datastore.maxtxnretries"))
Expand All @@ -57,7 +57,7 @@ func TestLoadConfigNotExist(t *testing.T) {
assert.Equal(t, false, cfg.GetBool("log.stacktrace"))
assert.Equal(t, false, cfg.GetBool("log.source"))
assert.Equal(t, "", cfg.GetString("log.overrides"))
assert.Equal(t, false, cfg.GetBool("log.nocolor"))
assert.Equal(t, false, cfg.GetBool("log.colordisabled"))

assert.Equal(t, filepath.Join(rootdir, "keys"), cfg.GetString("keyring.path"))
assert.Equal(t, false, cfg.GetBool("keyring.disabled"))
Expand Down
134 changes: 38 additions & 96 deletions cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,156 +12,98 @@ package cli

import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func MakeRootCommand() *cobra.Command {
var cmd = &cobra.Command{
SilenceUsage: true,
Use: "defradb",
Short: "DefraDB Edge Database",
Long: `DefraDB is the edge database to power the user-centric future.
// rootFlags is a set of persistent flags that are bound to config values.
var rootFlags = pflag.NewFlagSet("root", pflag.ContinueOnError)

Start a DefraDB node, interact with a local or remote node, and much more.
`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if err := setContextRootDir(cmd); err != nil {
return err
}
return setContextConfig(cmd)
},
}

cmd.PersistentFlags().String(
func init() {
rootFlags.String(
"rootdir",
"",
"Directory for persistent data (default: $HOME/.defradb)",
)

cmd.PersistentFlags().String(
rootFlags.String(
"log-level",
"info",
"Log level to use. Options are debug, info, error, fatal",
)

cmd.PersistentFlags().String(
rootFlags.String(
"log-output",
"stderr",
"Log output path. Options are stderr or stdout.",
)

cmd.PersistentFlags().String(
rootFlags.String(
"log-format",
"text",
"Log format to use. Options are text or json",
)

cmd.PersistentFlags().Bool(
rootFlags.Bool(
"log-stacktrace",
false,
"Include stacktrace in error and fatal logs",
)

cmd.PersistentFlags().Bool(
rootFlags.Bool(
"log-source",
false,
"Include source location in logs",
)

cmd.PersistentFlags().String(
rootFlags.String(
"log-overrides",
"",
"Logger config overrides. Format <name>,<key>=<val>,...;<name>,...",
)

cmd.PersistentFlags().Bool(
"log-no-color",
rootFlags.Bool(
"no-log-color",
false,
"Disable colored log output",
)

cmd.PersistentFlags().String(
rootFlags.String(
"url",
"127.0.0.1:9181",
"URL of HTTP endpoint to listen on or connect to",
)

cmd.PersistentFlags().StringArray(
"peers",
[]string{},
"List of peers to connect to",
)

cmd.PersistentFlags().Int(
"max-txn-retries",
5,
"Specify the maximum number of retries per transaction",
)

cmd.PersistentFlags().String(
"store",
"badger",
"Specify the datastore to use (supported: badger, memory)",
)

cmd.PersistentFlags().Int(
"valuelogfilesize",
1<<30,
"Specify the datastore value log file size (in bytes). In memory size will be 2*valuelogfilesize",
)

cmd.PersistentFlags().StringSlice(
"p2paddr",
[]string{"/ip4/127.0.0.1/tcp/9171"},
"Listen addresses for the p2p network (formatted as a libp2p MultiAddr)",
)

cmd.PersistentFlags().Bool(
"no-p2p",
false,
"Disable the peer-to-peer network synchronization system",
)

cmd.PersistentFlags().StringArray(
"allowed-origins",
[]string{},
"List of origins to allow for CORS requests",
)

cmd.PersistentFlags().String(
"pubkeypath",
"",
"Path to the public key for tls",
)

cmd.PersistentFlags().String(
"privkeypath",
"",
"Path to the private key for tls",
)

cmd.PersistentFlags().String(
rootFlags.String(
"keyring-namespace",
"defradb",
"Service name to use when using the system backend",
)

cmd.PersistentFlags().String(
rootFlags.String(
"keyring-backend",
"file",
"Keyring backend to use. Options are file or system",
)

cmd.PersistentFlags().String(
rootFlags.String(
"keyring-path",
"keys",
"Path to store encrypted keys when using the file backend",
)

cmd.PersistentFlags().Bool(
rootFlags.Bool(
"no-keyring",
false,
"Disable the keyring and generate ephemeral keys",
)
}

func MakeRootCommand() *cobra.Command {
var cmd = &cobra.Command{
SilenceUsage: true,
Use: "defradb",
Short: "DefraDB Edge Database",
Long: `DefraDB is the edge database to power the user-centric future.
Start a DefraDB node, interact with a local or remote node, and much more.
`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if err := setContextRootDir(cmd); err != nil {
return err
}
return setContextConfig(cmd)
},
}

cmd.PersistentFlags().AddFlagSet(rootFlags)

return cmd
}
Loading

0 comments on commit 530f21e

Please sign in to comment.