mirror of https://github.com/statping/statping
pull/429/head
parent
a14fb1f616
commit
71b7254fce
5
Makefile
5
Makefile
|
@ -20,6 +20,9 @@ up:
|
|||
down:
|
||||
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml down --volumes --remove-orphans
|
||||
|
||||
test: clean
|
||||
go test -v -p=1 -ldflags="-X main.VERSION=dev" -coverprofile=coverage.out ./...
|
||||
|
||||
lite: clean
|
||||
docker build -t hunterlong/statping:dev -f dev/Dockerfile.dev .
|
||||
docker-compose -f dev/docker-compose.lite.yml down
|
||||
|
@ -107,7 +110,7 @@ clean:
|
|||
rm -rf ./{logs,assets,plugins,*.db,config.yml,.sass-cache,config.yml,statping,build,.sass-cache,index.html,vendor}
|
||||
rm -rf cmd/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log,*.html,*.json}
|
||||
rm -rf core/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf core/notifier/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf types/notifications/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf handlers/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf notifiers/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
rm -rf source/{logs,assets,plugins,*.db,config.yml,.sass-cache,*.log}
|
||||
|
|
|
@ -106,7 +106,7 @@ func catchCLI(args []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = configs.ConnectConfigs(config, false); err != nil {
|
||||
if err = configs.ConnectConfigs(config); err != nil {
|
||||
return err
|
||||
}
|
||||
if data, err = handlers.ExportSettings(); err != nil {
|
||||
|
@ -206,7 +206,7 @@ func runOnce() error {
|
|||
if err != nil {
|
||||
return errors.Wrap(err, "config.yml file not found")
|
||||
}
|
||||
err = configs.ConnectConfigs(config, false)
|
||||
err = configs.ConnectConfigs(config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "issue connecting to database")
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"github.com/hunterlong/statping/types/groups"
|
||||
"github.com/hunterlong/statping/types/hits"
|
||||
"github.com/hunterlong/statping/types/incidents"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/messages"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
|
@ -19,5 +18,5 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}, &integrations.Integration{}}
|
||||
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||
}
|
||||
|
|
30
cmd/main.go
30
cmd/main.go
|
@ -19,6 +19,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/hunterlong/statping/notifiers"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
@ -125,14 +126,41 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
if err = configs.ConnectConfigs(c, true); err != nil {
|
||||
if err = configs.ConnectConfigs(c); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
||||
exists := database.DB().HasTable("core")
|
||||
if !exists {
|
||||
|
||||
if err := c.DropDatabase(); err != nil {
|
||||
exit(errors.Wrap(err, "error dropping database"))
|
||||
}
|
||||
|
||||
if err := configs.CreateDatabase(); err != nil {
|
||||
exit(errors.Wrap(err, "error creating database"))
|
||||
}
|
||||
|
||||
if err := configs.CreateAdminUser(c); err != nil {
|
||||
exit(errors.Wrap(err, "error creating default admin user"))
|
||||
}
|
||||
|
||||
if err := configs.TriggerSamples(); err != nil {
|
||||
exit(errors.Wrap(err, "error creating database"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if err := c.MigrateDatabase(); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
||||
log.Infoln("Migrating Notifiers...")
|
||||
if err := notifiers.Migrate(); err != nil {
|
||||
exit(errors.Wrap(err, "error migrating notifiers"))
|
||||
}
|
||||
log.Infoln("Notifiers Migrated")
|
||||
|
||||
if err := mainProcess(); err != nil {
|
||||
exit(err)
|
||||
}
|
||||
|
|
|
@ -9,19 +9,3 @@ type DbObject interface {
|
|||
type Sampler interface {
|
||||
Sample() DbObject
|
||||
}
|
||||
|
||||
func MigrateTable(table interface{}) error {
|
||||
tx := database.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
tx = tx.AutoMigrate(table)
|
||||
|
||||
if err := tx.Commit().Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,171 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 database
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
)
|
||||
|
||||
var (
|
||||
sampleStart = time.Now().Add((-24 * 7) * time.Hour).UTC()
|
||||
SampleHits = 9900.
|
||||
)
|
||||
|
||||
// InsertSampleHits will create a couple new hits for the sample services
|
||||
//func InsertSampleHits() error {
|
||||
// tx := Begin(&hits.Hit{})
|
||||
// sg := new(sync.WaitGroup)
|
||||
// for i := int64(1); i <= 5; i++ {
|
||||
// sg.Add(1)
|
||||
// service := SelectService(i)
|
||||
// seed := time.Now().UnixNano()
|
||||
// log.Infoln(fmt.Sprintf("Adding %v sample hit records to service %v", SampleHits, service.Name))
|
||||
// createdAt := sampleStart
|
||||
// p := utils.NewPerlin(2., 2., 10, seed)
|
||||
// go func(sg *sync.WaitGroup) {
|
||||
// defer sg.Done()
|
||||
// for hi := 0.; hi <= float64(SampleHits); hi++ {
|
||||
// latency := p.Noise1D(hi / 500)
|
||||
// createdAt = createdAt.Add(60 * time.Second)
|
||||
// hit := &hits.Hit{
|
||||
// Service: service.Id,
|
||||
// CreatedAt: createdAt,
|
||||
// Latency: latency,
|
||||
// }
|
||||
// tx = tx.Create(&hit)
|
||||
// }
|
||||
// }(sg)
|
||||
// }
|
||||
// sg.Wait()
|
||||
// if err := tx.Commit().Error(); err != nil {
|
||||
// log.Errorln(err)
|
||||
// return types.ErrWrap(err, types.ErrorCreateSampleHits)
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
//func TmpRecords(dbFile string) error {
|
||||
// var sqlFile = utils.Directory + "/" + dbFile
|
||||
// if err := utils.CreateDirectory(utils.Directory + "/tmp"); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// var tmpSqlFile = utils.Directory + "/tmp/" + dbFile
|
||||
// SampleHits = 480
|
||||
//
|
||||
// var err error
|
||||
// CoreApp = NewCore()
|
||||
// CoreApp.Name = "Tester"
|
||||
// CoreApp.Setup = true
|
||||
// configs := &types.DbConfig{
|
||||
// DbConn: "sqlite",
|
||||
// Project: "Tester",
|
||||
// Location: utils.Directory,
|
||||
// SqlFile: sqlFile,
|
||||
// }
|
||||
// log.Infoln("saving config.yml in: " + utils.Directory)
|
||||
// if err := configs.Save(utils.Directory); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
//
|
||||
// log.Infoln("loading config.yml from: " + utils.Directory)
|
||||
// if configs, err = LoadConfigs(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("connecting to database")
|
||||
//
|
||||
// exists := utils.FileExists(tmpSqlFile)
|
||||
// if exists {
|
||||
// log.Infoln(tmpSqlFile + " was found, copying the temp database to " + sqlFile)
|
||||
// if err := utils.DeleteFile(sqlFile); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// if err := utils.CopyFile(tmpSqlFile, sqlFile); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("loading config.yml from: " + utils.Directory)
|
||||
//
|
||||
// if err := CoreApp.Connect(configs, false, utils.Directory); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("selecting the Core variable")
|
||||
// if _, err := SelectCore(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("inserting notifiers into database")
|
||||
// if err := InsertNotifierDB(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("inserting integrations into database")
|
||||
// if err := InsertIntegratorDB(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// log.Infoln("loading all services")
|
||||
// if _, err := SelectAllServices(false); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// if err := AttachNotifiers(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// if err := AddIntegrations(); err != nil {
|
||||
// log.Error(err)
|
||||
// }
|
||||
// CoreApp.Notifications = notifier.AllCommunications
|
||||
// return nil
|
||||
// }
|
||||
//
|
||||
// log.Infoln(tmpSqlFile + " not found, creating a new database...")
|
||||
//
|
||||
// if err := CoreApp.Connect(configs, false, utils.Directory); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("creating database")
|
||||
// if err := CoreApp.CreateDatabase(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("migrating database")
|
||||
// if err := MigrateDatabase(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("insert large sample data into database")
|
||||
// if err := InsertLargeSampleData(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("selecting the Core variable")
|
||||
// if CoreApp, err = SelectCore(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("inserting notifiers into database")
|
||||
// if err := InsertNotifierDB(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("inserting integrations into database")
|
||||
// if err := InsertIntegratorDB(); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("loading all services")
|
||||
// if _, err := SelectAllServices(false); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// log.Infoln("copying sql database file to: " + tmpSqlFile)
|
||||
// if err := utils.CopyFile(sqlFile, tmpSqlFile); err != nil {
|
||||
// return err
|
||||
// }
|
||||
// return err
|
||||
//}
|
|
@ -129,18 +129,6 @@ class Api {
|
|||
return axios.post('/api/notifier/' + data.method + '/test', data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async integrations() {
|
||||
return axios.get('/api/integrations').then(response => (response.data))
|
||||
}
|
||||
|
||||
async integration(name) {
|
||||
return axios.get('/api/integrations/' + name).then(response => (response.data))
|
||||
}
|
||||
|
||||
async integration_save(data) {
|
||||
return axios.post('/api/integrations/' + data.name, data).then(response => (response.data))
|
||||
}
|
||||
|
||||
async renewApiKeys() {
|
||||
return axios.get('/api/renew').then(response => (response.data))
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
<template>
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<FormService :in_service="service"/>
|
||||
</div>
|
||||
</div>
|
||||
<FormService :in_service="service"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -87,6 +87,37 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row d-none">
|
||||
<div class="col-12">
|
||||
<h4 class="mt-5">Github Authentication</h4>
|
||||
|
||||
<div class="form-group row d-none">
|
||||
<label class="col-sm-4 col-form-label">Github Client ID</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="core.github_clientId" type="text" class="form-control" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Github Client Secret</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="core.github_clientScret" type="text" class="form-control" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="switch-group-public" class="col-sm-4 col-form-label">Enabled</label>
|
||||
<div class="col-md-8 col-xs-12 mt-1">
|
||||
<span @click="enabled = !!enabled" class="switch float-left">
|
||||
<input v-model="enabled" type="checkbox" class="switch" id="switch-group-public" :checked="enabled">
|
||||
<label for="switch-group-public">Enabled Github Auth</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button @click.prevent="saveSettings" type="submit" class="btn btn-primary btn-block">Save Settings</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</template>
|
||||
|
||||
|
@ -99,16 +130,14 @@
|
|||
return {
|
||||
core: this.$store.getters.core,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
async saveSettings() {
|
||||
const c = this.core
|
||||
const coreForm = {
|
||||
name: c.name, description: c.description, domain: c.domain,
|
||||
timezone: c.timezone, using_cdn: c.using_cdn, footer: c.footer, update_notify: c.update_notify
|
||||
timezone: c.timezone, using_cdn: c.using_cdn, footer: c.footer, update_notify: c.update_notify,
|
||||
gh_client_id: c.github_clientId, gh_client_secret: c.github_clientSecret
|
||||
}
|
||||
await Api.core_save(coreForm)
|
||||
const core = await Api.core()
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
<template>
|
||||
<form @submit="updateCore">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Github Client ID</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="clientId" type="text" class="form-control" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Github Client Secret</label>
|
||||
<div class="col-sm-8">
|
||||
<input v-model="clientSecret" type="text" class="form-control" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="switch-group-public" class="col-sm-4 col-form-label">Enabled</label>
|
||||
<div class="col-md-8 col-xs-12 mt-1">
|
||||
<span @click="enabled = !!enabled" class="switch float-left">
|
||||
<input v-model="enabled" type="checkbox" class="switch" id="switch-group-public" :checked="enabled">
|
||||
<label for="switch-group-public">Enabled Github Auth</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-12">
|
||||
<button @click="updateCore" type="submit" :disabled="loading || group.name === ''" class="btn btn-block" :class="{'btn-primary': !group.id, 'btn-secondary': group.id}">
|
||||
{{loading ? "Loading..." : group.id ? "Update Group" : "Create Group"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Api from "../API";
|
||||
|
||||
export default {
|
||||
name: 'FormGroup',
|
||||
props: {
|
||||
in_group: {
|
||||
type: Object
|
||||
},
|
||||
edit: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
clientId: "",
|
||||
clientSecret: "",
|
||||
enabled: true,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
in_group() {
|
||||
this.group = this.in_group
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
removeEdit() {
|
||||
this.group = {}
|
||||
this.edit(false)
|
||||
},
|
||||
async updateCore() {
|
||||
const g = this.group
|
||||
const data = {id: g.id, name: g.name, public: g.public}
|
||||
await Api.core_save(data)
|
||||
const groups = await Api.groups()
|
||||
this.$store.commit('setGroups', groups)
|
||||
this.edit(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
|
@ -22,6 +22,7 @@
|
|||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</template>
|
||||
|
||||
|
@ -37,9 +38,13 @@
|
|||
auth: {},
|
||||
loading: false,
|
||||
error: false,
|
||||
disabled: true
|
||||
disabled: true,
|
||||
ghLoginURL: ""
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.GHlogin()
|
||||
},
|
||||
methods: {
|
||||
checkForm() {
|
||||
if (!this.username || !this.password) {
|
||||
|
@ -60,6 +65,10 @@
|
|||
this.$router.push('/dashboard')
|
||||
}
|
||||
this.loading = false
|
||||
},
|
||||
async GHlogin() {
|
||||
const core = this.$store.getters.core;
|
||||
this.ghLoginURL = `https://github.com/login/oauth/authorize?client_id=${core.gh_client_id}&redirect_uri=${core.domain}/oauth/callback&scope=user,repo`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<template>
|
||||
<form @submit.prevent="saveService">
|
||||
<h4 class="mb-5 text-muted">Basic Information</h4>
|
||||
<div class="card contain-card text-black-50 bg-white mb-4">
|
||||
<div class="card-header">Basic Information</div>
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Service Name</label>
|
||||
<div class="col-sm-8">
|
||||
|
@ -37,8 +39,12 @@
|
|||
<small class="form-text text-muted">Attach this service to a group</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 v-if="service.type !== 'icmp'" class="mt-5 mb-5 text-muted">Request Details</h4>
|
||||
<div v-if="service.type !== 'icmp'" class="card contain-card text-black-50 bg-white mb-4">
|
||||
<div class="card-header">Request Details</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label">Service Check Type</label>
|
||||
|
@ -87,8 +93,12 @@
|
|||
<input v-model="service.port" type="number" name="port" class="form-control" id="service_port" placeholder="8080">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4 class="mt-5 mb-5 text-muted">Additional Options</h4>
|
||||
<div class="card contain-card text-black-50 bg-white mb-4">
|
||||
<div class="card-header">Additional Options</div>
|
||||
<div class="card-body">
|
||||
|
||||
<div class="form-group row">
|
||||
<label for="service_interval" class="col-sm-4 col-form-label">Check Interval (Seconds)</label>
|
||||
|
@ -153,6 +163,8 @@
|
|||
{{service.id ? "Update Service" : "Create Service"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger d-none" id="alerter" role="alert"></div>
|
||||
</form>
|
||||
|
|
|
@ -22,12 +22,6 @@
|
|||
<span v-if="notifier.enabled" class="badge badge-pill float-right mt-1" :class="{'badge-success': !liClass(`v-pills-${notifier.method.toLowerCase()}-tab`), 'badge-light': liClass(`v-pills-${notifier.method.toLowerCase()}-tab`), 'text-dark': liClass(`v-pills-${notifier.method.toLowerCase()}-tab`)}">ON</span>
|
||||
</a>
|
||||
|
||||
<h6 class="mt-4 text-muted">Integrations <span class="badge badge-secondary float-right">BETA</span></h6>
|
||||
|
||||
<a v-for="(integration, index) in $store.getters.integrations" v-bind:key="`${integration.name}_${index}`" @click.prevent="changeTab" class="nav-link text-capitalize" v-bind:class="{active: liClass(`v-pills-integration-${integration.name}`)}" v-bind:id="`v-pills-integration-${integration.name}`" data-toggle="pill" v-bind:href="`#v-pills-integration-${integration.name}`" role="tab" :aria-controls="`v-pills-integration-${integration.name}`" aria-selected="false">
|
||||
<font-awesome-icon :icon="iconName(integration.name)" class="mr-2"/> {{integration.full_name}}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9 col-sm-12">
|
||||
|
@ -90,10 +84,6 @@
|
|||
<Notifier :notifier="notifier"/>
|
||||
</div>
|
||||
|
||||
<div v-for="(integration, index) in $store.getters.integrations" v-bind:key="`${integration.name}_${index}`" class="tab-pane fade" v-bind:class="{active: liClass(`v-pills-integration-${integration.name}`), show: liClass(`v-pills-integration-${integration.name}`)}" v-bind:id="`v-pills-integration-${integration.name}`" role="tabpanel">
|
||||
<FormIntegration :integration="integration"/>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
1
go.mod
1
go.mod
|
@ -33,6 +33,7 @@ require (
|
|||
github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/mail.v2 v2.3.1 // indirect
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1,3 +1,4 @@
|
|||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
|
@ -300,6 +301,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r
|
|||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
|
@ -310,6 +312,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func findIntegration(r *http.Request) (*integrations.Integration, string, error) {
|
||||
vars := mux.Vars(r)
|
||||
name := vars["name"]
|
||||
intgr, err := integrations.Find(name)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
return intgr, name, nil
|
||||
}
|
||||
|
||||
func apiAllIntegrationsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
inte := integrations.All()
|
||||
returnJson(inte, w, r)
|
||||
}
|
||||
|
||||
func apiIntegrationViewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
intgr, _, err := findIntegration(r)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
returnJson(intgr, w, r)
|
||||
}
|
||||
|
||||
func apiIntegrationHandler(w http.ResponseWriter, r *http.Request) {
|
||||
intgr, _, err := findIntegration(r)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&intgr); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := intgr.Update(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
returnJson(intgr, w, r)
|
||||
}
|
|
@ -27,12 +27,8 @@ import (
|
|||
)
|
||||
|
||||
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var notifiers []*notifications.Notification
|
||||
for _, n := range core.App.Notifications {
|
||||
notif := n.(notifications.Notifier)
|
||||
notifiers = append(notifiers, notif.Select())
|
||||
}
|
||||
returnJson(notifiers, w, r)
|
||||
all := notifications.All()
|
||||
returnJson(all, w, r)
|
||||
}
|
||||
|
||||
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -104,7 +104,8 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
}
|
||||
|
||||
for _, notif := range notifications.All() {
|
||||
for _, n := range notifications.All() {
|
||||
notif := n.Select()
|
||||
PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method))
|
||||
enabled := 0
|
||||
if notif.Enabled.Bool {
|
||||
|
|
|
@ -87,6 +87,7 @@ func Router() *mux.Router {
|
|||
|
||||
// API Routes
|
||||
r.Handle("/api", scoped(apiIndexHandler))
|
||||
//r.Handle("/oauth/callback", http.HandlerFunc(OAuthRedirect))
|
||||
api.Handle("/api/login", http.HandlerFunc(apiLoginHandler)).Methods("POST")
|
||||
r.Handle("/api/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
|
||||
api.Handle("/api/logout", http.HandlerFunc(logoutHandler))
|
||||
|
@ -103,11 +104,6 @@ func Router() *mux.Router {
|
|||
api.Handle("/api/theme/create", authenticated(apiThemeCreateHandler, false)).Methods("GET")
|
||||
api.Handle("/api/theme", authenticated(apiThemeRemoveHandler, false)).Methods("DELETE")
|
||||
|
||||
// API INTEGRATIONS Routes
|
||||
api.Handle("/api/integrations", authenticated(apiAllIntegrationsHandler, false)).Methods("GET")
|
||||
api.Handle("/api/integrations/{name}", authenticated(apiIntegrationViewHandler, false)).Methods("GET")
|
||||
api.Handle("/api/integrations/{name}", authenticated(apiIntegrationHandler, false)).Methods("POST")
|
||||
|
||||
// API GROUPS Routes
|
||||
api.Handle("/api/groups", scoped(apiAllGroupHandler)).Methods("GET")
|
||||
api.Handle("/api/groups", authenticated(apiCreateGroupHandler, false)).Methods("POST")
|
||||
|
|
|
@ -81,6 +81,7 @@ func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
|
|||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
go services.ServiceCheckQueue(service, true)
|
||||
|
||||
sendJsonAction(service, "create", w, r)
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ package handlers
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/notifiers"
|
||||
"github.com/hunterlong/statping/types/configs"
|
||||
"github.com/hunterlong/statping/types/core"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
|
@ -43,7 +45,7 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
log.WithFields(utils.ToFields(core.App, confgs)).Debugln("new configs posted")
|
||||
|
||||
if err = configs.ConnectConfigs(confgs, true); err != nil {
|
||||
if err = configs.ConnectConfigs(confgs); err != nil {
|
||||
log.Errorln(err)
|
||||
if err := confgs.Delete(); err != nil {
|
||||
log.Errorln(err)
|
||||
|
@ -60,11 +62,40 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
exists := database.DB().HasTable("core")
|
||||
if !exists {
|
||||
if err := confgs.DropDatabase(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := configs.CreateDatabase(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := configs.CreateAdminUser(confgs); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if err := configs.TriggerSamples(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = confgs.MigrateDatabase(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
log.Infoln("Migrating Notifiers...")
|
||||
if err := notifiers.Migrate(); err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
c := &core.Core{
|
||||
Name: "Statping Sample Data",
|
||||
Description: "This data is only used to testing",
|
||||
|
@ -86,15 +117,6 @@ func processSetupHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
core.App = c
|
||||
|
||||
//if sample {
|
||||
// log.Infoln("Adding sample data into new database")
|
||||
// if err = configs.TriggerSamples(); err != nil {
|
||||
// log.Errorln(err)
|
||||
// sendErrorJson(err, w, r)
|
||||
// return
|
||||
// }
|
||||
//}
|
||||
|
||||
log.Infoln("Initializing new Statping instance")
|
||||
if err := core.InitApp(); err != nil {
|
||||
log.Errorln(err)
|
||||
|
|
|
@ -1,132 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 integrators
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const requiredSize = 17
|
||||
|
||||
type csvIntegration struct {
|
||||
*integrations.Integration
|
||||
}
|
||||
|
||||
var CsvIntegrator = &csvIntegration{&integrations.Integration{
|
||||
ShortName: "csv",
|
||||
Name: "CSV File",
|
||||
Icon: "<i class=\"fas fa-file-csv\"></i>",
|
||||
Description: "Import multiple services from a CSV file. Please have your CSV file formatted with the correct amount of columns based on the <a href=\"https://raw.githubusercontent.com/hunterlong/statping/master/source/tmpl/bulk_import.csv\">example file on Github</a>.",
|
||||
Fields: []*integrations.IntegrationField{
|
||||
{
|
||||
Name: "input",
|
||||
Type: "textarea",
|
||||
Description: "",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
var csvData [][]string
|
||||
|
||||
func (t *csvIntegration) Get() *integrations.Integration {
|
||||
return t.Integration
|
||||
}
|
||||
|
||||
func (t *csvIntegration) List() ([]*services.Service, error) {
|
||||
data := Value(t, "input").(string)
|
||||
buf := bytes.NewReader([]byte(data))
|
||||
r := csv.NewReader(buf)
|
||||
records, err := r.ReadAll()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var services []*services.Service
|
||||
for k, v := range records[1:] {
|
||||
s, err := commaToService(v)
|
||||
if err != nil {
|
||||
log.Errorf("error on line %v: %v", k, err)
|
||||
continue
|
||||
}
|
||||
services = append(services, s)
|
||||
}
|
||||
return services, nil
|
||||
}
|
||||
|
||||
// commaToService will convert a CSV comma delimited string slice to a Service type
|
||||
// this function is used for the bulk import services feature
|
||||
func commaToService(s []string) (*services.Service, error) {
|
||||
if len(s) != requiredSize {
|
||||
err := fmt.Errorf("file has %v columns of data, not the expected amount of %v columns for a service", len(s), requiredSize)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
interval, err := time.ParseDuration(s[4])
|
||||
if err != nil {
|
||||
return nil, errors.New("could not parse internal duration: " + s[4])
|
||||
}
|
||||
|
||||
timeout, err := time.ParseDuration(s[9])
|
||||
if err != nil {
|
||||
return nil, errors.New("could not parse timeout duration: " + s[9])
|
||||
}
|
||||
|
||||
allowNotifications, err := strconv.ParseBool(s[11])
|
||||
if err != nil {
|
||||
return nil, errors.New("could not parse allow notifications boolean: " + s[11])
|
||||
}
|
||||
|
||||
public, err := strconv.ParseBool(s[12])
|
||||
if err != nil {
|
||||
return nil, errors.New("could not parse public boolean: " + s[12])
|
||||
}
|
||||
|
||||
verifySsl, err := strconv.ParseBool(s[16])
|
||||
if err != nil {
|
||||
return nil, errors.New("could not parse verifiy SSL boolean: " + s[16])
|
||||
}
|
||||
|
||||
newService := &services.Service{
|
||||
Name: s[0],
|
||||
Domain: s[1],
|
||||
Expected: null.NewNullString(s[2]),
|
||||
ExpectedStatus: int(utils.ToInt(s[3])),
|
||||
Interval: int(utils.ToInt(interval.Seconds())),
|
||||
Type: s[5],
|
||||
Method: s[6],
|
||||
PostData: null.NewNullString(s[7]),
|
||||
Port: int(utils.ToInt(s[8])),
|
||||
Timeout: int(utils.ToInt(timeout.Seconds())),
|
||||
AllowNotifications: null.NewNullBool(allowNotifications),
|
||||
Public: null.NewNullBool(public),
|
||||
GroupId: int(utils.ToInt(s[13])),
|
||||
Headers: null.NewNullString(s[14]),
|
||||
Permalink: null.NewNullString(s[15]),
|
||||
VerifySSL: null.NewNullBool(verifySsl),
|
||||
}
|
||||
|
||||
return newService, nil
|
||||
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package integrators
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCsvFileIntegration(t *testing.T) {
|
||||
data, err := ioutil.ReadFile("testdata/bulk_import.csv")
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("Set Field Value", func(t *testing.T) {
|
||||
formPost := map[string][]string{}
|
||||
formPost["input"] = []string{string(data)}
|
||||
_, err = SetFields(CsvIntegrator, formPost)
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Get Field Value", func(t *testing.T) {
|
||||
value := Value(CsvIntegrator, "input").(string)
|
||||
assert.Equal(t, string(data), value)
|
||||
})
|
||||
|
||||
t.Run("List Services from CSV File", func(t *testing.T) {
|
||||
services, err := CsvIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 10, len(services))
|
||||
})
|
||||
|
||||
t.Run("Confirm Services from CSV File", func(t *testing.T) {
|
||||
services, err := CsvIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Bulk Upload", services[0].Name)
|
||||
assert.Equal(t, "http://google.com", services[0].Domain)
|
||||
assert.Equal(t, 60, services[0].Interval)
|
||||
for _, s := range services {
|
||||
t.Log(s)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 integrators
|
||||
|
||||
import (
|
||||
"context"
|
||||
dTypes "github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"os"
|
||||
)
|
||||
|
||||
type dockerIntegration struct {
|
||||
*integrations.Integration
|
||||
}
|
||||
|
||||
var DockerIntegrator = &dockerIntegration{&integrations.Integration{
|
||||
ShortName: "docker",
|
||||
Name: "Docker",
|
||||
Icon: "<i class=\"fab fa-docker\"></i>",
|
||||
Description: `Import multiple services from Docker by attaching the unix socket to Statping.
|
||||
You can also do this in Docker by setting <u>-v /var/run/docker.sock:/var/run/docker.sock</u> in the Statping Docker container.
|
||||
All of the containers with open TCP/UDP ports will be listed for you to choose which services you want to add. If you running Statping inside of a container,
|
||||
this container must be attached to all networks you want to communicate with.`,
|
||||
Fields: []*integrations.IntegrationField{
|
||||
{
|
||||
Name: "path",
|
||||
Description: "The absolute path to the Docker unix socket",
|
||||
Type: "text",
|
||||
Value: client.DefaultDockerHost,
|
||||
},
|
||||
{
|
||||
Name: "version",
|
||||
Description: "Version number of Docker server",
|
||||
Type: "text",
|
||||
Value: client.DefaultVersion,
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
var cli *client.Client
|
||||
|
||||
func (t *dockerIntegration) Get() *integrations.Integration {
|
||||
return t.Integration
|
||||
}
|
||||
|
||||
func (t *dockerIntegration) List() ([]*services.Service, error) {
|
||||
var err error
|
||||
path := Value(t, "path").(string)
|
||||
version := Value(t, "version").(string)
|
||||
os.Setenv("DOCKER_HOST", path)
|
||||
os.Setenv("DOCKER_VERSION", version)
|
||||
cli, err = client.NewEnvClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
var srvs []*services.Service
|
||||
|
||||
containers, err := cli.ContainerList(context.Background(), dTypes.ContainerListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, container := range containers {
|
||||
if container.State != "running" {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, v := range container.Ports {
|
||||
if v.IP == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
service := &services.Service{
|
||||
Name: container.Names[0][1:],
|
||||
Domain: v.IP,
|
||||
Type: v.Type,
|
||||
Port: int(v.PublicPort),
|
||||
Interval: 60,
|
||||
Timeout: 2,
|
||||
}
|
||||
|
||||
srvs = append(srvs, service)
|
||||
}
|
||||
|
||||
}
|
||||
return srvs, nil
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
package integrators
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDockerIntegration(t *testing.T) {
|
||||
|
||||
t.SkipNow()
|
||||
|
||||
t.Run("Set Field Value", func(t *testing.T) {
|
||||
formPost := map[string][]string{}
|
||||
formPost["path"] = []string{"unix:///var/run/docker.sock"}
|
||||
formPost["version"] = []string{"1.25"}
|
||||
_, err := SetFields(CsvIntegrator, formPost)
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Get Field Value", func(t *testing.T) {
|
||||
path := Value(DockerIntegrator, "path").(string)
|
||||
version := Value(DockerIntegrator, "version").(string)
|
||||
assert.Equal(t, "unix:///var/run/docker.sock", path)
|
||||
assert.Equal(t, "1.25", version)
|
||||
})
|
||||
|
||||
t.Run("List Services from Docker", func(t *testing.T) {
|
||||
services, err := DockerIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 0, len(services))
|
||||
})
|
||||
|
||||
t.Run("Confirm Services from Docker", func(t *testing.T) {
|
||||
services, err := DockerIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
for _, s := range services {
|
||||
t.Log(s)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 integrators
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
Integrations []integrations.Integrator
|
||||
log = utils.Log.WithField("type", "integration")
|
||||
db database.Database
|
||||
)
|
||||
|
||||
//func init() {
|
||||
// Integrations = append(Integrations,
|
||||
// CsvIntegrator,
|
||||
// DockerIntegrator,
|
||||
// TraefikIntegrator,
|
||||
// )
|
||||
//}
|
||||
|
||||
func init() {
|
||||
AddIntegrations(
|
||||
CsvIntegrator,
|
||||
TraefikIntegrator,
|
||||
DockerIntegrator,
|
||||
)
|
||||
}
|
||||
|
||||
// integrationsDb returns the 'integrations' database column
|
||||
func integrationsDb() database.Database {
|
||||
return db.Model(&integrations.Integration{})
|
||||
}
|
||||
|
||||
// SetDB is called by core to inject the database for a integrator to use
|
||||
func SetDB(d database.Database) {
|
||||
db = d
|
||||
}
|
||||
|
||||
func Value(intg integrations.Integrator, fieldName string) interface{} {
|
||||
for _, v := range intg.Get().Fields {
|
||||
if fieldName == v.Name {
|
||||
return v.Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Update(integrator *integrations.Integration) error {
|
||||
fields := FieldsToJson(integrator)
|
||||
fmt.Println(fields)
|
||||
set := db.Model(&integrations.Integration{}).Where("name = ?", integrator.Name)
|
||||
set.Set("enabled", integrator.Enabled)
|
||||
set.Set("fields", fields)
|
||||
return set.Error()
|
||||
}
|
||||
|
||||
func FieldsToJson(integrator *integrations.Integration) string {
|
||||
jsonData := make(map[string]interface{})
|
||||
for _, v := range integrator.Fields {
|
||||
jsonData[v.Name] = v.Value
|
||||
}
|
||||
data, _ := json.Marshal(jsonData)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func JsonToFields(intg integrations.Integrator, input string) []*integrations.IntegrationField {
|
||||
integrator := intg.Get()
|
||||
var jsonData map[string]interface{}
|
||||
json.Unmarshal([]byte(input), &jsonData)
|
||||
|
||||
for _, v := range integrator.Fields {
|
||||
v.Value = jsonData[v.Name]
|
||||
}
|
||||
return integrator.Fields
|
||||
}
|
||||
|
||||
func SetFields(intg integrations.Integrator, data map[string][]string) (*integrations.Integration, error) {
|
||||
i := intg.Get()
|
||||
for _, v := range i.Fields {
|
||||
if data[v.Name] != nil {
|
||||
v.Value = data[v.Name][0]
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func Find(name string) (integrations.Integrator, error) {
|
||||
for _, i := range Integrations {
|
||||
obj := i.Get()
|
||||
if obj.ShortName == name {
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New(name + " not found")
|
||||
}
|
||||
|
||||
// db will return the notifier database column/record
|
||||
func integratorDb(n *integrations.Integration) database.Database {
|
||||
return db.Model(&integrations.Integration{}).Where("name = ?", n.Name).Find(n)
|
||||
}
|
||||
|
||||
// isInDatabase returns true if the integration has already been installed
|
||||
func isInDatabase(i integrations.Integrator) bool {
|
||||
inDb := integratorDb(i.Get()).RecordNotFound()
|
||||
return !inDb
|
||||
}
|
||||
|
||||
// SelectIntegration returns the Notification struct from the database
|
||||
func SelectIntegration(i integrations.Integrator) (*integrations.Integration, error) {
|
||||
integration := i.Get()
|
||||
err := db.Model(&integrations.Integration{}).Where("name = ?", integration.Name).Scan(&integration)
|
||||
return integration, err.Error()
|
||||
}
|
||||
|
||||
// AddIntegrations accept a Integrator interface to be added into the array
|
||||
func AddIntegrations(inte ...integrations.Integrator) error {
|
||||
for _, i := range inte {
|
||||
if utils.IsType(i, new(integrations.Integrator)) {
|
||||
Integrations = append(Integrations, i)
|
||||
err := install(i)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return errors.New("notifier does not have the required methods")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// install will check the database for the notification, if its not inserted it will insert a new record for it
|
||||
func install(i integrations.Integrator) error {
|
||||
_, err := insertDatabase(i)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// insertDatabase will create a new record into the database for the integrator
|
||||
func insertDatabase(i integrations.Integrator) (string, error) {
|
||||
integrator := i.Get()
|
||||
query := db.FirstOrCreate(integrator)
|
||||
if query.Error() != nil {
|
||||
return "", query.Error()
|
||||
}
|
||||
return integrator.Name, query.Error()
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
name,domain,expected,expected_status,interval,type,method,post_data,port,timeout,order,allow_notifications,public,group_id,headers,permalink,verify_ssl
|
||||
Bulk Upload,http://google.com,,200,60s,http,get,,,60s,1,TRUE,TRUE,,Authorization=example,bulk_example,FALSE
|
||||
JSON Post,https://jsonplaceholder.typicode.com/posts,,200,1m,http,post,"{""id"": 1, ""title"": 'foo', ""body"": 'bar', ""userId"": 1}",,15s,2,TRUE,TRUE,,Content-Type=application/json,json_post_example,FALSE
|
||||
Google DNS,8.8.8.8,,,60s,tcp,,,53,10s,3,TRUE,TRUE,,,google_dns_example,FALSE
|
||||
Google DNS UDP,8.8.8.8,,,60s,udp,,,53,10s,4,TRUE,TRUE,,,google_dns_udp_example,FALSE
|
||||
Statping Demo Page,https://demo.statping.com/health,"(\""online\"": true)",200,30s,http,get,,,10s,5,TRUE,TRUE,,,demo_link,FALSE
|
||||
Statping MySQL Page,https://mysql.statping.com/health,"(\""online\"": true)",200,30s,http,get,,,10s,6,TRUE,TRUE,,,mysql_demo_link,FALSE
|
||||
Statping SQLite Page,https://sqlite.statping.com/health,"(\""online\"": true)",200,30s,http,get,,,10s,7,TRUE,TRUE,,,sqlite_demo_link,FALSE
|
||||
Token Balance,https://status.tokenbalance.com/health,"(\""online\"": true)",200,30s,http,get,,,10s,8,TRUE,TRUE,,,token_balance,FALSE
|
||||
CloudFlare DNS,1.1.1.1,,,60s,tcp,,,53,10s,9,TRUE,TRUE,,,cloudflare_dns_example,FALSE
|
||||
Verisign DNS,64.6.64.4,,,60s,tcp,,,53,10s,10,TRUE,TRUE,,,verisign_dns_example,FALSE
|
|
|
@ -1,127 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 integrators
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type traefikIntegration struct {
|
||||
*integrations.Integration
|
||||
}
|
||||
|
||||
var TraefikIntegrator = &traefikIntegration{&integrations.Integration{
|
||||
ShortName: "traefik",
|
||||
Name: "Traefik",
|
||||
Icon: "<i class=\"fas fa-network-wired\"></i>",
|
||||
Description: ``,
|
||||
Fields: []*integrations.IntegrationField{
|
||||
{
|
||||
Name: "endpoint",
|
||||
Description: "The URL for the traefik API Endpoint",
|
||||
Type: "text",
|
||||
Value: "http://localhost:8080",
|
||||
},
|
||||
{
|
||||
Name: "username",
|
||||
Description: "Username for HTTP Basic Authentication",
|
||||
Type: "text",
|
||||
},
|
||||
{
|
||||
Name: "password",
|
||||
Description: "Password for HTTP Basic Authentication",
|
||||
Type: "password",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
func (t *traefikIntegration) Get() *integrations.Integration {
|
||||
return t.Integration
|
||||
}
|
||||
|
||||
func (t *traefikIntegration) List() ([]*services.Service, error) {
|
||||
var err error
|
||||
var services []*services.Service
|
||||
|
||||
endpoint := Value(t, "endpoint").(string)
|
||||
|
||||
httpServices, err := fetchMethod(endpoint, "http")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
services = append(services, httpServices...)
|
||||
|
||||
tcpServices, err := fetchMethod(endpoint, "tcp")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
services = append(services, tcpServices...)
|
||||
|
||||
return services, err
|
||||
}
|
||||
|
||||
func fetchMethod(endpoint, method string) ([]*services.Service, error) {
|
||||
var traefikServices []traefikService
|
||||
var srvs []*services.Service
|
||||
d, _, err := utils.HttpRequest(endpoint+"/api/"+method+"/services", "GET", nil, []string{}, nil, 10*time.Second, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.Unmarshal(d, &traefikServices); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, s := range traefikServices {
|
||||
log.Infoln(s)
|
||||
|
||||
for _, l := range s.LoadBalancer.Servers {
|
||||
|
||||
url, err := url.Parse(l.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
service := &services.Service{
|
||||
Name: s.Name,
|
||||
Domain: url.Hostname(),
|
||||
Port: int(utils.ToInt(url.Port())),
|
||||
Type: method,
|
||||
Interval: 60,
|
||||
Timeout: 2,
|
||||
}
|
||||
srvs = append(srvs, service)
|
||||
|
||||
}
|
||||
}
|
||||
return srvs, err
|
||||
}
|
||||
|
||||
type traefikService struct {
|
||||
Status string `json:"status"`
|
||||
UsedBy []string `json:"usedBy"`
|
||||
Name string `json:"name"`
|
||||
Provider string `json:"provider"`
|
||||
LoadBalancer struct {
|
||||
Servers []struct {
|
||||
URL string `json:"url"`
|
||||
} `json:"servers"`
|
||||
PassHostHeader bool `json:"passHostHeader"`
|
||||
} `json:"loadBalancer,omitempty"`
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
package integrators
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTraefikIntegration(t *testing.T) {
|
||||
|
||||
t.SkipNow()
|
||||
|
||||
t.Run("List Services from Traefik", func(t *testing.T) {
|
||||
services, err := TraefikIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
assert.NotEqual(t, 0, len(services))
|
||||
})
|
||||
|
||||
t.Run("Confirm Services from Traefik", func(t *testing.T) {
|
||||
services, err := TraefikIntegrator.List()
|
||||
require.Nil(t, err)
|
||||
for _, s := range services {
|
||||
t.Log(s)
|
||||
}
|
||||
})
|
||||
|
||||
}
|
|
@ -25,12 +25,14 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*commandLine)(nil)
|
||||
|
||||
type commandLine struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
||||
var Command = &commandLine{¬ifications.Notification{
|
||||
Method: "Command",
|
||||
Method: "command",
|
||||
Title: "Shell Command",
|
||||
Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.",
|
||||
Author: "Hunter Long",
|
||||
|
|
|
@ -1,102 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
commandTest = "curl -I https://statping.com/"
|
||||
)
|
||||
|
||||
func TestCommandNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
Command.Host = "sh"
|
||||
Command.Var1 = commandTest
|
||||
Command.Var2 = commandTest
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load Command", func(t *testing.T) {
|
||||
Command.Host = "sh"
|
||||
Command.Var1 = commandTest
|
||||
Command.Var2 = commandTest
|
||||
Command.Delay = time.Duration(100 * time.Millisecond)
|
||||
Command.Limits = 99
|
||||
err := AddNotifiers(Command)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Command.Author)
|
||||
assert.Equal(t, "sh", Command.Host)
|
||||
assert.Equal(t, commandTest, Command.Var1)
|
||||
assert.Equal(t, commandTest, Command.Var2)
|
||||
})
|
||||
|
||||
t.Run("Command Notifier Tester", func(t *testing.T) {
|
||||
assert.True(t, Command.CanTest())
|
||||
})
|
||||
|
||||
t.Run("Command Within Limits", func(t *testing.T) {
|
||||
ok, err := Command.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Command OnFailure", func(t *testing.T) {
|
||||
Command.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Command.Queue))
|
||||
})
|
||||
|
||||
t.Run("Command OnSuccess", func(t *testing.T) {
|
||||
Command.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Command.Queue))
|
||||
})
|
||||
|
||||
t.Run("Command OnSuccess Again", func(t *testing.T) {
|
||||
Command.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Command.Queue))
|
||||
go notifications.Queue(Command)
|
||||
time.Sleep(20 * time.Second)
|
||||
assert.Equal(t, 0, len(Command.Queue))
|
||||
})
|
||||
|
||||
t.Run("Command Within Limits again", func(t *testing.T) {
|
||||
ok, err := Command.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Command Send", func(t *testing.T) {
|
||||
Command.Send(commandTest)
|
||||
assert.Equal(t, 0, len(Command.Queue))
|
||||
})
|
||||
|
||||
t.Run("Command Test", func(t *testing.T) {
|
||||
Command.OnTest()
|
||||
})
|
||||
|
||||
t.Run("Command Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Command)
|
||||
time.Sleep(5 * time.Second)
|
||||
assert.Equal(t, "sh", Command.Host)
|
||||
assert.Equal(t, commandTest, Command.Var1)
|
||||
assert.Equal(t, commandTest, Command.Var2)
|
||||
assert.Equal(t, 0, len(Command.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*discord)(nil)
|
||||
|
||||
type discord struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
DISCORD_URL = os.Getenv("DISCORD_URL")
|
||||
discordMessage = `{"content": "The discord notifier on Statping has been tested!"}`
|
||||
)
|
||||
|
||||
func init() {
|
||||
DISCORD_URL = os.Getenv("DISCORD_URL")
|
||||
Discorder.Host = DISCORD_URL
|
||||
}
|
||||
|
||||
func TestDiscordNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
if DISCORD_URL == "" {
|
||||
t.Log("discord notifier testing skipped, missing DISCORD_URL environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load discord", func(t *testing.T) {
|
||||
Discorder.Host = DISCORD_URL
|
||||
Discorder.Delay = time.Duration(100 * time.Millisecond)
|
||||
err := AddNotifiers(Discorder)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Discorder.Author)
|
||||
assert.Equal(t, DISCORD_URL, Discorder.Host)
|
||||
})
|
||||
|
||||
t.Run("discord Notifier Tester", func(t *testing.T) {
|
||||
assert.True(t, Discorder.CanTest())
|
||||
})
|
||||
|
||||
t.Run("discord Within Limits", func(t *testing.T) {
|
||||
ok, err := Discorder.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("discord OnFailure", func(t *testing.T) {
|
||||
Discorder.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Discorder.Queue))
|
||||
})
|
||||
|
||||
t.Run("discord OnSuccess", func(t *testing.T) {
|
||||
Discorder.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Discorder.Queue))
|
||||
})
|
||||
|
||||
t.Run("discord Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("discord OnSuccess Again", func(t *testing.T) {
|
||||
Discorder.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Discorder.Queue))
|
||||
})
|
||||
|
||||
t.Run("discord Send", func(t *testing.T) {
|
||||
err := Discorder.Send(discordMessage)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("discord Test", func(t *testing.T) {
|
||||
err := Discorder.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("discord Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Discorder)
|
||||
time.Sleep(1 * time.Second)
|
||||
assert.Equal(t, DISCORD_URL, Discorder.Host)
|
||||
assert.Equal(t, 0, len(Discorder.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -29,6 +29,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*email)(nil)
|
||||
|
||||
const (
|
||||
mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
|
|
@ -1,136 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
EMAIL_HOST string
|
||||
EMAIL_USER string
|
||||
EMAIL_PASS string
|
||||
EMAIL_OUTGOING string
|
||||
EMAIL_SEND_TO string
|
||||
EMAIL_PORT int64
|
||||
)
|
||||
|
||||
var testEmail *emailOutgoing
|
||||
|
||||
func init() {
|
||||
EMAIL_HOST = os.Getenv("EMAIL_HOST")
|
||||
EMAIL_USER = os.Getenv("EMAIL_USER")
|
||||
EMAIL_PASS = os.Getenv("EMAIL_PASS")
|
||||
EMAIL_OUTGOING = os.Getenv("EMAIL_OUTGOING")
|
||||
EMAIL_SEND_TO = os.Getenv("EMAIL_SEND_TO")
|
||||
EMAIL_PORT = utils.ToInt(os.Getenv("EMAIL_PORT"))
|
||||
|
||||
Emailer.Host = EMAIL_HOST
|
||||
Emailer.Username = EMAIL_USER
|
||||
Emailer.Password = EMAIL_PASS
|
||||
Emailer.Var1 = EMAIL_OUTGOING
|
||||
Emailer.Var2 = EMAIL_SEND_TO
|
||||
Emailer.Port = int(EMAIL_PORT)
|
||||
}
|
||||
|
||||
func TestEmailNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
if EMAIL_HOST == "" || EMAIL_USER == "" || EMAIL_PASS == "" {
|
||||
t.Log("email notifier testing skipped, missing EMAIL_ environment variables")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("New Emailer", func(t *testing.T) {
|
||||
Emailer.Host = EMAIL_HOST
|
||||
Emailer.Username = EMAIL_USER
|
||||
Emailer.Password = EMAIL_PASS
|
||||
Emailer.Var1 = EMAIL_OUTGOING
|
||||
Emailer.Var2 = EMAIL_SEND_TO
|
||||
Emailer.Port = int(EMAIL_PORT)
|
||||
Emailer.Delay = time.Duration(100 * time.Millisecond)
|
||||
|
||||
testEmail = &emailOutgoing{
|
||||
To: Emailer.GetValue("var2"),
|
||||
Subject: fmt.Sprintf("Service %v is Failing", TestService.Name),
|
||||
Template: mainEmailTemplate,
|
||||
Data: TestService,
|
||||
From: Emailer.GetValue("var1"),
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Add email Notifier", func(t *testing.T) {
|
||||
err := AddNotifiers(Emailer)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Emailer.Author)
|
||||
assert.Equal(t, EMAIL_HOST, Emailer.Host)
|
||||
})
|
||||
|
||||
t.Run("email Within Limits", func(t *testing.T) {
|
||||
ok, err := Emailer.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("email Test Source", func(t *testing.T) {
|
||||
emailSource(testEmail)
|
||||
assert.NotEmpty(t, testEmail.Source)
|
||||
})
|
||||
|
||||
t.Run("email OnFailure", func(t *testing.T) {
|
||||
Emailer.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Emailer.Queue))
|
||||
})
|
||||
|
||||
t.Run("email OnSuccess", func(t *testing.T) {
|
||||
Emailer.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Emailer.Queue))
|
||||
})
|
||||
|
||||
t.Run("email Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("email OnSuccess Again", func(t *testing.T) {
|
||||
Emailer.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Emailer.Queue))
|
||||
})
|
||||
|
||||
t.Run("email Send", func(t *testing.T) {
|
||||
err := Emailer.Send(testEmail)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Emailer Test", func(t *testing.T) {
|
||||
t.SkipNow()
|
||||
err := Emailer.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("email Run Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Emailer)
|
||||
time.Sleep(6 * time.Second)
|
||||
assert.Equal(t, EMAIL_HOST, Emailer.Host)
|
||||
assert.Equal(t, 0, len(Emailer.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -26,8 +26,10 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*lineNotifier)(nil)
|
||||
|
||||
const (
|
||||
lineNotifyMethod = "line notify"
|
||||
lineNotifyMethod = "line_notify"
|
||||
)
|
||||
|
||||
type lineNotifier struct {
|
||||
|
|
|
@ -26,6 +26,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*mobilePush)(nil)
|
||||
|
||||
const mobileIdentifier = "com.statping"
|
||||
|
||||
type mobilePush struct {
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
MOBILE_ID string
|
||||
MOBILE_NUMBER string
|
||||
)
|
||||
|
||||
func init() {
|
||||
MOBILE_ID = os.Getenv("MOBILE_ID")
|
||||
MOBILE_NUMBER = os.Getenv("MOBILE_NUMBER")
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
}
|
||||
|
||||
func TestMobileNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
Mobile.Var2 = os.Getenv("MOBILE_NUMBER")
|
||||
if MOBILE_ID == "" {
|
||||
t.Log("Mobile notifier testing skipped, missing MOBILE_ID environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load Mobile", func(t *testing.T) {
|
||||
Mobile.Var1 = MOBILE_ID
|
||||
Mobile.Var2 = MOBILE_NUMBER
|
||||
Mobile.Delay = time.Duration(100 * time.Millisecond)
|
||||
Mobile.Limits = 10
|
||||
err := AddNotifiers(Mobile)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Mobile.Author)
|
||||
assert.Equal(t, MOBILE_ID, Mobile.Var1)
|
||||
assert.Equal(t, MOBILE_NUMBER, Mobile.Var2)
|
||||
})
|
||||
|
||||
t.Run("Mobile Notifier Tester", func(t *testing.T) {
|
||||
assert.True(t, Mobile.CanTest())
|
||||
})
|
||||
|
||||
t.Run("Mobile Within Limits", func(t *testing.T) {
|
||||
ok, err := Mobile.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Mobile OnFailure", func(t *testing.T) {
|
||||
Mobile.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Mobile.Queue))
|
||||
})
|
||||
|
||||
t.Run("Mobile OnSuccess", func(t *testing.T) {
|
||||
Mobile.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Mobile.Queue))
|
||||
})
|
||||
|
||||
t.Run("Mobile OnSuccess Again", func(t *testing.T) {
|
||||
t.SkipNow()
|
||||
assert.True(t, TestService.Online)
|
||||
Mobile.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Mobile.Queue))
|
||||
go notifications.Queue(Mobile)
|
||||
time.Sleep(20 * time.Second)
|
||||
assert.Equal(t, 1, len(Mobile.Queue))
|
||||
})
|
||||
|
||||
t.Run("Mobile Within Limits again", func(t *testing.T) {
|
||||
ok, err := Mobile.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Mobile Test", func(t *testing.T) {
|
||||
t.SkipNow()
|
||||
err := Mobile.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Mobile Queue", func(t *testing.T) {
|
||||
t.SkipNow()
|
||||
go notifications.Queue(Mobile)
|
||||
time.Sleep(15 * time.Second)
|
||||
assert.Equal(t, MOBILE_ID, Mobile.Var1)
|
||||
assert.Equal(t, 0, len(Mobile.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -5,7 +5,6 @@ import (
|
|||
"github.com/google/martian/log"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -13,9 +12,8 @@ var (
|
|||
allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
|
||||
)
|
||||
|
||||
func checkNotifierForm(n notifications.Notifier) error {
|
||||
notifier := n.Select()
|
||||
for _, f := range notifier.Form {
|
||||
func checkNotifierForm(n *notifications.Notification) error {
|
||||
for _, f := range n.Form {
|
||||
contains := contains(f.DbField, allowedVars)
|
||||
if !contains {
|
||||
return fmt.Errorf("the DbField '%v' is not allowed, allowed vars: %v", f.DbField, allowedVars)
|
||||
|
@ -35,34 +33,50 @@ func contains(s string, arr []string) bool {
|
|||
|
||||
// AddNotifier accept a Notifier interface to be added into the array
|
||||
func AddNotifiers(notifiers ...notifications.Notifier) error {
|
||||
log.Infof("Initiating %d Notifiers\n", len(notifiers))
|
||||
|
||||
for _, n := range notifiers {
|
||||
log.Infof("Installing %s Notifier...", n.Select().Method)
|
||||
if err := checkNotifierForm(n); err != nil {
|
||||
return errors.Wrap(err, "error with notifier form fields")
|
||||
notif := n.Select()
|
||||
log.Infof("Initiating %s Notifier\n", notif.Method)
|
||||
|
||||
if err := checkNotifierForm(notif); err != nil {
|
||||
log.Errorf(err.Error())
|
||||
return err
|
||||
}
|
||||
if _, err := notifications.Init(n); err != nil {
|
||||
return errors.Wrap(err, "error initiating notifier")
|
||||
|
||||
log.Infof("Creating %s Notifier\n", notif.Method)
|
||||
if err := notif.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
notifications.Append(notif)
|
||||
|
||||
if notif.Enabled.Bool {
|
||||
notif.Close()
|
||||
notif.Start()
|
||||
go notifications.Queue(notif)
|
||||
}
|
||||
|
||||
}
|
||||
startAllNotifiers()
|
||||
return nil
|
||||
}
|
||||
|
||||
// startAllNotifiers will start the go routine for each loaded notifier
|
||||
func startAllNotifiers() {
|
||||
for _, comm := range notifications.AllCommunications {
|
||||
if utils.IsType(comm, new(notifications.Notifier)) {
|
||||
notify := comm.(notifications.Notifier)
|
||||
if notify.Select().Enabled.Bool {
|
||||
notify.Select().Close()
|
||||
notify.Select().Start()
|
||||
for _, notify := range notifications.All() {
|
||||
n := notify.Select()
|
||||
log.Infof("Initiating %s Notifier\n", n.Method)
|
||||
if utils.IsType(notify, new(notifications.Notifier)) {
|
||||
if n.Enabled.Bool {
|
||||
n.Close()
|
||||
n.Start()
|
||||
go notifications.Queue(notify)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func AttachNotifiers() error {
|
||||
func Migrate() error {
|
||||
return AddNotifiers(
|
||||
Command,
|
||||
Discorder,
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/source"
|
||||
"github.com/hunterlong/statping/types/failures"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/types/users"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
db *gorm.DB
|
||||
currentCount int
|
||||
)
|
||||
|
||||
var TestService = &services.Service{
|
||||
Id: 1,
|
||||
Name: "Interpol - All The Rage Back Home",
|
||||
Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU",
|
||||
ExpectedStatus: 200,
|
||||
Expected: null.NewNullString("test example"),
|
||||
Interval: 30,
|
||||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 20,
|
||||
LastStatusCode: 404,
|
||||
Online: true,
|
||||
LastResponse: "<html>this is an example response</html>",
|
||||
CreatedAt: utils.Now().Add(-24 * time.Hour),
|
||||
}
|
||||
|
||||
var TestFailure = &failures.Failure{
|
||||
Issue: "testing",
|
||||
Service: 1,
|
||||
CreatedAt: utils.Now().Add(-12 * time.Hour),
|
||||
}
|
||||
|
||||
var TestUser = &users.User{
|
||||
Username: "admin",
|
||||
Email: "info@email.com",
|
||||
}
|
||||
|
||||
func CountNotifiers() int {
|
||||
return len(notifications.AllCommunications)
|
||||
}
|
||||
|
||||
func init() {
|
||||
dir = utils.Directory
|
||||
source.Assets()
|
||||
utils.InitLogs()
|
||||
injectDatabase()
|
||||
}
|
||||
|
||||
func injectDatabase() {
|
||||
utils.DeleteFile(dir + "/notifiers.db")
|
||||
db, err := gorm.Open("sqlite3", dir+"/notifiers.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.CreateTable(¬ifications.Notification{})
|
||||
notifications.SetDB(&database.Db{db, "sqlite3"})
|
||||
}
|
|
@ -28,6 +28,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*slack)(nil)
|
||||
|
||||
const (
|
||||
slackMethod = "slack"
|
||||
failingTemplate = `{ "attachments": [ { "fallback": "Service {{.Service.Name}} - is currently failing", "text": "Your Statping service <{{.Service.Domain}}|{{.Service.Name}}> has just received a Failure notification based on your expected results. {{.Service.Name}} responded with a HTTP Status code of {{.Service.LastStatusCode}}.", "fields": [ { "title": "Expected Status Code", "value": "{{.Service.ExpectedStatus}}", "short": true }, { "title": "Received Status Code", "value": "{{.Service.LastStatusCode}}", "short": true } ,{ "title": "Error Message", "value": "{{.Issue}}", "short": false } ], "color": "#FF0000", "thumb_url": "https://statping.com", "footer": "Statping", "footer_icon": "https://img.cjx.io/statuplogo32.png" } ] }`
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
SLACK_URL string
|
||||
slackTestMessage = `{"text":"this is a test from the slack notifier!"}`
|
||||
)
|
||||
|
||||
func init() {
|
||||
SLACK_URL = os.Getenv("SLACK_URL")
|
||||
Slacker.Host = SLACK_URL
|
||||
}
|
||||
|
||||
func TestSlackNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
SLACK_URL = os.Getenv("SLACK_URL")
|
||||
Slacker.Host = SLACK_URL
|
||||
if SLACK_URL == "" {
|
||||
t.Log("slack notifier testing skipped, missing SLACK_URL environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load slack", func(t *testing.T) {
|
||||
Slacker.Host = SLACK_URL
|
||||
Slacker.Delay = time.Duration(100 * time.Millisecond)
|
||||
Slacker.Limits = 3
|
||||
err := AddNotifiers(Slacker)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Slacker.Author)
|
||||
assert.Equal(t, SLACK_URL, Slacker.Host)
|
||||
})
|
||||
|
||||
t.Run("slack Notifier Tester", func(t *testing.T) {
|
||||
assert.True(t, Slacker.CanTest())
|
||||
})
|
||||
|
||||
//t.Run("slack parse message", func(t *testing.T) {
|
||||
// err := parseSlackMessage(slackText, "this is a test!")
|
||||
// assert.Nil(t, err)
|
||||
// assert.Equal(t, 1, len(Slacker.Queue))
|
||||
//})
|
||||
|
||||
t.Run("slack Within Limits", func(t *testing.T) {
|
||||
ok, err := Slacker.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("slack OnFailure", func(t *testing.T) {
|
||||
Slacker.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Slacker.Queue))
|
||||
})
|
||||
|
||||
t.Run("slack OnSuccess", func(t *testing.T) {
|
||||
Slacker.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Slacker.Queue))
|
||||
})
|
||||
|
||||
t.Run("slack OnSuccess Again", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
Slacker.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Slacker.Queue))
|
||||
go notifications.Queue(Slacker)
|
||||
time.Sleep(15 * time.Second)
|
||||
assert.Equal(t, 0, len(Slacker.Queue))
|
||||
})
|
||||
|
||||
t.Run("slack Within Limits again", func(t *testing.T) {
|
||||
ok, err := Slacker.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("slack Send", func(t *testing.T) {
|
||||
err := Slacker.Send(slackTestMessage)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 0, len(Slacker.Queue))
|
||||
})
|
||||
|
||||
t.Run("slack Test", func(t *testing.T) {
|
||||
err := Slacker.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("slack Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Slacker)
|
||||
time.Sleep(10 * time.Second)
|
||||
assert.Equal(t, SLACK_URL, Slacker.Host)
|
||||
assert.Equal(t, 0, len(Slacker.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*telegram)(nil)
|
||||
|
||||
type telegram struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
|
|
@ -1,105 +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/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
telegramToken string
|
||||
telegramChannel string
|
||||
telegramMessage = "The Telegram notifier on Statping has been tested!"
|
||||
)
|
||||
|
||||
func init() {
|
||||
telegramToken = os.Getenv("TELEGRAM_TOKEN")
|
||||
telegramChannel = os.Getenv("TELEGRAM_CHANNEL")
|
||||
Telegram.ApiSecret = telegramToken
|
||||
Telegram.Var1 = telegramChannel
|
||||
}
|
||||
|
||||
func TestTelegramNotifier(t *testing.T) {
|
||||
t.SkipNow()
|
||||
t.Parallel()
|
||||
if telegramToken == "" || telegramChannel == "" {
|
||||
t.Log("Telegram notifier testing skipped, missing TELEGRAM_TOKEN and TELEGRAM_CHANNEL environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load Telegram", func(t *testing.T) {
|
||||
Telegram.ApiSecret = telegramToken
|
||||
Telegram.Var1 = telegramChannel
|
||||
Telegram.Delay = time.Duration(1 * time.Second)
|
||||
err := AddNotifiers(Telegram)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Telegram.Author)
|
||||
assert.Equal(t, telegramToken, Telegram.ApiSecret)
|
||||
assert.Equal(t, telegramChannel, Telegram.Var1)
|
||||
})
|
||||
|
||||
t.Run("Telegram Within Limits", func(t *testing.T) {
|
||||
ok, err := Telegram.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Telegram OnFailure", func(t *testing.T) {
|
||||
Telegram.OnFailure(TestService, TestFailure)
|
||||
assert.Equal(t, 1, len(Telegram.Queue))
|
||||
})
|
||||
|
||||
t.Run("Telegram Check Offline", func(t *testing.T) {
|
||||
assert.False(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("Telegram OnSuccess", func(t *testing.T) {
|
||||
Telegram.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Telegram.Queue))
|
||||
})
|
||||
|
||||
t.Run("Telegram Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("Telegram OnSuccess Again", func(t *testing.T) {
|
||||
Telegram.OnSuccess(TestService)
|
||||
assert.Equal(t, 1, len(Telegram.Queue))
|
||||
})
|
||||
|
||||
t.Run("Telegram Send", func(t *testing.T) {
|
||||
err := Telegram.Send(telegramMessage)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Telegram Test", func(t *testing.T) {
|
||||
err := Telegram.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Telegram Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Telegram)
|
||||
time.Sleep(3 * time.Second)
|
||||
assert.Equal(t, telegramToken, Telegram.ApiSecret)
|
||||
assert.Equal(t, 0, len(Telegram.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -28,6 +28,8 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*twilio)(nil)
|
||||
|
||||
type twilio struct {
|
||||
*notifications.Notification
|
||||
}
|
||||
|
|
|
@ -1,109 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
TWILIO_SID = os.Getenv("TWILIO_SID")
|
||||
TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
|
||||
TWILIO_FROM = os.Getenv("TWILIO_FROM")
|
||||
TWILIO_TO = os.Getenv("TWILIO_TO")
|
||||
twilioMessage = "The Twilio notifier on Statping has been tested!"
|
||||
)
|
||||
|
||||
func init() {
|
||||
TWILIO_SID = os.Getenv("TWILIO_SID")
|
||||
TWILIO_SECRET = os.Getenv("TWILIO_SECRET")
|
||||
TWILIO_FROM = os.Getenv("TWILIO_FROM")
|
||||
TWILIO_TO = os.Getenv("TWILIO_TO")
|
||||
|
||||
Twilio.ApiKey = TWILIO_SID
|
||||
Twilio.ApiSecret = TWILIO_SECRET
|
||||
Twilio.Var1 = TWILIO_TO
|
||||
Twilio.Var2 = TWILIO_FROM
|
||||
}
|
||||
|
||||
func TestTwilioNotifier(t *testing.T) {
|
||||
t.SkipNow()
|
||||
if TWILIO_SID == "" || TWILIO_SECRET == "" || TWILIO_FROM == "" {
|
||||
t.Log("twilio notifier testing skipped, missing TWILIO_SID environment variable")
|
||||
t.SkipNow()
|
||||
}
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load Twilio", func(t *testing.T) {
|
||||
Twilio.ApiKey = TWILIO_SID
|
||||
Twilio.Delay = time.Duration(100 * time.Millisecond)
|
||||
err := AddNotifiers(Twilio)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Twilio.Author)
|
||||
assert.Equal(t, TWILIO_SID, Twilio.ApiKey)
|
||||
})
|
||||
|
||||
t.Run("Twilio Within Limits", func(t *testing.T) {
|
||||
ok, err := Twilio.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnFailure", func(t *testing.T) {
|
||||
Twilio.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, Twilio.Queue, 1)
|
||||
})
|
||||
|
||||
t.Run("Twilio Check Offline", func(t *testing.T) {
|
||||
assert.False(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnSuccess", func(t *testing.T) {
|
||||
Twilio.OnSuccess(TestService)
|
||||
assert.Len(t, Twilio.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Twilio Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("Twilio OnSuccess Again", func(t *testing.T) {
|
||||
Twilio.OnSuccess(TestService)
|
||||
assert.Len(t, Twilio.Queue, 2)
|
||||
})
|
||||
|
||||
t.Run("Twilio Send", func(t *testing.T) {
|
||||
err := Twilio.Send(twilioMessage)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Twilio Test", func(t *testing.T) {
|
||||
err := Twilio.OnTest()
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Twilio Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Twilio)
|
||||
time.Sleep(1 * time.Second)
|
||||
assert.Equal(t, TWILIO_SID, Twilio.ApiKey)
|
||||
assert.Equal(t, 0, len(Twilio.Queue))
|
||||
})
|
||||
|
||||
}
|
|
@ -28,8 +28,10 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ notifications.Notifier = (*webhooker)(nil)
|
||||
|
||||
const (
|
||||
webhookMethod = "Webhook"
|
||||
webhookMethod = "webhook"
|
||||
)
|
||||
|
||||
type webhooker struct {
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifiers
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
webhookTestUrl = "https://statping.com"
|
||||
webhookMessage = `{"id": "%service.Id","name": "%service.Name","online": "%service.Online","issue": "%failure.Issue"}`
|
||||
apiKey = "application/json"
|
||||
fullMsg string
|
||||
)
|
||||
|
||||
func init() {
|
||||
Webhook.Host = webhookTestUrl
|
||||
Webhook.Var1 = "POST"
|
||||
Webhook.Var2 = webhookMessage
|
||||
Webhook.ApiKey = "application/json"
|
||||
}
|
||||
|
||||
func TestWebhookNotifier(t *testing.T) {
|
||||
t.Parallel()
|
||||
currentCount = CountNotifiers()
|
||||
|
||||
t.Run("Load webhooker", func(t *testing.T) {
|
||||
Webhook.Host = webhookTestUrl
|
||||
Webhook.Delay = time.Duration(100 * time.Millisecond)
|
||||
Webhook.ApiKey = apiKey
|
||||
err := AddNotifiers(Webhook)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "Hunter Long", Webhook.Author)
|
||||
assert.Equal(t, webhookTestUrl, Webhook.Host)
|
||||
assert.Equal(t, apiKey, Webhook.ApiKey)
|
||||
})
|
||||
|
||||
t.Run("webhooker Notifier Tester", func(t *testing.T) {
|
||||
assert.True(t, Webhook.CanTest())
|
||||
})
|
||||
|
||||
t.Run("webhooker Replace Body Text", func(t *testing.T) {
|
||||
fullMsg = replaceBodyText(webhookMessage, TestService, TestFailure)
|
||||
assert.Equal(t, `{"id": "1","name": "Interpol - All The Rage Back Home","online": "true","issue": "testing"}`, fullMsg)
|
||||
})
|
||||
|
||||
t.Run("webhooker Within Limits", func(t *testing.T) {
|
||||
ok, err := Webhook.WithinLimits()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
t.Run("webhooker OnFailure", func(t *testing.T) {
|
||||
Webhook.OnFailure(TestService, TestFailure)
|
||||
assert.Len(t, Webhook.Queue, 1)
|
||||
})
|
||||
|
||||
t.Run("webhooker OnSuccess", func(t *testing.T) {
|
||||
Webhook.OnSuccess(TestService)
|
||||
assert.Equal(t, len(Webhook.Queue), 1)
|
||||
})
|
||||
|
||||
t.Run("webhooker Check Back Online", func(t *testing.T) {
|
||||
assert.True(t, TestService.Online)
|
||||
})
|
||||
|
||||
t.Run("webhooker OnSuccess Again", func(t *testing.T) {
|
||||
Webhook.OnSuccess(TestService)
|
||||
assert.Equal(t, len(Webhook.Queue), 1)
|
||||
})
|
||||
|
||||
t.Run("webhooker Send", func(t *testing.T) {
|
||||
err := Webhook.Send(fullMsg)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(Webhook.Queue), 1)
|
||||
})
|
||||
|
||||
t.Run("webhooker Queue", func(t *testing.T) {
|
||||
go notifications.Queue(Webhook)
|
||||
time.Sleep(8 * time.Second)
|
||||
assert.Equal(t, webhookTestUrl, Webhook.Host)
|
||||
assert.Equal(t, len(Webhook.Queue), 0)
|
||||
})
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
checkin1 := &Checkin{
|
||||
Name: "Example Checkin 1",
|
||||
ServiceId: 1,
|
||||
|
@ -13,7 +13,9 @@ func Samples() {
|
|||
GracePeriod: 300,
|
||||
ApiKey: utils.RandomString(7),
|
||||
}
|
||||
checkin1.Create()
|
||||
if err := checkin1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkin2 := &Checkin{
|
||||
Name: "Example Checkin 2",
|
||||
|
@ -22,10 +24,13 @@ func Samples() {
|
|||
GracePeriod: 300,
|
||||
ApiKey: utils.RandomString(7),
|
||||
}
|
||||
checkin2.Create()
|
||||
if err := checkin2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func SamplesChkHits() {
|
||||
func SamplesChkHits() error {
|
||||
checkTime := time.Now().UTC().Add(-24 * time.Hour)
|
||||
|
||||
for i := int64(1); i <= 2; i++ {
|
||||
|
@ -35,8 +40,12 @@ func SamplesChkHits() {
|
|||
CreatedAt: checkTime.UTC(),
|
||||
}
|
||||
|
||||
checkHit.Create()
|
||||
if err := checkHit.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
checkTime = checkTime.Add(10 * time.Minute)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
package configs
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
testConfigs *DbConfig
|
||||
)
|
||||
|
||||
func TestDbConfig_Save(t *testing.T) {
|
||||
config := &DbConfig{
|
||||
DbConn: "sqlite",
|
||||
Project: "Tester",
|
||||
Location: utils.Directory,
|
||||
}
|
||||
|
||||
err := ConnectConfigs(config, true)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = config.Save(utils.Directory)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "sqlite3", config.DbConn)
|
||||
assert.NotEmpty(t, config.ApiKey)
|
||||
assert.NotEmpty(t, config.ApiSecret)
|
||||
}
|
||||
|
||||
func TestLoadDbConfig(t *testing.T) {
|
||||
Configs, err := LoadConfigFile(utils.Directory)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "sqlite3", Configs.DbConn)
|
||||
}
|
||||
|
||||
func TestEnvToConfig(t *testing.T) {
|
||||
os.Setenv("DB_CONN", "sqlite")
|
||||
os.Setenv("DB_USER", "")
|
||||
os.Setenv("DB_PASS", "")
|
||||
os.Setenv("DB_DATABASE", "")
|
||||
os.Setenv("NAME", "Testing")
|
||||
os.Setenv("DOMAIN", "http://localhost:8080")
|
||||
os.Setenv("DESCRIPTION", "Testing Statping")
|
||||
os.Setenv("ADMIN_USER", "admin")
|
||||
os.Setenv("ADMIN_PASS", "admin123")
|
||||
os.Setenv("VERBOSE", "1")
|
||||
config, err := loadConfigEnvs()
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, config.DbConn, "sqlite")
|
||||
assert.Equal(t, config.Domain, "http://localhost:8080")
|
||||
assert.Equal(t, config.Description, "Testing Statping")
|
||||
assert.Equal(t, config.Username, "admin")
|
||||
assert.Equal(t, config.Password, "admin123")
|
||||
|
||||
testConfigs = config
|
||||
}
|
|
@ -84,21 +84,9 @@ func Connect(configs *DbConfig, retry bool) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func InitialSetup(configs *DbConfig) error {
|
||||
func CreateAdminUser(configs *DbConfig) error {
|
||||
log.Infoln(fmt.Sprintf("Core database does not exist, creating now!"))
|
||||
|
||||
if err := configs.DropDatabase(); err != nil {
|
||||
return errors.Wrap(err, "error dropping database")
|
||||
}
|
||||
|
||||
if err := CreateDatabase(); err != nil {
|
||||
return errors.Wrap(err, "error creating database")
|
||||
}
|
||||
|
||||
if err := TriggerSamples(); err != nil {
|
||||
return errors.Wrap(err, "error creating database")
|
||||
}
|
||||
|
||||
if configs.Username == "" && configs.Password == "" {
|
||||
configs.Username = utils.Getenv("ADMIN_USER", "admin").(string)
|
||||
configs.Password = utils.Getenv("ADMIN_PASSWORD", "admin").(string)
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/hunterlong/statping/types/groups"
|
||||
"github.com/hunterlong/statping/types/hits"
|
||||
"github.com/hunterlong/statping/types/incidents"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/messages"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
|
@ -18,7 +17,7 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
type SamplerFunc func()
|
||||
type SamplerFunc func() error
|
||||
|
||||
type Sampler interface {
|
||||
Samples() []database.DbObject
|
||||
|
@ -27,7 +26,7 @@ type Sampler interface {
|
|||
func TriggerSamples() error {
|
||||
return createSamples(
|
||||
core.Samples,
|
||||
users.Samples,
|
||||
//users.Samples,
|
||||
messages.Samples,
|
||||
services.Samples,
|
||||
checkins.Samples,
|
||||
|
@ -42,7 +41,9 @@ func TriggerSamples() error {
|
|||
|
||||
func createSamples(sm ...SamplerFunc) error {
|
||||
for _, v := range sm {
|
||||
v()
|
||||
if err := v(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -72,7 +73,7 @@ func (d *DbConfig) Delete() error {
|
|||
|
||||
// DropDatabase will DROP each table Statping created
|
||||
func (d *DbConfig) DropDatabase() error {
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}, &integrations.Integration{}}
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||
log.Infoln("Dropping Database Tables...")
|
||||
for _, t := range DbModels {
|
||||
if err := database.DB().DropTableIfExists(t); err != nil {
|
||||
|
@ -87,7 +88,7 @@ func (d *DbConfig) DropDatabase() error {
|
|||
func CreateDatabase() error {
|
||||
var err error
|
||||
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}, &integrations.Integration{}}
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||
|
||||
log.Infoln("Creating Database Tables...")
|
||||
for _, table := range DbModels {
|
||||
|
|
|
@ -2,7 +2,6 @@ package configs
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/pkg/errors"
|
||||
"os"
|
||||
|
@ -11,7 +10,7 @@ import (
|
|||
|
||||
var log = utils.Log
|
||||
|
||||
func ConnectConfigs(configs *DbConfig, initiate bool) error {
|
||||
func ConnectConfigs(configs *DbConfig) error {
|
||||
err := Connect(configs, true)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "error connecting to database")
|
||||
|
@ -20,10 +19,6 @@ func ConnectConfigs(configs *DbConfig, initiate bool) error {
|
|||
return errors.Wrap(err, "error saving configuration")
|
||||
}
|
||||
|
||||
exists := database.DB().HasTable("core")
|
||||
if !exists && initiate {
|
||||
return InitialSetup(configs)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/hunterlong/statping/types/groups"
|
||||
"github.com/hunterlong/statping/types/hits"
|
||||
"github.com/hunterlong/statping/types/incidents"
|
||||
"github.com/hunterlong/statping/types/integrations"
|
||||
"github.com/hunterlong/statping/types/messages"
|
||||
"github.com/hunterlong/statping/types/notifications"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
|
@ -49,7 +48,7 @@ import (
|
|||
//If this function has an issue, it will ROLLBACK to the previous state.
|
||||
func (c *DbConfig) MigrateDatabase() error {
|
||||
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}, &integrations.Integration{}}
|
||||
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, ¬ifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
|
||||
|
||||
log.Infoln("Migrating Database Tables...")
|
||||
tx := database.Begin("migration")
|
||||
|
@ -91,8 +90,7 @@ func (c *DbConfig) MigrateDatabase() error {
|
|||
if err := database.DB().Model(&failures.Failure{}).AddIndex("idx_checkin_fail", "checkin").Error(); err != nil {
|
||||
log.Errorln(err)
|
||||
}
|
||||
|
||||
log.Infoln("Statping Database Indexes Migrated")
|
||||
log.Infoln("Database Indexes Created")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package core
|
|||
|
||||
import (
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/notifiers"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
)
|
||||
|
||||
|
@ -10,27 +9,11 @@ func InitApp() error {
|
|||
if _, err := Select(); err != nil {
|
||||
return err
|
||||
}
|
||||
//if err := InsertNotifierDB(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//if err := InsertIntegratorDB(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
if _, err := services.SelectAllServices(true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := notifiers.AttachNotifiers(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
//App.Notifications = notifications.AllCommunications
|
||||
//if err := integrations.AddIntegrations(); err != nil {
|
||||
// return err
|
||||
//}
|
||||
//App.Integrations = integrations.Integrations
|
||||
|
||||
go services.CheckServices()
|
||||
|
||||
database.StartMaintenceRoutine()
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
apiKey := utils.Getenv("API_KEY", "samplekey")
|
||||
apiSecret := utils.Getenv("API_SECRET", "samplesecret")
|
||||
|
||||
|
@ -21,5 +21,6 @@ func Samples() {
|
|||
UseCdn: null.NewNullBool(false),
|
||||
Footer: null.NewNullString(""),
|
||||
}
|
||||
core.Create()
|
||||
|
||||
return core.Create()
|
||||
}
|
||||
|
|
|
@ -37,6 +37,13 @@ type Core struct {
|
|||
Image string `gorm:"image" json:"started_on"`
|
||||
Notifications []AllNotifiers `gorm:"-" json:"-"`
|
||||
Integrations []Integrator `gorm:"-" json:"-"`
|
||||
|
||||
GHAuth
|
||||
}
|
||||
|
||||
type GHAuth struct {
|
||||
GithubClientID string `gorm:"gh_client_id" json:"gh_client_id"`
|
||||
GithubClientSecret string `gorm:"gh_client_secret" json:"-"`
|
||||
}
|
||||
|
||||
// AllNotifiers contains all the Notifiers loaded
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
tx := DB().Begin()
|
||||
sg := new(sync.WaitGroup)
|
||||
|
||||
|
@ -22,7 +22,7 @@ func Samples() {
|
|||
for i := int64(1); i <= 4; i++ {
|
||||
sg.Add(1)
|
||||
|
||||
log.Infoln(fmt.Sprintf("Adding %v Failure records to service", 730))
|
||||
log.Infoln(fmt.Sprintf("Adding %v Failure records to service", 400))
|
||||
|
||||
go func() {
|
||||
defer sg.Done()
|
||||
|
@ -42,6 +42,8 @@ func Samples() {
|
|||
|
||||
if err := tx.Commit().Error(); err != nil {
|
||||
log.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
package groups
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGroup_Create(t *testing.T) {
|
||||
group := &Group{
|
||||
Name: "Testing",
|
||||
}
|
||||
err := group.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, group.Id)
|
||||
}
|
||||
|
||||
func TestGroup_Services(t *testing.T) {
|
||||
group, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.NotEmpty(t, group.Services())
|
||||
}
|
||||
|
||||
func TestSelectGroups(t *testing.T) {
|
||||
grs := SelectGroups(true, false)
|
||||
assert.Equal(t, int(3), len(grs))
|
||||
grs = SelectGroups(true, true)
|
||||
assert.Equal(t, int(5), len(grs))
|
||||
}
|
|
@ -4,26 +4,33 @@ import (
|
|||
"github.com/hunterlong/statping/types/null"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
group1 := &Group{
|
||||
Name: "Main Services",
|
||||
Public: null.NewNullBool(true),
|
||||
Order: 2,
|
||||
}
|
||||
group1.Create()
|
||||
if err := group1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
group2 := &Group{
|
||||
Name: "Linked Services",
|
||||
Public: null.NewNullBool(false),
|
||||
Order: 1,
|
||||
}
|
||||
group2.Create()
|
||||
if err := group2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
group3 := &Group{
|
||||
Name: "Empty Group",
|
||||
Public: null.NewNullBool(false),
|
||||
Order: 3,
|
||||
}
|
||||
group3.Create()
|
||||
if err := group3.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package hits
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
|
@ -14,7 +15,7 @@ import (
|
|||
|
||||
var SampleHits = 99900.
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
tx := DB().Begin()
|
||||
sg := new(sync.WaitGroup)
|
||||
|
||||
|
@ -26,9 +27,12 @@ func Samples() {
|
|||
tx = DB().Begin()
|
||||
}
|
||||
|
||||
return tx.Error()
|
||||
}
|
||||
|
||||
func createHitsAt(db database.Database, serviceID int64, sg *sync.WaitGroup) error {
|
||||
log.Infoln(fmt.Sprintf("Adding sample hit records to service #%d", serviceID))
|
||||
|
||||
createdAt := utils.Now().Add(-3 * types.Day)
|
||||
p := utils.NewPerlin(2, 2, 5, utils.Now().UnixNano())
|
||||
|
||||
|
@ -46,6 +50,10 @@ func createHitsAt(db database.Database, serviceID int64, sg *sync.WaitGroup) err
|
|||
}
|
||||
|
||||
db = db.Create(&hit)
|
||||
if err := db.Error(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i++
|
||||
if createdAt.After(utils.Now()) {
|
||||
break
|
||||
|
|
|
@ -1,40 +1,53 @@
|
|||
package incidents
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
incident1 := &Incident{
|
||||
Title: "Github Downtime",
|
||||
Description: "This is an example of a incident for a service.",
|
||||
ServiceId: 2,
|
||||
}
|
||||
incident1.Create()
|
||||
if err := incident1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i1 := &IncidentUpdate{
|
||||
IncidentId: incident1.Id,
|
||||
Message: "Github's page for Statping seems to be sending a 501 error.",
|
||||
Type: "Investigating",
|
||||
}
|
||||
i1.Create()
|
||||
if err := i1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i2 := &IncidentUpdate{
|
||||
IncidentId: incident1.Id,
|
||||
Message: "Problem is continuing and we are looking at the issues.",
|
||||
Type: "Update",
|
||||
}
|
||||
i2.Create()
|
||||
if err := i2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i3 := &IncidentUpdate{
|
||||
IncidentId: incident1.Id,
|
||||
Message: "Github is now back online and everything is working.",
|
||||
Type: "Resolved",
|
||||
}
|
||||
i3.Create()
|
||||
if err := i3.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SamplesUpdates() {
|
||||
func SamplesUpdates() error {
|
||||
u1 := &IncidentUpdate{
|
||||
IncidentId: 1,
|
||||
Message: "Github is now back online and everything is working.",
|
||||
Type: "Resolved",
|
||||
}
|
||||
u1.Create()
|
||||
if err := u1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
package integrations
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
)
|
||||
|
||||
func DB() database.Database {
|
||||
return database.DB().Model(&Integration{})
|
||||
}
|
||||
|
||||
func Find(name string) (*Integration, error) {
|
||||
var integration Integration
|
||||
db := DB().Where("name = ?", name).Find(&integration)
|
||||
return &integration, db.Error()
|
||||
}
|
||||
|
||||
func All() []*Integration {
|
||||
var integrations []*Integration
|
||||
DB().Find(&integrations)
|
||||
return integrations
|
||||
}
|
||||
|
||||
func List(i Integrator) ([]*services.Service, error) {
|
||||
return i.List()
|
||||
}
|
||||
|
||||
func (i *Integration) Create() error {
|
||||
db := DB().Create(i)
|
||||
return db.Error()
|
||||
}
|
||||
|
||||
func (i *Integration) Update() error {
|
||||
db := DB().Update(i)
|
||||
return db.Error()
|
||||
}
|
||||
|
||||
func (i *Integration) Delete() error {
|
||||
db := DB().Delete(i)
|
||||
return db.Error()
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package integrations
|
||||
|
||||
import "github.com/hunterlong/statping/types/services"
|
||||
|
||||
type Integration struct {
|
||||
ShortName string `gorm:"column:name" json:"name"`
|
||||
Name string `gorm:"-" json:"full_name,omitempty"`
|
||||
Icon string `gorm:"-" json:"-"`
|
||||
Description string `gorm:"-" json:"description,omitempty"`
|
||||
Enabled bool `gorm:"column:enabled;default:false" json:"enabled"`
|
||||
Fields []*IntegrationField `gorm:"column:fields" json:"fields"`
|
||||
}
|
||||
|
||||
type IntegrationField struct {
|
||||
Name string `gorm:"-" json:"name"`
|
||||
Value interface{} `gorm:"-" json:"value"`
|
||||
Type string `gorm:"-" json:"type"`
|
||||
Description string `gorm:"-" json:"description,omitempty"`
|
||||
MimeType string `gorm:"-" json:"mime_type,omitempty"`
|
||||
}
|
||||
|
||||
type Integrator interface {
|
||||
Get() *Integration
|
||||
List() ([]*services.Service, error)
|
||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
m1 := &Message{
|
||||
Title: "Routine Downtime",
|
||||
Description: "This is an example a upcoming message for a service!",
|
||||
|
@ -13,7 +13,9 @@ func Samples() {
|
|||
EndOn: time.Now().UTC().Add(2 * time.Hour),
|
||||
}
|
||||
|
||||
m1.Create()
|
||||
if err := m1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m2 := &Message{
|
||||
Title: "Server Reboot",
|
||||
|
@ -23,5 +25,9 @@ func Samples() {
|
|||
EndOn: time.Now().UTC().Add(2 * time.Hour),
|
||||
}
|
||||
|
||||
m2.Create()
|
||||
if err := m2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -9,8 +9,12 @@ func DB() database.Database {
|
|||
return database.DB().Model(&Notification{})
|
||||
}
|
||||
|
||||
func Append(n Notifier) {
|
||||
allNotifiers = append(allNotifiers, n)
|
||||
}
|
||||
|
||||
func Find(name string) (Notifier, error) {
|
||||
for _, n := range AllCommunications {
|
||||
for _, n := range allNotifiers {
|
||||
notif := n.Select()
|
||||
if notif.Name() == name || notif.Method == name {
|
||||
return n, nil
|
||||
|
@ -19,15 +23,16 @@ func Find(name string) (Notifier, error) {
|
|||
return nil, errors.New("notifier not found")
|
||||
}
|
||||
|
||||
func All() []*Notification {
|
||||
var notifiers []*Notification
|
||||
DB().Find(¬ifiers)
|
||||
return notifiers
|
||||
func All() []Notifier {
|
||||
return allNotifiers
|
||||
}
|
||||
|
||||
func (n *Notification) Create() error {
|
||||
db := DB().FirstOrCreate(&n)
|
||||
return db.Error()
|
||||
var notif Notification
|
||||
if DB().Where("method = ?", n.Method).Find(¬if).RecordNotFound() {
|
||||
return DB().Create(n).Error()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *Notification) Update() error {
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
|
||||
// OnSave will trigger a notifier when it has been saved - Notifier interface
|
||||
func OnSave(method string) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(Notifier)) {
|
||||
notifier := comm.(Notifier)
|
||||
if notifier.Select().Method == method {
|
||||
|
@ -53,7 +53,7 @@ func OnFailure(s *services.Service, f *failures.Failure) {
|
|||
}
|
||||
|
||||
sendMessages:
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (s.Online || inLimits(comm)) {
|
||||
notifier := comm.(Notifier).Select()
|
||||
log.
|
||||
|
@ -76,7 +76,7 @@ func OnSuccess(s *services.Service) {
|
|||
s.UserNotified = false
|
||||
}
|
||||
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (!s.Online || inLimits(comm)) {
|
||||
notifier := comm.(Notifier).Select()
|
||||
log.
|
||||
|
@ -90,7 +90,7 @@ func OnSuccess(s *services.Service) {
|
|||
|
||||
// OnNewService is triggered when a new service is created - ServiceEvents interface
|
||||
func OnNewService(s *services.Service) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.
|
||||
WithField("trigger", "OnNewService").
|
||||
|
@ -106,7 +106,7 @@ func OnUpdatedService(s *services.Service) {
|
|||
if !s.AllowNotifications.Bool {
|
||||
return
|
||||
}
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Debugln(fmt.Sprintf("Sending updated service notification for service %v", s.Name))
|
||||
comm.(ServiceEvents).OnUpdatedService(s)
|
||||
|
@ -120,7 +120,7 @@ func OnDeletedService(s *services.Service) {
|
|||
if !s.AllowNotifications.Bool {
|
||||
return
|
||||
}
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(ServiceEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Debugln(fmt.Sprintf("Sending deleted service notification for service %v", s.Name))
|
||||
comm.(ServiceEvents).OnDeletedService(s)
|
||||
|
@ -131,7 +131,7 @@ func OnDeletedService(s *services.Service) {
|
|||
|
||||
// OnNewUser is triggered when a new user is created - UserEvents interface
|
||||
func OnNewUser(u *users.User) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Debugln(fmt.Sprintf("Sending new user notification for user %v", u.Username))
|
||||
comm.(UserEvents).OnNewUser(u)
|
||||
|
@ -142,7 +142,7 @@ func OnNewUser(u *users.User) {
|
|||
|
||||
// OnUpdatedUser is triggered when a new user is updated - UserEvents interface
|
||||
func OnUpdatedUser(u *users.User) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Debugln(fmt.Sprintf("Sending updated user notification for user %v", u.Username))
|
||||
comm.(UserEvents).OnUpdatedUser(u)
|
||||
|
@ -153,7 +153,7 @@ func OnUpdatedUser(u *users.User) {
|
|||
|
||||
// OnDeletedUser is triggered when a new user is deleted - UserEvents interface
|
||||
func OnDeletedUser(u *users.User) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(UserEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Debugln(fmt.Sprintf("Sending deleted user notification for user %v", u.Username))
|
||||
comm.(UserEvents).OnDeletedUser(u)
|
||||
|
@ -164,7 +164,7 @@ func OnDeletedUser(u *users.User) {
|
|||
|
||||
//// OnUpdatedCore is triggered when the CoreApp settings are saved - CoreEvents interface
|
||||
//func OnUpdatedCore(c *core.Core) {
|
||||
// for _, comm := range AllCommunications {
|
||||
// for _, comm := range allNotifiers {
|
||||
// if utils.IsType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
// log.Debugln(fmt.Sprintf("Sending updated core notification"))
|
||||
// comm.(CoreEvents).OnUpdatedCore(c)
|
||||
|
@ -174,7 +174,7 @@ func OnDeletedUser(u *users.User) {
|
|||
//
|
||||
//// OnStart is triggered when the Statping service has started
|
||||
//func OnStart(c *core.Core) {
|
||||
// for _, comm := range AllCommunications {
|
||||
// for _, comm := range allNotifiers {
|
||||
// if utils.IsType(comm, new(CoreEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
// comm.(CoreEvents).OnUpdatedCore(c)
|
||||
// }
|
||||
|
@ -183,7 +183,7 @@ func OnDeletedUser(u *users.User) {
|
|||
|
||||
// OnNewNotifier is triggered when a new notifier is loaded
|
||||
func OnNewNotifier(n *Notification) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
comm.(NotifierEvents).OnNewNotifier(n)
|
||||
comm.Select().Hits.OnNewNotifier++
|
||||
|
@ -193,7 +193,7 @@ func OnNewNotifier(n *Notification) {
|
|||
|
||||
// OnUpdatedNotifier is triggered when a notifier has been updated
|
||||
func OnUpdatedNotifier(n *Notification) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
if utils.IsType(comm, new(NotifierEvents)) && isEnabled(comm) && inLimits(comm) {
|
||||
log.Infoln(fmt.Sprintf("Sending updated notifier for %v", n.Id))
|
||||
comm.(NotifierEvents).OnUpdatedNotifier(n)
|
||||
|
|
|
@ -1,179 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifications
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/source"
|
||||
"github.com/hunterlong/statping/types/failures"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/types/users"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ExampleNotifier is an example on how to use the Statping notifier struct
|
||||
type ExampleNotifier struct {
|
||||
*Notification
|
||||
}
|
||||
|
||||
// example is a example variable for a example notifier
|
||||
var example = &ExampleNotifier{&Notification{
|
||||
Method: METHOD,
|
||||
Host: "http://exmaplehost.com",
|
||||
Title: "Example",
|
||||
Description: "Example Notifier",
|
||||
Author: "Hunter Long",
|
||||
AuthorUrl: "https://github.com/hunterlong",
|
||||
Delay: time.Duration(3 * time.Second),
|
||||
Limits: 7,
|
||||
Form: []NotificationForm{{
|
||||
Type: "text",
|
||||
Title: "Host",
|
||||
Placeholder: "Insert your Host here.",
|
||||
DbField: "host",
|
||||
SmallText: "this is where you would put the host",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "Username",
|
||||
Placeholder: "Insert your Username here.",
|
||||
DbField: "username",
|
||||
}, {
|
||||
Type: "password",
|
||||
Title: "Password",
|
||||
Placeholder: "Insert your Password here.",
|
||||
DbField: "password",
|
||||
}, {
|
||||
Type: "number",
|
||||
Title: "Port",
|
||||
Placeholder: "Insert your Port here.",
|
||||
DbField: "port",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "API Key",
|
||||
Placeholder: "Insert your API Key here",
|
||||
DbField: "api_key",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "API Secret",
|
||||
Placeholder: "Insert your API Secret here",
|
||||
DbField: "api_secret",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "Var 1",
|
||||
Placeholder: "Insert your Var1 here",
|
||||
DbField: "var1",
|
||||
}, {
|
||||
Type: "text",
|
||||
Title: "Var2",
|
||||
Placeholder: "Var2 goes here",
|
||||
DbField: "var2",
|
||||
}},
|
||||
}}
|
||||
|
||||
// init will be ran when Statping is loaded, AddNotifier will add the notifier instance to the system
|
||||
func init() {
|
||||
dir = utils.Directory
|
||||
source.Assets()
|
||||
utils.InitLogs()
|
||||
injectDatabase()
|
||||
}
|
||||
|
||||
// Send is the main function to hold your notifier functionality
|
||||
func (n *ExampleNotifier) Send(msg interface{}) error {
|
||||
message := msg.(string)
|
||||
fmt.Printf("i received this string: %v\n", message)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Select is a required basic event for the Notifier interface
|
||||
func (n *ExampleNotifier) Select() *Notification {
|
||||
return n.Notification
|
||||
}
|
||||
|
||||
// OnSave is a required basic event for the Notifier interface
|
||||
func (n *ExampleNotifier) OnSave() error {
|
||||
msg := fmt.Sprintf("received on save trigger")
|
||||
n.AddQueue("onsave", msg)
|
||||
return errors.New("onsave triggered")
|
||||
}
|
||||
|
||||
// OnSuccess is a required basic event for the Notifier interface
|
||||
func (n *ExampleNotifier) OnSuccess(s *services.Service) {
|
||||
msg := fmt.Sprintf("received a count trigger for service: %v\n", s.Name)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnFailure is a required basic event for the Notifier interface
|
||||
func (n *ExampleNotifier) OnFailure(s *services.Service, f *failures.Failure) {
|
||||
msg := fmt.Sprintf("received a failure trigger for service: %v\n", s.Name)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnTest is a option testing event for the Notifier interface
|
||||
func (n *ExampleNotifier) OnTest() error {
|
||||
fmt.Printf("received a test trigger with form data: %v\n", n.Host)
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnNewService is a option event for new services
|
||||
func (n *ExampleNotifier) OnNewService(s *services.Service) {
|
||||
msg := fmt.Sprintf("received a new service trigger for service: %v\n", s.Name)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnUpdatedService is a option event for updated services
|
||||
func (n *ExampleNotifier) OnUpdatedService(s *services.Service) {
|
||||
msg := fmt.Sprintf("received a update service trigger for service: %v\n", s.Name)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnDeletedService is a option event for deleted services
|
||||
func (n *ExampleNotifier) OnDeletedService(s *services.Service) {
|
||||
msg := fmt.Sprintf("received a delete service trigger for service: %v\n", s.Name)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnNewUser is a option event for new users
|
||||
func (n *ExampleNotifier) OnNewUser(s *users.User) {
|
||||
msg := fmt.Sprintf("received a new user trigger for user: %v\n", s.Username)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnUpdatedUser is a option event for updated users
|
||||
func (n *ExampleNotifier) OnUpdatedUser(s *users.User) {
|
||||
msg := fmt.Sprintf("received a updated user trigger for user: %v\n", s.Username)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnDeletedUser is a option event for deleted users
|
||||
func (n *ExampleNotifier) OnDeletedUser(s *users.User) {
|
||||
msg := fmt.Sprintf("received a deleted user trigger for user: %v\n", s.Username)
|
||||
n.AddQueue(fmt.Sprintf("service_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnNewNotifier is triggered when a new notifier has initialized
|
||||
func (n *ExampleNotifier) OnNewNotifier(s *Notification) {
|
||||
msg := fmt.Sprintf("received a new notifier trigger for notifier: %v\n", s.Method)
|
||||
n.AddQueue(fmt.Sprintf("notifier_%v", s.Id), msg)
|
||||
}
|
||||
|
||||
// OnUpdatedNotifier is triggered when a notifier has been updated
|
||||
func (n *ExampleNotifier) OnUpdatedNotifier(s *Notification) {
|
||||
msg := fmt.Sprintf("received a update notifier trigger for notifier: %v\n", s.Method)
|
||||
n.AddQueue(fmt.Sprintf("notifier_%v", s.Id), msg)
|
||||
}
|
|
@ -3,7 +3,6 @@ package notifications
|
|||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/pkg/errors"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
@ -96,30 +95,35 @@ func (n *Notification) GetValue(dbField string) string {
|
|||
}
|
||||
|
||||
// Init accepts the Notifier interface to initialize the notifier
|
||||
func Init(n Notifier) (*Notification, error) {
|
||||
err := install(n)
|
||||
if err == nil {
|
||||
notify, err := SelectNotification(n)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error selecting notification")
|
||||
}
|
||||
|
||||
notify.CreatedAt = time.Now().UTC()
|
||||
notify.UpdatedAt = time.Now().UTC()
|
||||
if notify.Delay.Seconds() == 0 {
|
||||
notify.Delay = 1 * time.Second
|
||||
}
|
||||
notify.testable = utils.IsType(n, new(Tester))
|
||||
notify.Form = n.Select().Form
|
||||
|
||||
AllCommunications = append(AllCommunications, n)
|
||||
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "error installing notification")
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
//func Init(n Notifier) (*Notification, error) {
|
||||
// if Exists(n.Select().Method) {
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// } else {
|
||||
// _, err := insertDatabase(n)
|
||||
// if err != nil {
|
||||
// log.Errorln(err)
|
||||
// return nil, err
|
||||
// }
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// }
|
||||
//
|
||||
// notify, err := SelectNotification(n)
|
||||
// if err != nil {
|
||||
// return nil, errors.Wrap(err, "error selecting notification")
|
||||
// }
|
||||
//
|
||||
// notify.CreatedAt = time.Now().UTC()
|
||||
// notify.UpdatedAt = time.Now().UTC()
|
||||
// if notify.Delay.Seconds() == 0 {
|
||||
// notify.Delay = 1 * time.Second
|
||||
// }
|
||||
// notify.testable = utils.IsType(n, new(Tester))
|
||||
// notify.Form = n.Select().Form
|
||||
//
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
//
|
||||
// return nil, err
|
||||
//}
|
||||
|
||||
// ResetQueue will clear the notifiers Queue
|
||||
func (n *Notification) ResetQueue() {
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
|
@ -29,16 +28,14 @@ import (
|
|||
|
||||
var (
|
||||
// db holds the Statping database connection
|
||||
db database.Database
|
||||
log = utils.Log.WithField("type", "notifier")
|
||||
AllCommunications []Notifier
|
||||
log = utils.Log.WithField("type", "notifier")
|
||||
allNotifiers []Notifier
|
||||
)
|
||||
|
||||
// Notification contains all the fields for a Statping Notifier.
|
||||
type Notification struct {
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Method string `gorm:"column:method" json:"method"`
|
||||
name string `gorm:"column:name" json:"name"`
|
||||
Host string `gorm:"not null;column:host" json:"host,omitempty"`
|
||||
Port int `gorm:"not null;column:port" json:"port,omitempty"`
|
||||
Username string `gorm:"not null;column:username" json:"username,omitempty"`
|
||||
|
@ -108,16 +105,6 @@ type NotificationLog struct {
|
|||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
|
||||
// SetDB is called by core to inject the database for a notifier to use
|
||||
func SetDB(d database.Database) {
|
||||
db = d
|
||||
}
|
||||
|
||||
// asNotification accepts a Notifier and returns a Notification struct
|
||||
func asNotification(n Notifier) *Notification {
|
||||
return n.Select()
|
||||
}
|
||||
|
||||
// normalizeType will accept multiple interfaces and converts it into a string for logging
|
||||
func normalizeType(ty interface{}) string {
|
||||
switch v := ty.(type) {
|
||||
|
@ -169,20 +156,9 @@ func SelectNotification(n Notifier) (*Notification, error) {
|
|||
return notifier, err.Error()
|
||||
}
|
||||
|
||||
// insertDatabase will create a new record into the database for the notifier
|
||||
func insertDatabase(n Notifier) (int64, error) {
|
||||
noti := n.Select()
|
||||
noti.Limits = 3
|
||||
noti.name = noti.Name()
|
||||
if err := noti.Create(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return noti.Id, nil
|
||||
}
|
||||
|
||||
// SelectNotifier returns the Notification struct from the database
|
||||
func SelectNotifier(method string) (*Notification, Notifier, error) {
|
||||
for _, comm := range AllCommunications {
|
||||
for _, comm := range allNotifiers {
|
||||
n, ok := comm.(Notifier)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("incorrect notification type: %v", reflect.TypeOf(n).String())
|
||||
|
@ -231,20 +207,22 @@ CheckNotifier:
|
|||
}
|
||||
|
||||
// install will check the database for the notification, if its not inserted it will insert a new record for it
|
||||
func install(n Notifier) error {
|
||||
_, err := insertDatabase(n)
|
||||
if err != nil {
|
||||
log.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
AllCommunications = append(AllCommunications, n)
|
||||
|
||||
log.WithFields(utils.ToFields(n)).
|
||||
Debugln(fmt.Sprintf("Checking if notifier '%v' is installed", n.Select().Method))
|
||||
|
||||
return nil
|
||||
}
|
||||
//func install(n Notifier) error {
|
||||
// log.WithFields(utils.ToFields(n)).
|
||||
// Debugln(fmt.Sprintf("Checking if notifier '%v' is installed", n.Select().Method))
|
||||
//
|
||||
// if Exists(n.Select().Method) {
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// } else {
|
||||
// _, err := insertDatabase(n)
|
||||
// if err != nil {
|
||||
// log.Errorln(err)
|
||||
// return err
|
||||
// }
|
||||
// AllCommunications = append(AllCommunications, n)
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
|
||||
// isEnabled returns true if the notifier is enabled
|
||||
func isEnabled(n interface{}) bool {
|
||||
|
|
|
@ -1,212 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 notifications
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types/failures"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
"github.com/hunterlong/statping/types/services"
|
||||
"github.com/hunterlong/statping/types/users"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
dir string
|
||||
METHOD = "example"
|
||||
)
|
||||
|
||||
var service = &services.Service{
|
||||
Name: "Interpol - All The Rage Back Home",
|
||||
Domain: "https://www.youtube.com/watch?v=-u6DvRyyKGU",
|
||||
ExpectedStatus: 200,
|
||||
Interval: 30,
|
||||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 20,
|
||||
AllowNotifications: null.NewNullBool(true),
|
||||
}
|
||||
|
||||
var failure = &failures.Failure{
|
||||
Issue: "testing",
|
||||
}
|
||||
|
||||
var user = &users.User{
|
||||
Username: "admin",
|
||||
Email: "info@email.com",
|
||||
}
|
||||
|
||||
func injectDatabase() {
|
||||
sqlPath := dir + "/notifier.db"
|
||||
utils.DeleteFile(sqlPath)
|
||||
db, _ = database.Openw("sqlite3", sqlPath)
|
||||
db.CreateTable(&Notification{})
|
||||
}
|
||||
|
||||
func TestIsBasicType(t *testing.T) {
|
||||
assert.True(t, utils.IsType(example, new(Notifier)))
|
||||
assert.True(t, utils.IsType(example, new(BasicEvents)))
|
||||
assert.True(t, utils.IsType(example, new(ServiceEvents)))
|
||||
assert.True(t, utils.IsType(example, new(UserEvents)))
|
||||
assert.True(t, utils.IsType(example, new(NotifierEvents)))
|
||||
assert.True(t, utils.IsType(example, new(Tester)))
|
||||
}
|
||||
|
||||
func TestSelectNotification(t *testing.T) {
|
||||
notifier, notif, err := SelectNotifier(example.Method)
|
||||
assert.Nil(t, err)
|
||||
assert.NotNil(t, notifier)
|
||||
assert.NotNil(t, notif)
|
||||
assert.Equal(t, "example", notifier.Method)
|
||||
assert.False(t, notifier.Enabled.Bool)
|
||||
assert.False(t, notifier.IsRunning())
|
||||
}
|
||||
|
||||
func TestAddQueue(t *testing.T) {
|
||||
msg := "this is a test in the queue!"
|
||||
example.AddQueue(fmt.Sprintf("service_%v", 0), msg)
|
||||
assert.Equal(t, 1, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestNotification_Update(t *testing.T) {
|
||||
notifier, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
notifier.Host = "http://demo.statping.com/api"
|
||||
notifier.Port = 9090
|
||||
notifier.Username = "admin"
|
||||
notifier.Password = "password123"
|
||||
notifier.Var1 = "var1_is_here"
|
||||
notifier.Var2 = "var2_is_here"
|
||||
notifier.ApiKey = "USBdu82HDiiuw9327yGYDGw"
|
||||
notifier.ApiSecret = "PQopncow929hUIDHGwiud"
|
||||
notifier.Limits = 10
|
||||
err = notifier.Update()
|
||||
assert.Nil(t, err)
|
||||
|
||||
selected, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "http://demo.statping.com/api", selected.GetValue("host"))
|
||||
assert.Equal(t, "http://demo.statping.com/api", example.Notification.Host)
|
||||
assert.Equal(t, "http://demo.statping.com/api", example.Host)
|
||||
assert.Equal(t, "USBdu82HDiiuw9327yGYDGw", selected.GetValue("api_key"))
|
||||
assert.Equal(t, "USBdu82HDiiuw9327yGYDGw", example.ApiKey)
|
||||
assert.False(t, selected.Enabled.Bool)
|
||||
assert.False(t, selected.IsRunning())
|
||||
}
|
||||
|
||||
func TestEnableNotification(t *testing.T) {
|
||||
notifier, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
notifier.Enabled = null.NewNullBool(true)
|
||||
err = notifier.Update()
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, notifier.Enabled.Bool)
|
||||
assert.True(t, notifier.IsRunning())
|
||||
}
|
||||
|
||||
func TestIsEnabled(t *testing.T) {
|
||||
assert.True(t, isEnabled(example))
|
||||
}
|
||||
|
||||
func TestIsRunning(t *testing.T) {
|
||||
assert.True(t, example.IsRunning())
|
||||
}
|
||||
|
||||
func TestLastSent(t *testing.T) {
|
||||
notifier, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "0s", notifier.LastSent().String())
|
||||
}
|
||||
|
||||
func TestWithinLimits(t *testing.T) {
|
||||
notifier, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 10, notifier.Limits)
|
||||
assert.True(t, inLimits(example))
|
||||
}
|
||||
|
||||
func TestNotification_GetValue(t *testing.T) {
|
||||
notifier, err := SelectNotification(example)
|
||||
assert.Nil(t, err)
|
||||
val := notifier.GetValue("Host")
|
||||
assert.Equal(t, "http://demo.statping.com/api", val)
|
||||
}
|
||||
|
||||
func TestOnSave(t *testing.T) {
|
||||
err := example.OnSave()
|
||||
assert.Equal(t, "onsave triggered", err.Error())
|
||||
}
|
||||
|
||||
func TestOnSuccess(t *testing.T) {
|
||||
OnSuccess(service)
|
||||
assert.Equal(t, 2, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnFailure(t *testing.T) {
|
||||
OnFailure(service, failure)
|
||||
assert.Equal(t, 3, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnNewService(t *testing.T) {
|
||||
OnNewService(service)
|
||||
assert.Equal(t, 4, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnUpdatedService(t *testing.T) {
|
||||
OnUpdatedService(service)
|
||||
assert.Equal(t, 5, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnDeletedService(t *testing.T) {
|
||||
OnDeletedService(service)
|
||||
assert.Equal(t, 6, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnNewUser(t *testing.T) {
|
||||
OnNewUser(user)
|
||||
assert.Equal(t, 7, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnUpdatedUser(t *testing.T) {
|
||||
OnUpdatedUser(user)
|
||||
assert.Equal(t, 8, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnDeletedUser(t *testing.T) {
|
||||
OnDeletedUser(user)
|
||||
assert.Equal(t, 9, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestOnUpdatedNotifier(t *testing.T) {
|
||||
OnUpdatedNotifier(example.Select())
|
||||
assert.Equal(t, 11, len(example.Queue))
|
||||
}
|
||||
|
||||
func TestRunAllQueueAndStop(t *testing.T) {
|
||||
assert.True(t, example.IsRunning())
|
||||
assert.Equal(t, 11, len(example.Queue))
|
||||
go Queue(example)
|
||||
time.Sleep(13 * time.Second)
|
||||
assert.NotZero(t, len(example.Queue))
|
||||
example.Close()
|
||||
assert.False(t, example.IsRunning())
|
||||
assert.NotZero(t, len(example.Queue))
|
||||
}
|
|
@ -48,8 +48,6 @@ func (s *Service) Create() error {
|
|||
return err.Error()
|
||||
}
|
||||
allServices[s.Id] = s
|
||||
|
||||
go ServiceCheckQueue(allServices[s.Id], true)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
createdOn := time.Now().Add(((-24 * 30) * 3) * time.Hour).UTC()
|
||||
s1 := &Service{
|
||||
Name: "Google",
|
||||
|
@ -21,7 +21,9 @@ func Samples() {
|
|||
VerifySSL: null.NewNullBool(true),
|
||||
CreatedAt: createdOn,
|
||||
}
|
||||
s1.Create()
|
||||
if err := s1.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s2 := &Service{
|
||||
Name: "Statping Github",
|
||||
|
@ -36,7 +38,9 @@ func Samples() {
|
|||
VerifySSL: null.NewNullBool(true),
|
||||
CreatedAt: createdOn,
|
||||
}
|
||||
s2.Create()
|
||||
if err := s2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s3 := &Service{
|
||||
Name: "JSON Users Test",
|
||||
|
@ -52,7 +56,9 @@ func Samples() {
|
|||
GroupId: 2,
|
||||
CreatedAt: createdOn,
|
||||
}
|
||||
s3.Create()
|
||||
if err := s3.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s4 := &Service{
|
||||
Name: "JSON API Tester",
|
||||
|
@ -70,7 +76,9 @@ func Samples() {
|
|||
GroupId: 2,
|
||||
CreatedAt: createdOn,
|
||||
}
|
||||
s4.Create()
|
||||
if err := s4.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s5 := &Service{
|
||||
Name: "Google DNS",
|
||||
|
@ -84,5 +92,9 @@ func Samples() {
|
|||
GroupId: 1,
|
||||
CreatedAt: createdOn,
|
||||
}
|
||||
s5.Create()
|
||||
if err := s5.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 services
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/checkins"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
testCheckin *checkins.Checkin
|
||||
)
|
||||
|
||||
func TestCreateCheckin(t *testing.T) {
|
||||
service, err := Find(2)
|
||||
require.Nil(t, err)
|
||||
checkin := &checkins.Checkin{
|
||||
ServiceId: service.Id,
|
||||
Interval: 10,
|
||||
GracePeriod: 5,
|
||||
}
|
||||
err = checkin.Create()
|
||||
require.Nil(t, err)
|
||||
assert.NotZero(t, checkin.Id)
|
||||
assert.NotEmpty(t, testCheckin.ApiKey)
|
||||
assert.Equal(t, int64(10), testCheckin.Interval)
|
||||
assert.Equal(t, int64(5), testCheckin.GracePeriod)
|
||||
assert.True(t, testCheckin.Expected().Minutes() < 0)
|
||||
}
|
||||
|
||||
func TestSelectCheckin(t *testing.T) {
|
||||
service, err := Find(2)
|
||||
require.Nil(t, err)
|
||||
chks := service.Checkins()
|
||||
assert.NotNil(t, chks)
|
||||
assert.Equal(t, 1, len(chks))
|
||||
c := chks[0]
|
||||
assert.Equal(t, int64(10), c.Interval)
|
||||
assert.Equal(t, int64(5), c.GracePeriod)
|
||||
assert.Equal(t, 7, len(c.ApiKey))
|
||||
}
|
||||
|
||||
func TestUpdateCheckin(t *testing.T) {
|
||||
testCheckin.Interval = 60
|
||||
testCheckin.GracePeriod = 15
|
||||
err := testCheckin.Update()
|
||||
require.Nil(t, err)
|
||||
assert.NotZero(t, testCheckin.Id)
|
||||
assert.NotEmpty(t, testCheckin.ApiKey)
|
||||
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
checkin := service.Checkins()[0]
|
||||
assert.Equal(t, int64(60), checkin.Interval)
|
||||
assert.Equal(t, int64(15), checkin.GracePeriod)
|
||||
t.Log(testCheckin.Expected())
|
||||
assert.True(t, testCheckin.Expected().Minutes() < 0)
|
||||
}
|
||||
|
||||
func TestCreateCheckinHits(t *testing.T) {
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
check := service.Checkins()
|
||||
assert.Equal(t, 1, len(check))
|
||||
created := time.Now().UTC().Add(-60 * time.Second)
|
||||
hit := &checkins.CheckinHit{
|
||||
Checkin: testCheckin.Id,
|
||||
From: "192.168.1.1",
|
||||
CreatedAt: created,
|
||||
}
|
||||
err = hit.Create()
|
||||
require.Nil(t, err)
|
||||
|
||||
checks := service.Checkins()
|
||||
assert.Equal(t, 1, len(checks))
|
||||
}
|
||||
|
||||
func TestSelectCheckinMethods(t *testing.T) {
|
||||
time.Sleep(5 * time.Second)
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
checkins := service.Checkins()
|
||||
assert.NotNil(t, checkins)
|
||||
assert.Equal(t, float64(60), testCheckin.Period().Seconds())
|
||||
assert.Equal(t, float64(15), testCheckin.Grace().Seconds())
|
||||
t.Log(testCheckin.Expected())
|
||||
|
||||
lastHit := checkins[0]
|
||||
assert.True(t, testCheckin.Expected().Seconds() < -5)
|
||||
assert.False(t, lastHit.CreatedAt.IsZero())
|
||||
}
|
|
@ -1,332 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 services
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/types/failures"
|
||||
"github.com/hunterlong/statping/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
newServiceId int64
|
||||
)
|
||||
|
||||
func TestSelectHTTPService(t *testing.T) {
|
||||
services, err := SelectAllServices(false)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 15, len(services))
|
||||
assert.Equal(t, "Google", services[0].Name)
|
||||
assert.Equal(t, "http", services[0].Type)
|
||||
}
|
||||
|
||||
func TestSelectAllServices(t *testing.T) {
|
||||
services := All()
|
||||
for _, s := range services {
|
||||
s.CheckService(false)
|
||||
assert.False(t, s.IsRunning())
|
||||
t.Logf("ID: %v %v\n", s.Id, s.Name)
|
||||
}
|
||||
assert.Equal(t, 15, len(services))
|
||||
}
|
||||
|
||||
func TestServiceDowntime(t *testing.T) {
|
||||
service, err := Find(15)
|
||||
require.Nil(t, err)
|
||||
downtime := service.Downtime()
|
||||
assert.True(t, downtime.Seconds() > 0)
|
||||
}
|
||||
|
||||
func TestSelectTCPService(t *testing.T) {
|
||||
services := All()
|
||||
assert.Equal(t, 15, len(services))
|
||||
service, err := Find(5)
|
||||
require.Nil(t, err)
|
||||
assert.NotNil(t, service)
|
||||
assert.Equal(t, "Google DNS", service.Name)
|
||||
assert.Equal(t, "tcp", service.Type)
|
||||
}
|
||||
|
||||
func TestUpdateService(t *testing.T) {
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Google", service.Name)
|
||||
service.Name = "Updated Google"
|
||||
service.Interval = 5
|
||||
|
||||
err = service.Update()
|
||||
require.Nil(t, err)
|
||||
|
||||
// check if updating pointer array shutdown any other service
|
||||
service, err = Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Updated Google", service.Name)
|
||||
assert.Equal(t, 5, service.Interval)
|
||||
}
|
||||
|
||||
func TestUpdateAllServices(t *testing.T) {
|
||||
services, err := SelectAllServices(false)
|
||||
require.Nil(t, err)
|
||||
var i int
|
||||
for _, srv := range services {
|
||||
srv.Name = "Changed " + srv.Name
|
||||
srv.Interval = i + 3
|
||||
|
||||
err := srv.Update()
|
||||
require.Nil(t, err)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceHTTPCheck(t *testing.T) {
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
service.CheckService(true)
|
||||
assert.Equal(t, "Changed Updated Google", service.Name)
|
||||
assert.True(t, service.Online)
|
||||
}
|
||||
|
||||
func TestCheckHTTPService(t *testing.T) {
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Changed Updated Google", service.Name)
|
||||
assert.True(t, service.Online)
|
||||
assert.Equal(t, 200, service.LastStatusCode)
|
||||
assert.NotZero(t, service.Latency)
|
||||
assert.NotZero(t, service.PingTime)
|
||||
}
|
||||
|
||||
func TestServiceTCPCheck(t *testing.T) {
|
||||
service, err := Find(5)
|
||||
require.Nil(t, err)
|
||||
service.CheckService(false)
|
||||
assert.Equal(t, "Changed Google DNS", service.Name)
|
||||
assert.True(t, service.Online)
|
||||
}
|
||||
|
||||
func TestCheckTCPService(t *testing.T) {
|
||||
service, err := Find(5)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Changed Google DNS", service.Name)
|
||||
assert.True(t, service.Online)
|
||||
assert.NotZero(t, service.Latency)
|
||||
assert.NotZero(t, service.PingTime)
|
||||
}
|
||||
|
||||
func TestServiceOnline24Hours(t *testing.T) {
|
||||
since := utils.Now().Add(-24 * time.Hour).Add(-10 * time.Minute)
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, float32(100), service.OnlineSince(since))
|
||||
service2, err := Find(5)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, float32(100), service2.OnlineSince(since))
|
||||
service3, err := Find(14)
|
||||
require.Nil(t, err)
|
||||
assert.True(t, service3.OnlineSince(since) > float32(49))
|
||||
}
|
||||
|
||||
func TestServiceAvgUptime(t *testing.T) {
|
||||
since := utils.Now().Add(-24 * time.Hour).Add(-10 * time.Minute)
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.NotEqual(t, "0.00", service.AvgTime())
|
||||
service2, err := Find(5)
|
||||
assert.Equal(t, "100", service2.AvgTime())
|
||||
service3, err := Find(13)
|
||||
assert.NotEqual(t, "0", service3.HitsSince(since).Avg())
|
||||
service4, err := Find(15)
|
||||
assert.NotEqual(t, "0", service4.HitsSince(since).Avg())
|
||||
}
|
||||
|
||||
func TestCreateService(t *testing.T) {
|
||||
s := &Service{
|
||||
Name: "That'll do 🐢",
|
||||
Domain: "https://www.youtube.com/watch?v=rjQtzV9IZ0Q",
|
||||
ExpectedStatus: 200,
|
||||
Interval: 3,
|
||||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 20,
|
||||
GroupId: 1,
|
||||
}
|
||||
err := s.Create()
|
||||
require.Nil(t, err)
|
||||
assert.NotZero(t, s.Id)
|
||||
newService, err := Find(s.Id)
|
||||
assert.Equal(t, "That'll do 🐢", newService.Name)
|
||||
}
|
||||
|
||||
func TestViewNewService(t *testing.T) {
|
||||
newService, err := Find(newServiceId)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "That'll do 🐢", newService.Name)
|
||||
}
|
||||
|
||||
func TestCreateFailingHTTPService(t *testing.T) {
|
||||
s := &Service{
|
||||
Name: "Bad URL",
|
||||
Domain: "http://localhost/iamnothere",
|
||||
ExpectedStatus: 200,
|
||||
Interval: 2,
|
||||
Type: "http",
|
||||
Method: "GET",
|
||||
Timeout: 5,
|
||||
GroupId: 1,
|
||||
}
|
||||
err := s.Create()
|
||||
require.Nil(t, err)
|
||||
assert.NotZero(t, s.Id)
|
||||
newService, err := Find(s.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Bad URL", newService.Name)
|
||||
t.Log("new service ID: ", newServiceId)
|
||||
}
|
||||
|
||||
func TestServiceFailedCheck(t *testing.T) {
|
||||
service, err := Find(17)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Bad URL", service.Name)
|
||||
service.CheckService(false)
|
||||
assert.Equal(t, "Bad URL", service.Name)
|
||||
assert.False(t, service.Online)
|
||||
}
|
||||
|
||||
func TestCreateFailingTCPService(t *testing.T) {
|
||||
s := &Service{
|
||||
Name: "Bad TCP",
|
||||
Domain: "localhost",
|
||||
Port: 5050,
|
||||
Interval: 30,
|
||||
Type: "tcp",
|
||||
Timeout: 5,
|
||||
GroupId: 1,
|
||||
}
|
||||
err := s.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, s.Id)
|
||||
newService, err := Find(s.Id)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "Bad TCP", newService.Name)
|
||||
t.Log("new failing tcp service ID: ", newServiceId)
|
||||
}
|
||||
|
||||
func TestServiceFailedTCPCheck(t *testing.T) {
|
||||
srv, err := Find(newServiceId)
|
||||
require.Nil(t, err)
|
||||
srv.CheckService(false)
|
||||
assert.Equal(t, "Bad TCP", srv.Name)
|
||||
assert.False(t, srv.Online)
|
||||
}
|
||||
|
||||
func TestCreateServiceFailure(t *testing.T) {
|
||||
service, err := Find(8)
|
||||
fail := &failures.Failure{
|
||||
Issue: "This is not an issue, but it would container HTTP response errors.",
|
||||
Method: "http",
|
||||
Service: service.Id,
|
||||
}
|
||||
err = fail.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, fail.Id)
|
||||
}
|
||||
|
||||
func TestDeleteService(t *testing.T) {
|
||||
service, err := Find(newServiceId)
|
||||
|
||||
count, err := SelectAllServices(false)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, 18, len(count))
|
||||
|
||||
err = service.Delete()
|
||||
assert.Nil(t, err)
|
||||
|
||||
services := All()
|
||||
assert.Equal(t, 17, len(services))
|
||||
}
|
||||
|
||||
func TestServiceCloseRoutine(t *testing.T) {
|
||||
s := new(Service)
|
||||
s.Name = "example"
|
||||
s.Domain = "https://google.com"
|
||||
s.Type = "http"
|
||||
s.Method = "GET"
|
||||
s.ExpectedStatus = 200
|
||||
s.Interval = 1
|
||||
s.Start()
|
||||
assert.True(t, s.IsRunning())
|
||||
t.Log(s.Checkpoint)
|
||||
t.Log(s.SleepDuration)
|
||||
go ServiceCheckQueue(s, false)
|
||||
t.Log(s.Checkpoint)
|
||||
t.Log(s.SleepDuration)
|
||||
time.Sleep(5 * time.Second)
|
||||
t.Log(s.Checkpoint)
|
||||
t.Log(s.SleepDuration)
|
||||
assert.True(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
}
|
||||
|
||||
func TestServiceCheckQueue(t *testing.T) {
|
||||
s := new(Service)
|
||||
s.Name = "example"
|
||||
s.Domain = "https://google.com"
|
||||
s.Type = "http"
|
||||
s.Method = "GET"
|
||||
s.ExpectedStatus = 200
|
||||
s.Interval = 1
|
||||
s.Start()
|
||||
assert.True(t, s.IsRunning())
|
||||
go ServiceCheckQueue(s, false)
|
||||
|
||||
go func() {
|
||||
time.Sleep(5 * time.Second)
|
||||
t.Log(s.Checkpoint)
|
||||
time.Sleep(6 * time.Second)
|
||||
}()
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
assert.True(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
s.Close()
|
||||
assert.False(t, s.IsRunning())
|
||||
}
|
||||
|
||||
func TestDNScheckService(t *testing.T) {
|
||||
s := new(Service)
|
||||
s.Name = "example"
|
||||
s.Domain = "http://localhost:9000"
|
||||
s.Type = "http"
|
||||
s.Method = "GET"
|
||||
s.ExpectedStatus = 200
|
||||
s.Interval = 1
|
||||
amount, err := dnsCheck(s)
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, amount)
|
||||
}
|
||||
|
||||
func TestFindLink(t *testing.T) {
|
||||
service, err := Find(1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, "google", service.Permalink.String)
|
||||
}
|
|
@ -51,10 +51,10 @@ func durationStr(d time.Duration) string {
|
|||
return "2006-01-02T00:00:00Z"
|
||||
|
||||
case m >= Day.Seconds():
|
||||
return "2006-01-02T15:00:00Z"
|
||||
return "2006-01-02T00:00:00Z"
|
||||
|
||||
case m >= Hour.Seconds():
|
||||
return "2006-01-02T15:04:00Z"
|
||||
return "2006-01-02T15:00:00Z"
|
||||
|
||||
case m >= Minute.Seconds():
|
||||
return "2006-01-02T15:04:00Z"
|
||||
|
|
|
@ -33,14 +33,6 @@ func TestFixedTime(t *testing.T) {
|
|||
timeVal,
|
||||
Day,
|
||||
"2020-05-22T00:00:00Z",
|
||||
}, {
|
||||
timeVal.Add(2 * Month),
|
||||
Month,
|
||||
"2020-07-01T00:00:00Z",
|
||||
}, {
|
||||
timeVal.Add(2 * Year),
|
||||
Year,
|
||||
"2022-01-01T00:00:00Z",
|
||||
}}
|
||||
|
||||
for _, e := range examples {
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"github.com/hunterlong/statping/types/null"
|
||||
)
|
||||
|
||||
func Samples() {
|
||||
func Samples() error {
|
||||
u2 := &User{
|
||||
Username: "testadmin",
|
||||
Password: "password123",
|
||||
|
@ -12,7 +12,9 @@ func Samples() {
|
|||
Admin: null.NewNullBool(true),
|
||||
}
|
||||
|
||||
u2.Create()
|
||||
if err := u2.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u3 := &User{
|
||||
Username: "testadmin2",
|
||||
|
@ -21,5 +23,9 @@ func Samples() {
|
|||
Admin: null.NewNullBool(true),
|
||||
}
|
||||
|
||||
u3.Create()
|
||||
if err := u3.Create(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ type User struct {
|
|||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Username string `gorm:"type:varchar(100);unique;column:username;" json:"username,omitempty"`
|
||||
Password string `gorm:"column:password" json:"password,omitempty"`
|
||||
Email string `gorm:"type:varchar(100);unique;column:email" json:"email,omitempty"`
|
||||
Email string `gorm:"type:varchar(100);column:email" json:"email,omitempty"`
|
||||
ApiKey string `gorm:"column:api_key" json:"api_key,omitempty"`
|
||||
ApiSecret string `gorm:"column:api_secret" json:"api_secret,omitempty"`
|
||||
Admin null.NullBool `gorm:"column:administrator" json:"admin,omitempty"`
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
// Statping
|
||||
// Copyright (C) 2018. Hunter Long and the project contributors
|
||||
// Written by Hunter Long <info@socialeck.com> and the project contributors
|
||||
//
|
||||
// https://github.com/hunterlong/statping
|
||||
//
|
||||
// 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 users
|
||||
|
||||
import (
|
||||
"github.com/hunterlong/statping/database"
|
||||
"github.com/hunterlong/statping/types/null"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateUser(t *testing.T) {
|
||||
user := &User{
|
||||
Username: "hunter",
|
||||
Password: "password123",
|
||||
Email: "test@email.com",
|
||||
Admin: null.NewNullBool(true),
|
||||
}
|
||||
err := user.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, user.Id)
|
||||
}
|
||||
|
||||
func TestSelectAllUsers(t *testing.T) {
|
||||
users := All()
|
||||
assert.Equal(t, 3, len(users))
|
||||
}
|
||||
|
||||
func TestSelectUser(t *testing.T) {
|
||||
user, err := Find(1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "info@betatude.com", user.Email)
|
||||
assert.True(t, user.Admin.Bool)
|
||||
}
|
||||
|
||||
func TestSelectUsername(t *testing.T) {
|
||||
user, err := FindByUsername("hunter")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "test@email.com", user.Email)
|
||||
assert.Equal(t, int64(3), user.Id)
|
||||
assert.True(t, user.Admin.Bool)
|
||||
}
|
||||
|
||||
func TestUpdateUser(t *testing.T) {
|
||||
user, err := Find(1)
|
||||
assert.Nil(t, err)
|
||||
user.Username = "updated"
|
||||
err = user.Update()
|
||||
assert.Nil(t, err)
|
||||
updatedUser, err := Find(1)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "updated", updatedUser.Username)
|
||||
}
|
||||
|
||||
func TestCreateUser2(t *testing.T) {
|
||||
user := &User{
|
||||
Username: "hunterlong",
|
||||
Password: "password123",
|
||||
Email: "User@email.com",
|
||||
Admin: null.NewNullBool(true),
|
||||
}
|
||||
err := user.Create()
|
||||
assert.Nil(t, err)
|
||||
assert.NotZero(t, user.Id)
|
||||
}
|
||||
|
||||
func TestSelectAllUsersAgain(t *testing.T) {
|
||||
users := All()
|
||||
assert.Equal(t, 4, len(users))
|
||||
}
|
||||
|
||||
func TestAuthUser(t *testing.T) {
|
||||
user, auth := AuthUser("hunterlong", "password123")
|
||||
assert.True(t, auth)
|
||||
assert.NotNil(t, user)
|
||||
assert.Equal(t, "User@email.com", user.Email)
|
||||
assert.Equal(t, int64(4), user.Id)
|
||||
assert.True(t, user.Admin.Bool)
|
||||
}
|
||||
|
||||
func TestFailedAuthUser(t *testing.T) {
|
||||
user, auth := AuthUser("hunterlong", "wrongpassword")
|
||||
assert.False(t, auth)
|
||||
assert.Nil(t, user)
|
||||
}
|
||||
|
||||
func TestCheckPassword(t *testing.T) {
|
||||
user, err := Find(2)
|
||||
assert.Nil(t, err)
|
||||
pass := CheckHash("password123", user.Password)
|
||||
assert.True(t, pass)
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
user, err := Find(2)
|
||||
assert.Nil(t, err)
|
||||
err = user.Delete()
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestDbConfig_Close(t *testing.T) {
|
||||
err := database.Close()
|
||||
assert.Nil(t, err)
|
||||
}
|
Loading…
Reference in New Issue