mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-02-14 18:29:53 +00:00
Http comperators (#1753)
* Allowing more comperators for the http analyzer * test * Update pkg/analyze/host_http.go Co-authored-by: Andrew Lavery <laverya@umich.edu> --------- Co-authored-by: Andrew Lavery <laverya@umich.edu>
This commit is contained in:
committed by
GitHub
parent
c770c32c2e
commit
3665d25abf
1
go.mod
1
go.mod
@@ -9,6 +9,7 @@ require (
|
||||
github.com/ahmetalpbalkan/go-cursor v0.0.0-20131010032410-8136607ea412
|
||||
github.com/apparentlymart/go-cidr v1.1.0
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/casbin/govaluate v1.3.0
|
||||
github.com/cilium/ebpf v0.17.3
|
||||
github.com/containerd/cgroups/v3 v3.0.5
|
||||
github.com/containers/image/v5 v5.34.1
|
||||
|
||||
2
go.sum
2
go.sum
@@ -707,6 +707,8 @@ github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuP
|
||||
github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk=
|
||||
github.com/c9s/goprocinfo v0.0.0-20170724085704-0010a05ce49f h1:tRk+aBit+q3oqnj/1mF5HHhP2yxJM2lSa0afOJxQ3nE=
|
||||
github.com/c9s/goprocinfo v0.0.0-20170724085704-0010a05ce49f/go.mod h1:uEyr4WpAH4hio6LFriaPkL938XnrvLpNPmQHBdrmbIE=
|
||||
github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc=
|
||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
|
||||
@@ -3,9 +3,9 @@ package analyzer
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/casbin/govaluate"
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
@@ -64,28 +64,33 @@ func compareHostHTTPConditionalToActual(conditional string, result *httpResult)
|
||||
return result.Error != nil, nil
|
||||
}
|
||||
|
||||
parts := strings.Split(conditional, " ")
|
||||
if len(parts) != 3 {
|
||||
return false, fmt.Errorf("Failed to parse conditional: got %d parts", len(parts))
|
||||
}
|
||||
conditional = strings.ReplaceAll(conditional, " = ", " == ")
|
||||
conditional = strings.ReplaceAll(conditional, " === ", " == ")
|
||||
|
||||
if parts[0] != "statusCode" {
|
||||
return false, errors.New(`Conditional must begin with keyword "statusCode"`)
|
||||
}
|
||||
|
||||
if parts[1] != "=" && parts[1] != "==" && parts[1] != "===" {
|
||||
return false, errors.New(`Only supported operator is "=="`)
|
||||
}
|
||||
|
||||
i, err := strconv.Atoi(parts[2])
|
||||
expression, err := govaluate.NewEvaluableExpression(conditional)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return false, errors.Wrap(err, "failed to create evaluable expression")
|
||||
}
|
||||
|
||||
if result.Response == nil {
|
||||
return false, err
|
||||
return false, nil
|
||||
}
|
||||
return result.Response.Status == i, nil
|
||||
|
||||
parameters := make(map[string]interface{}, 8)
|
||||
parameters["statusCode"] = result.Response.Status
|
||||
|
||||
comparisonResult, err := expression.Evaluate(parameters)
|
||||
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "failed to evaluate expression")
|
||||
}
|
||||
|
||||
boolResult, ok := comparisonResult.(bool)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("expression did not evaluate to a boolean value")
|
||||
}
|
||||
|
||||
return boolResult, nil
|
||||
}
|
||||
|
||||
func analyzeHTTPResult(analyzer *troubleshootv1beta2.HTTPAnalyze, fileName string, getCollectedFileContents getCollectedFileContents, title string) ([]*AnalyzeResult, error) {
|
||||
|
||||
@@ -113,6 +113,124 @@ func TestAnalyzeHostHTTP(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid compare operator",
|
||||
expectErr: true,
|
||||
httpResult: &httpResult{
|
||||
Response: &collect.HTTPResponse{
|
||||
Status: 200,
|
||||
},
|
||||
},
|
||||
hostAnalyzer: &troubleshootv1beta2.HTTPAnalyze{
|
||||
CollectorName: "collector",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "statusCode #$ 200",
|
||||
Message: "passed",
|
||||
},
|
||||
},
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "!= compare operator",
|
||||
httpResult: &httpResult{
|
||||
Response: &collect.HTTPResponse{
|
||||
Status: 201,
|
||||
},
|
||||
},
|
||||
hostAnalyzer: &troubleshootv1beta2.HTTPAnalyze{
|
||||
CollectorName: "collector",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "statusCode != 200",
|
||||
Message: "passed",
|
||||
},
|
||||
},
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "HTTP Request",
|
||||
IsPass: true,
|
||||
Message: "passed",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Looking for 2xx status codes",
|
||||
httpResult: &httpResult{
|
||||
Response: &collect.HTTPResponse{
|
||||
Status: 201,
|
||||
},
|
||||
},
|
||||
hostAnalyzer: &troubleshootv1beta2.HTTPAnalyze{
|
||||
CollectorName: "collector",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "statusCode >= 300 || statusCode < 200",
|
||||
Message: "expected 2xx status code",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "HTTP Request",
|
||||
IsPass: true,
|
||||
Message: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Looking for 2xx status codes does not match",
|
||||
httpResult: &httpResult{
|
||||
Response: &collect.HTTPResponse{
|
||||
Status: 300,
|
||||
},
|
||||
},
|
||||
hostAnalyzer: &troubleshootv1beta2.HTTPAnalyze{
|
||||
CollectorName: "collector",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "statusCode >= 300 || statusCode < 200",
|
||||
Message: "expected 2xx status code",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "default",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "HTTP Request",
|
||||
IsFail: true,
|
||||
Message: "expected 2xx status code",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
@@ -137,3 +255,77 @@ func TestAnalyzeHostHTTP(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnalyzeHostHTTPHTTPCodesAndCompareOperators(t *testing.T) {
|
||||
httpResult := &httpResult{
|
||||
Response: &collect.HTTPResponse{
|
||||
Status: 200,
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
}{
|
||||
{
|
||||
name: "statusCode == 200",
|
||||
},
|
||||
{
|
||||
name: "statusCode === 200",
|
||||
},
|
||||
{
|
||||
name: "statusCode = 200",
|
||||
},
|
||||
{
|
||||
name: "statusCode != 201",
|
||||
},
|
||||
{
|
||||
name: "statusCode >= 200",
|
||||
},
|
||||
{
|
||||
name: "statusCode > 199",
|
||||
},
|
||||
{
|
||||
name: "statusCode <= 200",
|
||||
},
|
||||
{
|
||||
name: "statusCode <= 201",
|
||||
},
|
||||
{
|
||||
name: "statusCode < 201",
|
||||
},
|
||||
{
|
||||
name: "statusCode < 201 && statusCode > 199",
|
||||
},
|
||||
{
|
||||
name: "statusCode < 201 || statusCode > 199 && statusCode == 200",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
hostAnalyzer := &troubleshootv1beta2.HTTPAnalyze{
|
||||
CollectorName: "registry",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: test.name},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
req := require.New(t)
|
||||
b, err := json.Marshal(httpResult)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
getCollectedFileContents := func(filename string) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostHTTP{hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
req.NoError(err)
|
||||
req.Len(result, 1)
|
||||
req.Equal(true, result[0].IsPass)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user