From 2fcbdb55b2aabb6e0a75cfb3e1e00d8f6118ee00 Mon Sep 17 00:00:00 2001 From: Guillaume Carre Date: Thu, 25 Jun 2026 17:37:02 +0200 Subject: [PATCH 1/3] fix(storcli2): treat absent "System Overview" as no controllers storcli2 "show all" omits the "System Overview" section on a host with no controllers ("Number of Controllers": 0). The controller getter treated the missing key as a fatal error ("key not found: System Overview") and aborted the whole inventory, so any tool running on a node without a storcli2-managed controller failed instead of reporting an empty list. Handle utils.ErrKeyNotFound as an empty inventory, mirroring the logical-volume and physical-drive getters. Captured a real "Number of Controllers: 0" output as a regression fixture. Issue: ARTESCA-17644 --- .../controllergetter/storcli2.go | 8 ++++++++ .../controllergetter/storcli2_test.go | 10 +++++++++- .../testdata/storcli2/all_no_controllers.json | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json diff --git a/pkg/implementation/controllergetter/storcli2.go b/pkg/implementation/controllergetter/storcli2.go index 58c9ed5..9e39ae4 100644 --- a/pkg/implementation/controllergetter/storcli2.go +++ b/pkg/implementation/controllergetter/storcli2.go @@ -118,6 +118,14 @@ func (s *StorCLI2) Controllers() ([]*raidcontroller.RAIDController, error) { cmd.Controllers[i].ResponseData, "System Overview", ) if err != nil { + // storcli2 omits the "System Overview" section when the host has no + // controllers ("Number of Controllers": 0); that is an empty + // inventory, not an error, mirroring the logical-volume and + // physical-drive getters. + if errors.Is(err, utils.ErrKeyNotFound) { + continue + } + return nil, errors.Wrap(err, "failed to unmarshal system overview") } diff --git a/pkg/implementation/controllergetter/storcli2_test.go b/pkg/implementation/controllergetter/storcli2_test.go index 8b4f56e..3d5bdcf 100644 --- a/pkg/implementation/controllergetter/storcli2_test.go +++ b/pkg/implementation/controllergetter/storcli2_test.go @@ -52,6 +52,11 @@ func TestStorCLI2Controllers(t *testing.T) { showAll: []byte(`{"Controllers":[]}`), expectError: true, }, + { + name: "no managed controllers", + showAll: storcli2Fixture(t, "all_no_controllers.json"), + expectedLen: 0, + }, } for _, tt := range tests { @@ -81,7 +86,10 @@ func TestStorCLI2Controllers(t *testing.T) { require.NoError(t, err) require.Len(t, controllers, tt.expectedLen) - assert.Equal(t, 0, controllers[0].ID) + + if tt.expectedLen > 0 { + assert.Equal(t, 0, controllers[0].ID) + } }) } } diff --git a/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json b/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json new file mode 100644 index 0000000..342c5cf --- /dev/null +++ b/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json @@ -0,0 +1,19 @@ +{ +"Controllers":[ +{ + "Command Status" : { + "CLI Version" : "008.0005.0000.0010 Feb 22, 2023", + "Operating system" : "Linux4.18.0-553.124.1.el8_10.x86_64", + "Status Code" : 0, + "Status" : "Success", + "Description" : "None" + }, + "Response Data" : { + "Number of Controllers" : 0, + "Host Name" : "artesca-node", + "Operating System " : "Linux4.18.0-553.124.1.el8_10.x86_64", + "SL8 Library Version" : "08.0507.0000" + } +} +] +} From f8ca1ef0ed2af198a5ebd06cde6b24bccda65e06 Mon Sep 17 00:00:00 2001 From: Guillaume Carre Date: Thu, 25 Jun 2026 18:01:08 +0200 Subject: [PATCH 2/3] refactor(storcli2): extract controllersFromOverview to cut complexity Handling the absent "System Overview" section pushed Controllers() over the gocognit threshold (13 > 10). Extract the per-envelope overview resolution into a helper, dropping both functions well under the limit. No behavior change. Issue: ARTESCA-17644 --- .../controllergetter/storcli2.go | 55 ++++++++++++------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/pkg/implementation/controllergetter/storcli2.go b/pkg/implementation/controllergetter/storcli2.go index 9e39ae4..84fcc48 100644 --- a/pkg/implementation/controllergetter/storcli2.go +++ b/pkg/implementation/controllergetter/storcli2.go @@ -114,31 +114,48 @@ func (s *StorCLI2) Controllers() ([]*raidcontroller.RAIDController, error) { controllers := make([]*raidcontroller.RAIDController, 0) for i := range cmd.Controllers { - overview, err := utils.UnmarshalToSlice[storcli2SystemOverview]( - cmd.Controllers[i].ResponseData, "System Overview", - ) + found, err := s.controllersFromOverview(cmd.Controllers[i]) if err != nil { - // storcli2 omits the "System Overview" section when the host has no - // controllers ("Number of Controllers": 0); that is an empty - // inventory, not an error, mirroring the logical-volume and - // physical-drive getters. - if errors.Is(err, utils.ErrKeyNotFound) { - continue - } - - return nil, errors.Wrap(err, "failed to unmarshal system overview") + return nil, err } - for j := range overview { - metadata := &raidcontroller.Metadata{ID: overview[j].Ctrl} + controllers = append(controllers, found...) + } - controller, err := s.Controller(metadata) - if err != nil { - return nil, errors.Wrapf(err, "failed to get controller %d", metadata.ID) - } + return controllers, nil +} - controllers = append(controllers, controller) +// controllersFromOverview resolves every controller listed in one "show all" +// envelope's "System Overview" section. storcli2 omits that section when the +// host has no controllers ("Number of Controllers": 0); that is an empty +// inventory, not an error, mirroring the logical-volume and physical-drive +// getters. +func (s *StorCLI2) controllersFromOverview(controller storcli2.Controller) ( + []*raidcontroller.RAIDController, + error, +) { + overview, err := utils.UnmarshalToSlice[storcli2SystemOverview]( + controller.ResponseData, "System Overview", + ) + if err != nil { + if errors.Is(err, utils.ErrKeyNotFound) { + return nil, nil } + + return nil, errors.Wrap(err, "failed to unmarshal system overview") + } + + controllers := make([]*raidcontroller.RAIDController, 0, len(overview)) + + for j := range overview { + metadata := &raidcontroller.Metadata{ID: overview[j].Ctrl} + + found, err := s.Controller(metadata) + if err != nil { + return nil, errors.Wrapf(err, "failed to get controller %d", metadata.ID) + } + + controllers = append(controllers, found) } return controllers, nil From 1443286ca259bb6db9c23011fb2028683661a47d Mon Sep 17 00:00:00 2001 From: Guillaume CARRE <122804551+g-carre@users.noreply.github.com> Date: Thu, 25 Jun 2026 18:02:55 +0200 Subject: [PATCH 3/3] Update pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json --- .../controllergetter/testdata/storcli2/all_no_controllers.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json b/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json index 342c5cf..77793af 100644 --- a/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json +++ b/pkg/implementation/controllergetter/testdata/storcli2/all_no_controllers.json @@ -10,7 +10,7 @@ }, "Response Data" : { "Number of Controllers" : 0, - "Host Name" : "artesca-node", + "Host Name" : "application-node", "Operating System " : "Linux4.18.0-553.124.1.el8_10.x86_64", "SL8 Library Version" : "08.0507.0000" }