Skip to content

Commit

Permalink
enhance skopeo inspect
Browse files Browse the repository at this point in the history
Signed-off-by: ningmingxiao <[email protected]>
  • Loading branch information
ningmingxiao committed Jul 20, 2022
1 parent 2bb3f3e commit 53278c4
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 96 deletions.
109 changes: 62 additions & 47 deletions internal/image/docker_schema1_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,56 +273,71 @@ func TestManifestSchema1Inspect(t *testing.T) {
manifestSchema1FromFixture(t, "schema1.json"),
manifestSchema1FromComponentsLikeFixture(t),
} {

labels := map[string]string{
"Kolla-SHA": "5.0.0-39-g6f1b947b",
"architecture": "x86_64",
"authoritative-source-url": "registry.access.redhat.com",
"build-date": "2018-01-25T00:32:27.807261",
"com.redhat.build-host": "ip-10-29-120-186.ec2.internal",
"com.redhat.component": "openstack-nova-api-docker",
"description": "Red Hat OpenStack Platform 12.0 nova-api",
"distribution-scope": "public",
"io.k8s.description": "Red Hat OpenStack Platform 12.0 nova-api",
"io.k8s.display-name": "Red Hat OpenStack Platform 12.0 nova-api",
"io.openshift.tags": "rhosp osp openstack osp-12.0",
"kolla_version": "stable/pike",
"name": "rhosp12/openstack-nova-api",
"release": "20180124.1",
"summary": "Red Hat OpenStack Platform 12.0 nova-api",
"tripleo-common_version": "7.6.3-23-g4891cfe",
"url": "https://access.redhat.com/containers/#/registry.access.redhat.com/rhosp12/openstack-nova-api/images/12.0-20180124.1",
"vcs-ref": "9b31243b7b448eb2fc3b6e2c96935b948f806e98",
"vcs-type": "git",
"vendor": "Red Hat, Inc.",
"version": "12.0",
"version-release": "12.0-20180124.1",
}

Layers := []string{
"sha256:9cadd93b16ff2a0c51ac967ea2abfadfac50cfa3af8b5bf983d89b8f8647f3e4",
"sha256:4aa565ad8b7a87248163ce7dba1dd3894821aac97e846b932ff6b8ef9a8a508a",
"sha256:f576d102e09b9eef0e305aaef705d2d43a11bebc3fd5810a761624bd5e11997e",
"sha256:9e92df2aea7dc0baf5f1f8d509678d6a6306de27ad06513f8e218371938c07a6",
"sha256:62e48e39dc5b30b75a97f05bccc66efbae6058b860ee20a5c9a184b9d5e25788",
"sha256:e623934bca8d1a74f51014256445937714481e49343a31bda2bc5f534748184d",
}

Env := []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"container=oci",
"KOLLA_BASE_DISTRO=rhel",
"KOLLA_INSTALL_TYPE=binary",
"KOLLA_INSTALL_METATYPE=rhos",
"PS1=$(tput bold)($(printenv KOLLA_SERVICE_NAME))$(tput sgr0)[$(id -un)@$(hostname -s) $(pwd)]$ ",
}

