mirror of https://github.com/statping/statping
parent
ab2832d0a3
commit
b920ba56c3
|
@ -18,7 +18,7 @@ services:
|
|||
|
||||
env:
|
||||
global:
|
||||
- VERSION=0.29.2
|
||||
- VERSION=0.29.3
|
||||
- DB_HOST=localhost
|
||||
- DB_USER=travis
|
||||
- DB_PASS=
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
FROM alpine:latest
|
||||
|
||||
ENV VERSION=v0.29.2
|
||||
ENV VERSION=v0.29.3
|
||||
|
||||
RUN apk --no-cache add libstdc++ ca-certificates
|
||||
RUN wget -q https://github.com/hunterlong/statup/releases/download/$VERSION/statup-linux-alpine.tar.gz && \
|
||||
|
|
88
cli.go
88
cli.go
|
@ -3,8 +3,12 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/plugin"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/joho/godotenv"
|
||||
"strings"
|
||||
"time"
|
||||
"upper.io/db.v3/sqlite"
|
||||
)
|
||||
|
||||
func CatchCLI(args []string) {
|
||||
|
@ -18,6 +22,12 @@ func CatchCLI(args []string) {
|
|||
core.CompileSASS()
|
||||
case "api":
|
||||
HelpEcho()
|
||||
case "test":
|
||||
cmd := args[2]
|
||||
switch cmd {
|
||||
case "plugins":
|
||||
LoadPlugins(true)
|
||||
}
|
||||
case "export":
|
||||
var err error
|
||||
fmt.Printf("Statup v%v Exporting Static 'index.html' page...\n", VERSION)
|
||||
|
@ -86,6 +96,7 @@ func HelpEcho() {
|
|||
fmt.Println(" statup - Main command to run Statup server")
|
||||
fmt.Println(" statup version - Returns the current version of Statup")
|
||||
fmt.Println(" statup run - Check all service 1 time and then quit")
|
||||
fmt.Println(" statup test plugins - Test all plugins for required information")
|
||||
fmt.Println(" statup assets - Export all assets used locally to be edited.")
|
||||
fmt.Println(" statup env - Show all environment variables being used for Statup")
|
||||
fmt.Println(" statup export - Exports the index page as a static HTML for pushing")
|
||||
|
@ -95,3 +106,80 @@ func HelpEcho() {
|
|||
fmt.Println(" statup help - Shows the user basic information about Statup")
|
||||
fmt.Println("Give Statup a Star at https://github.com/hunterlong/statup")
|
||||
}
|
||||
|
||||
func TestPlugin(plug plugin.PluginActions) {
|
||||
RenderBoxes()
|
||||
defer utils.DeleteFile("./.plugin_test.db")
|
||||
core.CoreApp.AllPlugins = []plugin.PluginActions{plug}
|
||||
info := plug.GetInfo()
|
||||
utils.Log(1, "=======================================================================")
|
||||
utils.Log(1, fmt.Sprintf(" Plugin Name: %v", info.Name))
|
||||
utils.Log(1, fmt.Sprintf(" Plugin Description: %v", info.Description))
|
||||
utils.Log(1, fmt.Sprintf(" Plugin Routes: %v", len(plug.Routes())))
|
||||
for k, r := range plug.Routes() {
|
||||
utils.Log(1, fmt.Sprintf(" - Route %v - (%v) /%v", k+1, r.Method, r.URL))
|
||||
}
|
||||
|
||||
fakeSrv := &core.Service{
|
||||
Id: 56,
|
||||
Name: "Test Plugin Service",
|
||||
Domain: "https://google.com",
|
||||
}
|
||||
|
||||
fakeFailD := core.FailureData{
|
||||
Issue: "No issue, just testing this plugin.",
|
||||
}
|
||||
|
||||
fakeCore := &core.Core{
|
||||
Name: "Plugin Test",
|
||||
Description: "This is a fake Core for testing your plugin",
|
||||
ApiSecret: "0x0x0x0x0",
|
||||
ApiKey: "abcdefg12345",
|
||||
Services: []*core.Service{fakeSrv},
|
||||
}
|
||||
|
||||
fakeUser := &core.User{
|
||||
Id: 6334,
|
||||
Username: "Bulbasaur",
|
||||
Password: "$2a$14$NzT/fLdE3f9iB1Eux2C84O6ZoPhI4NfY0Ke32qllCFo8pMTkUPZzy",
|
||||
Email: "info@testdomain.com",
|
||||
Admin: true,
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
|
||||
utils.Log(1, fmt.Sprintf("Creating a SQLite database for testing, will be deleted automatically..."))
|
||||
sqlFake := sqlite.ConnectionURL{
|
||||
Database: "./.plugin_test.db",
|
||||
}
|
||||
fakeDb, err := sqlite.Open(sqlFake)
|
||||
if err != nil {
|
||||
utils.Log(3, err)
|
||||
}
|
||||
up, _ := core.SqlBox.String("sqlite_up.sql")
|
||||
requests := strings.Split(up, ";")
|
||||
for _, request := range requests {
|
||||
_, err := fakeDb.Exec(request)
|
||||
if err != nil {
|
||||
utils.Log(2, err)
|
||||
}
|
||||
}
|
||||
utils.Log(1, fmt.Sprintf("Finished creating Test SQLite database, sending events."))
|
||||
|
||||
utils.Log(1, "======> Sending 'OnLoad(sqlbuilder.Database)'")
|
||||
core.OnLoad(fakeDb)
|
||||
utils.Log(1, "======> Sending 'OnSuccess(Service)'")
|
||||
core.OnSuccess(fakeSrv)
|
||||
utils.Log(1, "======> Sending 'OnFailure(Service, FailureData)'")
|
||||
core.OnFailure(fakeSrv, fakeFailD)
|
||||
utils.Log(1, "======> Sending 'OnSettingsSaved(Core)'")
|
||||
core.OnSettingsSaved(fakeCore)
|
||||
utils.Log(1, "======> Sending 'OnNewService(Service)'")
|
||||
core.OnNewService(fakeSrv)
|
||||
utils.Log(1, "======> Sending 'OnNewUser(User)'")
|
||||
core.OnNewUser(fakeUser)
|
||||
utils.Log(1, "======> Sending 'OnUpdateService(Service)'")
|
||||
core.OnUpdateService(fakeSrv)
|
||||
utils.Log(1, "======> Sending 'OnDeletedService(Service)'")
|
||||
core.OnDeletedService(fakeSrv)
|
||||
|
||||
}
|
||||
|
|
|
@ -21,19 +21,26 @@ func CheckServices() {
|
|||
for _, v := range CoreApp.Services {
|
||||
obj := v
|
||||
//go obj.StartCheckins()
|
||||
obj.stopRoutine = make(chan struct{})
|
||||
go obj.CheckQueue()
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) CheckQueue() {
|
||||
defer s.CheckQueue()
|
||||
s.Check()
|
||||
if s.Interval < 1 {
|
||||
s.Interval = 1
|
||||
for {
|
||||
select {
|
||||
case <-s.stopRoutine:
|
||||
return
|
||||
default:
|
||||
s.Check()
|
||||
if s.Interval < 1 {
|
||||
s.Interval = 1
|
||||
}
|
||||
msg := fmt.Sprintf("Service: %v | Online: %v | Latency: %0.0fms", s.Name, s.Online, (s.Latency * 1000))
|
||||
utils.Log(1, msg)
|
||||
time.Sleep(time.Duration(s.Interval) * time.Second)
|
||||
}
|
||||
}
|
||||
msg := fmt.Sprintf("Service: %v | Online: %v | Latency: %0.0fms", s.Name, s.Online, (s.Latency * 1000))
|
||||
utils.Log(1, msg)
|
||||
time.Sleep(time.Duration(s.Interval) * time.Second)
|
||||
}
|
||||
|
||||
func (s *Service) DNSCheck() (float64, error) {
|
||||
|
|
|
@ -61,6 +61,7 @@ func Create(c *types.Communication) (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
c.Id = uuid.(int64)
|
||||
c.Routine = make(chan struct{})
|
||||
if CoreApp != nil {
|
||||
CoreApp.Communications = append(CoreApp.Communications, c)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/GeertJohan/go.rice"
|
||||
"github.com/hunterlong/statup/plugin"
|
||||
"github.com/hunterlong/statup/types"
|
||||
|
@ -67,10 +66,6 @@ func InitApp() {
|
|||
func (c *Core) Update() (*Core, error) {
|
||||
res := DbSession.Collection("core").Find().Limit(1)
|
||||
err := res.Update(c)
|
||||
CoreApp.Services, err = SelectAllServices()
|
||||
|
||||
fmt.Println(CoreApp.Name, CoreApp.Description)
|
||||
|
||||
return c, err
|
||||
}
|
||||
|
||||
|
|
|
@ -25,9 +25,12 @@ func OnFailure(s *Service, f FailureData) {
|
|||
for _, p := range CoreApp.AllPlugins {
|
||||
p.OnFailure(structs.Map(s))
|
||||
}
|
||||
|
||||
onFailureEmail(s, f)
|
||||
onFailureSlack(s, f)
|
||||
if notifications.SlackComm != nil {
|
||||
onFailureSlack(s, f)
|
||||
}
|
||||
if notifications.EmailComm != nil {
|
||||
onFailureEmail(s, f)
|
||||
}
|
||||
}
|
||||
|
||||
func onFailureSlack(s *Service, f FailureData) {
|
||||
|
|
|
@ -32,7 +32,7 @@ type Service struct {
|
|||
OrderId int64 `json:"order_id"`
|
||||
Failures []*Failure `json:"failures"`
|
||||
Checkins []*Checkin `json:"checkins"`
|
||||
runRoutine bool
|
||||
stopRoutine chan struct{}
|
||||
LastResponse string
|
||||
LastStatusCode int
|
||||
LastOnline time.Time
|
||||
|
@ -212,6 +212,11 @@ func (u *Service) Delete() error {
|
|||
utils.Log(3, fmt.Sprintf("Failed to delete service %v. %v", u.Name, err))
|
||||
return err
|
||||
}
|
||||
utils.Log(1, fmt.Sprintf("Stopping %v Monitoring...", u.Name))
|
||||
if u.stopRoutine != nil {
|
||||
close(u.stopRoutine)
|
||||
}
|
||||
utils.Log(1, fmt.Sprintf("Stopped %v Monitoring Service", u.Name))
|
||||
u.RemoveArray()
|
||||
OnDeletedService(u)
|
||||
return err
|
||||
|
@ -237,8 +242,9 @@ func (u *Service) Create() (int64, error) {
|
|||
return 0, err
|
||||
}
|
||||
u.Id = uuid.(int64)
|
||||
u.stopRoutine = make(chan struct{})
|
||||
CoreApp.Services = append(CoreApp.Services, u)
|
||||
//go u.CheckQueue()
|
||||
go u.CheckQueue()
|
||||
OnNewService(u)
|
||||
return uuid.(int64), err
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ func RunHTTPServer() {
|
|||
for _, p := range core.CoreApp.AllPlugins {
|
||||
info := p.GetInfo()
|
||||
for _, route := range p.Routes() {
|
||||
path := fmt.Sprintf("/plugins/%v/%v", info.Name, route.URL)
|
||||
path := fmt.Sprintf("%v", route.URL)
|
||||
r.Handle(path, http.HandlerFunc(route.Handler)).Methods(route.Method)
|
||||
fmt.Printf("Added Route %v for plugin %v\n", path, info.Name)
|
||||
utils.Log(1, fmt.Sprintf("Added Route %v for plugin %v\n", path, info.Name))
|
||||
}
|
||||
}
|
||||
srv := &http.Server{
|
||||
|
|
|
@ -11,7 +11,7 @@ type index struct {
|
|||
}
|
||||
|
||||
func IndexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if core.CoreApp.Services == nil {
|
||||
if core.CoreApp == nil {
|
||||
http.Redirect(w, r, "/setup", http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
|
30
main.go
30
main.go
|
@ -3,6 +3,7 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/GeertJohan/go.rice"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/hunterlong/statup/core"
|
||||
"github.com/hunterlong/statup/handlers"
|
||||
"github.com/hunterlong/statup/plugin"
|
||||
|
@ -68,7 +69,7 @@ func mainProcess() {
|
|||
core.InitApp()
|
||||
|
||||
if !core.SetupMode {
|
||||
LoadPlugins()
|
||||
LoadPlugins(false)
|
||||
handlers.RunHTTPServer()
|
||||
}
|
||||
}
|
||||
|
@ -81,14 +82,13 @@ func ForEachPlugin() {
|
|||
}
|
||||
}
|
||||
|
||||
func LoadPlugins() {
|
||||
func LoadPlugins(debug bool) {
|
||||
utils.Log(1, fmt.Sprintf("Loading any available Plugins from /plugins directory"))
|
||||
if _, err := os.Stat("./plugins"); os.IsNotExist(err) {
|
||||
os.Mkdir("./plugins", os.ModePerm)
|
||||
}
|
||||
|
||||
//ForEachPlugin()
|
||||
|
||||
files, err := ioutil.ReadDir("./plugins")
|
||||
if err != nil {
|
||||
utils.Log(2, fmt.Sprintf("Plugins directory was not found. Error: %v\n", err))
|
||||
|
@ -116,18 +116,30 @@ func LoadPlugins() {
|
|||
continue
|
||||
}
|
||||
|
||||
if debug {
|
||||
utils.Log(1, fmt.Sprintf("Plugin '%v' struct:", f.Name()))
|
||||
utils.Log(1, structs.Map(symPlugin))
|
||||
}
|
||||
|
||||
var plugActions plugin.PluginActions
|
||||
plugActions, ok := symPlugin.(plugin.PluginActions)
|
||||
if !ok {
|
||||
utils.Log(3, fmt.Sprintf("Plugin '%v' could not load correctly, error: %v", f.Name(), err))
|
||||
if debug {
|
||||
//fmt.Println(symPlugin.(plugin.PluginActions))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
plugActions.OnLoad(core.DbSession)
|
||||
|
||||
core.CoreApp.Plugins = append(core.CoreApp.Plugins, plugActions.GetInfo())
|
||||
core.CoreApp.AllPlugins = append(core.CoreApp.AllPlugins, plugActions)
|
||||
if debug {
|
||||
TestPlugin(plugActions)
|
||||
} else {
|
||||
plugActions.OnLoad(core.DbSession)
|
||||
core.CoreApp.Plugins = append(core.CoreApp.Plugins, plugActions.GetInfo())
|
||||
core.CoreApp.AllPlugins = append(core.CoreApp.AllPlugins, plugActions)
|
||||
}
|
||||
}
|
||||
if !debug {
|
||||
utils.Log(1, fmt.Sprintf("Loaded %v Plugins\n", len(core.CoreApp.Plugins)))
|
||||
}
|
||||
|
||||
utils.Log(1, fmt.Sprintf("Loaded %v Plugins\n", len(core.CoreApp.Plugins)))
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ func (p *PluginInfo) Form() string {
|
|||
type PluginActions interface {
|
||||
GetInfo() Info
|
||||
GetForm() string
|
||||
OnLoad(sqlbuilder.Database)
|
||||
SetInfo(map[string]interface{}) Info
|
||||
Routes() []Routing
|
||||
OnSave(map[string]interface{})
|
||||
|
@ -52,7 +53,6 @@ type PluginActions interface {
|
|||
OnBeforeRequest(map[string]interface{})
|
||||
OnAfterRequest(map[string]interface{})
|
||||
OnShutdown()
|
||||
OnLoad(sqlbuilder.Database)
|
||||
}
|
||||
|
||||
type Routing struct {
|
||||
|
|
|
@ -41,6 +41,14 @@
|
|||
|
||||
|
||||
<div class="col-12 full-col-12">
|
||||
{{ if not .Services }}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<h4 class="alert-heading">No Services to Monitor!</h4>
|
||||
<p>Your Statup Status Page is working correctly, but you don't have any services to monitor. Go to the <b>Dashboard</b> and add a website to begin really using your status page!</p>
|
||||
<hr>
|
||||
<p class="mb-0">If this is a bug, please make an issue in the Statup Github Repo. <a href="https://github.com/hunterlong/statup" class="btn btn-sm btn-outline-danger float-right">Statup Github Repo</a></p>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ range .Services }}
|
||||
<div class="mt-4" id="service_id_{{.Id}}">
|
||||
<div class="card">
|
||||
|
|
|
@ -55,6 +55,7 @@ type Communication struct {
|
|||
Limits int64 `db:"limits" json:"-"`
|
||||
Removable bool `db:"removable" json:"-"`
|
||||
CreatedAt time.Time `db:"created_at" json:"created_at"`
|
||||
Routine chan struct{}
|
||||
}
|
||||
|
||||
type Email struct {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -33,3 +34,12 @@ func UnderScoreString(str string) string {
|
|||
|
||||
return newStr
|
||||
}
|
||||
|
||||
func DeleteFile(file string) bool {
|
||||
err := os.Remove(file)
|
||||
if err != nil {
|
||||
Log(3, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue