Skip to content

Commit cf97f48

Browse files
committed
WIP: Sketch PutBlob... digest choice in c/image/copy + transports
This is: - UNUSABLE (no external API) - INCOMPLETE (manifest digests, TryReusingBlob, ...) - BROKEN (various code assumes that digest returned from upload matches input) - INCONSISTENT (PutBlobOptions.Digests is only implemented in one transport, and silently ignored elsewhere) Signed-off-by: Miloslav Trmač <mitr@redhat.com>
1 parent c47544c commit cf97f48

File tree

5 files changed

+29
-3
lines changed

5 files changed

+29
-3
lines changed

image/copy/blob.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ func (ic *imageCopier) copyBlobFromStream(ctx context.Context, srcReader io.Read
101101
Cache: ic.c.blobInfoCache,
102102
IsConfig: isConfig,
103103
EmptyLayer: emptyLayer,
104+
Digests: ic.c.options.digestOptions,
105+
// CannotChangeDigestReason requires stream.info.Digest to always be set, and it is:
106+
// If ic.cannotModifyManifestReason, stream.info was not modified since its initialization at the top of this
107+
// function, and the caller is required to provide a digest.
108+
CannotChangeDigestReason: ic.cannotModifyManifestReason,
104109
}
105110
if !isConfig {
106111
options.LayerIndex = &layerIndex

image/directory/directory_dest.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/opencontainers/go-digest"
1313
"github.com/sirupsen/logrus"
14+
"go.podman.io/image/v5/internal/digests"
1415
"go.podman.io/image/v5/internal/imagedestination/impl"
1516
"go.podman.io/image/v5/internal/imagedestination/stubs"
1617
"go.podman.io/image/v5/internal/private"
@@ -150,7 +151,11 @@ func (d *dirImageDestination) PutBlobWithOptions(ctx context.Context, stream io.
150151
}
151152
}()
152153

153-
digester, stream := putblobdigest.DigestIfUnknown(stream, inputInfo)
154+
algorithm, err := options.Digests.Choose(digests.Situation{Preexisting: inputInfo.Digest, CannotChangeAlgorithmReason: options.CannotChangeDigestReason})
155+
if err != nil {
156+
return private.UploadedBlob{}, err
157+
}
158+
digester, stream := putblobdigest.DigestIfAlgorithmUnknown(stream, inputInfo, algorithm)
154159

155160
// TODO: This can take quite some time, and should ideally be cancellable using ctx.Done().
156161
size, err := io.Copy(blobFile, stream)

image/internal/imagedestination/impl/compat.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/opencontainers/go-digest"
88
"go.podman.io/image/v5/internal/blobinfocache"
9+
"go.podman.io/image/v5/internal/digests"
910
"go.podman.io/image/v5/internal/private"
1011
"go.podman.io/image/v5/internal/signature"
1112
"go.podman.io/image/v5/types"
@@ -46,6 +47,8 @@ func (c *Compat) PutBlob(ctx context.Context, stream io.Reader, inputInfo types.
4647
res, err := c.dest.PutBlobWithOptions(ctx, stream, inputInfo, private.PutBlobOptions{
4748
Cache: blobinfocache.FromBlobInfoCache(cache),
4849
IsConfig: isConfig,
50+
51+
Digests: digests.CanonicalDefault(),
4952
})
5053
if err != nil {
5154
return types.BlobInfo{}, err

image/internal/imagedestination/wrapper.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io"
66

77
"github.com/opencontainers/go-digest"
8+
"go.podman.io/image/v5/internal/digests"
89
"go.podman.io/image/v5/internal/imagedestination/stubs"
910
"go.podman.io/image/v5/internal/private"
1011
"go.podman.io/image/v5/internal/signature"
@@ -53,6 +54,15 @@ func (w *wrapped) PutBlobWithOptions(ctx context.Context, stream io.Reader, inpu
5354
if err != nil {
5455
return private.UploadedBlob{}, err
5556
}
57+
// Check that the returned digest is compatible with options.Digests. If it isn’t, there’s nothing we can do, but at least the callers of PutBlobWithOptions
58+
// won’t need to double-check.
59+
if _, err := options.Digests.Choose(digests.Situation{
60+
Preexisting: res.Digest,
61+
CannotChangeAlgorithmReason: "external transport API does not allow choosing a digest algorithm",
62+
}); err != nil {
63+
return private.UploadedBlob{}, err
64+
}
65+
5666
return private.UploadedBlob{
5767
Digest: res.Digest,
5868
Size: res.Size,

image/internal/private/private.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
1010
"go.podman.io/image/v5/docker/reference"
1111
"go.podman.io/image/v5/internal/blobinfocache"
12+
"go.podman.io/image/v5/internal/digests"
1213
"go.podman.io/image/v5/internal/signature"
1314
compression "go.podman.io/image/v5/pkg/compression/types"
1415
"go.podman.io/image/v5/types"
@@ -111,8 +112,10 @@ type PutBlobOptions struct {
111112
// if they use internal/imagedestination/impl.Compat;
112113
// in that case, they will all be consistently zero-valued.
113114

114-
EmptyLayer bool // True if the blob is an "empty"/"throwaway" layer, and may not necessarily be physically represented.
115-
LayerIndex *int // If the blob is a layer, a zero-based index of the layer within the image; nil otherwise.
115+
EmptyLayer bool // True if the blob is an "empty"/"throwaway" layer, and may not necessarily be physically represented.
116+
LayerIndex *int // If the blob is a layer, a zero-based index of the layer within the image; nil otherwise.
117+
Digests digests.Options // Unlike other private fields, this is always initialized, and mandatory requests are enforced by the compatibility wrapper.
118+
CannotChangeDigestReason string // The reason why PutBlobWithOptions is provided with a digest and the destination must use precisely that one (in particular, use that algorithm).
116119
}
117120

118121
// PutBlobPartialOptions are used in PutBlobPartial.

0 commit comments

Comments
 (0)