Skip to content

Issues/handle errors#7

Merged
ditahkk merged 5 commits into
mainfrom
issues/handle-errors
Jun 8, 2026
Merged

Issues/handle errors#7
ditahkk merged 5 commits into
mainfrom
issues/handle-errors

Conversation

@ditahkk

@ditahkk ditahkk commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Instance creation now supports user-data via --user-data or --user-data-file flags
    • SSH key import accepts --project and --region options
    • Volume creation supports --size parameter for custom plans
    • Instance retrieval automatically retries on transient routing errors
    • SSH connections prefer private IP addresses when available
  • Bug Fixes

    • Delete operations gracefully handle already-deleted resources with friendly messages
  • Changes

    • Removed -y shorthand from --yes flags on delete commands

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ditahkk, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 28 minutes and 45 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8b8bb2d7-c5e3-413e-8ddc-d6924be54c94

📥 Commits

Reviewing files that changed from the base of the PR and between a51e357 and 355fd75.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • RELEASE_NOTES.md
  • internal/api/apierrors/errors.go
  • internal/api/apierrors/errors_test.go
  • internal/api/instance/instance.go
  • internal/commands/dns.go
  • internal/commands/instance.go
  • internal/commands/template.go
  • internal/commands/volume.go
📝 Walkthrough

Walkthrough

This PR introduces error classification helpers to detect transient routing errors and resource-not-found conditions, applies idempotent delete patterns across ~20 CLI commands, and enhances instance command resilience with automatic retry and network IP fallback logic. It also refines API request models, normalizes command flags, and adds comprehensive test coverage.

Changes

Error handling, instance resilience, and idempotent deletes

Layer / File(s) Summary
Error classification helpers
internal/api/apierrors/errors.go, internal/api/apierrors/errors_test.go
Added IsTransientRoutingError and IsResourceNotFound to classify 403/404 errors; IsTransientRoutingError detects "route … could not be found" patterns for safe retry, while IsResourceNotFound handles both 404s and 403s containing "not-found". Comprehensive test coverage validates exact and case-insensitive matching.
Instance model and network types
internal/api/instance/instance.go
Extended VirtualMachine with Networks field; added VMNetwork and VMNetworkIP types to represent network attachments; added NetworkPrivateIP() method to extract first non-empty private IP from network pivot data.
API request enhancements
internal/api/sshkey/sshkey.go, internal/api/volume/volume.go
SSH key CreateRequest adds optional Project and Region fields; volume CreateRequest introduces CustomPlanStorage struct and changes custom_plan from string to optional *CustomPlanStorage, making plan optional.
Instance command resilience
internal/commands/instance.go
Instance get retries transient routing errors with exponential backoff (5 attempts); instance list and ssh fall back to NetworkPrivateIP(); instance create adds --user-data and --user-data-file support; delete/tag-delete treat not-found as success; reset/change-os/delete flags remove -y shorthand.
Idempotent deletes across commands
internal/commands/affinitygroup.go, autoscale.go, backup.go, dns.go, egress.go, firewall.go, ip.go, iso.go, kubernetes.go, loadbalancer.go, network.go, objectstorage.go, portforward.go, profile.go, project.go, snapshot.go, sshkey.go, support.go, template.go, vmbackup.go, vmsnapshot.go, volume.go, vpc.go, vpn.go
All delete operations now check apierrors.IsResourceNotFound(err) and treat not-found as a successful no-op with stderr messaging instead of error. The --yes flag is normalized to long-form only (no -y shorthand) across all affected commands.
Volume create custom-tier and delete
internal/commands/volume.go
Volume create adds --size flag with mutual exclusivity validation against --plan, rejects negative sizes, and maps custom-tier requests from numeric size; volume detach and delete treat not-found as success.
SSH key import targeting
internal/commands/sshkey.go
SSH key import accepts --project and --region flags to target key creation; delete removes -y shorthand and treats not-found as success.
Test coverage
internal/commands/commands_test.go
Added TestInstanceGetRetrySucceeds, TestInstanceGetRetryExhausted, and TestInstanceGetNonRoutingErrorNoRetry to validate retry behavior with mock HTTP servers; added TestNoShorthandCollisions to detect flag shorthand duplicates via Cobra tree traversal.
Smoke test updates
tests/smoke/cases.sh
Updated _read_with_network to filter for Isolated network type; added --timeout 60 to object-storage bucket list test.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • zsoftly/zcp-cli#1: Establishes the foundation for error field population that the new IsTransientRoutingError and IsResourceNotFound helpers rely on to classify routing and not-found errors.

Suggested reviewers

  • godsonten
  • ClintonChe

🐰 A routing error appears, but we don't despair,
Retry with grace and exponential care.
Resources gone? Just smile and say success,
Idempotent deletes make ops less of a mess! 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title 'Issues/handle errors' is vague and generic, using non-descriptive terms that don't convey specific information about the substantial changes made across multiple files. Use a more specific title that describes the main change, such as 'Make resource deletion idempotent across CLI commands' or 'Add transient error handling and idempotent deletes'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/handle-errors

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 and usage tips.

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

🧹 Nitpick comments (2)
internal/commands/vmbackup.go (1)

184-192: 💤 Low value

Consider using printer.Fprintf for consistency with the established pattern.

The success message on line 191 uses fmt.Fprintf(os.Stdout, ...), but the established pattern (as shown in iso.go context) is to use printer.Fprintf(...) for success messages.

♻️ Proposed fix for consistency
 		return fmt.Errorf("vm-backup delete: %w", err)
 	}
-	fmt.Fprintf(os.Stdout, "VM backup %q deleted.\n", slug)
+	printer.Fprintf("VM backup %q deleted.\n", slug)
 	return nil

Note: You'll need to capture the printer return value from buildClientAndPrinter on line 177.

🤖 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/commands/vmbackup.go` around lines 184 - 192, The success message
currently uses fmt.Fprintf(os.Stdout...)—capture the printer returned by
buildClientAndPrinter (the same way other commands do) and replace the
fmt.Fprintf call with printer.Fprintf to print the success message; keep the
existing svc.Delete error handling (including apierrors.IsResourceNotFound)
unchanged and only swap the output call to use printer.Fprintf so it follows the
established pattern.
internal/commands/snapshot.go (1)

225-232: 💤 Low value

Consider using printer.Fprintf for consistency with the established pattern.

The success message on line 232 uses fmt.Fprintf(os.Stdout, ...), but the established pattern (as shown in iso.go context) is to use printer.Fprintf(...) for success messages and reserve direct fmt.Fprintf(os.Stderr, ...) for the "already deleted" case.

♻️ Proposed fix for consistency
 		return fmt.Errorf("snapshot delete: %w", err)
 	}
-	fmt.Fprintf(os.Stdout, "Snapshot %q deleted.\n", slug)
+	printer.Fprintf("Snapshot %q deleted.\n", slug)
 	return nil
🤖 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/commands/snapshot.go` around lines 225 - 232, Replace the direct
stdout write used after svc.Delete with the package printer for consistency:
where the code calls fmt.Fprintf(os.Stdout, "Snapshot %q deleted.\n", slug)
(inside the Delete handling block after svc.Delete(ctx, slug)), change it to
printer.Fprintf(out, "Snapshot %q deleted.\n", slug) or
printer.Fprintf(cmd.OutOrStdout(), ...) depending on the surrounding code’s
printer/out variable; ensure the printer/Out variable used elsewhere in this
file (as in iso.go patterns) is referenced so you keep the established messaging
convention.
🤖 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 `@internal/commands/dns.go`:
- Around line 383-386: The fmt.Fprintf call that logs a missing DNS record is
using the string-quote verb %q for the integer variable recordID; update the
format specifier to %d so the integer prints correctly (change the fmt.Fprintf
invocation referencing recordID in the DNS delete handler to use "%d" instead of
"%q"). Ensure you only modify the format string and keep the same arguments and
error handling (the call around apierrors.IsResourceNotFound(err) and recordID).

In `@internal/commands/instance.go`:
- Around line 268-274: Add a mutual-exclusivity check before the user-data
handling so that if both userData (the inline --user-data flag) and userDataFile
(the --user-data-file flag) are set the command returns an error rather than
silently overwriting; specifically, in the function that contains the shown
snippet (where variables userData and userDataFile are used) add a check like:
if userData != "" && userDataFile != "" { return fmt.Errorf("flags --user-data
and --user-data-file are mutually exclusive") } and keep the existing logic that
reads the file into userData only when userDataFile is set.

---

Nitpick comments:
In `@internal/commands/snapshot.go`:
- Around line 225-232: Replace the direct stdout write used after svc.Delete
with the package printer for consistency: where the code calls
fmt.Fprintf(os.Stdout, "Snapshot %q deleted.\n", slug) (inside the Delete
handling block after svc.Delete(ctx, slug)), change it to printer.Fprintf(out,
"Snapshot %q deleted.\n", slug) or printer.Fprintf(cmd.OutOrStdout(), ...)
depending on the surrounding code’s printer/out variable; ensure the printer/Out
variable used elsewhere in this file (as in iso.go patterns) is referenced so
you keep the established messaging convention.

In `@internal/commands/vmbackup.go`:
- Around line 184-192: The success message currently uses
fmt.Fprintf(os.Stdout...)—capture the printer returned by buildClientAndPrinter
(the same way other commands do) and replace the fmt.Fprintf call with
printer.Fprintf to print the success message; keep the existing svc.Delete error
handling (including apierrors.IsResourceNotFound) unchanged and only swap the
output call to use printer.Fprintf so it follows the established pattern.
🪄 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

Run ID: 7aaa7c67-c5ba-4254-8ff5-c2cb2dffff62

📥 Commits

Reviewing files that changed from the base of the PR and between 6989c02 and a51e357.

📒 Files selected for processing (32)
  • internal/api/apierrors/errors.go
  • internal/api/apierrors/errors_test.go
  • internal/api/instance/instance.go
  • internal/api/sshkey/sshkey.go
  • internal/api/volume/volume.go
  • internal/commands/affinitygroup.go
  • internal/commands/autoscale.go
  • internal/commands/backup.go
  • internal/commands/commands_test.go
  • internal/commands/dns.go
  • internal/commands/egress.go
  • internal/commands/firewall.go
  • internal/commands/instance.go
  • internal/commands/ip.go
  • internal/commands/iso.go
  • internal/commands/kubernetes.go
  • internal/commands/loadbalancer.go
  • internal/commands/network.go
  • internal/commands/objectstorage.go
  • internal/commands/portforward.go
  • internal/commands/profile.go
  • internal/commands/project.go
  • internal/commands/snapshot.go
  • internal/commands/sshkey.go
  • internal/commands/support.go
  • internal/commands/template.go
  • internal/commands/vmbackup.go
  • internal/commands/vmsnapshot.go
  • internal/commands/volume.go
  • internal/commands/vpc.go
  • internal/commands/vpn.go
  • tests/smoke/cases.sh

Comment thread internal/commands/dns.go
Comment thread internal/commands/instance.go
@ditahkk ditahkk merged commit 56ff5bb into main Jun 8, 2026
12 checks passed
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