Skip to content

Commit

Permalink
manifest_list: inspect add fields from both OCIv1 and docker format
Browse files Browse the repository at this point in the history
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: containers/podman#15069

Signed-off-by: Aditya R <[email protected]>
  • Loading branch information
flouthoc committed Jul 29, 2022
1 parent a043189 commit cf35219
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 2 deletions.
40 changes: 38 additions & 2 deletions libimage/manifest_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand All @@ -39,6 +40,28 @@ type ManifestList struct {
list manifests.List
}

// InspectListDescriptor references a platform-specific manifest.
// Contains exclusive field like `annotations` which is only present in
// OCI spec and not in docker image spec.
type InspectListDescriptor struct {
manifest.Schema2Descriptor
Platform manifest.Schema2PlatformSpec `json:"platform"`
// Annotations contains arbitrary metadata for the image index.
Annotations map[string]string `json:"annotations,omitempty"`
}

// InspectListInfo 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 InspectListInfo struct {
SchemaVersion int `json:"schemaVersion"`
MediaType string `json:"mediaType"`
Manifests []InspectListDescriptor `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()
Expand Down Expand Up @@ -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() (*InspectListInfo, error) {
inspectList := InspectListInfo{}
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.
Expand Down
44 changes: 44 additions & 0 deletions libimage/manifest_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,50 @@ 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)
require.NotNil(t, inspectReport)

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)
require.NotNil(t, inspectReport)
// verify annotation
inspectReportJSON, err := json.Marshal(inspectReport)
require.NoError(t, err)
inspectReportString := string(inspectReportJSON)
require.Contains(t, inspectReportString, "hello")
require.Contains(t, inspectReportString, "world")
}

// 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) {
Expand Down

0 comments on commit cf35219

Please sign in to comment.