Skip to content

add LVMS toolset for storage diagnostics - #370

Open
mmakwana30 wants to merge 1 commit into
openshift:mainfrom
mmakwana30:add-lvms-toolset
Open

add LVMS toolset for storage diagnostics#370
mmakwana30 wants to merge 1 commit into
openshift:mainfrom
mmakwana30:add-lvms-toolset

Conversation

@mmakwana30

@mmakwana30 mmakwana30 commented Jul 1, 2026

Copy link
Copy Markdown

Jira: OCPEDGE-2726

Added a new toolset for diagnosing LVMS (Logical Volume Manager Storage) issues on OpenShift clusters.

Prompts (2):

  • lvms-troubleshoot: Step-by-step troubleshooting guide
  • lvms-capacity: Capacity analysis and planning

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added an optional LVMS (lvms) toolset with prompt-based troubleshooting and an LVMS capacity report.
    • Introduced an LVMS evaluation suite with scenarios for cluster status, capacity/thin-pool checks, disk/PVC diagnosis, and forced cleanup.
  • Documentation

    • Updated README and toolset configuration to list lvms and its available tools.
    • Added an LVMS tasks README explaining prerequisites and how to run the suite.
  • Tests

    • Added/extended toolset tests to cover the new lvms prompts and registrations.

@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a prompts-only LVMS toolset with Kubernetes-backed troubleshooting and capacity reports, registers it with MCP and README generation, documents the prompts, and adds 11 LVMS evaluation scenarios.

Changes

LVMS toolset

Layer / File(s) Summary
Prompt contracts and registration
pkg/toolsets/lvms/*, pkg/mcp/*, internal/tools/update-readme/main.go
Registers the prompts-only lvms toolset, exposes lvms-troubleshoot and lvms-capacity, and adds interface, MCP, and snapshot coverage.
Troubleshooting report
pkg/toolsets/lvms/lvms_troubleshoot.go
Collects LVMS operator, cluster, node, storage class, PVC, pod, log, and warning-event data into a Markdown result.
Capacity report
pkg/toolsets/lvms/lvms_capacity.go
Reports CSI capacity, TopoLVM PVC usage, and provisioned PV capacity with aggregate and per-node summaries.
Evaluation coverage
evals/claude-code/eval.yaml, evals/openai-agent/eval.yaml, evals/tasks/lvms/*
Adds LVMS evaluator configuration, task documentation, and scenarios for status, capacity, node inspection, troubleshooting, pending PVCs, and forced cleanup.
Documentation
README.md, docs/configuration.md
Documents LVMS as a validated project, available toolset, and prompt set.

Estimated code review effort: 4 (Complex) | ~60 minutes

Suggested reviewers: cali0707, manusa

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.99% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding an LVMS toolset for storage diagnostics.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@openshift-ci
openshift-ci Bot requested review from Cali0707 and matzew July 1, 2026 13:22
@openshift-ci

openshift-ci Bot commented Jul 1, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mmakwana30
Once this PR has been reviewed and has the lgtm label, please assign manusa for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (11)
pkg/toolsets/lvms/suite_test.go (1)

1-77: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Mock-based test scaffolding conflicts with "avoid mocks" guideline.

The suite constructs mockKubernetesClient/mockToolCallRequest in lieu of real implementations. As per coding guidelines, *_test.go files should "Use real implementations and integration testing where possible - avoid mocks," and use setup-envtest for test setup. This scaffolding is foundational for the whole LVMS test cohort, so reworking it to use envtest would be a broad, high-effort change; flagging for awareness rather than blocking, since it may already be an established pattern elsewhere in the codebase.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/suite_test.go` around lines 1 - 77, The LVMS test suite
currently relies on local mock types (`mockKubernetesClient` and
`mockToolCallRequest`) instead of real test setup, which conflicts with the
testing guideline. Update `LVMSTestSuite` to use `setup-envtest`-backed
Kubernetes client initialization and real request/argument handling where
possible, and remove or minimize the mock scaffolding in `SetupTest`,
`SetDynamicClient`, `SetClientset`, and `mockToolCallRequest` so the suite
exercises actual implementations.

Source: Coding guidelines

pkg/toolsets/lvms/manage.go (1)

115-122: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Raw params.GetArguments() access instead of the WrapParams helper used elsewhere in this function.

device_paths extraction bypasses p and reads params.GetArguments() directly, unlike name/namespace/etc. above. If WrapParams supports slice accessors, prefer using them for consistency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/manage.go` around lines 115 - 122, The device_paths parsing
in manageLVMS is bypassing the existing WrapParams-based access pattern and
reads params.GetArguments() directly. Update the device_paths extraction to use
the same p helper used for name, namespace, and the other fields in this
function, and use its slice/array accessor if available so the lookup is
consistent with the rest of manage.go.
pkg/toolsets/lvms/lvmcluster.go (1)

79-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Inconsistent parameter extraction vs. manage.go's WrapParams pattern.

Here namespace is pulled directly via params.GetArguments()["namespace"].(string), while manage.go uses api.WrapParams(params).OptionalString(...) for the same purpose. Consider using the same helper here for consistency and to avoid re-implementing the same type-assertion logic.

Also applies to: 154-156

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/lvmcluster.go` around lines 79 - 82, The namespace
extraction in lvms lvmcluster handling is re-implementing the same
type-assertion logic used elsewhere instead of following the WrapParams pattern.
Update the namespace reads in the affected logic to use
api.WrapParams(params).OptionalString(...) consistently, matching manage.go and
the surrounding parameter handling in lvmcluster.go so the same helper is used
at both call sites.
pkg/toolsets/lvms/lvmcluster_test.go (1)

10-175: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing coverage for the Forbidden error branch.

Both listLVMClusters and describeLVMCluster have explicit apierrors.IsForbidden handling (lvmcluster.go lines 98-100, 163-165), but no test exercises that branch. As per coding guidelines, tests should "Aim for high test coverage of the public API including edge case tests for error paths and boundary conditions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/lvmcluster_test.go` around lines 10 - 175, Add test
coverage for the Forbidden error path in both `TestListLVMClusters` and
`TestDescribeLVMCluster` by introducing a case that makes `listLVMClusters` and
`describeLVMCluster` return `apierrors.IsForbidden`-matching errors from the
dynamic client. Use the existing helpers and symbols (`listLVMClusters`,
`describeLVMCluster`, `LVMSTestSuite`, `SetDynamicClient`) to assert the result
contains the forbidden message and verifies the explicit forbidden handling
branch instead of the generic error path.

Source: Coding guidelines

pkg/toolsets/lvms/manage_test.go (1)

9-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing success-path test for lvmsCreateCluster and Forbidden-branch tests for create/delete.

Only the missing-name failure is tested for lvmsCreateCluster; there's no test validating a successful create (which would also exercise/validate the YAML templating in manage.go). Neither create nor delete exercises the apierrors.IsForbidden branch. As per coding guidelines, tests should "Aim for high test coverage of the public API including edge case tests for error paths and boundary conditions."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/manage_test.go` around lines 9 - 96, Add coverage for the
missing create success path in lvmsCreateCluster by adding a test that supplies
a valid name and namespace, uses the fake dynamic client, and asserts the
returned content indicates successful creation so the templating path in
manage.go is exercised. Also add Forbidden-branch tests for both
lvmsCreateCluster and lvmsDeleteCluster by configuring the client/errors to
trigger apierrors.IsForbidden and asserting the returned result/error message
matches the forbidden case. Use the existing lvmsCreateCluster and
lvmsDeleteCluster helpers and the LVMSTestSuite setup to keep the new tests
consistent with the current suite.

Source: Coding guidelines

pkg/toolsets/lvms/pods.go (1)

214-252: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate restart-count/pod-summary logic vs. troubleshoot.go.

The container-restart-count accumulation loop (Lines 233-242) is duplicated almost verbatim in fetchLVMSPods in troubleshoot.go (Lines 415-424). Consider extracting a shared helper, e.g. sumPodRestarts(pod unstructured.Unstructured) int64, to avoid drift between the two copies.

♻️ Proposed helper extraction
+func sumPodRestarts(pod unstructured.Unstructured) int64 {
+	var restarts int64
+	if containerStatuses, found, _ := unstructured.NestedSlice(pod.Object, "status", "containerStatuses"); found {
+		for _, cs := range containerStatuses {
+			if csMap, ok := cs.(map[string]interface{}); ok {
+				if rc, ok := csMap["restartCount"].(int64); ok {
+					restarts += rc
+				}
+			}
+		}
+	}
+	return restarts
+}

Then in lvmsListPods:

-		// Get restart count
-		restarts := int64(0)
-		if containerStatuses, found, _ := unstructured.NestedSlice(pod.Object, "status", "containerStatuses"); found {
-			for _, cs := range containerStatuses {
-				if csMap, ok := cs.(map[string]interface{}); ok {
-					if rc, ok := csMap["restartCount"].(int64); ok {
-						restarts += rc
-					}
-				}
-			}
-		}
-		podInfo["Restarts"] = restarts
+		podInfo["Restarts"] = sumPodRestarts(pod)

And reuse the same helper in troubleshoot.go's fetchLVMSPods.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/pods.go` around lines 214 - 252, The pod restart-count
logic in `lvmsListPods` is duplicated in `fetchLVMSPods` from `troubleshoot.go`,
so extract the shared container-status accumulation into a helper such as
`sumPodRestarts(pod unstructured.Unstructured) int64` and call it from both
places. Keep the existing pod-summary assembly in `lvmsListPods`, but delegate
the restart calculation to the helper so both code paths stay consistent and
don’t drift.
pkg/toolsets/lvms/volumegroups.go (1)

83-110: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Namespace default inconsistency vs. other LVMS tools.

Unlike pods.go tools (lvmsGetOperatorLogs, lvmsListPods, etc.), which default namespace to defaults.DefaultNamespace() when unspecified, listLVMVolumeGroups/getVolumeGroupNodeStatus default to listing across all namespaces. Since these CRDs are effectively always created in the LVMS namespace, this asymmetry adds needless cluster-wide list calls/RBAC surface for little practical benefit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/volumegroups.go` around lines 83 - 110, The namespace
handling in listLVMVolumeGroups is inconsistent with the other LVMS tools: when
namespace is omitted, it currently lists cluster-wide instead of defaulting to
defaults.DefaultNamespace(). Update listLVMVolumeGroups (and any matching helper
such as getVolumeGroupNodeStatus if it uses the same pattern) to use the default
LVMS namespace when params.GetArguments()["namespace"] is empty, and keep the
namespaced Resource(...).Namespace(namespace).List path as the normal case.
pkg/toolsets/lvms/troubleshoot.go (1)

344-367: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Marshal errors from yaml.Marshal are silently discarded.

Unlike volumegroups.go/pods.go/health.go, which check and surface yaml.Marshal errors, the helper functions here (fetchLVMClusterStatus Line 356, fetchPVCDetails Line 446) discard the error via data, _ := yaml.Marshal(...). Low risk given the inputs are simple maps, but inconsistent with the rest of the package's error-handling convention.

Also applies to: 432-455

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/troubleshoot.go` around lines 344 - 367, The helper in
fetchLVMClusterStatus is discarding yaml.Marshal errors, which is inconsistent
with the package’s error-handling pattern. Update fetchLVMClusterStatus (and the
similar fetchPVCDetails helper mentioned in the review) to check the marshal
return value instead of using the blank identifier, and surface or log the error
in the returned status text the same way other helpers like volumegroups.go,
pods.go, and health.go do. Use the existing fetchLVMClusterStatus and
fetchPVCDetails symbols to locate the affected paths.
pkg/toolsets/lvms/health.go (1)

262-264: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

round2 truncates rather than rounds — misleading name.

float64(int(v*100)) / 100 truncates towards zero; it does not round. The test at health_test.go Line 56-60 even documents this ("round up conceptually but truncate"). Displayed pool sizes will always be biased slightly low (e.g., 53.99953.99 instead of 54.0). Consider math.Round(v*100)/100 if actual rounding is intended, or rename to truncate2 for clarity.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/health.go` around lines 262 - 264, The helper round2 in
health.go is truncating values instead of rounding them, so either change its
implementation to use true rounding for the displayed pool sizes or rename it to
reflect truncation if that behavior is intended. Update the caller expectations
and the related health_test.go case so the behavior matches the chosen name and
logic, using round2 as the symbol to locate the change.
pkg/toolsets/lvms/troubleshoot_test.go (1)

25-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Unnecessary anonymous-struct copying adds boilerplate without benefit.

TestLvmsTroubleshootPromptMetadata, TestLvmsCapacityPromptMetadata, and TestTroubleshootPromptArgumentsMetadata each copy api.Prompt/api.PromptArgument fields into ad-hoc anonymous structs before asserting on them. This adds indirection for no benefit — assertions could run directly against p.Prompt.Title, p.Prompt.Arguments[i].Name, etc., inside the loop.

♻️ Simplified version (for TestLvmsTroubleshootPromptMetadata)
 func TestLvmsTroubleshootPromptMetadata(t *testing.T) {
 	prompts := initLVMSTroubleshoot()
-
-	var troubleshootPrompt *struct {
-		name        string
-		title       string
-		description string
-		arguments   int
-	}
-
-	for _, p := range prompts {
-		if p.Prompt.Name == "lvms-troubleshoot" {
-			troubleshootPrompt = &struct {
-				name        string
-				title       string
-				description string
-				arguments   int
-			}{
-				name:        p.Prompt.Name,
-				title:       p.Prompt.Title,
-				description: p.Prompt.Description,
-				arguments:   len(p.Prompt.Arguments),
-			}
-			break
-		}
-	}
-
-	require.NotNil(t, troubleshootPrompt, "lvms-troubleshoot prompt should be found")
-
-	assert.Equal(t, "lvms-troubleshoot", troubleshootPrompt.name)
-	assert.Equal(t, "LVMS Troubleshoot", troubleshootPrompt.title)
-	assert.Contains(t, troubleshootPrompt.description, "troubleshooting")
-	assert.Equal(t, 3, troubleshootPrompt.arguments, "should have 3 arguments: namespace, pvc, pvc_namespace")
+	var found bool
+	for _, p := range prompts {
+		if p.Prompt.Name != "lvms-troubleshoot" {
+			continue
+		}
+		found = true
+		assert.Equal(t, "LVMS Troubleshoot", p.Prompt.Title)
+		assert.Contains(t, p.Prompt.Description, "troubleshooting")
+		assert.Len(t, p.Prompt.Arguments, 3, "should have 3 arguments: namespace, pvc, pvc_namespace")
+	}
+	require.True(t, found, "lvms-troubleshoot prompt should be found")
 }

Also applies to: 103-159

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/troubleshoot_test.go` around lines 25 - 93, The prompt
metadata tests are over-copying fields into anonymous structs, adding
unnecessary boilerplate in TestLvmsTroubleshootPromptMetadata,
TestLvmsCapacityPromptMetadata, and TestTroubleshootPromptArgumentsMetadata.
Update the assertions to read directly from the found prompt’s api.Prompt fields
(for example, use p.Prompt.Name/Title/Description and
p.Prompt.Arguments[i].Name/Description inside the loop) and remove the temporary
anonymous-struct holders while keeping the same expectations and prompt lookup
logic.
pkg/toolsets/lvms/volumegroups_test.go (1)

10-65: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

No error-path coverage (CRD-not-found / forbidden) for either tool.

Both TestListLVMVolumeGroups and TestGetVolumeGroupNodeStatus define an expectedError field in the table-driven test struct, but no test case ever sets it — the error branches in listLVMVolumeGroups/getVolumeGroupNodeStatus (e.g., apierrors.IsNotFound, apierrors.IsForbidden in volumegroups.go Lines 98-106, 161-169) are never exercised.

As per coding guidelines, "Aim for high test coverage of the public API including edge case tests for error paths and boundary conditions."

Also applies to: 85-171

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/volumegroups_test.go` around lines 10 - 65, Add
table-driven error-path cases to TestListLVMVolumeGroups (and the matching
TestGetVolumeGroupNodeStatus) so the expectedError branch is actually exercised.
Use the existing listLVMVolumeGroups and getVolumeGroupNodeStatus flows with
fake dynamic client responses that trigger apierrors.IsNotFound and
apierrors.IsForbidden, then assert the returned error text matches
expectedError. Keep the current successful case, but extend the test table with
namespace/object setups that cover the CRD-not-found and forbidden paths in
volumegroups.go.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/toolsets/lvms/health.go`:
- Around line 222-223: Replace the `sb.WriteString(fmt.Sprintf(...))` calls in
the health report builder with `fmt.Fprintf` so the `strings.Builder` is written
to directly and the staticcheck QF1012 warning is removed. Update the same
pattern in the health status formatting logic around
`healthStatus(result.Healthy)` and the other matching call noted in the comment,
keeping the existing output unchanged while using `fmt.Fprintf(&sb, ...)`
instead of formatting into a temporary string first.
- Around line 121-151: The node scan in health.go is silently swallowing both
NodesDebugExec failures and JSON unmarshal errors inside the node loop, which
causes real execution/parse problems to look like a legitimate “no thin pools”
result. Update the health-check flow around the loop that calls NodesDebugExec
and parses lvsReport to track per-node failures (or at least the first
meaningful error), and return/report a distinct failure when all nodes fail for
exec or parsing rather than continuing to the generic empty-result path. Keep
the existing skip behavior only for expected “no LVM” cases, and surface the
actual error context for unexpected failures.

In `@pkg/toolsets/lvms/lvmcluster_test.go`:
- Around line 1-8: The tests are white-boxing private handlers instead of
exercising the public toolset API. Update the lvms tests to call the exported
surface exposed by Toolset.GetTools() and ServerTool.Handler, and remove direct
invocations of listLVMClusters and describeLVMCluster from the test flow. Keep
the assertions the same, but drive them through the public entry points so the
suite stays black-box and aligned with the testing guidelines.

In `@pkg/toolsets/lvms/manage.go`:
- Around line 114-151: The LVMCluster manifest assembly in manage.go is
vulnerable to YAML/field injection because `name`, `namespace`,
`deviceClassName`, `fstype`, and `devicePaths` are interpolated directly into
the template in the YAML-building block. Fix this by validating the identifiers
in the device selector/YAML construction path (the code around
`deviceSelectorYaml` and `yamlContent`) against Kubernetes-safe formats and safe
path patterns, and avoid manual string concatenation by constructing the
`LVMCluster` object as structured data and serializing it before
`ResourcesCreateOrUpdate`.

In `@pkg/toolsets/lvms/suite_test.go`:
- Around line 15-32: The mockKubernetesClient currently embeds a nil
api.KubernetesClient, so promoted calls like CoreV1() can still panic even
though Clientset() is set. Update mockKubernetesClient to forward the
api.KubernetesClient behavior to the underlying clientset used by
nodesdebug.NewNodeDebug, or replace the embedded field with a concrete fake that
fully implements api.KubernetesClient. Ensure the methods on
mockKubernetesClient and any setup in suite_test.go consistently use the fake
clientset for all delegated Kubernetes API calls.

In `@pkg/toolsets/lvms/troubleshoot.go`:
- Around line 77-102: The PVC lookup in lvmsTroubleshootHandler currently
becomes a silent no-op when only pvc or pvc_namespace is provided. Add input
validation or a user-facing hint before the fetchPVCDetails branch so incomplete
PVC arguments are surfaced instead of being ignored, and use the existing
lvmsTroubleshootHandler, pvcName, and pvcNamespace logic to detect and report
the mismatch.

---

Nitpick comments:
In `@pkg/toolsets/lvms/health.go`:
- Around line 262-264: The helper round2 in health.go is truncating values
instead of rounding them, so either change its implementation to use true
rounding for the displayed pool sizes or rename it to reflect truncation if that
behavior is intended. Update the caller expectations and the related
health_test.go case so the behavior matches the chosen name and logic, using
round2 as the symbol to locate the change.

In `@pkg/toolsets/lvms/lvmcluster_test.go`:
- Around line 10-175: Add test coverage for the Forbidden error path in both
`TestListLVMClusters` and `TestDescribeLVMCluster` by introducing a case that
makes `listLVMClusters` and `describeLVMCluster` return
`apierrors.IsForbidden`-matching errors from the dynamic client. Use the
existing helpers and symbols (`listLVMClusters`, `describeLVMCluster`,
`LVMSTestSuite`, `SetDynamicClient`) to assert the result contains the forbidden
message and verifies the explicit forbidden handling branch instead of the
generic error path.

In `@pkg/toolsets/lvms/lvmcluster.go`:
- Around line 79-82: The namespace extraction in lvms lvmcluster handling is
re-implementing the same type-assertion logic used elsewhere instead of
following the WrapParams pattern. Update the namespace reads in the affected
logic to use api.WrapParams(params).OptionalString(...) consistently, matching
manage.go and the surrounding parameter handling in lvmcluster.go so the same
helper is used at both call sites.

In `@pkg/toolsets/lvms/manage_test.go`:
- Around line 9-96: Add coverage for the missing create success path in
lvmsCreateCluster by adding a test that supplies a valid name and namespace,
uses the fake dynamic client, and asserts the returned content indicates
successful creation so the templating path in manage.go is exercised. Also add
Forbidden-branch tests for both lvmsCreateCluster and lvmsDeleteCluster by
configuring the client/errors to trigger apierrors.IsForbidden and asserting the
returned result/error message matches the forbidden case. Use the existing
lvmsCreateCluster and lvmsDeleteCluster helpers and the LVMSTestSuite setup to
keep the new tests consistent with the current suite.

In `@pkg/toolsets/lvms/manage.go`:
- Around line 115-122: The device_paths parsing in manageLVMS is bypassing the
existing WrapParams-based access pattern and reads params.GetArguments()
directly. Update the device_paths extraction to use the same p helper used for
name, namespace, and the other fields in this function, and use its slice/array
accessor if available so the lookup is consistent with the rest of manage.go.

In `@pkg/toolsets/lvms/pods.go`:
- Around line 214-252: The pod restart-count logic in `lvmsListPods` is
duplicated in `fetchLVMSPods` from `troubleshoot.go`, so extract the shared
container-status accumulation into a helper such as `sumPodRestarts(pod
unstructured.Unstructured) int64` and call it from both places. Keep the
existing pod-summary assembly in `lvmsListPods`, but delegate the restart
calculation to the helper so both code paths stay consistent and don’t drift.

In `@pkg/toolsets/lvms/suite_test.go`:
- Around line 1-77: The LVMS test suite currently relies on local mock types
(`mockKubernetesClient` and `mockToolCallRequest`) instead of real test setup,
which conflicts with the testing guideline. Update `LVMSTestSuite` to use
`setup-envtest`-backed Kubernetes client initialization and real
request/argument handling where possible, and remove or minimize the mock
scaffolding in `SetupTest`, `SetDynamicClient`, `SetClientset`, and
`mockToolCallRequest` so the suite exercises actual implementations.

In `@pkg/toolsets/lvms/troubleshoot_test.go`:
- Around line 25-93: The prompt metadata tests are over-copying fields into
anonymous structs, adding unnecessary boilerplate in
TestLvmsTroubleshootPromptMetadata, TestLvmsCapacityPromptMetadata, and
TestTroubleshootPromptArgumentsMetadata. Update the assertions to read directly
from the found prompt’s api.Prompt fields (for example, use
p.Prompt.Name/Title/Description and p.Prompt.Arguments[i].Name/Description
inside the loop) and remove the temporary anonymous-struct holders while keeping
the same expectations and prompt lookup logic.

In `@pkg/toolsets/lvms/troubleshoot.go`:
- Around line 344-367: The helper in fetchLVMClusterStatus is discarding
yaml.Marshal errors, which is inconsistent with the package’s error-handling
pattern. Update fetchLVMClusterStatus (and the similar fetchPVCDetails helper
mentioned in the review) to check the marshal return value instead of using the
blank identifier, and surface or log the error in the returned status text the
same way other helpers like volumegroups.go, pods.go, and health.go do. Use the
existing fetchLVMClusterStatus and fetchPVCDetails symbols to locate the
affected paths.

In `@pkg/toolsets/lvms/volumegroups_test.go`:
- Around line 10-65: Add table-driven error-path cases to
TestListLVMVolumeGroups (and the matching TestGetVolumeGroupNodeStatus) so the
expectedError branch is actually exercised. Use the existing listLVMVolumeGroups
and getVolumeGroupNodeStatus flows with fake dynamic client responses that
trigger apierrors.IsNotFound and apierrors.IsForbidden, then assert the returned
error text matches expectedError. Keep the current successful case, but extend
the test table with namespace/object setups that cover the CRD-not-found and
forbidden paths in volumegroups.go.

In `@pkg/toolsets/lvms/volumegroups.go`:
- Around line 83-110: The namespace handling in listLVMVolumeGroups is
inconsistent with the other LVMS tools: when namespace is omitted, it currently
lists cluster-wide instead of defaulting to defaults.DefaultNamespace(). Update
listLVMVolumeGroups (and any matching helper such as getVolumeGroupNodeStatus if
it uses the same pattern) to use the default LVMS namespace when
params.GetArguments()["namespace"] is empty, and keep the namespaced
Resource(...).Namespace(namespace).List path as the normal case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0dde6e77-2a7a-4640-bdc4-4827da339333

📥 Commits

Reviewing files that changed from the base of the PR and between 62a8031 and 8c3f548.

📒 Files selected for processing (19)
  • README.md
  • docs/configuration.md
  • internal/tools/update-readme/main.go
  • pkg/mcp/modules.go
  • pkg/toolsets/lvms/health.go
  • pkg/toolsets/lvms/health_test.go
  • pkg/toolsets/lvms/internal/defaults/defaults.go
  • pkg/toolsets/lvms/lvmcluster.go
  • pkg/toolsets/lvms/lvmcluster_test.go
  • pkg/toolsets/lvms/manage.go
  • pkg/toolsets/lvms/manage_test.go
  • pkg/toolsets/lvms/pods.go
  • pkg/toolsets/lvms/suite_test.go
  • pkg/toolsets/lvms/toolset.go
  • pkg/toolsets/lvms/toolset_test.go
  • pkg/toolsets/lvms/troubleshoot.go
  • pkg/toolsets/lvms/troubleshoot_test.go
  • pkg/toolsets/lvms/volumegroups.go
  • pkg/toolsets/lvms/volumegroups_test.go

Comment thread pkg/toolsets/lvms/health.go Outdated
Comment thread pkg/toolsets/lvms/health.go Outdated
Comment thread pkg/toolsets/lvms/lvmcluster_test.go Outdated
Comment thread pkg/toolsets/lvms/manage.go Outdated
Comment thread pkg/toolsets/lvms/suite_test.go Outdated
Comment thread pkg/toolsets/lvms/troubleshoot.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
evals/tasks/lvms/diagnose-disk-not-used/task.yaml (1)

48-55: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Generalize the node name in the prompt.

Hardcoding worker-1 as the node name could cause the evaluation task to spuriously fail if the test cluster does not have a node with that exact name, leading the agent to diagnose a missing node instead of evaluating LVMS filtering rules.

🔧 Proposed fix for a generalized node reference
   prompt:
     inline: |-
-      A user reports that /dev/sdb on node worker-1 is not being used by LVMS
-      even though they expected it to be available for storage.
+      A user reports that a specific disk (e.g., /dev/sdb on one of the worker nodes)
+      is not being used by LVMS even though they expected it to be available for storage.
 
       Investigate why this disk is not being used by LVMS and explain
       the reason to the user.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@evals/tasks/lvms/diagnose-disk-not-used/task.yaml` around lines 48 - 55,
Generalize the node reference in the inline prompt instead of hardcoding
“worker-1”; use a placeholder or variable consistent with the task’s existing
input conventions while preserving the /dev/sdb investigation and LVMS filtering
diagnosis.
pkg/mcp/toolsets_test.go (1)

121-124: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use Require().NoError for setup operations to prevent panics.

As per coding guidelines, use s.Require().NoError(err) for setup operations that must succeed.

Currently, if ListTools fails and returns a nil tools object, s.NoError inside this subtest will fail the subtest but will not abort the parent test. The subsequent subtest on line 125 will then panic with a nil pointer dereference when attempting to iterate over tools.Tools. Replace this subtest with required assertions in the parent scope.

🛠️ Proposed fix
-		s.Run("ListTools returns tools", func() {
-			s.NotNil(tools, "Expected tools from ListTools")
-			s.NoError(err, "Expected no error from ListTools")
-		})
+		s.Require().NoError(err, "Expected no error from ListTools")
+		s.Require().NotNil(tools, "Expected tools from ListTools")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/mcp/toolsets_test.go` around lines 121 - 124, Replace the non-fatal
assertions around the ListTools setup with s.Require().NoError(err) and a
required non-nil check in the parent test scope, before any subtests use tools.
Keep the existing ListTools success assertions and ensure failures abort before
the later tools.Tools iteration.

Source: Coding guidelines

🧹 Nitpick comments (2)
evals/tasks/lvms/check-thin-pool-utilization/task.yaml (1)

48-53: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align prompt with real user workflows.

The prompt dictates the specific properties (data_percent, metadata_percent) and the exact resource exclusion ("not just the Kubernetes CRD status") to check. Based on learnings from the provided context (.agents/skills/toolset-design/SKILL.md), eval task prompt fields should describe real user workflows and provide diagnostic data framing (not tool-shaped steps).

♻️ Proposed fix to align with user workflows
   prompt:
     inline: |-
-      What is the current thin pool utilization on each node? I need the actual
-      data_percent and metadata_percent values from the LVM thin pools, not just
-      the Kubernetes CRD status.
+      What is the true underlying thin pool utilization across the cluster nodes?
+      Please check the actual LVM thin pool metrics, as the Kubernetes CRD status
+      may not provide real-time or complete data.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@evals/tasks/lvms/check-thin-pool-utilization/task.yaml` around lines 48 - 53,
Revise the task.yaml prompt to describe the user’s goal of assessing current
thin-pool utilization across nodes and requesting actionable diagnostic context,
without prescribing exact field names such as data_percent or metadata_percent
or explicitly excluding Kubernetes CRD status. Keep the prompt focused on the
real workflow and expected utilization assessment rather than tool-specific
retrieval instructions.
README.md (1)

506-508: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Update the generator to omit empty <details> blocks.

The update-readme-tools generator produces an empty <details> block for toolsets like lvms because they do not export any MCP tools (GetTools returns nil).

Consider updating the internal/tools/update-readme/main.go script in a future PR to skip generating <details> blocks for toolsets that have no tools. As per coding guidelines, do not manually edit this generated file to fix the visual glitch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 506 - 508, Update the README generation logic in the
update-readme generator, specifically the toolset rendering flow in
internal/tools/update-readme/main.go, to skip emitting <details> blocks when
GetTools returns nil or an otherwise empty tool list. Do not manually modify the
generated README; regenerate it after fixing the generator so toolsets such as
lvms produce no empty block.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@evals/tasks/lvms/check-lvmcluster-status/task.yaml`:
- Around line 25-27: Update the LVMCluster existence check around the kubectl
get pipeline so it tests whether the command produces a non-empty resource name,
rather than relying on the pipeline exit status. Preserve the existing behavior
of creating the test cluster when no LVMCluster exists.

---

Outside diff comments:
In `@evals/tasks/lvms/diagnose-disk-not-used/task.yaml`:
- Around line 48-55: Generalize the node reference in the inline prompt instead
of hardcoding “worker-1”; use a placeholder or variable consistent with the
task’s existing input conventions while preserving the /dev/sdb investigation
and LVMS filtering diagnosis.

In `@pkg/mcp/toolsets_test.go`:
- Around line 121-124: Replace the non-fatal assertions around the ListTools
setup with s.Require().NoError(err) and a required non-nil check in the parent
test scope, before any subtests use tools. Keep the existing ListTools success
assertions and ensure failures abort before the later tools.Tools iteration.

---

Nitpick comments:
In `@evals/tasks/lvms/check-thin-pool-utilization/task.yaml`:
- Around line 48-53: Revise the task.yaml prompt to describe the user’s goal of
assessing current thin-pool utilization across nodes and requesting actionable
diagnostic context, without prescribing exact field names such as data_percent
or metadata_percent or explicitly excluding Kubernetes CRD status. Keep the
prompt focused on the real workflow and expected utilization assessment rather
than tool-specific retrieval instructions.

In `@README.md`:
- Around line 506-508: Update the README generation logic in the update-readme
generator, specifically the toolset rendering flow in
internal/tools/update-readme/main.go, to skip emitting <details> blocks when
GetTools returns nil or an otherwise empty tool list. Do not manually modify the
generated README; regenerate it after fixing the generator so toolsets such as
lvms produce no empty block.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 257a9ef6-bd83-4e04-8ee4-fba85684f182

📥 Commits

Reviewing files that changed from the base of the PR and between 7a2e9b4 and 5767bb7.

📒 Files selected for processing (20)
  • README.md
  • docs/configuration.md
  • evals/claude-code/eval.yaml
  • evals/openai-agent/eval.yaml
  • evals/tasks/lvms/README.md
  • evals/tasks/lvms/check-capacity/task.yaml
  • evals/tasks/lvms/check-lvmcluster-status/task.yaml
  • evals/tasks/lvms/check-thin-pool-utilization/task.yaml
  • evals/tasks/lvms/diagnose-disk-not-used/task.yaml
  • evals/tasks/lvms/diagnose-no-space-left/task.yaml
  • evals/tasks/lvms/forced-cleanup/task.yaml
  • evals/tasks/lvms/list-node-block-devices/task.yaml
  • evals/tasks/lvms/show-lvm-physical-volumes/task.yaml
  • evals/tasks/lvms/show-volume-groups/task.yaml
  • evals/tasks/lvms/troubleshoot-prompt/task.yaml
  • evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml
  • internal/tools/update-readme/main.go
  • pkg/mcp/modules.go
  • pkg/mcp/testdata/toolsets-lvms-tools.json
  • pkg/mcp/toolsets_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/mcp/modules.go
  • internal/tools/update-readme/main.go

Comment thread evals/tasks/lvms/check-lvmcluster-status/task.yaml
@mmakwana30
mmakwana30 force-pushed the add-lvms-toolset branch 3 times, most recently from 0e6b0ed to 6331136 Compare July 20, 2026 15:28

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
pkg/toolsets/lvms/lvms_capacity.go (1)

175-181: 🎯 Functional Correctness | 🔵 Trivial | ⚖️ Poor tradeoff

Ignored errors from unstructured.Nested* calls (same pattern as lvms_troubleshoot.go).

Lines 175-176, 180-181, 209-210, 230, 235-236, 275, 281 all discard the error return from unstructured.NestedString/NestedMap. As per coding guidelines, **/*.go: "Never ignore errors in production code; always check and handle returned errors."

Also applies to: 209-236, 275-281

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/lvms_capacity.go` around lines 175 - 181, The LVMS capacity
parsing flow discards errors from unstructured.NestedString and NestedMap calls.
Update the relevant extraction logic in the capacity-processing function to
capture and handle each returned error, including the storageClassName,
capacity, nodeTopology, and later Nested* calls around the referenced sections,
using the existing error-handling convention rather than silently continuing.

Source: Coding guidelines

pkg/toolsets/lvms/toolset_test.go (1)

1-81: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Missing unit coverage for pure helper functions.

This file only exercises the Toolset struct's plumbing; none of the pure helpers in lvms_capacity.go/lvms_troubleshoot.go (parseCapacity, formatCapacity, getPodReadyAndRestarts, filterLogLines, valueOrNA) have tests. These require no mocks/fixtures and, per this review, parseCapacity currently has a real unit-conflation bug (Line 332-341 of lvms_capacity.go) that a table-driven test would have caught. As per coding guidelines, **/*_test.go: "Aim for high public-API coverage and include edge cases such as nil or empty inputs, invalid values, type mismatches, and malformed input."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/toolset_test.go` around lines 1 - 81, Add table-driven unit
tests covering the pure helpers parseCapacity, formatCapacity,
getPodReadyAndRestarts, filterLogLines, and valueOrNA, including valid, empty or
nil, invalid, type-mismatch, and malformed inputs where applicable. Assert the
expected conversions and formatting, including distinct capacity units so the
parseCapacity unit-conflation bug is detected, while keeping the tests
independent of mocks and fixtures.

