mirror of https://github.com/statping/statping
refactor types - cypress testing docker image
parent
625b5d4b18
commit
c16749444d
14
Makefile
14
Makefile
|
@ -1,4 +1,4 @@
|
|||
VERSION=0.46
|
||||
VERSION=0.47
|
||||
BINARY_NAME=statup
|
||||
GOPATH:=$(GOPATH)
|
||||
GOCMD=go
|
||||
|
@ -72,10 +72,10 @@ docker-run: docker
|
|||
docker-dev: clean
|
||||
docker build -t hunterlong/statup:dev -f dev/Dockerfile-dev .
|
||||
|
||||
docker-push-dev: docker-base docker-dev docker-test
|
||||
docker-push-dev: docker-base docker-dev docker-cypress
|
||||
docker push hunterlong/statup:dev
|
||||
docker push hunterlong/statup:base
|
||||
docker push hunterlong/statup:test
|
||||
docker push hunterlong/statup:cypress
|
||||
|
||||
docker-push-latest: docker
|
||||
docker push hunterlong/statup:latest
|
||||
|
@ -84,14 +84,16 @@ docker-run-dev: docker-dev
|
|||
docker run -t -p 8080:8080 hunterlong/statup:dev
|
||||
|
||||
docker-cypress: clean
|
||||
docker build -t hunterlong/statup:test -f dev/Dockerfile-cypress .
|
||||
GOPATH=$(GOPATH) xgo -out statup -go 1.10.x -ldflags "-X main.VERSION=$(VERSION) -X main.COMMIT=$(TRAVIS_COMMIT)" --targets=linux/amd64 ./cmd
|
||||
docker build -t hunterlong/statup:cypress -f dev/Dockerfile-cypress .
|
||||
rm -f statup
|
||||
|
||||
docker-run-cypress: docker-cypress
|
||||
docker run -t -p 8080:8080 --entrypoint "go test -v -p=1 $(BUILDVERSION) ./..." hunterlong/statup:test
|
||||
docker run -t hunterlong/statup:cypress
|
||||
|
||||
docker-base: clean
|
||||
wget -q https://assets.statup.io/sass && chmod +x sass
|
||||
$(XGO) --targets=linux/amd64 -ldflags="-X main.VERSION=$(VERSION) -X main.COMMIT=$(TRAVIS_COMMIT) -linkmode external -extldflags -static" -out alpine ./cmd
|
||||
$(XGO) --targets=linux/amd64 -ldflags="-X main.VERSION=$(VERSION) -linkmode external -extldflags -static" -out alpine ./cmd
|
||||
docker build -t hunterlong/statup:base -f dev/Dockerfile-base .
|
||||
|
||||
docker-build-base:
|
||||
|
|
32
cmd/cli.go
32
cmd/cli.go
|
@ -140,12 +140,12 @@ func RunOnce() {
|
|||
if err != nil {
|
||||
fmt.Println("Core database was not found, Statup is not setup yet.")
|
||||
}
|
||||
core.CoreApp.Services, err = core.SelectAllServices()
|
||||
core.CoreApp.SelectAllServices()
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
for _, s := range core.CoreApp.Services {
|
||||
out := core.ServiceCheck(s, true)
|
||||
for _, s := range core.CoreApp.DbServices {
|
||||
out := core.ServiceCheck(core.ReturnService(s), true)
|
||||
fmt.Printf(" Service %v | URL: %v | Latency: %0.0fms | Online: %v\n", out.Name, out.Domain, (out.Latency * 1000), out.Online)
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ func TestPlugin(plug types.PluginActions) {
|
|||
core.OnSuccess(core.SelectService(1))
|
||||
fmt.Println("\n" + BRAKER)
|
||||
fmt.Println(POINT + "Sending 'OnFailure(Service, FailureData)'")
|
||||
fakeFailD := core.FailureData{
|
||||
fakeFailD := &types.Failure{
|
||||
Issue: "No issue, just testing this plugin. This would include HTTP failure information though",
|
||||
}
|
||||
core.OnFailure(core.SelectService(1), fakeFailD)
|
||||
|
@ -260,14 +260,14 @@ func FakeSeed(plug types.PluginActions) {
|
|||
Domain: "https://google.com",
|
||||
Method: "GET",
|
||||
}}
|
||||
core.CreateService(fakeSrv)
|
||||
fakeSrv.Create()
|
||||
|
||||
fakeSrv2 := &core.Service{Service: &types.Service{
|
||||
Name: "Awesome Plugin Service",
|
||||
Domain: "https://netflix.com",
|
||||
Method: "GET",
|
||||
}}
|
||||
core.CreateService(fakeSrv2)
|
||||
fakeSrv2.Create()
|
||||
|
||||
fakeUser := &types.User{
|
||||
Id: 6334,
|
||||
|
@ -277,7 +277,7 @@ func FakeSeed(plug types.PluginActions) {
|
|||
Admin: true,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
core.CreateUser(fakeUser)
|
||||
fakeUser.Create()
|
||||
|
||||
fakeUser = &types.User{
|
||||
Id: 6335,
|
||||
|
@ -286,28 +286,28 @@ func FakeSeed(plug types.PluginActions) {
|
|||
Email: "info@awesome.com",
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
core.CreateUser(fakeUser)
|
||||
fakeUser.Create()
|
||||
|
||||
for i := 0; i <= 50; i++ {
|
||||
dd := core.HitData{
|
||||
dd := &types.Hit{
|
||||
Latency: rand.Float64(),
|
||||
}
|
||||
core.CreateServiceHit(fakeSrv, dd)
|
||||
fakeSrv.CreateHit(dd)
|
||||
|
||||
dd = core.HitData{
|
||||
dd = &types.Hit{
|
||||
Latency: rand.Float64(),
|
||||
}
|
||||
core.CreateServiceHit(fakeSrv2, dd)
|
||||
fakeSrv2.CreateHit(dd)
|
||||
|
||||
fail := core.FailureData{
|
||||
fail := &types.Failure{
|
||||
Issue: "This is not an issue, but it would container HTTP response errors.",
|
||||
}
|
||||
core.CreateServiceFailure(fakeSrv, fail)
|
||||
fakeSrv.CreateFailure(fail)
|
||||
|
||||
fail = core.FailureData{
|
||||
fail = &types.Failure{
|
||||
Issue: "HTTP Status Code 521 did not match 200",
|
||||
}
|
||||
core.CreateServiceFailure(fakeSrv, fail)
|
||||
fakeSrv.CreateFailure(fail)
|
||||
}
|
||||
|
||||
fmt.Println("Seeding example data is complete, running Plugin Tests")
|
||||
|
|
|
@ -85,7 +85,7 @@ func TestRunAll(t *testing.T) {
|
|||
t.Run(dbt+" Select Core", func(t *testing.T) {
|
||||
RunSelectCoreMYQL(t, dbt)
|
||||
})
|
||||
t.Run(dbt+" Select Services", func(t *testing.T) {
|
||||
t.Run(dbt+" Select DbServices", func(t *testing.T) {
|
||||
RunSelectAllMysqlServices(t)
|
||||
})
|
||||
t.Run(dbt+" Select Comms", func(t *testing.T) {
|
||||
|
@ -104,7 +104,7 @@ func TestRunAll(t *testing.T) {
|
|||
t.Run(dbt+" Select Users", func(t *testing.T) {
|
||||
RunUser_SelectAll(t)
|
||||
})
|
||||
t.Run(dbt+" Select Services", func(t *testing.T) {
|
||||
t.Run(dbt+" Select DbServices", func(t *testing.T) {
|
||||
RunSelectAllServices(t)
|
||||
})
|
||||
t.Run(dbt+" Select One Service", func(t *testing.T) {
|
||||
|
@ -116,6 +116,9 @@ func TestRunAll(t *testing.T) {
|
|||
t.Run(dbt+" Create Hits", func(t *testing.T) {
|
||||
RunCreateService_Hits(t)
|
||||
})
|
||||
t.Run(dbt+" Service ToJSON()", func(t *testing.T) {
|
||||
RunService_ToJSON(t)
|
||||
})
|
||||
t.Run(dbt+" Avg Time", func(t *testing.T) {
|
||||
RunService_AvgTime(t)
|
||||
})
|
||||
|
@ -265,7 +268,7 @@ func RunSelectCoreMYQL(t *testing.T, db string) {
|
|||
|
||||
func RunSelectAllMysqlServices(t *testing.T) {
|
||||
var err error
|
||||
services, err := core.SelectAllServices()
|
||||
services, err := core.CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(services))
|
||||
}
|
||||
|
@ -285,22 +288,22 @@ func RunUser_SelectAll(t *testing.T) {
|
|||
}
|
||||
|
||||
func RunUser_Create(t *testing.T) {
|
||||
user := &types.User{
|
||||
user := core.ReturnUser(&types.User{
|
||||
Username: "admin",
|
||||
Password: "admin",
|
||||
Email: "info@testuser.com",
|
||||
Admin: true,
|
||||
}
|
||||
id, err := core.CreateUser(user)
|
||||
})
|
||||
id, err := user.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(1), id)
|
||||
user2 := &types.User{
|
||||
user2 := core.ReturnUser(&types.User{
|
||||
Username: "superadmin",
|
||||
Password: "admin",
|
||||
Email: "info@adminer.com",
|
||||
Admin: true,
|
||||
}
|
||||
id, err = core.CreateUser(user2)
|
||||
})
|
||||
id, err = user2.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(2), id)
|
||||
}
|
||||
|
@ -309,7 +312,7 @@ func RunUser_Update(t *testing.T) {
|
|||
user, err := core.SelectUser(1)
|
||||
user.Email = "info@updatedemail.com"
|
||||
assert.Nil(t, err)
|
||||
err = core.UpdateUser(user)
|
||||
err = user.Update()
|
||||
assert.Nil(t, err)
|
||||
updatedUser, err := core.SelectUser(1)
|
||||
assert.Nil(t, err)
|
||||
|
@ -317,12 +320,12 @@ func RunUser_Update(t *testing.T) {
|
|||
}
|
||||
|
||||
func RunUser_NonUniqueCreate(t *testing.T) {
|
||||
user := &types.User{
|
||||
user := core.ReturnUser(&types.User{
|
||||
Username: "admin",
|
||||
Password: "admin",
|
||||
Email: "info@testuser.com",
|
||||
}
|
||||
admin, err := core.CreateUser(user)
|
||||
})
|
||||
admin, err := user.Create()
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, admin)
|
||||
}
|
||||
|
@ -331,13 +334,13 @@ func RunUser_Delete(t *testing.T) {
|
|||
user, err := core.SelectUser(2)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, user)
|
||||
err = core.DeleteUser(user)
|
||||
err = user.Delete()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func RunSelectAllServices(t *testing.T) {
|
||||
var err error
|
||||
services, err := core.SelectAllServices()
|
||||
services, err := core.CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(services))
|
||||
}
|
||||
|
@ -360,12 +363,19 @@ func RunService_Create(t *testing.T) {
|
|||
Method: "GET",
|
||||
Timeout: 30,
|
||||
}}
|
||||
id, err := core.CreateService(service)
|
||||
id, err := service.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(6), id)
|
||||
t.Log(service)
|
||||
}
|
||||
|
||||
func RunService_ToJSON(t *testing.T) {
|
||||
service := core.SelectService(1)
|
||||
assert.NotNil(t, service)
|
||||
jsoned := service.ToJSON()
|
||||
assert.NotEmpty(t, jsoned)
|
||||
}
|
||||
|
||||
func RunService_AvgTime(t *testing.T) {
|
||||
service := core.SelectService(1)
|
||||
assert.NotNil(t, service)
|
||||
|
@ -401,7 +411,7 @@ func RunBadService_Create(t *testing.T) {
|
|||
Method: "GET",
|
||||
Timeout: 30,
|
||||
}}
|
||||
id, err := core.CreateService(service)
|
||||
id, err := service.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, int64(7), id)
|
||||
}
|
||||
|
@ -422,14 +432,14 @@ func RunDeleteService(t *testing.T) {
|
|||
assert.Equal(t, "JSON API Tester", service.Name)
|
||||
assert.True(t, service.IsRunning())
|
||||
t.Log(service.Running)
|
||||
err := core.DeleteService(service)
|
||||
err := service.Delete()
|
||||
t.Log(service.Running)
|
||||
assert.False(t, service.IsRunning())
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func RunCreateService_Hits(t *testing.T) {
|
||||
services, err := core.SelectAllServices()
|
||||
services, err := core.CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, services)
|
||||
assert.Equal(t, 6, len(services))
|
||||
|
@ -437,9 +447,9 @@ func RunCreateService_Hits(t *testing.T) {
|
|||
for _, s := range services {
|
||||
var service *core.Service
|
||||
if s.Type == "http" {
|
||||
service = core.ServiceHTTPCheck(s, true)
|
||||
service = core.ServiceHTTPCheck(core.ReturnService(s), true)
|
||||
} else {
|
||||
service = core.ServiceTCPCheck(s, true)
|
||||
service = core.ServiceTCPCheck(core.ReturnService(s), true)
|
||||
}
|
||||
assert.NotNil(t, service)
|
||||
}
|
||||
|
|
|
@ -31,15 +31,16 @@ import (
|
|||
type FailureData types.FailureData
|
||||
|
||||
func CheckServices() {
|
||||
CoreApp.Services, _ = SelectAllServices()
|
||||
utils.Log(1, fmt.Sprintf("Starting monitoring process for %v Services", len(CoreApp.Services)))
|
||||
for _, s := range CoreApp.Services {
|
||||
CoreApp.SelectAllServices()
|
||||
utils.Log(1, fmt.Sprintf("Starting monitoring process for %v DbServices", len(CoreApp.DbServices)))
|
||||
for _, ser := range CoreApp.DbServices {
|
||||
//go obj.StartCheckins()
|
||||
go CheckQueue(s, true)
|
||||
s := ReturnService(ser)
|
||||
go s.CheckQueue(true)
|
||||
}
|
||||
}
|
||||
|
||||
func CheckQueue(s *Service, record bool) {
|
||||
func (s *Service) CheckQueue(record bool) {
|
||||
CheckLoop:
|
||||
for {
|
||||
select {
|
||||
|
@ -188,21 +189,21 @@ type HitData struct {
|
|||
func RecordSuccess(s *Service) {
|
||||
s.Online = true
|
||||
s.LastOnline = time.Now()
|
||||
data := HitData{
|
||||
data := &types.Hit{
|
||||
Latency: s.Latency,
|
||||
}
|
||||
utils.Log(1, fmt.Sprintf("Service %v Successful: %0.2f ms", s.Name, data.Latency*1000))
|
||||
CreateServiceHit(s, data)
|
||||
s.CreateHit(data)
|
||||
OnSuccess(s)
|
||||
}
|
||||
|
||||
func RecordFailure(s *Service, issue string) {
|
||||
s.Online = false
|
||||
data := FailureData{
|
||||
data := &types.Failure{
|
||||
Issue: issue,
|
||||
}
|
||||
utils.Log(2, fmt.Sprintf("Service %v Failing: %v", s.Name, issue))
|
||||
CreateServiceFailure(s, data)
|
||||
s.CreateFailure(data)
|
||||
//SendFailureEmail(s)
|
||||
OnFailure(s, data)
|
||||
}
|
||||
|
|
|
@ -23,14 +23,20 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type Checkin types.Checkin
|
||||
type Checkin struct {
|
||||
*types.Checkin
|
||||
}
|
||||
|
||||
func (c *Checkin) String() string {
|
||||
return c.Api
|
||||
}
|
||||
|
||||
func ReturnCheckin(s *types.Checkin) *Checkin {
|
||||
return &Checkin{Checkin: s}
|
||||
}
|
||||
|
||||
func FindCheckin(api string) *types.Checkin {
|
||||
for _, ser := range CoreApp.Services {
|
||||
for _, ser := range CoreApp.DbServices {
|
||||
for _, c := range ser.Checkins {
|
||||
if c.Api == api {
|
||||
return c
|
||||
|
@ -40,7 +46,7 @@ func FindCheckin(api string) *types.Checkin {
|
|||
return nil
|
||||
}
|
||||
|
||||
func SelectAllCheckins(s *types.Service) []*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)
|
||||
|
@ -116,7 +122,7 @@ func (f *Checkin) Ago() string {
|
|||
//}
|
||||
//
|
||||
//func CheckinProcess() {
|
||||
// for _, s := range CoreApp.Services {
|
||||
// for _, s := range CoreApp.DbServices {
|
||||
// for _, c := range s.Checkins {
|
||||
// checkin := c
|
||||
// go checkin.Run()
|
||||
|
|
|
@ -125,7 +125,7 @@ func LoadUsingEnv() (*types.Config, error) {
|
|||
Email: "info@admin.com",
|
||||
Admin: true,
|
||||
}
|
||||
CreateUser(admin)
|
||||
admin.Create()
|
||||
|
||||
LoadSampleData()
|
||||
|
||||
|
|
15
core/core.go
15
core/core.go
|
@ -30,7 +30,6 @@ type PluginRepos types.PluginRepos
|
|||
|
||||
type Core struct {
|
||||
*types.Core
|
||||
Services []*Service
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -64,7 +63,7 @@ func (c *Core) ToCore() *types.Core {
|
|||
func InitApp() {
|
||||
SelectCore()
|
||||
InsertNotifierDB()
|
||||
SelectAllServices()
|
||||
CoreApp.SelectAllServices()
|
||||
CheckServices()
|
||||
CoreApp.Communications = notifiers.Load()
|
||||
go DatabaseMaintence()
|
||||
|
@ -113,7 +112,7 @@ func (c Core) MobileSASS() string {
|
|||
}
|
||||
|
||||
func (c Core) AllOnline() bool {
|
||||
for _, s := range CoreApp.Services {
|
||||
for _, s := range CoreApp.DbServices {
|
||||
if !s.Online {
|
||||
return false
|
||||
}
|
||||
|
@ -146,10 +145,18 @@ func SelectCore() (*Core, error) {
|
|||
CoreApp.Core = c
|
||||
CoreApp.DbConnection = Configs.Connection
|
||||
CoreApp.Version = VERSION
|
||||
CoreApp.Services, _ = SelectAllServices()
|
||||
CoreApp.SelectAllServices()
|
||||
if os.Getenv("USE_CDN") == "true" {
|
||||
CoreApp.UseCdn = true
|
||||
}
|
||||
//store = sessions.NewCookieStore([]byte(core.ApiSecret))
|
||||
return CoreApp, err
|
||||
}
|
||||
|
||||
func (c *Core) Services() []*Service {
|
||||
var services []*Service
|
||||
for _, ser := range CoreApp.DbServices {
|
||||
services = append(services, ReturnService(ser))
|
||||
}
|
||||
return services
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ func OnSuccess(s *Service) {
|
|||
// TODO convert notifiers to correct type
|
||||
}
|
||||
|
||||
func OnFailure(s *Service, f FailureData) {
|
||||
func OnFailure(s *Service, f *types.Failure) {
|
||||
for _, p := range CoreApp.AllPlugins {
|
||||
p.OnFailure(structs.Map(s))
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func OnSettingsSaved(c *types.Core) {
|
|||
}
|
||||
}
|
||||
|
||||
func OnNewUser(u *types.User) {
|
||||
func OnNewUser(u *User) {
|
||||
for _, p := range CoreApp.AllPlugins {
|
||||
p.OnNewUser(structs.Map(u))
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
func ExportIndexHTML() string {
|
||||
source.Assets()
|
||||
CoreApp.UseCdn = true
|
||||
//out := index{*CoreApp, CoreApp.Services}
|
||||
//out := index{*CoreApp, CoreApp.DbServices}
|
||||
nav, _ := source.TmplBox.String("nav.html")
|
||||
footer, _ := source.TmplBox.String("footer.html")
|
||||
render, err := source.TmplBox.String("index.html")
|
||||
|
|
|
@ -24,17 +24,19 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func CreateServiceFailure(s *Service, data FailureData) (int64, error) {
|
||||
fail := &types.Failure{
|
||||
Issue: data.Issue,
|
||||
Service: s.Id,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
s.Failures = append(s.Failures, fail)
|
||||
type Failure struct {
|
||||
*types.Failure
|
||||
}
|
||||
|
||||
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(fail)
|
||||
uuid, err := col.Insert(f)
|
||||
if err != nil {
|
||||
utils.Log(3, err)
|
||||
return 0, err
|
||||
}
|
||||
if uuid == nil {
|
||||
return 0, err
|
||||
|
@ -42,12 +44,13 @@ func CreateServiceFailure(s *Service, data FailureData) (int64, error) {
|
|||
return uuid.(int64), err
|
||||
}
|
||||
|
||||
func SelectAllFailures(s *types.Service) []*types.Failure {
|
||||
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 {
|
||||
utils.Log(3, fmt.Sprintf("Issue getting failures for service %v, %v", s.Name, err))
|
||||
return nil
|
||||
}
|
||||
return fails
|
||||
}
|
||||
|
@ -62,31 +65,25 @@ func DeleteFailures(u *Service) {
|
|||
}
|
||||
|
||||
func (s *Service) LimitedFailures() []*Failure {
|
||||
var fails []*types.Failure
|
||||
var failArr []*Failure
|
||||
col := DbSession.Collection("failures").Find("service", s.Id).OrderBy("-id").Limit(10)
|
||||
col.All(&fails)
|
||||
for _, f := range fails {
|
||||
failArr = append(failArr, MakeFailure(f))
|
||||
}
|
||||
col.All(&failArr)
|
||||
return failArr
|
||||
}
|
||||
|
||||
func reverseFailures(input []*types.Failure) []*types.Failure {
|
||||
func reverseFailures(input []*Failure) []*Failure {
|
||||
if len(input) == 0 {
|
||||
return input
|
||||
}
|
||||
return append(reverseFailures(input[1:]), input[0])
|
||||
}
|
||||
|
||||
func (fail *Failure) Ago() string {
|
||||
f := fail.ToFailure()
|
||||
func (f *Failure) Ago() string {
|
||||
got, _ := timeago.TimeAgoWithTime(time.Now(), f.CreatedAt)
|
||||
return got
|
||||
}
|
||||
|
||||
func (fail *Failure) Delete() error {
|
||||
f := fail.ToFailure()
|
||||
func (f *Failure) Delete() error {
|
||||
col := DbSession.Collection("failures").Find("id", f.Id)
|
||||
return col.Delete()
|
||||
}
|
||||
|
@ -113,17 +110,7 @@ func (s *Service) TotalFailures24Hours() (uint64, error) {
|
|||
return amount, err
|
||||
}
|
||||
|
||||
func (f *Failure) ToFailure() *types.Failure {
|
||||
return f.F.(*types.Failure)
|
||||
}
|
||||
|
||||
func MakeFailure(f *types.Failure) *Failure {
|
||||
fail := &Failure{f}
|
||||
return fail
|
||||
}
|
||||
|
||||
func (fail *Failure) ParseError() string {
|
||||
f := fail.ToFailure()
|
||||
func (f *Failure) ParseError() string {
|
||||
err := strings.Contains(f.Issue, "operation timed out")
|
||||
if err {
|
||||
return fmt.Sprintf("HTTP Request Timed Out")
|
||||
|
|
21
core/hits.go
21
core/hits.go
|
@ -22,18 +22,17 @@ import (
|
|||
"upper.io/db.v3"
|
||||
)
|
||||
|
||||
type Hit types.Hit
|
||||
type Hit struct {
|
||||
*types.Hit
|
||||
}
|
||||
|
||||
func hitCol() db.Collection {
|
||||
return DbSession.Collection("hits")
|
||||
}
|
||||
|
||||
func CreateServiceHit(s *Service, d HitData) (int64, error) {
|
||||
h := Hit{
|
||||
Service: s.Id,
|
||||
Latency: d.Latency,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
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)
|
||||
|
@ -42,8 +41,8 @@ func CreateServiceHit(s *Service, d HitData) (int64, error) {
|
|||
return uuid.(int64), err
|
||||
}
|
||||
|
||||
func (s *Service) Hits() ([]Hit, error) {
|
||||
var hits []Hit
|
||||
func (s *Service) Hits() ([]*Hit, error) {
|
||||
var hits []*Hit
|
||||
col := hitCol().Find("service", s.Id).OrderBy("-id")
|
||||
err := col.All(&hits)
|
||||
return hits, err
|
||||
|
@ -63,8 +62,8 @@ func reverseHits(input []*Hit) []*Hit {
|
|||
return append(reverseHits(input[1:]), input[0])
|
||||
}
|
||||
|
||||
func (s *Service) SelectHitsGroupBy(group string) ([]Hit, error) {
|
||||
var hits []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
|
||||
|
|
105
core/services.go
105
core/services.go
|
@ -29,8 +29,8 @@ type Service struct {
|
|||
*types.Service
|
||||
}
|
||||
|
||||
type Failure struct {
|
||||
F interface{}
|
||||
func ReturnService(s *types.Service) *Service {
|
||||
return &Service{Service: s}
|
||||
}
|
||||
|
||||
func serviceCol() db.Collection {
|
||||
|
@ -38,32 +38,37 @@ func serviceCol() db.Collection {
|
|||
}
|
||||
|
||||
func SelectService(id int64) *Service {
|
||||
for _, s := range CoreApp.Services {
|
||||
for _, s := range CoreApp.DbServices {
|
||||
if s.Id == id {
|
||||
return s
|
||||
return ReturnService(s)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SelectAllServices() ([]*Service, error) {
|
||||
func (c *Core) SelectAllServices() ([]*types.Service, error) {
|
||||
var services []*types.Service
|
||||
var sers []*Service
|
||||
var servs []*types.Service
|
||||
col := serviceCol().Find()
|
||||
err := col.All(&services)
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("service error: %v", err))
|
||||
return nil, err
|
||||
}
|
||||
for _, s := range services {
|
||||
ser := NewService(s)
|
||||
ser.Start()
|
||||
ser.Checkins = SelectAllCheckins(s)
|
||||
ser.Failures = SelectAllFailures(s)
|
||||
sers = append(sers, ser)
|
||||
for _, ser := range services {
|
||||
single := ReturnService(ser)
|
||||
single.Start()
|
||||
single.AllCheckins()
|
||||
single.AllFailures()
|
||||
servs = append(servs, single.Service)
|
||||
}
|
||||
CoreApp.Services = sers
|
||||
return sers, err
|
||||
CoreApp.DbServices = servs
|
||||
return services, err
|
||||
}
|
||||
|
||||
func (s *Service) ToJSON() string {
|
||||
data, _ := json.Marshal(s)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (s *Service) AvgTime() float64 {
|
||||
|
@ -104,8 +109,10 @@ type DateScan struct {
|
|||
Value int64 `json:"y"`
|
||||
}
|
||||
|
||||
func NewService(s *types.Service) *Service {
|
||||
return &Service{s}
|
||||
func (s *Service) lastFailure() *Failure {
|
||||
limited := s.LimitedFailures()
|
||||
last := limited[len(limited)-1]
|
||||
return last
|
||||
}
|
||||
|
||||
func (s *Service) SmallText() string {
|
||||
|
@ -119,8 +126,8 @@ func (s *Service) SmallText() string {
|
|||
}
|
||||
}
|
||||
if len(last) > 0 {
|
||||
lastFailure := MakeFailure(last[0].ToFailure())
|
||||
return fmt.Sprintf("%v on %v", lastFailure.ParseError(), last[0].ToFailure().CreatedAt.Format("Monday 3:04PM, Jan _2 2006"))
|
||||
lastFailure := s.lastFailure()
|
||||
return fmt.Sprintf("%v on %v", lastFailure.ParseError(), last[0].CreatedAt.Format("Monday 3:04PM, Jan _2 2006"))
|
||||
} else {
|
||||
return fmt.Sprintf("%v is currently offline", s.Name)
|
||||
}
|
||||
|
@ -142,9 +149,7 @@ func GroupDataBy(column string, id int64, tm time.Time, increment string) string
|
|||
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))
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
|
@ -196,18 +201,29 @@ func (s *Service) AvgUptime() string {
|
|||
return s.TotalUptime
|
||||
}
|
||||
|
||||
func RemoveArray(u *Service) []*Service {
|
||||
var srvcs []*Service
|
||||
for _, s := range CoreApp.Services {
|
||||
func RemoveArray(u *Service) []*types.Service {
|
||||
var srvcs []*types.Service
|
||||
for _, s := range CoreApp.DbServices {
|
||||
if s.Id != u.Id {
|
||||
srvcs = append(srvcs, s)
|
||||
}
|
||||
}
|
||||
CoreApp.Services = srvcs
|
||||
CoreApp.DbServices = srvcs
|
||||
return srvcs
|
||||
}
|
||||
|
||||
func DeleteService(u *Service) error {
|
||||
func updateService(new *Service) {
|
||||
var services []*types.Service
|
||||
for _, s := range CoreApp.DbServices {
|
||||
if s.Id == new.Id {
|
||||
s = new.Service
|
||||
}
|
||||
services = append(services, s)
|
||||
}
|
||||
CoreApp.DbServices = services
|
||||
}
|
||||
|
||||
func (u *Service) Delete() error {
|
||||
res := serviceCol().Find("id", u.Id)
|
||||
err := res.Delete()
|
||||
if err != nil {
|
||||
|
@ -220,36 +236,25 @@ func DeleteService(u *Service) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func UpdateService(service *Service) *Service {
|
||||
service.CreatedAt = time.Now()
|
||||
res := serviceCol().Find("id", service.Id)
|
||||
err := res.Update(service)
|
||||
func (u *Service) Update() error {
|
||||
u.CreatedAt = time.Now()
|
||||
res := serviceCol().Find("id", u.Id)
|
||||
err := res.Update(u)
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Failed to update service %v. %v", service.Name, err))
|
||||
return service
|
||||
utils.Log(3, fmt.Sprintf("Failed to update service %v. %v", u.Name, err))
|
||||
return err
|
||||
}
|
||||
updateService(service)
|
||||
CoreApp.Services, err = SelectAllServices()
|
||||
updateService(u)
|
||||
CoreApp.SelectAllServices()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("error selecting all services: %v", err))
|
||||
return service
|
||||
return err
|
||||
}
|
||||
OnUpdateService(service)
|
||||
return service
|
||||
OnUpdateService(u)
|
||||
return err
|
||||
}
|
||||
|
||||
func updateService(new *Service) {
|
||||
var services []*Service
|
||||
for _, s := range CoreApp.Services {
|
||||
if s.Id == new.Id {
|
||||
s = new
|
||||
}
|
||||
services = append(services, s)
|
||||
}
|
||||
CoreApp.Services = services
|
||||
}
|
||||
|
||||
func CreateService(u *Service) (int64, error) {
|
||||
func (u *Service) Create() (int64, error) {
|
||||
u.CreatedAt = time.Now()
|
||||
uuid, err := serviceCol().Insert(u)
|
||||
if uuid == nil {
|
||||
|
@ -258,13 +263,13 @@ func CreateService(u *Service) (int64, error) {
|
|||
}
|
||||
u.Id = uuid.(int64)
|
||||
u.Start()
|
||||
CoreApp.Services = append(CoreApp.Services, u)
|
||||
CoreApp.DbServices = append(CoreApp.DbServices, u.Service)
|
||||
return uuid.(int64), err
|
||||
}
|
||||
|
||||
func CountOnline() int {
|
||||
amount := 0
|
||||
for _, s := range CoreApp.Services {
|
||||
for _, s := range CoreApp.DbServices {
|
||||
if s.Online {
|
||||
amount++
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ var (
|
|||
)
|
||||
|
||||
func TestSelectAllServices(t *testing.T) {
|
||||
services, err := SelectAllServices()
|
||||
services, err := CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 5, len(services))
|
||||
}
|
||||
|
@ -49,19 +49,19 @@ func TestUpdateService(t *testing.T) {
|
|||
assert.Equal(t, "Google", service.Name)
|
||||
srv := service
|
||||
srv.Name = "Updated Google"
|
||||
newService := UpdateService(srv)
|
||||
assert.Equal(t, "Updated Google", newService.Name)
|
||||
err := srv.Update()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestUpdateAllServices(t *testing.T) {
|
||||
services, err := SelectAllServices()
|
||||
services, err := CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
for k, s := range services {
|
||||
srv := s
|
||||
srv := ReturnService(s)
|
||||
srv.Name = "Changed " + srv.Name
|
||||
srv.Interval = k + 3
|
||||
newService := UpdateService(srv)
|
||||
assert.Contains(t, newService.Name, "Changed")
|
||||
err := srv.Update()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ func TestCountOnline(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCreateService(t *testing.T) {
|
||||
s := &Service{&types.Service{
|
||||
s := ReturnService(&types.Service{
|
||||
Name: "That'll do 🐢",
|
||||
Domain: "https://www.youtube.com/watch?v=rjQtzV9IZ0Q",
|
||||
ExpectedStatus: 200,
|
||||
|
@ -154,9 +154,9 @@ func TestCreateService(t *testing.T) {
|
|||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 20,
|
||||
}}
|
||||
})
|
||||
var err error
|
||||
newServiceId, err = CreateService(s)
|
||||
newServiceId, err = s.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, newServiceId)
|
||||
newService := SelectService(newServiceId)
|
||||
|
@ -170,7 +170,7 @@ func TestViewNewService(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCreateFailingHTTPService(t *testing.T) {
|
||||
s := &Service{&types.Service{
|
||||
s := ReturnService(&types.Service{
|
||||
Name: "Bad URL",
|
||||
Domain: "http://localhost/iamnothere",
|
||||
ExpectedStatus: 200,
|
||||
|
@ -178,9 +178,9 @@ func TestCreateFailingHTTPService(t *testing.T) {
|
|||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 5,
|
||||
}}
|
||||
})
|
||||
var err error
|
||||
newServiceId, err = CreateService(s)
|
||||
newServiceId, err = s.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, newServiceId)
|
||||
newService := SelectService(newServiceId)
|
||||
|
@ -195,16 +195,16 @@ func TestServiceFailedCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCreateFailingTCPService(t *testing.T) {
|
||||
s := &Service{&types.Service{
|
||||
s := ReturnService(&types.Service{
|
||||
Name: "Bad TCP",
|
||||
Domain: "localhost",
|
||||
Port: 5050,
|
||||
Interval: 30,
|
||||
Type: "tcp",
|
||||
Timeout: 5,
|
||||
}}
|
||||
})
|
||||
var err error
|
||||
newServiceId, err = CreateService(s)
|
||||
newServiceId, err = s.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, newServiceId)
|
||||
newService := SelectService(newServiceId)
|
||||
|
@ -219,13 +219,12 @@ func TestServiceFailedTCPCheck(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCreateServiceFailure(t *testing.T) {
|
||||
|
||||
fail := FailureData{
|
||||
Issue: "This is not an issue, but it would container HTTP response errors.",
|
||||
fail := &types.Failure{
|
||||
Issue: "This is not an issue, but it would container HTTP response errors.",
|
||||
Method: "http",
|
||||
}
|
||||
service := SelectService(8)
|
||||
|
||||
id, err := CreateServiceFailure(service, fail)
|
||||
id, err := service.CreateFailure(fail)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, id)
|
||||
}
|
||||
|
@ -233,34 +232,33 @@ func TestCreateServiceFailure(t *testing.T) {
|
|||
func TestDeleteService(t *testing.T) {
|
||||
service := SelectService(newServiceId)
|
||||
|
||||
count, err := SelectAllServices()
|
||||
count, err := CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 8, len(count))
|
||||
|
||||
err = DeleteService(service)
|
||||
err = service.Delete()
|
||||
assert.Nil(t, err)
|
||||
|
||||
count, err = SelectAllServices()
|
||||
count, err = CoreApp.SelectAllServices()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 7, len(count))
|
||||
}
|
||||
|
||||
func TestServiceCloseRoutine(t *testing.T) {
|
||||
s := new(types.Service)
|
||||
s := ReturnService(new(types.Service))
|
||||
s.Name = "example"
|
||||
s.Domain = "https://google.com"
|
||||
s.Type = "http"
|
||||
s.Method = "GET"
|
||||
s.ExpectedStatus = 200
|
||||
s.Interval = 1
|
||||
service := NewService(s)
|
||||
service.Start()
|
||||
assert.True(t, service.IsRunning())
|
||||
go CheckQueue(service, false)
|
||||
s.Start()
|
||||
assert.True(t, s.IsRunning())
|
||||
go s.CheckQueue(false)
|
||||
time.Sleep(5 * time.Second)
|
||||
assert.True(t, service.IsRunning())
|
||||
service.Close()
|
||||
assert.False(t, service.IsRunning())
|
||||
service.Close()
|
||||
assert.False(t, service.IsRunning())
|
||||
assert.True(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
)
|
||||
|
||||
func DeleteConfig() {
|
||||
err := os.Remove("./config.yml")
|
||||
err := os.Remove(utils.Directory + "/config.yml")
|
||||
if err != nil {
|
||||
utils.Log(3, err)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ type ErrorResponse struct {
|
|||
|
||||
func LoadSampleData() error {
|
||||
utils.Log(1, "Inserting Sample Data...")
|
||||
s1 := &Service{&types.Service{
|
||||
s1 := ReturnService(&types.Service{
|
||||
Name: "Google",
|
||||
Domain: "https://google.com",
|
||||
ExpectedStatus: 200,
|
||||
|
@ -43,8 +43,8 @@ func LoadSampleData() error {
|
|||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 10,
|
||||
}}
|
||||
s2 := &Service{&types.Service{
|
||||
})
|
||||
s2 := ReturnService(&types.Service{
|
||||
Name: "Statup Github",
|
||||
Domain: "https://github.com/hunterlong/statup",
|
||||
ExpectedStatus: 200,
|
||||
|
@ -52,8 +52,8 @@ func LoadSampleData() error {
|
|||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 20,
|
||||
}}
|
||||
s3 := &Service{&types.Service{
|
||||
})
|
||||
s3 := ReturnService(&types.Service{
|
||||
Name: "JSON Users Test",
|
||||
Domain: "https://jsonplaceholder.typicode.com/users",
|
||||
ExpectedStatus: 200,
|
||||
|
@ -61,8 +61,8 @@ func LoadSampleData() error {
|
|||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 30,
|
||||
}}
|
||||
s4 := &Service{&types.Service{
|
||||
})
|
||||
s4 := ReturnService(&types.Service{
|
||||
Name: "JSON API Tester",
|
||||
Domain: "https://jsonplaceholder.typicode.com/posts",
|
||||
ExpectedStatus: 201,
|
||||
|
@ -72,32 +72,32 @@ func LoadSampleData() error {
|
|||
Method: "POST",
|
||||
PostData: `{ "title": "statup", "body": "bar", "userId": 19999 }`,
|
||||
Timeout: 30,
|
||||
}}
|
||||
s5 := &Service{&types.Service{
|
||||
})
|
||||
s5 := ReturnService(&types.Service{
|
||||
Name: "Google DNS",
|
||||
Domain: "8.8.8.8",
|
||||
Interval: 20,
|
||||
Type: "tcp",
|
||||
Port: 53,
|
||||
Timeout: 120,
|
||||
}}
|
||||
id, err := CreateService(s1)
|
||||
})
|
||||
id, err := s1.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err))
|
||||
}
|
||||
id, err = CreateService(s2)
|
||||
id, err = s2.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err))
|
||||
}
|
||||
id, err = CreateService(s3)
|
||||
id, err = s3.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err))
|
||||
}
|
||||
id, err = CreateService(s4)
|
||||
id, err = s4.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error creating Service %v: %v", id, err))
|
||||
}
|
||||
id, err = CreateService(s5)
|
||||
id, err = s5.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error creating TCP Service %v: %v", id, err))
|
||||
}
|
||||
|
|
|
@ -23,38 +23,44 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type User types.User
|
||||
type User struct {
|
||||
*types.User
|
||||
}
|
||||
|
||||
func SelectUser(id int64) (*types.User, error) {
|
||||
var user *types.User
|
||||
func ReturnUser(u *types.User) *User {
|
||||
return &User{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
|
||||
}
|
||||
|
||||
func SelectUsername(username string) (*types.User, error) {
|
||||
var user *types.User
|
||||
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
|
||||
}
|
||||
|
||||
func DeleteUser(u *types.User) error {
|
||||
func (u *User) Delete() error {
|
||||
col := DbSession.Collection("users")
|
||||
user := col.Find("id", u.Id)
|
||||
return user.Delete()
|
||||
}
|
||||
|
||||
func UpdateUser(u *types.User) error {
|
||||
func (u *User) Update() error {
|
||||
u.CreatedAt = time.Now()
|
||||
col := DbSession.Collection("users")
|
||||
user := col.Find("id", u.Id)
|
||||
return user.Update(u)
|
||||
}
|
||||
|
||||
func CreateUser(u *types.User) (int64, error) {
|
||||
func (u *User) Create() (int64, error) {
|
||||
u.CreatedAt = time.Now()
|
||||
u.Password = utils.HashPassword(u.Password)
|
||||
u.ApiKey = utils.NewSHA1Hash(5)
|
||||
|
@ -71,8 +77,8 @@ func CreateUser(u *types.User) (int64, error) {
|
|||
return uuid.(int64), err
|
||||
}
|
||||
|
||||
func SelectAllUsers() ([]User, error) {
|
||||
var users []User
|
||||
func SelectAllUsers() ([]*User, error) {
|
||||
var users []*User
|
||||
col := DbSession.Collection("users").Find()
|
||||
err := col.All(&users)
|
||||
if err != nil {
|
||||
|
@ -81,7 +87,7 @@ func SelectAllUsers() ([]User, error) {
|
|||
return users, err
|
||||
}
|
||||
|
||||
func AuthUser(username, password string) (*types.User, bool) {
|
||||
func AuthUser(username, password string) (*User, bool) {
|
||||
var auth bool
|
||||
user, err := SelectUsername(username)
|
||||
if err != nil {
|
||||
|
|
|
@ -22,13 +22,13 @@ import (
|
|||
)
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
user := &types.User{
|
||||
user := ReturnUser(&types.User{
|
||||
Username: "hunter",
|
||||
Password: "password123",
|
||||
Email: "test@email.com",
|
||||
Admin: true,
|
||||
}
|
||||
userId, err := CreateUser(user)
|
||||
})
|
||||
userId, err := user.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, userId)
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ func TestUpdateUser(t *testing.T) {
|
|||
user, err := SelectUser(1)
|
||||
assert.Nil(t, err)
|
||||
user.Username = "updated"
|
||||
err = UpdateUser(user)
|
||||
err = user.Update()
|
||||
assert.Nil(t, err)
|
||||
updatedUser, err := SelectUser(1)
|
||||
assert.Nil(t, err)
|
||||
|
@ -66,13 +66,13 @@ func TestUpdateUser(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCreateUser2(t *testing.T) {
|
||||
user := &types.User{
|
||||
user := ReturnUser(&types.User{
|
||||
Username: "hunterlong",
|
||||
Password: "password123",
|
||||
Email: "user@email.com",
|
||||
Admin: true,
|
||||
}
|
||||
userId, err := CreateUser(user)
|
||||
})
|
||||
userId, err := user.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, userId)
|
||||
}
|
||||
|
@ -108,6 +108,6 @@ func TestCheckPassword(t *testing.T) {
|
|||
func TestDeleteUser(t *testing.T) {
|
||||
user, err := SelectUser(2)
|
||||
assert.Nil(t, err)
|
||||
err = DeleteUser(user)
|
||||
err = user.Delete()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
|
|
@ -5,14 +5,11 @@ MAINTAINER "Hunter Long (https://github.com/hunterlong)"
|
|||
WORKDIR $HOME/statup
|
||||
ADD dev/test .
|
||||
|
||||
ENV VERSION=v0.46
|
||||
|
||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
|
||||
tar -xvzf statup-linux-alpine.tar.gz && \
|
||||
chmod +x statup && \
|
||||
mv statup /usr/local/bin/statup
|
||||
|
||||
RUN npm install node-sass
|
||||
ENV SASS=node-sass
|
||||
RUN npm install
|
||||
|
||||
ADD ./statup /usr/local/bin/statup
|
||||
RUN statup version
|
||||
|
||||
RUN npm run test-docker
|
|
@ -79,8 +79,7 @@ func ApiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
var s *types.Service
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
decoder.Decode(&s)
|
||||
service := serv
|
||||
core.UpdateService(service)
|
||||
serv.Update()
|
||||
json.NewEncoder(w).Encode(s)
|
||||
}
|
||||
|
||||
|
@ -89,7 +88,7 @@ func ApiAllServicesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
services, _ := core.SelectAllServices()
|
||||
services, _ := core.CoreApp.SelectAllServices()
|
||||
json.NewEncoder(w).Encode(services)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
)
|
||||
|
||||
type dashboard struct {
|
||||
Services []*core.Service
|
||||
Core *core.Core
|
||||
CountOnline int
|
||||
CountServices int
|
||||
|
@ -35,7 +34,7 @@ func DashboardHandler(w http.ResponseWriter, r *http.Request) {
|
|||
ExecuteResponse(w, r, "login.html", err)
|
||||
} else {
|
||||
fails := core.CountFailures()
|
||||
out := dashboard{core.CoreApp.Services, core.CoreApp, core.CountOnline(), len(core.CoreApp.Services), fails}
|
||||
out := dashboard{core.CoreApp, core.CountOnline(), len(core.CoreApp.Services()), fails}
|
||||
ExecuteResponse(w, r, "dashboard.html", out)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,10 +112,22 @@ func ExecuteResponse(w http.ResponseWriter, r *http.Request, file string, data i
|
|||
return utils.UnderScoreString(html)
|
||||
},
|
||||
})
|
||||
t, _ = t.Parse(nav)
|
||||
t, _ = t.Parse(footer)
|
||||
t.Parse(render)
|
||||
t.Execute(w, data)
|
||||
t, err = t.Parse(nav)
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
t, err = t.Parse(footer)
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
_, err = t.Parse(render)
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
err = t.Execute(w, data)
|
||||
if err != nil {
|
||||
utils.Log(4, err)
|
||||
}
|
||||
}
|
||||
|
||||
func ExecuteJSResponse(w http.ResponseWriter, r *http.Request, file string, data interface{}) {
|
||||
|
|
|
@ -41,9 +41,9 @@ func PrometheusHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
metrics := []string{}
|
||||
system := fmt.Sprintf("statup_total_failures %v\n", core.CountFailures())
|
||||
system += fmt.Sprintf("statup_total_services %v", len(core.CoreApp.Services))
|
||||
system += fmt.Sprintf("statup_total_services %v", len(core.CoreApp.DbServices))
|
||||
metrics = append(metrics, system)
|
||||
for _, ser := range core.CoreApp.Services {
|
||||
for _, ser := range core.CoreApp.DbServices {
|
||||
v := ser
|
||||
online := 1
|
||||
if !v.Online {
|
||||
|
|
|
@ -30,7 +30,7 @@ type Service struct {
|
|||
}
|
||||
|
||||
func RenderServiceChartsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
services := core.CoreApp.Services
|
||||
services := core.CoreApp.Services()
|
||||
w.Header().Set("Content-Type", "text/javascript")
|
||||
w.Header().Set("Cache-Control", "max-age=60")
|
||||
ExecuteJSResponse(w, r, "charts.js", services)
|
||||
|
@ -41,7 +41,7 @@ func ServicesHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.Services)
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.DbServices)
|
||||
}
|
||||
|
||||
func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -73,15 +73,15 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
PostData: postData,
|
||||
Timeout: timeout,
|
||||
}}
|
||||
_, err := core.CreateService(service)
|
||||
_, err := service.Create()
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("Error starting %v check routine. %v", service.Name, err))
|
||||
}
|
||||
|
||||
go core.CheckQueue(service, true)
|
||||
go service.CheckQueue(true)
|
||||
core.OnNewService(service)
|
||||
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.Services)
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.DbServices)
|
||||
}
|
||||
|
||||
func ServicesDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -96,8 +96,8 @@ func ServicesDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
service := serv
|
||||
core.DeleteService(service)
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.Services)
|
||||
service.Delete()
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.DbServices)
|
||||
}
|
||||
|
||||
func ServicesViewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -142,10 +142,10 @@ func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
PostData: postData,
|
||||
Timeout: timeout,
|
||||
}}
|
||||
service = core.UpdateService(serviceUpdate)
|
||||
core.CoreApp.Services, _ = core.SelectAllServices()
|
||||
serviceUpdate.Update()
|
||||
core.CoreApp.SelectAllServices()
|
||||
|
||||
serv = core.SelectService(service.Id)
|
||||
serv = core.SelectService(serviceUpdate.Id)
|
||||
ExecuteResponse(w, r, "service.html", serv)
|
||||
}
|
||||
|
||||
|
@ -158,8 +158,8 @@ func ServicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
|||
serv := core.SelectService(utils.StringInt(vars["id"]))
|
||||
service := serv
|
||||
core.DeleteFailures(service)
|
||||
core.CoreApp.Services, _ = core.SelectAllServices()
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.Services)
|
||||
core.CoreApp.SelectAllServices()
|
||||
ExecuteResponse(w, r, "services.html", core.CoreApp.DbServices)
|
||||
}
|
||||
|
||||
func CheckinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -171,7 +171,7 @@ func CheckinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
interval := utils.StringInt(r.PostForm.Get("interval"))
|
||||
serv := core.SelectService(utils.StringInt(vars["id"]))
|
||||
service := serv
|
||||
checkin := &core.Checkin{
|
||||
checkin := &types.Checkin{
|
||||
Service: service.Id,
|
||||
Interval: interval,
|
||||
Api: utils.NewSHA1Hash(18),
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
)
|
||||
|
||||
func SetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if core.CoreApp.Services != nil {
|
||||
if core.CoreApp.DbServices != nil {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ func SetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if core.CoreApp.Services != nil {
|
||||
if core.CoreApp.DbServices != nil {
|
||||
http.Redirect(w, r, "/", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
@ -123,13 +123,13 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
admin := &types.User{
|
||||
admin := core.ReturnUser(&types.User{
|
||||
Username: config.Username,
|
||||
Password: config.Password,
|
||||
Email: config.Email,
|
||||
Admin: true,
|
||||
}
|
||||
core.CreateUser(admin)
|
||||
})
|
||||
admin.Create()
|
||||
|
||||
if sample == "on" {
|
||||
core.LoadSampleData()
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/types"
|
||||
|
@ -52,7 +53,12 @@ func UpdateUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||
r.ParseForm()
|
||||
vars := mux.Vars(r)
|
||||
id, _ := strconv.Atoi(vars["id"])
|
||||
user, _ := core.SelectUser(int64(id))
|
||||
user, err := core.SelectUser(int64(id))
|
||||
if err != nil {
|
||||
utils.Log(3, fmt.Sprintf("user error: %v", err))
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
user.Username = r.PostForm.Get("username")
|
||||
user.Email = r.PostForm.Get("email")
|
||||
|
@ -61,7 +67,7 @@ func UpdateUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if password != "##########" {
|
||||
user.Password = utils.HashPassword(password)
|
||||
}
|
||||
core.UpdateUser(user)
|
||||
user.Update()
|
||||
users, _ := core.SelectAllUsers()
|
||||
ExecuteResponse(w, r, "users.html", users)
|
||||
}
|
||||
|
@ -77,15 +83,15 @@ func CreateUserHandler(w http.ResponseWriter, r *http.Request) {
|
|||
email := r.PostForm.Get("email")
|
||||
admin := r.PostForm.Get("admin")
|
||||
|
||||
user := &types.User{
|
||||
user := core.ReturnUser(&types.User{
|
||||
Username: username,
|
||||
Password: password,
|
||||
Email: email,
|
||||
Admin: (admin == "on"),
|
||||
}
|
||||
_, err := core.CreateUser(user)
|
||||
})
|
||||
_, err := user.Create()
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
utils.Log(3, err)
|
||||
}
|
||||
core.OnNewUser(user)
|
||||
http.Redirect(w, r, "/users", http.StatusSeeOther)
|
||||
|
@ -106,6 +112,6 @@ func UsersDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, "/users", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
core.DeleteUser(user)
|
||||
user.Delete()
|
||||
http.Redirect(w, r, "/users", http.StatusSeeOther)
|
||||
}
|
||||
|
|
|
@ -47,31 +47,28 @@
|
|||
<h3>Services</h3>
|
||||
|
||||
<div class="list-group mb-5 mt-3">
|
||||
{{ range .Services }}
|
||||
{{ $s := . }}
|
||||
{{ range .Core.Services }}
|
||||
<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">{{$s.Name}}</h5>
|
||||
<small>{{if $s.Online}} <span class="badge badge-success">ONLINE</span> {{else}} <span class="badge badge-danger">OFFLINE</span> {{end}}</small>
|
||||
<h5 class="mb-1">{{.Name}}</h5>
|
||||
<small>{{if .Online}} <span class="badge badge-success">ONLINE</span> {{else}} <span class="badge badge-danger">OFFLINE</span> {{end}}</small>
|
||||
</div>
|
||||
<p class="mb-1">{{.SmallText}}</p>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
{{ range .Services }}
|
||||
{{ $s := . }}
|
||||
{{ range .Core.Services }}
|
||||
{{ if .LimitedFailures }}
|
||||
<h4>{{$s.Name}} Failures</h4>
|
||||
<h4>{{.Name}} Failures</h4>
|
||||
<div class="list-group mt-3 mb-4">
|
||||
{{ range .LimitedFailures }}
|
||||
{{ $f := .ToFailure }}
|
||||
<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">{{.ParseError}}</h5>
|
||||
<small>Reported {{.Ago}}</small>
|
||||
</div>
|
||||
<p class="mb-1">{{$f.Issue}}</p>
|
||||
<p class="mb-1">{{.Issue}}</p>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
|
|
@ -28,11 +28,9 @@
|
|||
<div class="col-12 full-col-12 mb-5">
|
||||
<div class="list-group online_list">
|
||||
{{ range .Services }}
|
||||
{{ $s := . }}
|
||||
|
||||
<a href="#" class="service_li list-group-item list-group-item-action {{if not $s.Online}}bg-danger text-white{{ end }}" data-id="{{$s.Id}}">
|
||||
{{ $s.Name }}
|
||||
{{if $s.Online}}
|
||||
<a href="#" class="service_li list-group-item list-group-item-action {{if not .Online}}bg-danger text-white{{ end }}" data-id="{{.Id}}">
|
||||
{{ .Name }}
|
||||
{{if .Online}}
|
||||
<span class="badge bg-success float-right pulse-glow">ONLINE</span>
|
||||
{{ else }}
|
||||
<span class="badge bg-white text-black-50 float-right pulse">OFFLINE</span>
|
||||
|
@ -53,13 +51,12 @@
|
|||
</div>
|
||||
{{end}}
|
||||
{{ range .Services }}
|
||||
{{ $s := . }}
|
||||
<div class="mt-4" id="service_id_{{$s.Id}}">
|
||||
<div class="mt-4" id="service_id_{{.Id}}">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="col-12">
|
||||
<h4 class="mt-3"><a href="/service/{{$s.Id}}"{{if not $s.Online}} class="text-danger"{{end}}>{{ $s.Name }}</a>
|
||||
{{if $s.Online}}
|
||||
<h4 class="mt-3"><a href="/service/{{.Id}}"{{if not .Online}} class="text-danger"{{end}}>{{ .Name }}</a>
|
||||
{{if .Online}}
|
||||
<span class="badge bg-success float-right">ONLINE</span>
|
||||
{{ else }}
|
||||
<span class="badge bg-danger float-right pulse">OFFLINE</span>
|
||||
|
@ -80,22 +77,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{ if .LimitedFailures }}
|
||||
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ if .AvgTime }}
|
||||
<div class="chart-container">
|
||||
<canvas id="service_{{ $s.Id }}"></canvas>
|
||||
<canvas id="service_{{ .Id }}"></canvas>
|
||||
</div>
|
||||
{{ end }}
|
||||
<div class="row lower_canvas full-col-12 text-white{{if not $s.Online}} bg-danger{{end}}">
|
||||
<div class="row lower_canvas full-col-12 text-white{{if not .Online}} bg-danger{{end}}">
|
||||
<div class="col-10 text-truncate">
|
||||
<span class="d-none d-md-inline">{{.SmallText}}</span>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<a href="/service/{{ $s.Id }}" class="btn {{if $s.Online}}btn-success{{else}}btn-danger{{end}} btn-sm float-right dyn-dark btn-block">View Service</a>
|
||||
<a href="/service/{{ .Id }}" class="btn {{if .Online}}btn-success{{else}}btn-danger{{end}} btn-sm float-right dyn-dark btn-block">View Service</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{{ $s := . }}<!doctype html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
@ -13,7 +13,7 @@
|
|||
<script src="/js/Chart.bundle.min.js"></script>
|
||||
{{end}}
|
||||
|
||||
<title>Statup | {{$s.Name}} Service</title>
|
||||
<title>Statup | {{.Name}} Service</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
@ -25,14 +25,14 @@
|
|||
|
||||
<div class="col-12 mb-4">
|
||||
|
||||
{{if $s.Online }}
|
||||
{{if .Online }}
|
||||
<span class="mt-3 mb-3 text-white d-md-none btn bg-success d-block d-md-none">ONLINE</span>
|
||||
{{ else }}
|
||||
<span class="mt-3 mb-3 text-white d-md-none btn bg-danger d-block d-md-none">OFFLINE</span>
|
||||
{{end}}
|
||||
|
||||
<h4 class="mt-2">{{ $s.Name }}
|
||||
{{if $s.Online }}
|
||||
<h4 class="mt-2">{{ .Name }}
|
||||
{{if .Online }}
|
||||
<span class="badge bg-success float-right d-none d-md-block">ONLINE</span>
|
||||
{{ else }}
|
||||
<span class="badge bg-danger float-right d-none d-md-block">OFFLINE</span>
|
||||
|
@ -61,13 +61,12 @@
|
|||
{{ if .LimitedFailures }}
|
||||
<div class="list-group mt-3 mb-4">
|
||||
{{ range .LimitedFailures }}
|
||||
{{ $f := .ToFailure }}
|
||||
<a href="#" class="list-group-item list-group-item-action flex-column align-items-start">
|
||||
<div class="d-flex w-100 justify-content-between">
|
||||
<h5 class="mb-1">{{.ParseError}}</h5>
|
||||
<small>Reported {{.Ago}}</small>
|
||||
</div>
|
||||
<p class="mb-1">{{$f.Issue}}</p>
|
||||
<p class="mb-1">{{.Issue}}</p>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
@ -82,71 +81,71 @@
|
|||
|
||||
<h3>Edit Service</h3>
|
||||
|
||||
<form action="/service/{{$s.Id}}" method="POST">
|
||||
<form action="/service/{{.Id}}" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="service_name" class="col-sm-4 col-form-label">Service Name</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="name" class="form-control" id="service_name" value="{{$s.Name}}" placeholder="Name" required spellcheck="false">
|
||||
<input type="text" name="name" class="form-control" id="service_name" value="{{.Name}}" placeholder="Name" required spellcheck="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="service_type" class="col-sm-4 col-form-label">Service Check Type</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="check_type" class="form-control" id="service_type" value="{{$s.Type}}">
|
||||
<option value="http" {{if eq $s.Type "http"}}selected{{end}}>HTTP Service</option>
|
||||
<option value="tcp" {{if eq $s.Type "tcp"}}selected{{end}}>TCP Service</option>
|
||||
<select name="check_type" class="form-control" id="service_type" value="{{.Type}}">
|
||||
<option value="http" {{if eq .Type "http"}}selected{{end}}>HTTP Service</option>
|
||||
<option value="tcp" {{if eq .Type "tcp"}}selected{{end}}>TCP Service</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="service_url" class="col-sm-4 col-form-label">Application Endpoint (URL)</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="domain" class="form-control" id="service_url" value="{{$s.Domain}}" placeholder="https://google.com" required autocapitalize="false" spellcheck="false">
|
||||
<input type="text" name="domain" class="form-control" id="service_url" value="{{.Domain}}" placeholder="https://google.com" required autocapitalize="false" spellcheck="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="form-group row{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<label for="service_check_type" class="col-sm-4 col-form-label">Service Check Type</label>
|
||||
<div class="col-sm-8">
|
||||
<select name="method" class="form-control" id="service_check_type" value="{{$s.Method}}">
|
||||
<option value="GET" {{if eq $s.Method "GET"}}selected{{end}}>GET</option>
|
||||
<option value="POST" {{if eq $s.Method "POST"}}selected{{end}}>POST</option>
|
||||
<select name="method" class="form-control" id="service_check_type" value="{{.Method}}">
|
||||
<option value="GET" {{if eq .Method "GET"}}selected{{end}}>GET</option>
|
||||
<option value="POST" {{if eq .Method "POST"}}selected{{end}}>POST</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="form-group row{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<label for="post_data" class="col-sm-4 col-form-label">Optional Post Data (JSON)</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea name="post_data" class="form-control" id="post_data" rows="3" autocapitalize="false" spellcheck="false">{{$s.PostData}}</textarea>
|
||||
<textarea name="post_data" class="form-control" id="post_data" rows="3" autocapitalize="false" spellcheck="false">{{.PostData}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="form-group row{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<label for="service_response" class="col-sm-4 col-form-label">Expected Response (Regex)</label>
|
||||
<div class="col-sm-8">
|
||||
<textarea name="expected" class="form-control" id="service_response" rows="3" autocapitalize="false" spellcheck="false">{{$s.Expected}}</textarea>
|
||||
<textarea name="expected" class="form-control" id="service_response" rows="3" autocapitalize="false" spellcheck="false">{{.Expected}}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="form-group row{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<label for="service_response_code" class="col-sm-4 col-form-label">Expected Status Code</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="expected_status" class="form-control" value="{{$s.ExpectedStatus}}" id="service_response_code">
|
||||
<input type="number" name="expected_status" class="form-control" value="{{.ExpectedStatus}}" id="service_response_code">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row{{if eq $s.Type "http"}} d-none{{end}}">
|
||||
<div class="form-group row{{if eq .Type "http"}} d-none{{end}}">
|
||||
<label for="service_port" class="col-sm-4 col-form-label">TCP Port</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="port" class="form-control" value="{{$s.Port}}" id="service_port" placeholder="8080">
|
||||
<input type="number" name="port" class="form-control" value="{{.Port}}" id="service_port" placeholder="8080">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="service_interval" class="col-sm-4 col-form-label">Check Interval (Seconds)</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="interval" class="form-control" value="{{$s.Interval}}" id="service_interval" required>
|
||||
<input type="number" name="interval" class="form-control" value="{{.Interval}}" id="service_interval" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="service_timeout" class="col-sm-4 col-form-label">Timeout in Seconds</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="timeout" class="form-control" value="{{$s.Timeout}}" id="service_timeout" min="1" placeholder="30">
|
||||
<input type="number" name="timeout" class="form-control" value="{{.Timeout}}" id="service_timeout" min="1" placeholder="30">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
|
@ -154,34 +153,34 @@
|
|||
<button type="submit" class="btn btn-success btn-block">Update Service</button>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<a href="/service/{{ $s.Id }}/delete_failures" class="btn btn-danger btn-block confirm-btn">Delete All Failures</a>
|
||||
<a href="/service/{{ .Id }}/delete_failures" class="btn btn-danger btn-block confirm-btn">Delete All Failures</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="col-12 mt-4{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<h3>Last Response</h3>
|
||||
<textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea>
|
||||
<textarea rows="8" class="form-control" readonly>{{ .LastResponse }}</textarea>
|
||||
<div class="form-group row mt-2">
|
||||
<label for="last_status_code" class="col-sm-3 col-form-label">HTTP Status Code</label>
|
||||
<div class="col-sm-2">
|
||||
<input type="text" id="last_status_code" class="form-control" value="{{ $s.LastStatusCode }}" readonly>
|
||||
<input type="text" id="last_status_code" class="form-control" value="{{ .LastStatusCode }}" readonly>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="col-12 mt-4{{if eq .Type "tcp"}} d-none{{end}}">
|
||||
<h3>Service Checkins</h3>
|
||||
{{ range $s.Checkins }}
|
||||
{{ range .Checkins }}
|
||||
<h5>Check #{{.Id}} <span class="badge online_badge float-right">Checked in {{.Ago}}</span></h5>
|
||||
<input type="text" class="form-control" value="https://domainhere.com/api/checkin/{{.Api}}">
|
||||
{{ end }}
|
||||
|
||||
<form action="/service/{{$s.Id}}/checkin" method="POST">
|
||||
<form action="/service/{{.Id}}/checkin" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="service_name" class="col-sm-4 col-form-label">Check Interval (in seconds)</label>
|
||||
<div class="col-md-6 col-sm-12">
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package types
|
||||
|
||||
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"`
|
||||
Hits int64 `json:"hits"`
|
||||
Last time.Time `json:"last"`
|
||||
CheckinInterface
|
||||
}
|
||||
|
||||
type CheckinInterface interface {
|
||||
// Database functions
|
||||
Create() (int64, error)
|
||||
//Update() error
|
||||
//Delete() error
|
||||
Ago() string
|
||||
Receivehit()
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
type Core struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
Config string `db:"config" json:"-"`
|
||||
ApiKey string `db:"api_key" json:"api_key"`
|
||||
ApiSecret string `db:"api_secret" json:"api_secret"`
|
||||
Style string `db:"style" json:"-"`
|
||||
Footer string `db:"footer" json:"-"`
|
||||
Domain string `db:"domain" json:"domain,omitempty"`
|
||||
Version string `db:"version" json:"version,omitempty"`
|
||||
MigrationId int64 `db:"migration_id" json:"-"`
|
||||
UseCdn bool `db:"use_cdn" json:"-"`
|
||||
DbServices []*Service `json:"services,omitempty"`
|
||||
Plugins []Info
|
||||
Repos []PluginJSON
|
||||
AllPlugins []PluginActions
|
||||
Communications []AllNotifiers
|
||||
DbConnection string
|
||||
Started time.Time
|
||||
CoreInterface
|
||||
}
|
||||
|
||||
type CoreInterface interface {
|
||||
SelectAllServices() ([]*Service, error)
|
||||
Services() []*Service
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package types
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type FailureInterface interface {
|
||||
Delete() error
|
||||
// method functions
|
||||
Ago() string
|
||||
ParseError() string
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Statup
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statup
|
||||
//
|
||||
// The licenses for most software and other practical works are designed
|
||||
// to take away your freedom to share and change the works. By contrast,
|
||||
// the GNU General Public License is intended to guarantee your freedom to
|
||||
// share and change all versions of a program--to make sure it remains free
|
||||
// software for all its users.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package types
|
||||
|
||||
type ServiceInterface interface {
|
||||
AvgTime() float64
|
||||
Online24() float32
|
||||
ToService() *Service
|
||||
SmallText() string
|
||||
GraphData() string
|
||||
AvgUptime() string
|
||||
LimitedFailures() []*Failure
|
||||
TotalFailures() (uint64, error)
|
||||
TotalFailures24Hours() (uint64, error)
|
||||
}
|
||||
|
||||
type FailureInterface interface {
|
||||
ToFailure() *Failure
|
||||
Ago() string
|
||||
ParseError() string
|
||||
}
|
|
@ -45,6 +45,38 @@ type Service struct {
|
|||
LastStatusCode int
|
||||
LastOnline time.Time
|
||||
DnsLookup float64 `json:"dns_lookup_time"`
|
||||
ServiceInterface
|
||||
}
|
||||
|
||||
type ServiceInterface interface {
|
||||
// Database functions
|
||||
Create() (int64, error)
|
||||
Update() error
|
||||
Delete() error
|
||||
// Basic Method functions
|
||||
AvgTime() float64
|
||||
Online24() float32
|
||||
SmallText() string
|
||||
GraphData() string
|
||||
AvgUptime() string
|
||||
ToJSON() string
|
||||
// Failure functions
|
||||
CreateFailure(*Failure) (int64, error)
|
||||
LimitedFailures() []*Failure
|
||||
AllFailures() []*Failure
|
||||
TotalFailures() (uint64, error)
|
||||
TotalFailures24Hours() (uint64, error)
|
||||
// Hits functions (successful responses)
|
||||
CreateHit(*Hit) (int64, error)
|
||||
Hits() ([]*Hit, error)
|
||||
TotalHits() (uint64, error)
|
||||
Sum() (float64, error)
|
||||
LimitedHits() ([]*Hit, error)
|
||||
SelectHitsGroupBy(string) ([]*Hit, error)
|
||||
// Go Routines
|
||||
CheckQueue(bool)
|
||||
// Checkin functions
|
||||
AllCheckins() []*Checkin
|
||||
}
|
||||
|
||||
func (s *Service) Start() {
|
||||
|
|
|
@ -61,38 +61,6 @@ type PluginActions interface {
|
|||
|
||||
type AllNotifiers interface{}
|
||||
|
||||
type Core struct {
|
||||
Name string `db:"name" json:"name"`
|
||||
Description string `db:"description" json:"description"`
|
||||
Config string `db:"config" json:"-"`
|
||||
ApiKey string `db:"api_key" json:"api_key"`
|
||||
ApiSecret string `db:"api_secret" json:"api_secret"`
|
||||
Style string `db:"style" json:"-"`
|
||||
Footer string `db:"footer" json:"-"`
|
||||
Domain string `db:"domain" json:"domain,omitempty"`
|
||||
Version string `db:"version" json:"version,omitempty"`
|
||||
MigrationId int64 `db:"migration_id" json:"-"`
|
||||
UseCdn bool `db:"use_cdn" json:"-"`
|
||||
Services []*Service `json:"services,omitempty"`
|
||||
Plugins []Info
|
||||
Repos []PluginJSON
|
||||
AllPlugins []PluginActions
|
||||
Communications []AllNotifiers
|
||||
DbConnection string
|
||||
Started time.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"`
|
||||
}
|
||||
|
||||
type Hit struct {
|
||||
Id int `db:"id,omitempty"`
|
||||
Service int64 `db:"service"`
|
||||
|
@ -100,24 +68,6 @@ type Hit struct {
|
|||
CreatedAt time.Time `db:"created_at"`
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
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"`
|
||||
Hits int64 `json:"hits"`
|
||||
Last time.Time `json:"last"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Connection string `yaml:"connection"`
|
||||
Host string `yaml:"host"`
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package types
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
type UserInterface interface {
|
||||
// Database functions
|
||||
Create() (int64, error)
|
||||
Update() error
|
||||
Delete() error
|
||||
}
|
Loading…
Reference in New Issue