package analyzer import ( "encoding/json" "testing" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" "github.com/replicatedhq/troubleshoot/pkg/collect" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func Test_doCompareHostDiskUsage(t *testing.T) { tests := []struct { name string operator string desired string actual uint64 expected bool }{ { name: ">= 1Gi, when actual is 2Gi", operator: ">=", desired: "1Gi", actual: 2147483648, expected: true, }, { name: "<= 1Gi, when actual is 1GB", operator: "<=", desired: "1Gi", actual: 1000000000, expected: true, }, { name: "< 20Gi, when actual is 15Gi", operator: "<", desired: "20Gi", actual: 15 * 1024 * 1024 * 1024, expected: true, }, { name: "< 20Gi, when actual is 20Gi", operator: "<", desired: "20Gi", actual: 20 * 1024 * 1024 * 1024, expected: false, }, { name: "> 1073741824, when actual is 1024", operator: ">", desired: "1073741824", actual: 1024, expected: false, }, { name: "= 4096, when actual is 4096", operator: "=", desired: "4096", actual: 4096, expected: true, }, { name: "= 4096, when actual is 1024", operator: "=", desired: "4096", actual: 1024, expected: false, }, { name: "= 4096, when actual is 5000", operator: "=", desired: "4096", actual: 5000, expected: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { req := require.New(t) actual, err := doCompareHostDiskUsage(test.operator, test.desired, test.actual) req.NoError(err) assert.Equal(t, test.expected, actual) }) } } func Test_doCompareHostDiskUsagePercent(t *testing.T) { tests := []struct { name string operator string desired string actual float64 expected bool }{ { name: ">= .20, when actual is .30", operator: ">=", desired: ".20", actual: .30, expected: true, }, { name: ">= .20, when actual is .10", operator: ">=", desired: ".20", actual: .10, expected: false, }, { name: ">= .20, when actual is .20", operator: ">=", desired: ".20", actual: .20, expected: true, }, { name: "> .20, when actual is .30", operator: ">", desired: ".20", actual: .30, expected: true, }, { name: "> .20, when actual is .10", operator: ">", desired: ".20", actual: .10, expected: false, }, { name: "> .20, when actual is .20", operator: ">", desired: ".20", actual: .20, expected: false, }, { name: "<= .20, when actual is .30", operator: "<=", desired: ".20", actual: .30, expected: false, }, { name: "<= .20, when actual is .10", operator: "<=", desired: ".20", actual: .10, expected: true, }, { name: "<= .20, when actual is .20", operator: "<=", desired: ".20", actual: .20, expected: true, }, { name: "< .20, when actual is .30", operator: "<", desired: ".20", actual: .30, expected: false, }, { name: "< .20, when actual is .10", operator: "<", desired: ".20", actual: .10, expected: true, }, { name: "< .20, when actual is .20", operator: "<", desired: ".20", actual: .20, expected: false, }, { name: "= .20, when actual is .30", operator: "=", desired: ".20", actual: .30, expected: false, }, { name: "= .20, when actual is .10", operator: "=", desired: ".20", actual: .10, expected: false, }, { name: "= .20, when actual is .20", operator: "=", desired: ".20", actual: .20, expected: true, }, { name: "= 20%, when actual is .20", operator: "=", desired: "20%", actual: .20, expected: true, }, { name: "= 20%, when actual is 20", operator: "=", desired: "20%", actual: 20, expected: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { req := require.New(t) actual, err := doCompareHostDiskUsagePercent(test.operator, test.desired, test.actual) req.NoError(err) assert.Equal(t, test.expected, actual) }) } } func TestAnalyzeHostDiskUsage(t *testing.T) { tests := []struct { name string diskUsageInfo *collect.DiskUsageInfo hostAnalyzer *troubleshootv1beta2.DiskUsageAnalyze result *AnalyzeResult expectErr bool }{ { name: "Fail on insuffient total ephemeral disk space", diskUsageInfo: &collect.DiskUsageInfo{ TotalBytes: 10 * 1024 * 1024 * 1024, UsedBytes: 5 * 1024 * 1024 * 1024, }, hostAnalyzer: &troubleshootv1beta2.DiskUsageAnalyze{ CollectorName: "ephemeral", Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "used/total >= 80%", Message: "/var/lib/kubelet is more than 80% full", }, }, { Fail: &troubleshootv1beta2.SingleOutcome{ When: "total <= 10Gi", Message: "/var/lib/kubelet requires at least 10Gi", }, }, }, }, result: &AnalyzeResult{ Title: "Disk Usage ephemeral", IsFail: true, Message: "/var/lib/kubelet requires at least 10Gi", }, }, { name: "Fail on insuffient available ephemeral disk space percentage", diskUsageInfo: &collect.DiskUsageInfo{ TotalBytes: 10 * 1024 * 1024 * 1024, UsedBytes: 8 * 1024 * 1024 * 1024, }, hostAnalyzer: &troubleshootv1beta2.DiskUsageAnalyze{ CollectorName: "ephemeral", Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "total < 10Gi", Message: "/var/lib/kubelet requires at least 10Gi", }, }, { Fail: &troubleshootv1beta2.SingleOutcome{ When: "used/total >= 80%", Message: "/var/lib/kubelet is more than 80% full", }, }, }, }, result: &AnalyzeResult{ Title: "Disk Usage ephemeral", IsFail: true, Message: "/var/lib/kubelet is more than 80% full", }, }, { name: "Warn on high ephemeral disk space usage", diskUsageInfo: &collect.DiskUsageInfo{ TotalBytes: 1024 * 1024 * 1024 * 1024, UsedBytes: 100 * 1024 * 1024 * 1024, }, hostAnalyzer: &troubleshootv1beta2.DiskUsageAnalyze{ CollectorName: "ephemeral", Outcomes: []*troubleshootv1beta2.Outcome{ { Fail: &troubleshootv1beta2.SingleOutcome{ When: "total < 10Gi", Message: "/var/lib/kubelet requires at least 10Gi", }, }, { Fail: &troubleshootv1beta2.SingleOutcome{ When: "used/total >= 80%", Message: "/var/lib/kubelet is more than 80% full", }, }, { Warn: &troubleshootv1beta2.SingleOutcome{ When: "used >= 100Gi", Message: "/var/lib/kubelet has more than 100Gi used", }, }, }, }, result: &AnalyzeResult{ Title: "Disk Usage ephemeral", IsWarn: true, Message: "/var/lib/kubelet has more than 100Gi used", }, }, { name: "Pass on ephemeral disk space available", diskUsageInfo: &collect.DiskUsageInfo{ TotalBytes: 12 * 1024 * 1024 * 1024, UsedBytes: 1 * 1024 * 1024 * 1024, }, hostAnalyzer: &troubleshootv1beta2.DiskUsageAnalyze{ CollectorName: "ephemeral", Outcomes: []*troubleshootv1beta2.Outcome{ { Pass: &troubleshootv1beta2.SingleOutcome{ When: "available > 10Gi", Message: "/var/lib/kubelet has at least 10Gi available", }, }, }, }, result: &AnalyzeResult{ Title: "Disk Usage ephemeral", IsPass: true, Message: "/var/lib/kubelet has at least 10Gi available", }, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { req := require.New(t) b, err := json.Marshal(test.diskUsageInfo) if err != nil { t.Fatal(err) } getCollectedFileContents := func(filename string) ([]byte, error) { return b, nil } result, err := analyzeHostDiskUsage(test.hostAnalyzer, getCollectedFileContents) if test.expectErr { req.Error(err) } else { req.NoError(err) } assert.Equal(t, test.result, result) }) } }