mirror of https://github.com/statping/statping
vue
parent
f06ca9ef18
commit
268108c409
|
@ -17,7 +17,8 @@ ENV GO111MODULE on
|
||||||
|
|
||||||
RUN go get github.com/stretchr/testify/... && \
|
RUN go get github.com/stretchr/testify/... && \
|
||||||
go get github.com/GeertJohan/go.rice/rice && \
|
go get github.com/GeertJohan/go.rice/rice && \
|
||||||
go get github.com/cortesi/modd/cmd/modd
|
go get github.com/cortesi/modd/cmd/modd && \
|
||||||
|
go get github.com/crazy-max/xgo
|
||||||
|
|
||||||
ADD frontend/package.json frontend/yarn.lock ./frontend/
|
ADD frontend/package.json frontend/yarn.lock ./frontend/
|
||||||
|
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -25,6 +25,12 @@ lite: clean
|
||||||
|
|
||||||
reup: down clean compose-build-full up
|
reup: down clean compose-build-full up
|
||||||
|
|
||||||
|
yarn-serve:
|
||||||
|
cd frontend && yarn serve
|
||||||
|
|
||||||
|
go-run:
|
||||||
|
go run ./cmd
|
||||||
|
|
||||||
start:
|
start:
|
||||||
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml start
|
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml start
|
||||||
|
|
||||||
|
|
21
cmd/cli.go
21
cmd/cli.go
|
@ -17,7 +17,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hunterlong/statping/core"
|
"github.com/hunterlong/statping/core"
|
||||||
"github.com/hunterlong/statping/handlers"
|
"github.com/hunterlong/statping/handlers"
|
||||||
|
@ -25,6 +24,7 @@ import (
|
||||||
"github.com/hunterlong/statping/types"
|
"github.com/hunterlong/statping/types"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"time"
|
"time"
|
||||||
|
@ -184,8 +184,7 @@ func ExportIndexHTML() []byte {
|
||||||
func updateDisplay() error {
|
func updateDisplay() error {
|
||||||
gitCurrent, err := checkGithubUpdates()
|
gitCurrent, err := checkGithubUpdates()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Issue connecting to https://github.com/hunterlong/statping\n%v\n", err)
|
return errors.Wrap(err, "Issue connecting to https://github.com/hunterlong/statping")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if gitCurrent.TagName == "" {
|
if gitCurrent.TagName == "" {
|
||||||
return nil
|
return nil
|
||||||
|
@ -194,7 +193,7 @@ func updateDisplay() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if VERSION != gitCurrent.TagName[1:] {
|
if VERSION != gitCurrent.TagName[1:] {
|
||||||
fmt.Printf("\nNew Update %v Available!\n", gitCurrent.TagName[1:])
|
fmt.Printf("New Update %v Available!\n", gitCurrent.TagName[1:])
|
||||||
fmt.Printf("Update Command:\n")
|
fmt.Printf("Update Command:\n")
|
||||||
fmt.Printf("curl -o- -L https://statping.com/install.sh | bash\n\n")
|
fmt.Printf("curl -o- -L https://statping.com/install.sh | bash\n\n")
|
||||||
}
|
}
|
||||||
|
@ -202,27 +201,27 @@ func updateDisplay() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// runOnce will initialize the Statping application and check each service 1 time, will not run HTTP server
|
// runOnce will initialize the Statping application and check each service 1 time, will not run HTTP server
|
||||||
func runOnce() {
|
func runOnce() error {
|
||||||
var err error
|
_, err := core.LoadConfigFile(utils.Directory)
|
||||||
_, err = core.LoadConfigFile(utils.Directory)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln("config.yml file not found")
|
return errors.Wrap(err, "config.yml file not found")
|
||||||
}
|
}
|
||||||
err = core.CoreApp.Connect(false, utils.Directory)
|
err = core.CoreApp.Connect(false, utils.Directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "issue connecting to database")
|
||||||
}
|
}
|
||||||
core.CoreApp, err = core.SelectCore()
|
core.CoreApp, err = core.SelectCore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Core database was not found, Statping is not setup yet.")
|
return errors.Wrap(err, "core database was not found or setup")
|
||||||
}
|
}
|
||||||
_, err = core.SelectAllServices(true)
|
_, err = core.SelectAllServices(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "could not select all services")
|
||||||
}
|
}
|
||||||
for _, srv := range core.Services() {
|
for _, srv := range core.Services() {
|
||||||
core.CheckService(srv, true)
|
core.CheckService(srv, true)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HelpEcho prints out available commands and flags for Statping
|
// HelpEcho prints out available commands and flags for Statping
|
||||||
|
|
14
cmd/main.go
14
cmd/main.go
|
@ -17,6 +17,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -144,16 +145,25 @@ func mainProcess() error {
|
||||||
log.Errorln(fmt.Sprintf("could not connect to database: %v", err))
|
log.Errorln(fmt.Sprintf("could not connect to database: %v", err))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := core.CoreApp.MigrateDatabase(); err != nil {
|
if err := core.CoreApp.MigrateDatabase(); err != nil {
|
||||||
return err
|
return errors.Wrap(err, "database migration")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := core.CoreApp.CreateServicesFromEnvs(); err != nil {
|
||||||
|
errStr := "error 'SERVICE' environment variable"
|
||||||
|
log.Errorln(errStr)
|
||||||
|
return errors.Wrap(err, errStr)
|
||||||
|
}
|
||||||
|
|
||||||
if err := core.InitApp(); err != nil {
|
if err := core.InitApp(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if core.CoreApp.Setup {
|
if core.CoreApp.Setup {
|
||||||
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
|
if err := handlers.RunHTTPServer(ipAddress, port); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
|
return errors.Wrap(err, "http server")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-yaml/yaml"
|
"github.com/go-yaml/yaml"
|
||||||
"github.com/hunterlong/statping/database"
|
"github.com/hunterlong/statping/database"
|
||||||
"github.com/hunterlong/statping/types"
|
"github.com/hunterlong/statping/types"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrorResponse is used for HTTP errors to show to User
|
// ErrorResponse is used for HTTP errors to show to User
|
||||||
|
@ -43,11 +43,11 @@ func LoadConfigFile(directory string) (*DbConfig, error) {
|
||||||
file, err := utils.OpenFile(directory + "/config.yml")
|
file, err := utils.OpenFile(directory + "/config.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
CoreApp.Setup = false
|
CoreApp.Setup = false
|
||||||
return nil, errors.New("config.yml file not found at " + directory + "/config.yml - starting in setup mode")
|
return nil, errors.Wrapf(err, "config.yml file not found at %s/config.yml - starting in setup mode", directory)
|
||||||
}
|
}
|
||||||
err = yaml.Unmarshal([]byte(file), &configs)
|
err = yaml.Unmarshal([]byte(file), &configs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "yaml file not formatted correctly")
|
||||||
}
|
}
|
||||||
log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + directory + "/config.yml")
|
log.WithFields(utils.ToFields(configs)).Debugln("read config file: " + directory + "/config.yml")
|
||||||
CoreApp.Config = configs.DbConfig
|
CoreApp.Config = configs.DbConfig
|
||||||
|
@ -67,24 +67,23 @@ func LoadUsingEnv() (*DbConfig, error) {
|
||||||
|
|
||||||
err = CoreApp.Connect(true, utils.Directory)
|
err = CoreApp.Connect(true, utils.Directory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
return nil, errors.Wrap(err, "error connecting to database")
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
if err := Configs.Save(); err != nil {
|
if err := Configs.Save(); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "error saving configuration")
|
||||||
}
|
}
|
||||||
exists := DbSession.HasTable("core")
|
exists := DbSession.HasTable("core")
|
||||||
if !exists {
|
if !exists {
|
||||||
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
|
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
|
||||||
if err := CoreApp.DropDatabase(); err != nil {
|
if err := CoreApp.DropDatabase(); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "error dropping database")
|
||||||
}
|
}
|
||||||
if err := CoreApp.CreateDatabase(); err != nil {
|
if err := CoreApp.CreateDatabase(); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "error creating database")
|
||||||
}
|
}
|
||||||
CoreApp, err = Configs.InsertCore()
|
CoreApp, err = Configs.InsertCore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
return nil, errors.Wrap(err, "error creating the core database")
|
||||||
}
|
}
|
||||||
|
|
||||||
username := utils.Getenv("ADMIN_USER", "admin").(string)
|
username := utils.Getenv("ADMIN_USER", "admin").(string)
|
||||||
|
@ -97,13 +96,12 @@ func LoadUsingEnv() (*DbConfig, error) {
|
||||||
Admin: types.NewNullBool(true),
|
Admin: types.NewNullBool(true),
|
||||||
}
|
}
|
||||||
if _, err := database.Create(admin); err != nil {
|
if _, err := database.Create(admin); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "error creating admin")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := SampleData(); err != nil {
|
if err := SampleData(); err != nil {
|
||||||
return nil, err
|
return nil, errors.Wrap(err, "error connecting sample data")
|
||||||
}
|
}
|
||||||
|
|
||||||
return Configs, err
|
return Configs, err
|
||||||
}
|
}
|
||||||
return Configs, nil
|
return Configs, nil
|
||||||
|
@ -184,16 +182,13 @@ func EnvToConfig() (*DbConfig, error) {
|
||||||
// SampleData runs all the sample data for a new Statping installation
|
// SampleData runs all the sample data for a new Statping installation
|
||||||
func SampleData() error {
|
func SampleData() error {
|
||||||
if err := InsertSampleData(); err != nil {
|
if err := InsertSampleData(); err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "sample data")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if err := InsertSampleHits(); err != nil {
|
if err := InsertSampleHits(); err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "sample service hits")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
if err := insertSampleCheckins(); err != nil {
|
if err := insertSampleCheckins(); err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "sample checkin examples")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -203,8 +198,7 @@ func DeleteConfig() error {
|
||||||
log.Debugln("deleting config yaml file", utils.Directory+"/config.yml")
|
log.Debugln("deleting config yaml file", utils.Directory+"/config.yml")
|
||||||
err := utils.DeleteFile(utils.Directory + "/config.yml")
|
err := utils.DeleteFile(utils.Directory + "/config.yml")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorln(err)
|
return errors.Wrap(err, "error deleting config.yml")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
25
core/core.go
25
core/core.go
|
@ -21,7 +21,6 @@ import (
|
||||||
"github.com/hunterlong/statping/core/integrations"
|
"github.com/hunterlong/statping/core/integrations"
|
||||||
"github.com/hunterlong/statping/core/notifier"
|
"github.com/hunterlong/statping/core/notifier"
|
||||||
"github.com/hunterlong/statping/database"
|
"github.com/hunterlong/statping/database"
|
||||||
"github.com/hunterlong/statping/notifiers"
|
|
||||||
"github.com/hunterlong/statping/source"
|
"github.com/hunterlong/statping/source"
|
||||||
"github.com/hunterlong/statping/types"
|
"github.com/hunterlong/statping/types"
|
||||||
"github.com/hunterlong/statping/utils"
|
"github.com/hunterlong/statping/utils"
|
||||||
|
@ -202,30 +201,6 @@ func GetLocalIP() string {
|
||||||
return "http://localhost"
|
return "http://localhost"
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttachNotifiers will attach all the notifier's into the system
|
|
||||||
func AttachNotifiers() error {
|
|
||||||
return notifier.AddNotifiers(
|
|
||||||
notifiers.Command,
|
|
||||||
notifiers.Discorder,
|
|
||||||
notifiers.Emailer,
|
|
||||||
notifiers.LineNotify,
|
|
||||||
notifiers.Mobile,
|
|
||||||
notifiers.Slacker,
|
|
||||||
notifiers.Telegram,
|
|
||||||
notifiers.Twilio,
|
|
||||||
notifiers.Webhook,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddIntegrations will attach all the integrations into the system
|
|
||||||
func AddIntegrations() error {
|
|
||||||
return integrations.AddIntegrations(
|
|
||||||
integrations.CsvIntegrator,
|
|
||||||
integrations.TraefikIntegrator,
|
|
||||||
integrations.DockerIntegrator,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
// ServiceOrder will reorder the services based on 'order_id' (Order)
|
||||||
type ServiceOrder []*Service
|
type ServiceOrder []*Service
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-yaml/yaml"
|
"github.com/go-yaml/yaml"
|
||||||
"github.com/hunterlong/statping/core/notifier"
|
"github.com/hunterlong/statping/core/notifier"
|
||||||
|
@ -27,6 +26,7 @@ import (
|
||||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
@ -341,6 +341,43 @@ func (c *Core) CreateDatabase() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// findServiceByHas will return a service that matches the SHA256 hash of a service
|
||||||
|
// Service hash example: sha256(name:EXAMPLEdomain:HTTP://DOMAIN.COMport:8080type:HTTPmethod:GET)
|
||||||
|
func findServiceByHash(hash string) *Service {
|
||||||
|
for _, service := range Services() {
|
||||||
|
if service.String() == hash {
|
||||||
|
return service
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Core) CreateServicesFromEnvs() error {
|
||||||
|
servicesEnv := utils.Getenv("SERVICES", []*types.Service{}).([]*types.Service)
|
||||||
|
|
||||||
|
for k, service := range servicesEnv {
|
||||||
|
|
||||||
|
if err := service.Valid(); err != nil {
|
||||||
|
return errors.Wrapf(err, "invalid service at index %d in SERVICES environment variable", k)
|
||||||
|
}
|
||||||
|
if findServiceByHash(service.String()) == nil {
|
||||||
|
newService := &types.Service{
|
||||||
|
Name: service.Name,
|
||||||
|
Domain: service.Domain,
|
||||||
|
Method: service.Method,
|
||||||
|
Type: service.Type,
|
||||||
|
}
|
||||||
|
if _, err := database.Create(newService); err != nil {
|
||||||
|
return errors.Wrapf(err, "could not create service %s", newService.Name)
|
||||||
|
}
|
||||||
|
log.Infof("Created new service '%s'", newService.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// MigrateDatabase will migrate the database structure to current version.
|
// MigrateDatabase will migrate the database structure to current version.
|
||||||
// This function will NOT remove previous records, tables or columns from the database.
|
// This function will NOT remove previous records, tables or columns from the database.
|
||||||
// If this function has an issue, it will ROLLBACK to the previous state.
|
// If this function has an issue, it will ROLLBACK to the previous state.
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import "github.com/hunterlong/statping/core/integrations"
|
||||||
|
|
||||||
|
// AddIntegrations will attach all the integrations into the system
|
||||||
|
func AddIntegrations() error {
|
||||||
|
return integrations.AddIntegrations(
|
||||||
|
integrations.CsvIntegrator,
|
||||||
|
integrations.TraefikIntegrator,
|
||||||
|
integrations.DockerIntegrator,
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hunterlong/statping/core/notifier"
|
||||||
|
"github.com/hunterlong/statping/notifiers"
|
||||||
|
)
|
||||||
|
|
||||||
|
// AttachNotifiers will attach all the notifier's into the system
|
||||||
|
func AttachNotifiers() error {
|
||||||
|
return notifier.AddNotifiers(
|
||||||
|
notifiers.Command,
|
||||||
|
notifiers.Discorder,
|
||||||
|
notifiers.Emailer,
|
||||||
|
notifiers.LineNotify,
|
||||||
|
notifiers.Mobile,
|
||||||
|
notifiers.Slacker,
|
||||||
|
notifiers.Telegram,
|
||||||
|
notifiers.Twilio,
|
||||||
|
notifiers.Webhook,
|
||||||
|
)
|
||||||
|
}
|
|
@ -112,18 +112,27 @@ func InsertSampleData() error {
|
||||||
if _, err := database.Create(s1); err != nil {
|
if _, err := database.Create(s1); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorCreateService)
|
return types.ErrWrap(err, types.ErrorCreateService)
|
||||||
}
|
}
|
||||||
|
log.Infof("Created Service '%s'", s1.Name)
|
||||||
|
|
||||||
if _, err := database.Create(s2); err != nil {
|
if _, err := database.Create(s2); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorCreateService)
|
return types.ErrWrap(err, types.ErrorCreateService)
|
||||||
}
|
}
|
||||||
|
log.Infof("Created Service '%s'", s2.Name)
|
||||||
|
|
||||||
if _, err := database.Create(s3); err != nil {
|
if _, err := database.Create(s3); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorCreateService)
|
return types.ErrWrap(err, types.ErrorCreateService)
|
||||||
}
|
}
|
||||||
|
log.Infof("Created Service '%s'", s3.Name)
|
||||||
|
|
||||||
if _, err := database.Create(s4); err != nil {
|
if _, err := database.Create(s4); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorCreateService)
|
return types.ErrWrap(err, types.ErrorCreateService)
|
||||||
}
|
}
|
||||||
|
log.Infof("Created Service '%s'", s4.Name)
|
||||||
|
|
||||||
if _, err := database.Create(s5); err != nil {
|
if _, err := database.Create(s5); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorCreateService)
|
return types.ErrWrap(err, types.ErrorCreateService)
|
||||||
}
|
}
|
||||||
|
log.Infof("Created Service '%s'", s5.Name)
|
||||||
|
|
||||||
if _, err := SelectAllServices(false); err != nil {
|
if _, err := SelectAllServices(false); err != nil {
|
||||||
return types.ErrWrap(err, types.ErrorServiceSelection)
|
return types.ErrWrap(err, types.ErrorServiceSelection)
|
||||||
|
|
|
@ -37,13 +37,16 @@ func SelectService(id int64) *Service {
|
||||||
for _, s := range Services() {
|
for _, s := range Services() {
|
||||||
if s.Id == id {
|
if s.Id == id {
|
||||||
s.UpdateStats()
|
s.UpdateStats()
|
||||||
fmt.Println("service: ", s.Name, s.Stats)
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) AfterCreate(obj interface{}, err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// CheckinProcess runs the checkin routine for each checkin attached to service
|
// CheckinProcess runs the checkin routine for each checkin attached to service
|
||||||
func CheckinProcess(s database.Servicer) {
|
func CheckinProcess(s database.Servicer) {
|
||||||
for _, c := range s.Checkins() {
|
for _, c := range s.Checkins() {
|
||||||
|
@ -55,8 +58,12 @@ func CheckinProcess(s database.Servicer) {
|
||||||
// SelectAllServices returns a slice of *core.Service to be store on []*core.Services
|
// SelectAllServices returns a slice of *core.Service to be store on []*core.Services
|
||||||
// should only be called once on startup.
|
// should only be called once on startup.
|
||||||
func SelectAllServices(start bool) ([]*Service, error) {
|
func SelectAllServices(start bool) ([]*Service, error) {
|
||||||
srvs := database.Services()
|
var coreServices []*Service
|
||||||
for _, s := range srvs {
|
if len(CoreApp.services) > 0 {
|
||||||
|
return CoreApp.services, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range database.Services() {
|
||||||
if start {
|
if start {
|
||||||
s.Start()
|
s.Start()
|
||||||
CheckinProcess(s)
|
CheckinProcess(s)
|
||||||
|
@ -71,10 +78,13 @@ func SelectAllServices(start bool) ([]*Service, error) {
|
||||||
|
|
||||||
// collect initial service stats
|
// collect initial service stats
|
||||||
s.UpdateStats()
|
s.UpdateStats()
|
||||||
CoreApp.services = append(CoreApp.services, &Service{s})
|
coreServices = append(coreServices, &Service{s})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoreApp.services = coreServices
|
||||||
reorderServices()
|
reorderServices()
|
||||||
return CoreApp.services, nil
|
|
||||||
|
return coreServices, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func wrapFailures(f []*types.Failure) []*Failure {
|
func wrapFailures(f []*types.Failure) []*Failure {
|
||||||
|
|
|
@ -38,9 +38,22 @@ func modelId(model interface{}) int64 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Create(data interface{}) (*Object, error) {
|
type CreateCallback func(interface{}, error)
|
||||||
|
|
||||||
|
func runCallbacks(data interface{}, err error, fns ...AfterCreate) {
|
||||||
|
for _, fn := range fns {
|
||||||
|
fn.AfterCreate(data, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AfterCreate interface {
|
||||||
|
AfterCreate(interface{}, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Create(data interface{}, fns ...AfterCreate) (*Object, error) {
|
||||||
model := database.Model(&data)
|
model := database.Model(&data)
|
||||||
if err := model.Create(data).Error(); err != nil {
|
if err := model.Create(data).Error(); err != nil {
|
||||||
|
runCallbacks(data, err, fns...)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
obj := &Object{
|
obj := &Object{
|
||||||
|
@ -48,6 +61,7 @@ func Create(data interface{}) (*Object, error) {
|
||||||
model: data,
|
model: data,
|
||||||
db: model,
|
db: model,
|
||||||
}
|
}
|
||||||
|
runCallbacks(data, nil, fns...)
|
||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,38 +2,48 @@ version: '2.3'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
statping_dev:
|
nginx-proxy:
|
||||||
container_name: statping_dev
|
image: jwilder/nginx-proxy
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./dev/Dockerfile.dev
|
|
||||||
args:
|
|
||||||
VERSION: DEV
|
|
||||||
COMMIT: DEV
|
|
||||||
restart: on-failure
|
|
||||||
volumes:
|
|
||||||
- ./:/go/src/github.com/hunterlong/statping
|
|
||||||
environment:
|
|
||||||
GO_ENV: test
|
|
||||||
DB_CONN: sqlite
|
|
||||||
API_KEY: exampleapikey
|
|
||||||
API_SECRET: exampleapisecret
|
|
||||||
NAME: Statping on SQLite
|
|
||||||
DOMAIN: http://localhost:4000
|
|
||||||
DESCRIPTION: This is a dev environment on SQLite!
|
|
||||||
ADMIN_USER: admin
|
|
||||||
ADMIN_PASS: admin
|
|
||||||
PORT: 8585
|
|
||||||
ports:
|
ports:
|
||||||
- 8888:8888
|
- 80:80
|
||||||
- 8585:8585
|
volumes:
|
||||||
networks:
|
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||||
- statping
|
|
||||||
healthcheck:
|
# statping_dev:
|
||||||
test: ["CMD-SHELL", "curl -f http://localhost:8585/health || false"]
|
# container_name: statping_dev
|
||||||
timeout: 2s
|
# build:
|
||||||
interval: 20s
|
# context: .
|
||||||
retries: 30
|
# dockerfile: ./dev/Dockerfile.dev
|
||||||
|
# args:
|
||||||
|
# VERSION: DEV
|
||||||
|
# COMMIT: DEV
|
||||||
|
# restart: on-failure
|
||||||
|
# volumes:
|
||||||
|
# - ./:/go/src/github.com/hunterlong/statping
|
||||||
|
# environment:
|
||||||
|
# VIRTUAL_HOST: local.statping.com
|
||||||
|
# VIRTUAL_PORT: 8888
|
||||||
|
# GO_ENV: test
|
||||||
|
# DB_CONN: sqlite
|
||||||
|
# API_KEY: exampleapikey
|
||||||
|
# API_SECRET: exampleapisecret
|
||||||
|
# NAME: Statping on SQLite
|
||||||
|
# DOMAIN: http://localhost:4000
|
||||||
|
# DESCRIPTION: This is a dev environment on SQLite!
|
||||||
|
# ADMIN_USER: admin
|
||||||
|
# ADMIN_PASS: admin
|
||||||
|
# PORT: 8585
|
||||||
|
# SERVICES: '[{"name": "Local Statping", "type": "http", "domain": "http://localhost:8585", "interval": 30}]'
|
||||||
|
# ports:
|
||||||
|
# - 8888:8888
|
||||||
|
# - 8585:8585
|
||||||
|
# networks:
|
||||||
|
# - statping
|
||||||
|
# healthcheck:
|
||||||
|
# test: ["CMD-SHELL", "curl -f http://localhost:8585/health || false"]
|
||||||
|
# timeout: 2s
|
||||||
|
# interval: 20s
|
||||||
|
# retries: 30
|
||||||
|
|
||||||
statping:
|
statping:
|
||||||
container_name: statping
|
container_name: statping
|
||||||
|
@ -43,6 +53,9 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker/statping/sqlite:/app
|
- ./docker/statping/sqlite:/app
|
||||||
environment:
|
environment:
|
||||||
|
SERVICES: '[{"name": "Local Statping", "type": "http", "domain": "http://localhost:8585", "interval": 30}]'
|
||||||
|
VIRTUAL_HOST: sqlite.dev.statping.com
|
||||||
|
VIRTUAL_PORT: 8080
|
||||||
DB_CONN: sqlite
|
DB_CONN: sqlite
|
||||||
API_KEY: exampleapikey
|
API_KEY: exampleapikey
|
||||||
API_SECRET: exampleapisecret
|
API_SECRET: exampleapisecret
|
||||||
|
@ -73,6 +86,8 @@ services:
|
||||||
links:
|
links:
|
||||||
- mysql
|
- mysql
|
||||||
environment:
|
environment:
|
||||||
|
VIRTUAL_HOST: mysql.dev.statping.com
|
||||||
|
VIRTUAL_PORT: 8080
|
||||||
DB_CONN: mysql
|
DB_CONN: mysql
|
||||||
DB_HOST: mysql
|
DB_HOST: mysql
|
||||||
DB_PORT: 3306
|
DB_PORT: 3306
|
||||||
|
@ -109,6 +124,8 @@ services:
|
||||||
links:
|
links:
|
||||||
- postgres
|
- postgres
|
||||||
environment:
|
environment:
|
||||||
|
VIRTUAL_HOST: postgres.dev.statping.com
|
||||||
|
VIRTUAL_PORT: 8080
|
||||||
DB_CONN: postgres
|
DB_CONN: postgres
|
||||||
DB_HOST: postgres
|
DB_HOST: postgres
|
||||||
DB_PORT: 5432
|
DB_PORT: 5432
|
||||||
|
@ -181,6 +198,8 @@ services:
|
||||||
links:
|
links:
|
||||||
- mysql:db
|
- mysql:db
|
||||||
environment:
|
environment:
|
||||||
|
VIRTUAL_HOST: phpmyadmin.statping.com
|
||||||
|
VIRTUAL_PORT: 80
|
||||||
MYSQL_ROOT_PASSWORD: password123
|
MYSQL_ROOT_PASSWORD: password123
|
||||||
PMA_HOST: mysql
|
PMA_HOST: mysql
|
||||||
PMA_USER: root
|
PMA_USER: root
|
||||||
|
@ -204,6 +223,8 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./docker/statping/sqlite/statping.db:/data/statping.db:ro
|
- ./docker/statping/sqlite/statping.db:/data/statping.db:ro
|
||||||
environment:
|
environment:
|
||||||
|
VIRTUAL_HOST: sqladmin.statping.com
|
||||||
|
VIRTUAL_PORT: 8080
|
||||||
SQLITE_DATABASE: /data/statping.db
|
SQLITE_DATABASE: /data/statping.db
|
||||||
networks:
|
networks:
|
||||||
- statping
|
- statping
|
||||||
|
@ -213,6 +234,8 @@ services:
|
||||||
image: fenglc/pgadmin4
|
image: fenglc/pgadmin4
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
environment:
|
environment:
|
||||||
|
VIRTUAL_HOST: pgadmin.statping.com
|
||||||
|
VIRTUAL_PORT: 5050
|
||||||
DEFAULT_USER: admin@admin.com
|
DEFAULT_USER: admin@admin.com
|
||||||
DEFAULT_PASSWORD: admin
|
DEFAULT_PASSWORD: admin
|
||||||
depends_on:
|
depends_on:
|
||||||
|
@ -236,11 +259,13 @@ services:
|
||||||
- statping
|
- statping
|
||||||
- statping_mysql
|
- statping_mysql
|
||||||
- statping_postgres
|
- statping_postgres
|
||||||
- statping_dev
|
|
||||||
ports:
|
ports:
|
||||||
- 7050:9090
|
- 7050:9090
|
||||||
networks:
|
networks:
|
||||||
- statping
|
- statping
|
||||||
|
environment:
|
||||||
|
VIRTUAL_HOST: prometheus.statping.com
|
||||||
|
VIRTUAL_PORT: 9090
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: "/bin/wget -q -Y off http://localhost:9090/status -O /dev/null > /dev/null 2>&1"
|
test: "/bin/wget -q -Y off http://localhost:9090/status -O /dev/null > /dev/null 2>&1"
|
||||||
interval: 10s
|
interval: 10s
|
||||||
|
@ -258,6 +283,8 @@ services:
|
||||||
- ./dev/grafana/dashboard.yml:/etc/grafana/provisioning/dashboards/dashboard.yml
|
- ./dev/grafana/dashboard.yml:/etc/grafana/provisioning/dashboards/dashboard.yml
|
||||||
- ./dev/grafana/statping_dashboard.json:/etc/grafana/provisioning/dashboards/statping_dashboard.json
|
- ./dev/grafana/statping_dashboard.json:/etc/grafana/provisioning/dashboards/statping_dashboard.json
|
||||||
environment:
|
environment:
|
||||||
|
- VIRTUAL_HOST=grafana.statping.com
|
||||||
|
- VIRTUAL_PORT=3000
|
||||||
- GF_USERS_ALLOW_SIGN_UP=false
|
- GF_USERS_ALLOW_SIGN_UP=false
|
||||||
- GF_AUTH_ANONYMOUS_ENABLED=true
|
- GF_AUTH_ANONYMOUS_ENABLED=true
|
||||||
depends_on:
|
depends_on:
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -91,6 +95,9 @@ func (s *Service) Duration() time.Duration {
|
||||||
|
|
||||||
// Start will create a channel for the service checking go routine
|
// Start will create a channel for the service checking go routine
|
||||||
func (s *Service) Start() {
|
func (s *Service) Start() {
|
||||||
|
if s.IsRunning() {
|
||||||
|
return
|
||||||
|
}
|
||||||
s.Running = make(chan bool)
|
s.Running = make(chan bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,3 +120,23 @@ func (s *Service) IsRunning() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) String() string {
|
||||||
|
format := fmt.Sprintf("name:%sdomain:%sport:%dtype:%smethod:%s", s.Name, s.Domain, s.Port, s.Type, s.Method)
|
||||||
|
h := sha1.New()
|
||||||
|
h.Write([]byte(format))
|
||||||
|
return hex.EncodeToString(h.Sum(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Valid() error {
|
||||||
|
if s.Name == "" {
|
||||||
|
return errors.New("invalid - missing service name")
|
||||||
|
}
|
||||||
|
if s.Domain == "" {
|
||||||
|
return errors.New("invalid - missing service domain")
|
||||||
|
}
|
||||||
|
if s.Type == "" {
|
||||||
|
return errors.New("invalid - missing service type")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -18,9 +18,11 @@ package utils
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/ararog/timeago"
|
"github.com/ararog/timeago"
|
||||||
|
"github.com/hunterlong/statping/types"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
|
@ -84,6 +86,13 @@ func Getenv(key string, defaultValue interface{}) interface{} {
|
||||||
}
|
}
|
||||||
return ok
|
return ok
|
||||||
|
|
||||||
|
case []*types.Service:
|
||||||
|
var services []*types.Service
|
||||||
|
if err := json.Unmarshal([]byte(val), services); err != nil {
|
||||||
|
Log.Error("Incorrect formatting with SERVICE environment variable")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return services
|
||||||
default:
|
default:
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue