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 { if err != nil {
return err return err
} }

View File

@ -29,6 +29,7 @@ type createOptions struct {
dryrun bool dryrun bool
actionAppend bool actionAppend bool
progress string progress string
preferIndex bool
} }
func runCreate(ctx context.Context, dockerCli command.Cli, in createOptions, args []string) error { 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 { if err != nil {
return err 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.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.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.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 return cmd
} }

View File

@ -9,15 +9,16 @@ Create a new image based on source images
### Options ### Options
| Name | Type | Default | Description | | Name | Type | Default | Description |
|:---------------------------------|:--------------|:--------|:-----------------------------------------------------------------------------------------| |:---------------------------------|:--------------|:--------|:------------------------------------------------------------------------------------------------------------------------------|
| [`--annotation`](#annotation) | `stringArray` | | Add annotation to the image | | [`--annotation`](#annotation) | `stringArray` | | Add annotation to the image |
| [`--append`](#append) | | | Append to existing manifest | | [`--append`](#append) | | | Append to existing manifest |
| [`--builder`](#builder) | `string` | | Override the configured builder instance | | [`--builder`](#builder) | `string` | | Override the configured builder instance |
| [`--dry-run`](#dry-run) | | | Show final image instead of pushing | | [`--dry-run`](#dry-run) | | | Show final image instead of pushing |
| [`-f`](#file), [`--file`](#file) | `stringArray` | | Read source descriptor from file | | [`-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 | | `--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 |
| [`-t`](#tag), [`--tag`](#tag) | `stringArray` | | Set reference for new image | | `--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--> <!---MARKER_GEN_END-->
@ -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 Create a new manifest list based on source manifests. The source manifests can
be manifest lists or single platform distribution manifests and must already 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 exist in the registry where the new manifest is created.
specified, create performs a carbon copy.
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 ## Examples

View File

@ -78,6 +78,19 @@ func testImagetoolsCopyManifest(t *testing.T, sb integration.Sandbox) {
for i := range mfst.Layers { for i := range mfst.Layers {
require.Equal(t, mfst.Layers[i].Digest, mfst2.Layers[i].Digest) 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) { 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 { for i := range idx.Manifests {
require.Equal(t, idx.Manifests[i].Digest, idx2.Manifests[i].Digest) 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) { func testImagetoolsInspectAndFilter(t *testing.T, sb integration.Sandbox) {

View File

@ -29,7 +29,7 @@ type Source struct {
Ref reference.Named 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) eg, ctx := errgroup.WithContext(ctx)
dts := make([][]byte, len(srcs)) 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 // on single source, return original bytes
if len(srcs) == 1 && len(ann) == 0 { 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 return dts[0], srcs[0].Desc, nil
default:
if !preferIndex {
return dts[0], srcs[0].Desc, nil
}
} }
} }