Skip to content

copy: add InstancePlatforms field for platform-based filtering#656

Merged
mtrmac merged 1 commit intocontainers:mainfrom
aguidirh:sparse-manifest-platforms-pr1938
Mar 3, 2026
Merged

copy: add InstancePlatforms field for platform-based filtering#656
mtrmac merged 1 commit intocontainers:mainfrom
aguidirh:sparse-manifest-platforms-pr1938

Conversation

@aguidirh
Copy link
Copy Markdown
Contributor

@aguidirh aguidirh commented Feb 11, 2026

Add platform-based filtering for copying specific images

This PR adds the ability to select images by platform name (e.g., linux/amd64) instead of requiring digest hashes, implementing the functionality proposed in containers/image#1938.

Motivation

Relates to #227

When copying specific images from a multi-architecture manifest list, the current CopySpecificImages mode requires users to specify exact digest hashes in the Instances field. This is cumbersome because:

  1. Poor User Experience: Users must manually look up digest values for each platform
  2. Error-Prone: Easy to copy wrong digest or get confused about which digest corresponds to which platform
  3. Not Intuitive: Most users think in terms of "amd64" or "arm64", not "sha256:abc123..."

This PR adds a new InstancePlatforms field that allows users to specify platforms by human-readable OS and Architecture names.

Changes

1. New InstancePlatformFilter type and InstancePlatforms field

  • Added InstancePlatformFilter struct with OS and Architecture fields
  • Added InstancePlatforms []InstancePlatformFilter field to Options struct
  • Allows specifying platforms like {OS: "linux", Architecture: "amd64"}
  • Only supports OS and Architecture (not Variant, OSVersion, or OSFeatures)
  • Works alongside existing Instances field (both can be used simultaneously)

2. Platform resolution in determineSpecificImages()

  • New function that combines digest-based and platform-based selection
  • Iterates through all instances and copies ALL instances matching the specified OS/Architecture
  • This includes all compression variants (gzip, zstd, etc.) for a given platform
  • Returns deduplicated Set of digests from both sources
  • Clear error messages when requested platform doesn't exist (format: no instances found for platform OS/Architecture)

3. Efficient Set-based filtering

  • Refactored from slices.Contains() to Set-based lookup
  • Uses set.NewWithValues() for convenient initialization

4. Comprehensive test coverage

  • Added TestDetermineSpecificImages with table-driven tests
  • Tests platform-only, digest-only, and combined selection
  • Tests multi-compression scenarios (verifies ALL variants are copied)
  • Tests multi-variant scenarios (verifies ALL variants are copied)
  • Validates error handling for non-existent platforms
  • All existing tests continue to pass

User Experience Improvement

Before (digest-based only):

options := &copy.Options{
    ImageListSelection: copy.CopySpecificImages,
    Instances: []digest.Digest{
        "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",  // Which platform?
        "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",  // Which platform?
    },
}

After (platform-based):

options := &copy.Options{
    ImageListSelection: copy.CopySpecificImages,
    InstancePlatforms: []copy.InstancePlatformFilter{
        {OS: "linux", Architecture: "amd64"},
        {OS: "linux", Architecture: "ppc64le"},
    },
}

Combined (both methods):

options := &copy.Options{
    ImageListSelection: copy.CopySpecificImages,
    Instances:         []digest.Digest{specificDigest},      // When you know the exact digest
    InstancePlatforms: []copy.InstancePlatformFilter{        // When you know the platform
        {OS: "linux", Architecture: "arm64"},
    },
}

Multi-Compression Support

When a platform is specified, ALL instances matching that OS/Architecture are copied, including:

  • All compression variants (gzip, zstd, uncompressed, etc.)
  • All other variations of the same platform

This ensures that users get complete platform coverage without needing to understand the internal compression details.

API Design

The InstancePlatformFilter type only exposes OS and Architecture fields, making it impossible to set unsupported fields (like Variant) at compile time. This is safer than runtime validation and provides a clearer API.

Testing

All existing tests pass. New tests verify:

  • ✅ Platform-only selection
  • ✅ Digest-only selection (backward compatibility)
  • ✅ Combined platform and digest selection
  • ✅ Error handling for non-existent platforms
  • ✅ Set deduplication when same instance selected by both methods
  • ✅ Multi-compression scenarios (all variants copied)
  • ✅ Multi-variant scenarios (all variants copied)

