301 lines
6.8 KiB
Go
301 lines
6.8 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"runtime"
|
|
|
|
"github.com/rs/zerolog"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
const (
|
|
// Version roughly represents the applications current version.
|
|
Version = "0.2"
|
|
// Title is the name of the application used throughout the configuration process.
|
|
Title = "mapyweb"
|
|
)
|
|
|
|
var (
|
|
// BannerOnly when toggled causes the appllication to only print the banner and version then exit.
|
|
BannerOnly = false
|
|
// GenConfig when toggled causes the application to write its default config to the cwd and then exit.
|
|
GenConfig = false
|
|
// NoColor when true will disable the banner and any colored console output.
|
|
NoColor bool
|
|
)
|
|
|
|
// "http"
|
|
var (
|
|
// HTTPBindAddr is defined via our toml configuration file. It is the address that the http server listens on.
|
|
HTTPBindAddr string
|
|
// HTTPBindPort is defined via our toml configuration file. It is the port that the http server listens on.
|
|
HTTPBindPort string
|
|
// UseUnixSocket when toggled disables the TCP listener and listens on the given UnixSocketPath.
|
|
UseUnixSocket bool
|
|
// UnixSocketPath is the path of the unix socket used when UseUnixSocket is toggled.
|
|
UnixSocketPath = ""
|
|
// HTTPUseSSL determins whether or not we serve HTTPs
|
|
HTTPUseSSL bool
|
|
// SSLCertFile is our fullchain SSL Certificate
|
|
SSLCertFile string
|
|
// SSLKeyFile is our SSL Certificate private key
|
|
SSLKeyFile string
|
|
)
|
|
|
|
// "db"
|
|
var (
|
|
UseEmbeddedPostgres bool
|
|
SQLHost string
|
|
SQLPort string
|
|
SQLUsername string
|
|
SQLPassword string
|
|
SQLDatabase string
|
|
DataPath string
|
|
)
|
|
|
|
var (
|
|
// Filename returns the current location of our toml config file.
|
|
Filename string
|
|
)
|
|
|
|
var (
|
|
f *os.File
|
|
err error
|
|
noColorForce = false
|
|
customconfig = false
|
|
home string
|
|
configLocations []string
|
|
)
|
|
|
|
var (
|
|
// Debug is our global debug toggle
|
|
Debug bool
|
|
|
|
prefConfigLocation string
|
|
snek *viper.Viper
|
|
)
|
|
|
|
func init() {
|
|
if home, err = os.UserHomeDir(); err != nil {
|
|
panic(err)
|
|
}
|
|
prefConfigLocation = home + "/.config/" + Title
|
|
snek = viper.New()
|
|
}
|
|
|
|
func writeConfig() {
|
|
if runtime.GOOS != "windows" {
|
|
if _, err := os.Stat(prefConfigLocation); os.IsNotExist(err) {
|
|
if err = os.Mkdir(prefConfigLocation, 0755); err != nil {
|
|
println("error writing new config: " + err.Error())
|
|
}
|
|
}
|
|
newconfig := prefConfigLocation + "/" + "config.toml"
|
|
if err = snek.SafeWriteConfigAs(newconfig); err != nil {
|
|
fmt.Println(err.Error())
|
|
os.Exit(1)
|
|
}
|
|
Filename = newconfig
|
|
return
|
|
}
|
|
|
|
newconfig := Title
|
|
snek.SetConfigName(newconfig)
|
|
if err = snek.MergeInConfig(); err != nil {
|
|
if err = snek.SafeWriteConfigAs(newconfig + ".toml"); err != nil {
|
|
fmt.Println(err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
Filename = newconfig
|
|
}
|
|
|
|
// Init will initialize our toml configuration engine and define our default configuration values which can be written to a new configuration file if desired
|
|
func Init() {
|
|
snek.SetConfigType("toml")
|
|
snek.SetConfigName("config")
|
|
|
|
argParse()
|
|
|
|
if customconfig {
|
|
associate()
|
|
return
|
|
}
|
|
|
|
acquireClue()
|
|
|
|
setDefaults()
|
|
|
|
for _, loc := range configLocations {
|
|
snek.AddConfigPath(loc)
|
|
}
|
|
|
|
if err = snek.MergeInConfig(); err != nil {
|
|
writeConfig()
|
|
}
|
|
|
|
if len(Filename) < 1 {
|
|
Filename = snek.ConfigFileUsed()
|
|
}
|
|
|
|
associate()
|
|
}
|
|
|
|
func setDefaults() {
|
|
var (
|
|
// Add new configuration categories here
|
|
configSections = []string{"logger", "http", "db"}
|
|
|
|
deflogdir = home + "/.config/" + Title + "/logs/"
|
|
defNoColor = false
|
|
)
|
|
|
|
if runtime.GOOS == "windows" {
|
|
deflogdir = "logs/"
|
|
defNoColor = true
|
|
}
|
|
|
|
Opt := make(map[string]map[string]interface{})
|
|
|
|
Opt["logger"] = map[string]interface{}{
|
|
"debug": true,
|
|
"directory": deflogdir,
|
|
"nocolor": defNoColor,
|
|
"use_date_filename": true,
|
|
}
|
|
Opt["http"] = map[string]interface{}{
|
|
"use_unix_socket": false,
|
|
"unix_socket_path": "/var/run/cokeplate",
|
|
"bind_addr": "127.0.0.1",
|
|
"bind_port": "8080",
|
|
}
|
|
Opt["db"] = map[string]interface{}{
|
|
"embedded_pgsql": true,
|
|
"sql_host": "localhost",
|
|
"sql_port": "5432",
|
|
"sql_user": "postgres",
|
|
"sql_pass": "postgres",
|
|
"data_path": "./data",
|
|
}
|
|
|
|
for _, def := range configSections {
|
|
snek.SetDefault(def, Opt[def])
|
|
}
|
|
|
|
if GenConfig {
|
|
if err = snek.SafeWriteConfigAs("./config.toml"); err != nil {
|
|
fmt.Println(err.Error())
|
|
os.Exit(1)
|
|
}
|
|
os.Exit(0)
|
|
}
|
|
|
|
}
|
|
|
|
func acquireClue() {
|
|
configLocations = append(configLocations, "./")
|
|
|
|
if runtime.GOOS != "windows" {
|
|
configLocations = append(configLocations, prefConfigLocation)
|
|
configLocations = append(configLocations, "/etc/"+Title+"/")
|
|
configLocations = append(configLocations, "../")
|
|
configLocations = append(configLocations, "../../")
|
|
}
|
|
}
|
|
|
|
func loadCustomConfig(path string) {
|
|
if f, err = os.Open(path); err != nil {
|
|
println("Error opening specified config file: " + path)
|
|
panic("config file open fatal error: " + err.Error())
|
|
}
|
|
buf, err := ioutil.ReadAll(f)
|
|
err2 := snek.ReadConfig(bytes.NewBuffer(buf))
|
|
switch {
|
|
case err != nil:
|
|
fmt.Println("config file read fatal error: ", err.Error())
|
|
case err2 != nil:
|
|
fmt.Println("config file read fatal error: ", err2.Error())
|
|
default:
|
|
break
|
|
}
|
|
customconfig = true
|
|
}
|
|
|
|
func printUsage() {
|
|
println("\n" + Title + " v" + Version + " Usage\n")
|
|
println("-c <config.toml> - Specify config file")
|
|
println("--nocolor - disable color and banner ")
|
|
println("--banner - show banner + version and exit")
|
|
println("--genconfig - write default config to 'default.toml' then exit")
|
|
os.Exit(0)
|
|
}
|
|
|
|
// TODO: should probably just make a proper CLI with flags or something
|
|
func argParse() {
|
|
for i, arg := range os.Args {
|
|
switch arg {
|
|
case "-h":
|
|
printUsage()
|
|
case "--genconfig":
|
|
GenConfig = true
|
|
case "--nocolor":
|
|
noColorForce = true
|
|
case "--banner":
|
|
BannerOnly = true
|
|
case "--config":
|
|
fallthrough
|
|
case "-c":
|
|
if len(os.Args) <= i-1 {
|
|
panic("syntax error! expected file after -c")
|
|
}
|
|
loadCustomConfig(os.Args[i+1])
|
|
default:
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
func bl(key string) bool {
|
|
return snek.GetBool(key)
|
|
}
|
|
func st(key string) string {
|
|
return snek.GetString(key)
|
|
}
|
|
func sl(key string) []string {
|
|
return snek.GetStringSlice(key)
|
|
}
|
|
func it(key string) int {
|
|
return snek.GetInt(key)
|
|
}
|
|
|
|
func associate() {
|
|
HTTPBindAddr = st("http.bind_addr")
|
|
HTTPBindPort = st("http.bind_port")
|
|
UseUnixSocket = bl("http.use_unix_socket")
|
|
|
|
SQLPassword = st("db.sql_password")
|
|
SQLUsername = st("db.sql_username")
|
|
SQLDatabase = st("db.sql_database")
|
|
SQLHost = st("db.sql_host")
|
|
SQLPort = st("db.sql_port")
|
|
DataPath = st("db.data_path")
|
|
|
|
Debug = bl("logger.debug")
|
|
logDir = st("logger.directory")
|
|
NoColor = bl("logger.nocolor")
|
|
|
|
if noColorForce {
|
|
NoColor = true
|
|
}
|
|
// if UseUnixSocket {
|
|
// UnixSocketPath = snek.GetString("http.unix_socket_path")
|
|
// }
|
|
if Debug {
|
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
}
|
|
}
|