config/config.go
package config
import (
"fmt"
"strings"
"github.com/spf13/cast"
"github.com/spf13/viper"
"github.com/sprawl/sprawl/errors"
)
const dbPathVar string = "database.path"
const dbInMemoryVar string = "database.inMemory"
const rpcPortVar string = "rpc.port"
const p2pExternalIPVar string = "p2p.externalIP"
const p2pPortVar string = "p2p.port"
const p2pDebugVar string = "p2p.debug"
const p2pRelayVar string = "p2p.enableRelay"
const p2pAutoRelayVar string = "p2p.enableAutoRelay"
const p2pNATPortMapVar string = "p2p.enableNATPortMap"
const ipfsPeerVar string = "p2p.useIPFSPeers"
const errorsEnableStackTraceVar string = "errors.enableStackTrace"
const logLevelVar string = "log.level"
const logFormatVar string = "log.format"
const websocketEnableVar string = "websocket.enable"
const websocketPortVar string = "websocket.port"
// Config has an initialized version of spf13/viper
type Config struct {
v *viper.Viper
strings map[string]string
booleans map[string]bool
uints map[string]uint
}
// ReadConfig opens the configuration file and initializes viper
func (c *Config) ReadConfig(configPath string) {
// Init viper
c.v = viper.New()
// Init maps where the config will be stored
c.strings = make(map[string]string)
c.booleans = make(map[string]bool)
c.uints = make(map[string]uint)
// Define where viper tries to get config information
envPrefix := "sprawl"
// Set environment variable prefix, automatically transformed to uppercase
c.v.SetEnvPrefix(envPrefix)
// Set replacer to env variables, replacing dots with underscores
c.v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
// Automatically try to fetch all configs from env
c.v.AutomaticEnv()
// Initialize viper with Sprawl-specific options
c.v.SetConfigName("config")
// Use toml format for config files
c.v.SetConfigType("toml")
// Allow build to disable config file directories
if configPath != "" {
// Check for overriding config files
c.v.AddConfigPath(".")
// Check for user submitted config path
c.v.AddConfigPath(configPath)
}
// Read config file
if err := c.v.ReadInConfig(); !errors.IsEmpty(err) {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
fmt.Println("Config file not found, using ENV")
} else {
fmt.Println("Config file invalid!")
}
} else {
fmt.Println("Config successfully loaded.")
}
c.AddString(dbPathVar)
c.AddString(p2pExternalIPVar)
c.AddString(logLevelVar)
c.AddString(logFormatVar)
c.AddUint(p2pPortVar)
c.AddUint(rpcPortVar)
c.AddUint(websocketPortVar)
c.AddBoolean(websocketEnableVar)
c.AddBoolean(dbInMemoryVar)
c.AddBoolean(p2pNATPortMapVar)
c.AddBoolean(p2pRelayVar)
c.AddBoolean(p2pAutoRelayVar)
c.AddBoolean(p2pDebugVar)
c.AddBoolean(errorsEnableStackTraceVar)
c.AddBoolean(ipfsPeerVar)
}
// AddString to config and print a message, if default is used.
func (c *Config) AddString(key string) {
err := c.AddStringE(key)
if err != nil {
fmt.Println(key + ": set to \"\"")
}
}
// AddBoolean to config and print a message, if default is used.
func (c *Config) AddBoolean(key string) {
err := c.AddBooleanE(key)
if err != nil {
fmt.Println(key + ": set to false")
}
}
// AddUint to config and print a message, if default is used.
func (c *Config) AddUint(key string) {
err := c.AddUintE(key)
if err != nil {
fmt.Println(key + ": set to 0")
}
}
// AddStringE (default "") to config and return error
func (c *Config) AddStringE(key string) error {
s, err := cast.ToStringE(c.v.Get(key))
c.strings[key] = s
return err
}
// AddBooleanE (default false) to config and return error
func (c *Config) AddBooleanE(key string) error {
b, err := cast.ToBoolE(c.v.Get(key))
c.booleans[key] = b
return err
}
// AddUintE (default 0) to config and return error
func (c *Config) AddUintE(key string) error {
b, err := cast.ToUintE(c.v.Get(key))
c.uints[key] = b
return err
}
// GetDatabasePath defines the host directory for the database
func (c *Config) GetDatabasePath() string {
return c.strings[dbPathVar]
}
// GetExternalIP defines the listened external IP for P2P
func (c *Config) GetExternalIP() string {
return c.strings[p2pExternalIPVar]
}
// GetLogLevel gets configured log level for uber/zap
func (c *Config) GetLogLevel() string {
return c.strings[logLevelVar]
}
// GetLogFormat gets configured log format for uber/zap
func (c *Config) GetLogFormat() string {
return c.strings[logFormatVar]
}
// GetP2PPort defines the listened P2P port
func (c *Config) GetP2PPort() uint {
return c.uints[p2pPortVar]
}
// GetRPCPort defines the port the gRPC is running at
func (c *Config) GetRPCPort() uint {
return c.uints[rpcPortVar]
}
// GetWebsocketPort defines port for websocket connections. websocket.enable must be true or the port is not used.
func (c *Config) GetWebsocketPort() uint {
return c.uints[websocketPortVar]
}
// GetWebsocketEnable defines if websocket connections are allowed. Starts waiting http request using websocket.port
func (c *Config) GetWebsocketEnable() bool {
return c.booleans[websocketEnableVar]
}
// GetInMemoryDatabaseSetting defines if RAM is used instead of LevelDB for storage
func (c *Config) GetInMemoryDatabaseSetting() bool {
return c.booleans[dbInMemoryVar]
}
// GetNATPortMapSetting defines whether to use NAT port mapping or not
func (c *Config) GetNATPortMapSetting() bool {
return c.booleans[p2pNATPortMapVar]
}
// GetRelaySetting defines whether to run the node in relay mode or not
func (c *Config) GetRelaySetting() bool {
return c.booleans[p2pRelayVar]
}
// GetAutoRelaySetting defines whether to run the node in autorelay mode or not
func (c *Config) GetAutoRelaySetting() bool {
return c.booleans[p2pAutoRelayVar]
}
// GetDebugSetting defines whether to run the debug pinger or not
func (c *Config) GetDebugSetting() bool {
return c.booleans[p2pDebugVar]
}
// GetStackTraceSetting defines whether to run the debug pinger or not
func (c *Config) GetStackTraceSetting() bool {
return c.booleans[errorsEnableStackTraceVar]
}
// GetIPFSPeerSetting defines if we use IPFS bootstrap peers for discovery or just our own
func (c *Config) GetIPFSPeerSetting() bool {
return c.booleans[ipfsPeerVar]
}