From 71f4c237fc641299640141b358e14c8d0acdad75 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Thu, 10 Sep 2026 11:58:33 +0300 Subject: [PATCH] fix(inspur): match main board FRU on word boundary A bare "board" substring test let compound module names like "FANBOARD0_FRU" qualify as the main system board, overwriting the real board info with fan-board serial/part numbers. Switch to a word-boundary regex. Co-Authored-By: Claude Sonnet 5 --- internal/parser/vendors/inspur/fru.go | 9 +++---- internal/parser/vendors/inspur/fru_test.go | 30 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/internal/parser/vendors/inspur/fru.go b/internal/parser/vendors/inspur/fru.go index acf634c..d7bbf34 100644 --- a/internal/parser/vendors/inspur/fru.go +++ b/internal/parser/vendors/inspur/fru.go @@ -12,6 +12,9 @@ var ( fruDeviceRegex = regexp.MustCompile(`^FRU Device Description\s*:\s*(.+)$`) fruFieldRegex = regexp.MustCompile(`^\s+(.+?)\s*:\s*(.*)$`) platformIdRegex = regexp.MustCompile(`(?i)PlatformId\s*=\s*(\S+)`) + // Word-boundary match so compound module names like "FANBOARD0_FRU" don't + // falsely qualify as the main system board via a bare "board" substring. + mainBoardDescRegex = regexp.MustCompile(`(?i)\b(builtin|fru device|chassis|board)\b`) ) // ParseFRU parses BMC FRU (Field Replaceable Unit) output @@ -120,11 +123,7 @@ func extractBoardInfo(fruList []models.FRUInfo, hw *models.HardwareConfig) { } // Prioritize entries that look like main board info - desc := strings.ToLower(fru.Description) - isMainBoard := strings.Contains(desc, "builtin") || - strings.Contains(desc, "fru device") || - strings.Contains(desc, "chassis") || - strings.Contains(desc, "board") + isMainBoard := mainBoardDescRegex.MatchString(fru.Description) if fru.SerialNumber != "" && hw.BoardInfo.SerialNumber == "" { hw.BoardInfo.SerialNumber = fru.SerialNumber diff --git a/internal/parser/vendors/inspur/fru_test.go b/internal/parser/vendors/inspur/fru_test.go index bb8529e..f213fea 100644 --- a/internal/parser/vendors/inspur/fru_test.go +++ b/internal/parser/vendors/inspur/fru_test.go @@ -32,6 +32,36 @@ func TestExtractBoardInfo_PreservesBuiltinSerial(t *testing.T) { } } +func TestExtractBoardInfo_FanBoardIsNotMainBoard(t *testing.T) { + hw := &models.HardwareConfig{} + fruList := []models.FRUInfo{ + { + Description: "SCM_FRU (ID 8)", + SerialNumber: "CAR517GN0377A01", + ProductName: "CA", + PartNumber: "YZCA-04672-101", + }, + { + Description: "FANBOARD0_FRU (ID 64)", + SerialNumber: "CFR517G80024A01", + ProductName: "CF", + PartNumber: "YZCF-04669-101", + }, + } + + extractBoardInfo(fruList, hw) + + if hw.BoardInfo.ProductName != "CA" { + t.Fatalf("expected product name CA, got %q", hw.BoardInfo.ProductName) + } + if hw.BoardInfo.PartNumber != "YZCA-04672-101" { + t.Fatalf("expected part number YZCA-04672-101, got %q", hw.BoardInfo.PartNumber) + } + if hw.BoardInfo.SerialNumber != "CAR517GN0377A01" { + t.Fatalf("expected serial CAR517GN0377A01, got %q", hw.BoardInfo.SerialNumber) + } +} + func TestExtractBoardInfo_DoesNotUsePSUVendorAsBoardManufacturer(t *testing.T) { hw := &models.HardwareConfig{} fruList := []models.FRUInfo{