Skip to content

SPLAT-2829: Add vm-monitor for orphaned CI VM detection and cleanup - #3

Merged
nischawl merged 6 commits into
mainfrom
SPLAT-2829
Aug 5, 2026
Merged

SPLAT-2829: Add vm-monitor for orphaned CI VM detection and cleanup#3
nischawl merged 6 commits into
mainfrom
SPLAT-2829

Conversation

@nischawl

@nischawl nischawl commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features
    • Added VM monitoring to identify orphaned virtual machines using configurable age and naming criteria.
    • Added table and indented JSON reporting for VM details and cleanup results.
    • Added optional orphan cleanup with dry-run support and deletion status reporting.
    • Added Nutanix Prism Central configuration, credential loading, validation, and defaults.
    • Added graceful cancellation and distinct exit codes for configuration, runtime, orphan, and cleanup outcomes.
  • Build
    • Updated the build process to produce both monitoring binaries.

@openshift-ci-robot

openshift-ci-robot commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

@nischawl: This pull request references SPLAT-2829 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the spike to target the "5.0.0" version, but no target version was set.

Details

In response to this:

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 openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci
openshift-ci Bot requested review from bshaw7 and jcpowermac August 3, 2026 16:18
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 88d9ad02-a1a0-4db0-948a-d2c3e46c511e

📥 Commits

Reviewing files that changed from the base of the PR and between 30b6ae6 and d00b277.

📒 Files selected for processing (1)
  • Makefile
🚧 Files skipped from review as they are similar to previous changes (1)
  • Makefile

📝 Walkthrough

Walkthrough

Adds Nutanix VM monitoring with YAML configuration, Prism Central access, TTL-based orphan detection, optional cleanup, table or JSON output, signal handling, exit codes, tests, and build support.

Changes

VM monitoring

Layer / File(s) Summary
Nutanix configuration contract
internal/config/nutanix_config.go, internal/config/nutanix_config_test.go, config/nutanix.yaml
Defines Nutanix connection, VM filter, and orphan threshold settings. Applies defaults and validates required values.
Prism Central client
go.mod, internal/nutanix/client.go
Adds the Prism client dependency and wraps authenticated VM listing and deletion operations.
Orphan detection and cleanup
internal/vmmonitor/types.go, internal/vmmonitor/monitor.go, internal/vmmonitor/monitor_test.go
Detects VMs that exceed the configured TTL, removes duplicate IDs, and records cleanup results for dry-run or deletion mode.
CLI execution and build wiring
cmd/vm-monitor/main.go, Makefile, .github/workflows/build.yaml
Adds credential loading, signal-aware execution, table or JSON output, cleanup flags, exit codes, builds both monitor binaries, and updates the lint workflow.

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

Sequence Diagram(s)

sequenceDiagram
  participant VMMonitorCLI
  participant NutanixConfig
  participant VMMonitor
  participant PrismCentral
  VMMonitorCLI->>NutanixConfig: LoadNutanix
  VMMonitorCLI->>VMMonitor: Run
  VMMonitor->>PrismCentral: ListCIVMs
  PrismCentral-->>VMMonitor: VM metadata
  VMMonitor-->>VMMonitorCLI: VMReport
  VMMonitorCLI->>VMMonitor: Cleanup
  VMMonitor->>PrismCentral: DeleteVM
  PrismCentral-->>VMMonitor: Delete result
  VMMonitor-->>VMMonitorCLI: CleanupReport
Loading

Possibly related PRs

Suggested reviewers: jcpowermac, bshaw7

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 summarizes the addition of vm-monitor for detecting and cleaning up orphaned CI VMs.
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
  • Commit unit tests in branch SPLAT-2829

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.

@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: 4

🧹 Nitpick comments (3)
cmd/vm-monitor/main.go (2)

25-25: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

For consideration: format accepts any string and silently falls back to table output for anything other than "json" (Line 76-81), so a typo like --format=jso produces table output with no warning. Validating the flag value and failing fast would make misconfiguration visible.