ii, err := m.Inspect(context.Background())
require.NoError(t, err)
created := time.Date(2018, 1, 25, 0, 37, 48, 268558000, time.UTC)
assert.Equal(t, types.ImageInspectInfo{
Tag: "latest",
Created: &created,
DockerVersion: "1.12.6",
Labels: map[string]string{
"Kolla-SHA": "5.0.0-39-g6f1b947b",
"architecture": "x86_64",
"authoritative-source-url": "registry.access.redhat.com",
"build-date": "2018-01-25T00:32:27.807261",
"com.redhat.build-host": "ip-10-29-120-186.ec2.internal",
"com.redhat.component": "openstack-nova-api-docker",
"description": "Red Hat OpenStack Platform 12.0 nova-api",
"distribution-scope": "public",
"io.k8s.description": "Red Hat OpenStack Platform 12.0 nova-api",
"io.k8s.display-name": "Red Hat OpenStack Platform 12.0 nova-api",
"io.openshift.tags": "rhosp osp openstack osp-12.0",
"kolla_version": "stable/pike",
"name": "rhosp12/openstack-nova-api",
"release": "20180124.1",
"summary": "Red Hat OpenStack Platform 12.0 nova-api",
"tripleo-common_version": "7.6.3-23-g4891cfe",
"url": "https://access.redhat.com/containers/#/registry.access.redhat.com/rhosp12/openstack-nova-api/images/12.0-20180124.1",
"vcs-ref": "9b31243b7b448eb2fc3b6e2c96935b948f806e98",
"vcs-type": "git",
"vendor": "Red Hat, Inc.",
"version": "12.0",
"version-release": "12.0-20180124.1",
},
Architecture: "amd64",
Os: "linux",
Layers: []string{
"sha256:9cadd93b16ff2a0c51ac967ea2abfadfac50cfa3af8b5bf983d89b8f8647f3e4",
"sha256:4aa565ad8b7a87248163ce7dba1dd3894821aac97e846b932ff6b8ef9a8a508a",
"sha256:f576d102e09b9eef0e305aaef705d2d43a11bebc3fd5810a761624bd5e11997e",
"sha256:9e92df2aea7dc0baf5f1f8d509678d6a6306de27ad06513f8e218371938c07a6",
"sha256:62e48e39dc5b30b75a97f05bccc66efbae6058b860ee20a5c9a184b9d5e25788",
"sha256:e623934bca8d1a74f51014256445937714481e49343a31bda2bc5f534748184d",
},
Env: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"container=oci",
"KOLLA_BASE_DISTRO=rhel",
"KOLLA_INSTALL_TYPE=binary",
"KOLLA_INSTALL_METATYPE=rhos",
"PS1=$(tput bold)($(printenv KOLLA_SERVICE_NAME))$(tput sgr0)[$(id -un)@$(hostname -s) $(pwd)]$ ",
},
}, *ii)
assert.Equal(t, "latest", ii.Tag)
assert.Equal(t, &created, ii.Created)
assert.Equal(t, "1.12.6", ii.DockerVersion)
assert.Equal(t, labels, ii.Labels)
assert.Equal(t, "amd64", ii.Architecture)
assert.Equal(t, "linux", ii.Os)
assert.Equal(t, Layers, ii.Layers)
assert.Equal(t, Env, ii.Env)
assert.NotEqual(t, nil, ii.Config)
assert.Equal(t, int64(0), ii.Size)
assert.Equal(t, "", ii.Author)
for _, layer := range ii.LayersDetail {
assert.NotEqual(t, nil, layer)
}
assert.Equal(t, "", ii.Author)
for _, history := range ii.History {
assert.NotEqual(t, nil, history)
}
}
}

Expand Down
57 changes: 34 additions & 23 deletions internal/image/docker_schema2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -256,30 +256,41 @@ 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)
assert.Equal(t, types.ImageInspectInfo{
Tag: "",
Created: &created,
DockerVersion: "1.12.1",
Labels: map[string]string{},
Architecture: "amd64",
Os: "linux",
Layers: []string{
"sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
"sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c",
"sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9",
"sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909",
"sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa",
},
Env: []string{
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.23",
"HTTPD_SHA1=5101be34ac4a509b245adb70a56690a84fcc4e7f",
"HTTPD_BZ2_URL=https://www.apache.org/dyn/closer.cgi?action=download&filename=httpd/httpd-2.4.23.tar.bz2",
"HTTPD_ASC_URL=https://www.apache.org/dist/httpd/httpd-2.4.23.tar.bz2.asc",
},
}, *ii)
layers := []string{
"sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
"sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c",
"sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9",
"sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909",
"sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa",
}

env := []string{
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.23",
"HTTPD_SHA1=5101be34ac4a509b245adb70a56690a84fcc4e7f",
"HTTPD_BZ2_URL=https://www.apache.org/dyn/closer.cgi?action=download&filename=httpd/httpd-2.4.23.tar.bz2",
"HTTPD_ASC_URL=https://www.apache.org/dist/httpd/httpd-2.4.23.tar.bz2.asc",
}
assert.Equal(t, "", ii.Tag)
assert.Equal(t, &created, ii.Created)
assert.Equal(t, layers, ii.Layers)

assert.Equal(t, "1.12.1", ii.DockerVersion)
assert.Equal(t, map[string]string{}, ii.Labels)
assert.Equal(t, "amd64", ii.Architecture)
assert.Equal(t, "linux", ii.Os)
assert.Equal(t, layers, ii.Layers)
assert.Equal(t, env, ii.Env)
assert.NotEqual(t, nil, ii.Config)
assert.Equal(t, int64(0), ii.Size)
assert.Equal(t, "", ii.Author)
for _, layer := range ii.LayersDetail {
assert.NotEqual(t, nil, layer)
}
for _, history := range ii.History {
assert.NotEqual(t, nil, history)
}
// nil configBlob will trigger an error in m.ConfigBlob()
m = manifestSchema2FromComponentsLikeFixture(nil)
_, err = m.Inspect(context.Background())
Expand Down
60 changes: 37 additions & 23 deletions internal/image/oci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,30 +281,44 @@ func TestManifestOCI1Inspect(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)
assert.Equal(t, types.ImageInspectInfo{
Tag: "",
Created: &created,
DockerVersion: "1.12.1",
Labels: map[string]string{},
Architecture: "amd64",
Os: "linux",
Layers: []string{
"sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
"sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c",
"sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9",
"sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909",
"sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa",
},
Env: []string{
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.23",
"HTTPD_SHA1=5101be34ac4a509b245adb70a56690a84fcc4e7f",
"HTTPD_BZ2_URL=https://www.apache.org/dyn/closer.cgi?action=download&filename=httpd/httpd-2.4.23.tar.bz2",
"HTTPD_ASC_URL=https://www.apache.org/dist/httpd/httpd-2.4.23.tar.bz2.asc",
},
}, *ii)

layers := []string{
"sha256:6a5a5368e0c2d3e5909184fa28ddfd56072e7ff3ee9a945876f7eee5896ef5bb",
"sha256:1bbf5d58d24c47512e234a5623474acf65ae00d4d1414272a893204f44cc680c",
"sha256:8f5dc8a4b12c307ac84de90cdd9a7f3915d1be04c9388868ca118831099c67a9",
"sha256:bbd6b22eb11afce63cc76f6bc41042d99f10d6024c96b655dafba930b8d25909",
"sha256:960e52ecf8200cbd84e70eb2ad8678f4367e50d14357021872c10fa3fc5935fa",
}

env := []string{
"PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HTTPD_PREFIX=/usr/local/apache2",
"HTTPD_VERSION=2.4.23",
"HTTPD_SHA1=5101be34ac4a509b245adb70a56690a84fcc4e7f",
"HTTPD_BZ2_URL=https://www.apache.org/dyn/closer.cgi?action=download&filename=httpd/httpd-2.4.23.tar.bz2",
"HTTPD_ASC_URL=https://www.apache.org/dist/httpd/httpd-2.4.23.tar.bz2.asc",
}

assert.Equal(t, "", ii.Tag)
assert.Equal(t, &created, ii.Created)
assert.Equal(t, layers, ii.Layers)

assert.Equal(t, "1.12.1", ii.DockerVersion)
assert.Equal(t, map[string]string{}, ii.Labels)
assert.Equal(t, "amd64", ii.Architecture)
assert.Equal(t, "linux", ii.Os)
assert.Equal(t, layers, ii.Layers)
assert.Equal(t, env, ii.Env)
assert.NotEqual(t, nil, ii.Config)
assert.Equal(t, int64(-1), ii.Size)
assert.Equal(t, "", ii.Author)

for _, layer := range ii.LayersDetail {
assert.NotEqual(t, nil, layer)
}
for _, history := range ii.History {
assert.NotEqual(t, nil, history)
}
// nil configBlob will trigger an error in m.ConfigBlob()
m = manifestOCI1FromComponentsLikeFixture(nil)
_, err = m.Inspect(context.Background())
Expand Down
26 changes: 26 additions & 0 deletions manifest/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

