manifest_list: inspect add fields from both OCIv1 and docker format
ManifestInspect should contain all known formats for a valid manifest
list as of now only supported formats are `OCIv1` and `Docker` so
inspect should support fields from `OCIv1` format as well. Following
commit adds a new field to inspect i.e `Annotations` from `OCIv1`.
Example output from podman
```console
podman manifest inspect test
{
"schemaVersion": 2,
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
"manifests": [
{
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
"size": 528,
"digest": "sha256:9b2a28eb47540823042a2ba401386845089bb7b62a9637d55816132c4c3c36eb",
"platform": {
"architecture": "amd64",
"os": "linux"
},
"annotations": {
"annotationTest1": "annotationTest2"
}
}
]
}
```
Closes: https://github.com/containers/podman/issues/15069
Signed-off-by: Aditya R <arajan@redhat.com>
This commit is contained in:
parent
fe80e493d1
commit
975a5798cc
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/containers/image/v5/transports/alltransports"
|
||||
"github.com/containers/image/v5/types"
|
||||
"github.com/containers/storage"
|
||||
structcopier "github.com/jinzhu/copier"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
|
|
@ -39,6 +40,28 @@ type ManifestList struct {
|
|||
list manifests.List
|
||||
}
|
||||
|
||||
// ManifestListDescriptor references a platform-specific manifest.
|
||||
// Contains exclusive field like `annotations` which is only present in
|
||||
// OCI spec and not in docker image spec.
|
||||
type ManifestListDescriptor struct {
|
||||
manifest.Schema2Descriptor
|
||||
Platform manifest.Schema2PlatformSpec `json:"platform"`
|
||||
// Annotations contains arbitrary metadata for the image index.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// ManifestListData is a list of platform-specific manifests, specifically used to
|
||||
// generate output struct for `podman manifest inspect`. Reason for maintaining and
|
||||
// having this type is to ensure we can have a common type which contains exclusive
|
||||
// fields from both Docker manifest format and OCI manifest format.
|
||||
type ManifestListData struct {
|
||||
SchemaVersion int `json:"schemaVersion"`
|
||||
MediaType string `json:"mediaType"`
|
||||
Manifests []ManifestListDescriptor `json:"manifests"`
|
||||
// Annotations contains arbitrary metadata for the image index.
|
||||
Annotations map[string]string `json:"annotations,omitempty"`
|
||||
}
|
||||
|
||||
// ID returns the ID of the manifest list.
|
||||
func (m *ManifestList) ID() string {
|
||||
return m.image.ID()
|
||||
|
|
@ -210,8 +233,21 @@ func (i *Image) IsManifestList(ctx context.Context) (bool, error) {
|
|||
}
|
||||
|
||||
// Inspect returns a dockerized version of the manifest list.
|
||||
func (m *ManifestList) Inspect() (*manifest.Schema2List, error) {
|
||||
return m.list.Docker(), nil
|
||||
func (m *ManifestList) Inspect() (*ManifestListData, error) {
|
||||
inspectList := ManifestListData{}
|
||||
dockerFormat := m.list.Docker()
|
||||
err := structcopier.Copy(&inspectList, &dockerFormat)
|
||||
if err != nil {
|
||||
return &inspectList, err
|
||||
}
|
||||
// Get missing annotation field from OCIv1 Spec
|
||||
// and populate inspect data.
|
||||
ociFormat := m.list.OCIv1()
|
||||
inspectList.Annotations = ociFormat.Annotations
|
||||
for i, manifest := range ociFormat.Manifests {
|
||||
inspectList.Manifests[i].Annotations = manifest.Annotations
|
||||
}
|
||||
return &inspectList, nil
|
||||
}
|
||||
|
||||
// Options for adding a manifest list.
|
||||
|
|
|
|||
|
|
@ -39,6 +39,44 @@ func TestCreateManifestList(t *testing.T) {
|
|||
require.True(t, errors.Is(err, ErrNotAManifestList))
|
||||
}
|
||||
|
||||
// Inspect must contain both formats i.e OCIv1 and docker
|
||||
func TestInspectManifestListWithAnnotations(t *testing.T) {
|
||||
listName := "testinspect"
|
||||
runtime, cleanup := testNewRuntime(t)
|
||||
defer cleanup()
|
||||
ctx := context.Background()
|
||||
|
||||
list, err := runtime.CreateManifestList(listName)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, list)
|
||||
|
||||
manifestListOpts := &ManifestListAddOptions{All: true}
|
||||
_, err = list.Add(ctx, "docker://busybox", manifestListOpts)
|
||||
require.NoError(t, err)
|
||||
|
||||
list, err = runtime.LookupManifestList(listName)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, list)
|
||||
|
||||
inspectReport, err := list.Inspect()
|
||||
// get digest of the first instance
|
||||
digest := inspectReport.Manifests[0].Digest
|
||||
require.NoError(t, err)
|
||||
|
||||
annotateOptions := ManifestListAnnotateOptions{}
|
||||
annotations := make(map[string]string)
|
||||
annotations["hello"] = "world"
|
||||
annotateOptions.Annotations = annotations
|
||||
|
||||
err = list.AnnotateInstance(digest, &annotateOptions)
|
||||
require.NoError(t, err)
|
||||
// Inspect list again
|
||||
inspectReport, err = list.Inspect()
|
||||
require.NoError(t, err)
|
||||
// verify annotation
|
||||
require.Equal(t, inspectReport.Manifests[0].Annotations, annotations)
|
||||
}
|
||||
|
||||
// Following test ensure that `Tag` tags the manifest list instead of resolved image.
|
||||
// Both the tags should point to same image id
|
||||
func TestCreateAndTagManifestList(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue