mirror of
https://github.com/TwiN/gatus.git
synced 2024-11-22 07:53:38 +01:00
feat(remote): Implement lazy distributed feature (#64)
THIS IS AN EXPERIMENTAL FEATURE/IMPLEMENTATION, AND IT MAY BE REMOVED IN THE FUTURE. Note that for now, it will be an undocumented feature.
This commit is contained in:
parent
319f460553
commit
1aa94a3365
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/TwiN/gatus/v4/alerting/alert"
|
"github.com/TwiN/gatus/v4/alerting/alert"
|
||||||
"github.com/TwiN/gatus/v4/alerting/provider"
|
"github.com/TwiN/gatus/v4/alerting/provider"
|
||||||
"github.com/TwiN/gatus/v4/config/maintenance"
|
"github.com/TwiN/gatus/v4/config/maintenance"
|
||||||
|
"github.com/TwiN/gatus/v4/config/remote"
|
||||||
"github.com/TwiN/gatus/v4/config/ui"
|
"github.com/TwiN/gatus/v4/config/ui"
|
||||||
"github.com/TwiN/gatus/v4/config/web"
|
"github.com/TwiN/gatus/v4/config/web"
|
||||||
"github.com/TwiN/gatus/v4/core"
|
"github.com/TwiN/gatus/v4/core"
|
||||||
@ -85,6 +86,10 @@ type Config struct {
|
|||||||
// Maintenance is the configuration for creating a maintenance window in which no alerts are sent
|
// Maintenance is the configuration for creating a maintenance window in which no alerts are sent
|
||||||
Maintenance *maintenance.Config `yaml:"maintenance,omitempty"`
|
Maintenance *maintenance.Config `yaml:"maintenance,omitempty"`
|
||||||
|
|
||||||
|
// Remote is the configuration for remote Gatus instances
|
||||||
|
// WARNING: This is in ALPHA and may change or be completely removed in the future
|
||||||
|
Remote *remote.Config `yaml:"remote,omitempty"`
|
||||||
|
|
||||||
filePath string // path to the file from which config was loaded from
|
filePath string // path to the file from which config was loaded from
|
||||||
lastFileModTime time.Time // last modification time
|
lastFileModTime time.Time // last modification time
|
||||||
}
|
}
|
||||||
@ -185,10 +190,22 @@ func parseAndValidateConfigBytes(yamlBytes []byte) (config *Config, err error) {
|
|||||||
if err := validateStorageConfig(config); err != nil {
|
if err := validateStorageConfig(config); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if err := validateRemoteConfig(config); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateRemoteConfig(config *Config) error {
|
||||||
|
if config.Remote != nil {
|
||||||
|
if err := config.Remote.ValidateAndSetDefaults(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func validateStorageConfig(config *Config) error {
|
func validateStorageConfig(config *Config) error {
|
||||||
if config.Storage == nil {
|
if config.Storage == nil {
|
||||||
config.Storage = &storage.Config{
|
config.Storage = &storage.Config{
|
||||||
|
38
config/remote/remote.go
Normal file
38
config/remote/remote.go
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package remote
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/TwiN/gatus/v4/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NOTICE: This is an experimental alpha feature and may be updated/removed in future versions.
|
||||||
|
// For more information, see https://github.com/TwiN/gatus/issues/64
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
// Instances is a list of remote instances to retrieve endpoint statuses from.
|
||||||
|
Instances []Instance `yaml:"instances,omitempty"`
|
||||||
|
|
||||||
|
// ClientConfig is the configuration of the client used to communicate with the provider's target
|
||||||
|
ClientConfig *client.Config `yaml:"client,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Instance struct {
|
||||||
|
EndpointPrefix string `yaml:"endpoint-prefix"`
|
||||||
|
URL string `yaml:"url"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) ValidateAndSetDefaults() error {
|
||||||
|
if c.ClientConfig == nil {
|
||||||
|
c.ClientConfig = client.GetDefaultConfig()
|
||||||
|
} else {
|
||||||
|
if err := c.ClientConfig.ValidateAndSetDefaults(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(c.Instances) > 0 {
|
||||||
|
log.Println("WARNING: Your configuration is using 'remote', which is in alpha and may be updated/removed in future versions.")
|
||||||
|
log.Println("WARNING: See https://github.com/TwiN/gatus/issues/64 for more information")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
@ -8,10 +8,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/TwiN/gatus/v4/config"
|
||||||
"github.com/TwiN/gatus/v4/config/ui"
|
"github.com/TwiN/gatus/v4/config/ui"
|
||||||
"github.com/TwiN/gatus/v4/config/web"
|
|
||||||
"github.com/TwiN/gatus/v4/controller/handler"
|
"github.com/TwiN/gatus/v4/controller/handler"
|
||||||
"github.com/TwiN/gatus/v4/security"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -21,19 +20,19 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Handle creates the router and starts the server
|
// Handle creates the router and starts the server
|
||||||
func Handle(securityConfig *security.Config, webConfig *web.Config, uiConfig *ui.Config, enableMetrics bool) {
|
func Handle(cfg *config.Config) {
|
||||||
var router http.Handler = handler.CreateRouter(ui.StaticFolder, securityConfig, uiConfig, enableMetrics)
|
var router http.Handler = handler.CreateRouter(ui.StaticFolder, cfg)
|
||||||
if os.Getenv("ENVIRONMENT") == "dev" {
|
if os.Getenv("ENVIRONMENT") == "dev" {
|
||||||
router = handler.DevelopmentCORS(router)
|
router = handler.DevelopmentCORS(router)
|
||||||
}
|
}
|
||||||
server = &http.Server{
|
server = &http.Server{
|
||||||
Addr: fmt.Sprintf("%s:%d", webConfig.Address, webConfig.Port),
|
Addr: fmt.Sprintf("%s:%d", cfg.Web.Address, cfg.Web.Port),
|
||||||
Handler: router,
|
Handler: router,
|
||||||
ReadTimeout: 15 * time.Second,
|
ReadTimeout: 15 * time.Second,
|
||||||
WriteTimeout: 15 * time.Second,
|
WriteTimeout: 15 * time.Second,
|
||||||
IdleTimeout: 15 * time.Second,
|
IdleTimeout: 15 * time.Second,
|
||||||
}
|
}
|
||||||
log.Println("[controller][Handle] Listening on " + webConfig.SocketAddress())
|
log.Println("[controller][Handle] Listening on " + cfg.Web.SocketAddress())
|
||||||
if os.Getenv("ROUTER_TEST") == "true" {
|
if os.Getenv("ROUTER_TEST") == "true" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func TestHandle(t *testing.T) {
|
|||||||
_ = os.Setenv("ROUTER_TEST", "true")
|
_ = os.Setenv("ROUTER_TEST", "true")
|
||||||
_ = os.Setenv("ENVIRONMENT", "dev")
|
_ = os.Setenv("ENVIRONMENT", "dev")
|
||||||
defer os.Clearenv()
|
defer os.Clearenv()
|
||||||
Handle(cfg.Security, cfg.Web, cfg.UI, cfg.Metrics)
|
Handle(cfg)
|
||||||
defer Shutdown()
|
defer Shutdown()
|
||||||
request, _ := http.NewRequest("GET", "/health", http.NoBody)
|
request, _ := http.NewRequest("GET", "/health", http.NoBody)
|
||||||
responseRecorder := httptest.NewRecorder()
|
responseRecorder := httptest.NewRecorder()
|
||||||
|
@ -31,7 +31,7 @@ func TestBadge(t *testing.T) {
|
|||||||
}
|
}
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Connected: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Connected: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Connected: false, Duration: time.Second, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Connected: false, Duration: time.Second, Timestamp: time.Now()})
|
||||||
router := CreateRouter("../../web/static", cfg.Security, nil, cfg.Metrics)
|
router := CreateRouter("../../web/static", cfg)
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
@ -30,7 +30,7 @@ func TestResponseTimeChart(t *testing.T) {
|
|||||||
}
|
}
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
||||||
router := CreateRouter("../../web/static", cfg.Security, nil, cfg.Metrics)
|
router := CreateRouter("../../web/static", cfg)
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
@ -5,11 +5,16 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/TwiN/gatus/v4/client"
|
||||||
|
"github.com/TwiN/gatus/v4/config"
|
||||||
|
"github.com/TwiN/gatus/v4/config/remote"
|
||||||
|
"github.com/TwiN/gatus/v4/core"
|
||||||
"github.com/TwiN/gatus/v4/storage/store"
|
"github.com/TwiN/gatus/v4/storage/store"
|
||||||
"github.com/TwiN/gatus/v4/storage/store/common"
|
"github.com/TwiN/gatus/v4/storage/store/common"
|
||||||
"github.com/TwiN/gatus/v4/storage/store/common/paging"
|
"github.com/TwiN/gatus/v4/storage/store/common/paging"
|
||||||
@ -28,7 +33,8 @@ var (
|
|||||||
// EndpointStatuses handles requests to retrieve all EndpointStatus
|
// EndpointStatuses handles requests to retrieve all EndpointStatus
|
||||||
// Due to the size of the response, this function leverages a cache.
|
// Due to the size of the response, this function leverages a cache.
|
||||||
// Must not be wrapped by GzipHandler
|
// Must not be wrapped by GzipHandler
|
||||||
func EndpointStatuses(writer http.ResponseWriter, r *http.Request) {
|
func EndpointStatuses(cfg *config.Config) http.HandlerFunc {
|
||||||
|
return func(writer http.ResponseWriter, r *http.Request) {
|
||||||
page, pageSize := extractPageAndPageSizeFromRequest(r)
|
page, pageSize := extractPageAndPageSizeFromRequest(r)
|
||||||
gzipped := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
|
gzipped := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
|
||||||
var exists bool
|
var exists bool
|
||||||
@ -50,6 +56,13 @@ func EndpointStatuses(writer http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(writer, err.Error(), http.StatusInternalServerError)
|
http.Error(writer, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// ALPHA: Retrieve endpoint statuses from remote instances
|
||||||
|
if endpointStatusesFromRemote, err := getEndpointStatusesFromRemoteInstances(cfg.Remote); err != nil {
|
||||||
|
log.Printf("[handler][EndpointStatuses] Silently failed to retrieve endpoint statuses from remote: %s", err.Error())
|
||||||
|
} else if endpointStatusesFromRemote != nil {
|
||||||
|
endpointStatuses = append(endpointStatuses, endpointStatusesFromRemote...)
|
||||||
|
}
|
||||||
|
// Marshal endpoint statuses to JSON
|
||||||
data, err = json.Marshal(endpointStatuses)
|
data, err = json.Marshal(endpointStatuses)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[handler][EndpointStatuses] Unable to marshal object to JSON: %s", err.Error())
|
log.Printf("[handler][EndpointStatuses] Unable to marshal object to JSON: %s", err.Error())
|
||||||
@ -70,6 +83,39 @@ func EndpointStatuses(writer http.ResponseWriter, r *http.Request) {
|
|||||||
writer.Header().Add("Content-Type", "application/json")
|
writer.Header().Add("Content-Type", "application/json")
|
||||||
writer.WriteHeader(http.StatusOK)
|
writer.WriteHeader(http.StatusOK)
|
||||||
_, _ = writer.Write(data)
|
_, _ = writer.Write(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getEndpointStatusesFromRemoteInstances(remoteConfig *remote.Config) ([]*core.EndpointStatus, error) {
|
||||||
|
if remoteConfig == nil || len(remoteConfig.Instances) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var endpointStatusesFromAllRemotes []*core.EndpointStatus
|
||||||
|
httpClient := client.GetHTTPClient(remoteConfig.ClientConfig)
|
||||||
|
for _, instance := range remoteConfig.Instances {
|
||||||
|
response, err := httpClient.Get(instance.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
body, err := io.ReadAll(response.Body)
|
||||||
|
if err != nil {
|
||||||
|
_ = response.Body.Close()
|
||||||
|
log.Printf("[handler][getEndpointStatusesFromRemoteInstances] Silently failed to retrieve endpoint statuses from %s: %s", instance.URL, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var endpointStatuses []*core.EndpointStatus
|
||||||
|
if err = json.Unmarshal(body, &endpointStatuses); err != nil {
|
||||||
|
_ = response.Body.Close()
|
||||||
|
log.Printf("[handler][getEndpointStatusesFromRemoteInstances] Silently failed to retrieve endpoint statuses from %s: %s", instance.URL, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_ = response.Body.Close()
|
||||||
|
for _, endpointStatus := range endpointStatuses {
|
||||||
|
endpointStatus.Name = instance.EndpointPrefix + endpointStatus.Name
|
||||||
|
}
|
||||||
|
endpointStatusesFromAllRemotes = append(endpointStatusesFromAllRemotes, endpointStatuses...)
|
||||||
|
}
|
||||||
|
return endpointStatusesFromAllRemotes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointStatus retrieves a single core.EndpointStatus by group and endpoint name
|
// EndpointStatus retrieves a single core.EndpointStatus by group and endpoint name
|
||||||
|
@ -97,7 +97,7 @@ func TestEndpointStatus(t *testing.T) {
|
|||||||
}
|
}
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
||||||
router := CreateRouter("../../web/static", cfg.Security, nil, cfg.Metrics)
|
router := CreateRouter("../../web/static", cfg)
|
||||||
|
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
@ -153,7 +153,7 @@ func TestEndpointStatuses(t *testing.T) {
|
|||||||
// Can't be bothered dealing with timezone issues on the worker that runs the automated tests
|
// Can't be bothered dealing with timezone issues on the worker that runs the automated tests
|
||||||
firstResult.Timestamp = time.Time{}
|
firstResult.Timestamp = time.Time{}
|
||||||
secondResult.Timestamp = time.Time{}
|
secondResult.Timestamp = time.Time{}
|
||||||
router := CreateRouter("../../web/static", nil, nil, false)
|
router := CreateRouter("../../web/static", &config.Config{Metrics: true})
|
||||||
|
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -4,10 +4,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TwiN/gatus/v4/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFavIcon(t *testing.T) {
|
func TestFavIcon(t *testing.T) {
|
||||||
router := CreateRouter("../../web/static", nil, nil, false)
|
router := CreateRouter("../../web/static", &config.Config{})
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
@ -3,32 +3,31 @@ package handler
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/TwiN/gatus/v4/config/ui"
|
"github.com/TwiN/gatus/v4/config"
|
||||||
"github.com/TwiN/gatus/v4/security"
|
|
||||||
"github.com/TwiN/health"
|
"github.com/TwiN/health"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func CreateRouter(staticFolder string, securityConfig *security.Config, uiConfig *ui.Config, enabledMetrics bool) *mux.Router {
|
func CreateRouter(staticFolder string, cfg *config.Config) *mux.Router {
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
if enabledMetrics {
|
if cfg.Metrics {
|
||||||
router.Handle("/metrics", promhttp.Handler()).Methods("GET")
|
router.Handle("/metrics", promhttp.Handler()).Methods("GET")
|
||||||
}
|
}
|
||||||
api := router.PathPrefix("/api").Subrouter()
|
api := router.PathPrefix("/api").Subrouter()
|
||||||
protected := api.PathPrefix("/").Subrouter()
|
protected := api.PathPrefix("/").Subrouter()
|
||||||
unprotected := api.PathPrefix("/").Subrouter()
|
unprotected := api.PathPrefix("/").Subrouter()
|
||||||
if securityConfig != nil {
|
if cfg.Security != nil {
|
||||||
if err := securityConfig.RegisterHandlers(router); err != nil {
|
if err := cfg.Security.RegisterHandlers(router); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if err := securityConfig.ApplySecurityMiddleware(protected); err != nil {
|
if err := cfg.Security.ApplySecurityMiddleware(protected); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Endpoints
|
// Endpoints
|
||||||
unprotected.Handle("/v1/config", ConfigHandler{securityConfig: securityConfig}).Methods("GET")
|
unprotected.Handle("/v1/config", ConfigHandler{securityConfig: cfg.Security}).Methods("GET")
|
||||||
protected.HandleFunc("/v1/endpoints/statuses", EndpointStatuses).Methods("GET") // No GzipHandler for this one, because we cache the content as Gzipped already
|
protected.HandleFunc("/v1/endpoints/statuses", EndpointStatuses(cfg)).Methods("GET") // No GzipHandler for this one, because we cache the content as Gzipped already
|
||||||
protected.HandleFunc("/v1/endpoints/{key}/statuses", GzipHandlerFunc(EndpointStatus)).Methods("GET")
|
protected.HandleFunc("/v1/endpoints/{key}/statuses", GzipHandlerFunc(EndpointStatus)).Methods("GET")
|
||||||
unprotected.HandleFunc("/v1/endpoints/{key}/health/badge.svg", HealthBadge).Methods("GET")
|
unprotected.HandleFunc("/v1/endpoints/{key}/health/badge.svg", HealthBadge).Methods("GET")
|
||||||
unprotected.HandleFunc("/v1/endpoints/{key}/uptimes/{duration}/badge.svg", UptimeBadge).Methods("GET")
|
unprotected.HandleFunc("/v1/endpoints/{key}/uptimes/{duration}/badge.svg", UptimeBadge).Methods("GET")
|
||||||
@ -38,8 +37,8 @@ func CreateRouter(staticFolder string, securityConfig *security.Config, uiConfig
|
|||||||
router.Handle("/health", health.Handler().WithJSON(true)).Methods("GET")
|
router.Handle("/health", health.Handler().WithJSON(true)).Methods("GET")
|
||||||
router.HandleFunc("/favicon.ico", FavIcon(staticFolder)).Methods("GET")
|
router.HandleFunc("/favicon.ico", FavIcon(staticFolder)).Methods("GET")
|
||||||
// SPA
|
// SPA
|
||||||
router.HandleFunc("/endpoints/{name}", SinglePageApplication(staticFolder, uiConfig)).Methods("GET")
|
router.HandleFunc("/endpoints/{name}", SinglePageApplication(staticFolder, cfg.UI)).Methods("GET")
|
||||||
router.HandleFunc("/", SinglePageApplication(staticFolder, uiConfig)).Methods("GET")
|
router.HandleFunc("/", SinglePageApplication(staticFolder, cfg.UI)).Methods("GET")
|
||||||
// Everything else falls back on static content
|
// Everything else falls back on static content
|
||||||
router.PathPrefix("/").Handler(GzipHandler(http.FileServer(http.Dir(staticFolder))))
|
router.PathPrefix("/").Handler(GzipHandler(http.FileServer(http.Dir(staticFolder))))
|
||||||
return router
|
return router
|
||||||
|
@ -4,10 +4,12 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/TwiN/gatus/v4/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCreateRouter(t *testing.T) {
|
func TestCreateRouter(t *testing.T) {
|
||||||
router := CreateRouter("../../web/static", nil, nil, true)
|
router := CreateRouter("../../web/static", &config.Config{Metrics: true})
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
@ -30,7 +30,7 @@ func TestSinglePageApplication(t *testing.T) {
|
|||||||
}
|
}
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[0], &core.Result{Success: true, Duration: time.Millisecond, Timestamp: time.Now()})
|
||||||
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
watchdog.UpdateEndpointStatuses(cfg.Endpoints[1], &core.Result{Success: false, Duration: time.Second, Timestamp: time.Now()})
|
||||||
router := CreateRouter("../../web/static", cfg.Security, nil, cfg.Metrics)
|
router := CreateRouter("../../web/static", cfg)
|
||||||
type Scenario struct {
|
type Scenario struct {
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
|
2
main.go
2
main.go
@ -36,7 +36,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func start(cfg *config.Config) {
|
func start(cfg *config.Config) {
|
||||||
go controller.Handle(cfg.Security, cfg.Web, cfg.UI, cfg.Metrics)
|
go controller.Handle(cfg)
|
||||||
watchdog.Monitor(cfg)
|
watchdog.Monitor(cfg)
|
||||||
go listenToConfigurationFileChanges(cfg)
|
go listenToConfigurationFileChanges(cfg)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user