removed sql files - db updates - migrations - beginning to comment on funcs

pull/61/head^2
Hunter Long 2018-09-05 22:28:35 -07:00
parent 1eb55a0c71
commit 3f056125ae
29 changed files with 196 additions and 546 deletions

View File

@ -1,4 +1,4 @@
VERSION=0.53 VERSION=0.54
BINARY_NAME=statup BINARY_NAME=statup
GOPATH:=$(GOPATH) GOPATH:=$(GOPATH)
GOCMD=go GOCMD=go

View File

@ -29,7 +29,6 @@ import (
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"net/http" "net/http"
"strings"
"time" "time"
) )
@ -240,14 +239,6 @@ func FakeSeed(plug types.PluginActions) {
if err != nil { if err != nil {
utils.Log(3, err) utils.Log(3, err)
} }
up, _ := source.SqlBox.String("sqlite_up.sql")
requests := strings.Split(up, ";")
for _, request := range requests {
db := core.DbSession.Exec(request)
if db.Error != nil {
utils.Log(2, db.Error)
}
}
fmt.Println("Finished creating Test SQLite database") fmt.Println("Finished creating Test SQLite database")
fmt.Println("Inserting example services into test database...") fmt.Println("Inserting example services into test database...")

View File

@ -101,7 +101,7 @@ func mainProcess() {
if err != nil { if err != nil {
utils.Log(4, fmt.Sprintf("could not connect to database: %v", err)) utils.Log(4, fmt.Sprintf("could not connect to database: %v", err))
} }
core.RunDatabaseUpgrades() core.Configs.MigrateDatabase()
core.InitApp() core.InitApp()
if !core.SetupMode { if !core.SetupMode {
LoadPlugins(false) LoadPlugins(false)

View File

@ -101,7 +101,6 @@ func TestRunAll(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
}) })
t.Run(dbt+" Run Database Migrations", func(t *testing.T) { t.Run(dbt+" Run Database Migrations", func(t *testing.T) {
t.SkipNow()
RunDatabaseMigrations(t, dbt) RunDatabaseMigrations(t, dbt)
}) })
t.Run(dbt+" Select Core", func(t *testing.T) { t.Run(dbt+" Select Core", func(t *testing.T) {
@ -251,13 +250,8 @@ func RunCreateSchema(t *testing.T, db string) {
assert.Nil(t, err) assert.Nil(t, err)
} }
func RunConnectDatabase(t *testing.T) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
}
func RunDatabaseMigrations(t *testing.T, db string) { func RunDatabaseMigrations(t *testing.T, db string) {
err := core.RunDatabaseUpgrades() err := core.Configs.MigrateDatabase()
assert.Nil(t, err) assert.Nil(t, err)
} }
@ -493,7 +487,7 @@ func RunService_Failures(t *testing.T) {
service := core.SelectService(18) service := core.SelectService(18)
assert.NotNil(t, service) assert.NotNil(t, service)
assert.Equal(t, "Failing URL", service.Name) assert.Equal(t, "Failing URL", service.Name)
assert.NotEmpty(t, service.Failures) assert.NotEmpty(t, service.AllFailures())
} }
func RunService_LimitedHits(t *testing.T) { func RunService_LimitedHits(t *testing.T) {

View File

@ -48,15 +48,15 @@ func FindCheckin(api string) *types.Checkin {
func (s *Service) AllCheckins() []*types.Checkin { func (s *Service) AllCheckins() []*types.Checkin {
var checkins []*types.Checkin var checkins []*types.Checkin
col := checkinDB().Where("service = ?", s.Id).Order("-id") col := checkinDB().Where("service = ?", s.Id).Order("id desc")
col.Scan(&checkins) col.Find(&checkins)
s.Checkins = checkins s.Checkins = checkins
return checkins return checkins
} }
func (u *Checkin) Create() (int64, error) { func (u *Checkin) Create() (int64, error) {
u.CreatedAt = time.Now() u.CreatedAt = time.Now()
row := checkinDB().Create(&u) row := checkinDB().Create(u)
if row.Error == nil { if row.Error == nil {
utils.Log(2, row.Error) utils.Log(2, row.Error)
return 0, row.Error return 0, row.Error

View File

@ -22,6 +22,7 @@ import (
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"github.com/pkg/errors" "github.com/pkg/errors"
"os" "os"
"sort"
"time" "time"
) )
@ -33,10 +34,10 @@ type Core struct {
} }
var ( var (
Configs *DbConfig Configs *DbConfig // Configs holds all of the config.yml and database info
CoreApp *Core CoreApp *Core // CoreApp is a global variable that contains many elements
SetupMode bool SetupMode bool // SetupMode will be true if Statup does not have a database connection
VERSION string VERSION string // VERSION is set on build automatically by setting a -ldflag
) )
func init() { func init() {
@ -74,15 +75,18 @@ func InsertNotifierDB() error {
return nil return nil
} }
// UpdateCore will update the CoreApp variable inside of the 'core' table in database
func UpdateCore(c *Core) (*Core, error) { func UpdateCore(c *Core) (*Core, error) {
db := coreDB().Update(c) db := coreDB().Update(&c)
return c, db.Error return c, db.Error
} }
// UsingAssets will return true if /assets folder is present
func (c Core) UsingAssets() bool { func (c Core) UsingAssets() bool {
return source.UsingAssets(utils.Directory) return source.UsingAssets(utils.Directory)
} }
// SassVars opens the file /assets/scss/variables.scss to be edited in Theme
func (c Core) SassVars() string { func (c Core) SassVars() string {
if !source.UsingAssets(utils.Directory) { if !source.UsingAssets(utils.Directory) {
return "" return ""
@ -90,6 +94,7 @@ func (c Core) SassVars() string {
return source.OpenAsset(utils.Directory, "scss/variables.scss") return source.OpenAsset(utils.Directory, "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 { func (c Core) BaseSASS() string {
if !source.UsingAssets(utils.Directory) { if !source.UsingAssets(utils.Directory) {
return "" return ""
@ -97,6 +102,8 @@ func (c Core) BaseSASS() string {
return source.OpenAsset(utils.Directory, "scss/base.scss") return source.OpenAsset(utils.Directory, "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 { func (c Core) MobileSASS() string {
if !source.UsingAssets(utils.Directory) { if !source.UsingAssets(utils.Directory) {
return "" return ""
@ -104,6 +111,7 @@ func (c Core) MobileSASS() string {
return source.OpenAsset(utils.Directory, "scss/mobile.scss") return source.OpenAsset(utils.Directory, "scss/mobile.scss")
} }
// AllOnline will be true if all services are online
func (c Core) AllOnline() bool { func (c Core) AllOnline() bool {
for _, s := range CoreApp.Services() { for _, s := range CoreApp.Services() {
if !s.Online { if !s.Online {
@ -113,14 +121,7 @@ func (c Core) AllOnline() bool {
return true return true
} }
func SelectLastMigration() (int64, error) { // SelectCore will return the CoreApp global variable and the settings/configs for Statup
if DbSession == nil {
return 0, errors.New("Database connection has not been created yet")
}
row := coreDB().Take(&CoreApp)
return CoreApp.MigrationId, row.Error
}
func SelectCore() (*Core, error) { func SelectCore() (*Core, error) {
if DbSession == nil { if DbSession == nil {
return nil, errors.New("database has not been initiated yet.") return nil, errors.New("database has not been initiated yet.")
@ -129,7 +130,7 @@ func SelectCore() (*Core, error) {
if !exists { if !exists {
return nil, errors.New("core database has not been setup yet.") return nil, errors.New("core database has not been setup yet.")
} }
db := coreDB().Take(&CoreApp) db := coreDB().First(&CoreApp)
if db.Error != nil { if db.Error != nil {
return nil, db.Error return nil, db.Error
} }
@ -143,16 +144,19 @@ func SelectCore() (*Core, error) {
return CoreApp, db.Error return CoreApp, db.Error
} }
// ServiceOrder will reorder the services based on 'order_id' (Order)
type ServiceOrder []*types.Service type ServiceOrder []*types.Service
func (c ServiceOrder) Len() int { return len(c) } func (c ServiceOrder) Len() int { return len(c) }
func (c ServiceOrder) Swap(i, j int) { c[i], c[j] = c[j], c[i] } func (c ServiceOrder) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order } func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
// Services returns each Service that is attached to this instance
func (c *Core) Services() []*Service { func (c *Core) Services() []*Service {
var services []*Service var services []*Service
servs := CoreApp.GetServices() servs := CoreApp.GetServices()
//sort.Sort(ServiceOrder(servs)) sort.Sort(ServiceOrder(servs))
CoreApp.SetServices(servs)
for _, ser := range servs { for _, ser := range servs {
services = append(services, ReturnService(ser)) services = append(services, ReturnService(ser))
} }

View File

@ -70,8 +70,18 @@ func TestDbConnection(t *testing.T) {
assert.Nil(t, err) assert.Nil(t, err)
} }
func TestDropDatabase(t *testing.T) {
err := Configs.DropDatabase()
assert.Nil(t, err)
}
func TestSeedSchemaDatabase(t *testing.T) { func TestSeedSchemaDatabase(t *testing.T) {
_, _, err := Configs.SeedSchema() err := Configs.CreateDatabase()
assert.Nil(t, err)
}
func TestMigrateDatabase(t *testing.T) {
err := Configs.MigrateDatabase()
assert.Nil(t, err) assert.Nil(t, err)
} }
@ -92,13 +102,6 @@ func TestSelectCore(t *testing.T) {
assert.Equal(t, "Awesome Status", core.Name) assert.Equal(t, "Awesome Status", core.Name)
} }
func TestSelectLastMigration(t *testing.T) {
id, err := SelectLastMigration()
assert.Nil(t, err)
//assert.NotZero(t, id)
t.Log("Last migration id: ", id)
}
func TestInsertNotifierDB(t *testing.T) { func TestInsertNotifierDB(t *testing.T) {
err := InsertNotifierDB() err := InsertNotifierDB()
assert.Nil(t, err) assert.Nil(t, err)

View File

@ -17,10 +17,8 @@ package core
import ( import (
"fmt" "fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/hunterlong/statup/notifiers" "github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/source"
"github.com/hunterlong/statup/types" "github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
@ -28,23 +26,20 @@ import (
_ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite" _ "github.com/jinzhu/gorm/dialects/sqlite"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"os" "os"
"strings"
"time" "time"
) )
var ( var (
DbSession *gorm.DB DbSession *gorm.DB
currentMigration int64
) )
func failuresDB() *gorm.DB { func failuresDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Model(&types.Failure{})
return DbSession.Model(&types.Failure{}).Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Model(&types.Failure{}) return db
} }
func (s *Service) allHits() *gorm.DB { func (s *Service) allHits() *gorm.DB {
@ -53,42 +48,47 @@ func (s *Service) allHits() *gorm.DB {
} }
func hitsDB() *gorm.DB { func hitsDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Model(&types.Hit{})
return DbSession.Model(&types.Hit{}).Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Model(&types.Hit{}) return db
} }
func servicesDB() *gorm.DB { func servicesDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Model(&types.Service{})
return DbSession.Model(&types.Service{}).Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Model(&types.Service{}) return db
} }
func coreDB() *gorm.DB { func coreDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Table("core").Model(&CoreApp)
return DbSession.Table("core").Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Table("core") return db
} }
func usersDB() *gorm.DB { func usersDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Model(&types.User{})
return DbSession.Model(&types.User{}).Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Model(&types.User{}) return db
} }
func commDB() *gorm.DB { func commDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { db := DbSession.Table("communication").Model(&notifiers.Notification{})
return DbSession.Table("communication").Model(&notifiers.Notification{}).Debug() if os.Getenv("GO_ENV") == "test" {
return db.Debug()
} }
return DbSession.Table("communication").Model(&notifiers.Notification{}) return db
} }
func checkinDB() *gorm.DB { func checkinDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" { if os.Getenv("GO_ENV") == "test" {
return DbSession.Model(&types.Checkin{}).Debug() return DbSession.Model(&types.Checkin{}).Debug()
} }
return DbSession.Model(&types.Checkin{}) return DbSession.Model(&types.Checkin{})
@ -98,10 +98,12 @@ type DbConfig struct {
*types.DbConfig *types.DbConfig
} }
// Close shutsdown the database connection
func (db *DbConfig) Close() error { func (db *DbConfig) Close() error {
return DbSession.Close() return DbSession.DB().Close()
} }
// InsertCore create the single row for the Core settings in Statup
func (db *DbConfig) InsertCore() (*Core, error) { func (db *DbConfig) InsertCore() (*Core, error) {
CoreApp = &Core{Core: &types.Core{ CoreApp = &Core{Core: &types.Core{
Name: db.Project, Name: db.Project,
@ -117,41 +119,37 @@ func (db *DbConfig) InsertCore() (*Core, error) {
return CoreApp, query.Error return CoreApp, query.Error
} }
// Connect will attempt to connect to the sqlite, postgres, or mysql database
func (db *DbConfig) Connect(retry bool, location string) error { func (db *DbConfig) Connect(retry bool, location string) error {
var err error var err error
if DbSession != nil { if DbSession != nil {
DbSession = nil DbSession = nil
} }
switch Configs.DbConn { var conn, dbType string
dbType = Configs.DbConn
switch dbType {
case "sqlite": case "sqlite":
DbSession, err = gorm.Open("sqlite3", utils.Directory+"/statup.db") conn = utils.Directory + "/statup.db"
if err != nil { dbType = "sqlite3"
return err
}
case "mysql": case "mysql":
if Configs.DbPort == 0 { if Configs.DbPort == 0 {
Configs.DbPort = 3306 Configs.DbPort = 3306
} }
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort) host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort)
conn := fmt.Sprintf("%v:%v@tcp(%v)/%v?charset=utf8&parseTime=True&loc=Local", Configs.DbUser, Configs.DbPass, host, Configs.DbData) conn = fmt.Sprintf("%v:%v@tcp(%v)/%v?charset=utf8&parseTime=True&loc=Local", Configs.DbUser, Configs.DbPass, host, Configs.DbData)
DbSession, err = gorm.Open("mysql", conn)
DbSession.DB().SetConnMaxLifetime(time.Minute * 5)
DbSession.DB().SetMaxIdleConns(0)
DbSession.DB().SetMaxOpenConns(5)
if err != nil {
if retry {
utils.Log(1, fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", host))
return db.waitForDb()
} else {
return err
}
}
case "postgres": case "postgres":
if Configs.DbPort == 0 { if Configs.DbPort == 0 {
Configs.DbPort = 5432 Configs.DbPort = 5432
} }
conn := fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v sslmode=disable", Configs.DbHost, Configs.DbPort, Configs.DbUser, Configs.DbData, Configs.DbPass) conn = fmt.Sprintf("host=%v port=%v user=%v dbname=%v password=%v sslmode=disable", Configs.DbHost, Configs.DbPort, Configs.DbUser, Configs.DbData, Configs.DbPass)
DbSession, err = gorm.Open("postgres", conn) case "mssql":
if Configs.DbPort == 0 {
Configs.DbPort = 1433
}
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort)
conn = fmt.Sprintf("sqlserver://%v:%v@%v?database=%v", Configs.DbUser, Configs.DbPass, host, Configs.DbData)
}
DbSession, err = gorm.Open(dbType, conn)
if err != nil { if err != nil {
if retry { if retry {
utils.Log(1, fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", Configs.DbHost)) utils.Log(1, fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", Configs.DbHost))
@ -161,22 +159,6 @@ func (db *DbConfig) Connect(retry bool, location string) error {
return err return err
} }
} }
case "mssql":
if Configs.DbPort == 0 {
Configs.DbPort = 1433
}
host := fmt.Sprintf("%v:%v", Configs.DbHost, Configs.DbPort)
conn := fmt.Sprintf("sqlserver://%v:%v@%v?database=%v", Configs.DbUser, Configs.DbPass, host, Configs.DbData)
DbSession, err = gorm.Open("mssql", conn)
if err != nil {
if retry {
utils.Log(1, fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", host))
return db.waitForDb()
} else {
return err
}
}
}
err = DbSession.DB().Ping() err = DbSession.DB().Ping()
if err == nil { if err == nil {
utils.Log(1, fmt.Sprintf("Database connection to '%v' was successful.", Configs.DbData)) utils.Log(1, fmt.Sprintf("Database connection to '%v' was successful.", Configs.DbData))
@ -189,6 +171,8 @@ func (db *DbConfig) waitForDb() error {
return db.Connect(true, utils.Directory) return db.Connect(true, utils.Directory)
} }
// DatabaseMaintence will automatically delete old records from 'failures' and 'hits'
// this function is currently set to delete records 7+ days old every 60 minutes
func DatabaseMaintence() { func DatabaseMaintence() {
for range time.Tick(60 * time.Minute) { for range time.Tick(60 * time.Minute) {
utils.Log(1, "Checking for database records older than 7 days...") utils.Log(1, "Checking for database records older than 7 days...")
@ -198,6 +182,7 @@ func DatabaseMaintence() {
} }
} }
// DeleteAllSince will delete a specific table's records based on a time.
func DeleteAllSince(table string, date time.Time) { func DeleteAllSince(table string, date time.Time) {
sql := fmt.Sprintf("DELETE FROM %v WHERE created_at < '%v';", table, date.Format("2006-01-02")) sql := fmt.Sprintf("DELETE FROM %v WHERE created_at < '%v';", table, date.Format("2006-01-02"))
db := DbSession.Raw(sql) db := DbSession.Raw(sql)
@ -207,6 +192,7 @@ func DeleteAllSince(table string, date time.Time) {
} }
} }
// Update will save the config.yml file
func (c *DbConfig) Update() error { func (c *DbConfig) Update() error {
var err error var err error
config, err := os.Create(utils.Directory + "/config.yml") config, err := os.Create(utils.Directory + "/config.yml")
@ -224,6 +210,7 @@ func (c *DbConfig) Update() error {
return err return err
} }
// Save will initially create the config.yml file
func (c *DbConfig) Save() (*DbConfig, error) { func (c *DbConfig) Save() (*DbConfig, error) {
var err error var err error
config, err := os.Create(utils.Directory + "/config.yml") config, err := os.Create(utils.Directory + "/config.yml")
@ -243,6 +230,7 @@ func (c *DbConfig) Save() (*DbConfig, error) {
return c, err return c, err
} }
// CreateCore will initialize the global variable 'CoreApp". This global variable contains most of Statup app.
func (c *DbConfig) CreateCore() *Core { func (c *DbConfig) CreateCore() *Core {
newCore := &types.Core{ newCore := &types.Core{
Name: c.Project, Name: c.Project,
@ -264,91 +252,7 @@ func (c *DbConfig) CreateCore() *Core {
return CoreApp return CoreApp
} }
func versionHigher(migrate int64) bool { // SeedDatabase will insert many elements into the database. This is only ran in Dev/Test move
if CoreApp.MigrationId < migrate {
return true
}
return false
}
func reverseSlice(s []string) []string {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func RunDatabaseUpgrades() error {
var err error
currentMigration, err = SelectLastMigration()
if err != nil {
return err
}
utils.Log(1, fmt.Sprintf("Checking for Database Upgrades since #%v", currentMigration))
upgrade, _ := source.SqlBox.String(CoreApp.DbConnection + "_upgrade.sql")
// parse db version and upgrade file
ups := strings.Split(upgrade, "=========================================== ")
ups = reverseSlice(ups)
var ran int
var lastMigration int64
for _, v := range ups {
if len(v) == 0 {
continue
}
vers := strings.Split(v, "\n")
lastMigration = utils.StringInt(vers[0])
data := vers[1:]
//fmt.Printf("Checking Migration from v%v to v%v - %v\n", CoreApp.Version, version, versionHigher(version))
if currentMigration >= lastMigration {
continue
}
utils.Log(1, fmt.Sprintf("Migrating Database from #%v to #%v", currentMigration, lastMigration))
for _, m := range data {
if m == "" {
continue
}
utils.Log(1, fmt.Sprintf("Running Query: %v", m))
db := DbSession.Raw(m)
ran++
if db.Error != nil {
utils.Log(2, db.Error)
continue
}
}
currentMigration = lastMigration
}
if ran > 0 {
utils.Log(1, fmt.Sprintf("Database Upgraded %v queries ran, current #%v", ran, currentMigration))
CoreApp, err = SelectCore()
if err != nil {
return err
}
CoreApp.MigrationId = currentMigration
UpdateCore(CoreApp)
}
return err
}
func (db *DbConfig) SeedSchema() (string, string, error) {
utils.Log(1, "Seeding Schema Database with Dummy Data...")
dir := utils.Directory
var cmd string
switch db.DbConn {
case "sqlite":
cmd = fmt.Sprintf("cat %v/source/sql/sqlite_up.sql | sqlite3 %v/statup.db", dir, dir)
case "mysql":
cmd = fmt.Sprintf("mysql -h %v -P %v -u %v --password=%v %v < %v/source/sql/mysql_up.sql", Configs.DbHost, Configs.DbPort, Configs.DbUser, Configs.DbPass, Configs.DbData, dir)
case "postgres":
cmd = fmt.Sprintf("PGPASSWORD=%v psql -U %v -h %v -d %v -1 -f %v/source/sql/postgres_up.sql", db.DbPass, db.DbUser, db.DbHost, db.DbData, dir)
}
out, outErr, err := utils.Command(cmd)
if err != nil {
return out, outErr, err
}
return out, outErr, err
}
func (db *DbConfig) SeedDatabase() (string, string, error) { func (db *DbConfig) SeedDatabase() (string, string, error) {
utils.Log(1, "Seeding Database with Dummy Data...") utils.Log(1, "Seeding Database with Dummy Data...")
dir := utils.Directory dir := utils.Directory
@ -365,6 +269,7 @@ func (db *DbConfig) SeedDatabase() (string, string, error) {
return out, outErr, err return out, outErr, err
} }
// DropDatabase will DROP each table Statup created
func (db *DbConfig) DropDatabase() error { func (db *DbConfig) DropDatabase() error {
utils.Log(1, "Dropping Database Tables...") utils.Log(1, "Dropping Database Tables...")
err := DbSession.DropTableIfExists("checkins") err := DbSession.DropTableIfExists("checkins")
@ -377,6 +282,7 @@ func (db *DbConfig) DropDatabase() error {
return err.Error return err.Error
} }
// CreateDatabase will CREATE TABLES for each of the Statup elements
func (db *DbConfig) CreateDatabase() error { func (db *DbConfig) CreateDatabase() error {
utils.Log(1, "Creating Database Tables...") utils.Log(1, "Creating Database Tables...")
err := DbSession.CreateTable(&types.Checkin{}) err := DbSession.CreateTable(&types.Checkin{})
@ -390,17 +296,29 @@ func (db *DbConfig) CreateDatabase() error {
return err.Error return err.Error
} }
// MigrateDatabase will migrate the database structure to current version.
// This function will NOT remove previous records, tables or columns from the database.
// If this function has an issue, it will ROLLBACK to the previous state.
func (db *DbConfig) MigrateDatabase() error { func (db *DbConfig) MigrateDatabase() error {
utils.Log(1, "Migrating Database Tables...") utils.Log(1, "Migrating Database Tables...")
err := DbSession.AutoMigrate(&types.Checkin{})
err = DbSession.Table("communication").AutoMigrate(&notifiers.Notification{}) tx := DbSession.Begin()
err = DbSession.Table("core").AutoMigrate(&types.Core{}) defer func() {
err = DbSession.AutoMigrate(&types.Failure{}) if r := recover(); r != nil {
err = DbSession.AutoMigrate(&types.Hit{}) tx.Rollback()
err = DbSession.AutoMigrate(&types.Service{}) }
err = DbSession.AutoMigrate(&types.User{}) }()
if tx.Error != nil {
return tx.Error
}
tx = tx.AutoMigrate(&types.Service{}, &types.User{}, &types.Hit{}, &types.Failure{}, &types.Checkin{}).Table("core").AutoMigrate(&types.Core{}).Table("communication").AutoMigrate(&notifiers.Notification{})
if tx.Error != nil {
tx.Rollback()
utils.Log(3, fmt.Sprintf("Statup Database could not be migrated: %v", tx.Error))
return tx.Error
}
utils.Log(1, "Statup Database Migrated") utils.Log(1, "Statup Database Migrated")
return err.Error return tx.Commit().Error
} }
func (c *DbConfig) Clean() *DbConfig { func (c *DbConfig) Clean() *DbConfig {

View File

@ -66,13 +66,6 @@ func (s *Service) LimitedFailures() []*Failure {
return failArr return failArr
} }
func reverseFailures(input []*Failure) []*Failure {
if len(input) == 0 {
return input
}
return append(reverseFailures(input[1:]), input[0])
}
func (f *Failure) Ago() string { func (f *Failure) Ago() string {
got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt) got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt)
return got return got
@ -101,7 +94,7 @@ func (s *Service) TotalFailures24() (uint64, error) {
func (s *Service) TotalFailures() (uint64, error) { func (s *Service) TotalFailures() (uint64, error) {
var count uint64 var count uint64
rows := failuresDB().Where("service = ?", s.Id) rows := failuresDB().Where("service = ?", s.Id)
err := rows.Count(count) err := rows.Count(&count)
return count, err.Error return count, err.Error
} }

View File

@ -26,7 +26,7 @@ type Hit struct {
} }
func (s *Service) CreateHit(h *types.Hit) (int64, error) { func (s *Service) CreateHit(h *types.Hit) (int64, error) {
db := hitsDB().Create(&h) db := hitsDB().Create(h)
if db.Error != nil { if db.Error != nil {
utils.Log(2, db.Error) utils.Log(2, db.Error)
return 0, db.Error return 0, db.Error
@ -62,10 +62,6 @@ func (s *Service) SelectHitsGroupBy(group string) ([]*Hit, error) {
return hits, err.Error return hits, err.Error
} }
func (s *Service) hits() {
}
func (s *Service) TotalHits() (uint64, error) { func (s *Service) TotalHits() (uint64, error) {
var count uint64 var count uint64
col := hitsDB().Where("service = ?", s.Id) col := hitsDB().Where("service = ?", s.Id)

View File

@ -44,7 +44,7 @@ func SelectService(id int64) *Service {
func (c *Core) SelectAllServices() ([]*types.Service, error) { func (c *Core) SelectAllServices() ([]*types.Service, error) {
var services []*types.Service var services []*types.Service
var servs []*types.Service var servs []*types.Service
db := servicesDB().Find(&services) db := servicesDB().Find(&services).Order("order_id desc")
if db.Error != nil { if db.Error != nil {
utils.Log(3, fmt.Sprintf("service error: %v", db.Error)) utils.Log(3, fmt.Sprintf("service error: %v", db.Error))
return nil, db.Error return nil, db.Error
@ -186,24 +186,37 @@ func (s *Service) AvgUptime24() string {
func (s *Service) AvgUptime(ago time.Time) string { func (s *Service) AvgUptime(ago time.Time) string {
failed, _ := s.TotalFailuresSince(ago) failed, _ := s.TotalFailuresSince(ago)
if failed == 0 { if failed == 0 {
s.TotalUptime = "100" return "100"
return s.TotalUptime
} }
total, _ := s.TotalHitsSince(ago) total, _ := s.TotalHitsSince(ago)
if total == 0 { if total == 0 {
s.TotalUptime = "0" return "0"
return s.TotalUptime
} }
percent := float64(failed) / float64(total) * 100 percent := float64(failed) / float64(total) * 100
percent = 100 - percent percent = 100 - percent
if percent < 0 { if percent < 0 {
percent = 0 percent = 0
} }
s.TotalUptime = fmt.Sprintf("%0.2f", percent) amount := fmt.Sprintf("%0.2f", percent)
if s.TotalUptime == "100.00" { if amount == "100.00" {
s.TotalUptime = "100" amount = "100"
} }
return s.TotalUptime return amount
}
func (s *Service) TotalUptime() string {
hits, _ := s.TotalHits()
failures, _ := s.TotalFailures()
percent := float64(failures) / float64(hits) * 100
percent = 100 - percent
if percent < 0 {
percent = 0
}
amount := fmt.Sprintf("%0.2f", percent)
if amount == "100.00" {
amount = "100"
}
return amount
} }
func (s *Service) index() int { func (s *Service) index() int {

View File

@ -59,8 +59,10 @@ func ReorderServiceHandler(w http.ResponseWriter, r *http.Request) {
decoder := json.NewDecoder(r.Body) decoder := json.NewDecoder(r.Body)
decoder.Decode(&newOrder) decoder.Decode(&newOrder)
for _, s := range newOrder { for _, s := range newOrder {
fmt.Println("updating: ", s.Id, " to be order_id: ", s.Order)
service := core.SelectService(s.Id) service := core.SelectService(s.Id)
service.UpdateSingle("order_id", s.Order) service.Order = s.Order
service.Update(false)
} }
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }

View File

@ -33,18 +33,19 @@ var (
type Notification struct { type Notification struct {
Id int64 `gorm:"primary_key column:id" json:"id"` Id int64 `gorm:"primary_key column:id" json:"id"`
Method string `gorm:"column:method" json:"method"` Method string `gorm:"column:method" json:"method"`
Host string `gorm:"column:host" json:"-"` Host string `gorm:"not null;column:host" json:"-"`
Port int `gorm:"column:port" json:"-"` Port int `gorm:"not null;column:port" json:"-"`
Username string `gorm:"column:username" json:"-"` Username string `gorm:"not null;column:username" json:"-"`
Password string `gorm:"column:password" json:"-"` Password string `gorm:"not null;column:password" json:"-"`
Var1 string `gorm:"column:var1" json:"-"` Var1 string `gorm:"not null;column:var1" json:"-"`
Var2 string `gorm:"column:var2" json:"-"` Var2 string `gorm:"not null;column:var2" json:"-"`
ApiKey string `gorm:"column:api_key" json:"-"` ApiKey string `gorm:"not null;column:api_key" json:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"` ApiSecret string `gorm:"not null;column:api_secret" json:"-"`
Enabled bool `gorm:"column:enabled" json:"enabled"` Enabled bool `gorm:"column:enabled;type:boolean;default:false" json:"enabled"`
Limits int `gorm:"column:limits" json:"-"` Limits int `gorm:"not null;column:limits" json:"-"`
Removable bool `gorm:"column:removable" json:"-"` Removable bool `gorm:"column:removable" json:"-"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
Form []NotificationForm `gorm:"-" json:"-"` Form []NotificationForm `gorm:"-" json:"-"`
Routine chan struct{} `gorm:"-" json:"-"` Routine chan struct{} `gorm:"-" json:"-"`
} }

View File

@ -27,7 +27,6 @@ import (
) )
var ( var (
SqlBox *rice.Box
CssBox *rice.Box CssBox *rice.Box
ScssBox *rice.Box ScssBox *rice.Box
JsBox *rice.Box JsBox *rice.Box
@ -35,7 +34,6 @@ var (
) )
func Assets() { func Assets() {
SqlBox = rice.MustFindBox("sql")
CssBox = rice.MustFindBox("css") CssBox = rice.MustFindBox("css")
ScssBox = rice.MustFindBox("scss") ScssBox = rice.MustFindBox("scss")
JsBox = rice.MustFindBox("js") JsBox = rice.MustFindBox("js")

View File

@ -1,7 +0,0 @@
DROP TABLE IF EXISTS core;
DROP TABLE IF EXISTS hits;
DROP TABLE IF EXISTS failures;
DROP TABLE IF EXISTS users;
DROP TABLE IF EXISTS checkins;
DROP TABLE IF EXISTS services;
DROP TABLE IF EXISTS communication;

View File

@ -1,78 +0,0 @@
CREATE TABLE core (
name VARCHAR(50),
description text,
config VARCHAR(50),
api_key VARCHAR(50),
api_secret VARCHAR(50),
style text,
footer text,
domain text,
version VARCHAR(50),
migration_id INT(6) NOT NULL DEFAULT 0,
use_cdn BOOL NOT NULL DEFAULT '0'
) ENGINE=INNODB;
CREATE TABLE users (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
username VARCHAR(50) NOT NULL UNIQUE,
password text,
email VARCHAR (50),
api_key VARCHAR(50),
api_secret VARCHAR(50),
administrator BOOL NOT NULL DEFAULT '0',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (username, email)
) ENGINE=INNODB;
CREATE TABLE services (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
name VARCHAR(50),
domain text,
check_type text,
method VARCHAR(50),
port INT(6),
expected text,
expected_status INT(6),
check_interval int(11),
post_data text,
order_id integer default 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
timeout INT(6) DEFAULT 30
) ENGINE=INNODB;
CREATE TABLE hits (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
service BIGINT(20) UNSIGNED NOT NULL,
latency float,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
) ENGINE=INNODB;
CREATE TABLE failures (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
issue text,
method text,
service BIGINT(20) UNSIGNED NOT NULL,
created_at TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
) ENGINE=INNODB;
CREATE TABLE checkins (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
service BIGINT(20) UNSIGNED NOT NULL,
check_interval integer,
api text,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
) ENGINE=INNODB;
CREATE TABLE communication (
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
method text,
host text,
port integer,
username text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled BOOL NOT NULL DEFAULT '0',
removable BOOL NOT NULL DEFAULT '0',
limits integer,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;

View File

@ -1,9 +0,0 @@
=========================================== 1534178020
UPDATE services SET order_id=0 WHERE order_id IS NULL;
=========================================== 1532068515
ALTER TABLE services ALTER COLUMN order_id integer DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn BOOL NOT NULL DEFAULT '0';
=========================================== 1
ALTER TABLE core ADD COLUMN migration_id INT(6) NOT NULL DEFAULT 0;

View File

@ -1,84 +0,0 @@
CREATE TABLE core (
name text,
description text,
config text,
api_key text,
api_secret text,
style text,
footer text,
domain text,
version text,
migration_id integer default 0,
use_cdn bool default false
);
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR (50) UNIQUE,
password text,
email VARCHAR (50) UNIQUE,
api_key text,
api_secret text,
administrator bool,
created_at TIMESTAMP
);
CREATE TABLE services (
id SERIAL PRIMARY KEY,
name text,
domain text,
check_type text,
method text,
port integer,
expected text,
expected_status integer,
check_interval integer,
post_data text,
order_id integer default 0,
timeout integer default 30,
created_at TIMESTAMP
);
CREATE TABLE hits (
id SERIAL PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
latency float,
created_at TIMESTAMP
);
CREATE TABLE failures (
id SERIAL PRIMARY KEY,
issue text,
method text,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMP
);
CREATE TABLE checkins (
id SERIAL PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
check_interval integer,
api text,
created_at TIMESTAMP
);
CREATE TABLE communication (
id SERIAL PRIMARY KEY,
method text,
host text,
port integer,
username text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled boolean,
removable boolean,
limits integer,
created_at TIMESTAMP
);
CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service);
CREATE INDEX idx_checkins ON checkins(service);

View File

@ -1,9 +0,0 @@
=========================================== 1534178020
UPDATE services SET order_id=0 WHERE order_id IS NULL;
=========================================== 1532068515
ALTER TABLE services ALTER COLUMN order_id integer DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
=========================================== 1
ALTER TABLE core ADD COLUMN migration_id integer default 0 NOT NULL;

View File

@ -1,84 +0,0 @@
CREATE TABLE core (
name text,
description text,
config text,
api_key text,
api_secret text,
style text,
footer text,
domain text,
version text,
migration_id integer default 0,
use_cdn bool default false
);
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username text NOT NULL UNIQUE,
password text,
email text,
api_key text,
api_secret text,
administrator bool,
created_at TIMESTAMP,
UNIQUE (username, email)
);
CREATE TABLE services (
id INTEGER PRIMARY KEY,
name text,
domain text,
check_type text,
method text,
port integer,
expected text,
expected_status integer,
check_interval integer,
post_data text,
order_id integer default 0,
timeout integer default 30,
created_at TIMESTAMP
);
CREATE TABLE hits (
id INTEGER PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
latency float,
created_at TIMESTAMP
);
CREATE TABLE failures (
id INTEGER PRIMARY KEY,
issue text,
method text,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at TIMESTAMP
);
CREATE TABLE checkins (
id INTEGER PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
check_interval integer,
api text,
created_at TIMESTAMP
);
CREATE TABLE communication (
id INTEGER PRIMARY KEY,
method text,
host text,
port integer,
username text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled boolean,
removable boolean,
limits integer,
created_at TIMESTAMP
);
CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service);
CREATE INDEX idx_checkins ON checkins(service);

View File

@ -1,9 +0,0 @@
=========================================== 1534178020
UPDATE services SET order_id=0 WHERE order_id IS NULL;
=========================================== 1532068515
ALTER TABLE services ALTER COLUMN order_id integer DEFAULT 0;
ALTER TABLE services ADD COLUMN timeout integer DEFAULT 30;
=========================================== 1530841150
ALTER TABLE core ADD COLUMN use_cdn bool DEFAULT FALSE;
=========================================== 1
ALTER TABLE core ADD COLUMN migration_id integer NOT NULL DEFAULT 0;

View File

@ -1,6 +1,6 @@
{{ define "footer"}} {{ define "footer"}}
<div class="footer text-center mb-4"> <div class="footer text-center mb-4">
{{ if CoreApp.Footer }} {{ if ne CoreApp.Footer "" }}
{{ safe CoreApp.Footer }} {{ safe CoreApp.Footer }}
{{ else }} {{ else }}
<a href="https://github.com/hunterlong/statup" target="_blank">Statup {{VERSION}} made with ❤️</a> | <a href="/dashboard">Dashboard</a> <a href="https://github.com/hunterlong/statup" target="_blank">Statup {{VERSION}} made with ❤️</a> | <a href="/dashboard">Dashboard</a>

View File

@ -51,7 +51,7 @@
</div> </div>
<div class="col-4"> <div class="col-4">
<span class="lg_number">{{.AvgUptime24}}%</span> <span class="lg_number">{{.TotalUptime}}%</span>
Total Uptime Total Uptime
</div> </div>
</div> </div>

View File

@ -9,7 +9,8 @@ type Checkin struct {
Service int64 `gorm:"index;column:service"` Service int64 `gorm:"index;column:service"`
Interval int64 `gorm:"column:check_interval"` Interval int64 `gorm:"column:check_interval"`
Api string `gorm:"column:api"` Api string `gorm:"column:api"`
CreatedAt time.Time `gorm:"column:created_at"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
Hits int64 `json:"hits"` Hits int64 `json:"hits"`
Last time.Time `json:"last"` Last time.Time `json:"last"`
CheckinInterface `json:"-"` CheckinInterface `json:"-"`

View File

@ -1,32 +1,45 @@
package types package types
import ( import (
"sort"
"time" "time"
) )
// Core struct contains all the required fields for Statup. All application settings
// will be saved into 1 row in the 'core' table. You can use the core.CoreApp
// global variable to interact with the attributes to the application, such as services.
type Core struct { type Core struct {
Name string `gorm:"column:name" json:"name"` Name string `gorm:"not null;column:name" json:"name"`
Description string `gorm:"column:description" json:"description,omitempty"` Description string `gorm:"not null;column:description" json:"description,omitempty"`
Config string `gorm:"column:config" json:"-"` Config string `gorm:"column:config" json:"-"`
ApiKey string `gorm:"column:api_key" json:"-"` ApiKey string `gorm:"column:api_key" json:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"` ApiSecret string `gorm:"column:api_secret" json:"-"`
Style string `gorm:"column:style" json:"style,omitempty"` Style string `gorm:"not null;column:style" json:"style,omitempty"`
Footer string `gorm:"column:footer" json:"footer,omitempty"` Footer string `gorm:"not null;column:footer" json:"footer,omitempty"`
Domain string `gorm:"column:domain" json:"domain,omitempty"` Domain string `gorm:"not null;column:domain" json:"domain,omitempty"`
Version string `gorm:"column:version" json:"version"` Version string `gorm:"column:version" json:"version"`
MigrationId int64 `gorm:"column:migration_id" json:"migration_id,omitempty"` MigrationId int64 `gorm:"column:migration_id" json:"migration_id,omitempty"`
UseCdn bool `gorm:"column:use_cdn" json:"using_cdn,omitempty"` UseCdn bool `gorm:"column:use_cdn;default:false" json:"using_cdn,omitempty"`
DbConnection string `gorm:"-" json:database"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
Started time.Time `gorm:"-" json:started_on"` UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
dbServices []*Service `gorm:"-" json:services,omitempty"` DbConnection string `gorm:"-" json:"database"`
Plugins []Info `gorm:"-" json:-"` Started time.Time `gorm:"-" json:"started_on"`
Repos []PluginJSON `gorm:"-" json:-"` dbServices []*Service `gorm:"-" json:"services,omitempty"`
AllPlugins []PluginActions `gorm:"-" json:-"` Plugins []Info `gorm:"-" json:"-"`
Communications []AllNotifiers `gorm:"-" json:-"` Repos []PluginJSON `gorm:"-" json:"-"`
CoreInterface `gorm:"-" json:-"` AllPlugins []PluginActions `gorm:"-" json:"-"`
Communications []AllNotifiers `gorm:"-" json:"-"`
CoreInterface `gorm:"-" json:"-"`
} }
type ServiceOrder []*Service
func (c ServiceOrder) Len() int { return len(c) }
func (c ServiceOrder) Swap(i, j int) { c[i], c[j] = c[j], c[i] }
func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
func (c *Core) SetServices(s []*Service) { func (c *Core) SetServices(s []*Service) {
sort.Sort(ServiceOrder(c.dbServices))
c.dbServices = s c.dbServices = s
} }

View File

@ -23,21 +23,21 @@ type Service struct {
Id int64 `gorm:"primary_key;column:id" json:"id"` Id int64 `gorm:"primary_key;column:id" json:"id"`
Name string `gorm:"column:name" json:"name"` Name string `gorm:"column:name" json:"name"`
Domain string `gorm:"column:domain" json:"domain"` Domain string `gorm:"column:domain" json:"domain"`
Expected string `gorm:"column:expected" json:"expected"` Expected string `gorm:"not null;column:expected" json:"expected"`
ExpectedStatus int `gorm:"column:expected_status" json:"expected_status"` ExpectedStatus int `gorm:"default:200;column:expected_status" json:"expected_status"`
Interval int `gorm:"column:check_interval" json:"check_interval"` Interval int `gorm:"default:30;column:check_interval" json:"check_interval"`
Type string `gorm:"column:check_type" json:"type"` Type string `gorm:"column:check_type" json:"type"`
Method string `gorm:"column:method" json:"method"` Method string `gorm:"column:method" json:"method"`
PostData string `gorm:"column:post_data" json:"post_data"` PostData string `gorm:"not null;column:post_data" json:"post_data"`
Port int `gorm:"column:port" json:"port"` Port int `gorm:"not null;column:port" json:"port"`
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
Order int `gorm:"default:0;column:order_id" json:"order_id"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
Timeout int `gorm:"column:timeout" json:"timeout"` UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
Order int `gorm:"column:order_id" json:"order_id"`
Online bool `gorm:"-" json:"online"` Online bool `gorm:"-" json:"online"`
Latency float64 `gorm:"-" json:"latency"` Latency float64 `gorm:"-" json:"latency"`
Online24Hours float32 `gorm:"-" json:"24_hours_online"` Online24Hours float32 `gorm:"-" json:"24_hours_online"`
AvgResponse string `gorm:"-" json:"avg_response"` AvgResponse string `gorm:"-" json:"avg_response"`
TotalUptime string `gorm:"-" json:"uptime"`
Failures []*Failure `gorm:"-" json:"failures"` Failures []*Failure `gorm:"-" json:"failures"`
Checkins []*Checkin `gorm:"-" json:"checkins"` Checkins []*Checkin `gorm:"-" json:"checkins"`
Running chan bool `gorm:"-" json:"-"` Running chan bool `gorm:"-" json:"-"`

View File

@ -61,6 +61,7 @@ type PluginActions interface {
type AllNotifiers interface{} type AllNotifiers interface{}
// Hit struct is a 'successful' ping or web response entry for a service.
type Hit struct { type Hit struct {
Id int64 `gorm:"primary_key;column:id"` Id int64 `gorm:"primary_key;column:id"`
Service int64 `gorm:"index;column:service"` Service int64 `gorm:"index;column:service"`
@ -68,6 +69,7 @@ type Hit struct {
CreatedAt time.Time `gorm:"column:created_at"` CreatedAt time.Time `gorm:"column:created_at"`
} }
// DbConfig struct is used for the database connection and creates the 'config.yml' file
type DbConfig struct { type DbConfig struct {
DbConn string `yaml:"connection"` DbConn string `yaml:"connection"`
DbHost string `yaml:"host"` DbHost string `yaml:"host"`

View File

@ -13,6 +13,7 @@ type User struct {
ApiSecret string `gorm:"column:api_secret" json:"-"` ApiSecret string `gorm:"column:api_secret" json:"-"`
Admin bool `gorm:"column:administrator" json:"admin"` Admin bool `gorm:"column:administrator" json:"admin"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"` CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
UserInterface `gorm:"-" json:"-"` UserInterface `gorm:"-" json:"-"`
} }