mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Aggregate analyzers for node troubleshoot:
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user