pkg/manifests.List: add SetSubject()/Subject()
Add methods for reading and writing the index-level "subject" field. Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
This commit is contained in:
parent
ba247016fa
commit
0f7852ef9b
|
@ -0,0 +1,29 @@
|
|||
package internal
|
||||
|
||||
import (
|
||||
v1 "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"golang.org/x/exp/maps"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// DeepCopyDescriptor copies a Descriptor, deeply copying its contents
|
||||
func DeepCopyDescriptor(original *v1.Descriptor) *v1.Descriptor {
|
||||
tmp := *original
|
||||
if original.URLs != nil {
|
||||
tmp.URLs = slices.Clone(original.URLs)
|
||||
}
|
||||
if original.Annotations != nil {
|
||||
tmp.Annotations = maps.Clone(original.Annotations)
|
||||
}
|
||||
if original.Data != nil {
|
||||
tmp.Data = slices.Clone(original.Data)
|
||||
}
|
||||
if original.Platform != nil {
|
||||
tmpPlatform := *original.Platform
|
||||
if original.Platform.OSFeatures != nil {
|
||||
tmpPlatform.OSFeatures = slices.Clone(original.Platform.OSFeatures)
|
||||
}
|
||||
tmp.Platform = &tmpPlatform
|
||||
}
|
||||
return &tmp
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/containers/common/internal"
|
||||
"github.com/containers/image/v5/manifest"
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
imgspec "github.com/opencontainers/image-spec/specs-go"
|
||||
|
@ -39,6 +40,8 @@ type List interface {
|
|||
MediaType(instanceDigest digest.Digest) (string, error)
|
||||
SetArtifactType(instanceDigest digest.Digest, artifactType string) error
|
||||
ArtifactType(instanceDigest digest.Digest) (string, error)
|
||||
SetSubject(subject *v1.Descriptor) error
|
||||
Subject() (*v1.Descriptor, error)
|
||||
Serialize(mimeType string) ([]byte, error)
|
||||
Instances() []digest.Digest
|
||||
OCIv1() *v1.Index
|
||||
|
@ -488,6 +491,26 @@ func (l *list) ArtifactType(instanceDigest digest.Digest) (string, error) {
|
|||
return oci.ArtifactType, nil
|
||||
}
|
||||
|
||||
// SetSubject sets the image index's subject.
|
||||
// The field is specific to the OCI image index format, and is not present in Docker manifest lists.
|
||||
func (l *list) SetSubject(subject *v1.Descriptor) error {
|
||||
if subject != nil {
|
||||
subject = internal.DeepCopyDescriptor(subject)
|
||||
}
|
||||
l.oci.Subject = subject
|
||||
return nil
|
||||
}
|
||||
|
||||
// Subject retrieves the subject which might have been set on the image index.
|
||||
// The field is specific to the OCI image index format, and is not present in Docker manifest lists.
|
||||
func (l *list) Subject() (*v1.Descriptor, error) {
|
||||
s := l.oci.Subject
|
||||
if s != nil {
|
||||
s = internal.DeepCopyDescriptor(s)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// FromBlob builds a list from an encoded manifest list or image index.
|
||||
func FromBlob(manifestBytes []byte) (List, error) {
|
||||
manifestType := manifest.GuessMIMEType(manifestBytes)
|
||||
|
|
|
@ -462,3 +462,43 @@ func TestPlatform(t *testing.T) {
|
|||
assert.NoError(t, list.SetOSFeatures(instanceDigest, []string{}))
|
||||
assert.Nil(t, list.OCIv1().Manifests[0].Platform, "expected platform to be nil")
|
||||
}
|
||||
|
||||
func TestSubject(t *testing.T) {
|
||||
bytes, err := os.ReadFile(ociFixture)
|
||||
if err != nil {
|
||||
t.Fatalf("error loading blob: %v", err)
|
||||
}
|
||||
list, err := FromBlob(bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing blob: %v", err)
|
||||
}
|
||||
for _, wrote := range []*v1.Descriptor{
|
||||
nil,
|
||||
{},
|
||||
{
|
||||
MediaType: v1.MediaTypeImageManifest,
|
||||
Digest: expectedInstance,
|
||||
Size: 1234,
|
||||
},
|
||||
} {
|
||||
err := list.SetSubject(wrote)
|
||||
if err != nil {
|
||||
t.Fatalf("error setting subject: %v", err)
|
||||
}
|
||||
b, err := list.Serialize("")
|
||||
if err != nil {
|
||||
t.Fatalf("error serializing list: %v", err)
|
||||
}
|
||||
list, err = FromBlob(b)
|
||||
if err != nil {
|
||||
t.Fatalf("error parsing list: %v", err)
|
||||
}
|
||||
read, err := list.Subject()
|
||||
if err != nil {
|
||||
t.Fatalf("error retrieving subject: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(read, wrote) {
|
||||
t.Fatalf("expected subject %v, got %v", wrote, read)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue