Aggregate analyzers for node troubleshoot:

This commit is contained in:
Marc Campbell
2020-02-06 10:06:09 -08:00
parent 1e834430c2
commit eea2315c52
2 changed files with 88 additions and 45 deletions
+43 -20
View File
@@ -2,8 +2,10 @@ package analyzer
import (
"encoding/json"
"fmt"
"strconv"
"strings"
"regexp"
"github.com/pkg/errors"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
@@ -46,7 +48,7 @@ func analyzeNodeResources(analyzer *troubleshootv1beta1.NodeResources, getCollec
for _, outcome := range analyzer.Outcomes {
if outcome.Fail != nil {
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Fail.When, matchingNodeCount)
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Fail.When, matchingNodes, len(nodes))
if err != nil {
return nil, errors.Wrap(err, "failed to parse when")
}
@@ -59,7 +61,7 @@ func analyzeNodeResources(analyzer *troubleshootv1beta1.NodeResources, getCollec
return result, nil
}
} else if outcome.Warn != nil {
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Warn.When, matchingNodeCount)
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Warn.When, matchingNodes, len(nodes))
if err != nil {
return nil, errors.Wrap(err, "failed to parse when")
}
@@ -72,7 +74,7 @@ func analyzeNodeResources(analyzer *troubleshootv1beta1.NodeResources, getCollec
return result, nil
}
} else if outcome.Pass != nil {
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Pass.When, matchingNodeCount)
isWhenMatch, err := compareNodeResourceConditionalToActual(outcome.Pass.When, matchingNodes, len(nodes))
if err != nil {
return nil, errors.Wrap(err, "failed to parse when")
}
@@ -90,39 +92,60 @@ func analyzeNodeResources(analyzer *troubleshootv1beta1.NodeResources, getCollec
return result, nil
}
func compareNodeResourceConditionalToActual(conditional string, actual int) (bool, error) {
func compareNodeResourceConditionalToActual(conditional string, matchingNodes []corev1.Node, totalNodeCount int) (bool, error) {
if conditional == "" {
return true, nil
}
parts := strings.Split(strings.TrimSpace(conditional), " ")
if len(parts) != 2 {
if len(parts) == 2 {
parts = append([]string{"count"}, parts...)
}
if len(parts) != 3 {
return false, errors.New("unable to parse nodeResources conditional")
}
operator := parts[0]
desiredValue, err := strconv.Atoi(parts[1])
operator := parts[1]
var desiredValue interface{}
desiredValue = parts[2]
parsedDesiredValue, err := strconv.Atoi(parts[2])
if err != nil {
return false, errors.Wrap(err, "failed to parse nodeResource value")
desiredValue = parsedDesiredValue
}
switch operator {
case "=", "==", "===":
return desiredValue == actual, nil
case "<":
return actual < desiredValue, nil
case "<=":
return actual <= desiredValue, nil
case ">":
return actual > desiredValue, nil
case ">=":
return actual >= desiredValue, nil
}
var actualValue interface{}
actualValue = len(matchingNodes)
reg := regexp.MustCompile("(?P<function>.*)\((?P<property>.*)\)")
match := reg.FindStringSubmatch(parts[0])
fmt.Printf("reg = %#v\n", reg)
// result := make(map[string]string)
// switch operator {
// case "=", "==", "===":
// return desiredValue == actualValue, nil
// case "<":
// return actualValue < desiredValue, nil
// case "<=":
// return actualValue <= desiredValue, nil
// case ">":
// return actualValue > desiredValue, nil
// case ">=":
// return actualValue >= desiredValue, nil
// }
return false, errors.New("unexpected conditional in nodeResources")
}
func findMin(nodes []codev1.Node, property string) (string, error) {
return "", errors.New("not implemented")
}
func nodeMatchesFilters(node corev1.Node, filters *troubleshootv1beta1.NodeResourceFilters) (bool, error) {
if filters == nil {
return true, nil
+45 -25
View File
@@ -12,40 +12,60 @@ import (
func Test_compareNodeResourceConditionalToActual(t *testing.T) {
tests := []struct {
name string
conditional string
actual int
expected bool
name string
conditional string
matchingNodeCount int
totalNodeCount int
expected bool
}{
{
name: "=",
conditional: "= 5",
actual: 5,
expected: true,
name: "=",
conditional: "= 5",
matchingNodeCount: 5,
totalNodeCount: 1,
expected: true,
},
{
name: "<= (pass)",
conditional: "<= 5",
actual: 4,
expected: true,
name: "<= (pass)",
conditional: "<= 5",
matchingNodeCount: 4,
totalNodeCount: 1,
expected: true,
},
{
name: "<= (fail)",
conditional: "<= 5",
actual: 6,
expected: false,
name: "<= (fail)",
conditional: "<= 5",
matchingNodeCount: 6,
totalNodeCount: 1,
expected: false,
},
{
name: "> (pass)",
conditional: "> 5",
actual: 6,
expected: true,
name: "> (pass)",
conditional: "> 5",
matchingNodeCount: 6,
totalNodeCount: 1,
expected: true,
},
{
name: ">=(fail)",
conditional: ">= 5",
actual: 4,
expected: false,
name: ">= (fail)",
conditional: ">= 5",
matchingNodeCount: 4,
totalNodeCount: 1,
expected: false,
},
{
name: "min(memoryCapacity) <= 16Gi (pass)",
conditional: "min(memoryCapacity) <= 16Gi",
matchingNodeCount: 2,
totalNodeCount: 2,
expected: true,
},
{
name: "min(memoryCapacity) <= 16Gi",
conditional: "min(memoryCapacity) <= 16Gi",
matchingNodeCount: 1,
totalNodeCount: 2,
expected: false,
},
}
@@ -53,7 +73,7 @@ func Test_compareNodeResourceConditionalToActual(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
req := require.New(t)
actual, err := compareNodeResourceConditionalToActual(test.conditional, test.actual)
actual, err := compareNodeResourceConditionalToActual(test.conditional, test.matchingNodeCount, test.totalNodeCount)
req.NoError(err)
assert.Equal(t, test.expected, actual)