1
0

Vikunja now uses viper to handle config

This commit is contained in:
konrad
2018-09-08 13:29:35 +02:00
parent 4f3e016751
commit 427f752990
13 changed files with 256 additions and 109 deletions

View File

@ -1,28 +1,57 @@
package models
import (
"github.com/go-ini/ini"
"crypto/rand"
"fmt"
"github.com/spf13/viper"
"os"
"strings"
)
// ConfigStruct holds the config struct
type ConfigStruct struct {
Database struct {
Type string
Host string
User string
Password string
Database string
Path string
ShowQueries bool
func InitConfig() (err error) {
// Set defaults
// Service config
random, err := random(32)
if err != nil {
return err
}
JWTLoginSecret []byte
Interface string
viper.SetDefault("service.JWTSecret", random)
viper.SetDefault("service.interface", ":3456")
// Database
viper.SetDefault("database.type", "sqlite")
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.user", "vikunja")
viper.SetDefault("database.password", "")
viper.SetDefault("database.database", "vikunja")
viper.SetDefault("database.path", "./vikunja.db")
viper.SetDefault("database.showqueries", false)
// Init checking for environment variables
viper.SetEnvPrefix("vikunja")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// Load the config file
viper.AddConfigPath(".")
viper.SetConfigName("config")
err = viper.ReadInConfig()
if err != nil {
return
}
return
}
// Config holds the configuration for the program
var Config = new(ConfigStruct)
func random(length int) (string, error) {
b := make([]byte, length)
if _, err := rand.Read(b); err != nil {
return "", err
}
return fmt.Sprintf("%X", b), nil
}
// SetConfig initianlises the config and publishes it for other functions to use
func SetConfig() (err error) {
@ -33,25 +62,25 @@ func SetConfig() (err error) {
}
// Load the config
cfg, err := ini.Load("config.ini")
//cfg, err := ini.Load("config.ini")
if err != nil {
return err
}
// Map the config to our struct
err = cfg.MapTo(Config)
//err = cfg.MapTo(Config)
if err != nil {
return err
}
// Set default value for interface to listen on
Config.Interface = cfg.Section("General").Key("Interface").String()
/*Config.Interface = cfg.Section("General").Key("Interface").String()
if Config.Interface == "" {
Config.Interface = ":8080"
}
// JWT secret
Config.JWTLoginSecret = []byte(cfg.Section("General").Key("JWTSecret").String())
Config.JWTLoginSecret = []byte(cfg.Section("General").Key("JWTSecret").String())*/
return nil
}

View File

@ -1,61 +0,0 @@
package models
import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"testing"
)
func TestSetConfig(t *testing.T) {
// Create test database
assert.NoError(t, PrepareTestDatabase())
// This should fail as it is looking for a nonexistent config
err := SetConfig()
assert.Error(t, err)
// Write an invalid config
configString := `[General
JWTSecret = Supersecret
Interface = ; This should make it automatically to :8080
[Database
Type = sqlite
Path = ./library.db`
err = ioutil.WriteFile("config.ini", []byte(configString), 0644)
assert.NoError(t, err)
// Test setConfig (should fail as we're trying to parse an invalid config)
err = SetConfig()
assert.Error(t, err)
// Delete the invalid file
err = os.Remove("config.ini")
assert.NoError(t, err)
// Write a fake config
configString = `[General]
JWTSecret = Supersecret
Interface = ; This should make it automatically to :8080
[Database]
Type = sqlite
Path = ./library.db`
err = ioutil.WriteFile("config.ini", []byte(configString), 0644)
assert.NoError(t, err)
// Test setConfig
err = SetConfig()
assert.NoError(t, err)
// Check for the values
assert.Equal(t, []byte("Supersecret"), Config.JWTLoginSecret)
assert.Equal(t, string(":8080"), Config.Interface)
assert.Equal(t, string("sqlite"), Config.Database.Type)
assert.Equal(t, string("./library.db"), Config.Database.Path)
// Remove the dummy config
err = os.Remove("config.ini")
assert.NoError(t, err)
}

View File

@ -6,6 +6,7 @@ import (
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3" // Because.
"github.com/spf13/viper"
)
var (
@ -16,14 +17,18 @@ var (
func getEngine() (*xorm.Engine, error) {
// Use Mysql if set
if Config.Database.Type == "mysql" {
connStr := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true",
Config.Database.User, Config.Database.Password, Config.Database.Host, Config.Database.Database)
if viper.GetString("database.type") == "mysql" {
connStr := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true",
viper.GetString("database.user"),
viper.GetString("database.password"),
viper.GetString("database.host"),
viper.GetString("database.database"))
return xorm.NewEngine("mysql", connStr)
}
// Otherwise use sqlite
path := Config.Database.Path
path := viper.GetString("database.path")
if path == "" {
path = "./db.db"
}
@ -63,7 +68,7 @@ func SetEngine() (err error) {
return fmt.Errorf("sync database struct error: %v", err)
}
x.ShowSQL(Config.Database.ShowQueries)
x.ShowSQL(viper.GetBool("database.showqueries"))
return nil
}

View File

@ -1,12 +1,13 @@
package models
import (
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSetEngine(t *testing.T) {
Config.Database.Path = "file::memory:?cache=shared"
viper.Set("database.path", "file::memory:?cache=shared")
err := SetEngine()
assert.NoError(t, err)
}

View File

@ -19,6 +19,9 @@ func MainTest(m *testing.M, pathToRoot string) {
os.Exit(1)
}
// Create test database
PrepareTestDatabase()
os.Exit(m.Run())
}