gorm DB - issue fixes - DB seeds - benchmark tests

pull/61/head^2
Hunter Long 2018-09-05 03:54:57 -07:00
parent e4ccdba34d
commit 1eb55a0c71
48 changed files with 1408 additions and 677 deletions

82
Gopkg.lock generated
View File

@ -12,6 +12,14 @@
pruneopts = "UT"
revision = "c02ca9a983da5807ddf7d796784928f5be4afd09"
[[projects]]
digest = "1:e92f5581902c345eb4ceffdcd4a854fb8f73cf436d47d837d1ec98ef1fe0a214"
name = "github.com/StackExchange/wmi"
packages = ["."]
pruneopts = "UT"
revision = "5d049714c4a64225c3c79a7cf7d02f7fb5b96338"
version = "1.0.0"
[[projects]]
branch = "master"
digest = "1:4b79025e1eaa5726b92e409a46571f1998b56f0a2d881d6271ca616095eae46e"
@ -44,6 +52,17 @@
pruneopts = "UT"
revision = "ebf56d35bba727c68ac77f56f2fcf90b181851aa"
[[projects]]
digest = "1:64a5a67c69b70c2420e607a8545d674a23778ed9c3e80607bfd17b77c6c87f6a"
name = "github.com/go-ole/go-ole"
packages = [
".",
"oleutil",
]
pruneopts = "UT"
revision = "a41e3c4b706f6ae8dfbff342b06e40fa4d2d0506"
version = "v1.2.1"
[[projects]]
branch = "master"
digest = "1:70a20b8adf085489a342d033b68b7fc27f4017c51e015b857387249493ee0561"
@ -68,6 +87,14 @@
revision = "08b5f424b9271eedf6f9f0ce86cb9396ed337a42"
version = "v1.1.1"
[[projects]]
digest = "1:664d37ea261f0fc73dd17f4a1f5f46d01fbb0b0d75f6375af064824424109b7d"
name = "github.com/gorilla/handlers"
packages = ["."]
pruneopts = "UT"
revision = "7e0847f9db758cdebd26c149d0ae9d5d0b9c98ce"
version = "v1.4.0"
[[projects]]
digest = "1:195b71563f8432dac9d9692aca2a9ae098bc35763999573eb1c7d52a02a47ce7"
name = "github.com/gorilla/mux"
@ -91,6 +118,14 @@
revision = "03b6f63cc43ef9c7240a635a5e22b13180e822b8"
version = "v1.1.1"
[[projects]]
digest = "1:7b5c6e2eeaa9ae5907c391a91c132abfd5c9e8a784a341b5625e750c67e6825d"
name = "github.com/gorilla/websocket"
packages = ["."]
pruneopts = "UT"
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
version = "v1.4.0"
[[projects]]
branch = "master"
digest = "1:d166a4b3543a71d87e34767ace94e8b516e79ba45111730306f07c8d6f797f1f"
@ -126,6 +161,17 @@
pruneopts = "UT"
revision = "b3511bfdd742af558b54eb6160aca9446d762a19"
[[projects]]
branch = "master"
digest = "1:4f4fd75cbdd5ad0696f4d762328f094b9c86061323c9a9f8d0de157f06197e89"
name = "github.com/mkevac/debugcharts"
packages = [
".",
"bindata",
]
pruneopts = "UT"
revision = "d3203a8fa92649b82dc35c214979861de918874a"
[[projects]]
branch = "master"
digest = "1:3891cc78541df6e4596b3e73978eb062d32967084069270ec881b959be5155ae"
@ -150,6 +196,29 @@
pruneopts = "UT"
revision = "6283090d169f51a2410b4e260341a01c9a4c0ca7"
[[projects]]
digest = "1:7395b855a6078ad2e6c40311402a057a91125fb9f32cf228e1b32cdc57c33538"
name = "github.com/shirou/gopsutil"
packages = [
"cpu",
"host",
"internal/common",
"mem",
"net",
"process",
]
pruneopts = "UT"
revision = "8048a2e9c5773235122027dd585cf821b2af1249"
version = "v2.18.07"
[[projects]]
branch = "master"
digest = "1:99c6a6dab47067c9b898e8c8b13d130c6ab4ffbcc4b7cc6236c2cd0b1e344f5b"
name = "github.com/shirou/w32"
packages = ["."]
pruneopts = "UT"
revision = "bb4de0191aa41b5507caa14b0650cdbddcd9280b"
[[projects]]
digest = "1:18752d0b95816a1b777505a97f71c7467a8445b8ffb55631a7bf779f6ba4fa83"
name = "github.com/stretchr/testify"
@ -168,6 +237,17 @@
pruneopts = "UT"
revision = "c126467f60eb25f8f27e5a981f32a87e3965053f"
[[projects]]
branch = "master"
digest = "1:629034aef6b53eb8ea737e6d82cb5402907e2757fbab5ddf5e74c08b4c6473af"
name = "golang.org/x/sys"
packages = [
"unix",
"windows",
]
pruneopts = "UT"
revision = "fa5fdf94c78965f1aa8423f0cc50b8b8d728b05a"
[[projects]]
digest = "1:c25289f43ac4a68d88b02245742347c94f1e108c534dda442188015ff80669b3"
name = "google.golang.org/appengine"
@ -230,9 +310,11 @@
"github.com/ararog/timeago",
"github.com/fatih/structs",
"github.com/go-yaml/yaml",
"github.com/gorilla/handlers",
"github.com/gorilla/mux",
"github.com/gorilla/sessions",
"github.com/joho/godotenv",
"github.com/mkevac/debugcharts",
"github.com/pkg/errors",
"github.com/rendon/testcli",
"github.com/stretchr/testify/assert",

View File

@ -1,4 +1,4 @@
VERSION=0.52
VERSION=0.53
BINARY_NAME=statup
GOPATH:=$(GOPATH)
GOCMD=go
@ -26,6 +26,10 @@ docker-build-all: docker-build-base docker-dev docker
docker-publish-all: docker-push-base docker-push-dev docker-push-latest
seed:
rm -f statup.db
cat dev/seed.sql | sqlite3 statup.db
build: compile
$(GOBUILD) $(BUILDVERSION) -o $(BINARY_NAME) -v ./cmd

View File