compressiontypes "github.com/containers/image/v5/pkg/compression/types"
"github.com/containers/image/v5/types"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -228,3 +229,28 @@ 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.LayerDetail {
layers := make([]types.LayerDetail, 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
}

func schema2HistoryToV1History(history []Schema2History) []v1.History {
v1History := make([]v1.History, len(history))
for index, value := range history {
v1History[index].Created = &value.Created
v1History[index].Author = value.Author
v1History[index].CreatedBy = value.CreatedBy
v1History[index].Comment = value.Comment
v1History[index].EmptyLayer = value.EmptyLayer
}
return v1History
}
38 changes: 37 additions & 1 deletion manifest/docker_schema1.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,23 +215,59 @@ func validateV1ID(id string) error {
return nil
}

type schema2Image struct {
Schema2V1Image
Parent digest.Digest `json:"parent,omitempty"`
RootFS *Schema2RootFS `json:"rootfs,omitempty"`
History []Schema2History `json:"history,omitempty"`
OSVersion string `json:"os.version,omitempty"`
OSFeatures []string `json:"os.features,omitempty"`
}

// Inspect returns various information for (skopeo inspect) parsed from the manifest and configuration.
func (m *Schema1) Inspect(_ func(types.BlobInfo) ([]byte, error)) (*types.ImageInspectInfo, error) {
s1 := &Schema2V1Image{}
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),
LayersDetail: imgInspectLayersFromLayerInfos(layerInfos),
Author: s1.Author,
Size: s1.Size,
}

diffIDs := []digest.Digest{digest.FromString(s1.ID)}
schema2Config, err := m.ToSchema2Config(diffIDs)
if err != nil {
return nil, err
}
imageConfig := &schema2Image{}
if err := json.Unmarshal(schema2Config, imageConfig); err != nil {
return nil, err
}
i.History = schema2HistoryToV1History(imageConfig.History)
if s1.Config != nil {
i.Labels = s1.Config.Labels
i.Env = s1.Config.Env
i.Config.Env = s1.Config.Env
i.Config.Labels = s1.Config.Labels
i.Config.User = s1.Config.User
i.Config.Volumes = s1.Config.Volumes
i.Config.Entrypoint = s1.Config.Entrypoint
for key, value := range s1.Config.ExposedPorts {
exposedPorts := make(map[string]struct{})
exposedPorts[string(key)] = value
i.Config.ExposedPorts = exposedPorts
}
i.Config.StopSignal = s1.Config.StopSignal
i.Config.WorkingDir = s1.Config.WorkingDir
}
return i, nil
}
Expand Down
19 changes: 18 additions & 1 deletion manifest/docker_schema2.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,18 +271,35 @@ func (m *Schema2) Inspect(configGetter func(types.BlobInfo) ([]byte, error)) (*t
if err := json.Unmarshal(config, s2); err != nil {
return nil, err
}
layerInfos := m.LayerInfos()
i := &types.ImageInspectInfo{
Tag: "",
Created: &s2.Created,
DockerVersion: s2.DockerVersion,
Architecture: s2.Architecture,
Variant: s2.Variant,
Os: s2.OS,
Layers: layerInfosToStrings(m.LayerInfos()),
Layers: layerInfosToStrings(layerInfos),
LayersDetail: imgInspectLayersFromLayerInfos(layerInfos),
History: schema2HistoryToV1History(s2.History),
Author: s2.Author,
Size: s2.Size,
}
if s2.Config != nil {
i.Labels = s2.Config.Labels
i.Env = s2.Config.Env
i.Config.Env = s2.Config.Env
i.Config.Labels = s2.Config.Labels
i.Config.User = s2.Config.User
i.Config.Volumes = s2.Config.Volumes
i.Config.Entrypoint = s2.Config.Entrypoint
for key, value := range s2.Config.ExposedPorts {
exposedPorts := make(map[string]struct{})
exposedPorts[string(key)] = value
i.Config.ExposedPorts = exposedPorts
}
i.Config.StopSignal = s2.Config.StopSignal
i.Config.WorkingDir = s2.Config.WorkingDir
}
return i, nil
}
Expand Down
Loading

0 comments on commit 53278c4

Please sign in to comment.