database.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package database
  2. import (
  3. "fmt"
  4. "strconv"
  5. "sync"
  6. "time"
  7. "github.com/crowdsecurity/crowdsec/pkg/types"
  8. log "github.com/sirupsen/logrus"
  9. "github.com/jinzhu/gorm"
  10. _ "github.com/jinzhu/gorm/dialects/mysql"
  11. _ "github.com/jinzhu/gorm/dialects/sqlite"
  12. _ "github.com/mattn/go-sqlite3"
  13. "gopkg.in/tomb.v2"
  14. )
  15. type Context struct {
  16. Db *gorm.DB //Pointer to database
  17. tx *gorm.DB //Pointer to current transaction (flushed on a regular basis)
  18. lastCommit time.Time
  19. flush bool
  20. count int32
  21. lock sync.Mutex //booboo
  22. PusherTomb tomb.Tomb
  23. }
  24. func checkConfig(cfg map[string]string) error {
  25. switch dbType, _ := cfg["type"]; dbType {
  26. case "sqlite":
  27. if val, ok := cfg["db_path"]; !ok && val == "" {
  28. return fmt.Errorf("please specify a 'db_path' to SQLite db in the configuration")
  29. }
  30. case "mysql":
  31. if val, ok := cfg["db_host"]; !ok && val == "" {
  32. return fmt.Errorf("please specify a 'db_host' to SQLite db in the configuration")
  33. }
  34. if val, ok := cfg["db_username"]; !ok && val == "" {
  35. return fmt.Errorf("please specify a 'db_username' to SQLite db in the configuration")
  36. }
  37. if val, ok := cfg["db_password"]; !ok && val == "" {
  38. return fmt.Errorf("please specify a 'db_password' to SQLite db in the configuration")
  39. }
  40. if val, ok := cfg["db_name"]; !ok && val == "" {
  41. return fmt.Errorf("please specify a 'db_name' to SQLite db in the configuration")
  42. }
  43. default:
  44. return fmt.Errorf("please specify a proper 'type' to the database configuration ")
  45. }
  46. return nil
  47. }
  48. func NewDatabase(cfg map[string]string) (*Context, error) {
  49. var err error
  50. c := &Context{}
  51. if err = checkConfig(cfg); err != nil {
  52. return nil, fmt.Errorf("bad database configuration : %v", err)
  53. }
  54. if cfg["type"] == "sqlite" {
  55. c.Db, err = gorm.Open("sqlite3", cfg["db_path"]+"?_busy_timeout=1000")
  56. if err != nil {
  57. return nil, fmt.Errorf("failed to open %s : %s", cfg["db_path"], err)
  58. }
  59. }
  60. if cfg["type"] == "mysql" {
  61. gormArg := cfg["db_username"] + ":" + cfg["db_password"] + "@(" + cfg["db_host"] + ")/" + cfg["db_name"] + "?charset=utf8&parseTime=True&loc=Local"
  62. c.Db, err = gorm.Open("mysql", gormArg)
  63. if err != nil {
  64. return nil, fmt.Errorf("failed to open %s database : %s", cfg["db_name"], err)
  65. }
  66. }
  67. if val, ok := cfg["debug"]; ok && val == "true" {
  68. log.Infof("Enabling debug for %s", cfg["type"])
  69. c.Db.LogMode(true)
  70. }
  71. c.flush, _ = strconv.ParseBool(cfg["flush"])
  72. // Migrate the schema
  73. c.Db.AutoMigrate(&types.EventSequence{}, &types.SignalOccurence{}, &types.BanApplication{})
  74. c.Db.Model(&types.SignalOccurence{}).Related(&types.EventSequence{})
  75. c.Db.Model(&types.SignalOccurence{}).Related(&types.BanApplication{})
  76. c.tx = c.Db.Begin()
  77. c.lastCommit = time.Now()
  78. ret := c.tx.Commit()
  79. if ret.Error != nil {
  80. return nil, fmt.Errorf("failed to commit records : %v", ret.Error)
  81. }
  82. c.tx = c.Db.Begin()
  83. if c.tx == nil {
  84. return nil, fmt.Errorf("failed to begin %s transac : %s", cfg["type"], err)
  85. }
  86. c.PusherTomb.Go(func() error {
  87. c.AutoCommit()
  88. return nil
  89. })
  90. return c, nil
  91. }