diff --git a/pkg/cli/config_cmd.go b/pkg/cli/config_cmd.go index cbf6d9b1..9138d1d2 100644 --- a/pkg/cli/config_cmd.go +++ b/pkg/cli/config_cmd.go @@ -419,7 +419,8 @@ const ( Useful variables: url zot server URL showspinner show spinner while loading data [true/false] - verify-tls enable TLS certificate verification of the server [default: true]` + verify-tls enable TLS certificate verification of the server [default: true] +` nameKey = "_name" diff --git a/pkg/cli/cve_cmd_test.go b/pkg/cli/cve_cmd_test.go index 9984bbe6..03b12573 100644 --- a/pkg/cli/cve_cmd_test.go +++ b/pkg/cli/cve_cmd_test.go @@ -186,7 +186,7 @@ func TestSearchCVECmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY 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() { @@ -203,7 +203,7 @@ func TestSearchCVECmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") }) Convey("Test CVE by image name - in text format", t, func() { @@ -232,12 +232,11 @@ func TestSearchCVECmd(t *testing.T) { cveCmd.SetErr(buff) cveCmd.SetArgs(args) err := cveCmd.Execute() - space := regexp.MustCompile(`\s+`) - str := space.ReplaceAllString(buff.String(), " ") - So(strings.TrimSpace(str), ShouldEqual, `{ "Tag": "dummyImageName:tag", "CVEList": `+ - `[ { "Id": "dummyCVEID", "Severity": "HIGH", "Title": "Title of that CVE", `+ - `"Description": "Description of the CVE", "PackageList": [ { "Name": "packagename",`+ - ` "InstalledVersion": "installedver", "FixedVersion": "fixedver" } ] } ] }`) + // Output is supposed to be in json lines format, keep all spaces as is for verification + So(buff.String(), ShouldEqual, `{"Tag":"dummyImageName:tag","CVEList":`+ + `[{"Id":"dummyCVEID","Severity":"HIGH","Title":"Title of that CVE",`+ + `"Description":"Description of the CVE","PackageList":[{"Name":"packagename",`+ + `"InstalledVersion":"installedver","FixedVersion":"fixedver"}]}]}`+"\n") So(err, ShouldBeNil) }) @@ -253,7 +252,7 @@ func TestSearchCVECmd(t *testing.T) { err := cveCmd.Execute() space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") - So(strings.TrimSpace(str), ShouldEqual, `tag: dummyImageName:tag cvelist: - id: dummyCVEID`+ + So(strings.TrimSpace(str), ShouldEqual, `--- tag: dummyImageName:tag cvelist: - id: dummyCVEID`+ ` severity: HIGH title: Title of that CVE description: Description of the CVE packagelist: `+ `- name: packagename installedversion: installedver fixedversion: fixedver`) So(err, ShouldBeNil) @@ -286,7 +285,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 OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") //nolint:lll + So(strings.TrimSpace(str), ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") //nolint:lll So(err, ShouldBeNil) }) @@ -307,7 +306,7 @@ func TestSearchCVECmd(t *testing.T) { So(strings.TrimSpace(str), ShouldContainSubstring, "[warning] CVE DB is not ready [ 0 ] - retry in "+strconv.Itoa(cveDBRetryInterval)+" seconds") So(strings.TrimSpace(str), ShouldContainSubstring, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") So(err, ShouldBeNil) }) @@ -328,7 +327,7 @@ func TestSearchCVECmd(t *testing.T) { So(strings.TrimSpace(str), ShouldContainSubstring, "[warning] CVE DB is not ready [ 0 ] - retry in "+strconv.Itoa(cveDBRetryInterval)+" seconds") So(strings.TrimSpace(str), ShouldNotContainSubstring, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") So(err, ShouldNotBeNil) }) @@ -373,7 +372,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 OS/ARCH DIGEST SIGNED SIZE fixedImage tag os/arch 6e2f80bf false 123kB") //nolint:lll + So(strings.TrimSpace(str), ShouldEqual, "REPOSITORY 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() { @@ -758,7 +757,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) So(err, ShouldBeNil) - So(str, ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 40d1f749 false 605B") + So(str, ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 40d1f749 false 605B") }) Convey("Test images by CVE ID - GQL - invalid CVE ID", t, func() { @@ -775,7 +774,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) So(err, ShouldBeNil) - So(str, ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(str, ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test images by CVE ID - GQL - invalid output format", t, func() { @@ -823,7 +822,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 OS/ARCH DIGEST SIGNED SIZE") + So(strings.TrimSpace(str), ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by image name and CVE ID - GQL - random image", t, func() { @@ -840,7 +839,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 OS/ARCH DIGEST SIGNED SIZE") + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by image name and CVE ID - GQL - invalid image", t, func() { @@ -857,7 +856,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 OS/ARCH DIGEST SIGNED SIZE") + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test CVE by name and CVE ID - GQL - positive", t, func() { @@ -874,7 +873,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") So(err, ShouldBeNil) So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 40d1f749 false 605B") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 40d1f749 false 605B") }) Convey("Test CVE by name and CVE ID - GQL - invalid name and CVE ID", t, func() { @@ -890,7 +889,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 OS/ARCH SIGNED SIZE") + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH SIGNED SIZE") }) Convey("Test CVE by name and CVE ID - GQL - invalid output format", t, func() { @@ -952,7 +951,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) So(err, ShouldBeNil) - So(str, ShouldEqual, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 40d1f749 false 605B") + So(str, ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 40d1f749 false 605B") }) Convey("Test images by CVE ID - invalid CVE ID", t, func() { @@ -969,7 +968,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) So(err, ShouldBeNil) - So(str, ShouldNotContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(str, ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by and image name CVE ID - positive", t, func() { @@ -1003,7 +1002,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 OS/ARCH DIGEST SIGNED SIZE") + So(strings.TrimSpace(str), ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by and image name CVE ID - invalid image", t, func() { @@ -1020,7 +1019,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 OS/ARCH DIGEST SIGNED SIZE") + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test CVE by name and CVE ID - positive", t, func() { @@ -1037,7 +1036,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") So(err, ShouldBeNil) So(strings.TrimSpace(str), ShouldResemble, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 40d1f749 false 605B") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 40d1f749 false 605B") }) Convey("Test CVE by name and CVE ID - invalid name and CVE ID", t, func() { @@ -1054,7 +1053,7 @@ func TestServerCVEResponse(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") So(err, ShouldBeNil) So(strings.TrimSpace(str), ShouldNotContainSubstring, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) } diff --git a/pkg/cli/image_cmd_test.go b/pkg/cli/image_cmd_test.go index bad189ee..b7f6e1ac 100644 --- a/pkg/cli/image_cmd_test.go +++ b/pkg/cli/image_cmd_test.go @@ -187,7 +187,7 @@ func TestSearchImageCmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") So(err, ShouldBeNil) }) @@ -204,7 +204,7 @@ func TestSearchImageCmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY 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"} @@ -220,7 +220,7 @@ func TestSearchImageCmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") So(err, ShouldBeNil) }) }) @@ -238,7 +238,7 @@ func TestSearchImageCmd(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") So(err, ShouldBeNil) Convey("invalid URL format", func() { @@ -333,7 +333,7 @@ func TestSignature(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 8e59ed3b true 504B") t.Log("Test getting all images using rest calls to get catalog and individual manifests") @@ -346,7 +346,7 @@ func TestSignature(t *testing.T) { So(err, ShouldBeNil) str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 8e59ed3b true 504B") err = os.Chdir(currentWorkingDir) @@ -410,7 +410,7 @@ func TestSignature(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 8e59ed3b true 504B") t.Log("Test getting all images using rest calls to get catalog and individual manifests") @@ -423,7 +423,7 @@ func TestSignature(t *testing.T) { So(err, ShouldBeNil) str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 8e59ed3b true 504B") err = os.Chdir(currentWorkingDir) @@ -472,7 +472,7 @@ func TestDerivedImageList(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:1.0 2694fdb0 false 824B") }) @@ -545,7 +545,7 @@ func TestBaseImageList(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:2.0 3fc80493 false 494B") }) @@ -735,12 +735,10 @@ func TestOutputFormat(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, - "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") + "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB") So(err, ShouldBeNil) }) - // get image config functia - Convey("Test json", t, func() { args := []string{"imagetest", "--name", "dummyImageName", "-o", "json"} configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) @@ -751,21 +749,20 @@ func TestOutputFormat(t *testing.T) { cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() - space := regexp.MustCompile(`\s+`) - str := space.ReplaceAllString(buff.String(), " ") - So(strings.TrimSpace(str), ShouldEqual, `{ "repoName": "dummyImageName", "tag": "tag", `+ - `"digest": "sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", `+ - `"mediaType": "application/vnd.oci.image.manifest.v1+json", `+ - `"manifests": [ { "digest": "sha256:6e2f80bf9cfaabad474fbaf8ad68fdb652f776ea80b63492ecca404e5f6446a6", `+ - `"configDigest": "sha256:4c10985c40365538426f2ba8cf0c21384a7769be502a550dcc0601b3736625e0", `+ - `"lastUpdated": "0001-01-01T00:00:00Z", "size": "123445", "platform": { "os": "os", "arch": "arch", `+ - `"variant": "" }, "isSigned": false, "downloadCount": 0, `+ - `"layers": [ { "size": "", "digest": "sha256:c122a146f0d02349be211bb95cc2530f4a5793f96edbdfa00860f741e5d8c0e6", `+ - `"score": 0 } ], "history": null, "vulnerabilities": { "maxSeverity": "", "count": 0 }, `+ - `"referrers": null, "artifactType": "" } ], "size": "123445", `+ - `"downloadCount": 0, "lastUpdated": "0001-01-01T00:00:00Z", "description": "", "isSigned": false, "licenses": "", `+ - `"labels": "", "title": "", "source": "", "documentation": "", "authors": "", "vendor": "", `+ - `"vulnerabilities": { "maxSeverity": "", "count": 0 }, "referrers": null }`) + // Output is supposed to be in json lines format, keep all spaces as is for verification + So(buff.String(), ShouldEqual, `{"repoName":"dummyImageName","tag":"tag",`+ + `"digest":"sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",`+ + `"mediaType":"application/vnd.oci.image.manifest.v1+json",`+ + `"manifests":[{"digest":"sha256:6e2f80bf9cfaabad474fbaf8ad68fdb652f776ea80b63492ecca404e5f6446a6",`+ + `"configDigest":"sha256:4c10985c40365538426f2ba8cf0c21384a7769be502a550dcc0601b3736625e0",`+ + `"lastUpdated":"0001-01-01T00:00:00Z","size":"123445","platform":{"os":"os","arch":"arch",`+ + `"variant":""},"isSigned":false,"downloadCount":0,`+ + `"layers":[{"size":"","digest":"sha256:c122a146f0d02349be211bb95cc2530f4a5793f96edbdfa00860f741e5d8c0e6",`+ + `"score":0}],"history":null,"vulnerabilities":{"maxSeverity":"","count":0},`+ + `"referrers":null,"artifactType":""}],"size":"123445",`+ + `"downloadCount":0,"lastUpdated":"0001-01-01T00:00:00Z","description":"","isSigned":false,"licenses":"",`+ + `"labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",`+ + `"vulnerabilities":{"maxSeverity":"","count":0},"referrers":null}`+"\n") So(err, ShouldBeNil) }) @@ -784,7 +781,7 @@ func TestOutputFormat(t *testing.T) { So( strings.TrimSpace(str), ShouldEqual, - `reponame: dummyImageName tag: tag `+ + `--- reponame: dummyImageName tag: tag `+ `digest: sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 `+ `mediatype: application/vnd.oci.image.manifest.v1+json manifests: - `+ `digest: sha256:6e2f80bf9cfaabad474fbaf8ad68fdb652f776ea80b63492ecca404e5f6446a6 `+ @@ -818,7 +815,7 @@ func TestOutputFormat(t *testing.T) { So( strings.TrimSpace(str), ShouldEqual, - `reponame: dummyImageName tag: tag `+ + `--- reponame: dummyImageName tag: tag `+ `digest: sha256:9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 `+ `mediatype: application/vnd.oci.image.manifest.v1+json `+ `manifests: - digest: sha256:6e2f80bf9cfaabad474fbaf8ad68fdb652f776ea80b63492ecca404e5f6446a6 `+ @@ -851,6 +848,165 @@ func TestOutputFormat(t *testing.T) { }) } +func TestOutputFormatGQL(t *testing.T) { + Convey("Test from real server", t, func() { + port := test.GetFreePort() + url := test.GetBaseURL(port) + conf := config.New() + conf.HTTP.Port = port + 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() + + err := uploadManifest(url) + t.Logf("%s", ctlr.Config.Storage.RootDirectory) + So(err, ShouldBeNil) + + Convey("Test json", func() { + t.Logf("%s", ctlr.Config.Storage.RootDirectory) + args := []string{"imagetest", "--name", "repo7", "-o", "json"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) + defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) + buff := bytes.NewBufferString("") + cmd.SetOut(buff) + cmd.SetErr(buff) + cmd.SetArgs(args) + err := cmd.Execute() + So(err, ShouldBeNil) + expectedStr := `{"repoName":"repo7","tag":"test:1.0",` + + `"digest":"sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731",` + + `"mediaType":"application/vnd.oci.image.manifest.v1+json",` + + `"manifests":[{"digest":"sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731",` + + `"configDigest":"sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36",` + + `"lastUpdated":"0001-01-01T00:00:00Z","size":"492","platform":{"os":"linux","arch":"amd64",` + + `"variant":""},"isSigned":false,"downloadCount":0,"layers":[{"size":"15","digest":` + + `"sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6","score":0}],` + + `"history":null,"vulnerabilities":{"maxSeverity":"","count":0},"referrers":null,"artifactType":""}],` + + `"size":"492","downloadCount":0,"lastUpdated":"0001-01-01T00:00:00Z","description":"","isSigned":false,` + + `"licenses":"","labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",` + + `"vulnerabilities":{"maxSeverity":"","count":0},"referrers":null}` + "\n" + + `{"repoName":"repo7","tag":"test:2.0",` + + `"digest":"sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731",` + + `"mediaType":"application/vnd.oci.image.manifest.v1+json",` + + `"manifests":[{"digest":"sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731",` + + `"configDigest":"sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36",` + + `"lastUpdated":"0001-01-01T00:00:00Z","size":"492","platform":{"os":"linux","arch":"amd64",` + + `"variant":""},"isSigned":false,"downloadCount":0,"layers":[{"size":"15","digest":` + + `"sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6","score":0}],` + + `"history":null,"vulnerabilities":{"maxSeverity":"","count":0},"referrers":null,"artifactType":""}],` + + `"size":"492","downloadCount":0,"lastUpdated":"0001-01-01T00:00:00Z","description":"","isSigned":false,` + + `"licenses":"","labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",` + + `"vulnerabilities":{"maxSeverity":"","count":0},"referrers":null}` + "\n" + // Output is supposed to be in json lines format, keep all spaces as is for verification + So(buff.String(), ShouldEqual, expectedStr) + So(err, ShouldBeNil) + }) + + Convey("Test yaml", func() { + args := []string{"imagetest", "--name", "repo7", "-o", "yaml"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) + defer os.Remove(configPath) + cmd := NewImageCommand(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(), " ") + expectedStr := `--- reponame: repo7 tag: test:1.0 ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `configdigest: sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36 ` + + `lastupdated: 0001-01-01T00:00:00Z size: "492" platform: os: linux arch: amd64 variant: "" ` + + `issigned: false downloadcount: 0 layers: - size: "15" ` + + `digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` + + `history: [] vulnerabilities: maxseverity: "" count: 0 referrers: [] artifacttype: "" ` + + `size: "492" downloadcount: 0 lastupdated: 0001-01-01T00:00:00Z description: "" ` + + `issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` + + `authors: "" vendor: "" vulnerabilities: maxseverity: "" count: 0 referrers: [] ` + + `--- reponame: repo7 tag: test:2.0 ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `configdigest: sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36 ` + + `lastupdated: 0001-01-01T00:00:00Z size: "492" platform: os: linux arch: amd64 variant: "" ` + + `issigned: false downloadcount: 0 layers: - size: "15" ` + + `digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` + + `history: [] vulnerabilities: maxseverity: "" count: 0 referrers: [] artifacttype: "" ` + + `size: "492" downloadcount: 0 lastupdated: 0001-01-01T00:00:00Z description: "" ` + + `issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` + + `authors: "" vendor: "" vulnerabilities: maxseverity: "" count: 0 referrers: []` + So(strings.TrimSpace(str), ShouldEqual, expectedStr) + So(err, ShouldBeNil) + }) + + Convey("Test yml", func() { + args := []string{"imagetest", "--name", "repo7", "-o", "yml"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) + defer os.Remove(configPath) + cmd := NewImageCommand(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(), " ") + expectedStr := `--- reponame: repo7 tag: test:1.0 ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `configdigest: sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36 ` + + `lastupdated: 0001-01-01T00:00:00Z size: "492" platform: os: linux arch: amd64 variant: "" ` + + `issigned: false downloadcount: 0 layers: - size: "15" ` + + `digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` + + `history: [] vulnerabilities: maxseverity: "" count: 0 referrers: [] artifacttype: "" ` + + `size: "492" downloadcount: 0 lastupdated: 0001-01-01T00:00:00Z description: "" ` + + `issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` + + `authors: "" vendor: "" vulnerabilities: maxseverity: "" count: 0 referrers: [] ` + + `--- reponame: repo7 tag: test:2.0 ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` + + `digest: sha256:883fc0c54b8cb0c991399f950dae19bcc3561ba4f6ca4d3fb0ca446f2de03731 ` + + `configdigest: sha256:3a1d2d0cc867c06f01285a134f898e2f0b184036de70f331d4dd627f6f887a36 ` + + `lastupdated: 0001-01-01T00:00:00Z size: "492" platform: os: linux arch: amd64 variant: "" ` + + `issigned: false downloadcount: 0 layers: - size: "15" ` + + `digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` + + `history: [] vulnerabilities: maxseverity: "" count: 0 referrers: [] artifacttype: "" ` + + `size: "492" downloadcount: 0 lastupdated: 0001-01-01T00:00:00Z description: "" ` + + `issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` + + `authors: "" vendor: "" vulnerabilities: maxseverity: "" count: 0 referrers: []` + So(strings.TrimSpace(str), ShouldEqual, expectedStr) + So(err, ShouldBeNil) + }) + + Convey("Test invalid", func() { + args := []string{"imagetest", "--name", "repo7", "-o", "random"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) + defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) + buff := bytes.NewBufferString("") + cmd.SetOut(buff) + cmd.SetErr(buff) + cmd.SetArgs(args) + err := cmd.Execute() + So(err, ShouldNotBeNil) + So(buff.String(), ShouldContainSubstring, "invalid output format") + }) + }) +} + func TestServerResponseGQL(t *testing.T) { Convey("Test from real server", t, func() { port := test.GetFreePort() @@ -886,7 +1042,7 @@ func TestServerResponseGQL(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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() { @@ -919,12 +1075,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 OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE + // REPOSITORY 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, "REPOSITORY 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") }) @@ -944,7 +1100,7 @@ func TestServerResponseGQL(t *testing.T) { str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) So(actual, ShouldContainSubstring, "GET") - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") }) @@ -963,7 +1119,7 @@ func TestServerResponseGQL(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") @@ -981,7 +1137,7 @@ func TestServerResponseGQL(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") }) @@ -1016,10 +1172,10 @@ 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 OS/ARCH DIGEST SIZE + // REPOSITORY 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, "REPOSITORY 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") @@ -1037,7 +1193,7 @@ func TestServerResponseGQL(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") }) @@ -1147,7 +1303,7 @@ func TestServerResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") }) @@ -1167,12 +1323,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 OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE + // REPOSITORY 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, "REPOSITORY 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") }) @@ -1191,7 +1347,7 @@ func TestServerResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY 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") }) @@ -1211,10 +1367,10 @@ 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 OS/ARCH DIGEST SIZE + // REPOSITORY 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, "REPOSITORY 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") @@ -1346,11 +1502,11 @@ func runDisplayIndexTests(baseURL string) { 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 + // REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE // repo multi-arch * 59b25ae4 false 1.5kB // linux/amd64 97b0d65c false 634B // windows/arm64/v6 dcfa3a9c false 444B - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo multi-arch * 59b25ae4 false 1.5kB ") So(actual, ShouldContainSubstring, "linux/amd64 2ab1a275 false 634B ") So(actual, ShouldContainSubstring, "windows/arm64/v6 55fdd23a false 501B") @@ -1374,14 +1530,14 @@ func runDisplayIndexTests(baseURL string) { 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 + // REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE // repo multi-arch * 59b25ae4 false 1.5kB // linux/amd64 2ab1a275 58cc9abe false 634B // cbb5b121 4B // a00291e8 4B // windows/arm64/v6 55fdd23a 5132a1cd false 501B // 7d08ce29 4B - So(actual, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE") + So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE") So(actual, ShouldContainSubstring, "repo multi-arch * 59b25ae4 false 1.5kB") So(actual, ShouldContainSubstring, "linux/amd64 2ab1a275 58cc9abe false 634B") So(actual, ShouldContainSubstring, "cbb5b121 4B") diff --git a/pkg/cli/search_cmd_test.go b/pkg/cli/search_cmd_test.go index 2a331f8f..b580f9f9 100644 --- a/pkg/cli/search_cmd_test.go +++ b/pkg/cli/search_cmd_test.go @@ -192,7 +192,7 @@ func TestSearchCLI(t *testing.T) { err = cmd.Execute() So(err, ShouldBeNil) str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) - So(str, ShouldContainSubstring, "IMAGE NAME TAG OS/ARCH DIGEST SIGNED SIZE") + So(str, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(str, ShouldContainSubstring, "repo/alpine repo2tag1 Os/Arch "+formatterDigest1+" false 577B") So(str, ShouldContainSubstring, "repo/alpine repo2tag2 linux/amd64 "+formatterDigest2+" false 524B") diff --git a/pkg/cli/searcher.go b/pkg/cli/searcher.go index b8821e87..61c4236a 100644 --- a/pkg/cli/searcher.go +++ b/pkg/cli/searcher.go @@ -921,14 +921,14 @@ func printImageTableHeader(writer io.Writer, verbose bool, maxImageNameLen, maxT row := make([]string, 8) //nolint:gomnd - // adding spaces so that image name and tag columns are aligned + // adding spaces so that repository and tag columns are aligned // in case the name/tag are fully shown and too long var offset string - if maxImageNameLen > len("IMAGE NAME") { - offset = strings.Repeat(" ", maxImageNameLen-len("IMAGE NAME")) - row[colImageNameIndex] = "IMAGE NAME" + offset + if maxImageNameLen > len("REPOSITORY") { + offset = strings.Repeat(" ", maxImageNameLen-len("REPOSITORY")) + row[colImageNameIndex] = "REPOSITORY" + offset } else { - row[colImageNameIndex] = "IMAGE NAME" + row[colImageNameIndex] = "REPOSITORY" } if maxTagLen > len("TAG") { @@ -982,7 +982,7 @@ func printReferrersTableHeader(config searchConfig, writer io.Writer, maxArtifac row := make([]string, refRowWidth) - // adding spaces so that image name and tag columns are aligned + // adding spaces so that repository and tag columns are aligned // in case the name/tag are fully shown and too long var offset string @@ -1015,7 +1015,7 @@ func printRepoTableHeader(writer io.Writer, repoMaxLen, maxTimeLen int, verbose row := make([]string, repoRowWidth) - // adding spaces so that image name and tag columns are aligned + // adding spaces so that repository and tag columns are aligned // in case the name/tag are fully shown and too long var offset string @@ -1081,7 +1081,10 @@ func printImageResult(config searchConfig, imageList []imageStruct) error { } } - printImageTableHeader(&builder, *config.verbose, maxImgNameLen, maxTagLen, maxPlatformLen) + if *config.outputFormat == defaultOutoutFormat || *config.outputFormat == "" { + printImageTableHeader(&builder, *config.verbose, maxImgNameLen, maxTagLen, maxPlatformLen) + } + fmt.Fprint(config.resultWriter, builder.String()) } @@ -1114,7 +1117,7 @@ func printRepoResults(config searchConfig, repoList []repoStruct) error { } } - if len(repoList) > 0 { + if len(repoList) > 0 && (*config.outputFormat == defaultOutoutFormat || *config.outputFormat == "") { printRepoTableHeader(config.resultWriter, maxRepoNameLen, maxTimeLen, *config.verbose) } diff --git a/pkg/cli/service.go b/pkg/cli/service.go index 55c532d6..35d075d4 100644 --- a/pkg/cli/service.go +++ b/pkg/cli/service.go @@ -84,7 +84,7 @@ func (service searchService) getDerivedImageListGQL(ctx context.Context, config ) (*common.DerivedImageListResponse, error) { query := fmt.Sprintf(` { - DerivedImageList(image:"%s"){ + DerivedImageList(image:"%s", requestedPage: {sortBy: ALPHABETIC_ASC}){ Results{ RepoName, Tag, @@ -189,7 +189,7 @@ func (service searchService) getBaseImageListGQL(ctx context.Context, config sea ) (*common.BaseImageListResponse, error) { query := fmt.Sprintf(` { - BaseImageList(image:"%s"){ + BaseImageList(image:"%s", requestedPage: {sortBy: ALPHABETIC_ASC}){ Results{ RepoName, Tag, @@ -225,7 +225,7 @@ func (service searchService) getImagesGQL(ctx context.Context, config searchConf ) (*common.ImageListResponse, error) { query := fmt.Sprintf(` { - ImageList(repo: "%s") { + ImageList(repo: "%s", requestedPage: {sortBy: ALPHABETIC_ASC}) { Results { RepoName Tag Digest @@ -260,7 +260,7 @@ func (service searchService) getImagesByDigestGQL(ctx context.Context, config se ) (*common.ImagesForDigest, error) { query := fmt.Sprintf(` { - ImageListForDigest(id: "%s") { + ImageListForDigest(id: "%s", requestedPage: {sortBy: ALPHABETIC_ASC}) { Results { RepoName Tag Digest @@ -294,7 +294,7 @@ func (service searchService) getImagesByCveIDGQL(ctx context.Context, config sea ) (*common.ImagesForCve, error) { query := fmt.Sprintf(` { - ImageListForCVE(id: "%s") { + ImageListForCVE(id: "%s", requestedPage: {sortBy: ALPHABETIC_ASC}) { Results { RepoName Tag Digest @@ -1091,23 +1091,25 @@ func (cve cveResult) stringPlainText() (string, error) { } func (cve cveResult) stringJSON() (string, error) { + // Output is in json lines format - do not indent, append new line after json json := jsoniter.ConfigCompatibleWithStandardLibrary - body, err := json.MarshalIndent(cve.Data.CVEListForImage, "", " ") + body, err := json.Marshal(cve.Data.CVEListForImage) if err != nil { return "", err } - return string(body), nil + return string(body) + "\n", nil } func (cve cveResult) stringYAML() (string, error) { + // Output will be a multidoc yaml - use triple-dash to indicate a new document body, err := yaml.Marshal(&cve.Data.CVEListForImage) if err != nil { return "", err } - return string(body), nil + return "---\n" + string(body), nil } type referrersResult []common.Referrer @@ -1153,23 +1155,25 @@ func (ref referrersResult) stringPlainText(maxArtifactTypeLen int) (string, erro } func (ref referrersResult) stringJSON() (string, error) { + // Output is in json lines format - do not indent, append new line after json json := jsoniter.ConfigCompatibleWithStandardLibrary - body, err := json.MarshalIndent(ref, "", " ") + body, err := json.Marshal(ref) if err != nil { return "", err } - return string(body), nil + return string(body) + "\n", nil } func (ref referrersResult) stringYAML() (string, error) { + // Output will be a multidoc yaml - use triple-dash to indicate a new document body, err := yaml.Marshal(ref) if err != nil { return "", err } - return string(body), nil + return "---\n" + string(body), nil } type repoStruct common.RepoSummary @@ -1243,23 +1247,25 @@ func (repo repoStruct) stringPlainText(repoMaxLen, maxTimeLen int, verbose bool) } func (repo repoStruct) stringJSON() (string, error) { + // Output is in json lines format - do not indent, append new line after json json := jsoniter.ConfigCompatibleWithStandardLibrary - body, err := json.MarshalIndent(repo, "", " ") + body, err := json.Marshal(repo) if err != nil { return "", err } - return string(body), nil + return string(body) + "\n", nil } func (repo repoStruct) stringYAML() (string, error) { + // Output will be a multidoc yaml - use triple-dash to indicate a new document body, err := yaml.Marshal(&repo) if err != nil { return "", err } - return string(body), nil + return "---\n" + string(body), nil } type imageStruct common.ImageSummary @@ -1466,23 +1472,25 @@ func getPlatformStr(platf common.Platform) string { } func (img imageStruct) stringJSON() (string, error) { + // Output is in json lines format - do not indent, append new line after json json := jsoniter.ConfigCompatibleWithStandardLibrary - body, err := json.MarshalIndent(img, "", " ") + body, err := json.Marshal(img) if err != nil { return "", err } - return string(body), nil + return string(body) + "\n", nil } func (img imageStruct) stringYAML() (string, error) { + // Output will be a multidoc yaml - use triple-dash to indicate a new document body, err := yaml.Marshal(&img) if err != nil { return "", err } - return string(body), nil + return "---\n" + string(body), nil } type catalogResponse struct { diff --git a/pkg/extensions/search/convert/repodb.go b/pkg/extensions/search/convert/repodb.go index e077afbe..207b8491 100644 --- a/pkg/extensions/search/convert/repodb.go +++ b/pkg/extensions/search/convert/repodb.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "sort" "strconv" "strings" "time" @@ -572,7 +573,20 @@ func RepoMeta2ImageSummaries(ctx context.Context, repoMeta repodb.RepoMetadata, ) []*gql_generated.ImageSummary { imageSummaries := make([]*gql_generated.ImageSummary, 0, len(repoMeta.Tags)) - for tag, descriptor := range repoMeta.Tags { + // Make sure the tags are sorted + // We need to implement a proper fix for this taking into account + // the sorting criteria used in the requested page + tags := make([]string, 0, len(repoMeta.Tags)) + for tag := range repoMeta.Tags { + tags = append(tags, tag) + } + + // Sorting ascending by tag name should do for now + sort.Strings(tags) + + for _, tag := range tags { + descriptor := repoMeta.Tags[tag] + imageSummary, _, err := Descriptor2ImageSummary(ctx, descriptor, repoMeta.Name, tag, skip.Vulnerabilities, repoMeta, manifestMetaMap, indexDataMap, cveInfo) if err != nil { diff --git a/pkg/storage/scrub.go b/pkg/storage/scrub.go index 492a0d07..327ddb30 100644 --- a/pkg/storage/scrub.go +++ b/pkg/storage/scrub.go @@ -268,7 +268,7 @@ func printScrubTableHeader(writer io.Writer) { row := make([]string, tableCols) - row[colImageNameIndex] = "IMAGE NAME" + row[colImageNameIndex] = "REPOSITORY" row[colTagIndex] = "TAG" row[colStatusIndex] = "STATUS" row[colErrorIndex] = "ERROR" diff --git a/pkg/storage/scrub_test.go b/pkg/storage/scrub_test.go index e90e4a10..bea4c239 100644 --- a/pkg/storage/scrub_test.go +++ b/pkg/storage/scrub_test.go @@ -85,7 +85,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 ok") }) @@ -109,7 +109,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") // verify error message So(actual, ShouldContainSubstring, "test 1.0 affected parse application/vnd.oci.image.manifest.v1+json") @@ -149,7 +149,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 affected stat: parse application/vnd.oci.image.config.v1+json") // put config content back to file @@ -177,7 +177,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 affected blob: bad blob digest") // put layer content back to file @@ -218,7 +218,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 affected blob: not found") }) @@ -269,7 +269,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 ok") So(actual, ShouldContainSubstring, "test ok") @@ -286,7 +286,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test affected") err = os.Chmod(indexFile, 0o600) @@ -303,7 +303,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test affected") }) @@ -323,7 +323,7 @@ func TestCheckAllBlobsIntegrity(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) - So(actual, ShouldContainSubstring, "IMAGE NAME TAG STATUS ERROR") + So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS ERROR") So(actual, ShouldContainSubstring, "test 1.0 affected") So(actual, ShouldContainSubstring, "no such file or directory")