Skip to content

Commit b941c6b

Browse files
committed
Add private.ImageDestination.NoteOriginalOCIConfig
For now, this only adds the API, nothing actually benefits from it yet. Signed-off-by: Miloslav Trmač <[email protected]>
1 parent ce97c0f commit b941c6b

File tree

12 files changed

+79
-8
lines changed

12 files changed

+79
-8
lines changed

copy/single.go

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar
109109
}
110110
}
111111

112-
if err := checkImageDestinationForCurrentRuntime(ctx, c.options.DestinationCtx, src, c.dest); err != nil {
112+
if err := prepareImageConfigForDest(ctx, c.options.DestinationCtx, src, c.dest); err != nil {
113113
return copySingleImageResult{}, err
114114
}
115115

@@ -316,12 +316,15 @@ func (c *copier) copySingleImage(ctx context.Context, unparsedImage *image.Unpar
316316
return res, nil
317317
}
318318

319-
// checkImageDestinationForCurrentRuntime enforces dest.MustMatchRuntimeOS, if necessary.
320-
func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.SystemContext, src types.Image, dest types.ImageDestination) error {
319+
// prepareImageConfigForDest enforces dest.MustMatchRuntimeOS and handles dest.NoteOriginalOCIConfig, if necessary.
320+
func prepareImageConfigForDest(ctx context.Context, sys *types.SystemContext, src types.Image, dest private.ImageDestination) error {
321+
ociConfig, configErr := src.OCIConfig(ctx)
322+
// Do not fail on configErr here, this might be an artifact
323+
// and maybe nothing needs this to be a container image and to process the config.
324+
321325
if dest.MustMatchRuntimeOS() {
322-
c, err := src.OCIConfig(ctx)
323-
if err != nil {
324-
return fmt.Errorf("parsing image configuration: %w", err)
326+
if configErr != nil {
327+
return fmt.Errorf("parsing image configuration: %w", configErr)
325328
}
326329
wantedPlatforms := platform.WantedPlatforms(sys)
327330

@@ -331,17 +334,22 @@ func checkImageDestinationForCurrentRuntime(ctx context.Context, sys *types.Syst
331334
// For a transitional period, this might trigger warnings because the Variant
332335
// field was added to OCI config only recently. If this turns out to be too noisy,
333336
// revert this check to only look for (OS, Architecture).
334-
if platform.MatchesPlatform(c.Platform, wantedPlatform) {
337+
if platform.MatchesPlatform(ociConfig.Platform, wantedPlatform) {
335338
match = true
336339
break
337340
}
338341
options.append(fmt.Sprintf("%s+%s+%q", wantedPlatform.OS, wantedPlatform.Architecture, wantedPlatform.Variant))
339342
}
340343
if !match {
341344
logrus.Infof("Image operating system mismatch: image uses OS %q+architecture %q+%q, expecting one of %q",
342-
c.OS, c.Architecture, c.Variant, strings.Join(options.list, ", "))
345+
ociConfig.OS, ociConfig.Architecture, ociConfig.Variant, strings.Join(options.list, ", "))
343346
}
344347
}
348+
349+
if err := dest.NoteOriginalOCIConfig(ociConfig, configErr); err != nil {
350+
return err
351+
}
352+
345353
return nil
346354
}
347355

directory/directory_dest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var ErrNotContainerImageDir = errors.New("not a containers image directory, don'
2929
type dirImageDestination struct {
3030
impl.Compat
3131
impl.PropertyMethodsInitialize
32+
stubs.IgnoresOriginalOCIConfig
3233
stubs.NoPutBlobPartialInitialize
3334
stubs.AlwaysSupportsSignatures
3435

docker/docker_image_dest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
type dockerImageDestination struct {
4242
impl.Compat
4343
impl.PropertyMethodsInitialize
44+
stubs.IgnoresOriginalOCIConfig
4445
stubs.NoPutBlobPartialInitialize
4546

4647
ref dockerReference

docker/internal/tarfile/dest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
type Destination struct {
2525
impl.Compat
2626
impl.PropertyMethodsInitialize
27+
stubs.IgnoresOriginalOCIConfig
2728
stubs.NoPutBlobPartialInitialize
2829
stubs.NoSignaturesInitialize
2930

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package stubs
2+
3+
import (
4+
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
5+
)
6+
7+
// IgnoresOriginalOCIConfig implements NoteOriginalOCIConfig() that does nothing.
8+
type IgnoresOriginalOCIConfig struct{}
9+
10+
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
11+
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
12+
// The destination can use it in its TryReusingBlob/PutBlob implementations
13+
// (otherwise it only obtains the final config after all layers are written).
14+
func (stub IgnoresOriginalOCIConfig) NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error {
15+
return nil
16+
}

internal/imagedestination/wrapper.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
// wrapped provides the private.ImageDestination operations
1515
// for a destination that only implements types.ImageDestination
1616
type wrapped struct {
17+
stubs.IgnoresOriginalOCIConfig
1718
stubs.NoPutBlobPartialInitialize
1819

1920
types.ImageDestination

internal/private/private.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
compression "github.com/containers/image/v5/pkg/compression/types"
1111
"github.com/containers/image/v5/types"
1212
"github.com/opencontainers/go-digest"
13+
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
1314
)
1415

1516
// ImageSourceInternalOnly is the part of private.ImageSource that is not
@@ -41,6 +42,12 @@ type ImageDestinationInternalOnly interface {
4142
// FIXME: Add SupportsSignaturesWithFormat or something like that, to allow early failures
4243
// on unsupported formats.
4344

45+
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
46+
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
47+
// The destination can use it in its TryReusingBlob/PutBlob implementations
48+
// (otherwise it only obtains the final config after all layers are written).
49+
NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error
50+
4451
// PutBlobWithOptions writes contents of stream and returns data representing the result.
4552
// inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents.
4653
// inputInfo.Size is the expected length of stream, if known.

oci/archive/oci_dest.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/containers/storage/pkg/archive"
1515
"github.com/containers/storage/pkg/idtools"
1616
digest "github.com/opencontainers/go-digest"
17+
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
1718
"github.com/sirupsen/logrus"
1819
)
1920

@@ -103,6 +104,14 @@ func (d *ociArchiveImageDestination) SupportsPutBlobPartial() bool {
103104
return d.unpackedDest.SupportsPutBlobPartial()
104105
}
105106

107+
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
108+
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
109+
// The destination can use it in its TryReusingBlob/PutBlob implementations
110+
// (otherwise it only obtains the final config after all layers are written).
111+
func (d *ociArchiveImageDestination) NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error {
112+
return d.unpackedDest.NoteOriginalOCIConfig(ociConfig, configErr)
113+
}
114+
106115
// PutBlobWithOptions writes contents of stream and returns data representing the result.
107116
// inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents.
108117
// inputInfo.Size is the expected length of stream, if known.

oci/layout/oci_dest.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
type ociImageDestination struct {
2828
impl.Compat
2929
impl.PropertyMethodsInitialize
30+
stubs.IgnoresOriginalOCIConfig
3031
stubs.NoPutBlobPartialInitialize
3132
stubs.NoSignaturesInitialize
3233

openshift/openshift_dest.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/containers/image/v5/manifest"
2323
"github.com/containers/image/v5/types"
2424
"github.com/opencontainers/go-digest"
25+
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
2526
)
2627

2728
type openshiftImageDestination struct {
@@ -111,6 +112,14 @@ func (d *openshiftImageDestination) SupportsPutBlobPartial() bool {
111112
return d.docker.SupportsPutBlobPartial()
112113
}
113114

115+
// NoteOriginalOCIConfig provides the config of the image, as it exists on the source, BUT converted to OCI format,
116+
// or an error obtaining that value (e.g. if the image is an artifact and not a container image).
117+
// The destination can use it in its TryReusingBlob/PutBlob implementations
118+
// (otherwise it only obtains the final config after all layers are written).
119+
func (d *openshiftImageDestination) NoteOriginalOCIConfig(ociConfig *imgspecv1.Image, configErr error) error {
120+
return d.docker.NoteOriginalOCIConfig(ociConfig, configErr)
121+
}
122+
114123
// PutBlobWithOptions writes contents of stream and returns data representing the result.
115124
// inputInfo.Digest can be optionally provided if known; if provided, and stream is read to the end without error, the digest MUST match the stream contents.
116125
// inputInfo.Size is the expected length of stream, if known.

0 commit comments

Comments
 (0)