Skip to content

Commit

Permalink
cmd/node: make loadConfig directly log any errors
Browse files Browse the repository at this point in the history
The function already logged at the info level,
so do the same for any messages like "creating config file".

For any errors that means we can't continue,
log at the fatal level directly rather than returning an error.
This is a function used only by the main function, so that's fine.
It also keeps our code easier to follow.

We also make errors such as "failed to read config",
"failed to unmarshal config", and "failed to write config" fatal,
so as to not log them as warnings and silently continue.
If there are any such errors, the user likely wants to correct them.
  • Loading branch information
mvdan authored and p4u committed Dec 21, 2023
1 parent 42b43f6 commit 1ca3a1a
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 55 deletions.
59 changes: 14 additions & 45 deletions cmd/node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,19 +110,14 @@ func (p pflagValue) HasChanged() bool { return p.flag.Changed }
func (p pflagValue) ValueString() string { return p.flag.Value.String() }
func (p pflagValue) ValueType() string { return p.flag.Value.Type() }

// newConfig creates a new config object and loads the stored configuration file
func newConfig() (*config.Config, config.Error) {
var cfgError config.Error
// loadConfig creates a new config object and loads the stored configuration file
func loadConfig() *config.Config {
conf := &config.Config{}

// get current user home dir
home, err := os.UserHomeDir()
if err != nil {
cfgError = config.Error{
Critical: true,
Message: fmt.Sprintf("cannot get user home directory with error: %s", err),
}
return nil, cfgError
log.Fatal(err)
}

// CLI flags will be used if something fails from this point
Expand Down Expand Up @@ -252,48 +247,35 @@ func newConfig() (*config.Config, config.Error) {
// check if config file exists
_, err = os.Stat(conf.DataDir + "/vocdoni.yml")
if os.IsNotExist(err) {
cfgError = config.Error{
Message: fmt.Sprintf("creating new config file in %s", conf.DataDir),
}
log.Infof("creating new config file in %s", conf.DataDir)
// creating config folder if not exists
err = os.MkdirAll(conf.DataDir, os.ModePerm)
if err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot create data directory: %s", err),
}
log.Fatalf("cannot create data directory: %s", err)
}
// create config file if not exists
if err := viper.SafeWriteConfig(); err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot write config file into config dir: %s", err),
}
log.Fatalf("cannot write config file into config dir: %s", err)
}
} else {
// read config file
err = viper.ReadInConfig()
if err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot read loaded config file in %s: %s", conf.DataDir, err),
}
log.Fatalf("cannot read loaded config file in %s: %s", conf.DataDir, err)
}
}

err = viper.Unmarshal(&conf)
if err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot unmarshal loaded config file: %s", err),
}
log.Fatalf("cannot unmarshal loaded config file: %s", err)
}

if conf.SigningKey == "" {
log.Info("no signing key, generating one...")
signer := ethereum.NewSignKeys()
err = signer.Generate()
if err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot generate signing key: %s", err),
}
return conf, cfgError
log.Fatalf("cannot generate signing key: %s", err)
}
_, priv := signer.HexString()
viper.Set("signingKey", priv)
Expand All @@ -313,13 +295,11 @@ func newConfig() (*config.Config, config.Error) {
if flagSaveConfig {
viper.Set("saveConfig", false)
if err := viper.WriteConfig(); err != nil {
cfgError = config.Error{
Message: fmt.Sprintf("cannot overwrite config file into config dir: %s", err),
}
log.Fatalf("cannot overwrite config file into config dir: %s", err)
}
}

return conf, cfgError
return conf
}

func main() {
Expand All @@ -328,10 +308,8 @@ func main() {
fmt.Fprintf(os.Stderr, "vocdoni version %q\n", internal.Version)

// creating config and init logger
conf, cfgErr := newConfig()
if conf == nil {
log.Fatal("cannot read configuration")
}
conf := loadConfig()

var errorOutput io.Writer
if path := conf.LogErrorFile; path != "" {
f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
Expand All @@ -345,6 +323,7 @@ func main() {
// Once the logger has been initialized.
log.Infof("using file %s for logging warning and errors", path)
}
log.Debugf("loaded config %+v", *conf)

// Check if we need to create a vochain genesis file with validators and exit.
if flagVochainCreateGenesis != "" {
Expand All @@ -363,16 +342,6 @@ func main() {
return
}

// Check if errors during config creation and determine if Critical.
log.Debugf("initializing config %+v", *conf)
if cfgErr.Critical && cfgErr.Message != "" {
log.Fatalf("critical error loading config: %s", cfgErr.Message)
} else if !cfgErr.Critical && cfgErr.Message != "" {
log.Warnf("non-critical error loading config: %s", cfgErr.Message)
} else if !cfgErr.Critical && cfgErr.Message == "" {
log.Infof("config file loaded successfully. Reminder: CLI flags have preference")
}

// Overwrite the default path to download the zksnarks circuits artifacts
// using the global datadir as parent folder.
circuit.BaseDir = filepath.Join(conf.DataDir, "zkCircuits")
Expand Down
10 changes: 0 additions & 10 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,3 @@ type MetricsCfg struct {
Enabled bool
RefreshInterval int
}

// TODO(mvdan): replace with a special error type

// Error helps to handle better config errors on startup
type Error struct {
// Critical indicates if the error encountered is critical and the app must be stopped
Critical bool
// Message error message
Message string
}

0 comments on commit 1ca3a1a

Please sign in to comment.