Add health api
This commit is contained in:
parent
ad157a138b
commit
81c4a73df3
|
|
@ -0,0 +1,46 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gotify/server/model"
|
||||
)
|
||||
|
||||
// The HealthDatabase interface for encapsulating database access.
|
||||
type HealthDatabase interface {
|
||||
Ping() error
|
||||
}
|
||||
|
||||
// The HealthAPI provides handlers for the health information.
|
||||
type HealthAPI struct {
|
||||
DB HealthDatabase
|
||||
}
|
||||
|
||||
// Health returns health information.
|
||||
// swagger:operation GET /health health getHealth
|
||||
//
|
||||
// Get health information.
|
||||
//
|
||||
// ---
|
||||
// produces: [application/json]
|
||||
// responses:
|
||||
// 200:
|
||||
// description: Ok
|
||||
// schema:
|
||||
// $ref: "#/definitions/Health"
|
||||
// 500:
|
||||
// description: Ok
|
||||
// schema:
|
||||
// $ref: "#/definitions/Health"
|
||||
func (a *HealthAPI) Health(ctx *gin.Context) {
|
||||
if err := a.DB.Ping(); err != nil {
|
||||
ctx.JSON(500, model.Health{
|
||||
Health: model.StatusOrange,
|
||||
Database: model.StatusRed,
|
||||
})
|
||||
return
|
||||
}
|
||||
ctx.JSON(200, model.Health{
|
||||
Health: model.StatusGreen,
|
||||
Database: model.StatusGreen,
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gotify/server/mode"
|
||||
"github.com/gotify/server/model"
|
||||
"github.com/gotify/server/test"
|
||||
"github.com/gotify/server/test/testdb"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
func TestHealthSuite(t *testing.T) {
|
||||
suite.Run(t, new(HealthSuite))
|
||||
}
|
||||
|
||||
type HealthSuite struct {
|
||||
suite.Suite
|
||||
db *testdb.Database
|
||||
a *HealthAPI
|
||||
ctx *gin.Context
|
||||
recorder *httptest.ResponseRecorder
|
||||
}
|
||||
|
||||
func (s *HealthSuite) BeforeTest(suiteName, testName string) {
|
||||
mode.Set(mode.TestDev)
|
||||
s.recorder = httptest.NewRecorder()
|
||||
s.db = testdb.NewDB(s.T())
|
||||
s.ctx, _ = gin.CreateTestContext(s.recorder)
|
||||
withURL(s.ctx, "http", "example.com")
|
||||
s.a = &HealthAPI{DB: s.db}
|
||||
}
|
||||
|
||||
func (s *HealthSuite) AfterTest(suiteName, testName string) {
|
||||
s.db.Close()
|
||||
}
|
||||
|
||||
func (s *HealthSuite) TestHealthSuccess() {
|
||||
s.a.Health(s.ctx)
|
||||
test.BodyEquals(s.T(), model.Health{Health: model.StatusGreen, Database: model.StatusGreen}, s.recorder)
|
||||
}
|
||||
|
||||
func (s *HealthSuite) TestDatabaseFailure() {
|
||||
s.db.Close()
|
||||
s.a.Health(s.ctx)
|
||||
test.BodyEquals(s.T(), model.Health{Health: model.StatusOrange, Database: model.StatusRed}, s.recorder)
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package database
|
||||
|
||||
// Ping pings the database to verify the connection.
|
||||
func (d *GormDatabase) Ping() error {
|
||||
return d.DB.DB().Ping()
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func (s *DatabaseSuite) TestPing_onValidDB() {
|
||||
err := s.db.Ping()
|
||||
assert.NoError(s.T(), err)
|
||||
}
|
||||
|
||||
func (s *DatabaseSuite) TestPing_onClosedDB() {
|
||||
s.db.Close()
|
||||
err := s.db.Ping()
|
||||
assert.Error(s.T(), err)
|
||||
}
|
||||
|
|
@ -839,6 +839,32 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"/health": {
|
||||
"get": {
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"health"
|
||||
],
|
||||
"summary": "Get health information.",
|
||||
"operationId": "getHealth",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Ok",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Health"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Ok",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/Health"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/message": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -1969,6 +1995,30 @@
|
|||
},
|
||||
"x-go-package": "github.com/gotify/server/model"
|
||||
},
|
||||
"Health": {
|
||||
"description": "Health represents how healthy the application is.",
|
||||
"type": "object",
|
||||
"title": "Health Model",
|
||||
"required": [
|
||||
"health",
|
||||
"database"
|
||||
],
|
||||
"properties": {
|
||||
"database": {
|
||||
"description": "The health of the database connection.",
|
||||
"type": "string",
|
||||
"x-go-name": "Database",
|
||||
"example": "green"
|
||||
},
|
||||
"health": {
|
||||
"description": "The health of the overall application.",
|
||||
"type": "string",
|
||||
"x-go-name": "Health",
|
||||
"example": "green"
|
||||
}
|
||||
},
|
||||
"x-go-package": "github.com/gotify/server/model"
|
||||
},
|
||||
"Message": {
|
||||
"description": "The MessageExternal holds information about a message which was sent by an Application.",
|
||||
"type": "object",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
package model
|
||||
|
||||
// Health Model
|
||||
//
|
||||
// Health represents how healthy the application is.
|
||||
//
|
||||
// swagger:model Health
|
||||
type Health struct {
|
||||
// The health of the overall application.
|
||||
//
|
||||
// required: true
|
||||
// example: green
|
||||
Health string `json:"health"`
|
||||
// The health of the database connection.
|
||||
//
|
||||
// required: true
|
||||
// example: green
|
||||
Database string `json:"database"`
|
||||
}
|
||||
|
||||
const (
|
||||
// StatusGreen everything is alright.
|
||||
StatusGreen = "green"
|
||||
// StatusOrange some things are alright.
|
||||
StatusOrange = "orange"
|
||||
// StatusRed nothing is alright.
|
||||
StatusRed = "red"
|
||||
)
|
||||
|
|
@ -29,6 +29,7 @@ func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Co
|
|||
streamHandler := stream.New(200*time.Second, 15*time.Second, conf.Server.Stream.AllowedOrigins)
|
||||
authentication := auth.Auth{DB: db}
|
||||
messageHandler := api.MessageAPI{Notifier: streamHandler, DB: db}
|
||||
healthHandler := api.HealthAPI{DB: db}
|
||||
clientHandler := api.ClientAPI{
|
||||
DB: db,
|
||||
ImageDir: conf.UploadedImagesDir,
|
||||
|
|
@ -57,6 +58,7 @@ func Create(db *database.GormDatabase, vInfo *model.VersionInfo, conf *config.Co
|
|||
|
||||
ui.Register(g)
|
||||
|
||||
g.GET("/health", healthHandler.Health)
|
||||
g.GET("/swagger", docs.Serve)
|
||||
g.Static("/image", conf.UploadedImagesDir)
|
||||
g.GET("/docs", docs.UI)
|
||||
|
|
|
|||
Loading…
Reference in New Issue