Merge pull request #2482 from rvoh-tismith/fix/single_source_create

Add `--prefer-index` flag for`imagetools create` on a single source
This commit is contained in:
Tõnis Tiigi 2024-05-31 09:44:43 -07:00 committed by GitHub
commit 4549283f44
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 62 additions and 15 deletions

View File

@ -608,7 +608,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
}
}
dt, desc, err := itpull.Combine(ctx, srcs, nil)
dt, desc, err := itpull.Combine(ctx, srcs, nil, false)
if err != nil {
return err
}

View File

@ -29,6 +29,7 @@ type createOptions struct {
dryrun bool
actionAppend bool
progress string
preferIndex bool
}
func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, args []string) error {
@ -153,7 +154,7 @@ func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, arg
}
}
dt, desc, err := r.Combine(ctx, srcs, in.annotations)
dt, desc, err := r.Combine(ctx, srcs, in.annotations, in.preferIndex)
if err != nil {
return err
}
@ -283,6 +284,7 @@ func createCmd(dockerCli command.Cli, opts RootOptions) *cobra.Command {
flags.BoolVar(&options.actionAppend, "append", false, "Append to existing manifest")
flags.StringVar(&options.progress, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`)
flags.StringArrayVarP(&options.annotations, "annotation", "", []string{}, "Add annotation to the image")
flags.BoolVar(&options.preferIndex, "prefer-index", true, "When only a single source is specified, prefer outputting an image index or manifest list instead of performing a carbon copy")
return cmd
}

View File

@ -10,12 +10,13 @@ Create a new image based on source images
### Options
| Name | Type | Default | Description |
|:---------------------------------|:--------------|:--------|:-----------------------------------------------------------------------------------------|
|:---------------------------------|:--------------|:--------|:------------------------------------------------------------------------------------------------------------------------------|
| [`--annotation`](#annotation) | `stringArray` | | Add annotation to the image |
| [`--append`](#append) | | | Append to existing manifest |
| [`--builder`](#builder) | `string` | | Override the configured builder instance |
| [`--dry-run`](#dry-run) | | | Show final image instead of pushing |
| [`-f`](#file), [`--file`](#file) | `stringArray` | | Read source descriptor from file |
| `--prefer-index` | `bool` | `true` | When only a single source is specified, prefer outputting an image index or manifest list instead of performing a carbon copy |
| `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output |
| [`-t`](#tag), [`--tag`](#tag) | `stringArray` | | Set reference for new image |
@ -26,8 +27,13 @@ Create a new image based on source images
Create a new manifest list based on source manifests. The source manifests can
be manifest lists or single platform distribution manifests and must already
exist in the registry where the new manifest is created. If only one source is
specified, create performs a carbon copy.
exist in the registry where the new manifest is created.
If only one source is specified and that source is a manifest list or image index,
create performs a carbon copy. If one source is specified and that source is *not*
a list or index, the output will be a manifest list, however you can disable this
behavior with `--prefer-index=false` which attempts to preserve the source manifest
format in the output.
## Examples

View File

@ -78,6 +78,19 @@ func testImagetoolsCopyManifest(t *testing.T, sb integration.Sandbox) {
for i := range mfst.Layers {
require.Equal(t, mfst.Layers[i].Digest, mfst2.Layers[i].Digest)
}
cmd = buildxCmd(sb, withArgs("imagetools", "create", "--prefer-index=false", "-t", target2+"-not-index", target))
dt, err = cmd.CombinedOutput()
require.NoError(t, err, string(dt))
cmd = buildxCmd(sb, withArgs("imagetools", "inspect", target2+"-not-index", "--raw"))
dt, err = cmd.CombinedOutput()
require.NoError(t, err, string(dt))
var idx3 ocispecs.Manifest
err = json.Unmarshal(dt, &idx3)
require.NoError(t, err)
require.Equal(t, images.MediaTypeDockerSchema2Manifest, idx3.MediaType)
}
func testImagetoolsCopyIndex(t *testing.T, sb integration.Sandbox) {
@ -127,6 +140,24 @@ func testImagetoolsCopyIndex(t *testing.T, sb integration.Sandbox) {
for i := range idx.Manifests {
require.Equal(t, idx.Manifests[i].Digest, idx2.Manifests[i].Digest)
}
cmd = buildxCmd(sb, withArgs("imagetools", "create", "--prefer-index=false", "-t", target2+"-still-index", target))
dt, err = cmd.CombinedOutput()
require.NoError(t, err, string(dt))
cmd = buildxCmd(sb, withArgs("imagetools", "inspect", target2+"-still-index", "--raw"))
dt, err = cmd.CombinedOutput()
require.NoError(t, err, string(dt))
var idx3 ocispecs.Index
err = json.Unmarshal(dt, &idx3)
require.NoError(t, err)
require.Equal(t, images.MediaTypeDockerSchema2ManifestList, idx3.MediaType)
require.Equal(t, len(idx.Manifests), len(idx3.Manifests))
for i := range idx.Manifests {
require.Equal(t, idx.Manifests[i].Digest, idx3.Manifests[i].Digest)
}
}
func testImagetoolsInspectAndFilter(t *testing.T, sb integration.Sandbox) {

View File

@ -29,7 +29,7 @@ type Source struct {
Ref reference.Named
}
func (r *Resolver) Combine(ctx context.Context, srcs []*Source, ann []string) ([]byte, ocispec.Descriptor, error) {
func (r *Resolver) Combine(ctx context.Context, srcs []*Source, ann []string, preferIndex bool) ([]byte, ocispec.Descriptor, error) {
eg, ctx := errgroup.WithContext(ctx)
dts := make([][]byte, len(srcs))
@ -79,8 +79,16 @@ func (r *Resolver) Combine(ctx context.Context, srcs []*Source, ann []string) ([
// on single source, return original bytes
if len(srcs) == 1 && len(ann) == 0 {
if mt := srcs[0].Desc.MediaType; mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex {
switch srcs[0].Desc.MediaType {
// if the source is already an image index or manifest list, there is no need to consider the value
// of preferIndex since if set to true then the source is already in the preferred format, and if false
// it doesn't matter since we're not going to split it into separate manifests
case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex:
return dts[0], srcs[0].Desc, nil
default:
if !preferIndex {
return dts[0], srcs[0].Desc, nil
}
}
}