Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a4ab62ddd | ||
|
|
a4e9d8e9b0 | ||
|
|
3be6d04d29 | ||
|
|
b59ff6f89e | ||
|
|
813fea93ee | ||
|
|
8f50e44b45 | ||
|
|
fb2448c15a | ||
|
|
db575aad13 |
@@ -1,4 +1,4 @@
|
||||
examples
|
||||
.examples
|
||||
Dockerfile
|
||||
.github
|
||||
.idea
|
||||
|
||||
@@ -9,14 +9,17 @@ data:
|
||||
endpoints:
|
||||
- name: website
|
||||
url: https://twin.sh/health
|
||||
interval: 1m
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[BODY].status == UP"
|
||||
|
||||
- name: github
|
||||
url: https://api.github.com/healthz
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
|
||||
- name: cat-fact
|
||||
url: "https://cat-fact.herokuapp.com/facts/random"
|
||||
interval: 5m
|
||||
@@ -27,11 +30,18 @@ data:
|
||||
- "[BODY].text == pat(*cat*)"
|
||||
- "[STATUS] == pat(2*)"
|
||||
- "[CONNECTED] == true"
|
||||
|
||||
- name: example
|
||||
url: https://example.com/
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: gatus
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
@@ -41,14 +51,16 @@ spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: gatus
|
||||
app: gatus
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
k8s-app: gatus
|
||||
app: gatus
|
||||
name: gatus
|
||||
namespace: kube-system
|
||||
spec:
|
||||
serviceAccountName: gatus
|
||||
terminationGracePeriodSeconds: 5
|
||||
containers:
|
||||
- image: twinproduction/gatus
|
||||
imagePullPolicy: IfNotPresent
|
||||
@@ -84,4 +96,4 @@ spec:
|
||||
protocol: TCP
|
||||
targetPort: 8080
|
||||
selector:
|
||||
k8s-app: gatus
|
||||
app: gatus
|
||||
20
README.md
20
README.md
@@ -19,7 +19,7 @@ core applications: https://status.twin.sh/
|
||||
<details>
|
||||
<summary><b>Quick start</b></summary>
|
||||
|
||||
```
|
||||
```console
|
||||
docker run -p 8080:8080 --name gatus twinproduction/gatus
|
||||
```
|
||||
For more details, see [Usage](#usage)
|
||||
@@ -246,7 +246,7 @@ storage:
|
||||
type: sqlite
|
||||
file: data.db
|
||||
```
|
||||
See [examples/docker-compose-sqlite-storage](examples/docker-compose-sqlite-storage) for an example.
|
||||
See [examples/docker-compose-sqlite-storage](.examples/docker-compose-sqlite-storage) for an example.
|
||||
|
||||
- If `storage.type` is `postgres`, `storage.file` must be the connection URL:
|
||||
```yaml
|
||||
@@ -254,7 +254,7 @@ storage:
|
||||
type: postgres
|
||||
file: "postgres://user:password@127.0.0.1:5432/gatus?sslmode=disable"
|
||||
```
|
||||
See [examples/docker-compose-postgres-storage](examples/docker-compose-postgres-storage) for an example.
|
||||
See [examples/docker-compose-postgres-storage](.examples/docker-compose-postgres-storage) for an example.
|
||||
|
||||
|
||||
### Client configuration
|
||||
@@ -798,29 +798,29 @@ maintenance:
|
||||
|
||||
|
||||
## Deployment
|
||||
Many examples can be found in the [examples](examples) folder, but this section will focus on the most popular ways of deploying Gatus.
|
||||
Many examples can be found in the [.examples](.examples) folder, but this section will focus on the most popular ways of deploying Gatus.
|
||||
|
||||
|
||||
### Docker
|
||||
To run Gatus locally with Docker:
|
||||
```
|
||||
```console
|
||||
docker run -p 8080:8080 --name gatus twinproduction/gatus
|
||||
```
|
||||
|
||||
Other than using one of the examples provided in the `examples` folder, you can also try it out locally by
|
||||
Other than using one of the examples provided in the [.examples](.examples) folder, you can also try it out locally by
|
||||
creating a configuration file, we'll call it `config.yaml` for this example, and running the following
|
||||
command:
|
||||
```
|
||||
```console
|
||||
docker run -p 8080:8080 --mount type=bind,source="$(pwd)"/config.yaml,target=/config/config.yaml --name gatus twinproduction/gatus
|
||||
```
|
||||
|
||||
If you're on Windows, replace `"$(pwd)"` by the absolute path to your current directory, e.g.:
|
||||
```
|
||||
```console
|
||||
docker run -p 8080:8080 --mount type=bind,source=C:/Users/Chris/Desktop/config.yaml,target=/config/config.yaml --name gatus twinproduction/gatus
|
||||
```
|
||||
|
||||
To build the image locally:
|
||||
```
|
||||
```console
|
||||
docker build . -t twinproduction/gatus
|
||||
```
|
||||
|
||||
@@ -845,7 +845,7 @@ Gatus can be deployed on Terraform by using the following module: [terraform-kub
|
||||
|
||||
|
||||
## Running the tests
|
||||
```
|
||||
```console
|
||||
go test ./... -mod vendor
|
||||
```
|
||||
|
||||
|
||||
@@ -43,28 +43,28 @@ var (
|
||||
// Config is the main configuration structure
|
||||
type Config struct {
|
||||
// Debug Whether to enable debug logs
|
||||
Debug bool `yaml:"debug"`
|
||||
Debug bool `yaml:"debug,omitempty"`
|
||||
|
||||
// Metrics Whether to expose metrics at /metrics
|
||||
Metrics bool `yaml:"metrics"`
|
||||
Metrics bool `yaml:"metrics,omitempty"`
|
||||
|
||||
// SkipInvalidConfigUpdate Whether to make the application ignore invalid configuration
|
||||
// if the configuration file is updated while the application is running
|
||||
SkipInvalidConfigUpdate bool `yaml:"skip-invalid-config-update"`
|
||||
SkipInvalidConfigUpdate bool `yaml:"skip-invalid-config-update,omitempty"`
|
||||
|
||||
// DisableMonitoringLock Whether to disable the monitoring lock
|
||||
// The monitoring lock is what prevents multiple endpoints from being processed at the same time.
|
||||
// Disabling this may lead to inaccurate response times
|
||||
DisableMonitoringLock bool `yaml:"disable-monitoring-lock"`
|
||||
DisableMonitoringLock bool `yaml:"disable-monitoring-lock,omitempty"`
|
||||
|
||||
// Security Configuration for securing access to Gatus
|
||||
Security *security.Config `yaml:"security"`
|
||||
Security *security.Config `yaml:"security,omitempty"`
|
||||
|
||||
// Alerting Configuration for alerting
|
||||
Alerting *alerting.Config `yaml:"alerting"`
|
||||
Alerting *alerting.Config `yaml:"alerting,omitempty"`
|
||||
|
||||
// Endpoints List of endpoints to monitor
|
||||
Endpoints []*core.Endpoint `yaml:"endpoints"`
|
||||
Endpoints []*core.Endpoint `yaml:"endpoints,omitempty"`
|
||||
|
||||
// Services List of endpoints to monitor
|
||||
//
|
||||
@@ -72,19 +72,19 @@ type Config struct {
|
||||
// XXX: This is not a typo -- not v4.0.0, but v5.0.0 -- I want to give enough time for people to migrate
|
||||
//
|
||||
// Deprecated in favor of Endpoints
|
||||
Services []*core.Endpoint `yaml:"services"`
|
||||
Services []*core.Endpoint `yaml:"services,omitempty"`
|
||||
|
||||
// Storage is the configuration for how the data is stored
|
||||
Storage *storage.Config `yaml:"storage"`
|
||||
Storage *storage.Config `yaml:"storage,omitempty"`
|
||||
|
||||
// Web is the web configuration for the application
|
||||
Web *web.Config `yaml:"web"`
|
||||
Web *web.Config `yaml:"web,omitempty"`
|
||||
|
||||
// UI is the configuration for the UI
|
||||
UI *ui.Config `yaml:"ui"`
|
||||
UI *ui.Config `yaml:"ui,omitempty"`
|
||||
|
||||
// Maintenance is the configuration for creating a maintenance window in which no alerts are sent
|
||||
Maintenance *maintenance.Config `yaml:"maintenance"`
|
||||
Maintenance *maintenance.Config `yaml:"maintenance,omitempty"`
|
||||
|
||||
filePath string // path to the file from which config was loaded from
|
||||
lastFileModTime time.Time // last modification time
|
||||
@@ -149,12 +149,12 @@ func readConfigurationFile(fileName string) (config *Config, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// parseAndValidateConfigBytes parses a Gatus configuration file into a Config struct and validates its parameters
|
||||
func parseAndValidateConfigBytes(yamlBytes []byte) (config *Config, err error) {
|
||||
// Expand environment variables
|
||||
yamlBytes = []byte(os.ExpandEnv(string(yamlBytes)))
|
||||
// Parse configuration file
|
||||
err = yaml.Unmarshal(yamlBytes, &config)
|
||||
if err != nil {
|
||||
if err = yaml.Unmarshal(yamlBytes, &config); err != nil {
|
||||
return
|
||||
}
|
||||
if config != nil && len(config.Services) > 0 { // XXX: Remove this in v5.0.0
|
||||
@@ -167,8 +167,6 @@ func parseAndValidateConfigBytes(yamlBytes []byte) (config *Config, err error) {
|
||||
if config == nil || config.Endpoints == nil || len(config.Endpoints) == 0 {
|
||||
err = ErrNoEndpointInConfig
|
||||
} else {
|
||||
// Note that the functions below may panic, and this is on purpose to prevent Gatus from starting with
|
||||
// invalid configurations
|
||||
validateAlertingConfig(config.Alerting, config.Endpoints, config.Debug)
|
||||
if err := validateSecurityConfig(config); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -79,19 +79,19 @@ type Endpoint struct {
|
||||
Conditions []*Condition `yaml:"conditions"`
|
||||
|
||||
// Alerts is the alerting configuration for the endpoint in case of failure
|
||||
Alerts []*alert.Alert `yaml:"alerts"`
|
||||
Alerts []*alert.Alert `yaml:"alerts,omitempty"`
|
||||
|
||||
// ClientConfig is the configuration of the client used to communicate with the endpoint's target
|
||||
ClientConfig *client.Config `yaml:"client"`
|
||||
ClientConfig *client.Config `yaml:"client,omitempty"`
|
||||
|
||||
// UIConfig is the configuration for the UI
|
||||
UIConfig *ui.Config `yaml:"ui"`
|
||||
UIConfig *ui.Config `yaml:"ui,omitempty"`
|
||||
|
||||
// NumberOfFailuresInARow is the number of unsuccessful evaluations in a row
|
||||
NumberOfFailuresInARow int
|
||||
NumberOfFailuresInARow int `yaml:"-"`
|
||||
|
||||
// NumberOfSuccessesInARow is the number of successful evaluations in a row
|
||||
NumberOfSuccessesInARow int
|
||||
NumberOfSuccessesInARow int `yaml:"-"`
|
||||
}
|
||||
|
||||
// IsEnabled returns whether the endpoint is enabled or not
|
||||
|
||||
@@ -2,7 +2,11 @@ package memory
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -40,6 +44,20 @@ func NewStore(file string) (*Store, error) {
|
||||
if len(file) > 0 {
|
||||
_, err := store.cache.ReadFromFile(file)
|
||||
if err != nil {
|
||||
// XXX: Remove the block below in v4.0.0
|
||||
if data, err2 := ioutil.ReadFile(file); err2 == nil {
|
||||
isFromOldVersion := strings.Contains(string(data), "*core.ServiceStatus")
|
||||
if isFromOldVersion {
|
||||
log.Println("WARNING: Couldn't read file due to recent change in v3.3.0, see https://github.com/TwiN/gatus/issues/191")
|
||||
log.Println("WARNING: Will automatically rename old file to " + file + ".old and overwrite the current file")
|
||||
if err = ioutil.WriteFile(file+".old", data, fs.ModePerm); err != nil {
|
||||
log.Println("WARNING: Tried my best to keep the old file, but it wasn't enough. Sorry, your file will be overwritten :(")
|
||||
}
|
||||
// Return the store regardless of whether there was an error or not
|
||||
return store, nil
|
||||
}
|
||||
}
|
||||
// XXX: Remove the block above in v4.0.0
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user