Skip to content

Enhance image management with DeleteImage API and improved resilience - #102

Merged
gaius-qi merged 5 commits into
mainfrom
feature/image
Nov 11, 2026
Merged

gaius-qi merged 5 commits into
mainfrom
feature/image

Conversation

@gaius-qi

@gaius-qi gaius-qi commented Nov 11, 2026 •

Copy link
Copy Markdown
Member

Description

Makes the image APIs of client-request (Go and Rust) image-aware. PreheatImage, StatImage and DeleteImage now all talk to the seed peers directly; the scheduler is only used to list the seed peers.

sequenceDiagram
    participant SDK
    participant Registry
    participant SeedPeers as Seed peers (dfdaemon)

    Note over SDK,SeedPeers: PreheatImage
    SDK->>Registry: resolve manifests (all platforms, or one)
    SDK->>SeedPeers: DownloadTask(url, image{reference, platform})

    Note over SDK,SeedPeers: StatImage
    SDK->>Registry: resolve manifests (all platforms, or one)
    SDK->>SeedPeers: StatLocalTask(task id) for every layer

    Note over SDK,SeedPeers: DeleteImage
    SDK->>SeedPeers: DeleteImage(manifest url, platform)
    SeedPeers-->>SDK: deleted / retained task ids
Loading
API Before After
PreheatImage Preheats one platform, the current platform by default. Preheats all the platforms unless a platform is set. Every download carries the image reference and the platform, so dfdaemon records which image a task belongs to.
StatImage Calls the scheduler StatImage gRPC, which needs the scheduler job service (redis). Resolves the image itself and asks every healthy seed peer for each layer with dfdaemon StatLocalTask.
DeleteImage Resolves the image from the registry and deletes every manifest and blob task from its replicas. Calls dfdaemon DeleteImage on every healthy seed peer, without resolving the image. A task still referenced by another image or platform is retained. Returns the deleted and retained task ids of each seed peer.

API changes

 // Go (the Rust crate mirrors it with the same names in snake_case)
-DeleteImage(ctx, req) error
+DeleteImage(ctx, req) (*DeleteImageResponse, error)   // Peers []*PeerDeletedImage{IP, Hostname, DeletedTaskIDs, RetainedTaskIDs}

 // DeleteImageRequest options
+WithDeleteImageRequestConcurrentPeerCount             // default 500
 WithDeleteImageRequestPlatform
 WithDeleteImageRequestTimeout
-WithDeleteImageRequest{Auth,PieceLength,Tag,Application,FilteredQueryParams,
-  ContentForCalculatingTaskID,EnableTaskIDBasedBlobDigest,Replicas,Scope,ConcurrentTaskCount}

 // StatImageRequest options
+WithStatImageRequestConcurrentPeerCount               // default 500

-PeerImage
+PeerStatedImage
  • The platform is optional (*string / Option<String>), unset means all the platforms, and it is validated: containerd/platforms in Go, the os/arch form in Rust.
  • StatImage and DeleteImage fan out to the seed peers with a concurrency limit. A seed peer that fails is left out of the response instead of failing the request.
  • An image index that lists the same manifest twice for a platform is preheated once.

Notes

  • The seed peers must run dfdaemon v1.5.12 or later. An image preheated by an earlier SDK has no image record, so DeleteImage deletes nothing for it.
  • StatImage now needs the registry to be reachable from the SDK, as PreheatImage does.
  • With a platform set, Go follows the strict matcher of containerd (linux/arm selects arm/v7 only) and normalizes aliases such as linux/aarch64; Rust selects every index entry with that os/arch and sends the platform as given.
  • Bumps d7y.io/api/v2 to v2.3.10 and d7y.io/dragonfly/v2 to v2.5.4-rc.0, dragonfly-api to 2.3.10, and the crate version to 1.13.0. The e2e cluster uses scheduler v2.5.4-rc.0 and client v1.5.12.

Tests

  • Go: table-driven tests for PreheatImage, StatImage and DeleteImage against an in-test TLS registry and mock seed peers (targets and Download.image per platform, cached layers per seed peer, a failed seed peer left out, retries, invalid arguments).
  • Rust: table-driven twins for delete_image and for the invalid arguments of the three APIs. The success paths of preheat_image and stat_image need a registry and are covered by the e2e tests.
  • e2e: the drivers gain preheat-image --platform, stat-image and delete-image --platform. The suite grows from 31 to 53 specs, run for both SDKs: preheat all platforms, one platform and by digest; stat by platform and after delete; delete by platform, platforms preheated one by one, a platform or an image that is not preheated, a tag and a digest reference sharing a platform, two tags sharing one blob, and an image preheated by one SDK and deleted by the other.