🤖 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 `@cmd/vm-monitor/main.go` at line 25, Validate the format flag in the main
command flow after parsing, allowing only "table" and "json"; for any other
value, report the invalid option and terminate with a non-zero status instead of
silently using table output. Keep the existing output handling unchanged for
valid values.

160-167: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

outputJSON exits the process directly, bypassing cleanup in main.

On encode failure, outputJSON calls os.Exit(1) (Line 165) instead of returning an error to run. This skips klog.Flush() and the deferred stop() call for the signal context that main/run otherwise perform, so buffered log output can be lost on this failure path.

Return an error from outputJSON and let run propagate the failing exit code through the normal path.

🤖 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 `@cmd/vm-monitor/main.go` around lines 160 - 167, Update outputJSON to return
an error from json.Encoder.Encode failures instead of logging and calling
os.Exit; adjust its callers, including run, to propagate the error through the
normal return path so main performs deferred stop and klog.Flush cleanup.
internal/vmmonitor/monitor.go (1)

79-97: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Stop the cleanup loop early on context cancellation.

Cleanup keeps calling m.client.DeleteVM for every remaining orphan even after ctx is canceled (for example, by SIGTERM through signal.NotifyContext in cmd/vm-monitor/main.go). Each subsequent call fails immediately, and its error gets recorded in report.Results as DeleteStatusFailed, indistinguishable from a genuine deletion failure.

Check ctx.Err() at the top of the loop and stop attempting further deletions once the context is canceled, so the report distinguishes "not attempted due to shutdown" from "attempted and failed."

♻️ Proposed early-exit guard
 	report.Attempted = len(orphans)
 	for i := range orphans {
+		if ctx.Err() != nil {
+			klog.Warningf("Cleanup canceled, %d VM(s) not attempted", len(orphans)-i)
+			break
+		}
 		vm := &orphans[i]
🤖 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 `@internal/vmmonitor/monitor.go` around lines 79 - 97, Update the
orphan-deletion loop in Cleanup to check ctx.Err() before each iteration and
break when the context is canceled. Leave already processed results unchanged
and avoid calling m.client.DeleteVM or recording failed results for remaining
orphans after cancellation.
🤖 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 `@cmd/vm-monitor/main.go`:
- Around line 83-99: Update the exit-code flow in the cleanup handling around
mon.Cleanup so a cleanup that removes all orphaned VMs with zero failures does
not fall through to the generic orphan-detected return. Track the successful
cleanup outcome and return the intended distinct or zero status, while
preserving the existing failure return and behavior when cleanup is not
performed.
- Around line 76-93: Move the JSON emission in the main report flow so
outputJSON(report) runs after the cleanup block assigns report.CleanupReport.
Preserve table output behavior and cleanup failure handling, ensuring JSON runs
with --cleanup, including dry-run, contains the completed cleanup_report.

In `@config/nutanix.yaml`:
- Around line 1-4: Update the default prism_central configuration to document
that insecure mode is only for the dev/staging endpoint with a self-signed
certificate, and explicitly state that production deployments must override
insecure to false.

In `@internal/config/nutanix_config.go`:
- Around line 22-25: Wire VMFilters.CategoryPattern into the VM selection path
so configured category patterns actually narrow results, updating Monitor.Run or
Client.ListCIVMs and preserving NamePrefixes filtering. Alternatively, remove
CategoryPattern from VMFilters, applyDefaults, and the sample configuration
until filtering is implemented.

---

Nitpick comments:
In `@cmd/vm-monitor/main.go`:
- Line 25: Validate the format flag in the main command flow after parsing,
allowing only "table" and "json"; for any other value, report the invalid option
and terminate with a non-zero status instead of silently using table output.
Keep the existing output handling unchanged for valid values.
- Around line 160-167: Update outputJSON to return an error from
json.Encoder.Encode failures instead of logging and calling os.Exit; adjust its
callers, including run, to propagate the error through the normal return path so
main performs deferred stop and klog.Flush cleanup.

In `@internal/vmmonitor/monitor.go`:
- Around line 79-97: Update the orphan-deletion loop in Cleanup to check
ctx.Err() before each iteration and break when the context is canceled. Leave
already processed results unchanged and avoid calling m.client.DeleteVM or
recording failed results for remaining orphans after cancellation.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8c058404-20c2-4e48-9c4c-13e6255224e8

📥 Commits

Reviewing files that changed from the base of the PR and between 6ebcd13 and 9751234.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (10)
  • Makefile
  • cmd/vm-monitor/main.go
  • config/nutanix.yaml
  • go.mod
  • internal/config/nutanix_config.go
  • internal/config/nutanix_config_test.go
  • internal/nutanix/client.go
  • internal/vmmonitor/monitor.go
  • internal/vmmonitor/monitor_test.go
  • internal/vmmonitor/types.go

Comment thread cmd/vm-monitor/main.go
Comment thread cmd/vm-monitor/main.go Outdated
Comment thread config/nutanix.yaml
Comment on lines +1 to +4
prism_central:
endpoint: "prismcentral.sts2-cluster.internal.nutanix-dev.devcluster.openshift.com"
port: "9440"
insecure: true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Default config disables TLS certificate verification.

insecure: true is the value shipped in the default config path (config/nutanix.yaml is the default --config flag value in cmd/vm-monitor/main.go). This turns off certificate validation for Prism Central connections unless an operator overrides it.

If this endpoint is a dev/staging cluster with a self-signed certificate, add a comment stating that and confirm production deployments override insecure to false.

🤖 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 `@config/nutanix.yaml` around lines 1 - 4, Update the default prism_central
configuration to document that insecure mode is only for the dev/staging
endpoint with a self-signed certificate, and explicitly state that production
deployments must override insecure to false.

@nischawl nischawl Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This is the dev Prism Central endpoint which uses a self-signed certificate. Production deployments will override insecure: false with a proper CA bundle. Added a comment to clarify.

Comment thread internal/config/nutanix_config.go

@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.

🧹 Nitpick comments (1)
.github/workflows/build.yaml (1)

46-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the exact golangci-lint patch version.

Line 48 changes the selector from v2.12.2 to v2.12. The shorter selector can resolve a different patch release later and change CI results without a workflow change. The action supports both minor and patch selectors, so restore v2.12.2 unless floating patch updates are intentional. (github.com)

🤖 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 @.github/workflows/build.yaml around lines 46 - 48, Update the version
selector in the golangci-lint action configuration to the exact patch version
v2.12.2 instead of the floating minor selector v2.12, while leaving the action
and surrounding workflow unchanged.
🤖 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.

Nitpick comments:
In @.github/workflows/build.yaml:
- Around line 46-48: Update the version selector in the golangci-lint action
configuration to the exact patch version v2.12.2 instead of the floating minor
selector v2.12, while leaving the action and surrounding workflow unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a42e8d4b-4824-4957-af6c-5be8ea5f42c4

📥 Commits

Reviewing files that changed from the base of the PR and between 9751234 and cd45332.

📒 Files selected for processing (5)
  • .github/workflows/build.yaml
  • cmd/vm-monitor/main.go
  • config/nutanix.yaml
  • internal/config/nutanix_config.go
  • internal/config/nutanix_config_test.go
💤 Files with no reviewable changes (2)
  • internal/config/nutanix_config_test.go
  • config/nutanix.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/vm-monitor/main.go

@nischawl

nischawl commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

/retest

1 similar comment
@nischawl

nischawl commented Aug 4, 2026

Copy link
Copy Markdown
Collaborator Author

/retest

@openshift-splat-team openshift-splat-team deleted a comment from openshift-ci Bot Aug 5, 2026
@nischawl

nischawl commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

/override ci/prow/lint

@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown

@nischawl: Overrode contexts on behalf of nischawl: ci/prow/lint

Details

In response to this:

/override ci/prow/lint

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.

@nischawl

nischawl commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator Author

/override ci/prow/unit

@openshift-ci

openshift-ci Bot commented Aug 5, 2026

Copy link
Copy Markdown

@nischawl: Overrode contexts on behalf of nischawl: ci/prow/unit

Details

In response to this:

/override ci/prow/unit

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.

@nischawl
nischawl merged commit f751ace into main Aug 5, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants