Don't export, persist or retain result body after evaluation
This commit is contained in:
@ -38,7 +38,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: nil,
|
Errors: nil,
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: true,
|
Success: true,
|
||||||
@ -64,7 +63,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: []string{"error-1", "error-2"},
|
Errors: []string{"error-1", "error-2"},
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: false,
|
Success: false,
|
||||||
|
@ -23,7 +23,7 @@ const (
|
|||||||
|
|
||||||
// DNSRCodePlaceholder is a place holder for DNS_RCODE
|
// DNSRCodePlaceholder is a place holder for DNS_RCODE
|
||||||
//
|
//
|
||||||
// Values that could be NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMP and REFUSED
|
// Values that could replace the placeholder: NOERROR, FORMERR, SERVFAIL, NXDOMAIN, NOTIMP, REFUSED
|
||||||
DNSRCodePlaceholder = "[DNS_RCODE]"
|
DNSRCodePlaceholder = "[DNS_RCODE]"
|
||||||
|
|
||||||
// ResponseTimePlaceholder is a placeholder for the request response time, in milliseconds.
|
// ResponseTimePlaceholder is a placeholder for the request response time, in milliseconds.
|
||||||
@ -123,6 +123,12 @@ func (c Condition) evaluate(result *Result) bool {
|
|||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasBodyPlaceholder checks whether the condition has a BodyPlaceholder
|
||||||
|
// Used for determining whether the response body should be read or not
|
||||||
|
func (c Condition) hasBodyPlaceholder() bool {
|
||||||
|
return strings.Contains(string(c), BodyPlaceholder)
|
||||||
|
}
|
||||||
|
|
||||||
// isEqual compares two strings.
|
// isEqual compares two strings.
|
||||||
//
|
//
|
||||||
// Supports the pattern and the any functions.
|
// Supports the pattern and the any functions.
|
||||||
@ -181,7 +187,7 @@ func isEqual(first, second string) bool {
|
|||||||
func sanitizeAndResolve(elements []string, result *Result) ([]string, []string) {
|
func sanitizeAndResolve(elements []string, result *Result) ([]string, []string) {
|
||||||
parameters := make([]string, len(elements))
|
parameters := make([]string, len(elements))
|
||||||
resolvedParameters := make([]string, len(elements))
|
resolvedParameters := make([]string, len(elements))
|
||||||
body := strings.TrimSpace(string(result.Body))
|
body := strings.TrimSpace(string(result.body))
|
||||||
for i, element := range elements {
|
for i, element := range elements {
|
||||||
element = strings.TrimSpace(element)
|
element = strings.TrimSpace(element)
|
||||||
parameters[i] = element
|
parameters[i] = element
|
||||||
@ -208,7 +214,7 @@ func sanitizeAndResolve(elements []string, result *Result) ([]string, []string)
|
|||||||
wantLength = true
|
wantLength = true
|
||||||
element = strings.TrimSuffix(strings.TrimPrefix(element, LengthFunctionPrefix), FunctionSuffix)
|
element = strings.TrimSuffix(strings.TrimPrefix(element, LengthFunctionPrefix), FunctionSuffix)
|
||||||
}
|
}
|
||||||
resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.TrimPrefix(element, BodyPlaceholder+"."), result.Body)
|
resolvedElement, resolvedElementLength, err := jsonpath.Eval(strings.TrimPrefix(element, BodyPlaceholder+"."), result.body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err.Error() != "unexpected end of JSON input" {
|
if err.Error() != "unexpected end of JSON input" {
|
||||||
result.Errors = append(result.Errors, err.Error())
|
result.Errors = append(result.Errors, err.Error())
|
||||||
|
@ -5,7 +5,7 @@ import "testing"
|
|||||||
func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
@ -14,7 +14,7 @@ func BenchmarkCondition_evaluateWithBodyStringAny(b *testing.B) {
|
|||||||
func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
@ -23,7 +23,7 @@ func BenchmarkCondition_evaluateWithBodyStringAnyFailure(b *testing.B) {
|
|||||||
func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
||||||
condition := Condition("[BODY].name == john.doe")
|
condition := Condition("[BODY].name == john.doe")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
@ -32,7 +32,7 @@ func BenchmarkCondition_evaluateWithBodyString(b *testing.B) {
|
|||||||
func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
||||||
condition := Condition("[BODY].name == john.doe")
|
condition := Condition("[BODY].name == john.doe")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
@ -41,7 +41,7 @@ func BenchmarkCondition_evaluateWithBodyStringFailure(b *testing.B) {
|
|||||||
func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
||||||
condition := Condition("len([BODY].name) == 8")
|
condition := Condition("len([BODY].name) == 8")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
@ -50,7 +50,7 @@ func BenchmarkCondition_evaluateWithBodyStringLen(b *testing.B) {
|
|||||||
func BenchmarkCondition_evaluateWithBodyStringLenFailure(b *testing.B) {
|
func BenchmarkCondition_evaluateWithBodyStringLenFailure(b *testing.B) {
|
||||||
condition := Condition("len([BODY].name) == 8")
|
condition := Condition("len([BODY].name) == 8")
|
||||||
for n := 0; n < b.N; n++ {
|
for n := 0; n < b.N; n++ {
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
}
|
}
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
|
@ -162,7 +162,7 @@ func TestCondition_evaluateWithResponseTimeUsingLessThanOrEqualTo(t *testing.T)
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBody(t *testing.T) {
|
func TestCondition_evaluateWithBody(t *testing.T) {
|
||||||
condition := Condition("[BODY] == test")
|
condition := Condition("[BODY] == test")
|
||||||
result := &Result{Body: []byte("test")}
|
result := &Result{body: []byte("test")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -175,7 +175,7 @@ func TestCondition_evaluateWithBody(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPath(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPath(t *testing.T) {
|
||||||
condition := Condition("[BODY].status == UP")
|
condition := Condition("[BODY].status == UP")
|
||||||
result := &Result{Body: []byte("{\"status\":\"UP\"}")}
|
result := &Result{body: []byte("{\"status\":\"UP\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -188,7 +188,7 @@ func TestCondition_evaluateWithBodyJSONPath(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplex(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplex(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.name == john")
|
condition := Condition("[BODY].data.name == john")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1, \"name\": \"john\"}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1, \"name\": \"john\"}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -201,7 +201,7 @@ func TestCondition_evaluateWithBodyJSONPathComplex(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithInvalidBodyJSONPathComplex(t *testing.T) {
|
func TestCondition_evaluateWithInvalidBodyJSONPathComplex(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.name == john")
|
condition := Condition("[BODY].data.name == john")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure, because the path was invalid", condition)
|
t.Errorf("Condition '%s' should have been a failure, because the path was invalid", condition)
|
||||||
@ -214,7 +214,7 @@ func TestCondition_evaluateWithInvalidBodyJSONPathComplex(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithInvalidBodyJSONPathComplexWithLengthFunction(t *testing.T) {
|
func TestCondition_evaluateWithInvalidBodyJSONPathComplexWithLengthFunction(t *testing.T) {
|
||||||
condition := Condition("len([BODY].data.name) == john")
|
condition := Condition("len([BODY].data.name) == john")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure, because the path was invalid", condition)
|
t.Errorf("Condition '%s' should have been a failure, because the path was invalid", condition)
|
||||||
@ -227,7 +227,7 @@ func TestCondition_evaluateWithInvalidBodyJSONPathComplexWithLengthFunction(t *t
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathDoublePlaceholders(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathDoublePlaceholders(t *testing.T) {
|
||||||
condition := Condition("[BODY].user.firstName != [BODY].user.lastName")
|
condition := Condition("[BODY].user.firstName != [BODY].user.lastName")
|
||||||
result := &Result{Body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")}
|
result := &Result{body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -240,7 +240,7 @@ func TestCondition_evaluateWithBodyJSONPathDoublePlaceholders(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathDoublePlaceholdersFailure(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathDoublePlaceholdersFailure(t *testing.T) {
|
||||||
condition := Condition("[BODY].user.firstName == [BODY].user.lastName")
|
condition := Condition("[BODY].user.firstName == [BODY].user.lastName")
|
||||||
result := &Result{Body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")}
|
result := &Result{body: []byte("{\"user\": {\"firstName\": \"john\", \"lastName\": \"doe\"}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
@ -253,7 +253,7 @@ func TestCondition_evaluateWithBodyJSONPathDoublePlaceholdersFailure(t *testing.
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathLongInt(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathLongInt(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.id == 1")
|
condition := Condition("[BODY].data.id == 1")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -266,7 +266,7 @@ func TestCondition_evaluateWithBodyJSONPathLongInt(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplexInt(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplexInt(t *testing.T) {
|
||||||
condition := Condition("[BODY].data[1].id == 2")
|
condition := Condition("[BODY].data[1].id == 2")
|
||||||
result := &Result{Body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")}
|
result := &Result{body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -279,7 +279,7 @@ func TestCondition_evaluateWithBodyJSONPathComplexInt(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplexIntUsingGreaterThan(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplexIntUsingGreaterThan(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.id > 0")
|
condition := Condition("[BODY].data.id > 0")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -292,7 +292,7 @@ func TestCondition_evaluateWithBodyJSONPathComplexIntUsingGreaterThan(t *testing
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingGreaterThan(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingGreaterThan(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.id > 5")
|
condition := Condition("[BODY].data.id > 5")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 1}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 1}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
@ -305,7 +305,7 @@ func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingGreaterThan(t *
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplexIntUsingLessThan(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplexIntUsingLessThan(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.id < 5")
|
condition := Condition("[BODY].data.id < 5")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 2}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 2}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -318,7 +318,7 @@ func TestCondition_evaluateWithBodyJSONPathComplexIntUsingLessThan(t *testing.T)
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingLessThan(t *testing.T) {
|
func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingLessThan(t *testing.T) {
|
||||||
condition := Condition("[BODY].data.id < 5")
|
condition := Condition("[BODY].data.id < 5")
|
||||||
result := &Result{Body: []byte("{\"data\": {\"id\": 10}}")}
|
result := &Result{body: []byte("{\"data\": {\"id\": 10}}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
@ -331,7 +331,7 @@ func TestCondition_evaluateWithBodyJSONPathComplexIntFailureUsingLessThan(t *tes
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodySliceLength(t *testing.T) {
|
func TestCondition_evaluateWithBodySliceLength(t *testing.T) {
|
||||||
condition := Condition("len([BODY].data) == 3")
|
condition := Condition("len([BODY].data) == 3")
|
||||||
result := &Result{Body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")}
|
result := &Result{body: []byte("{\"data\": [{\"id\": 1}, {\"id\": 2}, {\"id\": 3}]}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -344,7 +344,7 @@ func TestCondition_evaluateWithBodySliceLength(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyStringLength(t *testing.T) {
|
func TestCondition_evaluateWithBodyStringLength(t *testing.T) {
|
||||||
condition := Condition("len([BODY].name) == 8")
|
condition := Condition("len([BODY].name) == 8")
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -357,7 +357,7 @@ func TestCondition_evaluateWithBodyStringLength(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyPattern(t *testing.T) {
|
func TestCondition_evaluateWithBodyPattern(t *testing.T) {
|
||||||
condition := Condition("[BODY] == pat(*john*)")
|
condition := Condition("[BODY] == pat(*john*)")
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -370,7 +370,7 @@ func TestCondition_evaluateWithBodyPattern(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithReverseBodyPattern(t *testing.T) {
|
func TestCondition_evaluateWithReverseBodyPattern(t *testing.T) {
|
||||||
condition := Condition("pat(*john*) == [BODY]")
|
condition := Condition("pat(*john*) == [BODY]")
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -383,7 +383,7 @@ func TestCondition_evaluateWithReverseBodyPattern(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyStringPattern(t *testing.T) {
|
func TestCondition_evaluateWithBodyStringPattern(t *testing.T) {
|
||||||
condition := Condition("[BODY].name == pat(*ohn*)")
|
condition := Condition("[BODY].name == pat(*ohn*)")
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -397,7 +397,7 @@ func TestCondition_evaluateWithBodyStringPattern(t *testing.T) {
|
|||||||
func TestCondition_evaluateWithBodyHTMLPattern(t *testing.T) {
|
func TestCondition_evaluateWithBodyHTMLPattern(t *testing.T) {
|
||||||
var html = `<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">john.doe</div></body></html>`
|
var html = `<!DOCTYPE html><html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body><div id="user">john.doe</div></body></html>`
|
||||||
condition := Condition("[BODY] == pat(*<div id=\"user\">john.doe</div>*)")
|
condition := Condition("[BODY] == pat(*<div id=\"user\">john.doe</div>*)")
|
||||||
result := &Result{Body: []byte(html)}
|
result := &Result{body: []byte(html)}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a success", condition)
|
t.Errorf("Condition '%s' should have been a success", condition)
|
||||||
@ -410,7 +410,7 @@ func TestCondition_evaluateWithBodyHTMLPattern(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyStringPatternFailure(t *testing.T) {
|
func TestCondition_evaluateWithBodyStringPatternFailure(t *testing.T) {
|
||||||
condition := Condition("[BODY].name == pat(bob*)")
|
condition := Condition("[BODY].name == pat(bob*)")
|
||||||
result := &Result{Body: []byte("{\"name\": \"john.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"john.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
@ -477,8 +477,8 @@ func TestCondition_evaluateWithBodyStringAny(t *testing.T) {
|
|||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
expectedConditionDisplayed := "[BODY].name == any(john.doe, jane.doe)"
|
expectedConditionDisplayed := "[BODY].name == any(john.doe, jane.doe)"
|
||||||
results := []*Result{
|
results := []*Result{
|
||||||
{Body: []byte("{\"name\": \"john.doe\"}")},
|
{body: []byte("{\"name\": \"john.doe\"}")},
|
||||||
{Body: []byte("{\"name\": \"jane.doe\"}")},
|
{body: []byte("{\"name\": \"jane.doe\"}")},
|
||||||
}
|
}
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
success := condition.evaluate(result)
|
success := condition.evaluate(result)
|
||||||
@ -493,7 +493,7 @@ func TestCondition_evaluateWithBodyStringAny(t *testing.T) {
|
|||||||
|
|
||||||
func TestCondition_evaluateWithBodyStringAnyFailure(t *testing.T) {
|
func TestCondition_evaluateWithBodyStringAnyFailure(t *testing.T) {
|
||||||
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
condition := Condition("[BODY].name == any(john.doe, jane.doe)")
|
||||||
result := &Result{Body: []byte("{\"name\": \"bob.doe\"}")}
|
result := &Result{body: []byte("{\"name\": \"bob.doe\"}")}
|
||||||
condition.evaluate(result)
|
condition.evaluate(result)
|
||||||
if result.ConditionResults[0].Success {
|
if result.ConditionResults[0].Success {
|
||||||
t.Errorf("Condition '%s' should have been a failure", condition)
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
@ -660,3 +660,27 @@ func TestCondition_evaluateWithCertificateExpirationGreaterThanDurationFailure(t
|
|||||||
t.Errorf("Condition '%s' should have resolved to '%s', got '%s'", condition, expectedConditionDisplayed, result.ConditionResults[0].Condition)
|
t.Errorf("Condition '%s' should have resolved to '%s', got '%s'", condition, expectedConditionDisplayed, result.ConditionResults[0].Condition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCondition_evaluateWithInvalidOperator(t *testing.T) {
|
||||||
|
condition := Condition("[STATUS] ? 201")
|
||||||
|
result := &Result{HTTPStatus: 201}
|
||||||
|
condition.evaluate(result)
|
||||||
|
if result.Success {
|
||||||
|
t.Error("condition was invalid, result should've been a failure")
|
||||||
|
}
|
||||||
|
if len(result.Errors) != 1 {
|
||||||
|
t.Error("condition was invalid, result should've had an error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCondition_evaluateWithNoPlaceholder(t *testing.T) {
|
||||||
|
condition := Condition("1 == 2")
|
||||||
|
result := &Result{}
|
||||||
|
condition.evaluate(result)
|
||||||
|
if result.ConditionResults[0].Success {
|
||||||
|
t.Errorf("Condition '%s' should have been a failure", condition)
|
||||||
|
}
|
||||||
|
if result.ConditionResults[0].Condition != string(condition) {
|
||||||
|
t.Errorf("Condition '%s' should have resolved to '%s', got '%s'", condition, condition, result.ConditionResults[0].Condition)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
12
core/dns.go
12
core/dns.go
@ -60,26 +60,26 @@ func (d *DNS) query(url string, result *Result) {
|
|||||||
switch rr.Header().Rrtype {
|
switch rr.Header().Rrtype {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
if a, ok := rr.(*dns.A); ok {
|
if a, ok := rr.(*dns.A); ok {
|
||||||
result.Body = []byte(a.A.String())
|
result.body = []byte(a.A.String())
|
||||||
}
|
}
|
||||||
case dns.TypeAAAA:
|
case dns.TypeAAAA:
|
||||||
if aaaa, ok := rr.(*dns.AAAA); ok {
|
if aaaa, ok := rr.(*dns.AAAA); ok {
|
||||||
result.Body = []byte(aaaa.AAAA.String())
|
result.body = []byte(aaaa.AAAA.String())
|
||||||
}
|
}
|
||||||
case dns.TypeCNAME:
|
case dns.TypeCNAME:
|
||||||
if cname, ok := rr.(*dns.CNAME); ok {
|
if cname, ok := rr.(*dns.CNAME); ok {
|
||||||
result.Body = []byte(cname.Target)
|
result.body = []byte(cname.Target)
|
||||||
}
|
}
|
||||||
case dns.TypeMX:
|
case dns.TypeMX:
|
||||||
if mx, ok := rr.(*dns.MX); ok {
|
if mx, ok := rr.(*dns.MX); ok {
|
||||||
result.Body = []byte(mx.Mx)
|
result.body = []byte(mx.Mx)
|
||||||
}
|
}
|
||||||
case dns.TypeNS:
|
case dns.TypeNS:
|
||||||
if ns, ok := rr.(*dns.NS); ok {
|
if ns, ok := rr.(*dns.NS); ok {
|
||||||
result.Body = []byte(ns.Ns)
|
result.body = []byte(ns.Ns)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
result.Body = []byte("query type is not supported yet")
|
result.body = []byte("query type is not supported yet")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,12 +91,12 @@ func TestIntegrationQuery(t *testing.T) {
|
|||||||
|
|
||||||
if test.inputDNS.QueryType == "NS" {
|
if test.inputDNS.QueryType == "NS" {
|
||||||
// Because there are often multiple nameservers backing a single domain, we'll only look at the suffix
|
// Because there are often multiple nameservers backing a single domain, we'll only look at the suffix
|
||||||
if !pattern.Match(test.expectedBody, string(result.Body)) {
|
if !pattern.Match(test.expectedBody, string(result.body)) {
|
||||||
t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
|
t.Errorf("got %s, expected result %s,", string(result.body), test.expectedBody)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if string(result.Body) != test.expectedBody {
|
if string(result.body) != test.expectedBody {
|
||||||
t.Errorf("got %s, expected result %s,", string(result.Body), test.expectedBody)
|
t.Errorf("got %s, expected result %s,", string(result.body), test.expectedBody)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -12,10 +12,7 @@ type Result struct {
|
|||||||
// DNSRCode is the response code of a DNS query in a human readable format
|
// DNSRCode is the response code of a DNS query in a human readable format
|
||||||
DNSRCode string `json:"-"`
|
DNSRCode string `json:"-"`
|
||||||
|
|
||||||
// Body is the response body
|
// Hostname extracted from Service.URL
|
||||||
Body []byte `json:"-"`
|
|
||||||
|
|
||||||
// Hostname extracted from the Service URL
|
|
||||||
Hostname string `json:"hostname"`
|
Hostname string `json:"hostname"`
|
||||||
|
|
||||||
// IP resolved from the Service URL
|
// IP resolved from the Service URL
|
||||||
@ -41,4 +38,11 @@ type Result struct {
|
|||||||
|
|
||||||
// CertificateExpiration is the duration before the certificate expires
|
// CertificateExpiration is the duration before the certificate expires
|
||||||
CertificateExpiration time.Duration `json:"-"`
|
CertificateExpiration time.Duration `json:"-"`
|
||||||
|
|
||||||
|
// body is the response body
|
||||||
|
//
|
||||||
|
// Note that this variable is only used during the evaluation of a service's health.
|
||||||
|
// This means that the call Service.EvaluateHealth both populates the body (if necessary)
|
||||||
|
// and sets it to nil after the evaluation has been completed.
|
||||||
|
body []byte
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
body: []byte("body"),
|
||||||
Errors: nil,
|
Errors: nil,
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: true,
|
Success: true,
|
||||||
@ -55,7 +55,7 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
body: []byte("body"),
|
||||||
Errors: []string{"error-1", "error-2"},
|
Errors: []string{"error-1", "error-2"},
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: false,
|
Success: false,
|
||||||
|
@ -80,7 +80,7 @@ type Service struct {
|
|||||||
// NumberOfFailuresInARow is the number of unsuccessful evaluations in a row
|
// NumberOfFailuresInARow is the number of unsuccessful evaluations in a row
|
||||||
NumberOfFailuresInARow int
|
NumberOfFailuresInARow int
|
||||||
|
|
||||||
// NumberOfFailuresInARow is the number of successful evaluations in a row
|
// NumberOfSuccessesInARow is the number of successful evaluations in a row
|
||||||
NumberOfSuccessesInARow int
|
NumberOfSuccessesInARow int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,6 +149,8 @@ func (service *Service) EvaluateHealth() *Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.Timestamp = time.Now()
|
result.Timestamp = time.Now()
|
||||||
|
// No need to keep the body after the service has been evaluated
|
||||||
|
result.body = nil
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,11 +222,14 @@ func (service *Service) call(result *Result) {
|
|||||||
}
|
}
|
||||||
result.HTTPStatus = response.StatusCode
|
result.HTTPStatus = response.StatusCode
|
||||||
result.Connected = response.StatusCode > 0
|
result.Connected = response.StatusCode > 0
|
||||||
result.Body, err = ioutil.ReadAll(response.Body)
|
// Only read the body if there's a condition that uses the BodyPlaceholder
|
||||||
|
if service.needsToReadBody() {
|
||||||
|
result.body, err = ioutil.ReadAll(response.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Errors = append(result.Errors, err.Error())
|
result.Errors = append(result.Errors, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (service *Service) buildHTTPRequest() *http.Request {
|
func (service *Service) buildHTTPRequest() *http.Request {
|
||||||
@ -247,3 +252,13 @@ func (service *Service) buildHTTPRequest() *http.Request {
|
|||||||
}
|
}
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// needsToReadBody checks if there's any conditions that requires the response body to be read
|
||||||
|
func (service *Service) needsToReadBody() bool {
|
||||||
|
for _, condition := range service.Conditions {
|
||||||
|
if condition.hasBodyPlaceholder() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
func TestService_ValidateAndSetDefaults(t *testing.T) {
|
func TestService_ValidateAndSetDefaults(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
Alerts: []*Alert{{Type: PagerDutyAlert}},
|
Alerts: []*Alert{{Type: PagerDutyAlert}},
|
||||||
@ -94,7 +94,7 @@ func TestService_ValidateAndSetDefaultsWithDNS(t *testing.T) {
|
|||||||
func TestService_GetAlertsTriggered(t *testing.T) {
|
func TestService_GetAlertsTriggered(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
Alerts: []*Alert{{Type: PagerDutyAlert, Enabled: true}},
|
Alerts: []*Alert{{Type: PagerDutyAlert, Enabled: true}},
|
||||||
@ -118,7 +118,7 @@ func TestService_GetAlertsTriggered(t *testing.T) {
|
|||||||
func TestService_buildHTTPRequest(t *testing.T) {
|
func TestService_buildHTTPRequest(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
}
|
}
|
||||||
@ -138,7 +138,7 @@ func TestService_buildHTTPRequest(t *testing.T) {
|
|||||||
func TestService_buildHTTPRequestWithCustomUserAgent(t *testing.T) {
|
func TestService_buildHTTPRequestWithCustomUserAgent(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
Headers: map[string]string{
|
Headers: map[string]string{
|
||||||
@ -161,7 +161,7 @@ func TestService_buildHTTPRequestWithCustomUserAgent(t *testing.T) {
|
|||||||
func TestService_buildHTTPRequestWithHostHeader(t *testing.T) {
|
func TestService_buildHTTPRequestWithHostHeader(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
@ -182,7 +182,7 @@ func TestService_buildHTTPRequestWithHostHeader(t *testing.T) {
|
|||||||
func TestService_buildHTTPRequestWithGraphQLEnabled(t *testing.T) {
|
func TestService_buildHTTPRequestWithGraphQLEnabled(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-graphql",
|
||||||
URL: "https://twinnation.org/graphql",
|
URL: "https://twinnation.org/graphql",
|
||||||
Method: "POST",
|
Method: "POST",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
@ -206,16 +206,17 @@ func TestService_buildHTTPRequestWithGraphQLEnabled(t *testing.T) {
|
|||||||
}
|
}
|
||||||
body, _ := ioutil.ReadAll(request.Body)
|
body, _ := ioutil.ReadAll(request.Body)
|
||||||
if !strings.HasPrefix(string(body), "{\"query\":") {
|
if !strings.HasPrefix(string(body), "{\"query\":") {
|
||||||
t.Error("request.Body should've started with '{\"query\":', but it didn't:", string(body))
|
t.Error("request.body should've started with '{\"query\":', but it didn't:", string(body))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIntegrationEvaluateHealth(t *testing.T) {
|
func TestIntegrationEvaluateHealth(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 200")
|
condition := Condition("[STATUS] == 200")
|
||||||
|
bodyCondition := Condition("[BODY].status == UP")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition, &bodyCondition},
|
||||||
}
|
}
|
||||||
result := service.EvaluateHealth()
|
result := service.EvaluateHealth()
|
||||||
if !result.ConditionResults[0].Success {
|
if !result.ConditionResults[0].Success {
|
||||||
@ -232,7 +233,7 @@ func TestIntegrationEvaluateHealth(t *testing.T) {
|
|||||||
func TestIntegrationEvaluateHealthWithFailure(t *testing.T) {
|
func TestIntegrationEvaluateHealthWithFailure(t *testing.T) {
|
||||||
condition := Condition("[STATUS] == 500")
|
condition := Condition("[STATUS] == 500")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "twinnation-health",
|
||||||
URL: "https://twinnation.org/health",
|
URL: "https://twinnation.org/health",
|
||||||
Conditions: []*Condition{&condition},
|
Conditions: []*Condition{&condition},
|
||||||
}
|
}
|
||||||
@ -252,7 +253,7 @@ func TestIntegrationEvaluateHealthForDNS(t *testing.T) {
|
|||||||
conditionSuccess := Condition("[DNS_RCODE] == NOERROR")
|
conditionSuccess := Condition("[DNS_RCODE] == NOERROR")
|
||||||
conditionBody := Condition("[BODY] == 93.184.216.34")
|
conditionBody := Condition("[BODY] == 93.184.216.34")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "TwiNNatioN",
|
Name: "example",
|
||||||
URL: "8.8.8.8",
|
URL: "8.8.8.8",
|
||||||
DNS: &DNS{
|
DNS: &DNS{
|
||||||
QueryType: "A",
|
QueryType: "A",
|
||||||
@ -275,7 +276,7 @@ func TestIntegrationEvaluateHealthForDNS(t *testing.T) {
|
|||||||
func TestIntegrationEvaluateHealthForICMP(t *testing.T) {
|
func TestIntegrationEvaluateHealthForICMP(t *testing.T) {
|
||||||
conditionSuccess := Condition("[CONNECTED] == true")
|
conditionSuccess := Condition("[CONNECTED] == true")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "ICMP test",
|
Name: "icmp-test",
|
||||||
URL: "icmp://127.0.0.1",
|
URL: "icmp://127.0.0.1",
|
||||||
Conditions: []*Condition{&conditionSuccess},
|
Conditions: []*Condition{&conditionSuccess},
|
||||||
}
|
}
|
||||||
@ -294,7 +295,7 @@ func TestIntegrationEvaluateHealthForICMP(t *testing.T) {
|
|||||||
func TestService_getIP(t *testing.T) {
|
func TestService_getIP(t *testing.T) {
|
||||||
conditionSuccess := Condition("[CONNECTED] == true")
|
conditionSuccess := Condition("[CONNECTED] == true")
|
||||||
service := Service{
|
service := Service{
|
||||||
Name: "Invalid URL test",
|
Name: "invalid-url-test",
|
||||||
URL: "",
|
URL: "",
|
||||||
Conditions: []*Condition{&conditionSuccess},
|
Conditions: []*Condition{&conditionSuccess},
|
||||||
}
|
}
|
||||||
@ -304,3 +305,27 @@ func TestService_getIP(t *testing.T) {
|
|||||||
t.Error("service.getIP(result) should've thrown an error because the URL is invalid, thus cannot be parsed")
|
t.Error("service.getIP(result) should've thrown an error because the URL is invalid, thus cannot be parsed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestService_NeedsToReadBody(t *testing.T) {
|
||||||
|
statusCondition := Condition("[STATUS] == 200")
|
||||||
|
bodyCondition := Condition("[BODY].status == UP")
|
||||||
|
bodyConditionWithLength := Condition("len([BODY].tags) > 0")
|
||||||
|
if (&Service{Conditions: []*Condition{&statusCondition}}).needsToReadBody() {
|
||||||
|
t.Error("expected false, got true")
|
||||||
|
}
|
||||||
|
if !(&Service{Conditions: []*Condition{&bodyCondition}}).needsToReadBody() {
|
||||||
|
t.Error("expected true, got false")
|
||||||
|
}
|
||||||
|
if !(&Service{Conditions: []*Condition{&bodyConditionWithLength}}).needsToReadBody() {
|
||||||
|
t.Error("expected true, got false")
|
||||||
|
}
|
||||||
|
if !(&Service{Conditions: []*Condition{&statusCondition, &bodyCondition}}).needsToReadBody() {
|
||||||
|
t.Error("expected true, got false")
|
||||||
|
}
|
||||||
|
if !(&Service{Conditions: []*Condition{&bodyCondition, &statusCondition}}).needsToReadBody() {
|
||||||
|
t.Error("expected true, got false")
|
||||||
|
}
|
||||||
|
if !(&Service{Conditions: []*Condition{&bodyConditionWithLength, &statusCondition}}).needsToReadBody() {
|
||||||
|
t.Error("expected true, got false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -33,7 +33,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: nil,
|
Errors: nil,
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: true,
|
Success: true,
|
||||||
@ -59,7 +58,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: []string{"error-1", "error-2"},
|
Errors: []string{"error-1", "error-2"},
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: false,
|
Success: false,
|
||||||
@ -107,9 +105,6 @@ func TestStore_Insert(t *testing.T) {
|
|||||||
if r.DNSRCode != expectedResult.DNSRCode {
|
if r.DNSRCode != expectedResult.DNSRCode {
|
||||||
t.Errorf("Result at index %d should've had a DNSRCode of %s, but was actually %s", i, expectedResult.DNSRCode, r.DNSRCode)
|
t.Errorf("Result at index %d should've had a DNSRCode of %s, but was actually %s", i, expectedResult.DNSRCode, r.DNSRCode)
|
||||||
}
|
}
|
||||||
if len(r.Body) != len(expectedResult.Body) {
|
|
||||||
t.Errorf("Result at index %d should've had a body of length %d, but was actually %d", i, len(expectedResult.Body), len(r.Body))
|
|
||||||
}
|
|
||||||
if r.Hostname != expectedResult.Hostname {
|
if r.Hostname != expectedResult.Hostname {
|
||||||
t.Errorf("Result at index %d should've had a Hostname of %s, but was actually %s", i, expectedResult.Hostname, r.Hostname)
|
t.Errorf("Result at index %d should've had a Hostname of %s, but was actually %s", i, expectedResult.Hostname, r.Hostname)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: nil,
|
Errors: nil,
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: true,
|
Success: true,
|
||||||
@ -58,7 +57,6 @@ var (
|
|||||||
Hostname: "example.org",
|
Hostname: "example.org",
|
||||||
IP: "127.0.0.1",
|
IP: "127.0.0.1",
|
||||||
HTTPStatus: 200,
|
HTTPStatus: 200,
|
||||||
Body: []byte("body"),
|
|
||||||
Errors: []string{"error-1", "error-2"},
|
Errors: []string{"error-1", "error-2"},
|
||||||
Connected: true,
|
Connected: true,
|
||||||
Success: false,
|
Success: false,
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package watchdog
|
package watchdog
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -37,26 +36,22 @@ func monitor(service *core.Service) {
|
|||||||
monitoringMutex.Lock()
|
monitoringMutex.Lock()
|
||||||
}
|
}
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
log.Printf("[watchdog][monitor] Monitoring serviceName=%s", service.Name)
|
log.Printf("[watchdog][monitor] Monitoring group=%s; service=%s", service.Group, service.Name)
|
||||||
}
|
}
|
||||||
result := service.EvaluateHealth()
|
result := service.EvaluateHealth()
|
||||||
metric.PublishMetricsForService(service, result)
|
metric.PublishMetricsForService(service, result)
|
||||||
UpdateServiceStatuses(service, result)
|
UpdateServiceStatuses(service, result)
|
||||||
var extra string
|
|
||||||
if !result.Success {
|
|
||||||
extra = fmt.Sprintf("responseBody=%s", result.Body)
|
|
||||||
}
|
|
||||||
log.Printf(
|
log.Printf(
|
||||||
"[watchdog][monitor] Monitored serviceName=%s; success=%v; errors=%d; requestDuration=%s; %s",
|
"[watchdog][monitor] Monitored group=%s; service=%s; success=%v; errors=%d; duration=%s",
|
||||||
|
service.Group,
|
||||||
service.Name,
|
service.Name,
|
||||||
result.Success,
|
result.Success,
|
||||||
len(result.Errors),
|
len(result.Errors),
|
||||||
result.Duration.Round(time.Millisecond),
|
result.Duration.Round(time.Millisecond),
|
||||||
extra,
|
|
||||||
)
|
)
|
||||||
HandleAlerting(service, result)
|
HandleAlerting(service, result)
|
||||||
if cfg.Debug {
|
if cfg.Debug {
|
||||||
log.Printf("[watchdog][monitor] Waiting for interval=%s before monitoring serviceName=%s again", service.Interval, service.Name)
|
log.Printf("[watchdog][monitor] Waiting for interval=%s before monitoring group=%s service=%s again", service.Interval, service.Group, service.Name)
|
||||||
}
|
}
|
||||||
if !cfg.DisableMonitoringLock {
|
if !cfg.DisableMonitoringLock {
|
||||||
monitoringMutex.Unlock()
|
monitoringMutex.Unlock()
|
||||||
|
Reference in New Issue
Block a user