Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --prefer-index flag forimagetools create on a single source #2482

Merged
merged 6 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
4 changes: 3 additions & 1 deletion commands/imagetools/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
28 changes: 17 additions & 11 deletions docs/reference/buildx_imagetools_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ 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 |
| `--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 |
| 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 |


<!---MARKER_GEN_END-->
Expand All @@ -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

Expand Down
31 changes: 31 additions & 0 deletions tests/imagetools.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
12 changes: 10 additions & 2 deletions util/imagetools/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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
}
}
}

Expand Down
Loading