Unit tests pass locally (go test -race, cargo test --all-features, clippy with and without the preheat feature). The e2e specs run in CI.

Related Issue

Motivation and Context

Deleting an image by resolving its manifest removes blobs that other images still share, and fails when the registry is unreachable or the tag has moved. dfdaemon v1.5.12 records the image and the platform every task is downloaded for, so the SDK passes them at preheat and lets dfdaemon decide what to delete.

StatImage went through the scheduler job service, which only exists when redis is deployed. Asking the seed peers directly makes it work like PreheatImage and DeleteImage in a scheduler-only deployment.

Screenshots (if appropriate)

N/A

🤖 Generated with Claude Code

… preheat all platforms by default

Image deletion is now delegated to dfdaemon's DeleteImage API on every seed
peer, keyed by the manifest URL (with retries), instead of being resolved and
removed task-by-task on the client side. Preheat tasks are tagged with the
image reference and platform so later deletions can match them, and image
preheat covers all manifest platforms unless one is specified. Examples drop
the obsolete scope parameter and print per-peer deleted/retained results.

E2E tests gain multi-platform and digest-reference cases for preheat and
delete, platform-aware SDK/driver helpers (Go and Rust), inline blob fixtures,
verification of deleted vs retained task IDs per seed peer, and bumped
dragonfly dependencies and chart images.

Signed-off-by: Gaius <gaius.qi@gmail.com>
…ate platforms

Make the Go and Rust client-request libraries resilient and consistent:
- DeleteImage no longer fails the whole operation when a single seed peer
  errors; failed peers are skipped and remaining peers are still processed.
- Seed peer requests in DeleteImage are now bounded by a concurrency limit
  instead of fanning out to all peers at once.
- PreheatImage deduplicates manifests that resolve to the same platform so
  identical layers are not preheated repeatedly.
- StatImage validates the requested platform up front and returns a clear
  error for unsupported or malformed values.

Tests and READMEs are updated to cover the new behavior.

Signed-off-by: Gaius <gaius.qi@gmail.com>
… instead of the scheduler

Resolve image manifests in stat_image and ask seed peers directly for
layer stat results, removing the scheduler round-trip. Both the Go and
Rust client libraries are updated along with their READMEs.

Add a stat-image command to the Go and Rust e2e drivers and an e2e test
that verifies cached image layers are reported correctly.

Signed-off-by: Gaius <gaius.qi@gmail.com>
@gaius-qi gaius-qi self-assigned this Nov 11, 2026
@gaius-qi
gaius-qi requested review from a team as code owners November 11, 2026 15:54
@gaius-qi
gaius-qi requested review from hyy0322 and yyzai384 November 11, 2026 15:54
@gaius-qi gaius-qi added the enhancement New feature or request label Nov 11, 2026
@gaius-qi
gaius-qi enabled auto-merge (squash) November 11, 2026 15:54
Drop the "since 1.11.0" and "since 1.13.0" breaking-change paragraphs and
the behavior details about seed peers recording tasks per image/platform
and omitting failed seed peers from the delete response in the Go and Rust
client READMEs, and remove the multi-platform preheat, delete and stat
description from the e2e README.

In the e2e SDK helper, make `run` take the driver command explicitly and
append the `--scheduler` endpoint itself, so each wrapper no longer repeats
the command name and scheduler flag; error and log messages use the command
directly instead of the first argument.

Signed-off-by: Gaius <gaius.qi@gmail.com>
…config

Add `backend.enableCacheTemporaryRedirect: false` to the seed client
section of the test chart configuration so the test deployment does not
cache HTTP temporary redirect responses.

Signed-off-by: Gaius <gaius.qi@gmail.com>
@gaius-qi
gaius-qi disabled auto-merge November 11, 2026 16:47
@gaius-qi
gaius-qi merged commit 27783d0 into main Nov 11, 2026
10 checks passed
@gaius-qi
gaius-qi deleted the feature/image branch November 11, 2026 16:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant