mirror of
https://github.com/muety/wakapi.git
synced 2023-08-10 21:12:56 +03:00
feat: introduce legacy config migration
This commit is contained in:
parent
660fefcca9
commit
ff3fea0359
@ -14,36 +14,50 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultConfigPath = "config.yml"
|
||||||
|
defaultConfigPathLegacy = "config.ini"
|
||||||
|
defaultEnvConfigPathLegacy = ".env"
|
||||||
|
)
|
||||||
|
|
||||||
var cfg *Config
|
var cfg *Config
|
||||||
|
|
||||||
|
type appConfig struct {
|
||||||
|
CleanUp bool `default:"false" env:"WAKAPI_CLEANUP"`
|
||||||
|
CustomLanguages map[string]string `yaml:"custom_languages"`
|
||||||
|
LanguageColors map[string]string `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type securityConfig struct {
|
||||||
|
// this is actually a pepper (https://en.wikipedia.org/wiki/Pepper_(cryptography))
|
||||||
|
PasswordSalt string `yaml:"password_salt" default:"" env:"WAKAPI_PASSWORD_SALT"`
|
||||||
|
InsecureCookies bool `yaml:"insecure_cookies" default:"false" env:"WAKAPI_INSECURE_COOKIES"`
|
||||||
|
SecureCookie *securecookie.SecureCookie `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type dbConfig struct {
|
||||||
|
Host string `env:"WAKAPI_DB_HOST"`
|
||||||
|
Port uint `env:"WAKAPI_DB_PORT"`
|
||||||
|
User string `env:"WAKAPI_DB_USER"`
|
||||||
|
Password string `env:"WAKAPI_DB_PASSWORD"`
|
||||||
|
Name string `default:"wakapi_db.db" env:"WAKAPI_DB_NAME"`
|
||||||
|
Dialect string `default:"sqlite3" env:"WAKAPI_DB_TYPE"`
|
||||||
|
MaxConn uint `yaml:"max_conn" default:"2" env:"WAKAPI_DB_MAX_CONNECTIONS"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverConfig struct {
|
||||||
|
Port int `default:"3000" env:"WAKAPI_PORT"`
|
||||||
|
Addr string `default:"127.0.0.1" env:"WAKAPI_LISTEN_IPV4"`
|
||||||
|
BasePath string `yaml:"base_path" default:"/" env:"WAKAPI_BASE_PATH"`
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Env string `default:"dev" env:"ENVIRONMENT"`
|
Env string `default:"dev" env:"ENVIRONMENT"`
|
||||||
Version string
|
Version string `yaml:"-"`
|
||||||
App struct {
|
App appConfig
|
||||||
CleanUp bool `default:"false" env:"WAKAPI_CLEANUP"`
|
Security securityConfig
|
||||||
CustomLanguages map[string]string `yaml:"custom_languages"`
|
Db dbConfig
|
||||||
LanguageColors map[string]string
|
Server serverConfig
|
||||||
}
|
|
||||||
Security struct {
|
|
||||||
// this is actually a pepper (https://en.wikipedia.org/wiki/Pepper_(cryptography))
|
|
||||||
PasswordSalt string `yaml:"password_salt" default:"" env:"WAKAPI_PASSWORD_SALT"`
|
|
||||||
InsecureCookies bool `yaml:"insecure_cookies" default:"false" env:"WAKAPI_INSECURE_COOKIES"`
|
|
||||||
SecureCookie *securecookie.SecureCookie
|
|
||||||
}
|
|
||||||
Db struct {
|
|
||||||
Host string `env:"WAKAPI_DB_HOST"`
|
|
||||||
Port uint `env:"WAKAPI_DB_PORT"`
|
|
||||||
User string `env:"WAKAPI_DB_USER"`
|
|
||||||
Password string `env:"WAKAPI_DB_PASSWORD"`
|
|
||||||
Name string `default:"wakapi_db.db" env:"WAKAPI_DB_PORT"`
|
|
||||||
Dialect string `default:"sqlite3" env:"WAKAPI_DB_TYPE"`
|
|
||||||
MaxConn uint `yaml:"max_conn" default:"2" env:"WAKAPI_DB_MAX_CONNECTIONS"`
|
|
||||||
}
|
|
||||||
Server struct {
|
|
||||||
Port int `default:"3000" env:"WAKAPI_PORT"`
|
|
||||||
Addr string `default:"127.0.0.1" env:"WAKAPI_LISTEN_IPV4"`
|
|
||||||
BasePath string `yaml:"base_path" default:"/" env:"WAKAPI_BASE_PATH"`
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) IsDev() bool {
|
func (c *Config) IsDev() bool {
|
||||||
@ -102,14 +116,6 @@ func IsDev(env string) bool {
|
|||||||
return env == "dev" || env == "development"
|
return env == "dev" || env == "development"
|
||||||
}
|
}
|
||||||
|
|
||||||
func LookupFatal(key string) string {
|
|
||||||
v, ok := os.LookupEnv(key)
|
|
||||||
if !ok {
|
|
||||||
log.Fatalf("missing env variable '%s'", key)
|
|
||||||
}
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
func readVersion() string {
|
func readVersion() string {
|
||||||
file, err := os.Open("version.txt")
|
file, err := os.Open("version.txt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -151,7 +157,7 @@ func readLanguageColors() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mustReadConfigLocation() string {
|
func mustReadConfigLocation() string {
|
||||||
var cFlag = flag.String("c", "config.yml", "config file location")
|
var cFlag = flag.String("c", defaultConfigPath, "config file location")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -173,6 +179,8 @@ func Get() *Config {
|
|||||||
func Load() *Config {
|
func Load() *Config {
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
|
|
||||||
|
maybeMigrateLegacyConfig()
|
||||||
|
|
||||||
if err := configor.New(&configor.Config{}).Load(config, mustReadConfigLocation()); err != nil {
|
if err := configor.New(&configor.Config{}).Load(config, mustReadConfigLocation()); err != nil {
|
||||||
log.Fatalf("failed to read config: %v\n", err)
|
log.Fatalf("failed to read config: %v\n", err)
|
||||||
}
|
}
|
||||||
|
127
config/legacy.go
Normal file
127
config/legacy.go
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"gopkg.in/ini.v1"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func maybeMigrateLegacyConfig() {
|
||||||
|
if yes, err := shouldMigrateLegacyConfig(); err != nil {
|
||||||
|
log.Fatalf("failed to determine whether to migrate legacy config: %v\n", err)
|
||||||
|
} else if yes {
|
||||||
|
log.Printf("migrating legacy config (%s, %s) to new format (%s); see https://github.com/muety/wakapi/issues/54\n", defaultConfigPathLegacy, defaultEnvConfigPathLegacy, defaultConfigPath)
|
||||||
|
if err := migrateLegacyConfig(); err != nil {
|
||||||
|
log.Fatalf("failed to migrate legacy config: %v\n", err)
|
||||||
|
}
|
||||||
|
log.Printf("config migration successful; please delete %s and %s now\n", defaultConfigPathLegacy, defaultEnvConfigPathLegacy)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldMigrateLegacyConfig() (bool, error) {
|
||||||
|
if _, err := os.Stat(defaultConfigPath); err == nil {
|
||||||
|
return false, nil
|
||||||
|
} else if !os.IsNotExist(err) {
|
||||||
|
return true, err
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func migrateLegacyConfig() error {
|
||||||
|
// step 1: read envVars file parameters
|
||||||
|
envFile, err := os.Open(defaultEnvConfigPathLegacy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
envVars, err := godotenv.Parse(envFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
env := envVars["ENV"]
|
||||||
|
dbType := envVars["WAKAPI_DB_TYPE"]
|
||||||
|
dbUser := envVars["WAKAPI_DB_USER"]
|
||||||
|
dbPassword := envVars["WAKAPI_DB_PASSWORD"]
|
||||||
|
dbHost := envVars["WAKAPI_DB_HOST"]
|
||||||
|
dbName := envVars["WAKAPI_DB_NAME"]
|
||||||
|
dbPortStr := envVars["WAKAPI_DB_PORT"]
|
||||||
|
passwordSalt := envVars["WAKAPI_PASSWORD_SALT"]
|
||||||
|
dbPort, _ := strconv.Atoi(dbPortStr)
|
||||||
|
|
||||||
|
// step 2: read ini file
|
||||||
|
cfg, err := ini.Load(defaultConfigPathLegacy)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if dbType == "" {
|
||||||
|
dbType = "sqlite3"
|
||||||
|
}
|
||||||
|
|
||||||
|
dbMaxConn := cfg.Section("database").Key("max_connections").MustUint(2)
|
||||||
|
addr := cfg.Section("server").Key("listen").MustString("127.0.0.1")
|
||||||
|
insecureCookies := cfg.Section("server").Key("insecure_cookies").MustBool(false)
|
||||||
|
port, err := strconv.Atoi(os.Getenv("PORT"))
|
||||||
|
if err != nil {
|
||||||
|
port = cfg.Section("server").Key("port").MustInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
basePathEnv, basePathEnvExists := os.LookupEnv("WAKAPI_BASE_PATH")
|
||||||
|
basePath := cfg.Section("server").Key("base_path").MustString("/")
|
||||||
|
if basePathEnvExists {
|
||||||
|
basePath = basePathEnv
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanUp := cfg.Section("app").Key("cleanup").MustBool(false)
|
||||||
|
|
||||||
|
// Read custom languages
|
||||||
|
customLangs := make(map[string]string)
|
||||||
|
languageKeys := cfg.Section("languages").Keys()
|
||||||
|
for _, k := range languageKeys {
|
||||||
|
customLangs[k.Name()] = k.MustString("unknown")
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 3: instantiate config
|
||||||
|
config := &Config{
|
||||||
|
Env: env,
|
||||||
|
App: appConfig{
|
||||||
|
CleanUp: cleanUp,
|
||||||
|
CustomLanguages: customLangs,
|
||||||
|
},
|
||||||
|
Security: securityConfig{
|
||||||
|
PasswordSalt: passwordSalt,
|
||||||
|
InsecureCookies: insecureCookies,
|
||||||
|
},
|
||||||
|
Db: dbConfig{
|
||||||
|
Host: dbHost,
|
||||||
|
Port: uint(dbPort),
|
||||||
|
User: dbUser,
|
||||||
|
Password: dbPassword,
|
||||||
|
Name: dbName,
|
||||||
|
Dialect: dbType,
|
||||||
|
MaxConn: dbMaxConn,
|
||||||
|
},
|
||||||
|
Server: serverConfig{
|
||||||
|
Port: port,
|
||||||
|
Addr: addr,
|
||||||
|
BasePath: basePath,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 4: serialize to yaml
|
||||||
|
yamlConfig, err := yaml.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// step 5: write file
|
||||||
|
if err := ioutil.WriteFile(defaultConfigPath, yamlConfig, 0600); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
1
go.mod
1
go.mod
@ -18,4 +18,5 @@ require (
|
|||||||
github.com/t-tiger/gorm-bulk-insert v1.3.0
|
github.com/t-tiger/gorm-bulk-insert v1.3.0
|
||||||
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
|
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c
|
||||||
gopkg.in/ini.v1 v1.50.0
|
gopkg.in/ini.v1 v1.50.0
|
||||||
|
gopkg.in/yaml.v2 v2.2.5
|
||||||
)
|
)
|
||||||
|
@ -1 +1 @@
|
|||||||
1.11.3
|
1.12.0
|
Loading…
x
Reference in New Issue
Block a user