Source: Coding guidelines

pkg/toolsets/lvms/lvms_troubleshoot.go (1)

340-385: 🎯 Functional Correctness | 🔵 Trivial | ⚖️ Poor tradeoff

Pervasive ignored errors from unstructured.Nested* helpers across the LVMS package. Both files repeatedly discard the third (error) return value of unstructured.NestedString/NestedSlice/NestedMap, violating the guideline **/*.go: "Never ignore errors in production code; always check and handle returned errors." One shared root cause: the fetch helpers rely on found alone and never inspect err.

  • pkg/toolsets/lvms/lvms_troubleshoot.go#L340-L385: check/handle the discarded errors in fetchLVMClusterStatus (Lines 344, 348, 375) and mirror the fix in fetchVolumeGroupNodeStatus, fetchVGManagerPods, fetchOperatorHealth, fetchTopoLVMStorageClasses, fetchTopoLVMPVCs (Lines 412, 448-449, 606-607, 625, 649, 658, 694, 714, 719-720).
  • pkg/toolsets/lvms/lvms_capacity.go#L175-L281: check/handle the discarded errors in fetchCSICapacity (Lines 175-176, 180-181) and fetchPVCCapacitySummary (Lines 209-210, 230, 235-236).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/lvms_troubleshoot.go` around lines 340 - 385, Handle the
error returns from every unstructured.NestedString, NestedSlice, and NestedMap
call instead of relying only on found. In
pkg/toolsets/lvms/lvms_troubleshoot.go:340-385, update fetchLVMClusterStatus and
mirror the same handling in fetchVolumeGroupNodeStatus, fetchVGManagerPods,
fetchOperatorHealth, fetchTopoLVMStorageClasses, and fetchTopoLVMPVCs; in
pkg/toolsets/lvms/lvms_capacity.go:175-281, update fetchCSICapacity and
fetchPVCCapacitySummary. Propagate or report errors using each function’s
existing error-handling behavior before consuming the fetched values.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@evals/claude-code/eval.yaml`:
- Around line 87-97: Update the LVMS task assertions in
evals/claude-code/eval.yaml lines 87-97 and evals/openai-agent/eval.yaml lines
85-95 to explicitly require the lvms-troubleshoot prompt/tool for the
troubleshoot-prompt task path, while preserving the existing generic Kubernetes
call limits for other LVMS tasks.

In `@pkg/toolsets/lvms/lvms_capacity.go`:
- Around line 285-304: The node-affinity lookup currently uses NestedMap through
nodeSelectorTerms, which is a slice, so the capacity update is never reached. In
the node-affinity handling block, read the required node selector terms with the
appropriate nested-slice accessor, then iterate the returned terms and preserve
the existing topology.topolvm.io/node match and nodeCapacity update logic.
- Around line 322-344: Replace the manual parsing in parseCapacity with
Kubernetes resource.ParseQuantity, returning the quantity’s byte value when
parsing succeeds. Handle the returned error by preserving the existing
zero-value fallback, and remove the fmt/string-based unit parsing so decimal,
binary, and exponent formats are interpreted correctly.

---

Nitpick comments:
In `@pkg/toolsets/lvms/lvms_capacity.go`:
- Around line 175-181: The LVMS capacity parsing flow discards errors from
unstructured.NestedString and NestedMap calls. Update the relevant extraction
logic in the capacity-processing function to capture and handle each returned
error, including the storageClassName, capacity, nodeTopology, and later Nested*
calls around the referenced sections, using the existing error-handling
convention rather than silently continuing.

In `@pkg/toolsets/lvms/lvms_troubleshoot.go`:
- Around line 340-385: Handle the error returns from every
unstructured.NestedString, NestedSlice, and NestedMap call instead of relying
only on found. In pkg/toolsets/lvms/lvms_troubleshoot.go:340-385, update
fetchLVMClusterStatus and mirror the same handling in
fetchVolumeGroupNodeStatus, fetchVGManagerPods, fetchOperatorHealth,
fetchTopoLVMStorageClasses, and fetchTopoLVMPVCs; in
pkg/toolsets/lvms/lvms_capacity.go:175-281, update fetchCSICapacity and
fetchPVCCapacitySummary. Propagate or report errors using each function’s
existing error-handling behavior before consuming the fetched values.

In `@pkg/toolsets/lvms/toolset_test.go`:
- Around line 1-81: Add table-driven unit tests covering the pure helpers
parseCapacity, formatCapacity, getPodReadyAndRestarts, filterLogLines, and
valueOrNA, including valid, empty or nil, invalid, type-mismatch, and malformed
inputs where applicable. Assert the expected conversions and formatting,
including distinct capacity units so the parseCapacity unit-conflation bug is
detected, while keeping the tests independent of mocks and fixtures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0c30e54d-f71a-4a56-91c7-b8fa797be1ac

📥 Commits

Reviewing files that changed from the base of the PR and between 5767bb7 and 6331136.

📒 Files selected for processing (24)
  • README.md
  • docs/configuration.md
  • evals/claude-code/eval.yaml
  • evals/openai-agent/eval.yaml
  • evals/tasks/lvms/README.md
  • evals/tasks/lvms/check-capacity/task.yaml
  • evals/tasks/lvms/check-lvmcluster-status/task.yaml
  • evals/tasks/lvms/check-thin-pool-utilization/task.yaml
  • evals/tasks/lvms/diagnose-disk-not-used/task.yaml
  • evals/tasks/lvms/diagnose-no-space-left/task.yaml
  • evals/tasks/lvms/forced-cleanup/task.yaml
  • evals/tasks/lvms/list-node-block-devices/task.yaml
  • evals/tasks/lvms/show-lvm-physical-volumes/task.yaml
  • evals/tasks/lvms/show-volume-groups/task.yaml
  • evals/tasks/lvms/troubleshoot-prompt/task.yaml
  • evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml
  • internal/tools/update-readme/main.go
  • pkg/mcp/modules.go
  • pkg/mcp/testdata/toolsets-lvms-tools.json
  • pkg/mcp/toolsets_test.go
  • pkg/toolsets/lvms/lvms_capacity.go
  • pkg/toolsets/lvms/lvms_troubleshoot.go
  • pkg/toolsets/lvms/toolset.go
  • pkg/toolsets/lvms/toolset_test.go
🚧 Files skipped from review as they are similar to previous changes (16)
  • evals/tasks/lvms/diagnose-disk-not-used/task.yaml
  • evals/tasks/lvms/list-node-block-devices/task.yaml
  • pkg/mcp/modules.go
  • evals/tasks/lvms/show-lvm-physical-volumes/task.yaml
  • evals/tasks/lvms/diagnose-no-space-left/task.yaml
  • evals/tasks/lvms/show-volume-groups/task.yaml
  • pkg/mcp/toolsets_test.go
  • pkg/mcp/testdata/toolsets-lvms-tools.json
  • internal/tools/update-readme/main.go
  • evals/tasks/lvms/forced-cleanup/task.yaml
  • evals/tasks/lvms/check-capacity/task.yaml
  • evals/tasks/lvms/check-lvmcluster-status/task.yaml
  • evals/tasks/lvms/troubleshoot-prompt/task.yaml
  • evals/tasks/lvms/README.md
  • evals/tasks/lvms/check-thin-pool-utilization/task.yaml
  • evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml

Comment thread evals/claude-code/eval.yaml
Comment thread pkg/toolsets/lvms/lvms_capacity.go
Comment thread pkg/toolsets/lvms/lvms_capacity.go
@mmakwana30
mmakwana30 force-pushed the add-lvms-toolset branch 3 times, most recently from 8dd0ba7 to 66b17ee Compare July 20, 2026 16:08

@dhensel-rh dhensel-rh left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The heredoc YAML inside the indented bash setup scripts will break kubectl apply — the leading whitespace becomes part of the YAML content. For example in check-lvmcluster-status/task.yaml:

      cat <<EOF | kubectl apply -f -
      apiVersion: lvm.topolvm.io/v1alpha1
      kind: LVMCluster

That indentation produces invalid YAML. Needs to use <<-EOF with tabs, or dedent the YAML block to column 0.

Same issue in forced-cleanup/task.yaml with the LogicalVolume heredoc.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@evals/tasks/lvms/list-node-block-devices/task.yaml`:
- Around line 24-34: Update the verify step in the task configuration so it
evaluates the captured agent transcript instead of unconditionally exiting
successfully. Assert that the output demonstrates running lsblk and listing node
disk devices, partitions, and sizes via node access; alternatively, replace or
supplement the inline verifier with an llmJudge check covering those
requirements.
- Around line 1-2: Update the task’s verify step in the YAML so it evaluates the
produced answer against the expected block-device results and exits with a
nonzero status when they differ, rather than only printing expectations and
returning success. Preserve successful verification for correct answers and keep
the change scoped to the verify script.

In `@pkg/toolsets/lvms/lvms_capacity.go`:
- Around line 176-177: Handle the error return from every unstructured lookup in
pkg/toolsets/lvms/lvms_capacity.go: storageClassName and capacity at lines
176-177, nodeTopology at 181, provisioner at 210, storageClassName at 231, phase
and requestedStorage at 236-237, driver at 277, storage at 283, and
nodeSelectorTerms at 288. Replace discarded errors in the relevant
capacity-reporting flow with appropriate handling, such as logging through
klogutil.FromContext(ctx) or returning an error message, while preserving
successful value extraction.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9863f96f-dbcc-4628-af15-fd33d20f48c1

📥 Commits

Reviewing files that changed from the base of the PR and between 6331136 and 20fe635.

📒 Files selected for processing (24)
  • README.md
  • docs/configuration.md
  • evals/claude-code/eval.yaml
  • evals/openai-agent/eval.yaml
  • evals/tasks/lvms/README.md
  • evals/tasks/lvms/check-capacity/task.yaml
  • evals/tasks/lvms/check-lvmcluster-status/task.yaml
  • evals/tasks/lvms/check-thin-pool-utilization/task.yaml
  • evals/tasks/lvms/diagnose-disk-not-used/task.yaml
  • evals/tasks/lvms/diagnose-no-space-left/task.yaml
  • evals/tasks/lvms/forced-cleanup/task.yaml
  • evals/tasks/lvms/list-node-block-devices/task.yaml
  • evals/tasks/lvms/show-lvm-physical-volumes/task.yaml
  • evals/tasks/lvms/show-volume-groups/task.yaml
  • evals/tasks/lvms/troubleshoot-prompt/task.yaml
  • evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml
  • internal/tools/update-readme/main.go
  • pkg/mcp/modules.go
  • pkg/mcp/testdata/toolsets-lvms-tools.json
  • pkg/mcp/toolsets_test.go
  • pkg/toolsets/lvms/lvms_capacity.go
  • pkg/toolsets/lvms/lvms_troubleshoot.go
  • pkg/toolsets/lvms/toolset.go
  • pkg/toolsets/lvms/toolset_test.go
🚧 Files skipped from review as they are similar to previous changes (20)
  • pkg/mcp/modules.go
  • evals/tasks/lvms/show-lvm-physical-volumes/task.yaml
  • evals/openai-agent/eval.yaml
  • pkg/mcp/testdata/toolsets-lvms-tools.json
  • evals/claude-code/eval.yaml
  • evals/tasks/lvms/diagnose-no-space-left/task.yaml
  • evals/tasks/lvms/troubleshoot-prompt/task.yaml
  • evals/tasks/lvms/check-thin-pool-utilization/task.yaml
  • evals/tasks/lvms/diagnose-disk-not-used/task.yaml
  • evals/tasks/lvms/README.md
  • evals/tasks/lvms/show-volume-groups/task.yaml
  • evals/tasks/lvms/forced-cleanup/task.yaml
  • pkg/mcp/toolsets_test.go
  • evals/tasks/lvms/check-capacity/task.yaml
  • pkg/toolsets/lvms/toolset.go
  • evals/tasks/lvms/check-lvmcluster-status/task.yaml
  • pkg/toolsets/lvms/toolset_test.go
  • evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml
  • README.md
  • pkg/toolsets/lvms/lvms_troubleshoot.go

Comment on lines +1 to +2
kind: Task
metadata:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n '^apiVersion: mcpchecker/v1alpha2$|^kind: Task$' evals/tasks

Repository: openshift/openshift-mcp-server

Length of output: 20670


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== task file =="
cat -n evals/tasks/lvms/list-node-block-devices/task.yaml

echo
echo "== nearby similar task examples =="
for f in \
  evals/tasks/lvms/troubleshoot-stuck-pvc/task.yaml \
  evals/tasks/lvms/show-volume-groups/task.yaml \
  evals/tasks/lvms/check-capacity/task.yaml \
  evals/tasks/lvms/check-lvmcluster-status/task.yaml
do
  echo "--- $f"
  cat -n "$f" | sed -n '1,30p'
done

Repository: openshift/openshift-mcp-server

Length of output: 6307


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path
p = Path('evals/tasks/lvms/list-node-block-devices/task.yaml')
text = p.read_text()
print('apiVersion present:', 'apiVersion:' in text)
print('verify step mentions exit 0:', 'exit 0' in text)
print('verify step mentions result:', 'verify' in text.lower())
PY

Repository: openshift/openshift-mcp-server

Length of output: 262


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== references to mcpchecker/v1alpha2 =="
rg -n --hidden --glob '!**/.git/**' 'mcpchecker/v1alpha2|apiVersion:' README* docs evals . 2>/dev/null | sed -n '1,200p'

echo
echo "== task schema/docs files =="
fd -a -t f 'schema|task|mcpchecker|README' . | sed -n '1,200p'

Repository: openshift/openshift-mcp-server

Length of output: 30682


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== evals/tasks/README.md =="
cat -n evals/tasks/README.md | sed -n '1,220p'

echo
echo "== evals/core-eval-testing/README.md =="
cat -n evals/core-eval-testing/README.md | sed -n '1,220p'

echo
echo "== pkg/kubernetes/schema_validator.go =="
cat -n pkg/kubernetes/schema_validator.go | sed -n '1,260p'

Repository: openshift/openshift-mcp-server

Length of output: 11000


Make the verify step fail on incorrect answers (evals/tasks/lvms/list-node-block-devices/task.yaml:24-34). The script only prints expectations and exits 0, so incorrect results still pass.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@evals/tasks/lvms/list-node-block-devices/task.yaml` around lines 1 - 2,
Update the task’s verify step in the YAML so it evaluates the produced answer
against the expected block-device results and exits with a nonzero status when
they differ, rather than only printing expectations and returning success.
Preserve successful verification for correct answers and keep the change scoped
to the verify script.

Comment on lines +24 to +34
verify:
inline: |-
#!/usr/bin/env bash
echo "=== Verification ==="
echo "The agent should have:"
echo " 1. Run 'lsblk' command on the node"
echo " 2. Shown disk devices, partitions, sizes"
echo " 3. This CANNOT be done with Kubernetes API - requires node access"
echo ""
echo "If the agent only queried Kubernetes resources, it FAILED."
exit 0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

set -euo pipefail

printf '\n== task file ==\n'
cat -n evals/tasks/lvms/list-node-block-devices/task.yaml | sed -n '1,120p'

printf '\n== similar verify patterns ==\n'
rg -n "inline: \|-|exit 0|llmJudge|Verification" evals/tasks -g 'task.yaml' | sed -n '1,200p'

Repository: openshift/openshift-mcp-server

Length of output: 14021


Make the verifier check the agent output evals/tasks/lvms/list-node-block-devices/task.yaml:24-34 — this step always exits 0, so the task passes even when the agent does nothing. Replace it with an assertion on the captured transcript/output, or add an llmJudge step that checks the agent listed node block devices via node access.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@evals/tasks/lvms/list-node-block-devices/task.yaml` around lines 24 - 34,
Update the verify step in the task configuration so it evaluates the captured
agent transcript instead of unconditionally exiting successfully. Assert that
the output demonstrates running lsblk and listing node disk devices, partitions,
and sizes via node access; alternatively, replace or supplement the inline
verifier with an llmJudge check covering those requirements.

Comment on lines +176 to +177
storageClass, _, _ := unstructured.NestedString(cap.Object, "storageClassName")
capacity, _, _ := unstructured.NestedString(cap.Object, "capacity")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Handle errors from unstructured.Nested* functions.

As per coding guidelines, "Never ignore errors in production code; always check and handle returned errors." The unstructured.NestedString, NestedMap, and NestedSlice methods return a third error value when the field exists but is not of the expected type. Discarding this error with the blank identifier _ can silently hide type-mismatches and drop data from the report. Please check these errors and handle them appropriately (e.g., by logging with klogutil.FromContext(ctx) or returning an error message).

  • pkg/toolsets/lvms/lvms_capacity.go#L176-L177: handle the error for storageClassName and capacity.
  • pkg/toolsets/lvms/lvms_capacity.go#L181-L181: handle the error for nodeTopology.
  • pkg/toolsets/lvms/lvms_capacity.go#L210-L210: handle the error for provisioner.
  • pkg/toolsets/lvms/lvms_capacity.go#L231-L231: handle the error for storageClassName.
  • pkg/toolsets/lvms/lvms_capacity.go#L236-L237: handle the error for phase and requestedStorage.
  • pkg/toolsets/lvms/lvms_capacity.go#L277-L277: handle the error for driver.
  • pkg/toolsets/lvms/lvms_capacity.go#L283-L283: handle the error for storage.
  • pkg/toolsets/lvms/lvms_capacity.go#L288-L288: handle the error for nodeSelectorTerms.
📍 Affects 1 file
  • pkg/toolsets/lvms/lvms_capacity.go#L176-L177 (this comment)
  • pkg/toolsets/lvms/lvms_capacity.go#L181-L181
  • pkg/toolsets/lvms/lvms_capacity.go#L210-L210
  • pkg/toolsets/lvms/lvms_capacity.go#L231-L231
  • pkg/toolsets/lvms/lvms_capacity.go#L236-L237
  • pkg/toolsets/lvms/lvms_capacity.go#L277-L277
  • pkg/toolsets/lvms/lvms_capacity.go#L283-L283
  • pkg/toolsets/lvms/lvms_capacity.go#L288-L288
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/toolsets/lvms/lvms_capacity.go` around lines 176 - 177, Handle the error
return from every unstructured lookup in pkg/toolsets/lvms/lvms_capacity.go:
storageClassName and capacity at lines 176-177, nodeTopology at 181, provisioner
at 210, storageClassName at 231, phase and requestedStorage at 236-237, driver
at 277, storage at 283, and nodeSelectorTerms at 288. Replace discarded errors
in the relevant capacity-reporting flow with appropriate handling, such as
logging through klogutil.FromContext(ctx) or returning an error message, while
preserving successful value extraction.

Source: Coding guidelines

@openshift-ci

openshift-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown

@mmakwana30: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants