Skip to content

feat: Allow partial success results - #400

Open
nurof3n wants to merge 3 commits into
prod-stagingfrom
nurof3n/partial-results
Open

feat: Allow partial success results#400
nurof3n wants to merge 3 commits into
prod-stagingfrom
nurof3n/partial-results

Conversation

@nurof3n

@nurof3n nurof3n commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

To be merged after #388
Closes TOOL-1048

@nurof3n
nurof3n requested a review from jedevc July 6, 2026 12:50
@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch from 91aa4ef to e0a2d5b Compare July 6, 2026 12:52
@nurof3n nurof3n changed the title fix(volume): Allow GET to show more than expected results feat: Allow partial success results Jul 6, 2026
@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch 3 times, most recently from 67276b3 to 1d4c4d4 Compare July 6, 2026 13:07
@jedevc

jedevc commented Jul 6, 2026

Copy link
Copy Markdown
Member

Ho hum. Can I get an explanation of what this one is for? 🤔 It's not immediately obvious to me sorry!

@nurof3n

nurof3n commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Ho hum. Can I get an explanation of what this one is for? 🤔 It's not immediately obvious to me sorry!

@jedevc Yup, so the router can return a 207 on listing or bulk requests when some of the metros returned errors, and it would contain both the results for successful calls and the errors for the others.
And I needed a way to show the error in the CLI and also show the listing output.

Copilot AI 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.

Pull request overview

This PR extends the CLI’s multi-metro list/get/delete operations to allow returning partial results when the API returns both a response payload and an error (or when only some items succeed). It introduces shared helpers in internal/cmd/util.go and wires them into several resource commands (instances, volumes, templates, certificates, service groups), aligning with TOOL-1048 and the follow-up to PR #388.

Changes:

  • Add shared partial-success helpers and a PartialResult error type to preserve successful items while still surfacing failures.
  • Update list/get handlers across multiple resources to continue processing response payloads even when an API error is present (when data exists).
  • Update delete handlers to detect partial deletions and return structured partial failures when possible.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
internal/cmd/util.go Adds partial-success helpers (listGetOpError, deleteOpError), PartialResult, and error-combining utilities.
internal/cmd/instances.go Uses partial-success logic for list/get and returns partial delete results when some instances delete successfully.
internal/cmd/instance_templates.go Uses partial-success logic for template instance list/get/delete operations.
internal/cmd/volumes.go Uses partial-success logic for volume list/get and returns partial delete results when possible.
internal/cmd/volume_templates.go Uses partial-success logic for template volume list/get/delete operations.
internal/cmd/certificates.go Uses partial-success logic for certificate list/get and returns partial delete results when possible.
internal/cmd/services.go Uses partial-success logic for service group list/get; delete path attempts partial handling but currently has dead/unreachable logic.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/cmd/services.go Outdated
Comment thread internal/cmd/instances.go Outdated
Comment thread internal/cmd/instances.go Outdated
Comment thread internal/cmd/util.go Outdated
Comment thread internal/cmd/util.go Outdated
@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch from 48a0314 to 7aece91 Compare July 8, 2026 10:13
@jedevc

jedevc commented Jul 8, 2026

Copy link
Copy Markdown
Member

Ho hum. Can I get an explanation of what this one is for? 🤔 It's not immediately obvious to me sorry!

@jedevc Yup, so the router can return a 207 on listing or bulk requests when some of the metros returned errors, and it would contain both the results for successful calls and the errors for the others. And I needed a way to show the error in the CLI and also show the listing output.

Makes sense.

The bit that I don't get is the new helpers in utils.go. Why listGetOpError and similar? IMO, if the response has a partial-success (i.e. resp.Status == "partial_success" and status is 207), we should never abort processing. We should return both all the errors and all the successful responses. It feels like it's a bit overcomplicated but maybe I'm missing something.

Comment thread internal/cmd/instances.go Outdated
@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch 2 times, most recently from eb97ef3 to c82a922 Compare August 3, 2026 13:23
@nurof3n

nurof3n commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@jedevc My bad, I simplified it and now we don't abort processing on partial success.
I also added some tests

@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch from c82a922 to 3d464ff Compare August 3, 2026 13:27
@nurof3n
nurof3n requested a review from jedevc August 3, 2026 13:36
@nurof3n
nurof3n force-pushed the nurof3n/partial-results branch 2 times, most recently from 5c8e9aa to cdb4605 Compare August 3, 2026 13:51

@jedevc jedevc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Ahh, this is super neat. I like this a lot 🎉

Small comments, good finds all around.

Comment thread internal/cmd/certificates.go Outdated
Comment thread internal/cmd/instances.go Outdated
nurof3n and others added 2 commits August 31, 2026 15:06
The router can answer a listing or a bulk request with a 207, carrying
both the results from the metros that succeeded and the errors from the
ones that did not. Abort on such a response and the successful half is
thrown away, so nothing is printed at all.

Never stop processing a response: collect whatever data came back and
join it with the errors, letting the callers decide. The commands
already print partial results before returning the error, so this is
mostly a matter of not discarding them on the way up.

Not-found is the exception: the group helpers already report the refs
that were missing, so ignoreNotFound() drops it on ref-based operations
to avoid reporting it twice. A listing has no refs to fall back on, so
it keeps reporting the error itself.

The lookups that surround a mutation only exist to display it, so a
partial lookup there is warned about rather than turned into a failure.
Waiting is not a mutation: the conditions can only be evaluated against
the resources that were looked up, so an incomplete lookup keeps the
wait polling instead of letting it succeed early.

Signed-off-by: Alex-Andrei Cioc <andrei.cioc@unikraft.io>
Checkpoints, and the history endpoint behind them, landed after this
branch was cut, so they still aborted on a 207 and threw away the metros
that answered.

Same treatment as the rest: read whatever data came back before looking
at the error, and hand it up alongside ignoreNotFound() so the group
helpers stay in charge of reporting missing refs.

Signed-off-by: Justin Chadwell <justin@unikraft.com>
@jedevc
jedevc force-pushed the nurof3n/partial-results branch from cdb4605 to 89ce48a Compare August 31, 2026 14:17
@jedevc jedevc self-assigned this Aug 31, 2026
Applied everywhere the patterns appear rather than only at the lines
they were raised on.

errors.Join already drops nils, so guarding the append with an if in the
listing loops buys nothing. Drop the guard and let the join do the work.

The partial-lookup warnings talked about metros, which internal/resource
has no concept of: it drives images, profiles and config through the
same interfaces, and the fan-out is a detail of internal/cmd. They now
say what the layer actually knows — which resource type could not be
read and what that costs the reader — with the type and keys carried as
structured fields rather than left inside the wrapped error.

A 207 also has to fail the command. Listing and getting already returned
the error after printing, but creating, deleting and editing logged a
warning and returned nil, so a script checking the exit code was told
everything was fine when half the metros never answered. Return it
instead, still only once the output has been written.

Bulk remove returned before printing whenever the delete failed, so a
partial delete reported neither the refs it removed nor the ones it
could not. It prints first now, sharing the filtering that single remove
already used to avoid listing a failed delete as a success.

The sandbox keeps warning rather than returning. Its lookups are
bookkeeping for dependency tracking rather than the user's operation,
and the command layer already looks up and reports the same keys, so
returning them there as well only prints the failure twice. The same
reasoning drops the display lookup from remove when the delete itself
failed.

Signed-off-by: Justin Chadwell <justin@unikraft.com>
@jedevc
jedevc force-pushed the nurof3n/partial-results branch from c14bc2c to e5e3b9f Compare August 31, 2026 15:29

@jedevc jedevc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@nurof3n can you do a quick pass? I made some modifications, can you check this still works as you intended, but I'd like to merge this now! 🎉

Reviewed-by: Justin Chadwell <justin@unikraft.com>
Approved-by: Justin Chadwell <justin@unikraft.com>

@nurof3n nurof3n left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

changes look good to me!
gotta test for regression as well

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.

3 participants