Move structs to core package

This commit is contained in:
TwinProduction 2019-09-06 20:25:31 -04:00
parent eea38c8618
commit ee479be716
6 changed files with 153 additions and 81 deletions

View File

@ -1,13 +1,12 @@
services:
- name: twinnation
url: https://twinnation.org/actuator/health
interval: 10
interval: 15
failure-threshold: 3
conditions:
- "$STATUS == 200"
- name: github
url: https://github.com
interval: 10
failure-threshold: 3
conditions:
- "$STATUS == 200"
- "$STATUS != 400"
- "$STATUS != 500"

View File

@ -1,24 +1,15 @@
package config
import (
"github.com/TwinProduction/gatus/core"
"gopkg.in/yaml.v2"
"io/ioutil"
)
type Config struct {
Services []Service `yaml:"services"`
Services []*core.Service `yaml:"services"`
}
type Service struct {
Name string `yaml:"name"`
Url string `yaml:"url"`
Interval uint `yaml:"interval"`
FailureThreshold uint `yaml:"failure-threshold"`
Conditions []Condition `yaml:"conditions"`
}
type Condition string
var config *Config
func Get() *Config {
@ -41,5 +32,13 @@ func ReadConfigurationFile(fileName string) *Config {
func ParseConfigBytes(yamlBytes []byte) *Config {
config = &Config{}
yaml.Unmarshal(yamlBytes, config)
for _, service := range config.Services {
if service.FailureThreshold == 0 {
service.FailureThreshold = 1
}
if service.Interval == 0 {
service.Interval = 10
}
}
return config
}

View File

@ -7,16 +7,14 @@ func TestParseConfigBytes(t *testing.T) {
services:
- name: twinnation
url: https://twinnation.org/actuator/health
interval: 10
interval: 15
failure-threshold: 3
conditions:
- "$STATUS == 200"
- name: github
url: https://github.com
interval: 9
failure-threshold: 2
conditions:
- "$STATUS != 405"
- "$STATUS != 400"
- "$STATUS != 500"
`))
if len(config.Services) != 2 {
@ -28,17 +26,17 @@ services:
if config.Services[1].Url != "https://github.com" {
t.Errorf("URL should have been %s", "https://github.com")
}
if config.Services[0].Interval != 10 {
t.Errorf("Interval should have been %d", 10)
if config.Services[0].Interval != 15 {
t.Errorf("Interval should have been %d", 15)
}
if config.Services[1].Interval != 9 {
t.Errorf("Interval should have been %d", 9)
if config.Services[1].Interval != 10 {
t.Errorf("Interval should have been %d, because it is the default value", 10)
}
if config.Services[0].FailureThreshold != 3 {
t.Errorf("FailureThreshold should have been %d", 3)
}
if config.Services[1].FailureThreshold != 2 {
t.Errorf("FailureThreshold should have been %d", 2)
if config.Services[1].FailureThreshold != 1 {
t.Errorf("FailureThreshold should have been %d, because it is the default value", 1)
}
if len(config.Services[0].Conditions) != 1 {
t.Errorf("There should have been %d conditions", 1)

126
core/types.go Normal file
View File

@ -0,0 +1,126 @@
package core
import (
"fmt"
"net"
"net/http"
"net/url"
"strconv"
"strings"
"time"
)
type Result struct {
HttpStatus int
Hostname string
Ip string
Duration time.Duration
Errors []error
ConditionResult []*ConditionResult
}
type Service struct {
Name string `yaml:"name"`
Url string `yaml:"url"`
Interval int `yaml:"interval,omitempty"`
FailureThreshold int `yaml:"failure-threshold,omitempty"`
Conditions []*Condition `yaml:"conditions"`
}
func (service *Service) getIp(result *Result) {
urlObject, err := url.Parse(service.Url)
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Hostname = urlObject.Hostname()
ips, err := net.LookupIP(urlObject.Hostname())
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Ip = ips[0].String()
}
func (service *Service) getStatus(result *Result) {
client := &http.Client{
Timeout: time.Second * 10,
}
startTime := time.Now()
response, err := client.Get(service.Url)
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Duration = time.Now().Sub(startTime)
result.HttpStatus = response.StatusCode
}
func (service *Service) EvaluateConditions() *Result {
result := &Result{}
service.getStatus(result)
service.getIp(result)
for _, condition := range service.Conditions {
condition.Evaluate(result)
}
return result
}
type ConditionResult struct {
Condition *Condition
Success bool
Explanation string
}
type Condition string
func (c *Condition) Evaluate(result *Result) {
condition := string(*c)
if strings.Contains(condition, "==") {
parts := sanitizeAndResolve(strings.Split(condition, "=="), result)
if parts[0] == parts[1] {
result.ConditionResult = append(result.ConditionResult, &ConditionResult{
Condition: c,
Success: true,
Explanation: fmt.Sprintf("%s is equal to %s", parts[0], parts[1]),
})
} else {
result.ConditionResult = append(result.ConditionResult, &ConditionResult{
Condition: c,
Success: false,
Explanation: fmt.Sprintf("%s is not equal to %s", parts[0], parts[1]),
})
}
} else if strings.Contains(condition, "!=") {
parts := sanitizeAndResolve(strings.Split(condition, "!="), result)
if parts[0] != parts[1] {
result.ConditionResult = append(result.ConditionResult, &ConditionResult{
Condition: c,
Success: true,
Explanation: fmt.Sprintf("%s is not equal to %s", parts[0], parts[1]),
})
} else {
result.ConditionResult = append(result.ConditionResult, &ConditionResult{
Condition: c,
Success: false,
Explanation: fmt.Sprintf("%s is equal to %s", parts[0], parts[1]),
})
}
}
}
func sanitizeAndResolve(list []string, result *Result) []string {
var sanitizedList []string
for _, element := range list {
element = strings.TrimSpace(element)
switch strings.ToUpper(element) {
case "$STATUS":
element = strconv.Itoa(result.HttpStatus)
case "$IP":
element = result.Ip
default:
}
sanitizedList = append(sanitizedList, element)
}
return sanitizedList
}

14
main.go
View File

@ -3,15 +3,13 @@ package main
import (
"fmt"
"github.com/TwinProduction/gatus/config"
"github.com/TwinProduction/gatus/watchdog"
)
func main() {
request := watchdog.Request{Url: "https://twinnation.org/actuator/health"}
result := &watchdog.Result{}
request.GetIp(result)
request.GetStatus(result)
fmt.Println(result)
fmt.Println(config.Get())
for _, service := range config.Get().Services {
result := service.EvaluateConditions()
for _, conditionResult := range result.ConditionResult {
fmt.Printf("%v\n", *conditionResult)
}
}
}

View File

@ -1,49 +1 @@
package watchdog
import (
"net"
"net/http"
"net/url"
"time"
)
type Request struct {
Url string
}
type Result struct {
HttpStatus int
Hostname string
Ip string
Duration time.Duration
Errors []error
}
func (request *Request) GetIp(result *Result) {
urlObject, err := url.Parse(request.Url)
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Hostname = urlObject.Hostname()
ips, err := net.LookupIP(urlObject.Hostname())
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Ip = ips[0].String()
}
func (request *Request) GetStatus(result *Result) {
client := &http.Client{
Timeout: time.Second * 10,
}
startTime := time.Now()
response, err := client.Get(request.Url)
if err != nil {
result.Errors = append(result.Errors, err)
return
}
result.Duration = time.Now().Sub(startTime)
result.HttpStatus = response.StatusCode
}