gorm-goose/lib/gorm-goose/dbconf.go

138 lines
3.2 KiB
Go

/*
* Copyright (c) 2020 Alex aka mailoman <alex@webz.asia>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Alex aka mailoman <alex@webz.asia>
* @copyright Copyright (c) 2020 Alex aka mailoman <alex@webz.asia>
* @since 08.01.2020
*
*/
package gormgoose
import (
"fmt"
"os"
"path/filepath"
"github.com/jinzhu/gorm"
"github.com/kylelemons/go-gypsy/yaml"
)
// DBDriver encapsulates the info needed to work with
// a specific database driver
type DBDriver struct {
Name string
OpenStr string
Import string
}
type DBConf struct {
MigrationsDir string
Env string
Driver DBDriver
PgSchema string
}
// NewDBConf extract configuration details from the given file
func NewDBConf(p, env string, pgschema string) (*DBConf, error) {
cfgFile := filepath.Join(p, "dbconf.yml")
f, err := yaml.ReadFile(cfgFile)
if err != nil {
return nil, err
}
drv, err := f.Get(fmt.Sprintf("%s.driver", env))
if err != nil {
return nil, err
}
drv = os.ExpandEnv(drv)
open, err := f.Get(fmt.Sprintf("%s.open", env))
if err != nil {
return nil, err
}
open = os.ExpandEnv(open)
d := newDBDriver(drv, open)
// allow the configuration to override the Import for this driver
if imprt, err := f.Get(fmt.Sprintf("%s.import", env)); err == nil {
d.Import = imprt
}
if !d.IsValid() {
return nil, fmt.Errorf("Invalid DBConf: %v", d)
}
return &DBConf{
MigrationsDir: filepath.Join(p, "migrations"),
Env: env,
Driver: d,
PgSchema: pgschema,
}, nil
}
// Create a new DBDriver and populate driver specific
// fields for drivers that we know about.
// Further customization may be done in NewDBConf
func newDBDriver(name, open string) DBDriver {
d := DBDriver{
Name: name,
OpenStr: open,
}
switch name {
case "postgres":
d.Import = "github.com/jinzhu/gorm/dialects/postgres"
case "mysql":
d.Import = "github.com/jinzhu/gorm/dialects/mysql"
d.OpenStr = d.OpenStr + "?charset=utf8&parseTime=True&loc=Local"
case "sqlite3":
d.Import = "github.com/jinzhu/gorm/dialects/sqlite"
}
return d
}
// IsValid ensure we have enough info about this driver
func (drv *DBDriver) IsValid() bool {
return len(drv.Import) > 0
}
// OpenDBFromDBConf wraps database/sql.DB.Open() and configures
// the newly opened DB based on the given DBConf.
//
// Callers must Close() the returned DB.
func OpenDBFromDBConf(conf *DBConf) (*gorm.DB, error) {
db, err := gorm.Open(conf.Driver.Name, conf.Driver.OpenStr)
if err != nil {
return nil, err
}
// if a postgres schema has been specified, apply it
if conf.Driver.Name == "postgres" && conf.PgSchema != "" {
if err := db.Exec("SET search_path TO " + conf.PgSchema).Error; err != nil {
return nil, err
}
}
return db, nil
}