0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00
zot/pkg/cli/client/image_cmd_internal_test.go
Jan-Otto Kröpke f618b1d4ef
ci(deps): upgrade golangci-lint (#2556)
* ci(deps): upgrade golangci-lint

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>

* build(deps): removed disabled linters

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>

* build(deps): go run github.com/daixiang0/gci@latest write .

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): go run golang.org/x/tools/cmd/goimports@latest -l -w .

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): go run github.com/bombsimon/wsl/v4/cmd...@latest -strict-append -test=true -fix ./...

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): go run github.com/catenacyber/perfsprint@latest -fix ./...

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): replace gomnd by mnd

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): make gqlgen

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build: Revert "build(deps): go run github.com/daixiang0/gci@latest write ."

This reverts commit 5bf8c42e1f.

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): go run github.com/daixiang0/gci@latest write -s 'standard' -s default -s 'prefix(zotregistry.dev/zot)' .

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* build(deps): make gqlgen

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: wsl issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: check-log issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: gci issues

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

* fix: tests

Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>

---------

Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
2024-07-29 10:32:51 -07:00

1592 lines
48 KiB
Go

//go:build search
// +build search
package client
import (
"bytes"
"context"
"errors"
"fmt"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"sync"
"testing"
"time"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
. "github.com/smartystreets/goconvey/convey"
zerr "zotregistry.dev/zot/errors"
"zotregistry.dev/zot/pkg/api"
"zotregistry.dev/zot/pkg/api/config"
"zotregistry.dev/zot/pkg/common"
extconf "zotregistry.dev/zot/pkg/extensions/config"
stypes "zotregistry.dev/zot/pkg/storage/types"
test "zotregistry.dev/zot/pkg/test/common"
. "zotregistry.dev/zot/pkg/test/image-utils"
)
func TestSearchImageCmd(t *testing.T) {
Convey("Test image help", t, func() {
args := []string{"--help"}
configPath := makeConfigFile("")
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(buff.String(), ShouldContainSubstring, "Usage")
So(err, ShouldBeNil)
Convey("with the shorthand", func() {
args[0] = "-h"
configPath := makeConfigFile("")
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(buff.String(), ShouldContainSubstring, "Usage")
So(err, ShouldBeNil)
})
})
Convey("Test image no url", t, func() {
args := []string{"name", "dummyIdRandom", "--config", "imagetest"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
So(errors.Is(err, zerr.ErrNoURLProvided), ShouldBeTrue)
})
Convey("Test image invalid home directory", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
err := os.Setenv("HOME", "nonExistentDirectory")
if err != nil {
panic(err)
}
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
err = os.Setenv("HOME", home)
if err != nil {
log.Fatal(err)
}
})
Convey("Test image no params", t, func() {
args := []string{"--url", "someUrl"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldBeNil)
})
Convey("Test image invalid url", t, func() {
args := []string{"name", "dummyImageName", "--url", "invalidUrl"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
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(strings.Contains(err.Error(), zerr.ErrInvalidURL.Error()), ShouldBeTrue)
So(buff.String(), ShouldContainSubstring, "invalid URL format")
})
Convey("Test image invalid url port", t, func() {
args := []string{"name", "dummyImageName", "--url", "http://localhost:99999"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
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 port")
Convey("without flags", func() {
args := []string{"list", "--url", "http://localhost:99999"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
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 port")
})
})
Convey("Test image unreachable", t, func() {
args := []string{"name", "dummyImageName", "--url", "http://localhost:9999"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
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)
})
Convey("Test image url from config", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
So(strings.TrimSpace(str), ShouldEqual,
"REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
So(err, ShouldBeNil)
})
Convey("Test image by name", t, func() {
args := []string{"name", "dummyImageName", "--url", "http://127.0.0.1:8080"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
defer os.Remove(configPath)
imageCmd := NewImageCommand(new(mockService))
buff := &bytes.Buffer{}
imageCmd.SetOut(buff)
imageCmd.SetErr(buff)
imageCmd.SetArgs(args)
err := imageCmd.Execute()
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
So(strings.TrimSpace(str), ShouldEqual,
"REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
So(err, ShouldBeNil)
})
Convey("Test image by digest", t, func() {
searchConfig := getTestSearchConfig("http://127.0.0.1:8080", new(mockService))
buff := &bytes.Buffer{}
searchConfig.ResultWriter = buff
err := SearchImagesByDigest(searchConfig, "6e2f80bf")
So(err, ShouldBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
So(strings.TrimSpace(str), ShouldEqual,
"REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB")
So(err, ShouldBeNil)
})
}
func TestListRepos(t *testing.T) {
searchConfig := getTestSearchConfig("https://test-url.com", new(mockService))
Convey("Test listing repositories", t, func() {
buff := &bytes.Buffer{}
searchConfig.ResultWriter = buff
err := SearchRepos(searchConfig)
So(err, ShouldBeNil)
})
Convey("Test listing repositories with debug flag", t, func() {
args := []string{"list", "--config", "config-test", "--debug"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(searchService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring, "GET")
})
Convey("Test error on home directory", t, func() {
args := []string{"list", "--config", "config-test"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
err := os.Setenv("HOME", "nonExistentDirectory")
if err != nil {
panic(err)
}
cmd := NewRepoCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
err = os.Setenv("HOME", home)
if err != nil {
log.Fatal(err)
}
})
Convey("Test listing repositories error", t, func() {
args := []string{"list", "--config", "config-test"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test",
"url":"https://invalid.invalid","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(searchService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("Test unable to get config value", t, func() {
args := []string{"list", "--config", "config-test-nonexistent"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("Test error - no url provided", t, func() {
args := []string{"list", "--config", "config-test"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("Test error - spinner config invalid", t, func() {
args := []string{"list", "--config", "config-test"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test",
"url":"https://test-url.com","showspinner":invalid}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("Test error - verifyTLSConfig fails", t, func() {
args := []string{"list", "--config", "config-test"}
configPath := makeConfigFile(`{"configs":[{"_name":"config-test",
"verify-tls":"invalid", "url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewRepoCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
}
func TestOutputFormat(t *testing.T) {
Convey("Test text", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "text"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
So(strings.TrimSpace(str), ShouldEqual,
"REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE dummyImageName tag os/arch 6e2f80bf false 123kB")
So(err, ShouldBeNil)
})
Convey("Test json", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "json"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
// 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":"","unknownCount":0,"lowCount":0,`+
`"mediumCount":0,"highCount":0,"criticalCount":0,"count":0},`+
`"referrers":null,"artifactType":"","signatureInfo":null}],"size":"123445",`+
`"downloadCount":0,"lastUpdated":"0001-01-01T00:00:00Z","description":"","isSigned":false,"licenses":"",`+
`"labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",`+
`"vulnerabilities":{"maxSeverity":"","unknownCount":0,"lowCount":0,"mediumCount":0,"highCount":0,`+
`"criticalCount":0,"count":0},"referrers":null,"signatureInfo":null}`+"\n")
So(err, ShouldBeNil)
})
Convey("Test yaml", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "yaml"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
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: [] vulnerabilities: maxseverity: "" `+
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 `+
`referrers: [] artifacttype: "" `+
`signatureinfo: [] size: "123445" downloadcount: 0 `+
`lastupdated: 0001-01-01T00:00:00Z description: "" issigned: false licenses: "" labels: "" `+
`title: "" source: "" documentation: "" authors: "" vendor: "" vulnerabilities: maxseverity: "" `+
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 `+
`count: 0 referrers: [] signatureinfo: []`,
)
So(err, ShouldBeNil)
Convey("Test yml", func() {
args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "yml"}
configPath := makeConfigFile(
`{"configs":[{"_name":"imagetest",` +
`"url":"https://test-url.com","showspinner":false}]}`,
)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
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: [] vulnerabilities: maxseverity: "" unknowncount: 0 lowcount: 0 mediumcount: 0 `+
`highcount: 0 criticalcount: 0 count: 0 referrers: [] artifacttype: "" `+
`signatureinfo: [] size: "123445" downloadcount: 0 `+
`lastupdated: 0001-01-01T00:00:00Z description: "" issigned: false licenses: "" labels: "" `+
`title: "" source: "" documentation: "" authors: "" vendor: "" vulnerabilities: maxseverity: "" `+
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 `+
`count: 0 referrers: [] signatureinfo: []`,
)
So(err, ShouldBeNil)
})
})
Convey("Test invalid", t, func() {
args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "random"}
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
defer os.Remove(configPath)
cmd := NewImageCommand(new(mockService))
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
So(buff.String(), ShouldContainSubstring, "invalid cli output format")
})
}
func TestImagesCommandGQL(t *testing.T) {
port := test.GetFreePort()
baseURL := 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()
Convey("commands with gql", t, func() {
err := removeLocalStorageContents(ctlr.StoreController.DefaultStore)
So(err, ShouldBeNil)
Convey("base and derived command", func() {
baseImage := CreateImageWith().LayerBlobs(
[][]byte{{1, 2, 3}, {11, 22, 33}},
).DefaultConfig().Build()
derivedImage := CreateImageWith().LayerBlobs(
[][]byte{{1, 2, 3}, {11, 22, 33}, {44, 55, 66}},
).DefaultConfig().Build()
err := UploadImage(baseImage, baseURL, "repo", "base")
So(err, ShouldBeNil)
err = UploadImage(derivedImage, baseURL, "repo", "derived")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"base", "repo:derived", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
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)
So(actual, ShouldContainSubstring, "repo base linux/amd64 df554ddd false 699B")
args = []string{"derived", "repo:base", "--config", "imagetest"}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
str = space.ReplaceAllString(buff.String(), " ")
actual = strings.TrimSpace(str)
So(actual, ShouldContainSubstring, "repo derived linux/amd64 79f4b82e false 854B")
})
Convey("base and derived command errors", func() {
// too many parameters
buff := bytes.NewBufferString("")
args := []string{"too", "many", "args", "--config", "imagetest"}
cmd := NewImageBaseCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
cmd = NewImageDerivedCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
// bad input
buff = bytes.NewBufferString("")
args = []string{"only-repo"}
cmd = NewImageBaseCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
cmd = NewImageDerivedCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
// no url
buff = bytes.NewBufferString("")
args = []string{"repo:tag"}
cmd = NewImageBaseCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
cmd = NewImageDerivedCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("digest command", func() {
image := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"digest", image.DigestStr(), "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
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)
So(actual, ShouldContainSubstring, fmt.Sprintf("repo img linux/amd64 %s false 552B",
image.DigestStr()[7:7+8]))
})
Convey("digest command errors", func() {
// too many parameters
buff := bytes.NewBufferString("")
args := []string{"too", "many", "args", "--config", "imagetest"}
cmd := NewImageDigestCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
// bad input
buff = bytes.NewBufferString("")
args = []string{"bad-digest"}
cmd = NewImageDigestCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
// no url
buff = bytes.NewBufferString("")
args = []string{godigest.FromString("str").String()}
cmd = NewImageDigestCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("list command", func() {
image := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"list", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
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)
fmt.Println(actual)
So(actual, ShouldContainSubstring, fmt.Sprintf("repo img linux/amd64 %s false 552B",
image.DigestStr()[7:7+8]))
fmt.Println(actual)
})
Convey("list command errors", func() {
// too many parameters
buff := bytes.NewBufferString("")
args := []string{"repo:img", "arg", "--config", "imagetest"}
cmd := NewImageListCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
// no url
buff = bytes.NewBufferString("")
args = []string{}
cmd = NewImageListCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("name command", func() {
image := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
err = UploadImage(CreateRandomImage(), baseURL, "repo", "img2")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"name", "repo:img", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
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)
fmt.Println(actual)
So(actual, ShouldContainSubstring, fmt.Sprintf("repo img linux/amd64 %s false 552B",
image.DigestStr()[7:7+8]))
fmt.Println(actual)
})
Convey("name command errors", func() {
// too many parameters
buff := bytes.NewBufferString("")
args := []string{"repo:img", "arg", "--config", "imagetest"}
cmd := NewImageNameCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
// bad input
buff = bytes.NewBufferString("")
args = []string{":tag"}
cmd = NewImageNameCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
// no url
buff = bytes.NewBufferString("")
args = []string{"repo:tag"}
cmd = NewImageNameCommand(NewSearchService())
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("CVE", func() {
vulnImage := CreateDefaultVulnerableImage()
err := UploadImage(vulnImage, baseURL, "repo", "vuln")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"cve", "repo:vuln", "--config", "imagetest"}
cmd := NewImageCommand(mockService{})
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)
So(actual, ShouldContainSubstring, "CRITICAL 0, HIGH 1, MEDIUM 0, LOW 0, UNKNOWN 0, TOTAL 1")
So(actual, ShouldContainSubstring, "dummyCVEID HIGH Title of that CVE")
})
Convey("CVE errors", func() {
count := 0
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"cve", "repo:vuln", "--config", "imagetest"}
cmd := NewImageCommand(mockService{
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username, password,
imageName, searchedCVE string) (*cveResult, error,
) {
if count == 0 {
count++
fmt.Println("Count:", count)
return &cveResult{}, zerr.ErrCVEDBNotFound
}
return &cveResult{}, zerr.ErrInjected
},
})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring, "[warning] CVE DB is not ready")
})
})
Convey("Config error", t, func() {
args := []string{"base", "repo:derived", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
So(err, ShouldNotBeNil)
args = []string{"derived", "repo:base"}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
args = []string{"digest", ispec.DescriptorEmptyJSON.Digest.String()}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
args = []string{"list"}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
args = []string{"name", "repo:img"}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
args = []string{"cve", "repo:vuln"}
cmd = NewImageCommand(mockService{})
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
}
func TestImageCommandREST(t *testing.T) {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("commands without gql", t, func() {
err := removeLocalStorageContents(ctlr.StoreController.DefaultStore)
So(err, ShouldBeNil)
Convey("base and derived command", func() {
baseImage := CreateImageWith().LayerBlobs(
[][]byte{{1, 2, 3}, {11, 22, 33}},
).DefaultConfig().Build()
derivedImage := CreateImageWith().LayerBlobs(
[][]byte{{1, 2, 3}, {11, 22, 33}, {44, 55, 66}},
).DefaultConfig().Build()
err := UploadImage(baseImage, baseURL, "repo", "base")
So(err, ShouldBeNil)
err = UploadImage(derivedImage, baseURL, "repo", "derived")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"base", "repo:derived", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
args = []string{"derived", "repo:base"}
cmd = NewImageCommand(NewSearchService())
buff = bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("digest command", func() {
image := CreateRandomImage()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"digest", image.DigestStr(), "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("list command", func() {
image := CreateRandomImage()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"list", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
fmt.Println(buff.String())
fmt.Println()
})
Convey("name command", func() {
image := CreateRandomImage()
err := UploadImage(image, baseURL, "repo", "img")
So(err, ShouldBeNil)
err = UploadImage(CreateRandomImage(), baseURL, "repo", "img2")
So(err, ShouldBeNil)
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
args := []string{"name", "repo:img", "--config", "imagetest"}
cmd := NewImageCommand(NewSearchService())
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
fmt.Println(buff.String())
fmt.Println()
})
Convey("CVE", func() {
vulnImage := CreateDefaultVulnerableImage()
err := UploadImage(vulnImage, baseURL, "repo", "vuln")
So(err, ShouldBeNil)
args := []string{"cve", "repo:vuln", "--config", "imagetest"}
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
cmd := NewImageCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldNotBeNil)
})
})
}
type mockService struct {
getAllImagesFn func(ctx context.Context, config SearchConfig, username, password string,
channel chan stringResult, wtgrp *sync.WaitGroup)
getImagesGQLFn func(ctx context.Context, config SearchConfig, username, password string,
imageName string) (*common.ImageListResponse, error)
getImageByNameFn func(ctx context.Context, config SearchConfig,
username, password, imageName string, channel chan stringResult, wtgrp *sync.WaitGroup,
)
getImagesByDigestFn func(ctx context.Context, config SearchConfig, username,
password, digest string, rch chan stringResult, wtgrp *sync.WaitGroup,
)
getReferrersFn func(ctx context.Context, config SearchConfig, username, password string,
repo, digest string,
) (referrersResult, error)
globalSearchGQLFn func(ctx context.Context, config SearchConfig, username, password string,
query string,
) (*common.GlobalSearch, error)
getReferrersGQLFn func(ctx context.Context, config SearchConfig, username, password string,
repo, digest string,
) (*common.ReferrersResp, error)
getDerivedImageListGQLFn func(ctx context.Context, config SearchConfig, username, password string,
derivedImage string,
) (*common.DerivedImageListResponse, error)
getBaseImageListGQLFn func(ctx context.Context, config SearchConfig, username, password string,
derivedImage string,
) (*common.BaseImageListResponse, error)
getImagesForDigestGQLFn func(ctx context.Context, config SearchConfig, username, password string,
digest string,
) (*common.ImagesForDigest, error)
getCveByImageGQLFn func(ctx context.Context, config SearchConfig, username, password,
imageName, searchedCVE string,
) (*cveResult, error)
getTagsForCVEGQLFn func(ctx context.Context, config SearchConfig, username, password,
imageName, cveID string,
) (*common.ImagesForCve, error)
getFixedTagsForCVEGQLFn func(ctx context.Context, config SearchConfig, username, password,
imageName, cveID string,
) (*common.ImageListWithCVEFixedResponse, error)
getCVEDiffListGQLFn func(ctx context.Context, config SearchConfig, username, password string,
minuend, subtrahend ImageIdentifier,
) (*cveDiffListResp, error)
}
func (service mockService) getCVEDiffListGQL(ctx context.Context, config SearchConfig, username, password string,
minuend, subtrahend ImageIdentifier,
) (*cveDiffListResp, error) {
if service.getCVEDiffListGQLFn != nil {
return service.getCVEDiffListGQLFn(ctx, config, username, password, minuend, subtrahend)
}
return &cveDiffListResp{}, nil
}
func (service mockService) getRepos(ctx context.Context, config SearchConfig, username,
password string, channel chan stringResult, wtgrp *sync.WaitGroup,
) {
defer wtgrp.Done()
defer close(channel)
fmt.Fprintln(config.ResultWriter, "\n\nREPOSITORY NAME")
fmt.Fprintln(config.ResultWriter, "repo1")
fmt.Fprintln(config.ResultWriter, "repo2")
}
func (service mockService) getReferrers(ctx context.Context, config SearchConfig, username, password string,
repo, digest string,
) (referrersResult, error) {
if service.getReferrersFn != nil {
return service.getReferrersFn(ctx, config, username, password, repo, digest)
}
return referrersResult{
common.Referrer{
ArtifactType: "art.type",
Digest: ispec.DescriptorEmptyJSON.Digest.String(),
MediaType: ispec.MediaTypeImageManifest,
Size: 100,
},
}, nil
}
func (service mockService) globalSearchGQL(ctx context.Context, config SearchConfig, username, password string,
query string,
) (*common.GlobalSearch, error) {
if service.globalSearchGQLFn != nil {
return service.globalSearchGQLFn(ctx, config, username, password, query)
}
return &common.GlobalSearch{
Images: []common.ImageSummary{
{
RepoName: "repo",
MediaType: ispec.MediaTypeImageManifest,
Size: "100",
Manifests: []common.ManifestSummary{
{
Digest: godigest.FromString("str").String(),
Size: "100",
ConfigDigest: ispec.DescriptorEmptyJSON.Digest.String(),
},
},
},
},
Repos: []common.RepoSummary{
{
Name: "repo",
Size: "100",
LastUpdated: time.Date(2010, 1, 1, 1, 1, 1, 0, time.UTC),
},
},
}, nil
}
func (service mockService) getReferrersGQL(ctx context.Context, config SearchConfig, username, password string,
repo, digest string,
) (*common.ReferrersResp, error) {
if service.getReferrersGQLFn != nil {
return service.getReferrersGQLFn(ctx, config, username, password, repo, digest)
}
return &common.ReferrersResp{
ReferrersResult: common.ReferrersResult{
Referrers: []common.Referrer{
{
MediaType: "MediaType",
ArtifactType: "ArtifactType",
Size: 100,
Digest: "Digest",
},
},
},
}, nil
}
func (service mockService) getDerivedImageListGQL(ctx context.Context, config SearchConfig, username, password string,
derivedImage string,
) (*common.DerivedImageListResponse, error) {
if service.getDerivedImageListGQLFn != nil {
return service.getDerivedImageListGQLFn(ctx, config, username, password, derivedImage)
}
imageListGQLResponse := &common.DerivedImageListResponse{}
imageListGQLResponse.DerivedImageList.Results = []common.ImageSummary{
{
RepoName: "dummyImageName",
Tag: "tag",
Manifests: []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Size: "123445",
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Platform: common.Platform{Os: "os", Arch: "arch"},
},
},
Size: "123445",
},
}
return imageListGQLResponse, nil
}
func (service mockService) getBaseImageListGQL(ctx context.Context, config SearchConfig, username, password string,
baseImage string,
) (*common.BaseImageListResponse, error) {
if service.getBaseImageListGQLFn != nil {
return service.getBaseImageListGQLFn(ctx, config, username, password, baseImage)
}
imageListGQLResponse := &common.BaseImageListResponse{}
imageListGQLResponse.BaseImageList.Results = []common.ImageSummary{
{
RepoName: "dummyImageName",
Tag: "tag",
Manifests: []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Size: "123445",
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Platform: common.Platform{Os: "os", Arch: "arch"},
},
},
Size: "123445",
},
}
return imageListGQLResponse, nil
}
func (service mockService) getImagesGQL(ctx context.Context, config SearchConfig, username, password string,
imageName string,
) (*common.ImageListResponse, error) {
if service.getImagesGQLFn != nil {
return service.getImagesGQLFn(ctx, config, username, password, imageName)
}
imageListGQLResponse := &common.ImageListResponse{}
imageListGQLResponse.PaginatedImagesResult.Results = []common.ImageSummary{
{
RepoName: "dummyImageName",
Tag: "tag",
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromString("test").String(),
Manifests: []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Size: "123445",
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Platform: common.Platform{Os: "os", Arch: "arch"},
},
},
Size: "123445",
},
}
return imageListGQLResponse, nil
}
func (service mockService) getImagesForDigestGQL(ctx context.Context, config SearchConfig, username, password string,
digest string,
) (*common.ImagesForDigest, error) {
if service.getImagesForDigestGQLFn != nil {
return service.getImagesForDigestGQLFn(ctx, config, username, password, digest)
}
imageListGQLResponse := &common.ImagesForDigest{}
imageListGQLResponse.Results = []common.ImageSummary{
{
RepoName: "randomimageName",
Tag: "tag",
MediaType: ispec.MediaTypeImageManifest,
Digest: godigest.FromString("test").String(),
Manifests: []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Size: "123445",
Platform: common.Platform{Os: "os", Arch: "arch"},
},
},
Size: "123445",
},
}
return imageListGQLResponse, nil
}
func (service mockService) getTagsForCVEGQL(ctx context.Context, config SearchConfig, username, password,
imageName, cveID string,
) (*common.ImagesForCve, error) {
if service.getTagsForCVEGQLFn != nil {
return service.getTagsForCVEGQLFn(ctx, config, username, password, imageName, cveID)
}
images := &common.ImagesForCve{
Errors: nil,
ImagesForCVEList: struct {
common.PaginatedImagesResult `json:"ImageListForCVE"` //nolint:tagliatelle // graphQL schema
}{},
}
if imageName == "" {
imageName = "image-name"
}
images.Errors = nil
mockedImage := service.getMockedImageByName(imageName)
images.Results = []common.ImageSummary{common.ImageSummary(mockedImage)}
return images, nil
}
func (service mockService) getFixedTagsForCVEGQL(ctx context.Context, config SearchConfig, username, password,
imageName, cveID string,
) (*common.ImageListWithCVEFixedResponse, error) {
if service.getFixedTagsForCVEGQLFn != nil {
return service.getFixedTagsForCVEGQLFn(ctx, config, username, password, imageName, cveID)
}
fixedTags := &common.ImageListWithCVEFixedResponse{
Errors: nil,
ImageListWithCVEFixed: struct {
common.PaginatedImagesResult `json:"ImageListWithCVEFixed"` //nolint:tagliatelle // graphQL schema
}{},
}
fixedTags.Errors = nil
mockedImage := service.getMockedImageByName(imageName)
fixedTags.Results = []common.ImageSummary{common.ImageSummary(mockedImage)}
return fixedTags, nil
}
func (service mockService) getCveByImageGQL(ctx context.Context, config SearchConfig, username, password,
imageName, searchedCVE string,
) (*cveResult, error) {
if service.getCveByImageGQLFn != nil {
return service.getCveByImageGQLFn(ctx, config, username, password, imageName, searchedCVE)
}
cveRes := &cveResult{}
cveRes.Data = cveData{
CVEListForImage: cveListForImage{
Tag: imageName,
CVEList: []cve{
{
ID: "dummyCVEID",
Description: "Description of the CVE",
Title: "Title of that CVE",
Severity: "HIGH",
PackageList: []packageList{
{
Name: "packagename",
FixedVersion: "fixedver",
InstalledVersion: "installedver",
},
},
},
},
Summary: common.ImageVulnerabilitySummary{
Count: 1,
UnknownCount: 0,
LowCount: 0,
MediumCount: 0,
HighCount: 1,
CriticalCount: 0,
MaxSeverity: "HIGH",
},
},
}
return cveRes, nil
}
//nolint:goconst
func (service mockService) getMockedImageByName(imageName string) imageStruct {
image := imageStruct{}
image.RepoName = imageName
image.Tag = "tag"
image.MediaType = ispec.MediaTypeImageManifest
image.Manifests = []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Size: "123445",
Platform: common.Platform{Os: "os", Arch: "arch"},
},
}
image.Size = "123445"
return image
}
func (service mockService) getAllImages(ctx context.Context, config SearchConfig, username, password string,
channel chan stringResult, wtgrp *sync.WaitGroup,
) {
defer wtgrp.Done()
defer close(channel)
if service.getAllImagesFn != nil {
service.getAllImagesFn(ctx, config, username, password, channel, wtgrp)
return
}
image := &imageStruct{}
image.RepoName = "randomimageName"
image.Tag = "tag"
image.Digest = godigest.FromString("test").String()
image.MediaType = ispec.MediaTypeImageManifest
image.Manifests = []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Size: "123445",
Platform: common.Platform{Os: "os", Arch: "arch"},
},
}
image.Size = "123445"
str, err := image.string(config.OutputFormat, len(image.RepoName), len(image.Tag), len("os/Arch"), config.Verbose)
if err != nil {
channel <- stringResult{"", err}
return
}
channel <- stringResult{str, nil}
}
func (service mockService) getImageByName(ctx context.Context, config SearchConfig,
username, password, imageName string, channel chan stringResult, wtgrp *sync.WaitGroup,
) {
defer wtgrp.Done()
defer close(channel)
if service.getImageByNameFn != nil {
service.getImageByNameFn(ctx, config, username, password, imageName, channel, wtgrp)
return
}
image := &imageStruct{}
image.RepoName = imageName
image.Tag = "tag"
image.Digest = godigest.FromString("test").String()
image.MediaType = ispec.MediaTypeImageManifest
image.Manifests = []common.ManifestSummary{
{
Digest: godigest.FromString("Digest").String(),
ConfigDigest: godigest.FromString("ConfigDigest").String(),
Layers: []common.LayerSummary{{Digest: godigest.FromString("LayerDigest").String()}},
Size: "123445",
Platform: common.Platform{Os: "os", Arch: "arch"},
},
}
image.Size = "123445"
str, err := image.string(config.OutputFormat, len(image.RepoName), len(image.Tag), len("os/Arch"), config.Verbose)
if err != nil {
channel <- stringResult{"", err}
return
}
channel <- stringResult{str, nil}
}
func (service mockService) getImagesByDigest(ctx context.Context, config SearchConfig, username,
password, digest string, rch chan stringResult, wtgrp *sync.WaitGroup,
) {
if service.getImagesByDigestFn != nil {
defer wtgrp.Done()
defer close(rch)
service.getImagesByDigestFn(ctx, config, username, password, digest, rch, wtgrp)
return
}
service.getImageByName(ctx, config, username, password, "anImage", rch, wtgrp)
}
func makeConfigFile(content string) string {
os.Setenv("HOME", os.TempDir())
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
configPath := path.Join(home, "/.zot")
if err := os.WriteFile(configPath, []byte(content), 0o600); err != nil {
panic(err)
}
return configPath
}
func getTestSearchConfig(url string, searchService SearchService) SearchConfig {
var (
user string
outputFormat string
verbose bool
debug bool
verifyTLS bool
)
return SearchConfig{
SearchService: searchService,
SortBy: "alpha-asc",
ServURL: url,
User: user,
OutputFormat: outputFormat,
Verbose: verbose,
Debug: debug,
VerifyTLS: verifyTLS,
ResultWriter: nil,
}
}
func removeLocalStorageContents(imageStore stypes.ImageStore) error {
repos, err := imageStore.GetRepositories()
if err != nil {
return err
}
for _, repo := range repos {
// take just the first path
err = os.RemoveAll(filepath.Join(imageStore.RootDir(), filepath.SplitList(repo)[0]))
if err != nil {
return err
}
}
return nil
}