pull/78/head v0.64
Hunter Long 2018-09-18 23:12:42 -07:00
parent 0a1b63fa76
commit 8dbf573667
8 changed files with 65 additions and 55 deletions

View File

@ -172,6 +172,9 @@ docker-push-latest:
docker push hunterlong/statup:latest docker push hunterlong/statup:latest
docker push hunterlong/statup:latest-v$(VERSION) docker push hunterlong/statup:latest-v$(VERSION)
docker-run-mssql:
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=PaSsW0rD123' -p 1433:1433 -d microsoft/mssql-server-linux
# create Postgres, and MySQL instance using Docker (used for testing) # create Postgres, and MySQL instance using Docker (used for testing)
databases: databases:
docker run --name statup_postgres -p 5432:5432 -e POSTGRES_PASSWORD=password123 -e POSTGRES_USER=root -e POSTGRES_DB=root -d postgres docker run --name statup_postgres -p 5432:5432 -e POSTGRES_PASSWORD=password123 -e POSTGRES_USER=root -e POSTGRES_DB=root -d postgres

View File

@ -52,7 +52,13 @@ func Clean() {
utils.DeleteDirectory(dir + "/logs") utils.DeleteDirectory(dir + "/logs")
} }
func RunInit(t *testing.T) { func RunInit(db string, t *testing.T) {
if db == "mssql" {
os.Setenv("DB_DATABASE", "tempdb")
os.Setenv("DB_PASS", "PaSsW0rD123")
os.Setenv("DB_PORT", "1433")
os.Setenv("DB_USER", "sa")
}
source.Assets() source.Assets()
Clean() Clean()
route = handlers.Router() route = handlers.Router()
@ -69,7 +75,7 @@ func TestRunAll(t *testing.T) {
for _, dbt := range databases { for _, dbt := range databases {
t.Run(dbt+" init", func(t *testing.T) { t.Run(dbt+" init", func(t *testing.T) {
RunInit(t) RunInit(dbt, t)
}) })
t.Run(dbt+" Save Config", func(t *testing.T) { t.Run(dbt+" Save Config", func(t *testing.T) {
RunSaveConfig(t, dbt) RunSaveConfig(t, dbt)
@ -206,6 +212,11 @@ func TestRunAll(t *testing.T) {
t.Run(dbt+" Cleanup", func(t *testing.T) { t.Run(dbt+" Cleanup", func(t *testing.T) {
core.Configs.Close() core.Configs.Close()
core.DbSession = nil core.DbSession = nil
if dbt == "mssql" {
os.Setenv("DB_DATABASE", "root")
os.Setenv("DB_PASS", "password123")
os.Setenv("DB_PORT", "1433")
}
//Clean() //Clean()
}) })
@ -220,6 +231,8 @@ func RunSaveConfig(t *testing.T, db string) {
port := 5432 port := 5432
if db == "mysql" { if db == "mysql" {
port = 3306 port = 3306
} else if db == "mssql" {
port = 1433
} }
core.Configs = &core.DbConfig{DbConfig: &types.DbConfig{ core.Configs = &core.DbConfig{DbConfig: &types.DbConfig{
DbConn: db, DbConn: db,

View File

@ -163,12 +163,7 @@ func (s *Service) SmallText() string {
} }
func (s *Service) DowntimeText() string { func (s *Service) DowntimeText() string {
lastFailure := s.lastFailure() return fmt.Sprintf("%v has been offline for %v", s.Name, utils.DurationReadable(s.Downtime()))
if lastFailure == nil {
return ""
}
got, _ := timeago.TimeAgoWithTime(time.Now().UTC().Add(s.Downtime()), time.Now().UTC())
return fmt.Sprintf("Reported offline %v, %v", got, lastFailure.ParseError())
} }
// GroupDataBy returns a SQL query as a string to group a column by a time // GroupDataBy returns a SQL query as a string to group a column by a time
@ -188,13 +183,13 @@ func GroupDataBy(column string, id int64, start, end time.Time, increment string
// Downtime returns the amount of time of a offline service // Downtime returns the amount of time of a offline service
func (s *Service) Downtime() time.Duration { func (s *Service) Downtime() time.Duration {
hits, _ := s.Hits() hits, _ := s.Hits()
if len(hits) == 0 {
return time.Duration(0)
}
fails := s.LimitedFailures() fails := s.LimitedFailures()
if len(fails) == 0 { if len(fails) == 0 {
return time.Duration(0) return time.Duration(0)
} }
if len(hits) == 0 {
return time.Now().UTC().Sub(fails[len(fails)-1].CreatedAt.UTC())
}
since := fails[0].CreatedAt.UTC().Sub(hits[0].CreatedAt.UTC()) since := fails[0].CreatedAt.UTC().Sub(hits[0].CreatedAt.UTC())
return since return since
} }

32
dev/docker-compose.yml Normal file
View File

@ -0,0 +1,32 @@
postgres:
container_name: postgres
image: postgres
restart: always
ports:
- 5432:5432
environment:
POSTGRES_PASSWORD: password123
POSTGRES_USER: root
POSTGRES_DB: root
mysql:
container_name: mysql
image: mysql:5.6
restart: always
ports:
- 3306:3306
environment:
MYSQL_ROOT_PASSWORD: password123
MYSQL_DATABASE: root
MYSQL_USER: root
MYSQL_PASSWORD: password123
mssql:
container_name: mssql
image: microsoft/mssql-server-linux
restart: always
ports:
- 1433:1433
environment:
SA_PASSWORD: PaSsW0rD123
ACCEPT_EULA: "Y"

View File

@ -23,7 +23,6 @@ import (
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"net/http" "net/http"
"os" "os"
"time"
) )
type ApiResponse struct { type ApiResponse struct {
@ -94,38 +93,6 @@ func apiServiceHandler(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(service) json.NewEncoder(w).Encode(service)
} }
func apiServiceDataHandler(w http.ResponseWriter, r *http.Request) {
if !isAPIAuthorized(r) {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
return
}
vars := mux.Vars(r)
fields := parseGet(r)
startField := utils.StringInt(fields.Get("start"))
endField := utils.StringInt(fields.Get("end"))
var start time.Time
var end time.Time
if startField == 0 {
start = time.Now().Add(-24 * time.Hour).UTC()
} else {
start = time.Unix(startField, 0)
}
if endField == 0 {
end = time.Now().UTC()
} else {
end = time.Unix(endField, 0)
}
service := core.SelectService(utils.StringInt(vars["id"]))
if service == nil {
http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(core.GraphDataRaw(service, start, end).Array)
}
func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) { func apiCreateServiceHandler(w http.ResponseWriter, r *http.Request) {
if !isAPIAuthorized(r) { if !isAPIAuthorized(r) {
http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)

View File

@ -121,16 +121,6 @@ func TestApiServiceHandler(t *testing.T) {
assert.Equal(t, "https://google.com", obj.Domain) assert.Equal(t, "https://google.com", obj.Domain)
} }
func TestApiServiceDataHandler(t *testing.T) {
rr, err := httpRequestAPI(t, "GET", "/api/services/1/data", nil)
assert.Nil(t, err)
body := rr.Body.String()
var obj []*core.DateScan
formatJSON(body, &obj)
assert.Equal(t, 200, rr.Code)
assert.Equal(t, 60, len(obj))
}
func TestApiCreateServiceHandler(t *testing.T) { func TestApiCreateServiceHandler(t *testing.T) {
rr, err := httpRequestAPI(t, "POST", "/api/services", strings.NewReader(NEW_HTTP_SERVICE)) rr, err := httpRequestAPI(t, "POST", "/api/services", strings.NewReader(NEW_HTTP_SERVICE))
assert.Nil(t, err) assert.Nil(t, err)

View File

@ -84,7 +84,6 @@ func Router() *mux.Router {
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET") r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
r.Handle("/api/services", http.HandlerFunc(apiCreateServiceHandler)).Methods("POST") r.Handle("/api/services", http.HandlerFunc(apiCreateServiceHandler)).Methods("POST")
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceHandler)).Methods("GET") r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceHandler)).Methods("GET")
r.Handle("/api/services/{id}/data", http.HandlerFunc(apiServiceDataHandler)).Methods("GET")
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST") r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceUpdateHandler)).Methods("POST")
r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE") r.Handle("/api/services/{id}", http.HandlerFunc(apiServiceDeleteHandler)).Methods("DELETE")

View File

@ -190,3 +190,14 @@ func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
} }
} }
} }
func DurationReadable(d time.Duration) string {
if d.Hours() >= 1 {
return fmt.Sprintf("%0.0f hours and %0.0f minutes", d.Hours(), d.Minutes())
} else if d.Minutes() >= 1 {
return fmt.Sprintf("%0.0f minutes", d.Minutes())
} else if d.Seconds() >= 1 {
return fmt.Sprintf("%0.0f seconds", d.Seconds())
}
return d.String()
}