From 820e56765083b50d0e8f4baf06f4804700f33a92 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Thu, 29 May 2025 15:33:50 -0700 Subject: [PATCH 1/3] Add more error details when unpack fails to extract Signed-off-by: Derek McGowan --- core/unpack/unpacker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/unpack/unpacker.go b/core/unpack/unpacker.go index a1c49e23b8..642b2dde8c 100644 --- a/core/unpack/unpacker.go +++ b/core/unpack/unpacker.go @@ -428,7 +428,7 @@ func (u *Unpacker) unpack( diff, err := a.Apply(ctx, desc, mounts, unpack.ApplyOpts...) if err != nil { cleanup.Do(ctx, abort) - return fmt.Errorf("failed to extract layer %s: %w", diffIDs[i], err) + return fmt.Errorf("failed to extract layer (%s %s) to %s as %q: %w", desc.MediaType, desc.Digest, unpack.SnapshotterKey, key, err) } if diff.Digest != diffIDs[i] { cleanup.Do(ctx, abort) From 0c3cd8a99529849ee2e3f9661ebfa937f3f9be66 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Thu, 29 May 2025 15:34:06 -0700 Subject: [PATCH 2/3] Add debug log when transfer returns not implemented Currently the error details are not included in the output error and there is no log. One of the reasons a the transferer was skipped could be do to a specific component which is not implemented (such as trying to use erofs differ) or unsupported image (pulling schema1). This information is useful to find a bad configuration. Signed-off-by: Derek McGowan --- plugins/services/transfer/service.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/services/transfer/service.go b/plugins/services/transfer/service.go index 9b4113f204..fa862a4c33 100644 --- a/plugins/services/transfer/service.go +++ b/plugins/services/transfer/service.go @@ -138,6 +138,7 @@ func (s *service) Transfer(ctx context.Context, req *transferapi.TransferRequest } else if !errdefs.IsNotImplemented(err) { return nil, errgrpc.ToGRPC(err) } + log.G(ctx).WithError(err).Debugf("transfer not implemented for %T to %T", src, dst) } return nil, status.Errorf(codes.Unimplemented, "method Transfer not implemented for %s to %s", req.Source.GetTypeUrl(), req.Destination.GetTypeUrl()) } From 4bcea74decd64dcbf616f56b47cf8f5b4a2a586f Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Thu, 29 May 2025 15:49:09 -0700 Subject: [PATCH 3/3] Update differ selection in transfer service to prefer default Currently the erofs differ will be chosen and cause pulls to fail with not implemented errors. Signed-off-by: Derek McGowan --- plugins/transfer/plugin.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/plugins/transfer/plugin.go b/plugins/transfer/plugin.go index 4c61b898b4..c1041e94c6 100644 --- a/plugins/transfer/plugin.go +++ b/plugins/transfer/plugin.go @@ -30,6 +30,7 @@ import ( "github.com/containerd/containerd/v2/core/metadata" "github.com/containerd/containerd/v2/core/transfer/local" "github.com/containerd/containerd/v2/core/unpack" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/containerd/v2/internal/kmutex" "github.com/containerd/containerd/v2/pkg/imageverifier" "github.com/containerd/containerd/v2/plugins" @@ -115,6 +116,7 @@ func init() { } applier = inst.(diff.Applier) } else { + var applierID string for name, plugin := range ic.GetAll() { if plugin.Registration.Type != plugins.DiffPlugin { continue @@ -129,14 +131,25 @@ func init() { continue } if applier != nil { - log.G(ic.Context).Warnf("multiple differs match for platform, set `differ` option to choose, skipping %q", plugin.Registration.ID) - continue + skippedApplier := plugin.Registration.ID + + // Prefer the default when multiple plugins match + if skippedApplier == defaults.DefaultDiffer { + skippedApplier = applierID + } + + log.G(ic.Context).Warnf("multiple differs match for platform, set `differ` option to choose, skipping %q", skippedApplier) + + if plugin.Registration.ID == skippedApplier { + continue + } } inst, err := plugin.Instance() if err != nil { return nil, fmt.Errorf("failed to get instance for diff plugin %q: %w", name, err) } applier = inst.(diff.Applier) + applierID = plugin.Registration.ID } } if applier == nil {