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

support copy multi arch instance #2612

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

cleverhu
Copy link

support copy multi arch instance

Copy link
Collaborator

@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.

For now just a quick skim. Primarily note that we must not break API.

Note the existence of previous #1707 , #1938 , those probably discuss relevant concerns. I didn’t now go back to re-visit either of them.

@@ -98,8 +99,65 @@ func validateCompressionVariantExists(input []OptionCompressionVariant) error {
return nil
}

func isPlatformSupported(list internalManifest.List, platform manifest.Schema2PlatformSpec) (digest.Digest, bool) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It’s unexpected for a predicate-named function is… to return a non-boolean value.

if digest, ok := isPlatformSupported(list, platform); !ok {
missingPlatforms = append(missingPlatforms, platform)
} else {
supportedInstance = append(supportedInstance, digest)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is insufficient; there can be multiple instances for the same platform, and in that case, by default, all of them should be copied. (Compare EnsureCompressionVariantsExist).

Copy link
Author

Choose a reason for hiding this comment

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

I am simulating Docker buildx with this parameter, and the examples passed in are linux/amd64,linux/arm64。If user need to copy all instance, they need to add such as linux/arm64,linux/arm/v6

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don’t think that’s applicable. The manifest can, legitimately, contain two instances with exactly the same platform specification.

return nil, fmt.Errorf("requested platforms not found in image: %s", strings.Join(platformStrings, ", "))
}

if len(platforms) == 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

(If this were a special case, I’d expect it to be handled at the top, before starting the other logic.)

// prepareInstanceCopies prepares a list of instances which needs to copied to the manifest list.
func prepareInstanceCopies(list internalManifest.List, instanceDigests []digest.Digest, options *Options) ([]instanceCopy, error) {
filteredInstanceDigests, err := filterInstancesByPlatforms(list, options.ImageListPlatforms)
Copy link
Collaborator

Choose a reason for hiding this comment

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

The CopySpecificImages logic exists at the start of the existing range instanceDigest loop; splitting that into two separate locations is unexpected.


return supportedInstance, nil
}

// prepareInstanceCopies prepares a list of instances which needs to copied to the manifest list.
func prepareInstanceCopies(list internalManifest.List, instanceDigests []digest.Digest, options *Options) ([]instanceCopy, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

prepareInstanceCopies exists, to a large extent, to be a strictly isolated ~functional piece of code that can be unit tested; the option handling, especially the way various options can interact, should have unit tests.

@@ -285,6 +346,21 @@ func (c *copier) copyMultipleImages(ctx context.Context) (copiedManifest []byte,
return nil, fmt.Errorf("updating manifest list: %w", err)
}

if len(c.options.Instances) > 0 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I’d expect this logic to be driven by prepareInstanceCopies, therefore unit-testable, and unit-tested.

Comment on lines +349 to +363
if len(c.options.Instances) > 0 {
deletedInstanceDigests := []internalManifest.ListEdit{}
for _, instanceDigest := range updatedList.Instances() {
if !slices.Contains(c.options.Instances, instanceDigest) {
deletedInstanceDigests = append(deletedInstanceDigests, internalManifest.ListEdit{
ListOperation: internalManifest.ListOpRemove,
UpdateOldDigest: instanceDigest,
})
}
}
if err = updatedList.EditInstances(deletedInstanceDigests); err != nil {
return nil, fmt.Errorf("updating manifest list: %w", err)
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

We outright must not change the semantics of the existing Instances option to trigger manifest edits. c/image keeps a stable API, if at all possible.

if targetIndex == -1 {
return fmt.Errorf("Schema2List.EditInstances: digest %s not found", editInstance.UpdateOldDigest)
}
index.Manifests = append(index.Manifests[:targetIndex], index.Manifests[targetIndex+1:]...)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should use some form of slices.Delete*. And have a test.

if targetIndex == -1 {
return fmt.Errorf("OCI1Index.EditInstances: digest %s not found", editInstance.UpdateOldDigest)
}
index.Manifests = append(index.Manifests[:targetIndex], index.Manifests[targetIndex+1:]...)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This should use some form of slices.Delete*. And have a test.

if err != nil {
return nil, err
}
options.Instances = filteredInstanceDigests
Copy link
Collaborator

Choose a reason for hiding this comment

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

Outright overwriting and ignoring previously-defined options is not acceptable.

@mtrmac mtrmac added the kind/feature A request for, or a PR adding, new functionality label Oct 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/feature A request for, or a PR adding, new functionality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants