diff --git a/pkg/analyze/host_cpu.go b/pkg/analyze/host_cpu.go index 1dba635cf..97d9f04e2 100644 --- a/pkg/analyze/host_cpu.go +++ b/pkg/analyze/host_cpu.go @@ -63,7 +63,7 @@ func (a *AnalyzeHostCPU) Analyze( return []*AnalyzeResult{&result}, nil } - isMatch, err := compareHostCPUConditionalToActual(outcome.Fail.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags) + isMatch, err := compareHostCPUConditionalToActual(outcome.Fail.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags, cpuInfo.MachineArch) if err != nil { return nil, errors.Wrap(err, "failed to compare") } @@ -84,7 +84,7 @@ func (a *AnalyzeHostCPU) Analyze( return []*AnalyzeResult{&result}, nil } - isMatch, err := compareHostCPUConditionalToActual(outcome.Warn.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags) + isMatch, err := compareHostCPUConditionalToActual(outcome.Warn.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags, cpuInfo.MachineArch) if err != nil { return nil, errors.Wrap(err, "failed to compare") } @@ -105,7 +105,7 @@ func (a *AnalyzeHostCPU) Analyze( return []*AnalyzeResult{&result}, nil } - isMatch, err := compareHostCPUConditionalToActual(outcome.Pass.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags) + isMatch, err := compareHostCPUConditionalToActual(outcome.Pass.When, cpuInfo.LogicalCount, cpuInfo.PhysicalCount, cpuInfo.Flags, cpuInfo.MachineArch) if err != nil { return nil, errors.Wrap(err, "failed to compare") } @@ -164,14 +164,19 @@ func doCompareHostCPUFlags(expected string, flags []string) (res bool, err error return true, nil } -func compareHostCPUConditionalToActual(conditional string, logicalCount int, physicalCount int, flags []string) (res bool, err error) { +func compareHostCPUConditionalToActual(conditional string, logicalCount int, physicalCount int, flags []string, machineArch string) (res bool, err error) { compareLogical := false comparePhysical := false compareUnspecified := false + compareMachineArch := false comparator := "" desired := "" + /* When the conditional is in the format of "logical " + example: when: "count < 2" + */ + parts := strings.Split(conditional, " ") if len(parts) == 3 { comparator = parts[1] @@ -182,6 +187,8 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy comparePhysical = true } else if strings.ToLower(parts[0]) == "count" { compareUnspecified = true + } else if strings.ToLower(parts[0]) == "machinearch" { + compareMachineArch = true } } else if len(parts) == 2 { compareUnspecified = true @@ -199,7 +206,7 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy return doCompareHostCPUFlags(desired, flags) } - if !compareLogical && !comparePhysical && !compareUnspecified { + if !compareLogical && !comparePhysical && !compareUnspecified && !compareMachineArch { return false, errors.New("unable to parse conditional") } @@ -207,6 +214,8 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy return doCompareHostCPU(comparator, desired, logicalCount) } else if comparePhysical { return doCompareHostCPU(comparator, desired, physicalCount) + } else if compareMachineArch { + return doCompareMachineArch(comparator, desired, machineArch) } else { actual := logicalCount if physicalCount > logicalCount { @@ -217,6 +226,16 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy } } +func doCompareMachineArch(operator string, desired string, actual string) (bool, error) { + switch operator { + case "=", "==", "===": + return actual == desired, nil + case "!=", "!==": + return actual != desired, nil + } + return false, errors.New("unknown operator") +} + func doCompareHostCPU(operator string, desired string, actual int) (bool, error) { desiredInt, err := strconv.ParseInt(desired, 10, 64) if err != nil { @@ -234,6 +253,8 @@ func doCompareHostCPU(operator string, desired string, actual int) (bool, error) return actual >= int(desiredInt), nil case "=", "==", "===": return actual == int(desiredInt), nil + case "!=", "!==": + return actual != int(desiredInt), nil } return false, errors.New("unknown operator") diff --git a/pkg/analyze/host_cpu_test.go b/pkg/analyze/host_cpu_test.go index 316ee7a37..05ba22340 100644 --- a/pkg/analyze/host_cpu_test.go +++ b/pkg/analyze/host_cpu_test.go @@ -82,6 +82,7 @@ func Test_compareHostCPUConditionalToActual(t *testing.T) { logicalCount int physicalCount int flags []string + machineArch string expected bool }{ { @@ -164,12 +165,18 @@ func Test_compareHostCPUConditionalToActual(t *testing.T) { flags: []string{"a", "b", "c", "d", "e"}, expected: true, }, + { + name: "machine arch matches", + when: "machineArch == x86_64", + machineArch: "x86_64", + expected: true, + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { req := require.New(t) - actual, err := compareHostCPUConditionalToActual(test.when, test.logicalCount, test.physicalCount, test.flags) + actual, err := compareHostCPUConditionalToActual(test.when, test.logicalCount, test.physicalCount, test.flags, test.machineArch) req.NoError(err) assert.Equal(t, test.expected, actual) diff --git a/pkg/collect/host_cpu.go b/pkg/collect/host_cpu.go index d35cb00f6..4e7bb1ed8 100644 --- a/pkg/collect/host_cpu.go +++ b/pkg/collect/host_cpu.go @@ -7,12 +7,14 @@ import ( "github.com/pkg/errors" troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2" "github.com/shirou/gopsutil/v3/cpu" + "github.com/shirou/gopsutil/v3/host" ) type CPUInfo struct { LogicalCount int `json:"logicalCount"` PhysicalCount int `json:"physicalCount"` Flags []string `json:"flags"` + MachineArch string `json:"machineArch"` } const HostCPUPath = `host-collectors/system/cpu.json` @@ -45,6 +47,11 @@ func (c *CollectHostCPU) Collect(progressChan chan<- interface{}) (map[string][] } cpuInfo.PhysicalCount = physicalCount + cpuInfo.MachineArch, err = host.KernelArch() + if err != nil { + return nil, errors.Wrap(err, "failed to fetch cpu architecture") + } + // XXX even though the cpu.Info() returns a slice per CPU it is way // common to have the same flags for all CPUs. We consolidate them here // so the output is a list of all different flags present in all CPUs. diff --git a/pkg/collect/host_cpu_test.go b/pkg/collect/host_cpu_test.go index 3c5d6f9da..7e1b831b8 100644 --- a/pkg/collect/host_cpu_test.go +++ b/pkg/collect/host_cpu_test.go @@ -25,8 +25,9 @@ func TestCollectHostCPU_Collect(t *testing.T) { require.NoError(t, err) // Check if values exist. They will be different on different machines. - assert.Equal(t, 3, len(m)) + assert.Equal(t, 4, len(m)) assert.Contains(t, m, "logicalCount") assert.Contains(t, m, "physicalCount") assert.Contains(t, m, "flags") + assert.Contains(t, m, "machineArch") }