Compatibility

  • Fully backward compatible - new optional field
  • ✅ Existing code using Instances field continues to work unchanged
  • ✅ No breaking changes to public API

Credits

This implementation is based on the original work by @nalind in containers/image#1938, adapted for the container-libs monorepo structure.

@github-actions github-actions Bot added the image Related to "image" package label Feb 11, 2026
@packit-as-a-service
Copy link
Copy Markdown

Packit jobs failed. @containers/packit-build please check.

1 similar comment
@packit-as-a-service
Copy link
Copy Markdown

Packit jobs failed. @containers/packit-build please check.

Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

An extremely brief look for now.

Comment thread image/copy/multiple.go Outdated
Comment thread image/copy/multiple_test.go Outdated
@TomSweeneyRedHat
Copy link
Copy Markdown
Member

I've approved this and restarted a couple of failng tests. I'd be interested in seeing your reply to @mtrmac 's comment on the multi-compression images.

Overall, a nice change, thanks!

Comment thread image/copy/multiple_test.go Outdated
Comment thread image/copy/multiple.go
@TomSweeneyRedHat
Copy link
Copy Markdown
Member

LGTM
and happy green test buttons.

@mtrmac
Copy link
Copy Markdown
Contributor

mtrmac commented Feb 26, 2026

#656 (comment) still needs addressing.

Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK to the implementation.

Please rebase, I think that should fix the Skopeo test failures.

Comment thread image/copy/multiple.go Outdated
Comment thread image/copy/multiple.go Outdated
Comment thread image/copy/multiple.go Outdated
Comment thread image/copy/multiple_test.go Outdated
Comment thread image/internal/set/set.go Outdated
Comment thread image/copy/multiple.go Outdated
Comment thread image/copy/multiple_test.go Outdated
Comment thread image/copy/multiple.go Outdated
@aguidirh aguidirh force-pushed the sparse-manifest-platforms-pr1938 branch from 8dd19fb to 630a079 Compare February 27, 2026 17:22
@aguidirh aguidirh changed the title copy: add InstancePlatforms field for platform-based filtering WIP: copy: add InstancePlatforms field for platform-based filtering Feb 27, 2026
Copy link
Copy Markdown
Contributor

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

LGTM; please squash to avoid the "address review feedback" commit messages.

@aguidirh aguidirh changed the title WIP: copy: add InstancePlatforms field for platform-based filtering copy: add InstancePlatforms field for platform-based filtering Mar 3, 2026
Add the ability to select images by platform name instead of requiring
digest hashes when copying specific images from multi-architecture
manifest lists.

When copying specific images using CopySpecificImages mode, users
previously had to specify exact digest hashes in the Instances field.
This was cumbersome and error-prone because users must manually look up
digest values and can easily confuse which digest corresponds to which
platform. Most users think in terms of "linux/amd64" or "linux/arm64",
not "sha256:abc123...".

This commit introduces a new InstancePlatforms field that allows users
to specify platforms by human-readable OS and Architecture combinations.
The field works alongside the existing Instances field, enabling both
digest-based and platform-based selection to be used together.

Key features:
- New InstancePlatformFilter type with OS and Architecture fields
- InstancePlatforms []InstancePlatformFilter field in Options struct
- determineSpecificImages() function resolves platforms to digests and
  combines with digest-based selection using efficient Set-based lookup
- Copies ALL instances matching the specified OS/Architecture, including
  all compression variants and other variations
- Fully backward compatible - existing Instances field continues to work
- Clear error messages when requested platform doesn't exist

Example usage:
  options := &copy.Options{
      ImageListSelection: copy.CopySpecificImages,
      InstancePlatforms: []copy.InstancePlatformFilter{
          {OS: "linux", Architecture: "amd64"},
          {OS: "linux", Architecture: "arm64"},
      },
  }

Based on original work by @nalind in containers/image#1938.

Relates to containers#227

Signed-off-by: Alex Guidi <aguidi@redhat.com>
@aguidirh aguidirh force-pushed the sparse-manifest-platforms-pr1938 branch from 2c20778 to af517b0 Compare March 3, 2026 14:45
@aguidirh
Copy link
Copy Markdown
Contributor Author

aguidirh commented Mar 3, 2026

Thanks!

LGTM; please squash to avoid the "address review feedback" commit messages.

All commits squashed as requested.

Please let me know if there is something pending before merging this PR.

@mtrmac mtrmac merged commit 8044c96 into containers:main Mar 3, 2026
24 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

image Related to "image" package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants