UI updates, incident updates API changes

pull/778/head
hunterlong 2020-08-04 01:50:06 -07:00
parent dbe858c842
commit 6b9f0766a5
26 changed files with 337 additions and 66 deletions

View File

@ -29,6 +29,12 @@ go-build: clean
tar -xvf source.tar.gz
go build -a -ldflags "-s -w -extldflags -static -X main.VERSION=${VERSION}" -o statping --tags "netgo" ./cmd
lint:
go fmt ./...
golint ./...
impi --local github.com/statping/statping/ --scheme stdLocalThirdParty ./...
goimports ./...
up:
docker-compose -f docker-compose.yml -f dev/docker-compose.full.yml up -d --remove-orphans
make print_details

View File

@ -39,12 +39,15 @@ func systemctlCli(dir string, uninstall bool, port int64) error {
location := "/etc/systemd/system/statping.service"
if uninstall {
fmt.Println("systemctl stop statping")
if _, _, err := utils.Command("systemctl", "stop", "statping"); err != nil {
log.Errorln(err)
}
fmt.Println("systemctl disable statping")
if _, _, err := utils.Command("systemctl", "disable", "statping"); err != nil {
log.Errorln(err)
}
fmt.Println("Deleting systemctl: ", location)
if err := utils.DeleteFile(location); err != nil {
log.Errorln(err)
}
@ -79,20 +82,24 @@ WantedBy=multi-user.target"
fmt.Println("Saving systemctl service to: ", location)
fmt.Printf("Using directory %s for Statping data\n", dir)
fmt.Printf("Running on port %d\n", port)
fmt.Printf("\n\n%s\n\n", string(config))
if err := utils.SaveFile(location, config); err != nil {
return err
}
fmt.Println("systemctl daemon-reload")
if _, _, err := utils.Command("systemctl", "daemon-reload"); err != nil {
return err
}
fmt.Println("systemctl enable statping")
if _, _, err := utils.Command("systemctl", "enable", "statping.service"); err != nil {
return err
}
fmt.Println("systemctl start statping")
if _, _, err := utils.Command("systemctl", "start", "statping"); err != nil {
return err
}
fmt.Println("Statping was will auto start on reboots")
fmt.Println("systemctl service: /etc/systemd/system/statping.service")
fmt.Println("systemctl service: ", location)
return nil
}

View File

@ -26,6 +26,7 @@ var updateCmd = &cobra.Command{
Short: "Update to the latest version",
RunE: func(cmd *cobra.Command, args []string) error {
log.Infoln("Updating Statping to the latest version...")
log.Infoln("curl -o- -L https://statping.com/install.sh | bash")
curl, err := exec.LookPath("curl")
if err != nil {
return err

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,82 @@
<template>
<div>
<Loading :loading="!loaded"/>
<div v-if="loaded && !service.online" class="bg-white shadow-sm mt-3 p-3 pr-4 pl-4 col-12">
<font-awesome-icon icon="exclamation" class="mr-3" size="1x"/>
Last failure was {{ago(service.last_error)}} ago.
<code v-if="failure" class="d-block bg-light p-3 mt-3">
{{failure.issue}}
<span class="d-block text-dim float-right small mt-3 mb-1">Failure #{{failure.id}}</span>
</code>
</div>
<div v-if="loaded" v-for="message in messages" class="bg-light shadow-sm p-3 pr-4 pl-4 col-12 mt-3">
<font-awesome-icon icon="calendar" class="mr-3" size="1x"/> {{message.description}}
<span class="d-block small text-muted mt-3">
Starts at <strong>{{niceDate(message.start_on)}}</strong> till <strong>{{niceDate(message.end_on)}}</strong>
({{dur(parseISO(message.start_on), parseISO(message.end_on))}})
</span>
</div>
<div v-if="loaded" v-for="incident in incidents" class="bg-light shadow-sm p-3 pr-4 pl-4 col-12 mt-3">
<font-awesome-icon icon="calendar" class="mr-3" size="1x"/>
{{incident.title}} - {{incident.description}}
<div v-for="update in incident.updates" class="d-block small">
<span class="font-weight-bold text-capitalize">{{update.type}}</span> - {{update.message}}
</div>
</div>
</div>
</template>
<script>
import Api from "../../API";
import Loading from "@/components/Elements/Loading";
export default {
name: "ServiceEvents",
components: {
Loading
},
props: {
service: {
type: Object,
required: true
}
},
data() {
return {
messages: null,
incidents: null,
failure: null,
loaded: false,
}
},
mounted() {
this.load()
},
methods: {
async load() {
this.loaded = false
if (!this.service.online) {
await this.getFailure()
}
await this.getMessages()
await this.getIncidents()
this.loaded = true
},
async getMessages() {
this.messages = await Api.messages()
},
async getFailure() {
const f = await Api.service_failures(this.service.id, null, null, 1)
this.failure = f[0]
},
async getIncidents() {
this.incidents = await Api.incidents_service(this.service.id)
},
}
}
</script>
<style scoped>
</style>

View File

@ -9,60 +9,31 @@
</h4>
</div>
<div class="card-body p-3 p-md-1 pt-md-3 pb-md-1">
<div class="card-body">
<transition name="fade">
<div v-if="loaded" class="col-12 pb-2">
<div v-if="false" class="row mb-4 align-content-center">
<div v-if="!service.online" class="col-3 text-left">
<span css="text-danger font-5 font-weight-bold"></span>
<span class="font-2 d-block">Current Downtime</span>
</div>
<div v-if="service.online" class="col-3 text-left">
<span class="text-success font-5 font-weight-bold">
{{service.online_24_hours.toString()}} %
</span>
<span class="font-2 d-block">Total Uptime</span>
</div>
<div v-if="service.online" class="col-3 text-left">
<span class="text-success font-5 font-weight-bold">
0
</span>
<span class="font-2 d-block">Downtime Today</span>
</div>
<div v-if="service.online" class="col-3 text-left">
<span class="text-success font-5 font-weight-bold">
{{(uptime.uptime / 10000).toFixed(0).toString()}}
</span>
<span class="font-2 d-block">Uptime Duration</span>
</div>
<div class="col-3 text-left">
<span class="text-danger font-5 font-weight-bold">
{{service.failures_24_hours}}
</span>
<span class="font-2 d-block">Failures last 24 hours</span>
</div>
</div>
<div class="row">
<div v-if="loaded" class="row pl-2 pr-2">
<div class="col-md-6 col-sm-12 mt-2 mt-md-0 mb-3">
<ServiceSparkLine :title="set2_name" subtitle="Latency Last 24 Hours" :series="set2"/>
</div>
<div class="col-md-6 col-sm-12 mt-4 mt-md-0 mb-3">
<ServiceSparkLine :title="set1_name" subtitle="Latency Last 7 Days" :series="set1"/>
</div>
</div>
<div class="col-12 mt-2 mt-md-0 mb-3">
<ServiceEvents :service="service"/>
</div>
</div>
<div v-else class="row mt-5 mb-5 pt-5 pb-5">
<div class="col-6 text-center text-muted">
<font-awesome-icon icon="circle-notch" size="3x" spin/>
</div>
<div class="col-6 text-center text-muted">
<font-awesome-icon icon="circle-notch" size="3x" spin/>
</div>
</div>
</transition>
</div>
<div class="card-footer">
<div class="row">
@ -105,10 +76,12 @@
import ServiceFailures from '../Service/ServiceFailures';
import ServiceSparkLine from "./ServiceSparkLine";
import Api from "../../API";
import ServiceEvents from "@/components/Dashboard/ServiceEvents";
export default {
name: 'ServiceInfo',
components: {
ServiceEvents,
Checkin,
ServiceFailures,
FormIncident,

View File

@ -0,0 +1,23 @@
<template>
<div v-if="loading" class="row mt-3 mb-3">
<div class="col-12 text-center text-muted">
<font-awesome-icon icon="circle-notch" size="3x" spin/>
</div>
</div>
</template>
<script>
export default {
name: "Loading",
props: {
loading: {
type: Boolean,
required: true,
}
}
}
</script>
<style scoped>
</style>

View File

@ -28,7 +28,7 @@
<label class="col-sm-4 col-form-label">Service</label>
<div class="col-sm-8">
<select v-model="message.service" name="service_id" class="form-control">
<option :value="0">Global Announcement</option>
<option v-bind:value="0">Global Announcement</option>
<option v-for="service in $store.getters.services" :value="service.id" v-bind:key="service.id" >{{service.name}}</option>
</select>
</div>
@ -48,7 +48,7 @@
<label for="service_id" class="col-sm-4 col-form-label">Service</label>
<div class="col-sm-8">
<select v-model="message.service" class="form-control" name="service" id="service_id">
<option :value="0">Global Message</option>
<option v-bind:value="0">Global Message</option>
<option v-for="service in $store.getters.services" :value="service.id" v-bind:key="service.id">{{service.name}}</option>
</select>
</div>
@ -130,6 +130,7 @@
start_on: new Date(),
end_on: new Date(),
service_id: 0,
service: 0,
notify_method: "",
notify: false,
notify_before: 0,

6
go.mod
View File

@ -17,6 +17,7 @@ require (
github.com/hako/durafmt v0.0.0-20200605151348-3a43fc422dd9
github.com/jinzhu/gorm v1.9.12
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/pavius/impi v0.0.3 // indirect
github.com/pelletier/go-toml v1.7.0 // indirect
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.1.0
@ -29,11 +30,14 @@ require (
github.com/spf13/viper v1.6.3
github.com/stretchr/testify v1.5.1
github.com/t-tiger/gorm-bulk-insert/v2 v2.0.1
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d // indirect
google.golang.org/grpc v1.28.1
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/mail.v2 v2.3.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v2 v2.2.8
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea // indirect
)

19
go.sum
View File

@ -357,6 +357,7 @@ github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6i
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d h1:V5Rs9ztEWdp58oayPq/ulmlqJJZeJP6pP79uP3qjcao=
github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.0 h1:GhthINjveNZAdFUD8QoQYfjxnOONZgztK/Yr6M23UTY=
@ -469,6 +470,8 @@ github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014 h1:37VE5TYj2m/FLA9SNr4z
github.com/ovh/go-ovh v0.0.0-20181109152953-ba5adb4cf014/go.mod h1:joRatxRJaZBsY3JAOEMcoOp05CnZzsx4scTxi95DHyQ=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pavius/impi v0.0.3 h1:DND6MzU+BLABhOZXbELR3FU8b+zDgcq4dOCNLhiTYuI=
github.com/pavius/impi v0.0.3/go.mod h1:x/hU0bfdWIhuOT1SKwiJg++yvkk6EuOtJk8WtDZqgr8=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
@ -606,6 +609,7 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -641,6 +645,8 @@ golang.org/x/crypto v0.0.0-20200406173513-056763e48d71 h1:DOmugCavvUtnUD114C1Wh+
golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a h1:y6sBfNd1b9Wy08a6K1Z1DZc4aXABUN5TKjkYhz7UKmo=
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -662,6 +668,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@ -670,6 +677,8 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -704,6 +713,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -719,6 +730,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180622082034-63fc586f45fe/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -808,7 +820,10 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4 h1:kDtqNkeBrZb8B+atrj50B5XLHpzXXqcCdZPP/ApQ5NY=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d h1:szSOL78iTCl0LF1AMjhSWJj8tIM0KixlUUnBtYXsmd8=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
@ -926,6 +941,10 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b h1:DxJ5nJdkhDlLok9K6qO+5290kphDJbHOQO1DFFFTeBo=
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea h1:M9wqFYtIbcU4ya22owATTPClIVAKkxqoYt2HAn02/JI=
mvdan.cc/unindent v0.0.0-20170829200357-ff6a34147cea/go.mod h1:uK66ibKYZGgWb8OWRdHaAVsidCOAFXHXLpYh0P+WFgA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

View File

@ -119,8 +119,19 @@ func apiThemeCreateHandler(w http.ResponseWriter, r *http.Request) {
return
}
if err := source.CompileSASS(); err != nil {
source.CopyToPublic(source.TmplBox, "css", "main.css")
source.CopyToPublic(source.TmplBox, "css", "base.css")
if err := source.CopyToPublic(source.TmplBox, "css", "style.css"); err != nil {
log.Errorln(err)
sendErrorJson(err, w, r)
return
}
jsFiles := []string{"bundle.js", "main.chunk.js", "polyfill.chunk.js", "style.chunk.js"}
for _, f := range jsFiles {
if err := source.CopyToPublic(source.TmplBox, "js", f); err != nil {
log.Errorln(err)
sendErrorJson(err, w, r)
return
}
}
log.Errorln("Default 'base.css' was inserted because SASS did not work.")
}
resetRouter()

View File

@ -45,7 +45,7 @@ func apiIncidentUpdatesHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
returnJson(incid.Updates(), w, r)
returnJson(incid.Updates, w, r)
}
func apiCreateIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) {
@ -100,8 +100,7 @@ func apiIncidentUpdateHandler(w http.ResponseWriter, r *http.Request) {
return
}
updates := incident.Updates()
sendJsonAction(updates, "update", w, r)
sendJsonAction(incident.Updates, "update", w, r)
}
func apiDeleteIncidentHandler(w http.ResponseWriter, r *http.Request) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -114,6 +114,11 @@ func TestInit(t *testing.T) {
assert.Len(t, all, 1)
})
t.Run("Test Samples", func(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 2)
})
t.Run("Test Checkin", func(t *testing.T) {
assert.Nil(t, db.Close())
assert.Nil(t, dbHits.Close())

View File

@ -0,0 +1,24 @@
package failures
import (
"github.com/statping/statping/database"
"github.com/statping/statping/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func TestInit(t *testing.T) {
t.Parallel()
err := utils.InitLogs()
require.Nil(t, err)
db, err := database.OpenTester()
require.Nil(t, err)
SetDB(db)
db.AutoMigrate(&Failure{})
t.Run("Test Samples", func(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 2)
})
}

View File

@ -106,6 +106,11 @@ func TestDelete(t *testing.T) {
assert.Len(t, all, 1)
}
func TestSamples(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 4)
}
func TestClose(t *testing.T) {
assert.Nil(t, db.Close())
}

28
types/hits/hits_test.go Normal file
View File

@ -0,0 +1,28 @@
package hits
import (
"github.com/statping/statping/database"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
)
func TestInit(t *testing.T) {
err := utils.InitLogs()
require.Nil(t, err)
db, err := database.OpenTester()
require.Nil(t, err)
db.CreateTable(&Hit{}, &services.Service{})
SetDB(db)
services.SetDB(db)
for i := 0; i <= 5; i++ {
s := services.Example(true)
assert.Nil(t, s.Create())
assert.Len(t, s.AllHits().List(), 2)
}
require.Nil(t, Samples())
}

View File

@ -18,6 +18,7 @@ func SetDB(database database.Database) {
}
func (i *Incident) AfterFind() {
db.Model(i).Related(&i.Updates).Order("DESC")
metrics.Query("incident", "find")
}
@ -64,11 +65,6 @@ func Find(id int64) (*Incident, error) {
func FindByService(id int64) []*Incident {
var incidents []*Incident
db.Where("service = ?", id).Find(&incidents)
for _, i := range incidents {
var updates []*IncidentUpdate
dbUpdate.Where("incident = ?", id).Find(&updates)
i.AllUpdates = updates
}
return incidents
}
@ -87,7 +83,7 @@ func (i *Incident) Update() error {
}
func (i *Incident) Delete() error {
for _, u := range i.Updates() {
for _, u := range i.Updates {
if err := u.Delete(); err != nil {
return err
}

View File

@ -1,11 +1,10 @@
package incidents
func (i *Incident) Updates() []*IncidentUpdate {
var updates []*IncidentUpdate
dbUpdate.Where("incident = ?", i.Id).Find(&updates)
i.AllUpdates = updates
return updates
}
//func (i Incident) Updates() []*IncidentUpdate {
// var updates []*IncidentUpdate
// dbUpdate.Where("incident = ?", i.Id).Find(&updates)
// return updates
//}
func (i *IncidentUpdate) Create() error {
q := dbUpdate.Create(i)

View File

@ -83,6 +83,11 @@ func TestDelete(t *testing.T) {
assert.Len(t, all, 1)
}
func TestSamples(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 3)
}
func TestClose(t *testing.T) {
assert.Nil(t, db.Close())
}

View File

@ -10,7 +10,7 @@ type Incident struct {
ServiceId int64 `gorm:"index;column:service" json:"service"`
CreatedAt time.Time `gorm:"column:created_at" json:"created_at" json:"created_at"`
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at" json:"updated_at"`
AllUpdates []*IncidentUpdate `gorm:"-" json:"updates,omitempty"`
Updates []*IncidentUpdate `gorm:"foreignkey:incident;association_foreignkey:id;association_autoupdate:false;association_autocreate:false" json:"updates,omitempty"`
}
// IncidentUpdate contains updates based on a Incident

View File

@ -73,6 +73,11 @@ func TestDelete(t *testing.T) {
assert.Len(t, all, 1)
}
func TestSamples(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 2)
}
func TestClose(t *testing.T) {
assert.Nil(t, db.Close())
}

View File

@ -1,10 +1,67 @@
package null
import (
"encoding/json"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"gopkg.in/yaml.v2"
"testing"
)
func TestJSONMarshal(t *testing.T) {
tests := []struct {
Input interface{}
ExpectedJSON string
}{
{
Input: NewNullBool(true),
ExpectedJSON: `true`,
},
{
Input: NewNullBool(false),
ExpectedJSON: `false`,
},
{
Input: NewNullFloat64(0.994),
ExpectedJSON: `0.994`,
},
{
Input: NewNullFloat64(0),
ExpectedJSON: `0`,
},
{
Input: NewNullInt64(42),
ExpectedJSON: `42`,
},
{
Input: NewNullInt64(0),
ExpectedJSON: `0`,
},
{
Input: NewNullString("test"),
ExpectedJSON: `"test"`,
},
{
Input: NewNullString(""),
ExpectedJSON: `""`,
},
}
for _, test := range tests {
str, err := json.Marshal(test.Input)
require.Nil(t, err)
assert.Equal(t, test.ExpectedJSON, string(str))
str, err = yaml.Marshal(yamlStruct{test.Input})
require.Nil(t, err)
assert.Equal(t, test.ExpectedJSON, string(str))
}
}
type yamlStruct struct {
Value interface{} `json:"value" yaml:"value"`
}
func TestNewNullBool(t *testing.T) {
val := NewNullBool(true)
assert.True(t, val.Bool)

View File

@ -6,6 +6,7 @@ import (
"github.com/statping/statping/types/null"
"github.com/statping/statping/utils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"time"
)
@ -251,6 +252,11 @@ func TestServiceNotifications(t *testing.T) {
runNotifyTests(t, notif, tests...)
})
t.Run("Test Samples", func(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 11)
})
t.Run("Test Close", func(t *testing.T) {
assert.Nil(t, db.Close())
})

View File

@ -7,7 +7,7 @@ import (
)
// AuthUser will return the User and a boolean if authentication was correct.
// AuthUser accepts username, and password as a string
// accepts username, and password as a string
func AuthUser(username, password string) (*User, bool) {
user, err := FindByUsername(username)
if err != nil {

View File

@ -73,6 +73,16 @@ func TestUpdate(t *testing.T) {
assert.Equal(t, "updated_user", item.Username)
}
func TestAuthUser(t *testing.T) {
u, err := AuthUser("updated_user", "admin")
require.Nil(t, err)
assert.Equal(t, "admin", u.Username)
u, err = AuthUser("updated_user", "wrongpass")
assert.NotNil(t, err)
assert.Nil(t, u)
}
func TestDelete(t *testing.T) {
all := All()
assert.Len(t, all, 2)
@ -87,6 +97,11 @@ func TestDelete(t *testing.T) {
assert.Len(t, all, 1)
}
func TestSamples(t *testing.T) {
require.Nil(t, Samples())
assert.Len(t, All(), 3)
}
func TestClose(t *testing.T) {
assert.Nil(t, db.Close())
}