diff --git a/internal/image/docker_schema1_test.go b/internal/image/docker_schema1_test.go index 58f222b3c7..7f1bf9908e 100644 --- a/internal/image/docker_schema1_test.go +++ b/internal/image/docker_schema1_test.go @@ -269,6 +269,7 @@ func TestManifestSchema1EmbeddedDockerReferenceConflicts(t *testing.T) { } func TestManifestSchema1Inspect(t *testing.T) { + for _, m := range []genericManifest{ manifestSchema1FromFixture(t, "schema1.json"), manifestSchema1FromComponentsLikeFixture(t), @@ -276,6 +277,7 @@ func TestManifestSchema1Inspect(t *testing.T) { ii, err := m.Inspect(context.Background()) require.NoError(t, err) created := time.Date(2018, 1, 25, 0, 37, 48, 268558000, time.UTC) + var annotations map[string]string assert.Equal(t, types.ImageInspectInfo{ Tag: "latest", Created: &created, @@ -314,6 +316,40 @@ func TestManifestSchema1Inspect(t *testing.T) { "sha256:62e48e39dc5b30b75a97f05bccc66efbae6058b860ee20a5c9a184b9d5e25788", "sha256:e623934bca8d1a74f51014256445937714481e49343a31bda2bc5f534748184d", }, + LayersData: []types.ImageInspectLayer{{ + MIMEType: "", + Digest: "sha256:9cadd93b16ff2a0c51ac967ea2abfadfac50cfa3af8b5bf983d89b8f8647f3e4", + Size: -1, + Annotations: annotations, + }, { + MIMEType: "", + Digest: "sha256:4aa565ad8b7a87248163ce7dba1dd3894821aac97e846b932ff6b8ef9a8a508a", + Size: -1, + Annotations: annotations, + }, { + MIMEType: "", + Digest: "sha256:f576d102e09b9eef0e305aaef705d2d43a11bebc3fd5810a761624bd5e11997e", + Size: -1, + Annotations: annotations, + }, { + MIMEType: "", + Digest: "sha256:9e92df2aea7dc0baf5f1f8d509678d6a6306de27ad06513f8e218371938c07a6", + Size: -1, + Annotations: annotations, + }, { + MIMEType: "", + Digest: "sha256:62e48e39dc5b30b75a97f05bccc66efbae6058b860ee20a5c9a184b9d5e25788", + Size: -1, + Annotations: annotations, + }, + { + MIMEType: "", + Digest: "sha256:e623934bca8d1a74f51014256445937714481e49343a31bda2bc5f534748184d", + Size: -1, + Annotations: annotations, + }, + }, + Author: "", Env: []string{ "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "container=oci", diff --git a/internal/image/docker_schema2_test.go b/internal/image/docker_schema2_test.go index 56abf941e8..6606885256 100644 --- a/internal/image/docker_schema2_test.go +++ b/internal/image/docker_schema2_test.go @@ -256,6 +256,8 @@ func TestManifestSchema2Inspect(t *testing.T) { ii, err := m.Inspect(context.Background()) require.NoError(t, err) created := time.Date(2016, 9, 23, 23, 20, 45, 789764590, time.UTC) + + var annotations map[string]string assert.Equal(t, types.ImageInspectInfo{ Tag: "", Created: &created, @@ -270,6 +272,34 @@ func TestManifestSchema2Inspect(t *testing.T) { "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909", "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa", }, + LayersData: []types.ImageInspectLayer{{ + MIMEType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Digest: "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb", + Size: 51354364, + Annotations: annotations, + }, { + MIMEType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Digest: "sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c", + Size: 150, + Annotations: annotations, + }, { + MIMEType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Digest: "sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9", + Size: 11739507, + Annotations: annotations, + }, { + MIMEType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Digest: "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909", + Size: 8841833, + Annotations: annotations, + }, { + MIMEType: "application/vnd.docker.image.rootfs.diff.tar.gzip", + Digest: "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa", + Size: 291, + Annotations: annotations, + }, + }, + Author: "", Env: []string{ "PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HTTPD_PREFIX=/usr/local/apache2", diff --git a/internal/image/oci_test.go b/internal/image/oci_test.go index 7442299ba6..23450a53b4 100644 --- a/internal/image/oci_test.go +++ b/internal/image/oci_test.go @@ -275,7 +275,7 @@ func TestManifestOCI1EmbeddedDockerReferenceConflicts(t *testing.T) { func TestManifestOCI1Inspect(t *testing.T) { configJSON, err := os.ReadFile("fixtures/oci1-config.json") require.NoError(t, err) - + var annotations map[string]string m := manifestOCI1FromComponentsLikeFixture(configJSON) ii, err := m.Inspect(context.Background()) require.NoError(t, err) @@ -294,6 +294,34 @@ func TestManifestOCI1Inspect(t *testing.T) { "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909", "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa", }, + LayersData: []types.ImageInspectLayer{{ + MIMEType: "application/vnd.oci.image.layer.v1.tar+gzip", + Digest: "sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb", + Size: 51354364, + Annotations: annotations, + }, { + MIMEType: "application/vnd.oci.image.layer.v1.tar+gzip", + Digest: "sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c", + Size: 150, + Annotations: annotations, + }, { + MIMEType: "application/vnd.oci.image.layer.v1.tar+gzip", + Digest: "sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9", + Size: 11739507, + Annotations: annotations, + }, { + MIMEType: "application/vnd.oci.image.layer.v1.tar+gzip", + Digest: "sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909", + Size: 8841833, + Annotations: map[string]string{"test-annotation-2": "two"}, + }, { + MIMEType: "application/vnd.oci.image.layer.v1.tar+gzip", + Digest: "sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa", + Size: 291, + Annotations: annotations, + }, + }, + Author: "", Env: []string{ "PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HTTPD_PREFIX=/usr/local/apache2", diff --git a/manifest/common.go b/manifest/common.go index 9cf7dd3a94..5f352acc2f 100644 --- a/manifest/common.go +++ b/manifest/common.go @@ -228,3 +228,16 @@ func compressionVariantsRecognizeMIMEType(variantTable []compressionMIMETypeSet, variants := findCompressionMIMETypeSet(variantTable, mimeType) return variants != nil // Alternatively, this could be len(variants) > 1, but really the caller should ask about a specific algorithm. } + +// imgInspectLayersFromLayerInfos converts a list of layer infos, presumably obtained from a Manifest.LayerInfos() +// method call, into a format suitable for inclusion in a types.ImageInspectInfo structure. +func imgInspectLayersFromLayerInfos(infos []LayerInfo) []types.ImageInspectLayer { + layers := make([]types.ImageInspectLayer, len(infos)) + for i, info := range infos { + layers[i].MIMEType = info.MediaType + layers[i].Digest = info.Digest + layers[i].Size = info.Size + layers[i].Annotations = info.Annotations + } + return layers +} diff --git a/manifest/docker_schema1.go b/manifest/docker_schema1.go index e1f1fb9d98..9df9bc6673 100644 --- a/manifest/docker_schema1.go +++ b/manifest/docker_schema1.go @@ -221,13 +221,16 @@ func (m *Schema1) Inspect(_ func(types.BlobInfo) ([]byte, error)) (*types.ImageI if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), s1); err != nil { return nil, err } + layerInfos := m.LayerInfos() i := &types.ImageInspectInfo{ Tag: m.Tag, Created: &s1.Created, DockerVersion: s1.DockerVersion, Architecture: s1.Architecture, Os: s1.OS, - Layers: layerInfosToStrings(m.LayerInfos()), + Layers: layerInfosToStrings(layerInfos), + LayersData: imgInspectLayersFromLayerInfos(layerInfos), + Author: s1.Author, } if s1.Config != nil { i.Labels = s1.Config.Labels diff --git a/manifest/docker_schema2.go b/manifest/docker_schema2.go index e79d0851f2..a6bbdb3011 100644 --- a/manifest/docker_schema2.go +++ b/manifest/docker_schema2.go @@ -267,6 +267,7 @@ func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*t if err != nil { return nil, err } + layerInfos := m.LayerInfos() s2 := &Schema2Image{} if err := json.Unmarshal(config, s2); err != nil { return nil, err @@ -278,7 +279,9 @@ func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*t Architecture: s2.Architecture, Variant: s2.Variant, Os: s2.OS, - Layers: layerInfosToStrings(m.LayerInfos()), + Layers: layerInfosToStrings(layerInfos), + LayersData: imgInspectLayersFromLayerInfos(layerInfos), + Author: s2.Author, } if s2.Config != nil { i.Labels = s2.Config.Labels diff --git a/manifest/oci.go b/manifest/oci.go index fc325009ce..0674eb47b8 100644 --- a/manifest/oci.go +++ b/manifest/oci.go @@ -212,6 +212,7 @@ func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*type if err := json.Unmarshal(config, d1); err != nil { return nil, err } + layerInfos := m.LayerInfos() i := &types.ImageInspectInfo{ Tag: "", Created: v1.Created, @@ -219,8 +220,10 @@ func (m *OCI1) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*type Labels: v1.Config.Labels, Architecture: v1.Architecture, Os: v1.OS, - Layers: layerInfosToStrings(m.LayerInfos()), + Layers: layerInfosToStrings(layerInfos), + LayersData: imgInspectLayersFromLayerInfos(layerInfos), Env: v1.Config.Env, + Author: v1.Author, } return i, nil } diff --git a/types/types.go b/types/types.go index dcff8caf76..917465b3a7 100644 --- a/types/types.go +++ b/types/types.go @@ -466,6 +466,16 @@ type ImageInspectInfo struct { Os string Layers []string Env []string + LayersData []ImageInspectLayer + Author string +} + +//ImageInspectLayer is a set of metadata describing an image layers' detail +type ImageInspectLayer struct { + MIMEType string + Digest digest.Digest + Size int64 + Annotations map[string]string } // DockerAuthConfig contains authorization information for connecting to a registry.