mirror of
https://github.com/project-zot/zot.git
synced 2026-06-16 04:17:55 +08:00
feat(cli): updated display format for multiarch images (#1268)
Signed-off-by: Laurentiu Niculae <niculae.laurentiu1@gmail.com>
This commit is contained in:
+11
-7
@@ -326,12 +326,14 @@ func fetchImageIndexStruct(ctx context.Context, job *httpJob) (*imageStruct, err
|
||||
isNotationSigned(ctx, job.imageName, indexDigest, job.config, job.username, job.password)
|
||||
|
||||
return &imageStruct{
|
||||
verbose: *job.config.verbose,
|
||||
RepoName: job.imageName,
|
||||
Tag: job.tagName,
|
||||
Digest: indexDigest,
|
||||
MediaType: ispec.MediaTypeImageIndex,
|
||||
Manifests: manifestList,
|
||||
Size: strconv.FormatInt(imageSize, 10),
|
||||
IsSigned: isIndexSigned,
|
||||
Manifests: manifestList,
|
||||
verbose: *job.config.verbose,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -351,14 +353,16 @@ func fetchImageManifestStruct(ctx context.Context, job *httpJob) (*imageStruct,
|
||||
}
|
||||
|
||||
return &imageStruct{
|
||||
verbose: *job.config.verbose,
|
||||
RepoName: job.imageName,
|
||||
Tag: job.tagName,
|
||||
Size: manifest.Size,
|
||||
IsSigned: manifest.IsSigned,
|
||||
RepoName: job.imageName,
|
||||
Tag: job.tagName,
|
||||
Digest: manifest.Digest,
|
||||
MediaType: ispec.MediaTypeImageManifest,
|
||||
Manifests: []manifestStruct{
|
||||
manifest,
|
||||
},
|
||||
Size: manifest.Size,
|
||||
IsSigned: manifest.IsSigned,
|
||||
verbose: *job.config.verbose,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
@@ -264,6 +265,7 @@ func TestDoHTTPRequest(t *testing.T) {
|
||||
vars := mux.Vars(req)
|
||||
|
||||
if vars["reference"] == "indexRef" {
|
||||
writer.Header().Add("docker-content-digest", godigest.FromString("t").String())
|
||||
_, err := writer.Write([]byte(`
|
||||
{
|
||||
"manifests": [
|
||||
@@ -592,6 +594,7 @@ func TestDoJobErrors(t *testing.T) {
|
||||
Route: "/v2/{name}/manifests/{reference}",
|
||||
HandlerFunc: func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", ispec.MediaTypeImageIndex)
|
||||
w.Header().Add("docker-content-digest", godigest.FromString("t").String())
|
||||
|
||||
_, err := w.Write([]byte(""))
|
||||
if err != nil {
|
||||
@@ -606,6 +609,8 @@ func TestDoJobErrors(t *testing.T) {
|
||||
vars := mux.Vars(req)
|
||||
|
||||
if vars["reference"] == "indexRef" {
|
||||
writer.Header().Add("docker-content-digest", godigest.FromString("t").String())
|
||||
|
||||
_, err := writer.Write([]byte(`{"manifests": [{"digest": "manifestRef"}]}`))
|
||||
if err != nil {
|
||||
return
|
||||
@@ -613,6 +618,8 @@ func TestDoJobErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
if vars["reference"] == "manifestRef" {
|
||||
writer.Header().Add("docker-content-digest", godigest.FromString("t").String())
|
||||
|
||||
_, err := writer.Write([]byte(`{"config": {"digest": "confDigest"}}`))
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
+17
-17
@@ -183,7 +183,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - using shorthand", t, func() {
|
||||
@@ -200,7 +200,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - in text format", t, func() {
|
||||
@@ -283,7 +283,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE anImage tag 6e2f80bf os/arch false 123kB") //nolint:lll
|
||||
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") //nolint:lll
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
@@ -328,7 +328,7 @@ func TestSearchCVECmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE fixedImage tag 6e2f80bf os/arch false 123kB") //nolint:lll
|
||||
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE fixedImage tag os/arch 6e2f80bf false 123kB") //nolint:lll
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by and image name CVE ID - invalid image name", t, func() {
|
||||
@@ -713,7 +713,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldEqual, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE zot-cve-test 0.0.1 82836dd7 N/A false 548B")
|
||||
So(str, ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 82836dd7 false 548B")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - invalid CVE ID", t, func() {
|
||||
@@ -730,7 +730,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldNotContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(str, ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - invalid output format", t, func() {
|
||||
@@ -778,7 +778,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - random image", t, func() {
|
||||
@@ -795,7 +795,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - invalid image", t, func() {
|
||||
@@ -812,7 +812,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - positive", t, func() {
|
||||
@@ -829,7 +829,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE zot-cve-test 0.0.1 82836dd7 N/A false 548B")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 82836dd7 false 548B")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - invalid name and CVE ID", t, func() {
|
||||
@@ -845,7 +845,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - invalid output format", t, func() {
|
||||
@@ -907,7 +907,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldEqual, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE zot-cve-test 0.0.1 82836dd7 linux/amd64 false 548B")
|
||||
So(str, ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 82836dd7 false 548B")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - invalid CVE ID", t, func() {
|
||||
@@ -924,7 +924,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldNotContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(str, ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by and image name CVE ID - positive", t, func() {
|
||||
@@ -958,7 +958,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by and image name CVE ID - invalid image", t, func() {
|
||||
@@ -975,7 +975,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - positive", t, func() {
|
||||
@@ -992,7 +992,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE zot-cve-test 0.0.1 82836dd7 linux/amd64 false 548B")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 82836dd7 false 548B")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - invalid name and CVE ID", t, func() {
|
||||
@@ -1009,7 +1009,7 @@ func TestServerCVEResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+231
-73
@@ -186,7 +186,7 @@ func TestSearchImageCmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
@@ -203,7 +203,7 @@ func TestSearchImageCmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
So(err, ShouldBeNil)
|
||||
Convey("using shorthand", func() {
|
||||
args := []string{"imagetest", "-n", "dummyImageName", "--url", "someUrlImage"}
|
||||
@@ -219,7 +219,7 @@ func TestSearchImageCmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
||||
@@ -237,7 +237,7 @@ func TestSearchImageCmd(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE anImage tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("invalid URL format", func() {
|
||||
@@ -330,8 +330,8 @@ func TestSignature(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 6742241d linux/amd64 true 447B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 6742241d true 447B")
|
||||
|
||||
t.Log("Test getting all images using rest calls to get catalog and individual manifests")
|
||||
cmd = MockNewImageCommand(new(searchService))
|
||||
@@ -343,8 +343,8 @@ func TestSignature(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
str = space.ReplaceAllString(buff.String(), " ")
|
||||
actual = strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 6742241d linux/amd64 true 447B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 6742241d true 447B")
|
||||
|
||||
err = os.Chdir(currentWorkingDir)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -407,8 +407,8 @@ func TestSignature(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 0.0.1 6742241d linux/amd64 true 447B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 6742241d true 447B")
|
||||
|
||||
t.Log("Test getting all images using rest calls to get catalog and individual manifests")
|
||||
cmd = MockNewImageCommand(new(searchService))
|
||||
@@ -420,8 +420,8 @@ func TestSignature(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
str = space.ReplaceAllString(buff.String(), " ")
|
||||
actual = strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 0.0.1 6742241d linux/amd64 true 447B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 6742241d true 447B")
|
||||
|
||||
err = os.Chdir(currentWorkingDir)
|
||||
So(err, ShouldBeNil)
|
||||
@@ -469,8 +469,8 @@ func TestDerivedImageList(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 2694fdb0 N/A false 824B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 2694fdb0 false 824B")
|
||||
})
|
||||
|
||||
Convey("Test derived images list fails", func() {
|
||||
@@ -542,8 +542,8 @@ func TestBaseImageList(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 3fc80493 N/A false 494B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 3fc80493 false 494B")
|
||||
})
|
||||
|
||||
Convey("Test base images list fail", func() {
|
||||
@@ -732,7 +732,7 @@ func TestOutputFormat(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE dummyImageName tag 6e2f80bf os/arch false 123kB")
|
||||
"IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
@@ -756,7 +756,8 @@ func TestOutputFormat(t *testing.T) {
|
||||
`"layers": [ { "size": "0", "digest": "sha256:c122a146f0d02349be211bb95cc2530f4a5793f96edbdfa00860f741e5d8c0e6" } ], `+ //nolint:lll
|
||||
`"platform": { "os": "os", "arch": "arch", "variant": "" }, `+
|
||||
`"size": "123445", "isSigned": false } ], `+
|
||||
`"size": "123445", "isSigned": false }`)
|
||||
`"size": "123445", "digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", `+
|
||||
`"mediaType": "application/vnd.oci.image.manifest.v1+json", "isSigned": false }`)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
@@ -782,7 +783,8 @@ func TestOutputFormat(t *testing.T) {
|
||||
`layers: - size: 0 digest: sha256:c122a146f0d02349be211bb95cc2530f4a5793f96edbdfa00860f741e5d8c0e6 `+
|
||||
`platform: os: os arch: arch variant: "" `+
|
||||
`size: "123445" issigned: false `+
|
||||
`size: "123445" issigned: false`,
|
||||
`size: "123445" digest: sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 `+
|
||||
`mediatype: application/vnd.oci.image.manifest.v1+json issigned: false`,
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
@@ -811,7 +813,8 @@ func TestOutputFormat(t *testing.T) {
|
||||
`layers: - size: 0 digest: sha256:c122a146f0d02349be211bb95cc2530f4a5793f96edbdfa00860f741e5d8c0e6 `+
|
||||
`platform: os: os arch: arch variant: "" `+
|
||||
`size: "123445" issigned: false `+
|
||||
`size: "123445" issigned: false`,
|
||||
`size: "123445" digest: sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 `+
|
||||
`mediatype: application/vnd.oci.image.manifest.v1+json issigned: false`,
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
@@ -867,9 +870,9 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
Convey("Test all images invalid output format", func() {
|
||||
args := []string{"imagetest", "-o", "random"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
||||
@@ -900,14 +903,14 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG DIGEST CONFIG OS/ARCH SIGNED LAYERS SIZE
|
||||
// repo7 test:2.0 a0ca253b b8781e88 linux/amd64 false 492B
|
||||
// b8781e88 15B
|
||||
// repo7 test:1.0 a0ca253b b8781e88 linux/amd64 false 492B
|
||||
// b8781e88 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST CONFIG OS/ARCH SIGNED LAYERS SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 3a1d2d0c linux/amd64 false 492B b8781e88 15B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 3a1d2d0c linux/amd64 false 492B b8781e88 15B")
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
||||
// repo7 test:2.0 linux/amd64 a0ca253b b8781e88 false 492B
|
||||
// b8781e88 15B
|
||||
// repo7 test:1.0 linux/amd64 a0ca253b b8781e88 false 492B
|
||||
// b8781e88 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 3a1d2d0c false 492B b8781e88 15B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 3a1d2d0c false 492B b8781e88 15B")
|
||||
})
|
||||
|
||||
Convey("Test all images with debug flag", func() {
|
||||
@@ -925,9 +928,9 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "GET")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
})
|
||||
|
||||
Convey("Test image by name config url", func() {
|
||||
@@ -944,9 +947,9 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
|
||||
Convey("with shorthand", func() {
|
||||
args := []string{"imagetest", "-n", "repo7"}
|
||||
@@ -962,9 +965,9 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
})
|
||||
|
||||
Convey("invalid output format", func() {
|
||||
@@ -997,12 +1000,12 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG DIGEST OS/ARCH SIZE
|
||||
// repo7 test:2.0 a0ca253b N/A 15B
|
||||
// repo7 test:1.0 a0ca253b N/A 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 N/A false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 N/A false 492B")
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST SIZE
|
||||
// repo7 test:2.0 a0ca253b 15B
|
||||
// repo7 test:1.0 a0ca253b 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 false 492B")
|
||||
|
||||
Convey("with shorthand", func() {
|
||||
args := []string{"imagetest", "-d", "883fc0c5"}
|
||||
@@ -1018,9 +1021,9 @@ func TestServerResponseGQL(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 N/A false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 N/A false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 false 492B")
|
||||
})
|
||||
|
||||
Convey("nonexistent digest", func() {
|
||||
@@ -1128,9 +1131,9 @@ func TestServerResponse(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
})
|
||||
|
||||
Convey("Test all images verbose", func() {
|
||||
@@ -1148,14 +1151,14 @@ func TestServerResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG DIGEST CONFIG OS/ARCH SIGNED LAYERS SIZE
|
||||
// repo7 test:2.0 a0ca253b b8781e88 linux/amd64 false 492B
|
||||
// linux/amd64 b8781e88 15B
|
||||
// repo7 test:1.0 a0ca253b b8781e88 linux/amd64 false 492B
|
||||
// linux/amd64 b8781e88 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST CONFIG OS/ARCH SIGNED LAYERS SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 3a1d2d0c linux/amd64 false 492B b8781e88 15B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 3a1d2d0c linux/amd64 false 492B b8781e88 15B")
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
||||
// repo7 test:2.0 linux/amd64 a0ca253b b8781e88 false 492B
|
||||
// b8781e88 15B
|
||||
// repo7 test:1.0 linux/amd64 a0ca253b b8781e88 false 492B
|
||||
// b8781e88 15B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 3a1d2d0c false 492B b8781e88 15B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 3a1d2d0c false 492B b8781e88 15B")
|
||||
})
|
||||
|
||||
Convey("Test image by name", func() {
|
||||
@@ -1172,9 +1175,9 @@ func TestServerResponse(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
})
|
||||
|
||||
Convey("Test image by digest", func() {
|
||||
@@ -1192,12 +1195,12 @@ func TestServerResponse(t *testing.T) {
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG DIGEST OS/ARCH SIZE
|
||||
// repo7 test:2.0 a0ca253b linux/amd64 492B
|
||||
// repo7 test:1.0 a0ca253b linux/amd64 492B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST OS/ARCH SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 883fc0c5 linux/amd64 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 883fc0c5 linux/amd64 false 492B")
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST SIZE
|
||||
// repo7 test:2.0 linux/amd64 a0ca253b 492B
|
||||
// repo7 test:1.0 linux/amd64 a0ca253b 492B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 883fc0c5 false 492B")
|
||||
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 883fc0c5 false 492B")
|
||||
|
||||
Convey("nonexistent digest", func() {
|
||||
args := []string{"imagetest", "--digest", "d1g35t"}
|
||||
@@ -1269,6 +1272,153 @@ func TestServerResponseGQLWithoutPermissions(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestDisplayIndex(t *testing.T) {
|
||||
Convey("Init Basic Server, No GQL", t, func() {
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
Convey("No GQL", func() {
|
||||
defaultVal := false
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
runDisplayIndexTests(baseURL)
|
||||
})
|
||||
|
||||
Convey("With GQL", func() {
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
runDisplayIndexTests(baseURL)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func runDisplayIndexTests(baseURL string) {
|
||||
Convey("Test Image Index", func() {
|
||||
uploadTestMultiarch(baseURL)
|
||||
|
||||
args := []string{"imagetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
cmd := MockNewImageCommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE
|
||||
// repo multi-arch * 46b78b06 false 1.4kB
|
||||
// linux/amd64 97b0d65c false 577B
|
||||
// windows/arm64/v6 dcfa3a9c false 444B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo multi-arch * 46b78b06 false 1.4kB ")
|
||||
So(actual, ShouldContainSubstring, "linux/amd64 97b0d65c false 577B ")
|
||||
So(actual, ShouldContainSubstring, "windows/arm64/v6 dcfa3a9c false 444B")
|
||||
})
|
||||
|
||||
Convey("Test Image Index Verbose", func() {
|
||||
uploadTestMultiarch(baseURL)
|
||||
|
||||
args := []string{"imagetest", "--verbose"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
cmd := MockNewImageCommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
actual := strings.TrimSpace(str)
|
||||
// Actual cli output should be something similar to (order of images may differ):
|
||||
// IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
||||
// repo multi-arch * 46b78b06 false 1.4kB
|
||||
// linux/amd64 97b0d65c 58cc9abe false 577B
|
||||
// cbb5b121 4B
|
||||
// a00291e8 4B
|
||||
// windows/arm64/v6 dcfa3a9c 5132a1cd false 444B
|
||||
// 7d08ce29 4B
|
||||
So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
||||
So(actual, ShouldContainSubstring, "repo multi-arch * 46b78b06 false 1.4kB")
|
||||
So(actual, ShouldContainSubstring, "linux/amd64 97b0d65c 58cc9abe false 577B")
|
||||
So(actual, ShouldContainSubstring, "cbb5b121 4B")
|
||||
So(actual, ShouldContainSubstring, "a00291e8 4B")
|
||||
So(actual, ShouldContainSubstring, "windows/arm64/v6 dcfa3a9c 5132a1cd false 444B")
|
||||
So(actual, ShouldContainSubstring, "7d08ce29 4B")
|
||||
})
|
||||
}
|
||||
|
||||
func uploadTestMultiarch(baseURL string) {
|
||||
// ------- Define Image1
|
||||
layer11 := []byte{11, 12, 13, 14}
|
||||
layer12 := []byte{16, 17, 18, 19}
|
||||
|
||||
image1, err := test.GetImageWithComponents(
|
||||
ispec.Image{
|
||||
Platform: ispec.Platform{
|
||||
OS: "linux",
|
||||
Architecture: "amd64",
|
||||
},
|
||||
},
|
||||
[][]byte{
|
||||
layer11,
|
||||
layer12,
|
||||
},
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// ------ Define Image2
|
||||
layer21 := []byte{21, 22, 23, 24}
|
||||
|
||||
image2, err := test.GetImageWithComponents(
|
||||
ispec.Image{
|
||||
Platform: ispec.Platform{
|
||||
OS: "windows",
|
||||
Architecture: "arm64",
|
||||
Variant: "v6",
|
||||
},
|
||||
},
|
||||
[][]byte{
|
||||
layer21,
|
||||
},
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// ------- Upload The multiarch image
|
||||
|
||||
multiarch := test.GetMultiarchImageForImages("multi-arch", []test.Image{image1, image2})
|
||||
|
||||
err = test.UploadMultiarchImage(multiarch, baseURL, "repo")
|
||||
So(err, ShouldBeNil)
|
||||
}
|
||||
|
||||
func MockNewImageCommand(searchService SearchService) *cobra.Command {
|
||||
searchImageParams := make(map[string]*string)
|
||||
|
||||
@@ -1596,8 +1746,10 @@ func (service mockService) getImagesGQL(ctx context.Context, config searchConfig
|
||||
imageListGQLResponse := &imageListStructGQL{}
|
||||
imageListGQLResponse.Data.Results = []imageStruct{
|
||||
{
|
||||
RepoName: "dummyImageName",
|
||||
Tag: "tag",
|
||||
RepoName: "dummyImageName",
|
||||
Tag: "tag",
|
||||
MediaType: ispec.MediaTypeImageManifest,
|
||||
Digest: godigest.FromString("test").String(),
|
||||
Manifests: []manifestStruct{
|
||||
{
|
||||
Digest: godigest.FromString("Digest").String(),
|
||||
@@ -1619,8 +1771,10 @@ func (service mockService) getImagesByDigestGQL(ctx context.Context, config sear
|
||||
imageListGQLResponse := &imageListStructForDigestGQL{}
|
||||
imageListGQLResponse.Data.Results = []imageStruct{
|
||||
{
|
||||
RepoName: "randomimageName",
|
||||
Tag: "tag",
|
||||
RepoName: "randomimageName",
|
||||
Tag: "tag",
|
||||
MediaType: ispec.MediaTypeImageManifest,
|
||||
Digest: godigest.FromString("test").String(),
|
||||
Manifests: []manifestStruct{
|
||||
{
|
||||
Digest: godigest.FromString("Digest").String(),
|
||||
@@ -1745,6 +1899,8 @@ func (service mockService) getAllImages(ctx context.Context, config searchConfig
|
||||
image := &imageStruct{}
|
||||
image.RepoName = "randomimageName"
|
||||
image.Tag = "tag"
|
||||
image.Digest = godigest.FromString("test").String()
|
||||
image.MediaType = ispec.MediaTypeImageManifest
|
||||
image.Manifests = []manifestStruct{
|
||||
{
|
||||
Digest: godigest.FromString("Digest").String(),
|
||||
@@ -1775,6 +1931,8 @@ func (service mockService) getImageByName(ctx context.Context, config searchConf
|
||||
image := &imageStruct{}
|
||||
image.RepoName = imageName
|
||||
image.Tag = "tag"
|
||||
image.Digest = godigest.FromString("test").String()
|
||||
image.MediaType = ispec.MediaTypeImageManifest
|
||||
image.Manifests = []manifestStruct{
|
||||
{
|
||||
Digest: godigest.FromString("Digest").String(),
|
||||
|
||||
+177
-81
@@ -17,6 +17,7 @@ import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
zotErrors "zotregistry.io/zot/errors"
|
||||
@@ -74,11 +75,14 @@ func (service searchService) getDerivedImageListGQL(ctx context.Context, config
|
||||
Results{
|
||||
RepoName,
|
||||
Tag,
|
||||
Digest,
|
||||
MediaType,
|
||||
Manifests {
|
||||
Digest,
|
||||
ConfigDigest,
|
||||
Layers {Size Digest},
|
||||
LastUpdated,
|
||||
IsSigned,
|
||||
Size
|
||||
},
|
||||
LastUpdated,
|
||||
@@ -107,11 +111,14 @@ func (service searchService) getBaseImageListGQL(ctx context.Context, config sea
|
||||
Results{
|
||||
RepoName,
|
||||
Tag,
|
||||
Digest,
|
||||
MediaType,
|
||||
Manifests {
|
||||
Digest,
|
||||
ConfigDigest,
|
||||
Layers {Size Digest},
|
||||
LastUpdated,
|
||||
IsSigned,
|
||||
Size
|
||||
},
|
||||
LastUpdated,
|
||||
@@ -139,11 +146,14 @@ func (service searchService) getImagesGQL(ctx context.Context, config searchConf
|
||||
ImageList(repo: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
Platform {Os Arch}
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
Size
|
||||
@@ -171,12 +181,15 @@ func (service searchService) getImagesByDigestGQL(ctx context.Context, config se
|
||||
ImageListForDigest(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
IsSigned
|
||||
}
|
||||
@@ -202,12 +215,15 @@ func (service searchService) getImagesByCveIDGQL(ctx context.Context, config sea
|
||||
ImageListForCVE(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
IsSigned
|
||||
}
|
||||
@@ -252,10 +268,13 @@ func (service searchService) getTagsForCVEGQL(ctx context.Context, config search
|
||||
ImageListForCVE(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
Size
|
||||
@@ -282,12 +301,15 @@ func (service searchService) getFixedTagsForCVEGQL(ctx context.Context, config s
|
||||
ImageListWithCVEFixed(id: "%s", image: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
}
|
||||
}
|
||||
@@ -426,12 +448,15 @@ func (service searchService) getImagesByCveID(ctx context.Context, config search
|
||||
ImageListForCVE(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
}
|
||||
}
|
||||
@@ -492,12 +517,15 @@ func (service searchService) getImagesByDigest(ctx context.Context, config searc
|
||||
ImageListForDigest(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
}
|
||||
}
|
||||
@@ -558,12 +586,15 @@ func (service searchService) getImageByNameAndCVEID(ctx context.Context, config
|
||||
ImageListForCVE(id: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
}
|
||||
}
|
||||
@@ -682,12 +713,15 @@ func (service searchService) getFixedTagsForCVE(ctx context.Context, config sear
|
||||
ImageListWithCVEFixed (id: "%s", image: "%s") {
|
||||
Results {
|
||||
RepoName Tag
|
||||
Digest
|
||||
MediaType
|
||||
Manifests {
|
||||
Digest
|
||||
ConfigDigest
|
||||
Size
|
||||
IsSigned
|
||||
Layers {Size Digest}
|
||||
}
|
||||
}
|
||||
Size
|
||||
}
|
||||
}
|
||||
@@ -984,8 +1018,10 @@ type imageStruct struct {
|
||||
Tag string `json:"tag"`
|
||||
Manifests []manifestStruct
|
||||
Size string `json:"size"`
|
||||
Digest string `json:"digest"`
|
||||
MediaType string `json:"mediaType"`
|
||||
IsSigned bool `json:"isSigned"`
|
||||
verbose bool
|
||||
IsSigned bool `json:"isSigned"`
|
||||
}
|
||||
|
||||
type manifestStruct struct {
|
||||
@@ -1106,69 +1142,9 @@ func (img imageStruct) stringPlainText(maxImgNameLen, maxTagLen, maxPlatformLen
|
||||
tagName += offset
|
||||
}
|
||||
|
||||
for i := range img.Manifests {
|
||||
manifestDigest, err := godigest.Parse(img.Manifests[i].Digest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing manifest digest %s: %w", img.Manifests[i].Digest, err)
|
||||
}
|
||||
|
||||
configDigest, err := godigest.Parse(img.Manifests[i].ConfigDigest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing config digest %s: %w", img.Manifests[i].ConfigDigest, err)
|
||||
}
|
||||
|
||||
platform := getPlatformStr(img.Manifests[i].Platform)
|
||||
|
||||
if maxPlatformLen > len(platform) {
|
||||
offset = strings.Repeat(" ", maxPlatformLen-len(platform))
|
||||
platform += offset
|
||||
}
|
||||
|
||||
minifestDigestStr := ellipsize(manifestDigest.Encoded(), digestWidth, "")
|
||||
configDigestStr := ellipsize(configDigest.Encoded(), configWidth, "")
|
||||
imgSize, _ := strconv.ParseUint(img.Manifests[i].Size, 10, 64)
|
||||
size := ellipsize(strings.ReplaceAll(humanize.Bytes(imgSize), " ", ""), sizeWidth, ellipsis)
|
||||
isSigned := img.IsSigned
|
||||
row := make([]string, 8) //nolint:gomnd
|
||||
|
||||
row[colImageNameIndex] = imageName
|
||||
row[colTagIndex] = tagName
|
||||
row[colDigestIndex] = minifestDigestStr
|
||||
row[colPlatformIndex] = platform
|
||||
row[colSizeIndex] = size
|
||||
row[colIsSignedIndex] = strconv.FormatBool(isSigned)
|
||||
|
||||
if img.verbose {
|
||||
row[colConfigIndex] = configDigestStr
|
||||
row[colLayersIndex] = ""
|
||||
}
|
||||
|
||||
table.Append(row)
|
||||
|
||||
if img.verbose {
|
||||
for _, entry := range img.Manifests[i].Layers {
|
||||
layerSize := entry.Size
|
||||
size := ellipsize(strings.ReplaceAll(humanize.Bytes(uint64(layerSize)), " ", ""), sizeWidth, ellipsis)
|
||||
|
||||
layerDigest, err := godigest.Parse(entry.Digest)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error parsing layer digest %s: %w", entry.Digest, err)
|
||||
}
|
||||
|
||||
layerDigestStr := ellipsize(layerDigest.Encoded(), digestWidth, "")
|
||||
|
||||
layerRow := make([]string, 8) //nolint:gomnd
|
||||
layerRow[colImageNameIndex] = ""
|
||||
layerRow[colTagIndex] = ""
|
||||
layerRow[colDigestIndex] = ""
|
||||
layerRow[colPlatformIndex] = ""
|
||||
layerRow[colSizeIndex] = size
|
||||
layerRow[colConfigIndex] = ""
|
||||
layerRow[colLayersIndex] = layerDigestStr
|
||||
|
||||
table.Append(layerRow)
|
||||
}
|
||||
}
|
||||
err := addImageToTable(table, &img, maxPlatformLen, imageName, tagName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
table.Render()
|
||||
@@ -1176,9 +1152,125 @@ func (img imageStruct) stringPlainText(maxImgNameLen, maxTagLen, maxPlatformLen
|
||||
return builder.String(), nil
|
||||
}
|
||||
|
||||
func addImageToTable(table *tablewriter.Table, img *imageStruct, maxPlatformLen int,
|
||||
imageName, tagName string,
|
||||
) error {
|
||||
switch img.MediaType {
|
||||
case ispec.MediaTypeImageManifest:
|
||||
return addManifestToTable(table, imageName, tagName, &img.Manifests[0], maxPlatformLen, img.verbose)
|
||||
case ispec.MediaTypeImageIndex:
|
||||
return addImageIndexToTable(table, img, maxPlatformLen, imageName, tagName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addImageIndexToTable(table *tablewriter.Table, img *imageStruct, maxPlatformLen int,
|
||||
imageName, tagName string,
|
||||
) error {
|
||||
indexDigest, err := godigest.Parse(img.Digest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing index digest %s: %w", indexDigest, err)
|
||||
}
|
||||
row := make([]string, rowWidth)
|
||||
row[colImageNameIndex] = imageName
|
||||
row[colTagIndex] = tagName
|
||||
row[colDigestIndex] = ellipsize(indexDigest.Encoded(), digestWidth, "")
|
||||
row[colPlatformIndex] = "*"
|
||||
|
||||
imgSize, _ := strconv.ParseUint(img.Size, 10, 64)
|
||||
row[colSizeIndex] = ellipsize(strings.ReplaceAll(humanize.Bytes(imgSize), " ", ""), sizeWidth, ellipsis)
|
||||
row[colIsSignedIndex] = strconv.FormatBool(img.IsSigned)
|
||||
|
||||
if img.verbose {
|
||||
row[colConfigIndex] = ""
|
||||
row[colLayersIndex] = ""
|
||||
}
|
||||
|
||||
table.Append(row)
|
||||
|
||||
for i := range img.Manifests {
|
||||
err := addManifestToTable(table, "", "", &img.Manifests[i], maxPlatformLen, img.verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func addManifestToTable(table *tablewriter.Table, imageName, tagName string, manifest *manifestStruct,
|
||||
maxPlatformLen int, verbose bool,
|
||||
) error {
|
||||
manifestDigest, err := godigest.Parse(manifest.Digest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing manifest digest %s: %w", manifest.Digest, err)
|
||||
}
|
||||
|
||||
configDigest, err := godigest.Parse(manifest.ConfigDigest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing config digest %s: %w", manifest.ConfigDigest, err)
|
||||
}
|
||||
|
||||
platform := getPlatformStr(manifest.Platform)
|
||||
|
||||
if maxPlatformLen > len(platform) {
|
||||
offset := strings.Repeat(" ", maxPlatformLen-len(platform))
|
||||
platform += offset
|
||||
}
|
||||
|
||||
minifestDigestStr := ellipsize(manifestDigest.Encoded(), digestWidth, "")
|
||||
configDigestStr := ellipsize(configDigest.Encoded(), configWidth, "")
|
||||
imgSize, _ := strconv.ParseUint(manifest.Size, 10, 64)
|
||||
size := ellipsize(strings.ReplaceAll(humanize.Bytes(imgSize), " ", ""), sizeWidth, ellipsis)
|
||||
isSigned := manifest.IsSigned
|
||||
row := make([]string, 8) //nolint:gomnd
|
||||
|
||||
row[colImageNameIndex] = imageName
|
||||
row[colTagIndex] = tagName
|
||||
row[colDigestIndex] = minifestDigestStr
|
||||
row[colPlatformIndex] = platform
|
||||
row[colSizeIndex] = size
|
||||
row[colIsSignedIndex] = strconv.FormatBool(isSigned)
|
||||
|
||||
if verbose {
|
||||
row[colConfigIndex] = configDigestStr
|
||||
row[colLayersIndex] = ""
|
||||
}
|
||||
|
||||
table.Append(row)
|
||||
|
||||
if verbose {
|
||||
for _, entry := range manifest.Layers {
|
||||
layerSize := entry.Size
|
||||
size := ellipsize(strings.ReplaceAll(humanize.Bytes(uint64(layerSize)), " ", ""), sizeWidth, ellipsis)
|
||||
|
||||
layerDigest, err := godigest.Parse(entry.Digest)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error parsing layer digest %s: %w", entry.Digest, err)
|
||||
}
|
||||
|
||||
layerDigestStr := ellipsize(layerDigest.Encoded(), digestWidth, "")
|
||||
|
||||
layerRow := make([]string, 8) //nolint:gomnd
|
||||
layerRow[colImageNameIndex] = ""
|
||||
layerRow[colTagIndex] = ""
|
||||
layerRow[colDigestIndex] = ""
|
||||
layerRow[colPlatformIndex] = ""
|
||||
layerRow[colSizeIndex] = size
|
||||
layerRow[colConfigIndex] = ""
|
||||
layerRow[colLayersIndex] = layerDigestStr
|
||||
|
||||
table.Append(layerRow)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getPlatformStr(platf platform) string {
|
||||
if platf.Arch == "" && platf.Os == "" {
|
||||
return "N/A"
|
||||
return ""
|
||||
}
|
||||
|
||||
platform := platf.Os
|
||||
@@ -1332,15 +1424,6 @@ const (
|
||||
layersWidth = 8
|
||||
ellipsis = "..."
|
||||
|
||||
colImageNameIndex = 0
|
||||
colTagIndex = 1
|
||||
colDigestIndex = 2
|
||||
colConfigIndex = 3
|
||||
colPlatformIndex = 4
|
||||
colIsSignedIndex = 5
|
||||
colLayersIndex = 6
|
||||
colSizeIndex = 7
|
||||
|
||||
cveIDWidth = 16
|
||||
cveSeverityWidth = 8
|
||||
cveTitleWidth = 48
|
||||
@@ -1351,3 +1434,16 @@ const (
|
||||
|
||||
defaultOutoutFormat = "text"
|
||||
)
|
||||
|
||||
const (
|
||||
colImageNameIndex = iota
|
||||
colTagIndex
|
||||
colPlatformIndex
|
||||
colDigestIndex
|
||||
colConfigIndex
|
||||
colIsSignedIndex
|
||||
colLayersIndex
|
||||
colSizeIndex
|
||||
|
||||
rowWidth
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user