@ -24,13 +24,13 @@ import (
"github.com/hunterlong/statup/source"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/jinzhu/gorm"
"github.com/joho/godotenv"
"io/ioutil"
"math/rand"
"net/http"
"strings"
"time"
"upper.io/db.v3/sqlite"
)
const (
@ -45,6 +45,8 @@ func CatchCLI(args []string) error {
LoadDotEnvs()
switch args[0] {
case "seed":
handlers.DesktopInit(ipAddress, port)
case "app":
handlers.DesktopInit(ipAddress, port)
case "version":
@ -94,7 +96,7 @@ func CatchCLI(args []string) error {
case "export":
var err error
fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION)
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(dir)
if err != nil {
utils.Log(4, "config.yml file not found")
return err
@ -132,11 +134,11 @@ func CatchCLI(args []string) error {
func RunOnce() {
var err error
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(utils.Directory)
if err != nil {
utils.Log(4, "config.yml file not found")
}
err = core.DbConnection(core.Configs.Connection, false, utils.Directory)
err = core.Configs.Connect(false, utils.Directory)
if err != nil {
utils.Log(4, err)
}
@ -234,19 +236,16 @@ func FakeSeed(plug types.PluginActions) {
fmt.Printf("\n" + BRAKER)
fmt.Println("\nCreating a SQLite database for testing, will be deleted automatically...")
sqlFake := sqlite.ConnectionURL{
Database: "./.plugin_test.db",
}
core.DbSession, err = sqlite.Open(sqlFake)
core.DbSession, err = gorm.Open("sqlite", "./.plugin_test.db")
if err != nil {
utils.Log(3, err)
}
up, _ := source.SqlBox.String("sqlite_up.sql")
requests := strings.Split(up, ";")
for _, request := range requests {
_, err := core.DbSession.Exec(request)
if err != nil {
utils.Log(2, err)
db := core.DbSession.Exec(request)
if db.Error != nil {
utils.Log(2, db.Error)
}
}

View File

@ -55,6 +55,8 @@ func parseFlags() {
func main() {
var err error
parseFlags()
LoadDotEnvs()
source.Assets()
utils.InitLogs()
args := flag.Args()
@ -68,13 +70,8 @@ func main() {
os.Exit(1)
}
}
source.Assets()
LoadDotEnvs()
utils.Log(1, fmt.Sprintf("Starting Statup v%v", VERSION))
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(utils.Directory)
if err != nil {
utils.Log(3, err)
core.SetupMode = true
@ -94,15 +91,18 @@ func LoadDotEnvs() error {
}
func mainProcess() {
dir := utils.Directory
var err error
err = core.DbConnection(core.Configs.Connection, false, utils.Directory)
core.Configs, err = core.LoadConfig(dir)
if err != nil {
utils.Log(4, fmt.Sprintf("could not load config.yml %v", err))
}
err = core.Configs.Connect(false, dir)
if err != nil {
utils.Log(4, fmt.Sprintf("could not connect to database: %v", err))
}
core.RunDatabaseUpgrades()
core.InitApp()
if !core.SetupMode {
LoadPlugins(false)
fmt.Println(handlers.RunHTTPServer(ipAddress, port))
@ -170,7 +170,7 @@ func LoadPlugins(debug bool) {
if debug {
TestPlugin(plugActions)
} else {
plugActions.OnLoad(core.DbSession)
plugActions.OnLoad(*core.DbSession)
core.CoreApp.Plugins = append(core.CoreApp.Plugins, plugActions.GetInfo())
core.CoreApp.AllPlugins = append(core.CoreApp.AllPlugins, plugActions)
}

View File

@ -31,27 +31,30 @@ import (
"os"
"strings"
"testing"
"time"
)
var (
route *mux.Router
testSession *sessions.Session
dir string
route *mux.Router
testSession *sessions.Session
dir string
SERVICE_SINCE, _ = time.Parse(time.RFC3339, "2018-08-30T10:42:08-07:00")
)
func init() {
dir = utils.Directory
os.Remove(dir + "/statup.db")
//os.Remove(gopath+"/cmd/config.yml")
os.RemoveAll(dir + "/cmd/assets")
os.RemoveAll(dir + "/logs")
}
func Clean() {
utils.DeleteFile(dir + "/config.yml")
utils.DeleteFile(dir + "/statup.db")
utils.DeleteDirectory(dir + "/assets")
utils.DeleteDirectory(dir + "/logs")
}
func RunInit(t *testing.T) {
source.Assets()
os.Remove(dir + "/statup.db")
os.Remove(dir + "/cmd/config.yml")
os.Remove(dir + "/cmd/index.html")
Clean()
route = handlers.Router()
LoadDotEnvs()
core.CoreApp = core.NewCore()
@ -60,35 +63,56 @@ func RunInit(t *testing.T) {
func TestRunAll(t *testing.T) {
//t.Parallel()
databases := []string{"sqlite", "postgres", "mysql"}
databases := []string{"postgres", "sqlite", "mysql"}
if os.Getenv("ONLY_DB") != "" {
databases = []string{os.Getenv("ONLY_DB")}
}
for _, dbt := range databases {
t.Run(dbt+" init", func(t *testing.T) {
RunInit(t)
})
t.Run(dbt+" load database config", func(t *testing.T) {
RunMakeDatabaseConfig(t, dbt)
})
t.Run(dbt+" run database migrations", func(t *testing.T) {
RunDatabaseMigrations(t, dbt)
})
t.Run(dbt+" Sample Data", func(t *testing.T) {
RunInsertSampleData(t)
t.Run(dbt+" Save Config", func(t *testing.T) {
RunSaveConfig(t, dbt)
})
t.Run(dbt+" Load Configs", func(t *testing.T) {
RunLoadConfig(t)
t.Log(core.Configs)
})
t.Run(dbt+" Connect to Database", func(t *testing.T) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
})
t.Run(dbt+" Drop Database", func(t *testing.T) {
RunDropDatabase(t)
})
t.Run(dbt+" Connect to Database Again", func(t *testing.T) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
})
t.Run(dbt+" Inserting Database Structure", func(t *testing.T) {
RunCreateSchema(t, dbt)
})
t.Run(dbt+" Inserting Seed Data", func(t *testing.T) {
RunInsertSampleData(t)
})
t.Run(dbt+" Connect to Database Again", func(t *testing.T) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
})
t.Run(dbt+" Run Database Migrations", func(t *testing.T) {
t.SkipNow()
RunDatabaseMigrations(t, dbt)
})
t.Run(dbt+" Select Core", func(t *testing.T) {
RunSelectCoreMYQL(t, dbt)
t.Log(core.CoreApp)
})
t.Run(dbt+" Select Services", func(t *testing.T) {
RunSelectAllMysqlServices(t)
})
t.Run(dbt+" Select Comms", func(t *testing.T) {
t.SkipNow()
RunSelectAllMysqlCommunications(t)
})
t.Run(dbt+" Create Users", func(t *testing.T) {
@ -131,7 +155,7 @@ func TestRunAll(t *testing.T) {
t.Run(dbt+" Create Failing Service", func(t *testing.T) {
RunBadService_Create(t)
})
t.Run(dbt+" Check Service", func(t *testing.T) {
t.Run(dbt+" Check Bad Service", func(t *testing.T) {
RunBadService_Check(t)
})
t.Run(dbt+" Select Hits", func(t *testing.T) {
@ -183,35 +207,24 @@ func TestRunAll(t *testing.T) {
RunSettingsHandler(t)
})
t.Run(dbt+" Cleanup", func(t *testing.T) {
//Cleanup(t)
core.Configs.Close()
core.DbSession = nil
//Clean()
})
//<-done
}
}
func Cleanup(t *testing.T) {
core.DbSession.ClearCache()
err := core.DbSession.Close()
assert.Nil(t, err)
}
func RunMakeDatabaseConfig(t *testing.T, db string) {
func RunSaveConfig(t *testing.T, db string) {
var err error
port := 5432
if db == "mysql" {
port = 3306
}
//Project string `yaml:"-"`
//Description string `yaml:"-"`
//Domain string `yaml:"-"`
//Username string `yaml:"-"`
//Password string `yaml:"-"`
//Email string `yaml:"-"`
//Error error `yaml:"-"`
//Location string `yaml:"location"`
config := &core.DbConfig{&types.DbConfig{
core.Configs = &core.DbConfig{DbConfig: &types.DbConfig{
DbConn: db,
DbHost: os.Getenv("DB_HOST"),
DbUser: os.Getenv("DB_USER"),
@ -227,14 +240,19 @@ func RunMakeDatabaseConfig(t *testing.T, db string) {
Error: nil,
Location: dir,
}}
err := config.Save()
core.Configs, err = core.Configs.Save()
assert.Nil(t, err)
}
_, err = core.LoadConfig()
func RunCreateSchema(t *testing.T, db string) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
assert.Equal(t, db, core.Configs.Connection)
err = core.Configs.CreateDatabase()
assert.Nil(t, err)
}
err = core.DbConnection(core.Configs.Connection, false, dir)
func RunConnectDatabase(t *testing.T) {
err := core.Configs.Connect(false, dir)
assert.Nil(t, err)
}
@ -244,22 +262,32 @@ func RunDatabaseMigrations(t *testing.T, db string) {
}
func RunInsertSampleData(t *testing.T) {
err := core.LoadSampleData()
_, _, err := core.Configs.SeedDatabase()
assert.Nil(t, err)
}
func RunLoadConfig(t *testing.T) {
var err error
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(dir)
t.Log(core.Configs)
assert.Nil(t, err)
assert.NotNil(t, core.Configs)
}
func RunDropDatabase(t *testing.T) {
err := core.Configs.DropDatabase()
assert.Nil(t, err)
}
func RunSelectCoreMYQL(t *testing.T, db string) {
var err error
core.CoreApp, err = core.SelectCore()
if err != nil {
t.FailNow()
}
assert.Nil(t, err)
assert.Equal(t, "Testing "+db, core.CoreApp.Name)
t.Log("core: ", core.CoreApp.Core)
assert.Equal(t, "Awesome Status", core.CoreApp.Name)
assert.Equal(t, db, core.CoreApp.DbConnection)
assert.NotEmpty(t, core.CoreApp.ApiKey)
assert.NotEmpty(t, core.CoreApp.ApiSecret)
@ -270,12 +298,12 @@ func RunSelectAllMysqlServices(t *testing.T) {
var err error
services, err := core.CoreApp.SelectAllServices()
assert.Nil(t, err)
assert.Equal(t, 5, len(services))
assert.Equal(t, 18, len(services))
}
func RunSelectAllMysqlCommunications(t *testing.T) {
var err error
notifiers.Collections = core.DbSession.Collection("communication")
notifiers.Collections = core.DbSession.Table("communication").Model(&notifiers.Notification{})
comms := notifiers.Load()
assert.Nil(t, err)
assert.Equal(t, 3, len(comms))
@ -284,19 +312,19 @@ func RunSelectAllMysqlCommunications(t *testing.T) {
func RunUser_SelectAll(t *testing.T) {
users, err := core.SelectAllUsers()
assert.Nil(t, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, 3, len(users))
}
func RunUser_Create(t *testing.T) {
user := core.ReturnUser(&types.User{
Username: "admin",
Password: "admin",
Email: "info@testuser.com",
Username: "hunterlong",
Password: "password123",
Email: "info@gmail.com",
Admin: true,
})
id, err := user.Create()
assert.Nil(t, err)
assert.Equal(t, int64(1), id)
assert.Equal(t, int64(2), id)
user2 := core.ReturnUser(&types.User{
Username: "superadmin",
Password: "admin",
@ -305,7 +333,7 @@ func RunUser_Create(t *testing.T) {
})
id, err = user2.Create()
assert.Nil(t, err)
assert.Equal(t, int64(2), id)
assert.Equal(t, int64(3), id)
}
func RunUser_Update(t *testing.T) {
@ -342,7 +370,10 @@ func RunSelectAllServices(t *testing.T) {
var err error
services, err := core.CoreApp.SelectAllServices()
assert.Nil(t, err)
assert.Equal(t, 5, len(services))
assert.Equal(t, 18, len(services))
for _, s := range services {
assert.NotEmpty(t, s.CreatedAt)
}
}
func RunOneService_Check(t *testing.T) {
@ -365,8 +396,7 @@ func RunService_Create(t *testing.T) {
})
id, err := service.Create()
assert.Nil(t, err)
assert.Equal(t, int64(6), id)
t.Log(service)
assert.Equal(t, int64(19), id)
}
func RunService_ToJSON(t *testing.T) {
@ -379,15 +409,20 @@ func RunService_ToJSON(t *testing.T) {
func RunService_AvgTime(t *testing.T) {
service := core.SelectService(1)
assert.NotNil(t, service)
avg := service.AvgUptime()
avg := service.AvgUptime24()
assert.Equal(t, "100", avg)
}
func RunService_Online24(t *testing.T) {
service := core.SelectService(1)
assert.NotNil(t, service)
online := service.Online24()
assert.Equal(t, float32(100), online)
online := service.OnlineSince(SERVICE_SINCE)
assert.Equal(t, float32(80), online)
service = core.SelectService(18)
assert.NotNil(t, service)
online = service.OnlineSince(SERVICE_SINCE)
assert.Equal(t, float32(0), online)
}
func RunService_GraphData(t *testing.T) {
@ -413,13 +448,13 @@ func RunBadService_Create(t *testing.T) {
})
id, err := service.Create()
assert.Nil(t, err)
assert.Equal(t, int64(7), id)
assert.Equal(t, int64(20), id)
}
func RunBadService_Check(t *testing.T) {
service := core.SelectService(7)
service := core.SelectService(18)
assert.NotNil(t, service)
assert.Equal(t, "Bad Service", service.Name)
assert.Equal(t, "Failing URL", service.Name)
for i := 0; i <= 10; i++ {
service.Check(true)
}
@ -431,9 +466,7 @@ func RunDeleteService(t *testing.T) {
assert.NotNil(t, service)
assert.Equal(t, "JSON API Tester", service.Name)
assert.True(t, service.IsRunning())
t.Log(service.Running)
err := service.Delete()
t.Log(service.Running)
assert.False(t, service.IsRunning())
assert.Nil(t, err)
}
@ -441,13 +474,10 @@ func RunDeleteService(t *testing.T) {
func RunCreateService_Hits(t *testing.T) {
services := core.CoreApp.Services()
assert.NotNil(t, services)
assert.Equal(t, 6, len(services))
for i := 0; i <= 15; i++ {
for _, s := range services {
var service *core.Service
service = s.Check(true)
assert.NotNil(t, service)
}
assert.Equal(t, 19, len(services))
for _, s := range services {
service := s.Check(true)
assert.NotNil(t, service)
}
}
@ -460,9 +490,9 @@ func RunService_Hits(t *testing.T) {
}
func RunService_Failures(t *testing.T) {
service := core.SelectService(7)
service := core.SelectService(18)
assert.NotNil(t, service)
assert.Equal(t, "Bad Service", service.Name)
assert.Equal(t, "Failing URL", service.Name)
assert.NotEmpty(t, service.Failures)
}
@ -479,7 +509,7 @@ func RunIndexHandler(t *testing.T) {
assert.Nil(t, err)
rr := httptest.NewRecorder()
route.ServeHTTP(rr, req)
assert.True(t, strings.Contains(rr.Body.String(), "This is a test of Statup.io!"))
assert.True(t, strings.Contains(rr.Body.String(), "Awesome"))
assert.True(t, strings.Contains(rr.Body.String(), "footer"))
}
@ -499,7 +529,7 @@ func RunPrometheusHandler(t *testing.T) {
rr := httptest.NewRecorder()
route.ServeHTTP(rr, req)
t.Log(rr.Body.String())
assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 6"))
assert.True(t, strings.Contains(rr.Body.String(), "statup_total_services 19"))
assert.True(t, handlers.IsAuthenticated(req))
}
@ -515,7 +545,7 @@ func RunFailingPrometheusHandler(t *testing.T) {
func RunLoginHandler(t *testing.T) {
form := url.Values{}
form.Add("username", "admin")
form.Add("password", "admin")
form.Add("password", "password123")
req, err := http.NewRequest("POST", "/dashboard", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
assert.Nil(t, err)

View File

@ -210,7 +210,9 @@ func RecordSuccess(s *Service) {
s.Online = true
s.LastOnline = time.Now()
data := &types.Hit{
Latency: s.Latency,
Service: s.Id,
Latency: s.Latency,
CreatedAt: time.Now(),
}
utils.Log(1, fmt.Sprintf("Service %v Successful: %0.2f ms", s.Name, data.Latency*1000))
s.CreateHit(data)

View File

@ -48,26 +48,25 @@ func FindCheckin(api string) *types.Checkin {
func (s *Service) AllCheckins() []*types.Checkin {
var checkins []*types.Checkin
col := DbSession.Collection("checkins").Find("service", s.Id).OrderBy("-id")
col.All(&checkins)
col := checkinDB().Where("service = ?", s.Id).Order("-id")
col.Scan(&checkins)
s.Checkins = checkins
return checkins
}
func (u *Checkin) Create() (int64, error) {
u.CreatedAt = time.Now()
uuid, err := DbSession.Collection("checkins").Insert(u)
if uuid == nil {
utils.Log(2, err)
return 0, err
row := checkinDB().Create(&u)
if row.Error == nil {
utils.Log(2, row.Error)
return 0, row.Error
}
fmt.Println("new checkin: ", uuid)
return uuid.(int64), err
return u.Id, row.Error
}
func SelectCheckinApi(api string) *Checkin {
var checkin *Checkin
DbSession.Collection("checkins").Find("api", api).One(&checkin)
checkinDB().Where("api = ?", api).Find(&checkin)
return checkin
}

View File

@ -23,29 +23,28 @@ import (
"github.com/hunterlong/statup/utils"
"io/ioutil"
"os"
"time"
)
func LoadConfig() (*types.Config, error) {
func LoadConfig(directory string) (*DbConfig, error) {
var configs *types.DbConfig
if os.Getenv("DB_CONN") != "" {
utils.Log(1, "DB_CONN environment variable was found, waiting for database...")
return LoadUsingEnv()
}
Configs = new(types.Config)
file, err := ioutil.ReadFile(utils.Directory + "/config.yml")
file, err := ioutil.ReadFile(directory + "/config.yml")
if err != nil {
return nil, errors.New("config.yml file not found - starting in setup mode")
return nil, errors.New("config.yml file not found at " + directory + "/config.yml - starting in setup mode")
}
err = yaml.Unmarshal(file, &Configs)
err = yaml.Unmarshal(file, &configs)
if err != nil {
return nil, err
}
CoreApp.DbConnection = Configs.Connection
Configs = &DbConfig{configs}
return Configs, err
}
func LoadUsingEnv() (*types.Config, error) {
Configs = new(types.Config)
func LoadUsingEnv() (*DbConfig, error) {
Configs = new(DbConfig)
if os.Getenv("DB_CONN") == "" {
return nil, errors.New("Missing DB_CONN environment variable")
}
@ -61,12 +60,12 @@ func LoadUsingEnv() (*types.Config, error) {
if os.Getenv("DB_DATABASE") == "" {
return nil, errors.New("Missing DB_DATABASE environment variable")
}
Configs.Connection = os.Getenv("DB_CONN")
Configs.Host = os.Getenv("DB_HOST")
Configs.Port = os.Getenv("DB_PORT")
Configs.User = os.Getenv("DB_USER")
Configs.DbConn = os.Getenv("DB_CONN")
Configs.DbHost = os.Getenv("DB_HOST")
Configs.DbPort = int(utils.StringInt(os.Getenv("DB_PORT")))
Configs.DbUser = os.Getenv("DB_USER")
Configs.Password = os.Getenv("DB_PASS")
Configs.Database = os.Getenv("DB_DATABASE")
Configs.DbData = os.Getenv("DB_DATABASE")
CoreApp.DbConnection = os.Getenv("DB_CONN")
CoreApp.Name = os.Getenv("NAME")
CoreApp.Domain = os.Getenv("DOMAIN")
@ -89,32 +88,19 @@ func LoadUsingEnv() (*types.Config, error) {
Email: "info@localhost.com",
}}
err := DbConnection(dbConfig.DbConn, true, utils.Directory)
err := dbConfig.Connect(true, utils.Directory)
if err != nil {
utils.Log(4, err)
return nil, err
}
exists, err := DbSession.Collection("core").Find().Exists()
exists := DbSession.HasTable("core")
if !exists {
utils.Log(1, fmt.Sprintf("Core database does not exist, creating now!"))
DropDatabase()
CreateDatabase()
dbConfig.DropDatabase()
dbConfig.CreateDatabase()
CoreApp = &Core{Core: &types.Core{
Name: dbConfig.Project,
Description: dbConfig.Description,
Config: "config.yml",
ApiKey: utils.NewSHA1Hash(9),
ApiSecret: utils.NewSHA1Hash(16),
Domain: dbConfig.Domain,
MigrationId: time.Now().Unix(),
}}
CoreApp.DbConnection = dbConfig.DbConn
err := InsertCore(CoreApp)
CoreApp, err = dbConfig.InsertCore()
if err != nil {
utils.Log(3, err)
}

View File

@ -22,7 +22,6 @@ import (
"github.com/hunterlong/statup/utils"
"github.com/pkg/errors"
"os"
"sort"
"time"
)
@ -34,7 +33,7 @@ type Core struct {
}
var (
Configs *types.Config
Configs *DbConfig
CoreApp *Core
SetupMode bool
VERSION string
@ -51,12 +50,6 @@ func NewCore() *Core {
return CoreApp
}
func InsertCore(c *Core) error {
col := DbSession.Collection("core")
_, err := col.Insert(c.Core)
return err
}
func (c *Core) ToCore() *types.Core {
return c.Core
}
@ -72,19 +65,18 @@ func InitApp() {
func InsertNotifierDB() error {
if DbSession == nil {
err := DbConnection(CoreApp.DbConnection, false, utils.Directory)
err := Configs.Connect(false, utils.Directory)
if err != nil {
return errors.New("database connection has not been created")
}
}
notifiers.Collections = DbSession.Collection("communication")
notifiers.Collections = commDB()
return nil
}
func UpdateCore(c *Core) (*Core, error) {
res := DbSession.Collection("core").Find().Limit(1)
err := res.Update(c.Core)
return c, err
db := coreDB().Update(c)
return c, db.Error
}
func (c Core) UsingAssets() bool {
@ -122,36 +114,33 @@ func (c Core) AllOnline() bool {
}
func SelectLastMigration() (int64, error) {
var c *types.Core
if DbSession == nil {
return 0, errors.New("Database connection has not been created yet")
}
err := DbSession.Collection("core").Find().One(&c)
if err != nil {
return 0, err
}
return c.MigrationId, err
row := coreDB().Take(&CoreApp)
return CoreApp.MigrationId, row.Error
}
func SelectCore() (*Core, error) {
var c *types.Core
exists := DbSession.Collection("core").Exists()
if DbSession == nil {
return nil, errors.New("database has not been initiated yet.")
}
exists := DbSession.HasTable("core")
if !exists {
return nil, errors.New("core database has not been setup yet.")
}
err := DbSession.Collection("core").Find().One(&c)
if err != nil {
return nil, err
db := coreDB().Take(&CoreApp)
if db.Error != nil {
return nil, db.Error
}
CoreApp.Core = c
CoreApp.DbConnection = Configs.Connection
CoreApp.DbConnection = Configs.DbConn
CoreApp.Version = VERSION
CoreApp.SelectAllServices()
if os.Getenv("USE_CDN") == "true" {
CoreApp.UseCdn = true
}
//store = sessions.NewCookieStore([]byte(core.ApiSecret))
return CoreApp, err
return CoreApp, db.Error
}
type ServiceOrder []*types.Service
@ -163,7 +152,7 @@ func (c ServiceOrder) Less(i, j int) bool { return c[i].Order < c[j].Order }
func (c *Core) Services() []*Service {
var services []*Service
servs := CoreApp.GetServices()
sort.Sort(ServiceOrder(servs))
//sort.Sort(ServiceOrder(servs))
for _, ser := range servs {
services = append(services, ReturnService(ser))
}

View File

@ -24,9 +24,11 @@ import (
)
var (
testCore *Core
testConfig *DbConfig
dir string
dir string
)
const (
SERVICE_SINCE = "2018-08-30T10:42:08-07:00" // "2006-01-02T15:04:05Z07:00"
)
func init() {
@ -36,51 +38,65 @@ func init() {
}
func TestNewCore(t *testing.T) {
testCore = NewCore()
assert.NotNil(t, testCore)
testCore.Name = "Tester"
utils.DeleteFile(dir + "/config.yml")
utils.DeleteFile(dir + "/statup.db")
CoreApp = NewCore()
assert.NotNil(t, CoreApp)
CoreApp.Name = "Tester"
}
func TestDbConfig_Save(t *testing.T) {
testConfig = &DbConfig{&types.DbConfig{
var err error
Configs = &DbConfig{&types.DbConfig{
DbConn: "sqlite",
Project: "Tester",
Location: dir,
}}
err := testConfig.Save()
Configs, err = Configs.Save()
assert.Nil(t, err)
assert.Equal(t, "sqlite", Configs.DbConn)
assert.NotEmpty(t, Configs.ApiKey)
assert.NotEmpty(t, Configs.ApiSecret)
}
func TestLoadDbConfig(t *testing.T) {
Configs, err := LoadConfig(dir)
assert.Nil(t, err)
assert.Equal(t, "sqlite", Configs.DbConn)
}
func TestDbConnection(t *testing.T) {
err := DbConnection(testConfig.DbConn, false, dir)
err := Configs.Connect(false, dir)
assert.Nil(t, err)
}
func TestCreateDatabase(t *testing.T) {
err := CreateDatabase()
func TestSeedSchemaDatabase(t *testing.T) {
_, _, err := Configs.SeedSchema()
assert.Nil(t, err)
}
func TestInsertCore(t *testing.T) {
err := InsertCore(testCore)
func TestSeedDatabase(t *testing.T) {
_, _, err := Configs.SeedDatabase()
assert.Nil(t, err)
}
func TestReLoadDbConfig(t *testing.T) {
err := Configs.Connect(false, dir)
assert.Nil(t, err)
assert.Equal(t, "sqlite", Configs.DbConn)
}
func TestSelectCore(t *testing.T) {
core, err := SelectCore()
assert.Nil(t, err)
assert.Equal(t, "Tester", core.Name)
}
func TestSampleData(t *testing.T) {
err := LoadSampleData()
assert.Nil(t, err)
assert.Equal(t, "Awesome Status", core.Name)
}
func TestSelectLastMigration(t *testing.T) {
id, err := SelectLastMigration()
assert.Nil(t, err)
assert.NotZero(t, id)
//assert.NotZero(t, id)
t.Log("Last migration id: ", id)
}
func TestInsertNotifierDB(t *testing.T) {

View File

@ -17,94 +17,176 @@ package core
import (
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/go-yaml/yaml"
"github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/source"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite"
_ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3"
"os"
"strings"
"time"
"upper.io/db.v3"
"upper.io/db.v3/lib/sqlbuilder"
"upper.io/db.v3/mysql"
"upper.io/db.v3/postgresql"
"upper.io/db.v3/sqlite"
)
var (
sqliteSettings sqlite.ConnectionURL
postgresSettings postgresql.ConnectionURL
mysqlSettings mysql.ConnectionURL
DbSession sqlbuilder.Database
DbSession *gorm.DB
currentMigration int64
)
func failuresDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Model(&types.Failure{}).Debug()
}
return DbSession.Model(&types.Failure{})
}
func (s *Service) allHits() *gorm.DB {
var hits []*Hit
return servicesDB().Find(s).Related(&hits)
}
func hitsDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Model(&types.Hit{}).Debug()
}
return DbSession.Model(&types.Hit{})
}
func servicesDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Model(&types.Service{}).Debug()
}
return DbSession.Model(&types.Service{})
}
func coreDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Table("core").Debug()
}
return DbSession.Table("core")
}
func usersDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Model(&types.User{}).Debug()
}
return DbSession.Model(&types.User{})
}
func commDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Table("communication").Model(&notifiers.Notification{}).Debug()
}
return DbSession.Table("communication").Model(&notifiers.Notification{})
}
func checkinDB() *gorm.DB {
if os.Getenv("GO_ENV") == "TEST" {
return DbSession.Model(&types.Checkin{}).Debug()
}
return DbSession.Model(&types.Checkin{})
}
type DbConfig struct {
*types.DbConfig
}
func DbConnection(dbType string, retry bool, location string) error {
func (db *DbConfig) Close() error {
return DbSession.Close()
}
func (db *DbConfig) InsertCore() (*Core, error) {
CoreApp = &Core{Core: &types.Core{
Name: db.Project,
Description: db.Description,
Config: "config.yml",
ApiKey: utils.NewSHA1Hash(9),
ApiSecret: utils.NewSHA1Hash(16),
Domain: db.Domain,
MigrationId: time.Now().Unix(),
}}
CoreApp.DbConnection = db.DbConn
query := coreDB().Create(&CoreApp)
return CoreApp, query.Error
}
func (db *DbConfig) Connect(retry bool, location string) error {
var err error
if dbType == "sqlite" {
sqliteSettings = sqlite.ConnectionURL{
Database: location + "/statup.db",
}
DbSession, err = sqlite.Open(sqliteSettings)
if DbSession != nil {
DbSession = nil
}
switch Configs.DbConn {
case "sqlite":
DbSession, err = gorm.Open("sqlite3", utils.Directory+"/statup.db")
if err != nil {
return err
}
} else if dbType == "mysql" {
if Configs.Port == "" {
Configs.Port = "3306"
case "mysql":
if Configs.DbPort == 0 {
Configs.DbPort = 3306
}
host := fmt.Sprintf("%v:%v", Configs.Host, Configs.Port)
mysqlSettings = mysql.ConnectionURL{
Database: Configs.Database,
Host: host,
User: Configs.User,
Password: Configs.Password,
Options: map[string]string{"parseTime": "true", "charset": "utf8"},
}
DbSession, err = mysql.Open(mysqlSettings)
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)
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 waitForDb(dbType)
return db.waitForDb()
} else {
return err
}
}
} else {
if Configs.Port == "" {
Configs.Port = "5432"
case "postgres":
if Configs.DbPort == 0 {
Configs.DbPort = 5432
}
host := fmt.Sprintf("%v:%v", Configs.Host, Configs.Port)
postgresSettings = postgresql.ConnectionURL{
Database: Configs.Database,
Host: host,
User: Configs.User,
Password: Configs.Password,
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)
if err != nil {
if retry {
utils.Log(1, fmt.Sprintf("Database connection to '%v' is not available, trying again in 5 seconds...", Configs.DbHost))
return db.waitForDb()
} else {
fmt.Println("ERROR:", err)
return err
}
}
DbSession, err = postgresql.Open(postgresSettings)
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 waitForDb(dbType)
return db.waitForDb()
} else {
return err
}
}
}
err = DbSession.Ping()
err = DbSession.DB().Ping()
if err == nil {
utils.Log(1, fmt.Sprintf("Database connection to '%v' was successful.", DbSession.Name()))
utils.Log(1, fmt.Sprintf("Database connection to '%v' was successful.", Configs.DbData))
}
return err
}
func waitForDb(dbType string) error {
func (db *DbConfig) waitForDb() error {
time.Sleep(5 * time.Second)
return DbConnection(dbType, true, utils.Directory)
return db.Connect(true, utils.Directory)
}
func DatabaseMaintence() {
@ -118,9 +200,10 @@ func DatabaseMaintence() {
func DeleteAllSince(table string, date time.Time) {
sql := fmt.Sprintf("DELETE FROM %v WHERE created_at < '%v';", table, date.Format("2006-01-02"))
_, err := DbSession.Exec(db.Raw(sql))
if err != nil {
utils.Log(2, err)
db := DbSession.Raw(sql)
defer db.Close()
if db.Error != nil {
utils.Log(2, db.Error)
}
}
@ -141,57 +224,44 @@ func (c *DbConfig) Update() error {
return err
}
func (c *DbConfig) Save() error {
func (c *DbConfig) Save() (*DbConfig, error) {
var err error
config, err := os.Create(utils.Directory + "/config.yml")
if err != nil {
utils.Log(4, err)
return err
return nil, err
}
c.ApiKey = utils.NewSHA1Hash(16)
c.ApiSecret = utils.NewSHA1Hash(16)
data, err := yaml.Marshal(c.DbConfig)
if err != nil {
utils.Log(3, err)
return err
return nil, err
}
config.WriteString(string(data))
config.Close()
Configs, err = LoadConfig()
if err != nil {
utils.Log(3, err)
return err
}
err = DbConnection(Configs.Connection, false, c.Location)
if err != nil {
utils.Log(4, err)
return err
}
DropDatabase()
CreateDatabase()
defer config.Close()
return c, err
}
func (c *DbConfig) CreateCore() *Core {
newCore := &types.Core{
Name: c.Project,
Description: c.Description,
Config: "config.yml",
ApiKey: utils.NewSHA1Hash(9),
ApiSecret: utils.NewSHA1Hash(16),
ApiKey: c.ApiKey,
ApiSecret: c.ApiSecret,
Domain: c.Domain,
MigrationId: time.Now().Unix(),
}
col := DbSession.Collection("core")
_, err = col.Insert(newCore)
if err == nil {
db := coreDB().Create(&newCore)
if db.Error == nil {
CoreApp = &Core{Core: newCore}
}
CoreApp, err = SelectCore()
CoreApp, err := SelectCore()
if err != nil {
utils.Log(4, err)
}
CoreApp.DbConnection = c.DbConn
c.ApiKey = CoreApp.ApiKey
c.ApiSecret = CoreApp.ApiSecret
return err
return CoreApp
}
func versionHigher(migrate int64) bool {
@ -239,10 +309,10 @@ func RunDatabaseUpgrades() error {
continue
}
utils.Log(1, fmt.Sprintf("Running Query: %v", m))
_, err := DbSession.Exec(db.Raw(m + ";"))
db := DbSession.Raw(m)
ran++
if err != nil {
utils.Log(2, err)
if db.Error != nil {
utils.Log(2, db.Error)
continue
}
}
@ -252,7 +322,7 @@ func RunDatabaseUpgrades() error {
utils.Log(1, fmt.Sprintf("Database Upgraded %v queries ran, current #%v", ran, currentMigration))
CoreApp, err = SelectCore()
if err != nil {
panic(err)
return err
}
CoreApp.MigrationId = currentMigration
UpdateCore(CoreApp)
@ -260,43 +330,77 @@ func RunDatabaseUpgrades() error {
return err
}
func DropDatabase() error {
utils.Log(1, "Dropping Database Tables...")
down, err := source.SqlBox.String("down.sql")
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 err
return out, outErr, err
}
requests := strings.Split(down, ";")
for _, request := range requests {
_, err := DbSession.Exec(request)
if err != nil {
utils.Log(2, err)
}
}
return err
return out, outErr, err
}
func CreateDatabase() error {
func (db *DbConfig) SeedDatabase() (string, string, error) {
utils.Log(1, "Seeding Database with Dummy Data...")
dir := utils.Directory
var cmd string
switch db.DbConn {
case "sqlite":
cmd = fmt.Sprintf("cat %v/dev/sqlite_seed.sql | sqlite3 %v/statup.db", dir, dir)
case "mysql":
cmd = fmt.Sprintf("mysql -h %v -P %v -u %v --password=%v %v < %v/dev/mysql_seed.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/dev/postgres_seed.sql", db.DbPass, db.DbUser, db.DbHost, db.DbData, dir)
}
out, outErr, err := utils.Command(cmd)
return out, outErr, err
}
func (db *DbConfig) DropDatabase() error {
utils.Log(1, "Dropping Database Tables...")
err := DbSession.DropTableIfExists("checkins")
err = DbSession.DropTableIfExists("communication")
err = DbSession.DropTableIfExists("core")
err = DbSession.DropTableIfExists("failures")
err = DbSession.DropTableIfExists("hits")
err = DbSession.DropTableIfExists("services")
err = DbSession.DropTableIfExists("users")
return err.Error
}
func (db *DbConfig) CreateDatabase() error {
utils.Log(1, "Creating Database Tables...")
sql := "postgres_up.sql"
if CoreApp.DbConnection == "mysql" {
sql = "mysql_up.sql"
} else if CoreApp.DbConnection == "sqlite" {
sql = "sqlite_up.sql"
}
up, err := source.SqlBox.String(sql)
requests := strings.Split(up, ";")
for _, request := range requests {
_, err := DbSession.Exec(request)
if err != nil {
utils.Log(2, err)
}
}
//secret := NewSHA1Hash()
//db.QueryRow("INSERT INTO core (secret, version) VALUES ($1, $2);", secret, VERSION).Scan()
utils.Log(1, "Database Created")
//SampleData()
return err
err := DbSession.CreateTable(&types.Checkin{})
err = DbSession.Table("communication").CreateTable(&notifiers.Notification{})
err = DbSession.Table("core").CreateTable(&types.Core{})
err = DbSession.CreateTable(&types.Failure{})
err = DbSession.CreateTable(&types.Hit{})
err = DbSession.CreateTable(&types.Service{})
err = DbSession.CreateTable(&types.User{})
utils.Log(1, "Statup Database Created")
return err.Error
}
func (db *DbConfig) MigrateDatabase() error {
utils.Log(1, "Migrating Database Tables...")
err := DbSession.AutoMigrate(&types.Checkin{})
err = DbSession.Table("communication").AutoMigrate(&notifiers.Notification{})
err = DbSession.Table("core").AutoMigrate(&types.Core{})
err = DbSession.AutoMigrate(&types.Failure{})
err = DbSession.AutoMigrate(&types.Hit{})
err = DbSession.AutoMigrate(&types.Service{})
err = DbSession.AutoMigrate(&types.User{})
utils.Log(1, "Statup Database Migrated")
return err.Error
}
func (c *DbConfig) Clean() *DbConfig {

View File

@ -19,12 +19,12 @@ import (
"github.com/fatih/structs"
"github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/types"
"upper.io/db.v3/lib/sqlbuilder"
"github.com/jinzhu/gorm"
)
func OnLoad(db sqlbuilder.Database) {
func OnLoad(db *gorm.DB) {
for _, p := range CoreApp.AllPlugins {
p.OnLoad(db)
p.OnLoad(*db)
}
}

View File

@ -25,7 +25,11 @@ import (
)
func injectDatabase() {
DbConnection(Configs.Connection, false, utils.Directory)
Configs.Connect(false, utils.Directory)
}
func GenerateSeed() {
}
func ExportIndexHTML() string {

View File

@ -32,23 +32,19 @@ func (s *Service) CreateFailure(f *types.Failure) (int64, error) {
f.CreatedAt = time.Now()
f.Service = s.Id
s.Failures = append(s.Failures, f)
col := DbSession.Collection("failures")
uuid, err := col.Insert(f)
if err != nil {
utils.Log(3, err)
return 0, err
row := failuresDB().Create(f)
if row.Error != nil {
utils.Log(3, row.Error)
return 0, row.Error
}
if uuid == nil {
return 0, err
}
return uuid.(int64), err
return f.Id, row.Error
}
func (s *Service) AllFailures() []*types.Failure {
var fails []*types.Failure
col := DbSession.Collection("failures").Find("service", s.Id).OrderBy("-id")
err := col.All(&fails)
if err != nil {
col := failuresDB().Where("service = ?", s.Id).Order("id desc")
err := col.Find(&fails)
if err.Error != nil {
utils.Log(3, fmt.Sprintf("Issue getting failures for service %v, %v", s.Name, err))
return nil
}
@ -56,8 +52,8 @@ func (s *Service) AllFailures() []*types.Failure {
}
func (u *Service) DeleteFailures() {
_, err := DbSession.Exec(`DELETE FROM failures WHERE service = ?`, u.Id)
if err != nil {
err := DbSession.Exec(`DELETE FROM failures WHERE service = ?`, u.Id)
if err.Error != nil {
utils.Log(3, fmt.Sprintf("failed to delete all failures: %v", err))
}
u.Failures = nil
@ -65,8 +61,8 @@ func (u *Service) DeleteFailures() {
func (s *Service) LimitedFailures() []*Failure {
var failArr []*Failure
col := DbSession.Collection("failures").Find("service", s.Id).OrderBy("-id").Limit(10)
col.All(&failArr)
col := failuresDB().Where("service = ?", s.Id).Order("id desc").Limit(10)
col.Find(&failArr)
return failArr
}
@ -83,30 +79,37 @@ func (f *Failure) Ago() string {
}
func (f *Failure) Delete() error {
col := DbSession.Collection("failures").Find("id", f.Id)
return col.Delete()
db := failuresDB().Delete(f)
return db.Error
}
func CountFailures() uint64 {
col := DbSession.Collection("failures").Find()
amount, err := col.Count()
if err != nil {
utils.Log(2, err)
var count uint64
err := failuresDB().Count(&count)
if err.Error != nil {
utils.Log(2, err.Error)
return 0
}
return amount
return count
}
func (s *Service) TotalFailures24() (uint64, error) {
ago := time.Now().Add(-24 * time.Hour)
return s.TotalFailuresSince(ago)
}
func (s *Service) TotalFailures() (uint64, error) {
col := DbSession.Collection("failures").Find("service", s.Id)
amount, err := col.Count()
return amount, err
var count uint64
rows := failuresDB().Where("service = ?", s.Id)
err := rows.Count(count)
return count, err.Error
}
func (s *Service) TotalFailures24Hours() (uint64, error) {
col := DbSession.Collection("failures").Find("service", s.Id)
amount, err := col.Count()
return amount, err
func (s *Service) TotalFailuresSince(ago time.Time) (uint64, error) {
var count uint64
rows := failuresDB().Where("service = ? AND created_at > ?", s.Id, ago.Format("2006-01-02 15:04:05"))
err := rows.Count(&count)
return count, err.Error
}
func (f *Failure) ParseError() string {

View File

@ -19,40 +19,33 @@ import (
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"time"
"upper.io/db.v3"
)
type Hit struct {
*types.Hit
}
func hitCol() db.Collection {
return DbSession.Collection("hits")
}
func (s *Service) CreateHit(h *types.Hit) (int64, error) {
h.CreatedAt = time.Now()
h.Service = s.Id
uuid, err := hitCol().Insert(h)
if uuid == nil {
utils.Log(2, err)
return 0, err
db := hitsDB().Create(&h)
if db.Error != nil {
utils.Log(2, db.Error)
return 0, db.Error
}
return uuid.(int64), err
return h.Id, db.Error
}
func (s *Service) Hits() ([]*Hit, error) {
var hits []*Hit
col := hitCol().Find("service", s.Id).OrderBy("-id")
err := col.All(&hits)
return hits, err
col := hitsDB().Where("service = ?", s.Id).Order("id desc")
err := col.Find(&hits)
return hits, err.Error
}
func (s *Service) LimitedHits() ([]*Hit, error) {
var hits []*Hit
col := hitCol().Find("service", s.Id).OrderBy("-id").Limit(1024)
err := col.All(&hits)
return reverseHits(hits), err
col := hitsDB().Where("service = ?", s.Id).Order("id desc").Limit(1024)
err := col.Find(&hits)
return reverseHits(hits), err.Error
}
func reverseHits(input []*Hit) []*Hit {
@ -64,15 +57,27 @@ func reverseHits(input []*Hit) []*Hit {
func (s *Service) SelectHitsGroupBy(group string) ([]*Hit, error) {
var hits []*Hit
col := hitCol().Find("service", s.Id)
err := col.All(&hits)
return hits, err
col := hitsDB().Where("service = ?", s.Id)
err := col.Find(&hits)
return hits, err.Error
}
func (s *Service) hits() {
}
func (s *Service) TotalHits() (uint64, error) {
col := hitCol().Find("service", s.Id)
amount, err := col.Count()
return amount, err
var count uint64
col := hitsDB().Where("service = ?", s.Id)
err := col.Count(&count)
return count, err.Error
}
func (s *Service) TotalHitsSince(ago time.Time) (uint64, error) {
var count uint64
rows := hitsDB().Where("service = ? AND created_at > ?", s.Id, ago.Format("2006-01-02 15:04:05"))
err := rows.Count(&count)
return count, err.Error
}
func (s *Service) Sum() (float64, error) {

View File

@ -22,7 +22,6 @@ import (
"github.com/hunterlong/statup/utils"
"strconv"
"time"
"upper.io/db.v3"
)
type Service struct {
@ -30,16 +29,12 @@ type Service struct {
}
func ReturnService(s *types.Service) *Service {
return &Service{Service: s}
}
func serviceCol() db.Collection {
return DbSession.Collection("services")
return &Service{s}
}
func SelectService(id int64) *Service {
for _, s := range CoreApp.Services() {
if s.Id == id {
if s.Service.Id == id {
return s
}
}
@ -49,11 +44,10 @@ func SelectService(id int64) *Service {
func (c *Core) SelectAllServices() ([]*types.Service, error) {
var services []*types.Service
var servs []*types.Service
col := serviceCol().Find().OrderBy("order_id")
err := col.All(&services)
if err != nil {
utils.Log(3, fmt.Sprintf("service error: %v", err))
return nil, err
db := servicesDB().Find(&services)
if db.Error != nil {
utils.Log(3, fmt.Sprintf("service error: %v", db.Error))
return nil, db.Error
}
for _, ser := range services {
single := ReturnService(ser)
@ -63,7 +57,7 @@ func (c *Core) SelectAllServices() ([]*types.Service, error) {
servs = append(servs, single.Service)
}
CoreApp.SetServices(servs)
return services, err
return services, db.Error
}
func (s *Service) ToJSON() string {
@ -84,12 +78,17 @@ func (s *Service) AvgTime() float64 {
}
func (s *Service) Online24() float32 {
total, _ := s.TotalHits()
failed, _ := s.TotalFailures24Hours()
ago := time.Now().Add(-24 * time.Hour)
return s.OnlineSince(ago)
}
func (s *Service) OnlineSince(ago time.Time) float32 {
failed, _ := s.TotalFailuresSince(ago)
if failed == 0 {
s.Online24Hours = 100.00
return s.Online24Hours
}
total, _ := s.TotalHitsSince(ago)
if total == 0 {
s.Online24Hours = 0
return s.Online24Hours
@ -150,16 +149,17 @@ func (s *Service) GraphData() string {
var d []*DateScan
since := time.Now().Add(time.Hour*-24 + time.Minute*0 + time.Second*0)
sql := GroupDataBy("hits", s.Id, since, "minute")
dated, err := DbSession.Query(db.Raw(sql))
rows, err := DbSession.Raw(sql).Rows()
defer rows.Close()
if err != nil {
utils.Log(2, err)
return ""
}
for dated.Next() {
for rows.Next() {
gd := new(DateScan)
var tt string
var ff float64
err := dated.Scan(&tt, &ff)
err := rows.Scan(&tt, &ff)
if err != nil {
utils.Log(2, fmt.Sprintf("Issue loading chart data for service %v, %v", s.Name, err))
}
@ -178,13 +178,18 @@ func (s *Service) GraphData() string {
return string(data)
}
func (s *Service) AvgUptime() string {
failed, _ := s.TotalFailures()
total, _ := s.TotalHits()
func (s *Service) AvgUptime24() string {
ago := time.Now().Add(-24 * time.Hour)
return s.AvgUptime(ago)
}
func (s *Service) AvgUptime(ago time.Time) string {
failed, _ := s.TotalFailuresSince(ago)
if failed == 0 {
s.TotalUptime = "100"
return s.TotalUptime
}
total, _ := s.TotalHitsSince(ago)
if total == 0 {
s.TotalUptime = "0"
return s.TotalUptime
@ -217,25 +222,27 @@ func updateService(service *Service) {
}
func (u *Service) Delete() error {
res := serviceCol().Find("id", u.Id)
err := res.Delete()
if err != nil {
utils.Log(3, fmt.Sprintf("Failed to delete service %v. %v", u.Name, err))
return err
err := servicesDB().Delete(u)
if err.Error != nil {
utils.Log(3, fmt.Sprintf("Failed to delete service %v. %v", u.Name, err.Error))
return err.Error
}
u.Close()
CoreApp.RemoveService(u.index())
OnDeletedService(u)
return err
return err.Error
}
func (u *Service) UpdateSingle(attr ...interface{}) error {
return servicesDB().Model(u).Update(attr).Error
}
func (u *Service) Update(restart bool) error {
u.CreatedAt = time.Now()
res := serviceCol().Find("id", u.Id)
err := res.Update(u)
if err != nil {
err := servicesDB().Update(u)
if err.Error != nil {
utils.Log(3, fmt.Sprintf("Failed to update service %v. %v", u.Name, err))
return err
return err.Error
}
if restart {
u.Close()
@ -245,20 +252,19 @@ func (u *Service) Update(restart bool) error {
go u.CheckQueue(true)
}
OnUpdateService(u)
return err
return err.Error
}
func (u *Service) Create() (int64, error) {
u.CreatedAt = time.Now()
uuid, err := serviceCol().Insert(u)
if uuid == nil {
utils.Log(3, fmt.Sprintf("Failed to create service %v. %v", u.Name, err))
return 0, err
db := servicesDB().Create(u)
if db.Error != nil {
utils.Log(3, fmt.Sprintf("Failed to create service %v #%v: %v", u.Name, u.Id, db.Error))
return 0, db.Error
}
u.Id = uuid.(int64)
u.Start()
CoreApp.AddService(u.Service)
return uuid.(int64), err
return u.Id, nil
}
func CountOnline() int {

View File

@ -26,23 +26,29 @@ var (
newServiceId int64
)
func TestSelectHTTPService(t *testing.T) {
services, err := CoreApp.SelectAllServices()
assert.Nil(t, err)
assert.Equal(t, 18, len(services))
assert.Equal(t, "Google", services[0].Name)
assert.Equal(t, "http", services[0].Type)
}
func TestSelectAllServices(t *testing.T) {
services := CoreApp.Services()
for _, s := range services {
service := s.Check(true)
assert.True(t, service.Online)
assert.True(t, service.IsRunning())
t.Logf("ID: %v %v\n", s.Id, s.Name)
}
assert.Equal(t, 5, len(services))
}
func TestSelectHTTPService(t *testing.T) {
service := SelectService(1)
assert.Equal(t, "Google", service.Name)
assert.Equal(t, "http", service.Type)
assert.Equal(t, 18, len(services))
}
func TestSelectTCPService(t *testing.T) {
services := CoreApp.Services()
assert.Equal(t, 18, len(services))
service := SelectService(5)
assert.NotNil(t, service)
assert.Equal(t, "Google DNS", service.Name)
assert.Equal(t, "tcp", service.Type)
}
@ -105,9 +111,14 @@ func TestCheckTCPService(t *testing.T) {
}
func TestServiceOnline24Hours(t *testing.T) {
service := SelectService(5)
amount := service.Online24()
assert.Equal(t, float32(100), amount)
since, err := time.Parse(time.RFC3339, SERVICE_SINCE)
assert.Nil(t, err)
service := SelectService(1)
assert.Equal(t, float32(83.33), service.OnlineSince(since))
service2 := SelectService(5)
assert.Equal(t, float32(100), service2.OnlineSince(since))
service3 := SelectService(18)
assert.Equal(t, float32(0), service3.OnlineSince(since))
}
func TestServiceSmallText(t *testing.T) {
@ -117,30 +128,35 @@ func TestServiceSmallText(t *testing.T) {
}
func TestServiceAvgUptime(t *testing.T) {
service := SelectService(5)
uptime := service.AvgUptime()
assert.Equal(t, "100", uptime)
since, err := time.Parse(time.RFC3339, SERVICE_SINCE)
assert.Nil(t, err)
service := SelectService(1)
assert.Equal(t, "83.33", service.AvgUptime(since))
service2 := SelectService(5)
assert.Equal(t, "100", service2.AvgUptime(since))
service3 := SelectService(18)
assert.Equal(t, "0.00", service3.AvgUptime(since))
}
func TestServiceHits(t *testing.T) {
service := SelectService(5)
hits, err := service.Hits()
assert.Nil(t, err)
assert.Equal(t, int(2), len(hits))
assert.Equal(t, int(5), len(hits))
}
func TestServiceLimitedHits(t *testing.T) {
service := SelectService(5)
hits, err := service.LimitedHits()
assert.Nil(t, err)
assert.Equal(t, int(2), len(hits))
assert.Equal(t, int(5), len(hits))
}
func TestServiceTotalHits(t *testing.T) {
service := SelectService(5)
hits, err := service.TotalHits()
assert.Nil(t, err)
assert.Equal(t, uint64(0x2), hits)
assert.Equal(t, uint64(0x5), hits)
}
func TestServiceSum(t *testing.T) {
@ -176,7 +192,6 @@ func TestCreateService(t *testing.T) {
func TestViewNewService(t *testing.T) {
newService := SelectService(newServiceId)
assert.Equal(t, "That'll do 🐢", newService.Name)
}
func TestCreateFailingHTTPService(t *testing.T) {
@ -195,10 +210,12 @@ func TestCreateFailingHTTPService(t *testing.T) {
assert.NotZero(t, newServiceId)
newService := SelectService(newServiceId)
assert.Equal(t, "Bad URL", newService.Name)
t.Log("new service ID: ", newServiceId)
}
func TestServiceFailedCheck(t *testing.T) {
service := SelectService(7)
service := SelectService(20)
assert.Equal(t, "Bad URL", service.Name)
checked := service.Check(true)
assert.Equal(t, "Bad URL", checked.Name)
assert.False(t, checked.Online)
@ -219,10 +236,11 @@ func TestCreateFailingTCPService(t *testing.T) {
assert.NotZero(t, newServiceId)
newService := SelectService(newServiceId)
assert.Equal(t, "Bad TCP", newService.Name)
t.Log("new failing tcp service ID: ", newServiceId)
}
func TestServiceFailedTCPCheck(t *testing.T) {
service := SelectService(8)
service := SelectService(21)
checked := service.Check(true)
assert.Equal(t, "Bad TCP", checked.Name)
assert.False(t, checked.Online)
@ -244,13 +262,13 @@ func TestDeleteService(t *testing.T) {
count, err := CoreApp.SelectAllServices()
assert.Nil(t, err)
assert.Equal(t, 8, len(count))
assert.Equal(t, 21, len(count))
err = service.Delete()
assert.Nil(t, err)
services := CoreApp.Services()
assert.Equal(t, 7, len(services))
assert.Equal(t, 20, len(services))
}
func TestServiceCloseRoutine(t *testing.T) {

View File

@ -28,36 +28,29 @@ type User struct {
}
func ReturnUser(u *types.User) *User {
return &User{User: u}
return &User{u}
}
func SelectUser(id int64) (*User, error) {
var user *User
col := DbSession.Collection("users")
res := col.Find("id", id)
err := res.One(&user)
return user, err
var user User
err := usersDB().First(&user, id)
return &user, err.Error
}
func SelectUsername(username string) (*User, error) {
var user *User
col := DbSession.Collection("users")
res := col.Find("username", username)
err := res.One(&user)
return user, err
var user User
res := usersDB().Where("username = ?", username)
err := res.First(&user)
return &user, err.Error
}
func (u *User) Delete() error {
col := DbSession.Collection("users")
user := col.Find("id", u.Id)
return user.Delete()
return usersDB().Delete(u).Error
}
func (u *User) Update() error {
u.CreatedAt = time.Now()
col := DbSession.Collection("users")
user := col.Find("id", u.Id)
return user.Update(u)
return usersDB().Update(u).Error
}
func (u *User) Create() (int64, error) {
@ -65,39 +58,36 @@ func (u *User) Create() (int64, error) {
u.Password = utils.HashPassword(u.Password)
u.ApiKey = utils.NewSHA1Hash(5)
u.ApiSecret = utils.NewSHA1Hash(10)
col := DbSession.Collection("users")
uuid, err := col.Insert(u)
if err != nil {
return 0, err
db := usersDB().Create(u)
if db.Error != nil {
return 0, db.Error
}
if uuid == nil {
utils.Log(3, fmt.Sprintf("Failed to create user %v. %v", u.Username, err))
return 0, err
if u.Id == 0 {
utils.Log(3, fmt.Sprintf("Failed to create user %v. %v", u.Username, db.Error))
return 0, db.Error
}
return uuid.(int64), err
return u.Id, db.Error
}
func SelectAllUsers() ([]*User, error) {
var users []*User
col := DbSession.Collection("users").Find()
err := col.All(&users)
if err != nil {
utils.Log(3, fmt.Sprintf("Failed to load all users. %v", err))
db := usersDB().Find(&users)
if db.Error != nil {
utils.Log(3, fmt.Sprintf("Failed to load all users. %v", db.Error))
}
return users, err
return users, db.Error
}
func AuthUser(username, password string) (*User, bool) {
var auth bool
user, err := SelectUsername(username)
if err != nil {
utils.Log(2, err)
return nil, false
}
if CheckHash(password, user.Password) {
auth = true
return user, true
}
return user, auth
return nil, false
}
func CheckHash(password, hash string) bool {

View File

@ -36,13 +36,13 @@ func TestCreateUser(t *testing.T) {
func TestSelectAllUsers(t *testing.T) {
users, err := SelectAllUsers()
assert.Nil(t, err)
assert.Equal(t, 1, len(users))
assert.Equal(t, 2, len(users))
}
func TestSelectUser(t *testing.T) {
user, err := SelectUser(1)
assert.Nil(t, err)
assert.Equal(t, "test@email.com", user.Email)
assert.Equal(t, "info@statup.io", user.Email)
assert.True(t, user.Admin)
}
@ -50,7 +50,7 @@ func TestSelectUsername(t *testing.T) {
user, err := SelectUsername("hunter")
assert.Nil(t, err)
assert.Equal(t, "test@email.com", user.Email)
assert.Equal(t, int64(1), user.Id)
assert.Equal(t, int64(2), user.Id)
assert.True(t, user.Admin)
}
@ -80,7 +80,7 @@ func TestCreateUser2(t *testing.T) {
func TestSelectAllUsersAgain(t *testing.T) {
users, err := SelectAllUsers()
assert.Nil(t, err)
assert.Equal(t, 2, len(users))
assert.Equal(t, 3, len(users))
}
func TestAuthUser(t *testing.T) {
@ -88,12 +88,12 @@ func TestAuthUser(t *testing.T) {
assert.True(t, auth)
assert.NotNil(t, user)
assert.Equal(t, "user@email.com", user.Email)
assert.Equal(t, int64(2), user.Id)
assert.Equal(t, int64(3), user.Id)
assert.True(t, user.Admin)
}
func TestFailedAuthUser(t *testing.T) {
user, auth := AuthUser("hunter", "wrongpassword")
user, auth := AuthUser("hunterlong", "wrongpassword")
assert.False(t, auth)
assert.Nil(t, user)
}
@ -111,3 +111,8 @@ func TestDeleteUser(t *testing.T) {
err = user.Delete()
assert.Nil(t, err)
}
func TestDbConfig_Close(t *testing.T) {
err := Configs.Close()
assert.Nil(t, err)
}

142
dev/mysql_seed.sql Normal file
View File

@ -0,0 +1,142 @@
INSERT INTO core (name,description,config,api_key,api_secret,style,footer,domain,version,migration_id,use_cdn) VALUES ('Awesome Status','This is from the seed file!','config.yml','d2fead3e459bd14f570cf08527175b88b32d7faa','e351393306ea245de5f9588cbe8627c74db007c6','','Created by Hunter Long','','',0,false);
INSERT INTO services (name,domain,check_type,method,port,expected,expected_status,check_interval,post_data,order_id,timeout,created_at) VALUES
('Google','https://google.com','http','GET',0,'',200,10,'',0,10,'2018-08-31 10:42:08'),
('Statup Github','https://github.com/hunterlong/statup','http','GET',0,'',200,30,'',0,20,'2018-08-31 10:42:08'),
('JSON Users Test','https://jsonplaceholder.typicode.com/users','http','GET',0,'',200,60,'',0,30,'2018-08-31 10:42:08'),
('JSON API Tester','https://jsonplaceholder.typicode.com/posts','http','POST',0,'(title)": "((\\"|[statup])*)"',201,30,'{ "title": "statup", "body": "bar", "userId": 19999 }',0,30,'2018-08-31 10:42:08'),
('Google DNS','8.8.8.8','tcp','',53,'',0,20,'',0,120,'2018-08-31 10:42:08'),
('The Bravery - An Honest Mistake','https://www.youtube.com/watch?v=O8vzbezVru4','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14'),
('Upper.io','https://upper.io/db.v3/','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14'),
('CoinApp Status','https://status.coinapp.io','http','GET',0,'',200,1,'',0,30,'2018-08-31 10:42:16'),
('Demo Page','https://demo.statup.io','http','GET',0,'',200,2,'',0,30,'2018-08-31 10:42:16'),
('Golang','https://golang.org','http','GET',0,'',200,3,'',0,30,'2018-08-31 10:42:16'),
('Github','https://github.com/hunterlong','http','GET',0,'',200,4,'',0,30,'2018-08-31 10:42:17'),
('Santa Monica','https://www.santamonica.com','http','GET',0,'',200,5,'',0,30,'2018-08-31 10:42:17'),
('Oeschs Die Dritten','https://www.oeschs-die-dritten.ch/en/','http','GET',0,'',200,6,'',0,30,'2018-08-31 10:42:18'),
('EtherScan.io','https://etherscan.io','http','GET',0,'',200,7,'',0,30,'2018-08-31 10:42:20'),
('Test Service 7','https://www.youtube.com/watch?v=ipvEIZMMILA','http','GET',0,'',200,8,'',0,30,'2018-08-31 10:42:20'),
('Test Service 8','https://www.youtube.com/watch?v=UdaYVxYF1Ok','http','GET',0,'',200,9,'',0,30,'2018-08-31 10:42:20'),
('Test Service 9','https://www.youtube.com/watch?v=yydZbVoCbn0&t=870s','http','GET',0,'',200,10,'',0,30,'2018-08-31 10:42:20'),
('Failing URL','http://failingdomainsarenofunatall.com','http','GET',0,'',200,11,'',0,30,'2018-08-31 10:42:20');
INSERT INTO users (username,password,email,api_key,api_secret,administrator,created_at) VALUES
('admin','$2a$14$Aye3yHae0ml6WRtvdgkRnO19OFze0IKF6IOHrdLpETtwLjnPelMUm','info@statup.io','27aa701119fb561d734eb4469cf13ba2550007e2','29de07014d32fbbbb80053ef3c19b464b2b72f64',1,'2018-08-31 10:42:07');
INSERT INTO hits (service,latency,created_at) VALUES
(5,0.006504081,'2018-08-29 10:42:08'),
(3,0.202164333,'2018-08-29 10:42:08'),
(4,0.376675172,'2018-08-29 10:42:09'),
(1,0.413912204,'2018-08-29 10:42:09'),
(1,0.473912204,'2018-08-29 10:42:09'),
(2,0.528427935,'2018-08-29 10:42:09'),
(6,0.11930188,'2018-08-29 10:42:09'),
(7,0.001062722,'2018-08-29 10:42:09'),
(7,0.004046882,'2018-08-29 10:42:09'),
(6,0.063360069,'2018-08-29 10:42:09'),
(8,0.168951416,'2018-08-29 10:42:16'),
(8,0.069032763,'2018-08-29 10:42:16'),
(9,0.47712966,'2018-08-29 10:42:16'),
(10,0.104510482,'2018-08-29 10:42:17'),
(10,0.062536146,'2018-08-29 10:42:17'),
(9,0.352823197,'2018-08-29 10:42:09'),
(8,0.38226374,'2018-08-29 10:42:09'),
(11,0.857324393,'2018-08-29 10:42:17'),
(12,0.113320285,'2018-08-29 10:42:18'),
(12,0.038532321,'2018-08-29 10:42:18'),
(8,0.123430059,'2018-08-29 10:42:18'),
(11,0.625290389,'2018-08-29 10:42:18'),
(1,0.091823417,'2018-08-29 10:42:18'),
(9,0.246651097,'2018-08-29 10:42:19'),
(8,0.222901604,'2018-08-29 10:42:19'),
(13,1.600367041,'2018-08-29 10:42:20'),
(10,0.050076397,'2018-08-29 10:42:20'),
(14,0.460363958,'2018-08-29 10:42:20'),
(8,0.252590543,'2018-08-29 10:42:20'),
(15,0.144109113,'2018-08-29 10:42:20'),
(15,0.059993314,'2018-08-29 10:42:20'),
(16,0.058810662,'2018-08-29 10:42:20'),
(17,0.061824594,'2018-08-29 10:42:20'),
(16,0.074584583,'2018-08-29 10:42:20'),
(17,0.057086551,'2018-08-29 10:42:20'),
(18,0.020983572,'2018-08-29 10:42:20'),
(5,0.006504081,'2018-08-30 10:42:08'),
(3,0.202164333,'2018-08-30 10:42:08'),
(4,0.376675172,'2018-08-30 10:42:09'),
(1,0.413912204,'2018-08-30 10:42:09'),
(2,0.528427935,'2018-08-30 10:42:09'),
(6,0.11930188,'2018-08-30 10:42:14'),
(7,0.001062722,'2018-08-30 10:42:14'),
(7,0.004046882,'2018-08-30 10:42:14'),
(6,0.063360069,'2018-08-30 10:42:14'),
(8,0.168951416,'2018-08-30 10:42:16'),
(8,0.069032763,'2018-08-30 10:42:16'),
(9,0.47712966,'2018-08-30 10:42:16'),
(10,0.104510482,'2018-08-30 10:42:17'),
(10,0.062536146,'2018-08-30 10:42:17'),
(9,0.352823197,'2018-08-30 10:42:17'),
(8,0.38226374,'2018-08-30 10:42:17'),
(11,0.857324393,'2018-08-30 10:42:17'),
(12,0.113320285,'2018-08-30 10:42:18'),
(12,0.038532321,'2018-08-30 10:42:18'),
(8,0.123430059,'2018-08-30 10:42:18'),
(11,0.625290389,'2018-08-30 10:42:18'),
(1,0.091823417,'2018-08-30 10:42:18'),
(9,0.246651097,'2018-08-30 10:42:19'),
(8,0.222901604,'2018-08-30 10:42:19'),
(13,1.600367041,'2018-08-30 10:42:20'),
(10,0.050076397,'2018-08-30 10:42:20'),
(14,0.460363958,'2018-08-30 10:42:20'),
(8,0.252590543,'2018-08-30 10:42:20'),
(15,0.144109113,'2018-08-30 10:42:20'),
(15,0.059993314,'2018-08-30 10:42:20'),
(16,0.058810662,'2018-08-30 10:42:20'),
(17,0.061824594,'2018-08-30 10:42:20'),
(16,0.074584583,'2018-08-30 10:42:20'),
(17,0.057086551,'2018-08-30 10:42:20'),
(18,0.020983572,'2018-08-30 10:42:20'),
(5,0.006504081,'2018-08-31 10:42:08'),
(3,0.202164333,'2018-08-31 10:42:08'),
(4,0.376675172,'2018-08-31 10:42:09'),
(1,0.413912204,'2018-08-31 10:42:09'),
(2,0.528427935,'2018-08-31 10:42:09'),
(6,0.11930188,'2018-08-31 10:42:14'),
(7,0.001062722,'2018-08-31 10:42:14'),
(7,0.004046882,'2018-08-31 10:42:14'),
(6,0.063360069,'2018-08-31 10:42:14'),
(8,0.168951416,'2018-08-31 10:42:16'),
(8,0.069032763,'2018-08-31 10:42:16'),
(9,0.47712966,'2018-08-31 10:42:16'),
(10,0.104510482,'2018-08-31 10:42:17'),
(10,0.062536146,'2018-08-31 10:42:17'),
(9,0.352823197,'2018-08-31 10:42:17'),
(8,0.38226374,'2018-08-31 10:42:17'),
(11,0.857324393,'2018-08-31 10:42:17'),
(12,0.113320285,'2018-08-31 10:42:18'),
(12,0.038532321,'2018-08-31 10:42:18'),
(8,0.123430059,'2018-08-31 10:42:18'),
(11,0.625290389,'2018-08-31 10:42:18'),
(1,0.091823417,'2018-08-31 10:42:18'),
(9,0.246651097,'2018-08-31 10:42:19'),
(8,0.222901604,'2018-08-31 10:42:19'),
(13,1.600367041,'2018-08-31 10:42:20'),
(10,0.050076397,'2018-08-31 10:42:20'),
(14,0.460363958,'2018-08-31 10:42:20'),
(8,0.252590543,'2018-08-31 10:42:20'),
(15,0.144109113,'2018-08-31 10:42:20'),
(15,0.059993314,'2018-08-31 10:42:20'),
(16,0.058810662,'2018-08-31 10:42:20'),
(17,0.061824594,'2018-08-31 10:42:20'),
(16,0.074584583,'2018-08-31 10:42:20'),
(17,0.057086551,'2018-08-31 10:42:20'),
(18,0.020983572,'2018-08-31 10:42:20');
INSERT INTO failures (issue,method,service,created_at) VALUES
('HTTP Status Code 200 did not match 0','',18,'2018-08-28 10:42:14'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-28 10:42:14'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-29 10:42:14'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-30 10:42:14'),
('Incorrect Response','',1,'2018-08-31 10:40:14'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14'),
('HTTP Status Code 200 did not match 0','',18,'2018-08-31 10:42:14');
INSERT INTO communication (id,method,host,port,username,password,var1,var2,api_key,api_secret,enabled,removable,limits,created_at) VALUES
(1,'email','smtp.emailer.com',587,'exampleuser','password123','info@betatude.com','sendto@gmail.com','','',1,0,7,'2018-08-31 10:42:15'),
(2,'slack','https://webhooksurl.slack.com/***',0,'','','','','','',0,0,3,'2018-08-31 10:42:08'),
(3,'twilio','',0,'','','','','','',0,0,3,'2018-08-31 10:42:08');

142
dev/postgres_seed.sql Normal file
View File

@ -0,0 +1,142 @@
INSERT INTO core (name,description,config,api_key,api_secret,style,footer,domain,version,migration_id,use_cdn) VALUES ('Awesome Status','This is from the seed file!','config.yml','d2fead3e459bd14f570cf08527175b88b32d7faa','e351393306ea245de5f9588cbe8627c74db007c6','','Created by Hunter Long','DEV','',0,false);
INSERT INTO services (name,domain,check_type,method,port,expected,expected_status,check_interval,post_data,order_id,timeout,created_at) VALUES
('Google','https://google.com','http','GET',0,'',200,10,'',0,10,'2018-08-31 10:42:08.76390584-07:00'),
('Statup Github','https://github.com/hunterlong/statup','http','GET',0,'',200,30,'',0,20,'2018-08-31 10:42:08.764977938-07:00'),
('JSON Users Test','https://jsonplaceholder.typicode.com/users','http','GET',0,'',200,60,'',0,30,'2018-08-31 10:42:08.765794226-07:00'),
('JSON API Tester','https://jsonplaceholder.typicode.com/posts','http','POST',0,'(title)": "((\\"|[statup])*)"',201,30,'{ "title": "statup", "body": "bar", "userId": 19999 }',0,30,'2018-08-31 10:42:08.766542311-07:00'),
('Google DNS','8.8.8.8','tcp','',53,'',0,20,'',0,120,'2018-08-31 10:42:08.767327346-07:00'),
('The Bravery - An Honest Mistake','https://www.youtube.com/watch?v=O8vzbezVru4','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14.201305666-07:00'),
('Upper.io','https://upper.io/db.v3/','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14.201305666-07:00'),
('CoinApp Status','https://status.coinapp.io','http','GET',0,'',200,1,'',0,30,'2018-08-31 10:42:16.097416218-07:00'),
('Demo Page','https://demo.statup.io','http','GET',0,'',200,2,'',0,30,'2018-08-31 10:42:16.360051225-07:00'),
('Golang','https://golang.org','http','GET',0,'',200,3,'',0,30,'2018-08-31 10:42:16.923478722-07:00'),
('Github','https://github.com/hunterlong','http','GET',0,'',200,4,'',0,30,'2018-08-31 10:42:17.075544885-07:00'),
('Santa Monica','https://www.santamonica.com','http','GET',0,'',200,5,'',0,30,'2018-08-31 10:42:17.946947674-07:00'),
('Oeschs Die Dritten','https://www.oeschs-die-dritten.ch/en/','http','GET',0,'',200,6,'',0,30,'2018-08-31 10:42:18.083709297-07:00'),
('EtherScan.io','https://etherscan.io','http','GET',0,'',200,7,'',0,30,'2018-08-31 10:42:20.020969513-07:00'),
('Test Service 7','https://www.youtube.com/watch?v=ipvEIZMMILA','http','GET',0,'',200,8,'',0,30,'2018-08-31 10:42:20.50135711-07:00'),
('Test Service 8','https://www.youtube.com/watch?v=UdaYVxYF1Ok','http','GET',0,'',200,9,'',0,30,'2018-08-31 10:42:20.651218082-07:00'),
('Test Service 9','https://www.youtube.com/watch?v=yydZbVoCbn0&t=870s','http','GET',0,'',200,10,'',0,30,'2018-08-31 10:42:20.725479695-07:00'),
('Failing URL','http://failingdomainsarenofunatall.com','http','GET',0,'',200,11,'',0,30,'2018-08-31 10:42:20.799471402-07:00');
INSERT INTO users (username,password,email,api_key,api_secret,administrator,created_at) VALUES
('admin','$2a$14$Aye3yHae0ml6WRtvdgkRnO19OFze0IKF6IOHrdLpETtwLjnPelMUm','info@statup.io','27aa701119fb561d734eb4469cf13ba2550007e2','29de07014d32fbbbb80053ef3c19b464b2b72f64',true,'2018-08-31 10:42:07.684406458-07:00');
INSERT INTO hits (service,latency,created_at) VALUES
(5,0.006504081,'2018-08-29 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-29 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-29 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-29 10:42:09.188850317-07:00'),
(1,0.473912204,'2018-08-29 10:42:10.118850317-07:00'),
(2,0.528427935,'2018-08-29 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-29 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-29 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-29 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-29 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-29 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-29 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-29 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-29 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-29 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-29 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-29 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-29 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-29 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-29 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-29 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-29 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-29 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-29 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-29 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-29 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-29 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-29 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-29 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-29 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-29 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-29 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-29 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-29 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-29 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-29 10:42:20.864610424-07:00'),
(5,0.006504081,'2018-08-30 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-30 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-30 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-30 10:42:09.188850317-07:00'),
(2,0.528427935,'2018-08-30 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-30 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-30 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-30 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-30 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-30 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-30 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-30 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-30 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-30 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-30 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-30 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-30 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-30 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-30 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-30 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-30 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-30 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-30 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-30 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-30 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-30 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-30 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-30 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-30 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-30 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-30 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-30 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-30 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-30 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-30 10:42:20.864610424-07:00'),
(5,0.006504081,'2018-08-31 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-31 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-31 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-31 10:42:09.188850317-07:00'),
(2,0.528427935,'2018-08-31 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-31 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-31 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-31 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-31 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-31 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-31 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-31 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-31 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-31 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-31 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-31 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-31 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-31 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-31 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-31 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-31 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-31 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-31 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-31 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-31 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-31 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-31 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-31 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-31 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-31 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-31 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-31 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-31 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-31 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-31 10:42:20.864610424-07:00');
INSERT INTO failures (issue,method,service,created_at) VALUES
('HTTP Status Code 200 did not match 0','',18,'2018-08-28 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-28 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-29 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-30 10:42:14.271162743-07:00'),
('Incorrect Response','',1,'2018-08-31 10:40:14.272209564-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14.272209564-07:00'),
('HTTP Status Code 200 did not match 0','',18,'2018-08-31 10:42:14.271162743-07:00');
INSERT INTO communication (id,method,host,port,username,password,var1,var2,api_key,api_secret,enabled,removable,limits,created_at) VALUES
(1,'email','smtp.emailer.com',587,'exampleuser','password123','info@betatude.com','sendto@gmail.com','','',true,false,7,'2018-08-31 10:42:15.000829706-07:00'),
(2,'slack','https://webhooksurl.slack.com/***',0,'','','','','','',false,false,3,'2018-08-31 10:42:08.775366824-07:00'),
(3,'twilio','',0,'','','','','','',false,false,3,'2018-08-31 10:42:08.776944923-07:00');

142
dev/sqlite_seed.sql Normal file
View File

@ -0,0 +1,142 @@
INSERT INTO core (name,description,config,api_key,api_secret,style,footer,domain,version,migration_id,use_cdn) VALUES ('Awesome Status','This is from the seed file!','config.yml','d2fead3e459bd14f570cf08527175b88b32d7faa','e351393306ea245de5f9588cbe8627c74db007c6','','Created by Hunter Long','','',0,0);
INSERT INTO services (id,name,domain,check_type,method,port,expected,expected_status,check_interval,post_data,order_id,timeout,created_at) VALUES
(1,'Google','https://google.com','http','GET',0,'',200,10,'',0,10,'2018-08-31 10:42:08.76390584-07:00'),
(2,'Statup Github','https://github.com/hunterlong/statup','http','GET',0,'',200,30,'',0,20,'2018-08-31 10:42:08.764977938-07:00'),
(3,'JSON Users Test','https://jsonplaceholder.typicode.com/users','http','GET',0,'',200,60,'',0,30,'2018-08-31 10:42:08.765794226-07:00'),
(4,'JSON API Tester','https://jsonplaceholder.typicode.com/posts','http','POST',0,'(title)": "((\\"|[statup])*)"',201,30,'{ "title": "statup", "body": "bar", "userId": 19999 }',0,30,'2018-08-31 10:42:08.766542311-07:00'),
(5,'Google DNS','8.8.8.8','tcp','',53,'',0,20,'',0,120,'2018-08-31 10:42:08.767327346-07:00'),
(6,'The Bravery - An Honest Mistake','https://www.youtube.com/watch?v=O8vzbezVru4','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14.201305666-07:00'),
(7,'Upper.io','https://upper.io/db.v3/','http','GET',0,'',0,30,'',0,15,'2018-08-31 10:42:14.201305666-07:00'),
(8,'CoinApp Status','https://status.coinapp.io','http','GET',0,'',200,1,'',0,30,'2018-08-31 10:42:16.097416218-07:00'),
(9,'Demo Page','https://demo.statup.io','http','GET',0,'',200,2,'',0,30,'2018-08-31 10:42:16.360051225-07:00'),
(10,'Golang','https://golang.org','http','GET',0,'',200,3,'',0,30,'2018-08-31 10:42:16.923478722-07:00'),
(11,'Github','https://github.com/hunterlong','http','GET',0,'',200,4,'',0,30,'2018-08-31 10:42:17.075544885-07:00'),
(12,'Santa Monica','https://www.santamonica.com','http','GET',0,'',200,5,'',0,30,'2018-08-31 10:42:17.946947674-07:00'),
(13,'Oeschs Die Dritten','https://www.oeschs-die-dritten.ch/en/','http','GET',0,'',200,6,'',0,30,'2018-08-31 10:42:18.083709297-07:00'),
(14,'EtherScan.io','https://etherscan.io','http','GET',0,'',200,7,'',0,30,'2018-08-31 10:42:20.020969513-07:00'),
(15,'Test Service 7','https://www.youtube.com/watch?v=ipvEIZMMILA','http','GET',0,'',200,8,'',0,30,'2018-08-31 10:42:20.50135711-07:00'),
(16,'Test Service 8','https://www.youtube.com/watch?v=UdaYVxYF1Ok','http','GET',0,'',200,9,'',0,30,'2018-08-31 10:42:20.651218082-07:00'),
(17,'Test Service 9','https://www.youtube.com/watch?v=yydZbVoCbn0&t=870s','http','GET',0,'',200,10,'',0,30,'2018-08-31 10:42:20.725479695-07:00'),
(18,'Failing URL','http://failingdomainsarenofunatall.com','http','GET',0,'',200,11,'',0,30,'2018-08-31 10:42:20.799471402-07:00');
INSERT INTO users (username,password,email,api_key,api_secret,administrator,created_at) VALUES
('admin','$2a$14$Aye3yHae0ml6WRtvdgkRnO19OFze0IKF6IOHrdLpETtwLjnPelMUm','info@statup.io','27aa701119fb561d734eb4469cf13ba2550007e2','29de07014d32fbbbb80053ef3c19b464b2b72f64',1,'2018-08-31 10:42:07.684406458-07:00');
INSERT INTO hits (service,latency,created_at) VALUES
(5,0.006504081,'2018-08-29 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-29 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-29 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-29 10:42:09.188850317-07:00'),
(1,0.473912204,'2018-08-29 10:42:10.118850317-07:00'),
(2,0.528427935,'2018-08-29 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-29 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-29 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-29 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-29 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-29 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-29 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-29 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-29 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-29 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-29 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-29 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-29 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-29 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-29 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-29 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-29 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-29 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-29 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-29 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-29 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-29 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-29 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-29 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-29 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-29 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-29 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-29 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-29 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-29 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-29 10:42:20.864610424-07:00'),
(5,0.006504081,'2018-08-30 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-30 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-30 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-30 10:42:09.188850317-07:00'),
(2,0.528427935,'2018-08-30 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-30 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-30 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-30 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-30 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-30 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-30 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-30 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-30 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-30 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-30 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-30 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-30 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-30 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-30 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-30 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-30 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-30 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-30 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-30 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-30 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-30 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-30 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-30 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-30 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-30 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-30 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-30 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-30 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-30 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-30 10:42:20.864610424-07:00'),
(5,0.006504081,'2018-08-31 10:42:08.779875117-07:00'),
(3,0.202164333,'2018-08-31 10:42:08.977187173-07:00'),
(4,0.376675172,'2018-08-31 10:42:09.151858662-07:00'),
(1,0.413912204,'2018-08-31 10:42:09.188850317-07:00'),
(2,0.528427935,'2018-08-31 10:42:09.310642068-07:00'),
(6,0.11930188,'2018-08-31 10:42:14.133392018-07:00'),
(7,0.001062722,'2018-08-31 10:42:14.148258553-07:00'),
(7,0.004046882,'2018-08-31 10:42:14.156087817-07:00'),
(6,0.063360069,'2018-08-31 10:42:14.205383358-07:00'),
(8,0.168951416,'2018-08-31 10:42:16.346340211-07:00'),
(8,0.069032763,'2018-08-31 10:42:16.421634189-07:00'),
(9,0.47712966,'2018-08-31 10:42:16.91309317-07:00'),
(10,0.104510482,'2018-08-31 10:42:17.065673146-07:00'),
(10,0.062536146,'2018-08-31 10:42:17.134754949-07:00'),
(9,0.352823197,'2018-08-31 10:42:17.272174866-07:00'),
(8,0.38226374,'2018-08-31 10:42:17.738731999-07:00'),
(11,0.857324393,'2018-08-31 10:42:17.939738264-07:00'),
(12,0.113320285,'2018-08-31 10:42:18.073586363-07:00'),
(12,0.038532321,'2018-08-31 10:42:18.119730063-07:00'),
(8,0.123430059,'2018-08-31 10:42:18.479407581-07:00'),
(11,0.625290389,'2018-08-31 10:42:18.5715553-07:00'),
(1,0.091823417,'2018-08-31 10:42:18.868788983-07:00'),
(9,0.246651097,'2018-08-31 10:42:19.165697332-07:00'),
(8,0.222901604,'2018-08-31 10:42:19.57929225-07:00'),
(13,1.600367041,'2018-08-31 10:42:20.010203546-07:00'),
(10,0.050076397,'2018-08-31 10:42:20.12391038-07:00'),
(14,0.460363958,'2018-08-31 10:42:20.495937751-07:00'),
(8,0.252590543,'2018-08-31 10:42:20.609139136-07:00'),
(15,0.144109113,'2018-08-31 10:42:20.64756516-07:00'),
(15,0.059993314,'2018-08-31 10:42:20.710322678-07:00'),
(16,0.058810662,'2018-08-31 10:42:20.712087274-07:00'),
(17,0.061824594,'2018-08-31 10:42:20.791266761-07:00'),
(16,0.074584583,'2018-08-31 10:42:20.797581163-07:00'),
(17,0.057086551,'2018-08-31 10:42:20.854020864-07:00'),
(18,0.020983572,'2018-08-31 10:42:20.864610424-07:00');
INSERT INTO failures (issue,method,service,created_at) VALUES
('HTTP Status Code 200 did not match 0','',18,'2018-08-28 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-28 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-29 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-30 10:42:14.271162743-07:00'),
('Incorrect Response','',1,'2018-08-31 10:40:14.272209564-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14.271162743-07:00'),
('HTTP Status Code 200 did not match 0','',6,'2018-08-31 10:42:14.272209564-07:00'),
('HTTP Status Code 200 did not match 0','',18,'2018-08-31 10:42:14.271162743-07:00');
INSERT INTO communication (id,method,host,port,username,password,var1,var2,api_key,api_secret,enabled,removable,limits,created_at) VALUES
(1,'email','smtp.emailer.com',587,'exampleuser','password123','info@betatude.com','sendto@gmail.com','','',1,0,7,'2018-08-31 10:42:15.000829706-07:00'),
(2,'slack','https://webhooksurl.slack.com/***',0,'','','','','','',0,0,3,'2018-08-31 10:42:08.775366824-07:00'),
(3,'twilio','',0,'','','','','','',0,0,3,'2018-08-31 10:42:08.776944923-07:00');

View File

@ -36,17 +36,23 @@ const (
func injectDatabase() {
core.NewCore()
core.Configs = new(types.Config)
core.Configs.Connection = "sqlite"
core.Configs = new(core.DbConfig)
core.Configs.DbConn = "sqlite"
core.CoreApp.DbConnection = "sqlite"
core.CoreApp.Version = "DEV"
core.DbConnection("sqlite", false, utils.Directory)
core.Configs.Connect(false, utils.Directory)
core.InitApp()
}
func Clean() {
utils.DeleteFile(dir + "/config.yml")
utils.DeleteFile(dir + "/statup.db")
utils.DeleteDirectory(dir + "/assets")
utils.DeleteDirectory(dir + "/logs")
}
func TestInit(t *testing.T) {
t.SkipNow()
injectDatabase()
Clean()
}
func formatJSON(res string, out interface{}) {

View File

@ -97,6 +97,8 @@ func TestProcessSetupHandler(t *testing.T) {
rr := httptest.NewRecorder()
Router().ServeHTTP(rr, req)
assert.Equal(t, 303, rr.Code)
assert.FileExists(t, dir+"/config.yml")
assert.FileExists(t, dir+"/statup.db")
}
func TestCheckSetupHandler(t *testing.T) {
@ -143,7 +145,9 @@ func TestServiceChartHandler(t *testing.T) {
assert.Equal(t, 200, rr.Code)
t.Log(body)
assert.Contains(t, body, "var ctx_1")
assert.Contains(t, body, "var ctx_2")
assert.Contains(t, body, "var ctx_3")
assert.Contains(t, body, "var ctx_4")
assert.Contains(t, body, "var ctx_5")
}

View File

@ -27,7 +27,7 @@ type index struct {
}
func IndexHandler(w http.ResponseWriter, r *http.Request) {
if core.CoreApp.DbConnection == "" {
if core.Configs == nil {
http.Redirect(w, r, "/setup", http.StatusSeeOther)
return
}
@ -42,12 +42,12 @@ func DesktopInit(ip string, port int) {
var err error
exists := utils.FileExists(utils.Directory + "/statup.db")
if exists {
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(utils.Directory)
if err != nil {
utils.Log(3, err)
return
}
err = core.DbConnection(core.Configs.Connection, false, utils.Directory)
err = core.Configs.Connect(false, utils.Directory)
if err != nil {
utils.Log(3, err)
return
@ -68,24 +68,28 @@ func DesktopInit(ip string, port int) {
Location: utils.Directory,
}}
err = config.Save()
config, err = config.Save()
if err != nil {
utils.Log(4, err)
}
config.DropDatabase()
config.CreateDatabase()
core.CoreApp = config.CreateCore()
if err != nil {
utils.Log(3, err)
return
}
core.Configs, err = core.LoadConfig()
core.Configs, err = core.LoadConfig(utils.Directory)
if err != nil {
utils.Log(3, err)
config.Error = err
return
}
err = core.DbConnection(core.Configs.Connection, false, utils.Directory)
err = core.Configs.Connect(false, utils.Directory)
if err != nil {
utils.Log(3, err)
core.DeleteConfig()

View File

@ -16,7 +16,6 @@
package handlers
import (
"github.com/hunterlong/statup/core"
"net/http"
"strings"
)
@ -53,6 +52,6 @@ func PluginsDownloadHandler(w http.ResponseWriter, r *http.Request) {
//vars := mux.Vars(router)
//name := vars["name"]
//DownloadPlugin(name)
core.LoadConfig()
//core.LoadConfig(utils.Directory)
http.Redirect(w, r, "/plugins", http.StatusSeeOther)
}

View File

@ -61,13 +61,6 @@ func PrometheusHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(output))
}
func ResetDbHandler(w http.ResponseWriter, r *http.Request) {
utils.Log(1, fmt.Sprintf("Prometheus /metrics Request From IP: %v\n", r.RemoteAddr))
core.DropDatabase()
core.CoreApp = nil
w.WriteHeader(http.StatusOK)
}
func isAuthorized(r *http.Request) bool {
var token string
tokens, ok := r.Header["Authorization"]

View File

@ -51,7 +51,6 @@ func Router() *mux.Router {
r.Handle("/setup", http.HandlerFunc(SetupHandler)).Methods("GET")
r.Handle("/setup", http.HandlerFunc(ProcessSetupHandler)).Methods("POST")
r.Handle("/dashboard", http.HandlerFunc(DashboardHandler)).Methods("GET")
//r.Handle("/backups/create", http.HandlerFunc(BackupCreateHandler)).Methods("GET")
r.Handle("/dashboard", http.HandlerFunc(LoginHandler)).Methods("POST")
r.Handle("/logout", http.HandlerFunc(LogoutHandler))
r.Handle("/services", http.HandlerFunc(ServicesHandler)).Methods("GET")

View File

@ -60,8 +60,7 @@ func ReorderServiceHandler(w http.ResponseWriter, r *http.Request) {
decoder.Decode(&newOrder)
for _, s := range newOrder {
service := core.SelectService(s.Id)
service.Order = s.Order
service.Update(false)
service.UpdateSingle("order_id", s.Order)
}
w.WriteHeader(http.StatusOK)
}

View File

@ -16,7 +16,6 @@
package handlers
import (
"fmt"
"github.com/hunterlong/statup/core"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
@ -56,6 +55,7 @@ func SetupHandler(w http.ResponseWriter, r *http.Request) {
}
func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
var err error
if core.CoreApp.Services() != nil {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
@ -75,7 +75,9 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
domain := r.PostForm.Get("domain")
email := r.PostForm.Get("email")
config := &core.DbConfig{&types.DbConfig{
dir := utils.Directory
config := &core.DbConfig{DbConfig: &types.DbConfig{
DbConn: dbConn,
DbHost: dbHost,
DbUser: dbUser,
@ -92,13 +94,15 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
Location: utils.Directory,
}}
fmt.Println(config)
err := config.Save()
core.Configs, err = config.Save()
if err != nil {
utils.Log(4, err)
config.Error = err
SetupResponseError(w, r, config)
return
}
core.Configs, err = core.LoadConfig(dir)
if err != nil {
utils.Log(3, err)
config.Error = err
@ -106,23 +110,26 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
return
}
core.Configs, err = core.LoadConfig()
err = core.Configs.Connect(false, dir)
if err != nil {
utils.Log(3, err)
config.Error = err
SetupResponseError(w, r, config)
return
}
err = core.DbConnection(core.Configs.Connection, false, utils.Directory)
if err != nil {
utils.Log(3, err)
utils.Log(4, err)
core.DeleteConfig()
config.Error = err
SetupResponseError(w, r, config)
return
}
config.DropDatabase()
config.CreateDatabase()
core.CoreApp, err = config.InsertCore()
if err != nil {
utils.Log(4, err)
config.Error = err
SetupResponseError(w, r, config)
return
}
admin := core.ReturnUser(&types.User{
Username: config.Username,
Password: config.Password,

View File

@ -215,7 +215,7 @@ func (u *Email) OnSave() error {
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
func (u *Email) Install() error {
inDb, err := emailer.Notification.IsInDatabase()
inDb := emailer.Notification.IsInDatabase()
if !inDb {
newNotifer, err := InsertDatabase(u.Notification)
if err != nil {
@ -224,7 +224,7 @@ func (u *Email) Install() error {
}
utils.Log(1, fmt.Sprintf("new notifier #%v installed: %v", newNotifer, u.Method))
}
return err
return nil
}
func (u *Email) dialSend(email *EmailOutgoing) error {

View File

@ -19,34 +19,34 @@ import (
"fmt"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/jinzhu/gorm"
"strings"
"time"
"upper.io/db.v3"
)
var (
AllCommunications []types.AllNotifiers
Collections db.Collection
Collections *gorm.DB
Logs []*NotificationLog
)
type Notification struct {
Id int64 `db:"id,omitempty" json:"id"`
Method string `db:"method" json:"method"`
Host string `db:"host" json:"-"`
Port int `db:"port" json:"-"`
Username string `db:"username" json:"-"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"-"`
Var2 string `db:"var2" json:"-"`
ApiKey string `db:"api_key" json:"-"`
ApiSecret string `db:"api_secret" json:"-"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int `db:"limits" json:"-"`
Removable bool `db:"removable" json:"-"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
Form []NotificationForm
Routine chan struct{}
Id int64 `gorm:"primary_key column:id" json:"id"`
Method string `gorm:"column:method" json:"method"`
Host string `gorm:"column:host" json:"-"`
Port int `gorm:"column:port" json:"-"`
Username string `gorm:"column:username" json:"-"`
Password string `gorm:"column:password" json:"-"`
Var1 string `gorm:"column:var1" json:"-"`
Var2 string `gorm:"column:var2" json:"-"`
ApiKey string `gorm:"column:api_key" json:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"`
Enabled bool `gorm:"column:enabled" json:"enabled"`
Limits int `gorm:"column:limits" json:"-"`
Removable bool `gorm:"column:removable" json:"-"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
Form []NotificationForm `gorm:"-" json:"-"`
Routine chan struct{} `gorm:"-" json:"-"`
}
type Notifier interface {
@ -115,30 +115,30 @@ func reverseLogs(input []*NotificationLog) []*NotificationLog {
return append(reverseLogs(input[1:]), input[0])
}
func (n *Notification) IsInDatabase() (bool, error) {
return Collections.Find("id", n.Id).Exists()
func (n *Notification) IsInDatabase() bool {
return !Collections.Find(n).RecordNotFound()
}
func SelectNotification(id int64) (*Notification, error) {
var notifier *Notification
err := Collections.Find("id", id).One(&notifier)
return notifier, err
var notifier Notification
err := Collections.Find(&notifier, id)
return &notifier, err.Error
}
func (n *Notification) Update() (*Notification, error) {
n.CreatedAt = time.Now()
err := Collections.Find("id", n.Id).Update(n)
return n, err
err := Collections.Update(n)
return n, err.Error
}
func InsertDatabase(n *Notification) (int64, error) {
n.CreatedAt = time.Now()
n.Limits = 3
newId, err := Collections.Insert(n)
if err != nil {
return 0, err
db := Collections.Create(n)
if db.Error != nil {
return 0, db.Error
}
return newId.(int64), err
return n.Id, db.Error
}
func SelectNotifier(id int64) Notifier {

View File

@ -18,10 +18,12 @@ package notifiers
import (
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
_ "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"testing"
"upper.io/db.v3/sqlite"
)
var (
@ -67,11 +69,8 @@ func init() {
}
func injectDatabase() {
sqliteDb := sqlite.ConnectionURL{
Database: dir + "/statup.db",
}
dbSession, _ := sqlite.Open(sqliteDb)
Collections = dbSession.Collection("communication")
dbSession, _ := gorm.Open("sqlite3", dir+"/statup.db")
Collections = dbSession.Table("communication").Model(&Notification{})
}
type Tester struct {
@ -100,8 +99,7 @@ func TestAdd(t *testing.T) {
}
func TestIsInDatabase(t *testing.T) {
in, err := testNotifier.IsInDatabase()
assert.Nil(t, err)
in := testNotifier.IsInDatabase()
assert.False(t, in)
}
@ -110,8 +108,7 @@ func TestInsertDatabase(t *testing.T) {
assert.Nil(t, err)
assert.NotZero(t, newId)
in, err := testNotifier.IsInDatabase()
assert.Nil(t, err)
in := testNotifier.IsInDatabase()
assert.True(t, in)
}

View File

@ -165,7 +165,7 @@ func (u *Slack) OnSave() error {
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
func (u *Slack) Install() error {
inDb, err := slacker.Notification.IsInDatabase()
inDb := slacker.Notification.IsInDatabase()
if !inDb {
newNotifer, err := InsertDatabase(u.Notification)
if err != nil {
@ -174,5 +174,5 @@ func (u *Slack) Install() error {
}
utils.Log(1, fmt.Sprintf("new notifier #%v installed: %v", newNotifer, u.Method))
}
return err
return nil
}

View File

@ -179,7 +179,7 @@ func (u *Twilio) OnSave() error {
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
func (u *Twilio) Install() error {
inDb, err := twilio.Notification.IsInDatabase()
inDb := twilio.Notification.IsInDatabase()
if !inDb {
newNotifer, err := InsertDatabase(u.Notification)
if err != nil {
@ -188,5 +188,5 @@ func (u *Twilio) Install() error {
}
utils.Log(1, fmt.Sprintf("new notifier #%v installed: %v", newNotifer, u.Method))
}
return err
return nil
}

View File

@ -4,4 +4,4 @@ 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;
DROP TABLE IF EXISTS communication;

View File

@ -10,21 +10,20 @@ CREATE TABLE core (
version VARCHAR(50),
migration_id INT(6) NOT NULL DEFAULT 0,
use_cdn BOOL NOT NULL DEFAULT '0'
);
) ENGINE=INNODB;
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
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 DATETIME DEFAULT CURRENT_TIMESTAMP,
INDEX (id),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE (username, email)
);
) ENGINE=INNODB;
CREATE TABLE services (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
name VARCHAR(50),
domain text,
check_type text,
@ -35,38 +34,34 @@ CREATE TABLE services (
check_interval int(11),
post_data text,
order_id integer default 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
timeout INT(6) DEFAULT 30,
INDEX (id)
);
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
timeout INT(6) DEFAULT 30
) ENGINE=INNODB;
CREATE TABLE hits (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
service INTEGER NOT NULL,
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
service BIGINT(20) UNSIGNED NOT NULL,
latency float,
created_at DATETIME,
INDEX (id, service),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
);
) ENGINE=INNODB;
CREATE TABLE failures (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
issue text,
method text,
service INTEGER NOT NULL,
created_at DATETIME,
INDEX (id, service),
service BIGINT(20) UNSIGNED NOT NULL,
created_at TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
);
) ENGINE=INNODB;
CREATE TABLE checkins (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
service INTEGER NOT NULL,
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
service BIGINT(20) UNSIGNED NOT NULL,
check_interval integer,
api text,
created_at DATETIME,
INDEX (id, service),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (service) REFERENCES services(id) ON DELETE CASCADE
);
) ENGINE=INNODB;
CREATE TABLE communication (
id SERIAL PRIMARY KEY,
id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY(id),
method text,
host text,
port integer,
@ -79,5 +74,5 @@ CREATE TABLE communication (
enabled BOOL NOT NULL DEFAULT '0',
removable BOOL NOT NULL DEFAULT '0',
limits integer,
created_at DATETIME
);
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;

View File

@ -11,21 +11,19 @@ CREATE TABLE core (
migration_id integer default 0,
use_cdn bool default false
);
CREATE TABLE users (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
username text NOT NULL UNIQUE,
password text,
email text,
api_key text,
api_secret text,
administrator bool,
created_at DATETIME,
created_at TIMESTAMP,
UNIQUE (username, email)
);
CREATE TABLE services (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
name text,
domain text,
check_type text,
@ -37,34 +35,34 @@ CREATE TABLE services (
post_data text,
order_id integer default 0,
timeout integer default 30,
created_at DATETIME
created_at TIMESTAMP
);
CREATE TABLE hits (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
latency float,
created_at DATETIME
created_at TIMESTAMP
);
CREATE TABLE failures (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
issue text,
method text,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
created_at DATETIME
created_at TIMESTAMP
);
CREATE TABLE checkins (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
service INTEGER NOT NULL REFERENCES services(id) ON DELETE CASCADE ON UPDATE CASCADE,
check_interval integer,
api text,
created_at DATETIME
created_at TIMESTAMP
);
CREATE TABLE communication (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
id INTEGER PRIMARY KEY,
method text,
host text,
port integer,
@ -77,10 +75,10 @@ CREATE TABLE communication (
enabled boolean,
removable boolean,
limits integer,
created_at DATETIME
created_at TIMESTAMP
);
CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service);
CREATE INDEX idx_checkins ON checkins(service);
CREATE INDEX idx_checkins ON checkins(service);

View File

@ -73,14 +73,14 @@
Average Response
</div>
<div class="col-4">
<span class="lg_number">{{.AvgUptime}}%</span>
Total Uptime
<span class="lg_number">{{.AvgUptime24}}%</span>
Uptime last 24 Hours
</div>
</div>
</div>
</div>
{{ if .AvgTime }}
{{ if .AvgUptime24 }}
<div class="chart-container">
<canvas id="service_{{ .Id }}"></canvas>
</div>
@ -127,4 +127,4 @@
</body>
</html>
</html>

View File

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

View File

@ -1,13 +1,15 @@
package types
import "time"
import (
"time"
)
type Checkin struct {
Id int `db:"id,omitempty"`
Service int64 `db:"service"`
Interval int64 `db:"check_interval"`
Api string `db:"api"`
CreatedAt time.Time `db:"created_at"`
Id int64 `gorm:"primary_key;column:id"`
Service int64 `gorm:"index;column:service"`
Interval int64 `gorm:"column:check_interval"`
Api string `gorm:"column:api"`
CreatedAt time.Time `gorm:"column:created_at"`
Hits int64 `json:"hits"`
Last time.Time `json:"last"`
CheckinInterface `json:"-"`

View File

@ -1,27 +1,29 @@
package types
import "time"
import (
"time"
)
type Core struct {
Name string `db:"name" json:"name"`
Description string `db:"description" json:"description,omitempty"`
Config string `db:"config" json:"-"`
ApiKey string `db:"api_key" json:"-"`
ApiSecret string `db:"api_secret" json:"-"`
Style string `db:"style" json:"style,omitempty"`
Footer string `db:"footer" json:"footer,omitempty"`
Domain string `db:"domain" json:"domain,omitempty"`
Version string `db:"version" json:"version"`
MigrationId int64 `db:"migration_id" json:"migration_id,omitempty"`
UseCdn bool `db:"use_cdn" json:"using_cdn,omitempty"`
DbConnection string `json:"database"`
Started time.Time `json:"started_on"`
dbServices []*Service `json:"services,omitempty"`
Plugins []Info `json:"-"`
Repos []PluginJSON `json:"-"`
AllPlugins []PluginActions `json:"-"`
Communications []AllNotifiers `json:"-"`
CoreInterface `json:"-"`
Name string `gorm:"column:name" json:"name"`
Description string `gorm:"column:description" json:"description,omitempty"`
Config string `gorm:"column:config" json:"-"`
ApiKey string `gorm:"column:api_key" json:"-"`
ApiSecret string `gorm:"column:api_secret" json:"-"`
Style string `gorm:"column:style" json:"style,omitempty"`
Footer string `gorm:"column:footer" json:"footer,omitempty"`
Domain string `gorm:"column:domain" json:"domain,omitempty"`
Version string `gorm:"column:version" json:"version"`
MigrationId int64 `gorm:"column:migration_id" json:"migration_id,omitempty"`
UseCdn bool `gorm:"column:use_cdn" json:"using_cdn,omitempty"`
DbConnection string `gorm:"-" json:database"`
Started time.Time `gorm:"-" json:started_on"`
dbServices []*Service `gorm:"-" json:services,omitempty"`
Plugins []Info `gorm:"-" json:-"`
Repos []PluginJSON `gorm:"-" json:-"`
AllPlugins []PluginActions `gorm:"-" json:-"`
Communications []AllNotifiers `gorm:"-" json:-"`
CoreInterface `gorm:"-" json:-"`
}
func (c *Core) SetServices(s []*Service) {

View File

@ -1,14 +1,16 @@
package types
import "time"
import (
"time"
)
type Failure struct {
Id int `db:"id,omitempty" json:"id"`
Issue string `db:"issue" json:"issue"`
Method string `db:"method" json:"method,omitempty"`
Service int64 `db:"service" json:"service_id"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
FailureInterface `json:"-"`
Id int64 `gorm:"primary_key;column:id" json:"id"`
Issue string `gorm:"column:issue" json:"issue"`
Method string `gorm:"column:method" json:"method,omitempty"`
Service int64 `gorm:"index;column:service" json:"service_id"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
FailureInterface `gorm:"-" json:"-"`
}
type FailureInterface interface {

View File

@ -20,33 +20,33 @@ import (
)
type Service struct {
Id int64 `db:"id,omitempty" json:"id"`
Name string `db:"name" json:"name"`
Domain string `db:"domain" json:"domain"`
Expected string `db:"expected" json:"expected"`
ExpectedStatus int `db:"expected_status" json:"expected_status"`
Interval int `db:"check_interval" json:"check_interval"`
Type string `db:"check_type" json:"type"`
Method string `db:"method" json:"method"`
PostData string `db:"post_data" json:"post_data"`
Port int `db:"port" json:"port"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
Timeout int `db:"timeout" json:"timeout"`
Order int `db:"order_id" json:"order_id"`
Online bool `json:"online"`
Latency float64 `json:"latency"`
Online24Hours float32 `json:"24_hours_online"`
AvgResponse string `json:"avg_response"`
TotalUptime string `json:"uptime"`
Failures []*Failure `json:"failures"`
Checkins []*Checkin `json:"checkins"`
Running chan bool `json:"-"`
Checkpoint time.Time `json:"-"`
LastResponse string `json:"-"`
LastStatusCode int `json:"status_code"`
LastOnline time.Time `json:"last_online"`
DnsLookup float64 `json:"dns_lookup_time"`
ServiceInterface `json:"-"`
Id int64 `gorm:"primary_key;column:id" json:"id"`
Name string `gorm:"column:name" json:"name"`
Domain string `gorm:"column:domain" json:"domain"`
Expected string `gorm:"column:expected" json:"expected"`
ExpectedStatus int `gorm:"column:expected_status" json:"expected_status"`
Interval int `gorm:"column:check_interval" json:"check_interval"`
Type string `gorm:"column:check_type" json:"type"`
Method string `gorm:"column:method" json:"method"`
PostData string `gorm:"column:post_data" json:"post_data"`
Port int `gorm:"column:port" json:"port"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
Timeout int `gorm:"column:timeout" json:"timeout"`
Order int `gorm:"column:order_id" json:"order_id"`
Online bool `gorm:"-" json:"online"`
Latency float64 `gorm:"-" json:"latency"`
Online24Hours float32 `gorm:"-" json:"24_hours_online"`
AvgResponse string `gorm:"-" json:"avg_response"`
TotalUptime string `gorm:"-" json:"uptime"`
Failures []*Failure `gorm:"-" json:"failures"`
Checkins []*Checkin `gorm:"-" json:"checkins"`
Running chan bool `gorm:"-" json:"-"`
Checkpoint time.Time `gorm:"-" json:"-"`
LastResponse string `gorm:"-" json:"-"`
LastStatusCode int `gorm:"-" json:"status_code"`
LastOnline time.Time `gorm:"-" json:"last_online"`
DnsLookup float64 `gorm:"-" json:"dns_lookup_time"`
ServiceInterface `gorm:"-" json:"-"`
}
type ServiceInterface interface {
@ -56,6 +56,7 @@ type ServiceInterface interface {
Delete() error
// Basic Method functions
AvgTime() float64
OnlineSince(time.Time) float32
Online24() float32
SmallText() string
GraphData() string
@ -65,13 +66,15 @@ type ServiceInterface interface {
CreateFailure(*Failure) (int64, error)
LimitedFailures() []*Failure
AllFailures() []*Failure
TotalFailuresSince(time.Time) (uint64, error)
TotalFailures24() (uint64, error)
TotalFailures() (uint64, error)
TotalFailures24Hours() (uint64, error)
DeleteFailures()
// Hits functions (successful responses)
CreateHit(*Hit) (int64, error)
Hits() ([]*Hit, error)
TotalHits() (uint64, error)
TotalHitsSince(time.Time) (uint64, error)
Sum() (float64, error)
LimitedHits() ([]*Hit, error)
SelectHitsGroupBy(string) ([]*Hit, error)

View File

@ -16,9 +16,9 @@
package types
import (
"github.com/jinzhu/gorm"
"net/http"
"time"
"upper.io/db.v3/lib/sqlbuilder"
)
type PluginInfo struct {
@ -41,7 +41,7 @@ type Info struct {
type PluginActions interface {
GetInfo() Info
GetForm() string
OnLoad(sqlbuilder.Database)
OnLoad(db gorm.DB)
SetInfo(map[string]interface{}) Info
Routes() []Routing
OnSave(map[string]interface{})
@ -62,20 +62,10 @@ type PluginActions interface {
type AllNotifiers interface{}
type Hit struct {
Id int `db:"id,omitempty"`
Service int64 `db:"service"`
Latency float64 `db:"latency"`
CreatedAt time.Time `db:"created_at"`
}
type Config struct {
Connection string `yaml:"connection"`
Host string `yaml:"host"`
Database string `yaml:"database"`
User string `yaml:"user"`
Password string `yaml:"password"`
Port string `yaml:"port"`
Secret string `yaml:"secret"`
Id int64 `gorm:"primary_key;column:id"`
Service int64 `gorm:"index;column:service"`
Latency float64 `gorm:"column:latency"`
CreatedAt time.Time `gorm:"column:created_at"`
}
type DbConfig struct {

View File

@ -1,17 +1,19 @@
package types
import "time"
import (
"time"
)
type User struct {
Id int64 `db:"id,omitempty" json:"id"`
Username string `db:"username" json:"username"`
Password string `db:"password" json:"-"`
Email string `db:"email" json:"-"`
ApiKey string `db:"api_key" json:"api_key"`
ApiSecret string `db:"api_secret" json:"-"`
Admin bool `db:"administrator" json:"admin"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
UserInterface `json:"-"`
Id int64 `gorm:"primary_key;column:id" json:"id"`
Username string `gorm:"type:varchar(100);unique;column:username;" json:"username"`
Password string `gorm:"column:password" json:"-"`
Email string `gorm:"type:varchar(100);unique;column:email" json:"-"`
ApiKey string `gorm:"column:api_key" json:"api_key"`
ApiSecret string `gorm:"column:api_secret" json:"-"`
Admin bool `gorm:"column:administrator" json:"admin"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
UserInterface `gorm:"-" json:"-"`
}
type UserInterface interface {

View File

@ -34,6 +34,10 @@ var (
LockLines sync.Mutex
)
func Logger() *lumberjack.Logger {
return ljLogger
}
func createLog(dir string) error {
var err error
_, err = os.Stat(dir + "/logs")

View File

@ -16,8 +16,11 @@
package utils
import (
"errors"
"github.com/ararog/timeago"
"io"
"os"
"os/exec"
"regexp"
"strconv"
"strings"
@ -97,6 +100,7 @@ func FileExists(name string) bool {
}
func DeleteFile(file string) error {
Log(1, "deleting file: "+file)
err := os.Remove(file)
if err != nil {
return err
@ -107,3 +111,56 @@ func DeleteFile(file string) error {
func DeleteDirectory(directory string) error {
return os.RemoveAll(directory)
}
func Command(cmd string) (string, string, error) {
Log(1, "running command: "+cmd)
testCmd := exec.Command("sh", "-c", cmd)
var stdout, stderr []byte
var errStdout, errStderr error
stdoutIn, _ := testCmd.StdoutPipe()
stderrIn, _ := testCmd.StderrPipe()
testCmd.Start()
go func() {
stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn)
}()
go func() {
stderr, errStderr = copyAndCapture(os.Stderr, stderrIn)
}()
err := testCmd.Wait()
if err != nil {
return "", "", err
}
if errStdout != nil || errStderr != nil {
return "", "", errors.New("failed to capture stdout or stderr")
}
outStr, errStr := string(stdout), string(stderr)
return outStr, errStr, err
}
func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
var out []byte
buf := make([]byte, 1024, 1024)
for {
n, err := r.Read(buf[:])
if n > 0 {
d := buf[:n]
out = append(out, d...)
_, err := w.Write(d)
if err != nil {
return out, err
}
}
if err != nil {
// Read returns io.EOF at the end of file, which is not an error for us
if err == io.EOF {
err = nil
}
return out, err
}
}
}