mirror of
https://github.com/project-zot/zot.git
synced 2026-06-17 21:17:58 +08:00
fix(zli): Improve zli CVE diff output (#3994)
* fix(cli): improve zli CVE diff output Signed-off-by: Akash Kumar <meakash7902@gmail.com> * test(api): avoid TestRoutes port collision Signed-off-by: Akash Kumar <meakash7902@gmail.com> * test(cli): cover CVE diff formatting helpers Signed-off-by: Akash Kumar <meakash7902@gmail.com> * test(search): remove redundant test case copy Signed-off-by: Akash Kumar <meakash7902@gmail.com> --------- Signed-off-by: Akash Kumar <meakash7902@gmail.com>
This commit is contained in:
@@ -386,6 +386,7 @@ func TestCVEDiffList(t *testing.T) {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(str, ShouldContainSubstring, "CVEs in image repo:image that are not in image repo:base-image")
|
||||
So(str, ShouldContainSubstring, "CVE3")
|
||||
So(str, ShouldNotContainSubstring, "CVE1")
|
||||
So(str, ShouldNotContainSubstring, "CVE2")
|
||||
@@ -406,6 +407,22 @@ func TestCVEDiffList(t *testing.T) {
|
||||
cveCmd.SetArgs(args)
|
||||
So(cveCmd.Execute(), ShouldNotBeNil)
|
||||
})
|
||||
Convey("Minuend image not found includes image name", func() {
|
||||
args := []string{"diff", "repo:missing-image", "repo:base-image", "--config", "cvetest"}
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldContainSubstring, "minuend image repo:missing-image")
|
||||
So(err.Error(), ShouldContainSubstring, "image not found")
|
||||
})
|
||||
Convey("Subtrahend image not found includes image name", func() {
|
||||
args := []string{"diff", "repo:image", "repo:missing-base", "--config", "cvetest"}
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldContainSubstring, "subtrahend image repo:missing-base")
|
||||
So(err.Error(), ShouldContainSubstring, "image not found")
|
||||
})
|
||||
Convey("Second input is arch but not enough args", func() {
|
||||
args := []string{"diff", "repo:base-image", "linux/amd64", "--config", "cvetest"}
|
||||
cveCmd.SetArgs(args)
|
||||
|
||||
@@ -297,6 +297,9 @@ func SearchCVEDiffList(config SearchConfig, minuend, subtrahend ImageIdentifier)
|
||||
var builder strings.Builder
|
||||
|
||||
if config.OutputFormat == defaultOutputFormat || config.OutputFormat == "" {
|
||||
fmt.Fprintf(config.ResultWriter, "CVEs in image %s that are not in image %s\n\n",
|
||||
formatImageIdentifier(cveDiffResult.Minuend), formatImageIdentifier(cveDiffResult.Subtrahend))
|
||||
|
||||
imageCVESummary := result.Data.CVEListForImage.Summary
|
||||
|
||||
statsStr := fmt.Sprintf("CRITICAL %d, HIGH %d, MEDIUM %d, LOW %d, UNKNOWN %d, TOTAL %d\n\n",
|
||||
@@ -319,6 +322,25 @@ func SearchCVEDiffList(config SearchConfig, minuend, subtrahend ImageIdentifier)
|
||||
return nil
|
||||
}
|
||||
|
||||
func formatImageIdentifier(image ImageIdentifier) string {
|
||||
if image.Repo == "" {
|
||||
return "unknown image"
|
||||
}
|
||||
|
||||
name := image.Repo
|
||||
if image.Tag != "" {
|
||||
name += ":" + image.Tag
|
||||
} else if image.Digest != "" {
|
||||
name += "@" + image.Digest
|
||||
}
|
||||
|
||||
if image.Platform != nil && image.Platform.Os != "" && image.Platform.Arch != "" {
|
||||
name += fmt.Sprintf(" (%s/%s)", image.Platform.Os, image.Platform.Arch)
|
||||
}
|
||||
|
||||
return name
|
||||
}
|
||||
|
||||
func SearchImagesByCVEIDGQL(config SearchConfig, repo, cveid string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
@@ -561,6 +561,58 @@ func TestSearchCVEForImageGQL(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatImageIdentifier(t *testing.T) {
|
||||
Convey("Format image identifier", t, func() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
image ImageIdentifier
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "unknown image",
|
||||
image: ImageIdentifier{},
|
||||
expected: "unknown image",
|
||||
},
|
||||
{
|
||||
name: "tag reference",
|
||||
image: ImageIdentifier{Repo: "repo", Tag: "tag"},
|
||||
expected: "repo:tag",
|
||||
},
|
||||
{
|
||||
name: "digest reference",
|
||||
image: ImageIdentifier{Repo: "repo", Digest: "sha256:123"},
|
||||
expected: "repo@sha256:123",
|
||||
},
|
||||
{
|
||||
name: "tag reference with platform",
|
||||
image: ImageIdentifier{
|
||||
Repo: "repo",
|
||||
Tag: "tag",
|
||||
Platform: &osArch{Os: "linux", Arch: "amd64"},
|
||||
},
|
||||
expected: "repo:tag (linux/amd64)",
|
||||
},
|
||||
{
|
||||
name: "partial platform is omitted",
|
||||
image: ImageIdentifier{
|
||||
Repo: "repo",
|
||||
Tag: "tag",
|
||||
Platform: &osArch{Os: "linux"},
|
||||
},
|
||||
expected: "repo:tag",
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
testCase := testCase
|
||||
|
||||
Convey(testCase.name, func() {
|
||||
So(formatImageIdentifier(testCase.image), ShouldEqual, testCase.expected)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchImagesByCVEIDGQL(t *testing.T) {
|
||||
Convey("SearchImagesByCVEIDGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
|
||||
@@ -168,8 +168,8 @@ func (service *searchService) getCVEDiffListGQL(ctx context.Context, config Sear
|
||||
query := fmt.Sprintf(`
|
||||
{
|
||||
CVEDiffListForImages( minuend: %s, subtrahend: %s ) {
|
||||
Minuend {Repo Tag}
|
||||
Subtrahend {Repo Tag}
|
||||
Minuend {Repo Tag Digest Platform {Os Arch}}
|
||||
Subtrahend {Repo Tag Digest Platform {Os Arch}}
|
||||
CVEList {
|
||||
Id Title Description Severity Reference
|
||||
PackageList {Name InstalledVersion FixedVersion}
|
||||
|
||||
Reference in New Issue
Block a user