mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-04-15 07:16:34 +00:00
feat(analyze): optional additionalDeviceTypes for blockDevices; refactor match config and tests Allow preflights to count extra lsblk TYPE values (e.g. loop, lvm) by listing them in blockDevices.additionalDeviceTypes on BlockDevicesAnalyze. Types in this list are eligible whether or not includeUnmountedPartitions is set; disk and optional partitions behave as before. Refactor matching to use blockDevicesMatchConfig and document eligibility on that type. Add host_block_devices_match_test.go for type-rule tables and preflight-style integration cases; keep classic scenarios in host_block_devices_test.go with a shared analyzeHostBlockDevicesOutput helper. Regenerate CRDs and deepcopy for the new API field. Signed-off-by: Evans Mungai <evans@replicated.com>
278 lines
6.7 KiB
Go
278 lines
6.7 KiB
Go
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 TestAnalyzeBlockDevices(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
devices []collect.BlockDeviceInfo
|
|
hostAnalyzer *troubleshootv1beta2.BlockDevicesAnalyze
|
|
result []*AnalyzeResult
|
|
expectErr bool
|
|
}{
|
|
{
|
|
name: "sdb == 1, pass when there is an empty /dev/sdb",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "sdb",
|
|
KernelName: "sdb",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk1",
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: "sdb == 1",
|
|
Message: "Block device available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsPass: true,
|
|
Message: "Block device available",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "sdb == 1, fail when partitioned",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "sdb",
|
|
KernelName: "sdb",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk1",
|
|
},
|
|
{
|
|
Name: "sdb1",
|
|
KernelName: "sdb1",
|
|
ParentKernelName: "sdb",
|
|
Type: "part",
|
|
Major: 8,
|
|
Minor: 1,
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: "sdb == 1",
|
|
Message: "Block device available",
|
|
},
|
|
},
|
|
{
|
|
Fail: &troubleshootv1beta2.SingleOutcome{
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsFail: true,
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "sdb == 1, fail when it has a filesystem",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "sdb",
|
|
KernelName: "sdb",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk1",
|
|
FilesystemType: "ext4",
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: "sdb == 1",
|
|
Message: "Block device available",
|
|
},
|
|
},
|
|
{
|
|
Fail: &troubleshootv1beta2.SingleOutcome{
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsFail: true,
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: ".* > 0, fail when only loop devices are found",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "loop0",
|
|
KernelName: "loop0",
|
|
Type: "loop",
|
|
Major: 7,
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: ".* > 0",
|
|
Message: "Block device available",
|
|
},
|
|
},
|
|
{
|
|
Fail: &troubleshootv1beta2.SingleOutcome{
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsFail: true,
|
|
Message: "No block device available",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: ".* > 1, pass with unmounted partition",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "sdb",
|
|
KernelName: "sdb",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk1",
|
|
},
|
|
{
|
|
Name: "sdb1",
|
|
KernelName: "sdb1",
|
|
ParentKernelName: "sdb",
|
|
Type: "part",
|
|
Major: 8,
|
|
Minor: 1,
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
IncludeUnmountedPartitions: true,
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: ".* >= 1",
|
|
Message: "Block device or partition available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsPass: true,
|
|
Message: "Block device or partition available",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: ".* = 2, pass with two unmounted partitions/devices of at least 10gb in size",
|
|
devices: []collect.BlockDeviceInfo{
|
|
{
|
|
Name: "sdb",
|
|
KernelName: "sdb",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk1",
|
|
Size: 1024 * 1024 * 1024 * 128,
|
|
},
|
|
{
|
|
Name: "sdb1",
|
|
KernelName: "sdb1",
|
|
ParentKernelName: "sdb",
|
|
Type: "part",
|
|
Major: 8,
|
|
Minor: 1,
|
|
Size: 1024 * 1024 * 1024 * 128,
|
|
},
|
|
{
|
|
Name: "sdc",
|
|
KernelName: "sdc",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk2",
|
|
Size: 1024 * 1024 * 1024 * 16,
|
|
},
|
|
{
|
|
Name: "sdd",
|
|
KernelName: "sdd",
|
|
Type: "disk",
|
|
Major: 8,
|
|
Serial: "disk3",
|
|
Size: 1024 * 1024 * 1024 * 8,
|
|
},
|
|
},
|
|
hostAnalyzer: &troubleshootv1beta2.BlockDevicesAnalyze{
|
|
IncludeUnmountedPartitions: true,
|
|
MinimumAcceptableSize: 1024 * 1024 * 1024 * 10,
|
|
Outcomes: []*troubleshootv1beta2.Outcome{
|
|
{
|
|
Pass: &troubleshootv1beta2.SingleOutcome{
|
|
When: ".* = 2",
|
|
Message: "Two block devices or partitions of >10gb size available",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
result: []*AnalyzeResult{
|
|
{
|
|
Title: "Block Devices",
|
|
IsPass: true,
|
|
Message: "Two block devices or partitions of >10gb size available",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, test := range tests {
|
|
t.Run(test.name, func(t *testing.T) {
|
|
req := require.New(t)
|
|
result, err := analyzeHostBlockDevicesOutput(t, test.devices, test.hostAnalyzer)
|
|
if test.expectErr {
|
|
req.Error(err)
|
|
} else {
|
|
req.NoError(err)
|
|
}
|
|
assert.Equal(t, test.result, result)
|
|
})
|
|
}
|
|
}
|
|
|
|
// analyzeHostBlockDevicesOutput runs the host block device analyzer on marshaled fixture data (shared by match tests).
|
|
func analyzeHostBlockDevicesOutput(t *testing.T, devices []collect.BlockDeviceInfo, hostAnalyzer *troubleshootv1beta2.BlockDevicesAnalyze) ([]*AnalyzeResult, error) {
|
|
t.Helper()
|
|
b, err := json.Marshal(devices)
|
|
require.NoError(t, err)
|
|
getCollectedFileContents := func(string) ([]byte, error) { return b, nil }
|
|
return (&AnalyzeHostBlockDevices{hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
|
}
|