2022-07-22 19:53:39 +02:00
|
|
|
package store
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"github.com/iancoleman/strcase"
|
|
|
|
"github.com/jmoiron/sqlx"
|
2022-10-21 15:31:12 +02:00
|
|
|
_ "github.com/lib/pq"
|
2022-07-22 19:53:39 +02:00
|
|
|
_ "github.com/mattn/go-sqlite3"
|
2022-10-21 15:31:12 +02:00
|
|
|
postgresql_schema "github.com/openziti-test-kitchen/zrok/controller/store/sql/postgresql"
|
2022-10-21 14:36:43 +02:00
|
|
|
sqlite3_schema "github.com/openziti-test-kitchen/zrok/controller/store/sql/sqlite3"
|
2022-07-22 19:53:39 +02:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
migrate "github.com/rubenv/sql-migrate"
|
|
|
|
"github.com/sirupsen/logrus"
|
2022-07-25 22:03:51 +02:00
|
|
|
"time"
|
2022-07-22 19:53:39 +02:00
|
|
|
)
|
|
|
|
|
2022-07-25 22:03:51 +02:00
|
|
|
type Model struct {
|
|
|
|
Id int
|
|
|
|
CreatedAt time.Time
|
|
|
|
UpdatedAt time.Time
|
|
|
|
}
|
|
|
|
|
2022-07-22 19:53:39 +02:00
|
|
|
type Config struct {
|
2022-10-31 20:56:59 +01:00
|
|
|
Path string `cf:"+secret"`
|
2022-10-21 15:31:12 +02:00
|
|
|
Type string
|
2022-07-22 19:53:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type Store struct {
|
|
|
|
cfg *Config
|
|
|
|
db *sqlx.DB
|
|
|
|
}
|
|
|
|
|
|
|
|
func Open(cfg *Config) (*Store, error) {
|
2022-10-21 15:31:12 +02:00
|
|
|
var dbx *sqlx.DB
|
|
|
|
var err error
|
|
|
|
|
|
|
|
switch cfg.Type {
|
|
|
|
case "sqlite3":
|
|
|
|
dbx, err = sqlx.Open("sqlite3", fmt.Sprintf("file:%s?_foreign_keys=on", cfg.Path))
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "error opening database '%v'", cfg.Path)
|
|
|
|
}
|
|
|
|
dbx.DB.SetMaxOpenConns(1)
|
|
|
|
|
|
|
|
case "postgres":
|
|
|
|
dbx, err = sqlx.Connect("postgres", cfg.Path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrapf(err, "error opening database '%v'", cfg.Path)
|
|
|
|
}
|
2022-10-21 16:30:05 +02:00
|
|
|
|
|
|
|
default:
|
|
|
|
return nil, errors.Errorf("unknown database type '%v' (supported: sqlite3, postgres)", cfg.Type)
|
2022-07-22 19:53:39 +02:00
|
|
|
}
|
2022-11-08 20:07:44 +01:00
|
|
|
logrus.Info("database connected")
|
2022-07-22 19:53:39 +02:00
|
|
|
dbx.MapperFunc(strcase.ToSnake)
|
2022-10-21 16:30:05 +02:00
|
|
|
|
2022-07-22 19:53:39 +02:00
|
|
|
store := &Store{cfg: cfg, db: dbx}
|
2022-10-21 15:31:12 +02:00
|
|
|
if err := store.migrate(cfg); err != nil {
|
2022-07-22 19:53:39 +02:00
|
|
|
return nil, errors.Wrapf(err, "error migrating database '%v'", cfg.Path)
|
|
|
|
}
|
|
|
|
return store, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Store) Begin() (*sqlx.Tx, error) {
|
|
|
|
return self.db.Beginx()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (self *Store) Close() error {
|
|
|
|
return self.db.Close()
|
|
|
|
}
|
|
|
|
|
2022-10-21 15:31:12 +02:00
|
|
|
func (self *Store) migrate(cfg *Config) error {
|
|
|
|
switch cfg.Type {
|
|
|
|
case "sqlite3":
|
|
|
|
migrations := &migrate.EmbedFileSystemMigrationSource{
|
|
|
|
FileSystem: sqlite3_schema.FS,
|
|
|
|
Root: "/",
|
|
|
|
}
|
|
|
|
migrate.SetTable("migrations")
|
|
|
|
n, err := migrate.Exec(self.db.DB, "sqlite3", migrations, migrate.Up)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "error running migrations")
|
|
|
|
}
|
|
|
|
logrus.Infof("applied %d migrations", n)
|
|
|
|
|
|
|
|
case "postgres":
|
|
|
|
migrations := &migrate.EmbedFileSystemMigrationSource{
|
|
|
|
FileSystem: postgresql_schema.FS,
|
|
|
|
Root: "/",
|
|
|
|
}
|
|
|
|
migrate.SetTable("migrations")
|
|
|
|
n, err := migrate.Exec(self.db.DB, "postgres", migrations, migrate.Up)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "error running migrations")
|
|
|
|
}
|
|
|
|
logrus.Infof("applied %d migrations", n)
|
2022-07-22 19:53:39 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|