mirror of https://github.com/statping/statping
vue
parent
d5ffa3a851
commit
eb5e291e56
4
Makefile
4
Makefile
|
@ -82,13 +82,13 @@ install:
|
|||
|
||||
generate:
|
||||
cd source && go generate
|
||||
cd handlers/graphql && go generate
|
||||
|
||||
# remove files for a clean compile/build
|
||||
clean:
|
||||
rm -rf ./{logs,assets,plugins,*.db,config.yml,.sass-cache,config.yml,statping,build,.sass-cache,index.html,vendor}
|
||||
rm -rf cmd/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log,*.html,*.json}
|
||||
rm -rf core/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf core/notifier/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf handlers/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf notifiers/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf source/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
|
@ -104,7 +104,7 @@ clean:
|
|||
find . -name "*.out" -type f -delete
|
||||
find . -name "*.cpu" -type f -delete
|
||||
find . -name "*.mem" -type f -delete
|
||||
rm -rf {build,tmp,docker}
|
||||
rm -rf {build,tmp}
|
||||
|
||||
print_details:
|
||||
@echo \==== Statping Development Instance ====
|
||||
|
|
76
cmd/cli.go
76
cmd/cli.go
|
@ -19,14 +19,11 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/core"
|
||||
"github.com/hunterlong/statping/handlers"
|
||||
"github.com/hunterlong/statping/source"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/joho/godotenv"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"net/http/httptest"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -72,25 +69,25 @@ func catchCLI(args []string) error {
|
|||
updateDisplay()
|
||||
return errors.New("end")
|
||||
case "static":
|
||||
var err error
|
||||
if err = runLogs(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = runAssets(); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Statping v%v Exporting Static 'index.html' page...\n", VERSION)
|
||||
if _, err = core.LoadConfigFile(dir); err != nil {
|
||||
log.Errorln("config.yml file not found")
|
||||
return err
|
||||
}
|
||||
indexSource := ExportIndexHTML()
|
||||
//core.CloseDB()
|
||||
if err = utils.SaveFile(dir+"/index.html", indexSource); err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
log.Infoln("Exported Statping index page: 'index.html'")
|
||||
//var err error
|
||||
//if err = runLogs(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//if err = runAssets(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//fmt.Printf("Statping v%v Exporting Static 'index.html' page...\n", VERSION)
|
||||
//if _, err = core.LoadConfigFile(dir); err != nil {
|
||||
// log.Errorln("config.yml file not found")
|
||||
// return err
|
||||
//}
|
||||
//indexSource := ExportIndexHTML()
|
||||
////core.CloseDB()
|
||||
//if err = utils.SaveFile(dir+"/index.html", indexSource); err != nil {
|
||||
// log.Errorln(err)
|
||||
// return err
|
||||
//}
|
||||
//log.Infoln("Exported Statping index page: 'index.html'")
|
||||
case "help":
|
||||
HelpEcho()
|
||||
return errors.New("end")
|
||||
|
@ -103,10 +100,11 @@ func catchCLI(args []string) error {
|
|||
if err = runAssets(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = core.LoadConfigFile(dir); err != nil {
|
||||
configs, err := core.LoadConfigFile(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = core.CoreApp.Connect(false, dir); err != nil {
|
||||
if err = core.CoreApp.Connect(configs, false, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
if data, err = core.ExportSettings(); err != nil {
|
||||
|
@ -167,19 +165,19 @@ func catchCLI(args []string) error {
|
|||
}
|
||||
|
||||
// ExportIndexHTML returns the HTML of the index page as a string
|
||||
func ExportIndexHTML() []byte {
|
||||
source.Assets()
|
||||
core.CoreApp.Connect(false, utils.Directory)
|
||||
core.SelectAllServices(false)
|
||||
core.CoreApp.UseCdn = types.NewNullBool(true)
|
||||
for _, srv := range core.Services() {
|
||||
core.CheckService(srv, true)
|
||||
}
|
||||
w := httptest.NewRecorder()
|
||||
r := httptest.NewRequest("GET", "/", nil)
|
||||
handlers.ExecuteResponse(w, r, "index.gohtml", nil, nil)
|
||||
return w.Body.Bytes()
|
||||
}
|
||||
//func ExportIndexHTML() []byte {
|
||||
// source.Assets()
|
||||
// core.CoreApp.Connect(core.CoreApp., utils.Directory)
|
||||
// core.SelectAllServices(false)
|
||||
// core.CoreApp.UseCdn = types.NewNullBool(true)
|
||||
// for _, srv := range core.Services() {
|
||||
// core.CheckService(srv, true)
|
||||
// }
|
||||
// w := httptest.NewRecorder()
|
||||
// r := httptest.NewRequest("GET", "/", nil)
|
||||
// handlers.ExecuteResponse(w, r, "index.gohtml", nil, nil)
|
||||
// return w.Body.Bytes()
|
||||
//}
|
||||
|
||||
func updateDisplay() error {
|
||||
gitCurrent, err := checkGithubUpdates()
|
||||
|
@ -202,11 +200,11 @@ func updateDisplay() error {
|
|||
|
||||
// runOnce will initialize the Statping application and check each service 1 time, will not run HTTP server
|
||||
func runOnce() error {
|
||||
_, err := core.LoadConfigFile(utils.Directory)
|
||||
configs, err := core.LoadConfigFile(utils.Directory)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "config.yml file not found")
|
||||
}
|
||||
err = core.CoreApp.Connect(false, utils.Directory)
|
||||
err = core.CoreApp.Connect(configs, false, utils.Directory)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue connecting to database")
|
||||
}
|
||||
|
|
46
cmd/main.go
46
cmd/main.go
|
@ -62,6 +62,13 @@ func parseFlags() {
|
|||
flag.Parse()
|
||||
}
|
||||
|
||||
func exit(err error) {
|
||||
fmt.Printf("%+v", core.Configs())
|
||||
panic(err)
|
||||
//log.Fatalln(err)
|
||||
//os.Exit(2)
|
||||
}
|
||||
|
||||
// main will run the Statping application
|
||||
func main() {
|
||||
var err error
|
||||
|
@ -80,35 +87,54 @@ func main() {
|
|||
if err != nil {
|
||||
if err.Error() == "end" {
|
||||
os.Exit(0)
|
||||
return
|
||||
}
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
exit(err)
|
||||
}
|
||||
}
|
||||
log.Info(fmt.Sprintf("Starting Statping v%v", VERSION))
|
||||
updateDisplay()
|
||||
|
||||
config, err := core.LoadConfigFile(utils.Directory)
|
||||
if err := updateDisplay(); err != nil {
|
||||
log.Warnln(err)
|
||||
}
|
||||
|
||||
// check if DB_CONN was set, and load config from that
|
||||
autoConfigDb := utils.Getenv("DB_CONN", "").(string)
|
||||
if autoConfigDb != "" {
|
||||
log.Infof("Environment variable 'DB_CONN' was set to %s, loading configs from ENV.", autoConfigDb)
|
||||
if _, err := core.LoadUsingEnv(); err != nil {
|
||||
exit(err)
|
||||
return
|
||||
} else {
|
||||
afterConfigLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
// attempt to load config.yml file from current directory, if no file, then start in setup mode.
|
||||
_, err = core.LoadConfigFile(utils.Directory)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
core.CoreApp.Setup = false
|
||||
writeAble, err := utils.DirWritable(utils.Directory)
|
||||
if err != nil {
|
||||
log.Fatalln(err)
|
||||
exit(err)
|
||||
return
|
||||
}
|
||||
if !writeAble {
|
||||
log.Fatalf("Statping does not have write permissions at: %v\nYou can change this directory by setting the STATPING_DIR environment variable to a dedicated path before starting.", utils.Directory)
|
||||
return
|
||||
}
|
||||
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
} else {
|
||||
afterConfigLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
core.CoreApp.Config = config.DbConfig
|
||||
|
||||
func afterConfigLoaded() {
|
||||
if err := mainProcess(); err != nil {
|
||||
log.Fatalln(err)
|
||||
os.Exit(2)
|
||||
exit(err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +166,7 @@ func loadDotEnvs() error {
|
|||
func mainProcess() error {
|
||||
dir := utils.Directory
|
||||
var err error
|
||||
err = core.CoreApp.Connect(false, dir)
|
||||
err = core.CoreApp.Connect(core.Configs(), false, dir)
|
||||
if err != nil {
|
||||
log.Errorln(fmt.Sprintf("could not connect to database: %v", err))
|
||||
return err
|
||||
|
|
|
@ -17,7 +17,6 @@ package core
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/ararog/timeago"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
|
@ -108,37 +107,6 @@ func SelectCheckin(api string) *Checkin {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AllHits returns all of the CheckinHits for a given Checkin
|
||||
func (c *Checkin) AllHits() []*types.CheckinHit {
|
||||
var checkins []*types.CheckinHit
|
||||
Database(&types.CheckinHit{}).Where("checkin = ?", c.Id).Order("id DESC").Find(&checkins)
|
||||
return checkins
|
||||
}
|
||||
|
||||
// Hits returns all of the CheckinHits for a given Checkin
|
||||
func (c *Checkin) AllFailures() []*types.Failure {
|
||||
var failures []*types.Failure
|
||||
Database(&types.Failure{}).
|
||||
Where("checkin = ?", c.Id).
|
||||
Where("method = 'checkin'").
|
||||
Order("id desc").
|
||||
Find(&failures)
|
||||
|
||||
return failures
|
||||
}
|
||||
|
||||
func (c *Checkin) GetFailures(count int) []*types.Failure {
|
||||
var failures []*types.Failure
|
||||
Database(&types.Failure{}).
|
||||
Where("checkin = ?", c.Id).
|
||||
Where("method = 'checkin'").
|
||||
Limit(count).
|
||||
Order("id desc").
|
||||
Find(&failures)
|
||||
|
||||
return failures
|
||||
}
|
||||
|
||||
// Create will create a new Checkin
|
||||
func (c *Checkin) Delete() {
|
||||
c.Close()
|
||||
|
@ -171,35 +139,6 @@ func (c *Checkin) Create() (int64, error) {
|
|||
return c.Id, err
|
||||
}
|
||||
|
||||
// Update will update a Checkin
|
||||
func (c *Checkin) Update() (int64, error) {
|
||||
row := Database(c).Update(&c)
|
||||
if row.Error() != nil {
|
||||
log.Warnln(row.Error())
|
||||
return 0, row.Error()
|
||||
}
|
||||
return c.Id, row.Error()
|
||||
}
|
||||
|
||||
// Create will create a new successful checkinHit
|
||||
func (c *CheckinHit) Create() (int64, error) {
|
||||
if c.CreatedAt.IsZero() {
|
||||
c.CreatedAt = utils.Now()
|
||||
}
|
||||
row := Database(c).Create(&c)
|
||||
if row.Error() != nil {
|
||||
log.Warnln(row.Error())
|
||||
return 0, row.Error()
|
||||
}
|
||||
return c.Id, row.Error()
|
||||
}
|
||||
|
||||
// Ago returns the duration of time between now and the last successful checkinHit
|
||||
func (c *CheckinHit) Ago() string {
|
||||
got, _ := timeago.TimeAgoWithTime(utils.Now(), c.CreatedAt)
|
||||
return got
|
||||
}
|
||||
|
||||
// RecheckCheckinFailure will check if a Service Checkin has been reported yet
|
||||
func (c *Checkin) RecheckCheckinFailure(guard chan struct{}) {
|
||||
between := utils.Now().Sub(utils.Now()).Seconds()
|
||||
|
|
|
@ -30,15 +30,9 @@ type ErrorResponse struct {
|
|||
}
|
||||
|
||||
// LoadConfigFile will attempt to load the 'config.yml' file in a specific directory
|
||||
func LoadConfigFile(directory string) (*DbConfig, error) {
|
||||
var configs *DbConfig
|
||||
func LoadConfigFile(directory string) (*types.DbConfig, error) {
|
||||
var configs *types.DbConfig
|
||||
|
||||
dbConn := utils.Getenv("DB_CONN", "").(string)
|
||||
|
||||
if dbConn != "" {
|
||||
log.Infof("DB_CONN=%s environment variable was found, waiting for database...", dbConn)
|
||||
return LoadUsingEnv()
|
||||
}
|
||||
log.Debugln("Attempting to read config file at: " + directory + "/config.yml")
|
||||
file, err := utils.OpenFile(directory + "/config.yml")
|
||||
if err != nil {
|
||||
|
@ -50,30 +44,44 @@ func LoadConfigFile(directory string) (*DbConfig, error) {
|
|||
return nil, errors.Wrap(err, "yaml file not formatted correctly")
|
||||
}
|
||||
log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + directory + "/config.yml")
|
||||
CoreApp.Config = configs.DbConfig
|
||||
|
||||
CoreApp.config = configs
|
||||
|
||||
return configs, err
|
||||
}
|
||||
|
||||
func Configs() *types.DbConfig {
|
||||
return CoreApp.config
|
||||
}
|
||||
|
||||
// LoadUsingEnv will attempt to load database configs based on environment variables. If DB_CONN is set if will force this function.
|
||||
func LoadUsingEnv() (*DbConfig, error) {
|
||||
Configs, err := EnvToConfig()
|
||||
func LoadUsingEnv() (*types.DbConfig, error) {
|
||||
configs, err := EnvToConfig()
|
||||
if err != nil {
|
||||
return Configs, err
|
||||
return configs, err
|
||||
}
|
||||
|
||||
CoreApp.Name = utils.Getenv("NAME", "").(string)
|
||||
CoreApp.Domain = utils.Getenv("DOMAIN", Configs.LocalIP).(string)
|
||||
CoreApp.Domain = utils.Getenv("DOMAIN", "").(string)
|
||||
CoreApp.UseCdn = types.NewNullBool(utils.Getenv("USE_CDN", false).(bool))
|
||||
|
||||
err = CoreApp.Connect(true, utils.Directory)
|
||||
err = CoreApp.Connect(configs, true, utils.Directory)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error connecting to database")
|
||||
}
|
||||
if err := Configs.Save(); err != nil {
|
||||
if err := SaveConfig(configs); err != nil {
|
||||
return nil, errors.Wrap(err, "error saving configuration")
|
||||
}
|
||||
exists := DbSession.HasTable("core")
|
||||
exists := database.Get().HasTable("core")
|
||||
if !exists {
|
||||
return InitialSetup(configs)
|
||||
}
|
||||
|
||||
CoreApp.config = configs
|
||||
return configs, nil
|
||||
}
|
||||
|
||||
func InitialSetup(configs *types.DbConfig) (*types.DbConfig, error) {
|
||||
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
|
||||
if err := CoreApp.DropDatabase(); err != nil {
|
||||
return nil, errors.Wrap(err, "error dropping database")
|
||||
|
@ -81,7 +89,7 @@ func LoadUsingEnv() (*DbConfig, error) {
|
|||
if err := CoreApp.CreateDatabase(); err != nil {
|
||||
return nil, errors.Wrap(err, "error creating database")
|
||||
}
|
||||
CoreApp, err = Configs.InsertCore()
|
||||
CoreApp, err := InsertCore(configs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error creating the core database")
|
||||
}
|
||||
|
@ -102,9 +110,9 @@ func LoadUsingEnv() (*DbConfig, error) {
|
|||
if err := SampleData(); err != nil {
|
||||
return nil, errors.Wrap(err, "error connecting sample data")
|
||||
}
|
||||
return Configs, err
|
||||
}
|
||||
return Configs, nil
|
||||
|
||||
CoreApp.config = configs
|
||||
return configs, err
|
||||
}
|
||||
|
||||
// defaultPort accepts a database type and returns its default port
|
||||
|
@ -122,7 +130,7 @@ func defaultPort(db string) int {
|
|||
}
|
||||
|
||||
// EnvToConfig converts environment variables to a DbConfig
|
||||
func EnvToConfig() (*DbConfig, error) {
|
||||
func EnvToConfig() (*types.DbConfig, error) {
|
||||
var err error
|
||||
|
||||
dbConn := utils.Getenv("DB_CONN", "").(string)
|
||||
|
@ -173,10 +181,7 @@ func EnvToConfig() (*DbConfig, error) {
|
|||
Location: utils.Directory,
|
||||
SqlFile: sqlFile,
|
||||
}
|
||||
|
||||
CoreApp.Config = config
|
||||
|
||||
return &DbConfig{config}, err
|
||||
return config, err
|
||||
}
|
||||
|
||||
// SampleData runs all the sample data for a new Statping installation
|
||||
|
@ -202,3 +207,10 @@ func DeleteConfig() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsSetup() bool {
|
||||
if CoreApp.config != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
65
core/core.go
65
core/core.go
|
@ -35,6 +35,7 @@ type PluginRepos types.PluginRepos
|
|||
type Core struct {
|
||||
*types.Core
|
||||
services map[int64]*Service
|
||||
config *types.DbConfig
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -93,91 +94,45 @@ func InitApp() error {
|
|||
|
||||
// InsertNotifierDB inject the Statping database instance to the Notifier package
|
||||
func InsertNotifierDB() error {
|
||||
if DbSession == nil {
|
||||
err := CoreApp.Connect(false, utils.Directory)
|
||||
if !database.Available() {
|
||||
err := CoreApp.Connect(CoreApp.config, false, utils.Directory)
|
||||
if err != nil {
|
||||
return errors.New("database connection has not been created")
|
||||
}
|
||||
}
|
||||
notifier.SetDB(DbSession)
|
||||
notifier.SetDB(database.Get())
|
||||
return nil
|
||||
}
|
||||
|
||||
// InsertIntegratorDB inject the Statping database instance to the Integrations package
|
||||
func InsertIntegratorDB() error {
|
||||
if DbSession == nil {
|
||||
err := CoreApp.Connect(false, utils.Directory)
|
||||
if !database.Available() {
|
||||
err := CoreApp.Connect(CoreApp.config, false, utils.Directory)
|
||||
if err != nil {
|
||||
return errors.New("database connection has not been created")
|
||||
}
|
||||
}
|
||||
integrations.SetDB(DbSession)
|
||||
integrations.SetDB(database.Get())
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateCore will update the CoreApp variable inside of the 'core' table in database
|
||||
func UpdateCore(c *Core) (*Core, error) {
|
||||
db := Database(&Core{}).Update(&c)
|
||||
return c, db.Error()
|
||||
}
|
||||
|
||||
// CurrentTime will return the current local time
|
||||
func (c Core) CurrentTime() string {
|
||||
t := time.Now().UTC()
|
||||
current := utils.Timezoner(t, c.Timezone)
|
||||
ansic := "Monday 03:04:05 PM"
|
||||
return current.Format(ansic)
|
||||
}
|
||||
|
||||
// Messages will return the current local time
|
||||
func (c Core) Messages() []*Message {
|
||||
var message []*Message
|
||||
Database(&Message{}).Where("service = ?", 0).Limit(10).Find(&message)
|
||||
return message
|
||||
}
|
||||
|
||||
// UsingAssets will return true if /assets folder is present
|
||||
func (c Core) UsingAssets() bool {
|
||||
return source.UsingAssets(utils.Directory)
|
||||
}
|
||||
|
||||
// SassVars opens the file /assets/scss/variables.scss to be edited in Theme
|
||||
func (c Core) SassVars() string {
|
||||
if !source.UsingAssets(utils.Directory) {
|
||||
return ""
|
||||
}
|
||||
return source.OpenAsset("scss/variables.scss")
|
||||
}
|
||||
|
||||
// BaseSASS is the base design , this opens the file /assets/scss/base.scss to be edited in Theme
|
||||
func (c Core) BaseSASS() string {
|
||||
if !source.UsingAssets(utils.Directory) {
|
||||
return ""
|
||||
}
|
||||
return source.OpenAsset("scss/base.scss")
|
||||
}
|
||||
|
||||
// MobileSASS is the -webkit responsive custom css designs. This opens the
|
||||
// file /assets/scss/mobile.scss to be edited in Theme
|
||||
func (c Core) MobileSASS() string {
|
||||
if !source.UsingAssets(utils.Directory) {
|
||||
return ""
|
||||
}
|
||||
return source.OpenAsset("scss/mobile.scss")
|
||||
}
|
||||
|
||||
// SelectCore will return the CoreApp global variable and the settings/configs for Statping
|
||||
func SelectCore() (*Core, error) {
|
||||
if DbSession == nil {
|
||||
if !database.Available() {
|
||||
log.Traceln("database has not been initiated yet.")
|
||||
return nil, errors.New("database has not been initiated yet.")
|
||||
}
|
||||
exists := DbSession.HasTable("core")
|
||||
exists := database.Get().HasTable("core")
|
||||
if !exists {
|
||||
log.Errorf("core database has not been setup yet, does not have the 'core' table")
|
||||
return nil, errors.New("core database has not been setup yet.")
|
||||
}
|
||||
db := Database(&Core{}).First(&CoreApp)
|
||||
db := database.Core().First(&CoreApp)
|
||||
if db.Error() != nil {
|
||||
return nil, db.Error()
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ var (
|
|||
skipNewDb bool
|
||||
)
|
||||
|
||||
var configs *types.DbConfig
|
||||
|
||||
func init() {
|
||||
dir = utils.Directory
|
||||
utils.InitLogs()
|
||||
|
@ -50,27 +52,29 @@ func TestDbConfig_Save(t *testing.T) {
|
|||
t.SkipNow()
|
||||
}
|
||||
|
||||
config := &DbConfig{&types.DbConfig{
|
||||
config := &types.DbConfig{
|
||||
DbConn: "sqlite",
|
||||
Project: "Tester",
|
||||
Location: dir,
|
||||
}}
|
||||
}
|
||||
|
||||
err := config.Save()
|
||||
err := SaveConfig(config)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "sqlite", CoreApp.Config.DbConn)
|
||||
assert.NotEmpty(t, CoreApp.Config.ApiKey)
|
||||
assert.NotEmpty(t, CoreApp.Config.ApiSecret)
|
||||
assert.Equal(t, "sqlite", config.DbConn)
|
||||
assert.NotEmpty(t, config.ApiKey)
|
||||
assert.NotEmpty(t, config.ApiSecret)
|
||||
}
|
||||
|
||||
func TestLoadDbConfig(t *testing.T) {
|
||||
Configs, err := LoadConfigFile(dir)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "sqlite", Configs.DbConn)
|
||||
|
||||
configs = Configs
|
||||
}
|
||||
|
||||
func TestDbConnection(t *testing.T) {
|
||||
err := CoreApp.Connect(false, dir)
|
||||
err := CoreApp.Connect(configs, false, dir)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
|
@ -102,9 +106,9 @@ func TestSeedDatabase(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestReLoadDbConfig(t *testing.T) {
|
||||
err := CoreApp.Connect(false, dir)
|
||||
err := CoreApp.Connect(configs, false, dir)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "sqlite", CoreApp.Config.DbConn)
|
||||
assert.Equal(t, "sqlite", CoreApp.config.DbConn)
|
||||
}
|
||||
|
||||
func TestSelectCore(t *testing.T) {
|
||||
|
|
158
core/database.go
158
core/database.go
|
@ -18,24 +18,25 @@ package core
|
|||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
|
||||
"github.com/go-yaml/yaml"
|
||||
"github.com/hunterlong/statping/core/notifier"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// DbSession stores the Statping database session
|
||||
DbSession database.Database
|
||||
DbModels []interface{}
|
||||
)
|
||||
|
||||
|
@ -43,45 +44,9 @@ func init() {
|
|||
DbModels = []interface{}{&types.Service{}, &types.User{}, &types.Hit{}, &types.Failure{}, &types.Message{}, &types.Group{}, &types.Checkin{}, &types.CheckinHit{}, ¬ifier.Notification{}, &types.Incident{}, &types.IncidentUpdate{}, &types.Integration{}}
|
||||
}
|
||||
|
||||
// DbConfig stores the config.yml file for the statup configuration
|
||||
type DbConfig struct {
|
||||
*types.DbConfig
|
||||
}
|
||||
|
||||
func Database(obj interface{}) database.Database {
|
||||
switch obj.(type) {
|
||||
case *types.Service, *Service, []*Service:
|
||||
return DbSession.Model(&types.Service{})
|
||||
case *types.Hit, *Hit, []*Hit:
|
||||
return DbSession.Model(&types.Hit{})
|
||||
case *types.Failure, *Failure, []*Failure:
|
||||
return DbSession.Model(&types.Failure{})
|
||||
case *types.Core, *Core:
|
||||
return DbSession.Table("core").Model(&CoreApp)
|
||||
case *types.Checkin, *Checkin, []*Checkin:
|
||||
return DbSession.Model(&types.Checkin{})
|
||||
case *types.CheckinHit, *CheckinHit, []*CheckinHit:
|
||||
return DbSession.Model(&types.CheckinHit{})
|
||||
case *types.User, *User, []*User:
|
||||
return DbSession.Model(&types.User{})
|
||||
case *types.Group, *Group, []*Group:
|
||||
return DbSession.Model(&types.Group{})
|
||||
case *types.Incident, *Incident, []*Incident:
|
||||
return DbSession.Model(&types.Incident{})
|
||||
case *types.IncidentUpdate, *IncidentUpdate, []*IncidentUpdate:
|
||||
return DbSession.Model(&types.IncidentUpdate{})
|
||||
case *types.Message, *Message, []*Message:
|
||||
return DbSession.Model(&types.Message{})
|
||||
default:
|
||||
return DbSession
|
||||
}
|
||||
}
|
||||
|
||||
// CloseDB will close the database connection if available
|
||||
func CloseDB() {
|
||||
if DbSession != nil {
|
||||
DbSession.DB().Close()
|
||||
}
|
||||
database.Close()
|
||||
}
|
||||
|
||||
//// AfterFind for Core will set the timezone
|
||||
|
@ -140,11 +105,11 @@ func CloseDB() {
|
|||
//}
|
||||
|
||||
// InsertCore create the single row for the Core settings in Statping
|
||||
func (d *DbConfig) InsertCore() (*Core, error) {
|
||||
func InsertCore(d *types.DbConfig) (*Core, error) {
|
||||
apiKey := utils.Getenv("API_KEY", utils.NewSHA1Hash(40))
|
||||
apiSecret := utils.Getenv("API_SECRET", utils.NewSHA1Hash(40))
|
||||
|
||||
CoreApp = &Core{Core: &types.Core{
|
||||
core := &types.Core{
|
||||
Name: d.Project,
|
||||
Description: d.Description,
|
||||
ConfigFile: "config.yml",
|
||||
|
@ -152,22 +117,34 @@ func (d *DbConfig) InsertCore() (*Core, error) {
|
|||
ApiSecret: apiSecret.(string),
|
||||
Domain: d.Domain,
|
||||
MigrationId: time.Now().Unix(),
|
||||
Config: d.DbConfig,
|
||||
}}
|
||||
query := DbSession.Create(CoreApp.Core)
|
||||
return CoreApp, query.Error()
|
||||
}
|
||||
|
||||
CoreApp = &Core{Core: core}
|
||||
|
||||
CoreApp.config = d
|
||||
|
||||
_, err := database.Create(CoreApp.Core)
|
||||
return CoreApp, err
|
||||
}
|
||||
|
||||
func findDbFile() string {
|
||||
if CoreApp.Config.SqlFile != "" {
|
||||
return CoreApp.Config.SqlFile
|
||||
if CoreApp.config == nil {
|
||||
return findSQLin(utils.Directory)
|
||||
}
|
||||
if CoreApp.config.SqlFile != "" {
|
||||
return CoreApp.config.SqlFile
|
||||
}
|
||||
return utils.Directory + "/" + types.SqliteFilename
|
||||
}
|
||||
|
||||
func findSQLin(path string) string {
|
||||
filename := types.SqliteFilename
|
||||
err := filepath.Walk(utils.Directory, func(path string, info os.FileInfo, err error) error {
|
||||
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if filepath.Ext(path) == ".db" {
|
||||
fmt.Println("DB file is now: ", info.Name())
|
||||
filename = info.Name()
|
||||
}
|
||||
return nil
|
||||
|
@ -179,20 +156,19 @@ func findDbFile() string {
|
|||
}
|
||||
|
||||
// Connect will attempt to connect to the sqlite, postgres, or mysql database
|
||||
func (c *Core) Connect(retry bool, location string) error {
|
||||
func (c *Core) Connect(configs *types.DbConfig, retry bool, location string) error {
|
||||
postgresSSL := os.Getenv("POSTGRES_SSLMODE")
|
||||
if DbSession != nil {
|
||||
if database.Available() {
|
||||
return nil
|
||||
}
|
||||
var conn string
|
||||
var err error
|
||||
|
||||
configs := c.Config
|
||||
switch configs.DbConn {
|
||||
case "sqlite":
|
||||
sqlFilename := findDbFile()
|
||||
conn = sqlFilename
|
||||
log.Infof("SQL database file at: %v/%v", utils.Directory, conn)
|
||||
case "sqlite", "sqlite3":
|
||||
conn = findDbFile()
|
||||
configs.SqlFile = fmt.Sprintf("%s/%s", utils.Directory, conn)
|
||||
log.Infof("SQL database file at: %s", configs.SqlFile)
|
||||
configs.DbConn = "sqlite3"
|
||||
case "mysql":
|
||||
host := fmt.Sprintf("%v:%v", configs.DbHost, configs.DbPort)
|
||||
|
@ -210,10 +186,10 @@ func (c *Core) Connect(retry bool, location string) error {
|
|||
log.WithFields(utils.ToFields(c, conn)).Debugln("attempting to connect to database")
|
||||
dbSession, err := database.Openw(configs.DbConn, conn)
|
||||
if err != nil {
|
||||
log.Debugln(fmt.Sprintf("Database connection error %v", err))
|
||||
log.Debugln(fmt.Sprintf("Database connection error %s", err))
|
||||
if retry {
|
||||
log.Errorln(fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", configs.DbHost))
|
||||
return c.waitForDb()
|
||||
log.Errorln(fmt.Sprintf("Database %s connection to '%s' is not available, trying again in 5 seconds...", configs.DbConn, configs.DbHost))
|
||||
return c.waitForDb(configs)
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
|
@ -229,19 +205,21 @@ func (c *Core) Connect(retry bool, location string) error {
|
|||
dbSession.DB().SetConnMaxLifetime(maxLifeConn.(time.Duration))
|
||||
|
||||
if dbSession.DB().Ping() == nil {
|
||||
DbSession = dbSession
|
||||
if utils.VerboseMode >= 4 {
|
||||
DbSession.LogMode(true).Debug().SetLogger(gorm.Logger{log})
|
||||
database.LogMode(true).Debug().SetLogger(gorm.Logger{log})
|
||||
}
|
||||
log.Infoln(fmt.Sprintf("Database %v connection was successful.", configs.DbConn))
|
||||
}
|
||||
|
||||
CoreApp.config = configs
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// waitForDb will sleep for 5 seconds and try to connect to the database again
|
||||
func (c *Core) waitForDb() error {
|
||||
func (c *Core) waitForDb(configs *types.DbConfig) error {
|
||||
time.Sleep(5 * time.Second)
|
||||
return c.Connect(true, utils.Directory)
|
||||
return c.Connect(configs, true, utils.Directory)
|
||||
}
|
||||
|
||||
// Update will save the config.yml file
|
||||
|
@ -252,18 +230,20 @@ func (c *Core) UpdateConfig() error {
|
|||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
data, err := yaml.Marshal(c.Config)
|
||||
defer config.Close()
|
||||
|
||||
data, err := yaml.Marshal(c.config)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
config.WriteString(string(data))
|
||||
config.Close()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Save will initially create the config.yml file
|
||||
func (d *DbConfig) Save() error {
|
||||
func SaveConfig(d *types.DbConfig) error {
|
||||
config, err := os.Create(utils.Directory + "/config.yml")
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
|
@ -271,20 +251,28 @@ func (d *DbConfig) Save() error {
|
|||
}
|
||||
defer config.Close()
|
||||
log.WithFields(utils.ToFields(d)).Debugln("saving config file at: " + utils.Directory + "/config.yml")
|
||||
CoreApp.Config = d.DbConfig
|
||||
|
||||
if d.ApiKey == "" || d.ApiSecret == "" {
|
||||
apiKey := utils.Getenv("API_KEY", utils.NewSHA1Hash(16))
|
||||
apiSecret := utils.Getenv("API_SECRET", utils.NewSHA1Hash(16))
|
||||
CoreApp.config.ApiKey = apiKey.(string)
|
||||
CoreApp.config.ApiSecret = apiSecret.(string)
|
||||
}
|
||||
if d.DbConn == "sqlite3" {
|
||||
d.DbConn = "sqlite"
|
||||
}
|
||||
|
||||
CoreApp.Config.ApiKey = apiKey.(string)
|
||||
CoreApp.Config.ApiSecret = apiSecret.(string)
|
||||
data, err := yaml.Marshal(d)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
config.WriteString(string(data))
|
||||
log.WithFields(utils.ToFields(d)).Infoln("saved config file at: " + utils.Directory + "/config.yml")
|
||||
if _, err := config.WriteString(string(data)); err != nil {
|
||||
return errors.Wrap(err, "error writing to config.yml")
|
||||
}
|
||||
log.WithFields(utils.ToFields(d)).Infoln("Saved config file at: " + utils.Directory + "/config.yml")
|
||||
|
||||
CoreApp.config = d
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -299,8 +287,8 @@ func (c *Core) CreateCore() *Core {
|
|||
Domain: c.Domain,
|
||||
MigrationId: time.Now().Unix(),
|
||||
}
|
||||
db := Database(newCore).Create(&newCore)
|
||||
if db.Error() == nil {
|
||||
_, err := database.Create(&newCore)
|
||||
if err == nil {
|
||||
CoreApp = &Core{Core: newCore}
|
||||
}
|
||||
CoreApp, err := SelectCore()
|
||||
|
@ -313,11 +301,11 @@ func (c *Core) CreateCore() *Core {
|
|||
// DropDatabase will DROP each table Statping created
|
||||
func (c *Core) DropDatabase() error {
|
||||
log.Infoln("Dropping Database Tables...")
|
||||
tables := []string{"checkins", "checkin_hits", "notifications", "core", "failures", "hits", "services", "users", "messages", "incidents", "incident_updates"}
|
||||
for _, t := range tables {
|
||||
if err := DbSession.DropTableIfExists(t); err != nil {
|
||||
for _, t := range DbModels {
|
||||
if err := database.Get().DropTableIfExists(t); err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
log.Infof("Dropped table: %T\n", t)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -327,11 +315,11 @@ func (c *Core) CreateDatabase() error {
|
|||
var err error
|
||||
log.Infoln("Creating Database Tables...")
|
||||
for _, table := range DbModels {
|
||||
if err := DbSession.CreateTable(table); err.Error() != nil {
|
||||
if err := database.Get().CreateTable(table); err.Error() != nil {
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
if err := DbSession.Table("core").CreateTable(&types.Core{}); err.Error() != nil {
|
||||
if err := database.Get().Table("core").CreateTable(&types.Core{}); err.Error() != nil {
|
||||
return err.Error()
|
||||
}
|
||||
log.Infoln("Statping Database Created")
|
||||
|
@ -394,7 +382,7 @@ func (c *Core) ServicesFromEnvFile() error {
|
|||
// If this function has an issue, it will ROLLBACK to the previous state.
|
||||
func (c *Core) MigrateDatabase() error {
|
||||
log.Infoln("Migrating Database Tables...")
|
||||
tx := DbSession.Begin()
|
||||
tx := database.Begin("migration")
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
|
@ -412,11 +400,11 @@ func (c *Core) MigrateDatabase() error {
|
|||
log.Errorln(fmt.Sprintf("Statping Database could not be migrated: %v", tx.Error()))
|
||||
return tx.Error()
|
||||
}
|
||||
log.Infoln("Statping Database Migrated")
|
||||
|
||||
if err := tx.Commit().Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infoln("Statping Database Migrated")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -27,9 +27,3 @@ const (
|
|||
limitedFailures = 32
|
||||
limitedHits = 32
|
||||
)
|
||||
|
||||
// Delete will remove a Failure record from the database
|
||||
func (f *Failure) Delete() error {
|
||||
db := Database(&types.Failure{}).Delete(f)
|
||||
return db.Error()
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package core
|
|||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Incident struct {
|
||||
|
@ -17,69 +16,3 @@ type IncidentUpdate struct {
|
|||
func ReturnIncident(u *types.Incident) *Incident {
|
||||
return &Incident{u}
|
||||
}
|
||||
|
||||
// SelectIncident returns the Incident based on the Incident's ID.
|
||||
func SelectIncident(id int64) (*Incident, error) {
|
||||
var incident Incident
|
||||
err := Database(incident).Where("id = ?", id).First(&incident)
|
||||
return &incident, err.Error()
|
||||
}
|
||||
|
||||
// AllIncidents will return all incidents and updates recorded
|
||||
func AllIncidents() []*Incident {
|
||||
var incidents []*Incident
|
||||
Database(incidents).Find(&incidents).Order("id desc")
|
||||
for _, i := range incidents {
|
||||
var updates []*types.IncidentUpdate
|
||||
Database(updates).Find(&updates).Order("id desc")
|
||||
i.Updates = updates
|
||||
}
|
||||
return incidents
|
||||
}
|
||||
|
||||
// Incidents will return the all incidents for a service
|
||||
func (s *Service) Incidents() []*Incident {
|
||||
var incidentArr []*Incident
|
||||
Database(incidentArr).Where("service = ?", s.Id).Order("id desc").Find(&incidentArr)
|
||||
return incidentArr
|
||||
}
|
||||
|
||||
// AllUpdates will return the all updates for an incident
|
||||
func (i *Incident) AllUpdates() []*IncidentUpdate {
|
||||
var updatesArr []*IncidentUpdate
|
||||
Database(updatesArr).Where("incident = ?", i.Id).Order("id desc").Find(&updatesArr)
|
||||
return updatesArr
|
||||
}
|
||||
|
||||
// Delete will remove a incident
|
||||
func (i *Incident) Delete() error {
|
||||
err := Database(i).Delete(i)
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
// Create will create a incident and insert it into the database
|
||||
func (i *Incident) Create() (int64, error) {
|
||||
i.CreatedAt = time.Now().UTC()
|
||||
db := Database(i).Create(i)
|
||||
return i.Id, db.Error()
|
||||
}
|
||||
|
||||
// Update will update a incident
|
||||
func (i *Incident) Update() (int64, error) {
|
||||
i.UpdatedAt = time.Now().UTC()
|
||||
db := Database(i).Update(i)
|
||||
return i.Id, db.Error()
|
||||
}
|
||||
|
||||
// Delete will remove a incident update
|
||||
func (i *IncidentUpdate) Delete() error {
|
||||
err := Database(i).Delete(i)
|
||||
return err.Error()
|
||||
}
|
||||
|
||||
// Create will create a incident update and insert it into the database
|
||||
func (i *IncidentUpdate) Create() (int64, error) {
|
||||
i.CreatedAt = time.Now().UTC()
|
||||
db := Database(i).Create(i)
|
||||
return i.Id, db.Error()
|
||||
}
|
||||
|
|
|
@ -16,64 +16,14 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
*types.Message
|
||||
}
|
||||
|
||||
// SelectServiceMessages returns all messages for a service
|
||||
func SelectServiceMessages(id int64) []*Message {
|
||||
var message []*Message
|
||||
Database(&Message{}).Where("service = ?", id).Limit(10).Find(&message)
|
||||
return message
|
||||
}
|
||||
|
||||
// ReturnMessage will convert *types.Message to *core.Message
|
||||
func ReturnMessage(m *types.Message) *Message {
|
||||
return &Message{m}
|
||||
}
|
||||
|
||||
// SelectMessages returns all messages
|
||||
func SelectMessages() ([]*Message, error) {
|
||||
var messages []*Message
|
||||
db := Database(&Message{}).Find(&messages).Order("id desc")
|
||||
return messages, db.Error()
|
||||
}
|
||||
|
||||
// SelectMessage returns a Message based on the ID passed
|
||||
func SelectMessage(id int64) (*Message, error) {
|
||||
var message Message
|
||||
db := Database(&Message{}).Where("id = ?", id).Find(&message)
|
||||
return &message, db.Error()
|
||||
}
|
||||
|
||||
// Create will create a Message and insert it into the database
|
||||
func (m *Message) Create() (int64, error) {
|
||||
m.CreatedAt = time.Now().UTC()
|
||||
db := Database(&Message{}).Create(m)
|
||||
if db.Error() != nil {
|
||||
log.Errorln(fmt.Sprintf("Failed to create message %v #%v: %v", m.Title, m.Id, db.Error()))
|
||||
return 0, db.Error()
|
||||
}
|
||||
return m.Id, nil
|
||||
}
|
||||
|
||||
// Delete will delete a Message from database
|
||||
func (m *Message) Delete() error {
|
||||
db := Database(&Message{}).Delete(m)
|
||||
return db.Error()
|
||||
}
|
||||
|
||||
// Update will update a Message in the database
|
||||
func (m *Message) Update() (*Message, error) {
|
||||
db := Database(&Message{}).Update(m)
|
||||
if db.Error() != nil {
|
||||
log.Errorln(fmt.Sprintf("Failed to update message %v #%v: %v", m.Title, m.Id, db.Error()))
|
||||
return nil, db.Error()
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
|
|
@ -21,11 +21,12 @@ import (
|
|||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -271,7 +272,7 @@ func insertSampleCheckins() error {
|
|||
|
||||
// InsertSampleHits will create a couple new hits for the sample services
|
||||
func InsertSampleHits() error {
|
||||
tx := Database(&Hit{}).Begin()
|
||||
tx := database.Begin(&types.Hit{})
|
||||
sg := new(sync.WaitGroup)
|
||||
for i := int64(1); i <= 5; i++ {
|
||||
sg.Add(1)
|
||||
|
@ -280,7 +281,7 @@ func InsertSampleHits() error {
|
|||
log.Infoln(fmt.Sprintf("Adding %v sample hit records to service %v", SampleHits, service.Name))
|
||||
createdAt := sampleStart
|
||||
p := utils.NewPerlin(2., 2., 10, seed)
|
||||
go func() {
|
||||
go func(sg *sync.WaitGroup) {
|
||||
defer sg.Done()
|
||||
for hi := 0.; hi <= float64(SampleHits); hi++ {
|
||||
latency := p.Noise1D(hi / 500)
|
||||
|
@ -292,7 +293,7 @@ func InsertSampleHits() error {
|
|||
}
|
||||
tx = tx.Create(&hit)
|
||||
}
|
||||
}()
|
||||
}(sg)
|
||||
}
|
||||
sg.Wait()
|
||||
if err := tx.Commit().Error(); err != nil {
|
||||
|
@ -626,14 +627,14 @@ func TmpRecords(dbFile string) error {
|
|||
CoreApp = NewCore()
|
||||
CoreApp.Name = "Tester"
|
||||
CoreApp.Setup = true
|
||||
configs := &DbConfig{&types.DbConfig{
|
||||
configs := &types.DbConfig{
|
||||
DbConn: "sqlite",
|
||||
Project: "Tester",
|
||||
Location: utils.Directory,
|
||||
SqlFile: sqlFile,
|
||||
}}
|
||||
}
|
||||
log.Infoln("saving config.yml in: " + utils.Directory)
|
||||
if err := configs.Save(); err != nil {
|
||||
if err := SaveConfig(configs); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
log.Infoln("loading config.yml from: " + utils.Directory)
|
||||
|
@ -653,7 +654,7 @@ func TmpRecords(dbFile string) error {
|
|||
}
|
||||
log.Infoln("loading config.yml from: " + utils.Directory)
|
||||
|
||||
if err := CoreApp.Connect(false, utils.Directory); err != nil {
|
||||
if err := CoreApp.Connect(configs, false, utils.Directory); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
log.Infoln("selecting the Core variable")
|
||||
|
@ -684,7 +685,7 @@ func TmpRecords(dbFile string) error {
|
|||
|
||||
log.Infoln(tmpSqlFile + " not found, creating a new database...")
|
||||
|
||||
if err := CoreApp.Connect(false, utils.Directory); err != nil {
|
||||
if err := CoreApp.Connect(configs, false, utils.Directory); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infoln("creating database")
|
||||
|
|
|
@ -58,9 +58,9 @@ func TestSelectCheckin(t *testing.T) {
|
|||
func TestUpdateCheckin(t *testing.T) {
|
||||
testCheckin.Interval = 60
|
||||
testCheckin.GracePeriod = 15
|
||||
id, err := testCheckin.Update()
|
||||
err := database.Update(testCheckin)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, id)
|
||||
assert.NotZero(t, testCheckin.Id)
|
||||
assert.NotEmpty(t, testCheckin.ApiKey)
|
||||
service := SelectService(1)
|
||||
checkin := service.Checkins()[0]
|
||||
|
@ -82,8 +82,9 @@ func TestCreateCheckinHits(t *testing.T) {
|
|||
}
|
||||
_, err := database.Create(hit)
|
||||
require.Nil(t, err)
|
||||
hits := testCheckin.AllHits()
|
||||
assert.Equal(t, 1, len(hits))
|
||||
|
||||
checks := service.Checkins()
|
||||
assert.Equal(t, 1, len(checks))
|
||||
}
|
||||
|
||||
func TestSelectCheckinMethods(t *testing.T) {
|
||||
|
|
|
@ -33,13 +33,6 @@ func uwrap(u *database.UserObj) *User {
|
|||
return &User{u}
|
||||
}
|
||||
|
||||
// CountUsers returns the amount of users
|
||||
func CountUsers() int64 {
|
||||
var amount int64
|
||||
Database(&User{}).Count(&amount)
|
||||
return amount
|
||||
}
|
||||
|
||||
// SelectUser returns the User based on the User's ID.
|
||||
func SelectUser(id int64) (*User, error) {
|
||||
user, err := database.User(id)
|
||||
|
|
|
@ -112,6 +112,6 @@ func TestDeleteUser(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDbConfig_Close(t *testing.T) {
|
||||
err := DbSession.Close()
|
||||
err := database.Close()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,10 @@ package database
|
|||
import (
|
||||
"github.com/hunterlong/statping/types"
|
||||
"reflect"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
)
|
||||
|
||||
type CrudObject interface {
|
||||
|
|
|
@ -4,12 +4,13 @@ import (
|
|||
"database/sql"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -117,6 +118,7 @@ type Database interface {
|
|||
}
|
||||
|
||||
type Objects interface {
|
||||
Core() Database
|
||||
Services() Database
|
||||
Users() Database
|
||||
Groups() Database
|
||||
|
@ -130,6 +132,51 @@ type Objects interface {
|
|||
Integrations() Database
|
||||
}
|
||||
|
||||
func Close() error {
|
||||
if database == nil {
|
||||
return nil
|
||||
}
|
||||
return database.Close()
|
||||
}
|
||||
|
||||
func LogMode(b bool) Database {
|
||||
return database.LogMode(b)
|
||||
}
|
||||
|
||||
func Begin(model interface{}) Database {
|
||||
if all, ok := model.(string); ok {
|
||||
if all == "migration" {
|
||||
return database.Begin()
|
||||
}
|
||||
}
|
||||
return database.Model(model).Begin()
|
||||
}
|
||||
|
||||
func Core() Database {
|
||||
return database.Core()
|
||||
}
|
||||
|
||||
func Get() Database {
|
||||
if Available() {
|
||||
return database
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Available() bool {
|
||||
if database == nil {
|
||||
return false
|
||||
}
|
||||
if err := database.DB().Ping(); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (d *Db) Core() Database {
|
||||
return d.Table("core").Model(&types.Service{})
|
||||
}
|
||||
|
||||
func (d *Db) Services() Database {
|
||||
return d.Model(&types.Service{})
|
||||
}
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
"github.com/hunterlong/statping/utils"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -39,6 +43,8 @@ func StartMaintenceRoutine() {
|
|||
func databaseMaintence(dur time.Duration) {
|
||||
deleteAfter := time.Now().UTC().Add(dur)
|
||||
|
||||
time.Sleep(20 * types.Second)
|
||||
|
||||
for range time.Tick(maintenceDuration) {
|
||||
log.Infof("Deleting failures older than %s", dur.String())
|
||||
DeleteAllSince("failures", deleteAfter)
|
||||
|
|
|
@ -6,13 +6,13 @@ services:
|
|||
container_name: postgres
|
||||
image: postgres
|
||||
volumes:
|
||||
- ./docker/databases/postgres:/var/lib/postgresql/data
|
||||
- ../docker/databases/postgres:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: password123
|
||||
POSTGRES_DB: statping
|
||||
POSTGRES_USER: root
|
||||
networks:
|
||||
- statping
|
||||
ports:
|
||||
- 5432:5432
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U root"]
|
||||
interval: 15s
|
||||
|
@ -23,15 +23,15 @@ services:
|
|||
container_name: mysql
|
||||
image: mysql:5.7
|
||||
volumes:
|
||||
- ./docker/databases/mysql:/var/lib/mysql
|
||||
- ../docker/databases/mysql:/var/lib/mysql
|
||||
restart: always
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: password123
|
||||
MYSQL_DATABASE: statping
|
||||
MYSQL_USER: root
|
||||
MYSQL_PASSWORD: password
|
||||
networks:
|
||||
- statping
|
||||
ports:
|
||||
- 3306:3306
|
||||
healthcheck:
|
||||
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
|
||||
timeout: 20s
|
||||
|
@ -55,27 +55,18 @@ services:
|
|||
PMA_USER: root
|
||||
PMA_PASSWORD: password123
|
||||
PMA_PORT: 3306
|
||||
networks:
|
||||
- statping
|
||||
|
||||
sqlite-web:
|
||||
container_name: sqlite-web
|
||||
image: coleifer/sqlite-web
|
||||
restart: on-failure
|
||||
command: sqlite_web -H 0.0.0.0 -r -x /data/statping.db
|
||||
depends_on:
|
||||
statping:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- 6050:8080
|
||||
links:
|
||||
- statping
|
||||
volumes:
|
||||
- ./docker/statping/sqlite/statping.db:/data/statping.db:ro
|
||||
- ../docker/statping/sqlite/statping.db:/data/statping.db:ro
|
||||
environment:
|
||||
SQLITE_DATABASE: /data/statping.db
|
||||
networks:
|
||||
- statping
|
||||
|
||||
pgadmin4:
|
||||
container_name: pgadmin4
|
||||
|
@ -91,25 +82,16 @@ services:
|
|||
- 7000:5050
|
||||
links:
|
||||
- postgres:postgres
|
||||
networks:
|
||||
- statping
|
||||
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:v2.0.0
|
||||
restart: on-failure
|
||||
volumes:
|
||||
- ./dev/prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- ./docker/databases/prometheus:/prometheus
|
||||
links:
|
||||
- statping
|
||||
- statping_mysql
|
||||
- statping_postgres
|
||||
- statping_dev
|
||||
- ./prometheus.yml:/etc/prometheus/prometheus.yml
|
||||
- ../docker/databases/prometheus:/prometheus
|
||||
ports:
|
||||
- 7050:9090
|
||||
networks:
|
||||
- statping
|
||||
healthcheck:
|
||||
test: "/bin/wget -q -Y off http://localhost:9090/status -O /dev/null > /dev/null 2>&1"
|
||||
interval: 10s
|
||||
|
|
|
@ -52,7 +52,7 @@ func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
var err error
|
||||
core.CoreApp.ApiKey = utils.NewSHA1Hash(40)
|
||||
core.CoreApp.ApiSecret = utils.NewSHA1Hash(40)
|
||||
core.CoreApp, err = core.UpdateCore(core.CoreApp)
|
||||
err = database.Update(core.CoreApp)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -91,7 +91,7 @@ func apiCoreHandler(w http.ResponseWriter, r *http.Request) {
|
|||
app.Timezone = c.Timezone
|
||||
}
|
||||
app.UseCdn = types.NewNullBool(c.UseCdn.Bool)
|
||||
core.CoreApp, err = core.UpdateCore(app)
|
||||
err = database.Update(app)
|
||||
returnJson(core.CoreApp, w, r)
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ func TestResetDatabase(t *testing.T) {
|
|||
t.Log(err)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, core.CoreApp)
|
||||
require.NotNil(t, core.CoreApp.Config)
|
||||
}
|
||||
|
||||
func TestFailedHTTPServer(t *testing.T) {
|
||||
|
|
|
@ -24,17 +24,17 @@ func apiCreateIncidentHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
newIncident := core.ReturnIncident(incident)
|
||||
_, err = newIncident.Create()
|
||||
obj, err := database.Create(newIncident)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
sendJsonAction(newIncident, "create", w, r)
|
||||
sendJsonAction(obj, "create", w, r)
|
||||
}
|
||||
|
||||
func apiIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
incident, err := core.SelectIncident(utils.ToInt(vars["id"]))
|
||||
incident, err := database.Incident(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -47,7 +47,7 @@ func apiIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
_, err = incident.Update()
|
||||
err = database.Update(&incident)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -57,12 +57,12 @@ func apiIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func apiDeleteIncidentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
incident, err := core.SelectIncident(utils.ToInt(vars["id"]))
|
||||
incident, err := database.Incident(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
err = incident.Delete()
|
||||
err = database.Delete(incident)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
|
|
@ -32,7 +32,7 @@ func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
|
|||
health := map[string]interface{}{
|
||||
"services": len(core.Services()),
|
||||
"online": true,
|
||||
"setup": core.CoreApp.Config != nil,
|
||||
"setup": core.IsSetup(),
|
||||
}
|
||||
returnJson(health, w, r)
|
||||
}
|
||||
|
|
|
@ -19,27 +19,15 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/hunterlong/statping/core"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func apiAllMessagesHandler(r *http.Request) interface{} {
|
||||
messages, err := core.SelectMessages()
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
return nil
|
||||
}
|
||||
return joinMessages(messages)
|
||||
}
|
||||
|
||||
func joinMessages(messages []*core.Message) []*types.Message {
|
||||
var m []*types.Message
|
||||
for _, v := range messages {
|
||||
m = append(m, v.Message)
|
||||
}
|
||||
return m
|
||||
messages := database.AllMessages()
|
||||
return messages
|
||||
}
|
||||
|
||||
func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -50,18 +38,17 @@ func apiMessageCreateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
msg := core.ReturnMessage(message)
|
||||
_, err = msg.Create()
|
||||
_, err = database.Create(message)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
sendJsonAction(msg, "create", w, r)
|
||||
sendJsonAction(message, "create", w, r)
|
||||
}
|
||||
|
||||
func apiMessageGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
message, err := core.SelectMessage(utils.ToInt(vars["id"]))
|
||||
message, err := database.Message(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -71,12 +58,12 @@ func apiMessageGetHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func apiMessageDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
message, err := core.SelectMessage(utils.ToInt(vars["id"]))
|
||||
message, err := database.Message(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
err = message.Delete()
|
||||
err = database.Delete(message)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -86,7 +73,7 @@ func apiMessageDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func apiMessageUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
message, err := core.SelectMessage(utils.ToInt(vars["id"]))
|
||||
message, err := database.Message(utils.ToInt(vars["id"]))
|
||||
if err != nil {
|
||||
sendErrorJson(fmt.Errorf("message #%v was not found", vars["id"]), w, r)
|
||||
return
|
||||
|
@ -97,7 +84,7 @@ func apiMessageUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
_, err = message.Update()
|
||||
err = database.Update(message)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
|
|
@ -135,7 +135,7 @@ func cached(duration, contentType string, handler func(w http.ResponseWriter, r
|
|||
content := CacheStorage.Get(r.RequestURI)
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
if core.CoreApp.Config == nil {
|
||||
if !core.IsSetup() {
|
||||
handler(w, r)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sample, _ := strconv.ParseBool(r.PostForm.Get("sample_data"))
|
||||
dir := utils.Directory
|
||||
|
||||
config := &core.DbConfig{DbConfig: &types.DbConfig{
|
||||
configs := &types.DbConfig{
|
||||
DbConn: dbConn,
|
||||
DbHost: dbHost,
|
||||
DbUser: dbUser,
|
||||
|
@ -67,11 +67,11 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
Email: email,
|
||||
Error: nil,
|
||||
Location: utils.Directory,
|
||||
}}
|
||||
}
|
||||
|
||||
log.WithFields(utils.ToFields(core.CoreApp, config)).Debugln("new configs posted")
|
||||
log.WithFields(utils.ToFields(core.CoreApp, configs)).Debugln("new configs posted")
|
||||
|
||||
if err := config.Save(); err != nil {
|
||||
if err := core.SaveConfig(configs); err != nil {
|
||||
log.Errorln(err)
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
|
@ -83,7 +83,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
if err = core.CoreApp.Connect(false, dir); err != nil {
|
||||
if err = core.CoreApp.Connect(configs, false, dir); err != nil {
|
||||
log.Errorln(err)
|
||||
core.DeleteConfig()
|
||||
sendErrorJson(err, w, r)
|
||||
|
@ -100,7 +100,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
core.CoreApp, err = config.InsertCore()
|
||||
core.CoreApp, err = core.InsertCore(configs)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
sendErrorJson(err, w, r)
|
||||
|
@ -108,9 +108,9 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
admin := &types.User{
|
||||
Username: config.Username,
|
||||
Password: config.Password,
|
||||
Email: config.Email,
|
||||
Username: configs.Username,
|
||||
Password: configs.Password,
|
||||
Email: configs.Email,
|
||||
Admin: types.NewNullBool(true),
|
||||
}
|
||||
database.Create(admin)
|
||||
|
@ -129,8 +129,8 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
Message string `json:"message"`
|
||||
Config *types.DbConfig `json:"config"`
|
||||
}{
|
||||
"okokok",
|
||||
config.DbConfig,
|
||||
"success",
|
||||
configs,
|
||||
}
|
||||
returnJson(out, w, r)
|
||||
}
|
||||
|
|
|
@ -60,8 +60,8 @@ func apiUserUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func apiUserDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
users := core.CountUsers()
|
||||
if users == 1 {
|
||||
users := database.AllUsers()
|
||||
if len(users) == 1 {
|
||||
sendErrorJson(errors.New("cannot delete the last user"), w, r)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ func TestSaveAndCompileAsset(t *testing.T) {
|
|||
themeCSS, err := utils.OpenFile(dir + "/assets/css/theme.css")
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, scssData, themeCSS)
|
||||
assert.Contains(t, themeCSS, `color: #333;`)
|
||||
}
|
||||
|
||||
func TestOpenAsset(t *testing.T) {
|
||||
|
@ -88,12 +88,7 @@ func TestOpenAsset(t *testing.T) {
|
|||
|
||||
func TestDeleteAssets(t *testing.T) {
|
||||
assert.True(t, UsingAssets(dir))
|
||||
//assert.Nil(t, DeleteAllAssets(dir))
|
||||
assert.False(t, UsingAssets(dir))
|
||||
}
|
||||
|
||||
func TestCopyToPluginFailed(t *testing.T) {
|
||||
//assert.Nil(t, DeleteAllAssets(dir))
|
||||
assert.Nil(t, DeleteAllAssets(dir))
|
||||
assert.False(t, UsingAssets(dir))
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,6 @@ type Core struct {
|
|||
Started time.Time `gorm:"-" json:"started_on"`
|
||||
Plugins []*Info `gorm:"-" json:"-"`
|
||||
Notifications []AllNotifiers `gorm:"-" json:"-"`
|
||||
Config *DbConfig `gorm:"-" json:"-"`
|
||||
Integrations []Integrator `gorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue