Merge pull request #3959 from deitch/manifest-with-sboms

fix merging indexes in pkg manifest command
This commit is contained in:
Avi Deitcher 2023-11-22 04:23:40 -08:00 committed by GitHub
commit d1a0596bee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 6 deletions

View File

@ -94,6 +94,11 @@ func PushManifest(img string, options ...remote.Option) (hash string, length int
if err != nil {
return hash, length, fmt.Errorf("getting index digest: %w", err)
}
// if it is unchanged, do nothing
if desc != nil && desc.Digest == dig {
log.Debugf("not pushing manifest list for %s, unchanged", img)
return dig.String(), size, nil
}
log.Debugf("pushing manifest list for %s -> %#v", img, index)
err = remote.WriteIndex(baseRef, index, options...)
if err != nil {

View File

@ -4,6 +4,7 @@ import (
"fmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
)
const (
@ -14,12 +15,15 @@ const (
AnnotationSPDXDoc = "https://spdx.dev/Document"
)
// AppendIndex appends the elements of secondary ImageIndex into primary ImageIndex,
// returning the updated primary ImageIndex.
// AppendIndex creates a new ImageIndex composed of the merge of the elements of secondary ImageIndex
// and primary ImageIndex.
// In the case of conflicts, the primary ImageIndex wins.
// For example, if both have a manifest for a specific platform, then use the one from primary.
// The append is aware of the buildkit-style attestations, and will keep any attestations that point to a valid
// manifest in the list, discarding any that do not.
// If either of the two ImageIndexes is nil, the other is returned.
// If the secondary ImageIndex is a precise superset of primary,
// then the returned new ImageIndex is an identical copy of the secondary ImageIndex.
func AppendIndex(primary, secondary v1.ImageIndex) (v1.ImageIndex, error) {
primaryManifest, err := primary.IndexManifest()
if err != nil {
@ -35,10 +39,14 @@ func AppendIndex(primary, secondary v1.ImageIndex) (v1.ImageIndex, error) {
// 2. attestation - after all platforms, does it point to something in the updated index?
// If not, remove
if indexSuperset(primaryManifest, secondaryManifest) {
return secondary, nil
}
// make a map of all the digests already in the index, so we can know what is there
var (
manifestMap = map[v1.Hash]bool{}
platformMap = map[string]bool{}
adds []mutate.IndexAddendum
)
for _, m := range primaryManifest.Manifests {
if m.Platform == nil || m.Platform.Architecture == "" {
@ -63,7 +71,15 @@ func AppendIndex(primary, secondary v1.ImageIndex) (v1.ImageIndex, error) {
// we already have this one, so we can skip it
continue
}
primaryManifest.Manifests = append(primaryManifest.Manifests, m)
img, err := secondary.Image(m.Digest)
if err != nil {
return nil, fmt.Errorf("could not get image %s: %v", m.Digest, err)
}
adds = append(adds, mutate.IndexAddendum{
Add: img,
Descriptor: m,
})
// want to add manifest "m"
manifestMap[m.Digest] = true
}
@ -73,7 +89,7 @@ func AppendIndex(primary, secondary v1.ImageIndex) (v1.ImageIndex, error) {
// we either add them to the local index, or remove them if they are no longer valid
// we assume the ones in the local index are valid because they would have been generated now
for _, m := range secondaryManifest.Manifests {
if m.Platform == nil || m.Platform.Architecture != "unknown" || m.Platform.OS == "unknown" || m.Annotations == nil || m.Annotations[AnnotationDockerReferenceDigest] == "" {
if m.Platform == nil || m.Platform.Architecture != "unknown" || m.Platform.OS != "unknown" || m.Annotations == nil || m.Annotations[AnnotationDockerReferenceDigest] == "" {
continue
}
// if we already have this one, we are good
@ -90,8 +106,34 @@ func AppendIndex(primary, secondary v1.ImageIndex) (v1.ImageIndex, error) {
if _, ok := manifestMap[dig]; !ok {
continue
}
primaryManifest.Manifests = append(primaryManifest.Manifests, m)
img, err := secondary.Image(m.Digest)
if err != nil {
return nil, fmt.Errorf("could not get image %s: %v", m.Digest, err)
}
adds = append(adds, mutate.IndexAddendum{
Add: img,
Descriptor: m,
})
// want to add manifest "m"
manifestMap[m.Digest] = true
}
return primary, nil
ret := mutate.AppendManifests(primary, adds...)
return ret, nil
}
func indexSuperset(inner, outer *v1.IndexManifest) bool {
var manifestMap = map[v1.Hash]bool{}
if len(inner.Manifests) > len(outer.Manifests) {
return false
}
for _, m := range outer.Manifests {
manifestMap[m.Digest] = true
}
for _, m := range inner.Manifests {
if _, ok := manifestMap[m.Digest]; !ok {
return false
}
}
return true
}