mirror of
https://github.com/project-zot/zot.git
synced 2024-12-16 21:56:37 -05:00
refactor(test): make sure cli tests are not internal unless they need to be (#1878)
As part of this change searchConfig needed to be exported, as it was passed as a parameter to exported functions At this moment most of the tests remaining internal depend on the mock service. The interface it implements has unexported methods. Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
This commit is contained in:
parent
99e29c0f46
commit
ca1c3288cf
18 changed files with 3227 additions and 3118 deletions
|
@ -179,7 +179,7 @@ type httpJob struct {
|
|||
password string
|
||||
imageName string
|
||||
tagName string
|
||||
config searchConfig
|
||||
config SearchConfig
|
||||
}
|
||||
|
||||
const rateLimiterBuffer = 5000
|
||||
|
@ -218,8 +218,8 @@ func (p *requestsPool) doJob(ctx context.Context, job *httpJob) {
|
|||
defer p.wtgrp.Done()
|
||||
|
||||
// Check manifest media type
|
||||
header, err := makeHEADRequest(ctx, job.url, job.username, job.password, job.config.verifyTLS,
|
||||
job.config.debug)
|
||||
header, err := makeHEADRequest(ctx, job.url, job.username, job.password, job.config.VerifyTLS,
|
||||
job.config.Debug)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -227,7 +227,7 @@ func (p *requestsPool) doJob(ctx context.Context, job *httpJob) {
|
|||
p.outputCh <- stringResult{"", err}
|
||||
}
|
||||
|
||||
verbose := job.config.verbose
|
||||
verbose := job.config.Verbose
|
||||
|
||||
switch header.Get("Content-Type") {
|
||||
case ispec.MediaTypeImageManifest:
|
||||
|
@ -242,7 +242,7 @@ func (p *requestsPool) doJob(ctx context.Context, job *httpJob) {
|
|||
}
|
||||
platformStr := getPlatformStr(image.Manifests[0].Platform)
|
||||
|
||||
str, err := image.string(job.config.outputFormat, len(job.imageName), len(job.tagName), len(platformStr), verbose)
|
||||
str, err := image.string(job.config.OutputFormat, len(job.imageName), len(job.tagName), len(platformStr), verbose)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -270,7 +270,7 @@ func (p *requestsPool) doJob(ctx context.Context, job *httpJob) {
|
|||
|
||||
platformStr := getPlatformStr(image.Manifests[0].Platform)
|
||||
|
||||
str, err := image.string(job.config.outputFormat, len(job.imageName), len(job.tagName), len(platformStr), verbose)
|
||||
str, err := image.string(job.config.OutputFormat, len(job.imageName), len(job.tagName), len(platformStr), verbose)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -294,7 +294,7 @@ func fetchImageIndexStruct(ctx context.Context, job *httpJob) (*imageStruct, err
|
|||
var indexContent ispec.Index
|
||||
|
||||
header, err := makeGETRequest(ctx, job.url, job.username, job.password,
|
||||
job.config.verifyTLS, job.config.debug, &indexContent, job.config.resultWriter)
|
||||
job.config.VerifyTLS, job.config.Debug, &indexContent, job.config.ResultWriter)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return nil, context.Canceled
|
||||
|
@ -376,16 +376,16 @@ func fetchImageManifestStruct(ctx context.Context, job *httpJob) (*imageStruct,
|
|||
}, nil
|
||||
}
|
||||
|
||||
func fetchManifestStruct(ctx context.Context, repo, manifestReference string, searchConf searchConfig,
|
||||
func fetchManifestStruct(ctx context.Context, repo, manifestReference string, searchConf SearchConfig,
|
||||
username, password string,
|
||||
) (common.ManifestSummary, error) {
|
||||
manifestResp := ispec.Manifest{}
|
||||
|
||||
URL := fmt.Sprintf("%s/v2/%s/manifests/%s",
|
||||
searchConf.servURL, repo, manifestReference)
|
||||
searchConf.ServURL, repo, manifestReference)
|
||||
|
||||
header, err := makeGETRequest(ctx, URL, username, password,
|
||||
searchConf.verifyTLS, searchConf.debug, &manifestResp, searchConf.resultWriter)
|
||||
searchConf.VerifyTLS, searchConf.Debug, &manifestResp, searchConf.ResultWriter)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return common.ManifestSummary{}, context.Canceled
|
||||
|
@ -465,16 +465,16 @@ func fetchManifestStruct(ctx context.Context, repo, manifestReference string, se
|
|||
}, nil
|
||||
}
|
||||
|
||||
func fetchConfig(ctx context.Context, repo, configDigest string, searchConf searchConfig,
|
||||
func fetchConfig(ctx context.Context, repo, configDigest string, searchConf SearchConfig,
|
||||
username, password string,
|
||||
) (ispec.Image, error) {
|
||||
configContent := ispec.Image{}
|
||||
|
||||
URL := fmt.Sprintf("%s/v2/%s/blobs/%s",
|
||||
searchConf.servURL, repo, configDigest)
|
||||
searchConf.ServURL, repo, configDigest)
|
||||
|
||||
_, err := makeGETRequest(ctx, URL, username, password,
|
||||
searchConf.verifyTLS, searchConf.debug, &configContent, searchConf.resultWriter)
|
||||
searchConf.VerifyTLS, searchConf.Debug, &configContent, searchConf.ResultWriter)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return ispec.Image{}, context.Canceled
|
||||
|
@ -486,16 +486,16 @@ func fetchConfig(ctx context.Context, repo, configDigest string, searchConf sear
|
|||
return configContent, nil
|
||||
}
|
||||
|
||||
func isNotationSigned(ctx context.Context, repo, digestStr string, searchConf searchConfig,
|
||||
func isNotationSigned(ctx context.Context, repo, digestStr string, searchConf SearchConfig,
|
||||
username, password string,
|
||||
) bool {
|
||||
var referrers ispec.Index
|
||||
|
||||
URL := fmt.Sprintf("%s/v2/%s/referrers/%s?artifactType=%s",
|
||||
searchConf.servURL, repo, digestStr, common.ArtifactTypeNotation)
|
||||
searchConf.ServURL, repo, digestStr, common.ArtifactTypeNotation)
|
||||
|
||||
_, err := makeGETRequest(ctx, URL, username, password,
|
||||
searchConf.verifyTLS, searchConf.debug, &referrers, searchConf.resultWriter)
|
||||
searchConf.VerifyTLS, searchConf.Debug, &referrers, searchConf.ResultWriter)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
@ -507,16 +507,16 @@ func isNotationSigned(ctx context.Context, repo, digestStr string, searchConf se
|
|||
return false
|
||||
}
|
||||
|
||||
func isCosignSigned(ctx context.Context, repo, digestStr string, searchConf searchConfig,
|
||||
func isCosignSigned(ctx context.Context, repo, digestStr string, searchConf SearchConfig,
|
||||
username, password string,
|
||||
) bool {
|
||||
var result interface{}
|
||||
cosignTag := strings.Replace(digestStr, ":", "-", 1) + "." + remote.SignatureTagSuffix
|
||||
|
||||
URL := fmt.Sprintf("%s/v2/%s/manifests/%s", searchConf.servURL, repo, cosignTag)
|
||||
URL := fmt.Sprintf("%s/v2/%s/manifests/%s", searchConf.ServURL, repo, cosignTag)
|
||||
|
||||
_, err := makeGETRequest(ctx, URL, username, password, searchConf.verifyTLS,
|
||||
searchConf.debug, &result, searchConf.resultWriter)
|
||||
_, err := makeGETRequest(ctx, URL, username, password, searchConf.VerifyTLS,
|
||||
searchConf.Debug, &result, searchConf.ResultWriter)
|
||||
|
||||
return err == nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -9,6 +9,7 @@ import (
|
|||
"crypto/x509"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
|
@ -18,6 +19,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
extConf "zotregistry.io/zot/pkg/extensions/config"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
)
|
||||
|
@ -91,7 +93,7 @@ func TestTLSWithAuth(t *testing.T) {
|
|||
defer os.RemoveAll(destCertsDir)
|
||||
|
||||
args := []string{"name", "dummyImageName", "--url", HOST1}
|
||||
imageCmd := NewImageCommand(new(searchService))
|
||||
imageCmd := client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff := bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
||||
|
@ -105,7 +107,7 @@ func TestTLSWithAuth(t *testing.T) {
|
|||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||
defer os.Remove(configPath)
|
||||
imageCmd = NewImageCommand(new(searchService))
|
||||
imageCmd = client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff = bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
||||
|
@ -120,7 +122,7 @@ func TestTLSWithAuth(t *testing.T) {
|
|||
fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`,
|
||||
BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||
defer os.Remove(configPath)
|
||||
imageCmd = NewImageCommand(new(searchService))
|
||||
imageCmd = client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff = bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
||||
|
@ -174,7 +176,7 @@ func TestTLSWithoutAuth(t *testing.T) {
|
|||
defer os.RemoveAll(destCertsDir)
|
||||
|
||||
args := []string{"list", "--config", "imagetest"}
|
||||
imageCmd := NewImageCommand(new(searchService))
|
||||
imageCmd := client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff := bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
||||
|
@ -215,7 +217,7 @@ func TestTLSBadCerts(t *testing.T) {
|
|||
defer os.Remove(configPath)
|
||||
|
||||
args := []string{"list", "--config", "imagetest"}
|
||||
imageCmd := NewImageCommand(new(searchService))
|
||||
imageCmd := client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff := bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
||||
|
@ -226,3 +228,20 @@ func TestTLSBadCerts(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -14,6 +14,7 @@ import (
|
|||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
zerr "zotregistry.io/zot/errors"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
)
|
||||
|
||||
func TestConfigCmdBasics(t *testing.T) {
|
||||
|
@ -21,7 +22,7 @@ func TestConfigCmdBasics(t *testing.T) {
|
|||
args := []string{"--help"}
|
||||
configPath := makeConfigFile("showspinner = false")
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -33,7 +34,7 @@ func TestConfigCmdBasics(t *testing.T) {
|
|||
args[0] = "-h"
|
||||
configPath := makeConfigFile("showspinner = false")
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -48,7 +49,7 @@ func TestConfigCmdBasics(t *testing.T) {
|
|||
args := []string{}
|
||||
configPath := makeConfigFile("showspinner = false")
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -64,7 +65,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"add", "configtest1", "https://test-url.com"}
|
||||
file := makeConfigFile("")
|
||||
defer os.Remove(file)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -90,7 +91,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -118,7 +119,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
cmd := NewConfigAddCommand()
|
||||
cmd := client.NewConfigAddCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -140,7 +141,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"--list"}
|
||||
configPath := makeConfigFile(`{"configs":{"_name":"configtest","url":"https://test-url.com","showspinner":false}}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -153,7 +154,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"add", "configtest1", "test..com"}
|
||||
file := makeConfigFile("")
|
||||
defer os.Remove(file)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -167,7 +168,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"remove", "configtest"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -185,7 +186,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"remove", "configtest"}
|
||||
configPath := makeConfigFile(`{"configs":[]`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -199,7 +200,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"remove", "configtest"}
|
||||
configPath := makeConfigFile(`{"asdf":[]`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -213,7 +214,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"remove", "configtest"}
|
||||
configPath := makeConfigFile(`{"configs":[asdad]`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -232,7 +233,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
}()
|
||||
err := os.Chmod(configPath, 0o400) // Read-only, so we fail only on updating the file, not reading
|
||||
So(err, ShouldBeNil)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -246,7 +247,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"--list"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -259,7 +260,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"-l"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -273,7 +274,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"-l"}
|
||||
configPath := makeConfigFile(``)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -288,7 +289,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "--list"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -302,7 +303,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "-l"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -317,7 +318,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "-l"}
|
||||
configPath := makeConfigFile(``)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -332,7 +333,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "url"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -345,7 +346,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "url"}
|
||||
configPath := makeConfigFile(``)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -360,7 +361,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "showspinner", "false"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com"}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -381,7 +382,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "showspinner", "false"}
|
||||
configPath := makeConfigFile(``)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -396,7 +397,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "url", "https://new-url.com"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -419,7 +420,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "showspinner", "--reset"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -441,7 +442,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"configtest", "url", "--reset"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -455,7 +456,7 @@ func TestConfigCmdMain(t *testing.T) {
|
|||
args := []string{"add", "configtest", "https://test-url.com/new"}
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`)
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewConfigCommand()
|
||||
cmd := client.NewConfigCommand()
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
|
@ -6,22 +6,14 @@ package client
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
regTypes "github.com/google/go-containerregistry/pkg/v1/types"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
zerr "zotregistry.io/zot/errors"
|
||||
|
@ -29,18 +21,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api/config"
|
||||
zcommon "zotregistry.io/zot/pkg/common"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||
"zotregistry.io/zot/pkg/storage"
|
||||
"zotregistry.io/zot/pkg/storage/local"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
"zotregistry.io/zot/pkg/test/deprecated"
|
||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||
"zotregistry.io/zot/pkg/test/mocks"
|
||||
ociutils "zotregistry.io/zot/pkg/test/oci-utils"
|
||||
)
|
||||
|
||||
func TestSearchCVECmd(t *testing.T) {
|
||||
|
@ -397,659 +378,6 @@ func TestSearchCVECmd(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestNegativeServerResponse(t *testing.T) {
|
||||
Convey("Test from real server without search endpoint", t, func() {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
|
||||
err := WriteImageToFileSystem(CreateDefaultVulnerableImage(), "zot-cve-test", "0.0.1", srcStorageCtlr)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := false
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "CVE config not provided, skipping CVE update", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Convey("Status Code Not Found", func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldContainSubstring, zerr.ErrExtensionNotEnabled.Error())
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Test non-existing manifest blob", t, func() {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
imageStore := local.NewImageStore(dir, false, false,
|
||||
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), nil, nil)
|
||||
|
||||
storeController := storage.StoreController{
|
||||
DefaultStore: imageStore,
|
||||
}
|
||||
|
||||
num := 10
|
||||
config, layers, manifest, err := deprecated.GetRandomImageComponents(num) //nolint:staticcheck
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = WriteImageToFileSystem(
|
||||
Image{
|
||||
Manifest: manifest,
|
||||
Layers: layers,
|
||||
Config: config,
|
||||
}, "zot-cve-test", "0.0.1", storeController,
|
||||
)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = os.RemoveAll(path.Join(dir, "zot-cve-test/blobs"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := true
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = getMockCveScanner(ctlr.MetaDB)
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(url)
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func TestServerCVEResponse(t *testing.T) {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := true
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = getMockCveScanner(ctlr.MetaDB)
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(url)
|
||||
|
||||
config, layers, manifest, err := deprecated.GetImageComponents(100) //nolint:staticcheck
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = UploadImage(Image{Manifest: manifest, Config: config, Layers: layers}, url, "zot-cve-test", "0.0.1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Convey("Test CVE by image name - GQL - positive", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search CVE by title in results", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-C1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE-C1")
|
||||
So(str, ShouldNotContainSubstring, "CVE-2")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search CVE by id in results", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-2", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE-2")
|
||||
So(str, ShouldNotContainSubstring, "CVE-1")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search nonexistent CVE", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-100", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "No CVEs found for image")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid image", t, func() {
|
||||
args := []string{"list", "invalid:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid image name and tag", t, func() {
|
||||
args := []string{"list", "invalid:", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid output format", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
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 - GQL - invalid CVE ID", t, func() {
|
||||
args := []string{"affected", "CVE-invalid", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - invalid output format", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldEqual, "")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - random cve", t, func() {
|
||||
args := []string{"fixed", "zot-cve-test", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
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() {
|
||||
args := []string{"fixed", "zot-cv-test", "CVE-2019-20807", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
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() {
|
||||
args := []string{"fixed", "zot-cv-test:tag", "CVE-2019-20807", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"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 - GQL - invalid name and CVE ID", t, func() {
|
||||
args := []string{"affected", "CVE-20807", "--repo", "test", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
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() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := NewCVECommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCVESort(t *testing.T) {
|
||||
rootDir := t.TempDir()
|
||||
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},
|
||||
CVE: &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
|
||||
image1 := CreateRandomImage()
|
||||
|
||||
storeController := ociutils.GetDefaultStoreController(rootDir, ctlr.Log)
|
||||
|
||||
err := WriteImageToFileSystem(image1, "repo", "tag", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = mocks.CveScannerMock{
|
||||
ScanImageFn: func(image string) (map[string]cvemodel.CVE, error) {
|
||||
return map[string]cvemodel.CVE{
|
||||
"CVE-2023-1255": {
|
||||
ID: "CVE-2023-1255",
|
||||
Severity: "LOW",
|
||||
Title: "Input buffer over-read in AES-XTS implementation and testing",
|
||||
},
|
||||
"CVE-2023-2650": {
|
||||
ID: "CVE-2023-2650",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Possible DoS translating ASN.1 object identifier and executer",
|
||||
},
|
||||
"CVE-2023-2975": {
|
||||
ID: "CVE-2023-2975",
|
||||
Severity: "HIGH",
|
||||
Title: "AES-SIV cipher implementation contains a bug that can break",
|
||||
},
|
||||
"CVE-2023-3446": {
|
||||
ID: "CVE-2023-3446",
|
||||
Severity: "CRITICAL",
|
||||
Title: "Excessive time spent checking DH keys and parenthesis",
|
||||
},
|
||||
"CVE-2023-3817": {
|
||||
ID: "CVE-2023-3817",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Excessive time spent checking DH q parameter and arguments",
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(baseURL)
|
||||
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
|
||||
Convey("test sorting", t, func() {
|
||||
args := []string{"list", "repo:tag", "--sort-by", "severity", "--url", baseURL}
|
||||
cmd := NewCVECommand(new(searchService))
|
||||
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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ... "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat...")
|
||||
|
||||
args = []string{"list", "repo:tag", "--sort-by", "alpha-asc", "--url", baseURL}
|
||||
cmd = NewCVECommand(new(searchService))
|
||||
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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ...")
|
||||
|
||||
args = []string{"list", "repo:tag", "--sort-by", "alpha-dsc", "--url", baseURL}
|
||||
cmd = NewCVECommand(new(searchService))
|
||||
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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ... "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat...")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCVECommandGQL(t *testing.T) {
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
|
@ -1096,7 +424,7 @@ func TestCVECommandGQL(t *testing.T) {
|
|||
args := []string{"affected", "CVE-12345", "--config", "cvetest"}
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewCVECommand(mockService{
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*zcommon.ImagesForCve, error,
|
||||
) {
|
||||
if count == 0 {
|
||||
|
@ -1143,7 +471,7 @@ func TestCVECommandGQL(t *testing.T) {
|
|||
args := []string{"fixed", "repo", "CVE-2222", "--config", "cvetest"}
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewCVECommand(mockService{
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*zcommon.ImageListWithCVEFixedResponse, error,
|
||||
) {
|
||||
if count == 0 {
|
||||
|
@ -1190,7 +518,7 @@ func TestCVECommandGQL(t *testing.T) {
|
|||
args := []string{"list", "repo:vuln", "--config", "cvetest"}
|
||||
defer os.Remove(configPath)
|
||||
cmd := NewCVECommand(mockService{
|
||||
getCveByImageGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, searchedCVE string) (*cveResult, error,
|
||||
) {
|
||||
if count == 0 {
|
||||
|
@ -1371,115 +699,13 @@ func TestCVECommandErrors(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
||||
// MetaDB loaded with initial data now mock the scanner
|
||||
// Setup test CVE data in mock scanner
|
||||
scanner := mocks.CveScannerMock{
|
||||
ScanImageFn: func(image string) (map[string]cvemodel.CVE, error) {
|
||||
if image == "zot-cve-test@sha256:40d1f74918aefed733c590f798d7eafde8fc0a7ec63bb8bc52eaae133cf92495" ||
|
||||
image == "zot-cve-test:0.0.1" {
|
||||
return map[string]cvemodel.CVE{
|
||||
"CVE-1": {
|
||||
ID: "CVE-1",
|
||||
Severity: "CRITICAL",
|
||||
Title: "Title for CVE-C1",
|
||||
Description: "Description of CVE-1",
|
||||
},
|
||||
"CVE-2019-9923": {
|
||||
ID: "CVE-2019-9923",
|
||||
Severity: "HIGH",
|
||||
Title: "Title for CVE-2",
|
||||
Description: "Description of CVE-2",
|
||||
},
|
||||
"CVE-3": {
|
||||
ID: "CVE-3",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Title for CVE-3",
|
||||
Description: "Description of CVE-3",
|
||||
},
|
||||
"CVE-4": {
|
||||
ID: "CVE-4",
|
||||
Severity: "LOW",
|
||||
Title: "Title for CVE-4",
|
||||
Description: "Description of CVE-4",
|
||||
},
|
||||
"CVE-5": {
|
||||
ID: "CVE-5",
|
||||
Severity: "UNKNOWN",
|
||||
Title: "Title for CVE-5",
|
||||
Description: "Description of CVE-5",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// By default the image has no vulnerabilities
|
||||
return map[string]cvemodel.CVE{}, nil
|
||||
},
|
||||
IsImageFormatScannableFn: func(repo string, reference string) (bool, error) {
|
||||
// Almost same logic compared to actual Trivy specific implementation
|
||||
imageDir := repo
|
||||
inputTag := reference
|
||||
|
||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
manifestDigestStr := reference
|
||||
|
||||
if zcommon.IsTag(reference) {
|
||||
var ok bool
|
||||
|
||||
descriptor, ok := repoMeta.Tags[inputTag]
|
||||
if !ok {
|
||||
return false, zerr.ErrTagMetaNotFound
|
||||
}
|
||||
|
||||
manifestDigestStr = descriptor.Digest
|
||||
}
|
||||
|
||||
manifestDigest, err := godigest.Parse(manifestDigestStr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var manifestContent ispec.Manifest
|
||||
|
||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
||||
if err != nil {
|
||||
return false, zerr.ErrScanNotSupported
|
||||
}
|
||||
|
||||
for _, imageLayer := range manifestContent.Layers {
|
||||
switch imageLayer.MediaType {
|
||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||
|
||||
return true, nil
|
||||
default:
|
||||
|
||||
return false, zerr.ErrScanNotSupported
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
|
||||
return &scanner
|
||||
}
|
||||
|
||||
type mockServiceForRetry struct {
|
||||
mockService
|
||||
retryCounter int
|
||||
succeedOn int
|
||||
}
|
||||
|
||||
func (service *mockServiceForRetry) getTagsForCVEGQL(ctx context.Context, config searchConfig, username, password, repo,
|
||||
func (service *mockServiceForRetry) getTagsForCVEGQL(ctx context.Context, config SearchConfig, username, password, repo,
|
||||
cveID string,
|
||||
) (*zcommon.ImagesForCve, error) {
|
||||
service.retryCounter += 1
|
||||
|
|
787
pkg/cli/client/cve_cmd_test.go
Normal file
787
pkg/cli/client/cve_cmd_test.go
Normal file
|
@ -0,0 +1,787 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
regTypes "github.com/google/go-containerregistry/pkg/v1/types"
|
||||
godigest "github.com/opencontainers/go-digest"
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
zerr "zotregistry.io/zot/errors"
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
zcommon "zotregistry.io/zot/pkg/common"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
"zotregistry.io/zot/pkg/extensions/monitoring"
|
||||
cveinfo "zotregistry.io/zot/pkg/extensions/search/cve"
|
||||
cvemodel "zotregistry.io/zot/pkg/extensions/search/cve/model"
|
||||
"zotregistry.io/zot/pkg/log"
|
||||
mTypes "zotregistry.io/zot/pkg/meta/types"
|
||||
"zotregistry.io/zot/pkg/storage"
|
||||
"zotregistry.io/zot/pkg/storage/local"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||
"zotregistry.io/zot/pkg/test/mocks"
|
||||
ociutils "zotregistry.io/zot/pkg/test/oci-utils"
|
||||
)
|
||||
|
||||
func TestNegativeServerResponse(t *testing.T) {
|
||||
Convey("Test from real server without search endpoint", t, func() {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, log.NewLogger("debug", ""))
|
||||
err := WriteImageToFileSystem(CreateDefaultVulnerableImage(), "zot-cve-test", "0.0.1", srcStorageCtlr)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := false
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "CVE config not provided, skipping CVE update", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Convey("Status Code Not Found", func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(err.Error(), ShouldContainSubstring, zerr.ErrExtensionNotEnabled.Error())
|
||||
})
|
||||
})
|
||||
|
||||
Convey("Test non-existing manifest blob", t, func() {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
imageStore := local.NewImageStore(dir, false, false,
|
||||
log.NewLogger("debug", ""), monitoring.NewMetricsServer(false, log.NewLogger("debug", "")), nil, nil)
|
||||
|
||||
storeController := storage.StoreController{
|
||||
DefaultStore: imageStore,
|
||||
}
|
||||
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := WriteImageToFileSystem(image, "zot-cve-test", "0.0.1", storeController)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = os.RemoveAll(path.Join(dir, "zot-cve-test/blobs"))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := true
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = getMockCveScanner(ctlr.MetaDB)
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(url)
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
}
|
||||
|
||||
//nolint:dupl
|
||||
func TestServerCVEResponse(t *testing.T) {
|
||||
port := test.GetFreePort()
|
||||
url := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
|
||||
dir := t.TempDir()
|
||||
|
||||
conf.Storage.RootDirectory = dir
|
||||
trivyConfig := &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
}
|
||||
cveConfig := &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: trivyConfig,
|
||||
}
|
||||
defaultVal := true
|
||||
searchConfig := &extconf.SearchConfig{
|
||||
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
||||
CVE: cveConfig,
|
||||
}
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: searchConfig,
|
||||
}
|
||||
|
||||
logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
logPath := logFile.Name()
|
||||
defer os.Remove(logPath)
|
||||
|
||||
writers := io.MultiWriter(os.Stdout, logFile)
|
||||
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Log.Logger = ctlr.Log.Output(writers)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = getMockCveScanner(ctlr.MetaDB)
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(url)
|
||||
|
||||
image := CreateDefaultImage()
|
||||
|
||||
err = UploadImage(image, url, "zot-cve-test", "0.0.1")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = test.ReadLogFileAndSearchString(logPath, "DB update completed, next update scheduled", 90*time.Second)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Convey("Test CVE by image name - GQL - positive", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search CVE by title in results", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-C1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE-C1")
|
||||
So(str, ShouldNotContainSubstring, "CVE-2")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search CVE by id in results", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-2", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "ID SEVERITY TITLE")
|
||||
So(str, ShouldContainSubstring, "CVE-2")
|
||||
So(str, ShouldNotContainSubstring, "CVE-1")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - search nonexistent CVE", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-100", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldContainSubstring, "No CVEs found for image")
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid image", t, func() {
|
||||
args := []string{"list", "invalid:0.0.1", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid image name and tag", t, func() {
|
||||
args := []string{"list", "invalid:", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("Test CVE by image name - GQL - invalid output format", t, func() {
|
||||
args := []string{"list", "zot-cve-test:0.0.1", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 db573b01 false 854B")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - invalid CVE ID", t, func() {
|
||||
args := []string{"affected", "CVE-invalid", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test images by CVE ID - GQL - invalid output format", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
So(str, ShouldEqual, "")
|
||||
})
|
||||
|
||||
Convey("Test fixed tags by image name and CVE ID - GQL - random cve", t, func() {
|
||||
args := []string{"fixed", "zot-cve-test", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldBeNil)
|
||||
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() {
|
||||
args := []string{"fixed", "zot-cv-test", "CVE-2019-20807", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
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() {
|
||||
args := []string{"fixed", "zot-cv-test:tag", "CVE-2019-20807", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
str = strings.TrimSpace(str)
|
||||
So(err, ShouldNotBeNil)
|
||||
So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - positive", t, func() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
So(strings.TrimSpace(str), ShouldEqual,
|
||||
"REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 db573b01 false 854B")
|
||||
})
|
||||
|
||||
Convey("Test CVE by name and CVE ID - GQL - invalid name and CVE ID", t, func() {
|
||||
args := []string{"affected", "CVE-20807", "--repo", "test", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err := cveCmd.Execute()
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := space.ReplaceAllString(buff.String(), " ")
|
||||
So(err, ShouldBeNil)
|
||||
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() {
|
||||
args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "-f", "random", "--config", "cvetest"}
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url))
|
||||
defer os.Remove(configPath)
|
||||
cveCmd := client.NewCVECommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cveCmd.SetOut(buff)
|
||||
cveCmd.SetErr(buff)
|
||||
cveCmd.SetArgs(args)
|
||||
err = cveCmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
||||
})
|
||||
}
|
||||
|
||||
func TestCVESort(t *testing.T) {
|
||||
rootDir := t.TempDir()
|
||||
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},
|
||||
CVE: &extconf.CVEConfig{
|
||||
UpdateInterval: 2,
|
||||
Trivy: &extconf.TrivyConfig{
|
||||
DBRepository: "ghcr.io/project-zot/trivy-db",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
|
||||
image1 := CreateRandomImage()
|
||||
|
||||
storeController := ociutils.GetDefaultStoreController(rootDir, ctlr.Log)
|
||||
|
||||
err := WriteImageToFileSystem(image1, "repo", "tag", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
if err := ctlr.Init(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ctlr.CveScanner = mocks.CveScannerMock{
|
||||
ScanImageFn: func(image string) (map[string]cvemodel.CVE, error) {
|
||||
return map[string]cvemodel.CVE{
|
||||
"CVE-2023-1255": {
|
||||
ID: "CVE-2023-1255",
|
||||
Severity: "LOW",
|
||||
Title: "Input buffer over-read in AES-XTS implementation and testing",
|
||||
},
|
||||
"CVE-2023-2650": {
|
||||
ID: "CVE-2023-2650",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Possible DoS translating ASN.1 object identifier and executer",
|
||||
},
|
||||
"CVE-2023-2975": {
|
||||
ID: "CVE-2023-2975",
|
||||
Severity: "HIGH",
|
||||
Title: "AES-SIV cipher implementation contains a bug that can break",
|
||||
},
|
||||
"CVE-2023-3446": {
|
||||
ID: "CVE-2023-3446",
|
||||
Severity: "CRITICAL",
|
||||
Title: "Excessive time spent checking DH keys and parenthesis",
|
||||
},
|
||||
"CVE-2023-3817": {
|
||||
ID: "CVE-2023-3817",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Excessive time spent checking DH q parameter and arguments",
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := ctlr.Run(ctx); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
defer ctlr.Shutdown()
|
||||
|
||||
test.WaitTillServerReady(baseURL)
|
||||
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
|
||||
Convey("test sorting", t, func() {
|
||||
args := []string{"list", "repo:tag", "--sort-by", "severity", "--url", baseURL}
|
||||
cmd := client.NewCVECommand(client.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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ... "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat...")
|
||||
|
||||
args = []string{"list", "repo:tag", "--sort-by", "alpha-asc", "--url", baseURL}
|
||||
cmd = client.NewCVECommand(client.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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ...")
|
||||
|
||||
args = []string{"list", "repo:tag", "--sort-by", "alpha-dsc", "--url", baseURL}
|
||||
cmd = client.NewCVECommand(client.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, ShouldResemble,
|
||||
"ID SEVERITY TITLE "+
|
||||
"CVE-2023-3817 MEDIUM Excessive time spent checking DH q parameter ... "+
|
||||
"CVE-2023-3446 CRITICAL Excessive time spent checking DH keys and par... "+
|
||||
"CVE-2023-2975 HIGH AES-SIV cipher implementation contains a bug ... "+
|
||||
"CVE-2023-2650 MEDIUM Possible DoS translating ASN.1 object identif... "+
|
||||
"CVE-2023-1255 LOW Input buffer over-read in AES-XTS implementat...")
|
||||
})
|
||||
}
|
||||
|
||||
func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner {
|
||||
// MetaDB loaded with initial data now mock the scanner
|
||||
// Setup test CVE data in mock scanner
|
||||
scanner := mocks.CveScannerMock{
|
||||
ScanImageFn: func(image string) (map[string]cvemodel.CVE, error) {
|
||||
if strings.Contains(image, "zot-cve-test@sha256:db573b01") ||
|
||||
image == "zot-cve-test:0.0.1" {
|
||||
return map[string]cvemodel.CVE{
|
||||
"CVE-1": {
|
||||
ID: "CVE-1",
|
||||
Severity: "CRITICAL",
|
||||
Title: "Title for CVE-C1",
|
||||
Description: "Description of CVE-1",
|
||||
},
|
||||
"CVE-2019-9923": {
|
||||
ID: "CVE-2019-9923",
|
||||
Severity: "HIGH",
|
||||
Title: "Title for CVE-2",
|
||||
Description: "Description of CVE-2",
|
||||
},
|
||||
"CVE-3": {
|
||||
ID: "CVE-3",
|
||||
Severity: "MEDIUM",
|
||||
Title: "Title for CVE-3",
|
||||
Description: "Description of CVE-3",
|
||||
},
|
||||
"CVE-4": {
|
||||
ID: "CVE-4",
|
||||
Severity: "LOW",
|
||||
Title: "Title for CVE-4",
|
||||
Description: "Description of CVE-4",
|
||||
},
|
||||
"CVE-5": {
|
||||
ID: "CVE-5",
|
||||
Severity: "UNKNOWN",
|
||||
Title: "Title for CVE-5",
|
||||
Description: "Description of CVE-5",
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// By default the image has no vulnerabilities
|
||||
return map[string]cvemodel.CVE{}, nil
|
||||
},
|
||||
IsImageFormatScannableFn: func(repo string, reference string) (bool, error) {
|
||||
// Almost same logic compared to actual Trivy specific implementation
|
||||
imageDir := repo
|
||||
inputTag := reference
|
||||
|
||||
repoMeta, err := metaDB.GetRepoMeta(imageDir)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
manifestDigestStr := reference
|
||||
|
||||
if zcommon.IsTag(reference) {
|
||||
var ok bool
|
||||
|
||||
descriptor, ok := repoMeta.Tags[inputTag]
|
||||
if !ok {
|
||||
return false, zerr.ErrTagMetaNotFound
|
||||
}
|
||||
|
||||
manifestDigestStr = descriptor.Digest
|
||||
}
|
||||
|
||||
manifestDigest, err := godigest.Parse(manifestDigestStr)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
manifestData, err := metaDB.GetManifestData(manifestDigest)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var manifestContent ispec.Manifest
|
||||
|
||||
err = json.Unmarshal(manifestData.ManifestBlob, &manifestContent)
|
||||
if err != nil {
|
||||
return false, zerr.ErrScanNotSupported
|
||||
}
|
||||
|
||||
for _, imageLayer := range manifestContent.Layers {
|
||||
switch imageLayer.MediaType {
|
||||
case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer):
|
||||
|
||||
return true, nil
|
||||
default:
|
||||
|
||||
return false, zerr.ErrScanNotSupported
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
},
|
||||
}
|
||||
|
||||
return &scanner
|
||||
}
|
|
@ -90,11 +90,11 @@ func haveSameArgs(query field, reqQuery GQLQuery) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func CheckExtEndPointQuery(config searchConfig, requiredQueries ...GQLQuery) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func CheckExtEndPointQuery(config SearchConfig, requiredQueries ...GQLQuery) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx := context.Background()
|
||||
|
||||
discoverEndPoint, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("%s%s",
|
||||
discoverEndPoint, err := combineServerAndEndpointURL(config.ServURL, fmt.Sprintf("%s%s",
|
||||
constants.RoutePrefix, constants.ExtOciDiscoverPrefix))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -102,8 +102,8 @@ func CheckExtEndPointQuery(config searchConfig, requiredQueries ...GQLQuery) err
|
|||
|
||||
discoverResponse := &distext.ExtensionList{}
|
||||
|
||||
_, err = makeGETRequest(ctx, discoverEndPoint, username, password, config.verifyTLS,
|
||||
config.debug, &discoverResponse, config.resultWriter)
|
||||
_, err = makeGETRequest(ctx, discoverEndPoint, username, password, config.VerifyTLS,
|
||||
config.Debug, &discoverResponse, config.ResultWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ func CheckExtEndPointQuery(config searchConfig, requiredQueries ...GQLQuery) err
|
|||
return fmt.Errorf("%w: search extension gql endpoints not found", zerr.ErrExtensionNotEnabled)
|
||||
}
|
||||
|
||||
searchEndPoint, _ := combineServerAndEndpointURL(config.servURL, constants.FullSearchPrefix)
|
||||
searchEndPoint, _ := combineServerAndEndpointURL(config.ServURL, constants.FullSearchPrefix)
|
||||
|
||||
schemaQuery := `
|
||||
{
|
||||
|
@ -153,8 +153,8 @@ func CheckExtEndPointQuery(config searchConfig, requiredQueries ...GQLQuery) err
|
|||
|
||||
queryResponse := &schemaList{}
|
||||
|
||||
err = makeGraphQLRequest(ctx, searchEndPoint, schemaQuery, username, password, config.verifyTLS,
|
||||
config.debug, queryResponse, config.resultWriter)
|
||||
err = makeGraphQLRequest(ctx, searchEndPoint, schemaQuery, username, password, config.VerifyTLS,
|
||||
config.Debug, queryResponse, config.ResultWriter)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gql query failed: %w", err)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//go:build search && needprivileges
|
||||
// +build search,needprivileges
|
||||
|
||||
package client
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -19,6 +19,7 @@ import (
|
|||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/api/constants"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
)
|
||||
|
||||
|
@ -94,7 +95,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) {
|
|||
defer os.Remove(configPath)
|
||||
|
||||
args := []string{"list", "--config", "imagetest"}
|
||||
imageCmd := NewImageCommand(new(searchService))
|
||||
imageCmd := client.NewImageCommand(client.NewSearchService())
|
||||
imageBuff := bytes.NewBufferString("")
|
||||
imageCmd.SetOut(imageBuff)
|
||||
imageCmd.SetErr(imageBuff)
|
|
@ -1,7 +1,7 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
)
|
||||
|
@ -36,57 +37,57 @@ func TestGQLQueries(t *testing.T) {
|
|||
|
||||
defer cm.StopServer()
|
||||
|
||||
searchConfig := searchConfig{
|
||||
servURL: baseURL,
|
||||
user: "",
|
||||
verifyTLS: false,
|
||||
debug: false,
|
||||
resultWriter: io.Discard,
|
||||
searchConfig := client.SearchConfig{
|
||||
ServURL: baseURL,
|
||||
User: "",
|
||||
VerifyTLS: false,
|
||||
Debug: false,
|
||||
ResultWriter: io.Discard,
|
||||
}
|
||||
|
||||
Convey("Make sure the current CLI used the right queries in case they change", t, func() {
|
||||
Convey("ImageList", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, ImageListQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.ImageListQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("ImageListForDigest", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, ImageListForDigestQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.ImageListForDigestQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("BaseImageList", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, BaseImageListQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.BaseImageListQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("DerivedImageList", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, DerivedImageListQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.DerivedImageListQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("CVEListForImage", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, CVEListForImageQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.CVEListForImageQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("ImageListForCVE", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, ImageListForCVEQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.ImageListForCVEQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("ImageListWithCVEFixed", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, ImageListWithCVEFixedQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.ImageListWithCVEFixedQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("Referrers", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, ReferrersQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.ReferrersQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("GlobalSearch", func() {
|
||||
err := CheckExtEndPointQuery(searchConfig, GlobalSearchQuery())
|
||||
err := client.CheckExtEndPointQuery(searchConfig, client.GlobalSearchQuery())
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
})
|
File diff suppressed because it is too large
Load diff
1260
pkg/cli/client/image_cmd_test.go
Normal file
1260
pkg/cli/client/image_cmd_test.go
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,7 +1,7 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -15,6 +15,7 @@ import (
|
|||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||
)
|
||||
|
@ -43,7 +44,7 @@ func TestReposCommand(t *testing.T) {
|
|||
defer os.Remove(configPath)
|
||||
|
||||
args := []string{"list", "--config", "repostest"}
|
||||
cmd := NewRepoCommand(mockService{})
|
||||
cmd := client.NewRepoCommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -57,7 +58,7 @@ func TestReposCommand(t *testing.T) {
|
|||
So(actual, ShouldContainSubstring, "repo2")
|
||||
|
||||
args = []string{"list", "--sort-by", "alpha-dsc", "--config", "repostest"}
|
||||
cmd = NewRepoCommand(new(searchService))
|
||||
cmd = client.NewRepoCommand(client.NewSearchService())
|
||||
buff = bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -72,7 +73,7 @@ func TestReposCommand(t *testing.T) {
|
|||
So(strings.Index(actual, "repo2"), ShouldBeLessThan, strings.Index(actual, "repo1"))
|
||||
|
||||
args = []string{"list", "--sort-by", "alpha-asc", "--config", "repostest"}
|
||||
cmd = NewRepoCommand(new(searchService))
|
||||
cmd = client.NewRepoCommand(client.NewSearchService())
|
||||
buff = bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
|
@ -91,11 +92,13 @@ func TestReposCommand(t *testing.T) {
|
|||
func TestSuggestions(t *testing.T) {
|
||||
Convey("Suggestions", t, func() {
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
suggestion := ShowSuggestionsIfUnknownCommand(NewRepoCommand(mockService{}), []string{"bad-command"})
|
||||
suggestion := client.ShowSuggestionsIfUnknownCommand(
|
||||
client.NewRepoCommand(client.NewSearchService()), []string{"bad-command"})
|
||||
str := space.ReplaceAllString(suggestion.Error(), " ")
|
||||
So(str, ShouldContainSubstring, "unknown subcommand")
|
||||
|
||||
suggestion = ShowSuggestionsIfUnknownCommand(NewRepoCommand(mockService{}), []string{"listt"})
|
||||
suggestion = client.ShowSuggestionsIfUnknownCommand(
|
||||
client.NewRepoCommand(client.NewSearchService()), []string{"listt"})
|
||||
str = space.ReplaceAllString(suggestion.Error(), " ")
|
||||
So(str, ShouldContainSubstring, "Did you mean this? list")
|
||||
})
|
|
@ -10,9 +10,7 @@ import (
|
|||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
|
@ -20,713 +18,8 @@ import (
|
|||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||
ociutils "zotregistry.io/zot/pkg/test/oci-utils"
|
||||
)
|
||||
|
||||
const (
|
||||
customArtTypeV1 = "application/custom.art.type.v1"
|
||||
customArtTypeV2 = "application/custom.art.type.v2"
|
||||
repoName = "repo"
|
||||
)
|
||||
|
||||
func TestReferrerCLI(t *testing.T) {
|
||||
Convey("Test GQL", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
|
||||
fmt.Println(buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
args = []string{"subject", repo + ":" + "tag", "--config", "reftest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd = NewSearchCommand(new(searchService))
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("Test REST", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := false
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// get referrers by digest
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
fmt.Println(buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
args = []string{"subject", repo + ":" + "tag", "--config", "reftest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatsReferrersCLI(t *testing.T) {
|
||||
Convey("Create server", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := false
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// add referrers
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("JSON format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "json", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
Convey("YAML format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "yaml", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
Convey("Invalid format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "invalid_format", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestReferrersCLIErrors(t *testing.T) {
|
||||
Convey("Errors", t, func() {
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
Convey("no url provided", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest","showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("getConfigValue", func() {
|
||||
args := []string{"subject", "repo/alpine", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`bad-json`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad showspinnerConfig ", func() {
|
||||
args := []string{"query", "repo", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad verifyTLSConfig ", func() {
|
||||
args := []string{"query", "repo", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("url from config is empty", func() {
|
||||
args := []string{"subject", "repo/alpine", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad params combination", func() {
|
||||
args := []string{"query", "repo", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchCLI(t *testing.T) {
|
||||
Convey("Test GQL", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
const (
|
||||
repo1 = "repo"
|
||||
r1tag1 = "repo1tag1"
|
||||
r1tag2 = "repo1tag2"
|
||||
|
||||
repo2 = "repo/alpine"
|
||||
r2tag1 = "repo2tag1"
|
||||
r2tag2 = "repo2tag2"
|
||||
|
||||
repo3 = "repo/test/alpine"
|
||||
r3tag1 = "repo3tag1"
|
||||
r3tag2 = "repo3tag2"
|
||||
)
|
||||
|
||||
image1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ImageConfig(ispec.Image{
|
||||
Created: DefaultTimeRef(),
|
||||
Platform: ispec.Platform{OS: "Os", Architecture: "Arch"},
|
||||
}).
|
||||
Build()
|
||||
formatterDigest1 := image1.Digest().Encoded()[:8]
|
||||
|
||||
image2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
DefaultConfig().
|
||||
Build()
|
||||
formatterDigest2 := image2.Digest().Encoded()[:8]
|
||||
|
||||
err := UploadImage(image1, baseURL, repo1, r1tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo1, r1tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo2, r2tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo2, r2tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo3, r3tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo3, r3tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// search by repos
|
||||
|
||||
args := []string{"query", "test/alpin", "--verbose", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "NAME SIZE LAST UPDATED DOWNLOADS STARS PLATFORMS")
|
||||
So(str, ShouldContainSubstring, "repo/test/alpine 1.1kB 2010-01-01 01:01:01 +0000 UTC 0 0")
|
||||
So(str, ShouldContainSubstring, "Os/Arch")
|
||||
So(str, ShouldContainSubstring, "linux/amd64")
|
||||
|
||||
fmt.Println("\n", buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
cmd = NewSearchCommand(new(searchService))
|
||||
|
||||
args = []string{"query", "repo/alpine:", "--config", "searchtest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(str, ShouldContainSubstring, "repo/alpine repo2tag1 Os/Arch "+formatterDigest1+" false 525B")
|
||||
So(str, ShouldContainSubstring, "repo/alpine repo2tag2 linux/amd64 "+formatterDigest2+" false 552B")
|
||||
|
||||
fmt.Println("\n", buff.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatsSearchCLI(t *testing.T) {
|
||||
Convey("", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
const (
|
||||
repo1 = "repo"
|
||||
r1tag1 = "repo1tag1"
|
||||
r1tag2 = "repo1tag2"
|
||||
|
||||
repo2 = "repo/alpine"
|
||||
r2tag1 = "repo2tag1"
|
||||
r2tag2 = "repo2tag2"
|
||||
|
||||
repo3 = "repo/test/alpine"
|
||||
r3tag1 = "repo3tag1"
|
||||
r3tag2 = "repo3tag2"
|
||||
)
|
||||
|
||||
image1 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
|
||||
image2 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
|
||||
|
||||
err := UploadImage(image1, baseURL, repo1, r1tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo1, r1tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo2, r2tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo2, r2tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo3, r3tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo3, r3tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
Convey("JSON format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "json", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("YAML format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "yaml", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("Invalid format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchCLIErrors(t *testing.T) {
|
||||
Convey("Errors", t, func() {
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
|
||||
Convey("no url provided", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"searchtest","showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("getConfigValue", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`bad-json`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad showspinnerConfig ", func() {
|
||||
args := []string{"query", "repo/alpine", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad verifyTLSConfig ", func() {
|
||||
args := []string{"query", "repo/alpine", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("url from config is empty", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"searchtest", "url":"", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchCommandGQL(t *testing.T) {
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
|
@ -865,70 +158,3 @@ func TestSearchCommandREST(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchSort(t *testing.T) {
|
||||
rootDir := t.TempDir()
|
||||
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},
|
||||
CVE: nil,
|
||||
},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
|
||||
image1 := CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 1, 1, 1, 0, time.UTC)}).
|
||||
Build()
|
||||
|
||||
image2 := CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{Created: DateRef(2020, 1, 1, 1, 1, 1, 0, time.UTC)}).
|
||||
Build()
|
||||
|
||||
storeController := ociutils.GetDefaultStoreController(rootDir, ctlr.Log)
|
||||
|
||||
err := WriteImageToFileSystem(image1, "b-repo", "tag2", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
err = WriteImageToFileSystem(image2, "a-test-repo", "tag2", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
|
||||
defer cm.StopServer()
|
||||
|
||||
Convey("test sorting", t, func() {
|
||||
args := []string{"query", "repo", "--sort-by", "relevance", "--url", baseURL}
|
||||
cmd := NewSearchCommand(new(searchService))
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str := buff.String()
|
||||
So(strings.Index(str, "b-repo"), ShouldBeLessThan, strings.Index(str, "a-test-repo"))
|
||||
|
||||
args = []string{"query", "repo", "--sort-by", "alpha-asc", "--url", baseURL}
|
||||
cmd = NewSearchCommand(new(searchService))
|
||||
buff = bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = buff.String()
|
||||
So(strings.Index(str, "a-test-repo"), ShouldBeLessThan, strings.Index(str, "b-repo"))
|
||||
})
|
||||
}
|
||||
|
|
796
pkg/cli/client/search_cmd_test.go
Normal file
796
pkg/cli/client/search_cmd_test.go
Normal file
|
@ -0,0 +1,796 @@
|
|||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
|
||||
"zotregistry.io/zot/pkg/api"
|
||||
"zotregistry.io/zot/pkg/api/config"
|
||||
"zotregistry.io/zot/pkg/cli/client"
|
||||
extconf "zotregistry.io/zot/pkg/extensions/config"
|
||||
test "zotregistry.io/zot/pkg/test/common"
|
||||
. "zotregistry.io/zot/pkg/test/image-utils"
|
||||
ociutils "zotregistry.io/zot/pkg/test/oci-utils"
|
||||
)
|
||||
|
||||
const (
|
||||
customArtTypeV1 = "application/custom.art.type.v1"
|
||||
customArtTypeV2 = "application/custom.art.type.v2"
|
||||
repoName = "repo"
|
||||
)
|
||||
|
||||
func TestReferrerCLI(t *testing.T) {
|
||||
Convey("Test GQL", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
|
||||
fmt.Println(buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
args = []string{"subject", repo + ":" + "tag", "--config", "reftest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd = client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("Test REST", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := false
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// get referrers by digest
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
fmt.Println(buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
args = []string{"subject", repo + ":" + "tag", "--config", "reftest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "ARTIFACT TYPE SIZE DIGEST")
|
||||
So(str, ShouldContainSubstring, "application/vnd.oci.image.config.v1+json 563 B "+ref1.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v1 551 B "+ref2.DigestStr())
|
||||
So(str, ShouldContainSubstring, "custom.art.type.v2 611 B "+ref3.DigestStr())
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatsReferrersCLI(t *testing.T) {
|
||||
Convey("Create server", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := false
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
repo := repoName
|
||||
image := CreateRandomImage()
|
||||
|
||||
err := UploadImage(image, baseURL, repo, "tag")
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// add referrers
|
||||
ref1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ArtifactConfig(customArtTypeV1).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
ref3 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
RandomConfig().
|
||||
ArtifactType(customArtTypeV2).
|
||||
Subject(image.DescriptorRef()).Build()
|
||||
|
||||
err = UploadImage(ref1, baseURL, repo, ref1.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref2, baseURL, repo, ref2.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(ref3, baseURL, repo, ref3.DigestStr())
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
Convey("JSON format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "json", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
Convey("YAML format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "yaml", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
Convey("Invalid format", func() {
|
||||
args := []string{"subject", repo + "@" + image.DigestStr(), "--format", "invalid_format", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"reftest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestReferrersCLIErrors(t *testing.T) {
|
||||
Convey("Errors", t, func() {
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
Convey("no url provided", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest","showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("getConfigValue", func() {
|
||||
args := []string{"subject", "repo/alpine", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`bad-json`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad showspinnerConfig ", func() {
|
||||
args := []string{"query", "repo", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad verifyTLSConfig ", func() {
|
||||
args := []string{"query", "repo", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("url from config is empty", func() {
|
||||
args := []string{"subject", "repo/alpine", "--config", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad params combination", func() {
|
||||
args := []string{"query", "repo", "reftest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"reftest", "url":"http://127.0.0.1:8080", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchCLI(t *testing.T) {
|
||||
Convey("Test GQL", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
const (
|
||||
repo1 = "repo"
|
||||
r1tag1 = "repo1tag1"
|
||||
r1tag2 = "repo1tag2"
|
||||
|
||||
repo2 = "repo/alpine"
|
||||
r2tag1 = "repo2tag1"
|
||||
r2tag2 = "repo2tag2"
|
||||
|
||||
repo3 = "repo/test/alpine"
|
||||
r3tag1 = "repo3tag1"
|
||||
r3tag2 = "repo3tag2"
|
||||
)
|
||||
|
||||
image1 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
ImageConfig(ispec.Image{
|
||||
Created: DefaultTimeRef(),
|
||||
Platform: ispec.Platform{OS: "Os", Architecture: "Arch"},
|
||||
}).
|
||||
Build()
|
||||
formatterDigest1 := image1.Digest().Encoded()[:8]
|
||||
|
||||
image2 := CreateImageWith().
|
||||
RandomLayers(1, 10).
|
||||
DefaultConfig().
|
||||
Build()
|
||||
formatterDigest2 := image2.Digest().Encoded()[:8]
|
||||
|
||||
err := UploadImage(image1, baseURL, repo1, r1tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo1, r1tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo2, r2tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo2, r2tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo3, r3tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo3, r3tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
// search by repos
|
||||
|
||||
args := []string{"query", "test/alpin", "--verbose", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
defer os.Remove(configPath)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
space := regexp.MustCompile(`\s+`)
|
||||
str := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "NAME SIZE LAST UPDATED DOWNLOADS STARS PLATFORMS")
|
||||
So(str, ShouldContainSubstring, "repo/test/alpine 1.1kB 2010-01-01 01:01:01 +0000 UTC 0 0")
|
||||
So(str, ShouldContainSubstring, "Os/Arch")
|
||||
So(str, ShouldContainSubstring, "linux/amd64")
|
||||
|
||||
fmt.Println("\n", buff.String())
|
||||
|
||||
os.Remove(configPath)
|
||||
|
||||
cmd = client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
args = []string{"query", "repo/alpine:", "--config", "searchtest"}
|
||||
|
||||
configPath = makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff = &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
||||
So(str, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
||||
So(str, ShouldContainSubstring, "repo/alpine repo2tag1 Os/Arch "+formatterDigest1+" false 525B")
|
||||
So(str, ShouldContainSubstring, "repo/alpine repo2tag2 linux/amd64 "+formatterDigest2+" false 552B")
|
||||
|
||||
fmt.Println("\n", buff.String())
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatsSearchCLI(t *testing.T) {
|
||||
Convey("", t, func() {
|
||||
rootDir := t.TempDir()
|
||||
|
||||
port := test.GetFreePort()
|
||||
baseURL := test.GetBaseURL(port)
|
||||
conf := config.New()
|
||||
conf.HTTP.Port = port
|
||||
conf.Storage.GC = false
|
||||
defaultVal := true
|
||||
conf.Extensions = &extconf.ExtensionConfig{
|
||||
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
defer cm.StopServer()
|
||||
|
||||
const (
|
||||
repo1 = "repo"
|
||||
r1tag1 = "repo1tag1"
|
||||
r1tag2 = "repo1tag2"
|
||||
|
||||
repo2 = "repo/alpine"
|
||||
r2tag1 = "repo2tag1"
|
||||
r2tag2 = "repo2tag2"
|
||||
|
||||
repo3 = "repo/test/alpine"
|
||||
r3tag1 = "repo3tag1"
|
||||
r3tag2 = "repo3tag2"
|
||||
)
|
||||
|
||||
image1 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
|
||||
image2 := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build()
|
||||
|
||||
err := UploadImage(image1, baseURL, repo1, r1tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo1, r1tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo2, r2tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo2, r2tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
err = UploadImage(image1, baseURL, repo3, r3tag1)
|
||||
So(err, ShouldBeNil)
|
||||
err = UploadImage(image2, baseURL, repo3, r3tag2)
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
Convey("JSON format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "json", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("YAML format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "yaml", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
fmt.Println(buff.String())
|
||||
})
|
||||
|
||||
Convey("Invalid format", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
|
||||
baseURL))
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchCLIErrors(t *testing.T) {
|
||||
Convey("Errors", t, func() {
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
|
||||
Convey("no url provided", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"searchtest","showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("getConfigValue", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`bad-json`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad showspinnerConfig ", func() {
|
||||
args := []string{"query", "repo/alpine", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":"bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("bad verifyTLSConfig ", func() {
|
||||
args := []string{"query", "repo/alpine", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(
|
||||
`{"configs":[{"_name":"searchtest", "url":"http://127.0.0.1:8080", "showspinner":false, "verify-tls": "bad"}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
||||
Convey("url from config is empty", func() {
|
||||
args := []string{"query", "repo/alpine", "--format", "invalid", "--config", "searchtest"}
|
||||
|
||||
configPath := makeConfigFile(`{"configs":[{"_name":"searchtest", "url":"", "showspinner":false}]}`)
|
||||
|
||||
defer os.Remove(configPath)
|
||||
|
||||
buff := &bytes.Buffer{}
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestSearchSort(t *testing.T) {
|
||||
rootDir := t.TempDir()
|
||||
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},
|
||||
CVE: nil,
|
||||
},
|
||||
}
|
||||
ctlr := api.NewController(conf)
|
||||
ctlr.Config.Storage.RootDirectory = rootDir
|
||||
|
||||
image1 := CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{Created: DateRef(2010, 1, 1, 1, 1, 1, 0, time.UTC)}).
|
||||
Build()
|
||||
|
||||
image2 := CreateImageWith().DefaultLayers().
|
||||
ImageConfig(ispec.Image{Created: DateRef(2020, 1, 1, 1, 1, 1, 0, time.UTC)}).
|
||||
Build()
|
||||
|
||||
storeController := ociutils.GetDefaultStoreController(rootDir, ctlr.Log)
|
||||
|
||||
err := WriteImageToFileSystem(image1, "b-repo", "tag2", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
err = WriteImageToFileSystem(image2, "a-test-repo", "tag2", storeController)
|
||||
if err != nil {
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
cm := test.NewControllerManager(ctlr)
|
||||
cm.StartAndWait(conf.HTTP.Port)
|
||||
|
||||
defer cm.StopServer()
|
||||
|
||||
Convey("test sorting", t, func() {
|
||||
args := []string{"query", "repo", "--sort-by", "relevance", "--url", baseURL}
|
||||
cmd := client.NewSearchCommand(client.NewSearchService())
|
||||
buff := bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err := cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str := buff.String()
|
||||
So(strings.Index(str, "b-repo"), ShouldBeLessThan, strings.Index(str, "a-test-repo"))
|
||||
|
||||
args = []string{"query", "repo", "--sort-by", "alpha-asc", "--url", baseURL}
|
||||
cmd = client.NewSearchCommand(client.NewSearchService())
|
||||
buff = bytes.NewBufferString("")
|
||||
cmd.SetOut(buff)
|
||||
cmd.SetErr(buff)
|
||||
cmd.SetArgs(args)
|
||||
err = cmd.Execute()
|
||||
So(err, ShouldBeNil)
|
||||
str = buff.String()
|
||||
So(strings.Index(str, "a-test-repo"), ShouldBeLessThan, strings.Index(str, "b-repo"))
|
||||
})
|
||||
}
|
|
@ -17,8 +17,8 @@ import (
|
|||
|
||||
const CveDBRetryInterval = 3
|
||||
|
||||
func SearchAllImages(config searchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchAllImages(config SearchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
imageErr := make(chan stringResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -26,7 +26,7 @@ func SearchAllImages(config searchConfig) error {
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go config.searchService.getAllImages(ctx, config, username, password, imageErr, &wg)
|
||||
go config.SearchService.getAllImages(ctx, config, username, password, imageErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
@ -41,13 +41,13 @@ func SearchAllImages(config searchConfig) error {
|
|||
}
|
||||
}
|
||||
|
||||
func SearchAllImagesGQL(config searchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchAllImagesGQL(config SearchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
imageList, err := config.searchService.getImagesGQL(ctx, config, username, password, "")
|
||||
imageList, err := config.SearchService.getImagesGQL(ctx, config, username, password, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,8 +61,8 @@ func SearchAllImagesGQL(config searchConfig) error {
|
|||
return printImageResult(config, imageListData)
|
||||
}
|
||||
|
||||
func SearchImageByName(config searchConfig, image string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchImageByName(config SearchConfig, image string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
imageErr := make(chan stringResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -70,7 +70,7 @@ func SearchImageByName(config searchConfig, image string) error {
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go config.searchService.getImageByName(ctx, config, username, password,
|
||||
go config.SearchService.getImageByName(ctx, config, username, password,
|
||||
image, imageErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
|
@ -91,15 +91,15 @@ func SearchImageByName(config searchConfig, image string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func SearchImageByNameGQL(config searchConfig, imageName string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchImageByNameGQL(config SearchConfig, imageName string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
repo, tag := zcommon.GetImageDirAndTag(imageName)
|
||||
|
||||
imageList, err := config.searchService.getImagesGQL(ctx, config, username, password, repo)
|
||||
imageList, err := config.SearchService.getImagesGQL(ctx, config, username, password, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ func SearchImageByNameGQL(config searchConfig, imageName string) error {
|
|||
return printImageResult(config, imageListData)
|
||||
}
|
||||
|
||||
func SearchImagesByDigest(config searchConfig, digest string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchImagesByDigest(config SearchConfig, digest string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
imageErr := make(chan stringResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -124,7 +124,7 @@ func SearchImagesByDigest(config searchConfig, digest string) error {
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go config.searchService.getImagesByDigest(ctx, config, username, password,
|
||||
go config.SearchService.getImagesByDigest(ctx, config, username, password,
|
||||
digest, imageErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
|
@ -141,13 +141,13 @@ func SearchImagesByDigest(config searchConfig, digest string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func SearchDerivedImageListGQL(config searchConfig, derivedImage string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchDerivedImageListGQL(config SearchConfig, derivedImage string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
imageList, err := config.searchService.getDerivedImageListGQL(ctx, config, username,
|
||||
imageList, err := config.SearchService.getDerivedImageListGQL(ctx, config, username,
|
||||
password, derivedImage)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -162,13 +162,13 @@ func SearchDerivedImageListGQL(config searchConfig, derivedImage string) error {
|
|||
return printImageResult(config, imageListData)
|
||||
}
|
||||
|
||||
func SearchBaseImageListGQL(config searchConfig, baseImage string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchBaseImageListGQL(config SearchConfig, baseImage string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
imageList, err := config.searchService.getBaseImageListGQL(ctx, config, username,
|
||||
imageList, err := config.SearchService.getBaseImageListGQL(ctx, config, username,
|
||||
password, baseImage)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -183,13 +183,13 @@ func SearchBaseImageListGQL(config searchConfig, baseImage string) error {
|
|||
return printImageResult(config, imageListData)
|
||||
}
|
||||
|
||||
func SearchImagesForDigestGQL(config searchConfig, digest string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchImagesForDigestGQL(config SearchConfig, digest string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
imageList, err := config.searchService.getImagesForDigestGQL(ctx, config, username, password, digest)
|
||||
imageList, err := config.SearchService.getImagesForDigestGQL(ctx, config, username, password, digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -207,8 +207,8 @@ func SearchImagesForDigestGQL(config searchConfig, digest string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func SearchCVEForImageGQL(config searchConfig, image, searchedCveID string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchCVEForImageGQL(config SearchConfig, image, searchedCveID string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
@ -218,7 +218,7 @@ func SearchCVEForImageGQL(config searchConfig, image, searchedCveID string) erro
|
|||
err := zcommon.RetryWithContext(ctx, func(attempt int, retryIn time.Duration) error {
|
||||
var err error
|
||||
|
||||
cveList, err = config.searchService.getCveByImageGQL(ctx, config, username, password, image, searchedCveID)
|
||||
cveList, err = config.SearchService.getCveByImageGQL(ctx, config, username, password, image, searchedCveID)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), zerr.ErrCVEDBNotFound.Error()) {
|
||||
cancel()
|
||||
|
@ -226,7 +226,7 @@ func SearchCVEForImageGQL(config searchConfig, image, searchedCveID string) erro
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(config.resultWriter,
|
||||
fmt.Fprintf(config.ResultWriter,
|
||||
"[warning] CVE DB is not ready [%d] - retry in %d seconds\n", attempt, int(retryIn.Seconds()))
|
||||
}
|
||||
|
||||
|
@ -237,30 +237,30 @@ func SearchCVEForImageGQL(config searchConfig, image, searchedCveID string) erro
|
|||
}
|
||||
|
||||
if len(cveList.Data.CVEListForImage.CVEList) == 0 {
|
||||
fmt.Fprint(config.resultWriter, "No CVEs found for image\n")
|
||||
fmt.Fprint(config.ResultWriter, "No CVEs found for image\n")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
|
||||
if config.outputFormat == defaultOutputFormat || config.outputFormat == "" {
|
||||
if config.OutputFormat == defaultOutputFormat || config.OutputFormat == "" {
|
||||
printCVETableHeader(&builder)
|
||||
fmt.Fprint(config.resultWriter, builder.String())
|
||||
fmt.Fprint(config.ResultWriter, builder.String())
|
||||
}
|
||||
|
||||
out, err := cveList.string(config.outputFormat)
|
||||
out, err := cveList.string(config.OutputFormat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(config.resultWriter, out)
|
||||
fmt.Fprint(config.ResultWriter, out)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func SearchImagesByCVEIDGQL(config searchConfig, repo, cveid string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchImagesByCVEIDGQL(config SearchConfig, repo, cveid string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
@ -270,7 +270,7 @@ func SearchImagesByCVEIDGQL(config searchConfig, repo, cveid string) error {
|
|||
err := zcommon.RetryWithContext(ctx, func(attempt int, retryIn time.Duration) error {
|
||||
var err error
|
||||
|
||||
imageList, err = config.searchService.getTagsForCVEGQL(ctx, config, username, password,
|
||||
imageList, err = config.SearchService.getTagsForCVEGQL(ctx, config, username, password,
|
||||
repo, cveid)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), zerr.ErrCVEDBNotFound.Error()) {
|
||||
|
@ -279,7 +279,7 @@ func SearchImagesByCVEIDGQL(config searchConfig, repo, cveid string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(config.resultWriter,
|
||||
fmt.Fprintf(config.ResultWriter,
|
||||
"[warning] CVE DB is not ready [%d] - retry in %d seconds\n", attempt, int(retryIn.Seconds()))
|
||||
}
|
||||
|
||||
|
@ -298,8 +298,8 @@ func SearchImagesByCVEIDGQL(config searchConfig, repo, cveid string) error {
|
|||
return printImageResult(config, imageListData)
|
||||
}
|
||||
|
||||
func SearchFixedTagsGQL(config searchConfig, repo, cveid string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchFixedTagsGQL(config SearchConfig, repo, cveid string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
@ -309,7 +309,7 @@ func SearchFixedTagsGQL(config searchConfig, repo, cveid string) error {
|
|||
err := zcommon.RetryWithContext(ctx, func(attempt int, retryIn time.Duration) error {
|
||||
var err error
|
||||
|
||||
fixedTags, err = config.searchService.getFixedTagsForCVEGQL(ctx, config, username, password,
|
||||
fixedTags, err = config.SearchService.getFixedTagsForCVEGQL(ctx, config, username, password,
|
||||
repo, cveid)
|
||||
if err != nil {
|
||||
if !strings.Contains(err.Error(), zerr.ErrCVEDBNotFound.Error()) {
|
||||
|
@ -318,7 +318,7 @@ func SearchFixedTagsGQL(config searchConfig, repo, cveid string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(config.resultWriter,
|
||||
fmt.Fprintf(config.ResultWriter,
|
||||
"[warning] CVE DB is not ready [%d] - retry in %d seconds\n", attempt, int(retryIn.Seconds()))
|
||||
}
|
||||
|
||||
|
@ -337,13 +337,13 @@ func SearchFixedTagsGQL(config searchConfig, repo, cveid string) error {
|
|||
return printImageResult(config, imageList)
|
||||
}
|
||||
|
||||
func GlobalSearchGQL(config searchConfig, query string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func GlobalSearchGQL(config SearchConfig, query string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
defer cancel()
|
||||
|
||||
globalSearchResult, err := config.searchService.globalSearchGQL(ctx, config, username, password, query)
|
||||
globalSearchResult, err := config.SearchService.globalSearchGQL(ctx, config, username, password, query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -367,8 +367,8 @@ func GlobalSearchGQL(config searchConfig, query string) error {
|
|||
return printRepoResults(config, reposList)
|
||||
}
|
||||
|
||||
func SearchReferrersGQL(config searchConfig, subject string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchReferrersGQL(config SearchConfig, subject string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
|
||||
repo, ref, refIsTag, err := zcommon.GetRepoReference(subject)
|
||||
if err != nil {
|
||||
|
@ -384,7 +384,7 @@ func SearchReferrersGQL(config searchConfig, subject string) error {
|
|||
}
|
||||
}
|
||||
|
||||
response, err := config.searchService.getReferrersGQL(context.Background(), config, username, password, repo, digest)
|
||||
response, err := config.SearchService.getReferrersGQL(context.Background(), config, username, password, repo, digest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -399,13 +399,13 @@ func SearchReferrersGQL(config searchConfig, subject string) error {
|
|||
}
|
||||
}
|
||||
|
||||
printReferrersTableHeader(config, config.resultWriter, maxArtifactTypeLen)
|
||||
printReferrersTableHeader(config, config.ResultWriter, maxArtifactTypeLen)
|
||||
|
||||
return printReferrersResult(config, referrersList, maxArtifactTypeLen)
|
||||
}
|
||||
|
||||
func SearchReferrers(config searchConfig, subject string) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchReferrers(config SearchConfig, subject string) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
|
||||
repo, ref, refIsTag, err := zcommon.GetRepoReference(subject)
|
||||
if err != nil {
|
||||
|
@ -421,7 +421,7 @@ func SearchReferrers(config searchConfig, subject string) error {
|
|||
}
|
||||
}
|
||||
|
||||
referrersList, err := config.searchService.getReferrers(context.Background(), config, username, password,
|
||||
referrersList, err := config.SearchService.getReferrers(context.Background(), config, username, password,
|
||||
repo, digest)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -435,13 +435,13 @@ func SearchReferrers(config searchConfig, subject string) error {
|
|||
}
|
||||
}
|
||||
|
||||
printReferrersTableHeader(config, config.resultWriter, maxArtifactTypeLen)
|
||||
printReferrersTableHeader(config, config.ResultWriter, maxArtifactTypeLen)
|
||||
|
||||
return printReferrersResult(config, referrersList, maxArtifactTypeLen)
|
||||
}
|
||||
|
||||
func SearchRepos(config searchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.user)
|
||||
func SearchRepos(config SearchConfig) error {
|
||||
username, password := getUsernameAndPassword(config.User)
|
||||
repoErr := make(chan stringResult)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
|
@ -449,7 +449,7 @@ func SearchRepos(config searchConfig) error {
|
|||
|
||||
wg.Add(1)
|
||||
|
||||
go config.searchService.getRepos(ctx, config, username, password, repoErr, &wg)
|
||||
go config.SearchService.getRepos(ctx, config, username, password, repoErr, &wg)
|
||||
wg.Add(1)
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
|
|
@ -29,7 +29,7 @@ func TestSearchAllImages(t *testing.T) {
|
|||
Convey("SearchAllImages", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getAllImagesFn: func(ctx context.Context, config searchConfig, username, password string,
|
||||
getAllImagesFn: func(ctx context.Context, config SearchConfig, username, password string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
str, err := getMockImageStruct().stringPlainText(10, 10, 10, false)
|
||||
|
@ -51,7 +51,7 @@ func TestSearchAllImagesGQL(t *testing.T) {
|
|||
Convey("SearchAllImagesGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesGQLFn: func(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
getImagesGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
) (*common.ImageListResponse, error) {
|
||||
return &common.ImageListResponse{ImageList: common.ImageList{
|
||||
PaginatedImagesResult: common.PaginatedImagesResult{
|
||||
|
@ -72,7 +72,7 @@ func TestSearchAllImagesGQL(t *testing.T) {
|
|||
Convey("SearchAllImagesGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesGQLFn: func(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
getImagesGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
) (*common.ImageListResponse, error) {
|
||||
return &common.ImageListResponse{ImageList: common.ImageList{
|
||||
PaginatedImagesResult: common.PaginatedImagesResult{
|
||||
|
@ -91,7 +91,7 @@ func TestSearchImageByName(t *testing.T) {
|
|||
Convey("SearchImageByName", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImageByNameFn: func(ctx context.Context, config searchConfig, username string, password string, imageName string,
|
||||
getImageByNameFn: func(ctx context.Context, config SearchConfig, username string, password string, imageName string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
str, err := getMockImageStruct().stringPlainText(10, 10, 10, false)
|
||||
|
@ -111,7 +111,7 @@ func TestSearchImageByName(t *testing.T) {
|
|||
Convey("SearchImageByName error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImageByNameFn: func(ctx context.Context, config searchConfig, username string, password string, imageName string,
|
||||
getImageByNameFn: func(ctx context.Context, config SearchConfig, username string, password string, imageName string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
channel <- stringResult{StrValue: "", Err: zerr.ErrInjected}
|
||||
|
@ -127,7 +127,7 @@ func TestSearchImageByNameGQL(t *testing.T) {
|
|||
Convey("SearchImageByNameGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesGQLFn: func(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
getImagesGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
) (*common.ImageListResponse, error) {
|
||||
return &common.ImageListResponse{ImageList: common.ImageList{
|
||||
PaginatedImagesResult: common.PaginatedImagesResult{
|
||||
|
@ -148,7 +148,7 @@ func TestSearchImageByNameGQL(t *testing.T) {
|
|||
Convey("SearchImageByNameGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesGQLFn: func(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
getImagesGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
) (*common.ImageListResponse, error) {
|
||||
return &common.ImageListResponse{ImageList: common.ImageList{
|
||||
PaginatedImagesResult: common.PaginatedImagesResult{
|
||||
|
@ -167,7 +167,7 @@ func TestSearchImagesByDigest(t *testing.T) {
|
|||
Convey("SearchImagesByDigest", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesByDigestFn: func(ctx context.Context, config searchConfig, username string, password string, digest string,
|
||||
getImagesByDigestFn: func(ctx context.Context, config SearchConfig, username string, password string, digest string,
|
||||
rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
str, err := getMockImageStruct().stringPlainText(10, 10, 10, false)
|
||||
|
@ -187,7 +187,7 @@ func TestSearchImagesByDigest(t *testing.T) {
|
|||
Convey("SearchImagesByDigest error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesByDigestFn: func(ctx context.Context, config searchConfig, username string, password string, digest string,
|
||||
getImagesByDigestFn: func(ctx context.Context, config SearchConfig, username string, password string, digest string,
|
||||
rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
rch <- stringResult{StrValue: "", Err: zerr.ErrInjected}
|
||||
|
@ -203,7 +203,7 @@ func TestSearchDerivedImageListGQL(t *testing.T) {
|
|||
Convey("SearchDerivedImageListGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getDerivedImageListGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getDerivedImageListGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
derivedImage string) (*common.DerivedImageListResponse, error,
|
||||
) {
|
||||
return &common.DerivedImageListResponse{DerivedImageList: common.DerivedImageList{
|
||||
|
@ -227,7 +227,7 @@ func TestSearchDerivedImageListGQL(t *testing.T) {
|
|||
Convey("SearchDerivedImageListGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getDerivedImageListGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getDerivedImageListGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
derivedImage string) (*common.DerivedImageListResponse, error,
|
||||
) {
|
||||
return &common.DerivedImageListResponse{DerivedImageList: common.DerivedImageList{
|
||||
|
@ -245,7 +245,7 @@ func TestSearchBaseImageListGQL(t *testing.T) {
|
|||
Convey("SearchBaseImageListGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getBaseImageListGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getBaseImageListGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
derivedImage string) (*common.BaseImageListResponse, error,
|
||||
) {
|
||||
return &common.BaseImageListResponse{BaseImageList: common.BaseImageList{
|
||||
|
@ -267,7 +267,7 @@ func TestSearchBaseImageListGQL(t *testing.T) {
|
|||
Convey("SearchBaseImageListGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getBaseImageListGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getBaseImageListGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
derivedImage string) (*common.BaseImageListResponse, error,
|
||||
) {
|
||||
return &common.BaseImageListResponse{BaseImageList: common.BaseImageList{
|
||||
|
@ -285,7 +285,7 @@ func TestSearchImagesForDigestGQL(t *testing.T) {
|
|||
Convey("SearchImagesForDigestGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesForDigestGQLFn: func(ctx context.Context, config searchConfig, username string,
|
||||
getImagesForDigestGQLFn: func(ctx context.Context, config SearchConfig, username string,
|
||||
password string, digest string) (*common.ImagesForDigest, error,
|
||||
) {
|
||||
return &common.ImagesForDigest{ImagesForDigestList: common.ImagesForDigestList{
|
||||
|
@ -307,7 +307,7 @@ func TestSearchImagesForDigestGQL(t *testing.T) {
|
|||
Convey("SearchImagesForDigestGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getImagesForDigestGQLFn: func(ctx context.Context, config searchConfig, username string,
|
||||
getImagesForDigestGQLFn: func(ctx context.Context, config SearchConfig, username string,
|
||||
password string, digest string) (*common.ImagesForDigest, error,
|
||||
) {
|
||||
return &common.ImagesForDigest{ImagesForDigestList: common.ImagesForDigestList{
|
||||
|
@ -325,7 +325,7 @@ func TestSearchCVEForImageGQL(t *testing.T) {
|
|||
Convey("SearchCVEForImageGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getCveByImageGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
imageName string, searchedCVE string) (*cveResult, error,
|
||||
) {
|
||||
return &cveResult{
|
||||
|
@ -363,7 +363,7 @@ func TestSearchCVEForImageGQL(t *testing.T) {
|
|||
Convey("SearchCVEForImageGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getCveByImageGQLFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
imageName string, searchedCVE string) (*cveResult, error,
|
||||
) {
|
||||
return &cveResult{}, zerr.ErrInjected
|
||||
|
@ -379,7 +379,7 @@ func TestSearchImagesByCVEIDGQL(t *testing.T) {
|
|||
Convey("SearchImagesByCVEIDGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*common.ImagesForCve, error,
|
||||
) {
|
||||
return &common.ImagesForCve{
|
||||
|
@ -405,7 +405,7 @@ func TestSearchImagesByCVEIDGQL(t *testing.T) {
|
|||
Convey("SearchImagesByCVEIDGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*common.ImagesForCve, error,
|
||||
) {
|
||||
return &common.ImagesForCve{
|
||||
|
@ -425,7 +425,7 @@ func TestSearchFixedTagsGQL(t *testing.T) {
|
|||
Convey("SearchFixedTagsGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*common.ImageListWithCVEFixedResponse, error,
|
||||
) {
|
||||
return &common.ImageListWithCVEFixedResponse{
|
||||
|
@ -449,7 +449,7 @@ func TestSearchFixedTagsGQL(t *testing.T) {
|
|||
Convey("SearchFixedTagsGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getFixedTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, cveID string) (*common.ImageListWithCVEFixedResponse, error,
|
||||
) {
|
||||
return &common.ImageListWithCVEFixedResponse{
|
||||
|
@ -469,7 +469,7 @@ func TestSearchReferrersGQL(t *testing.T) {
|
|||
Convey("SearchReferrersGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getReferrersGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getReferrersGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
repo, digest string) (*common.ReferrersResp, error,
|
||||
) {
|
||||
return &common.ReferrersResp{
|
||||
|
@ -497,7 +497,7 @@ func TestSearchReferrersGQL(t *testing.T) {
|
|||
Convey("SearchReferrersGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getReferrersGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
getReferrersGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
repo, digest string) (*common.ReferrersResp, error,
|
||||
) {
|
||||
return &common.ReferrersResp{}, zerr.ErrInjected
|
||||
|
@ -513,7 +513,7 @@ func TestGlobalSearchGQL(t *testing.T) {
|
|||
Convey("GlobalSearchGQL", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
globalSearchGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
globalSearchGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
query string) (*common.GlobalSearch, error,
|
||||
) {
|
||||
return &common.GlobalSearch{
|
||||
|
@ -538,7 +538,7 @@ func TestGlobalSearchGQL(t *testing.T) {
|
|||
Convey("GlobalSearchGQL error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
globalSearchGQLFn: func(ctx context.Context, config searchConfig, username, password,
|
||||
globalSearchGQLFn: func(ctx context.Context, config SearchConfig, username, password,
|
||||
query string) (*common.GlobalSearch, error,
|
||||
) {
|
||||
return &common.GlobalSearch{}, zerr.ErrInjected
|
||||
|
@ -554,7 +554,7 @@ func TestSearchReferrers(t *testing.T) {
|
|||
Convey("SearchReferrers", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getReferrersFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getReferrersFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
repo string, digest string) (referrersResult, error,
|
||||
) {
|
||||
return referrersResult([]common.Referrer{
|
||||
|
@ -580,7 +580,7 @@ func TestSearchReferrers(t *testing.T) {
|
|||
Convey("SearchReferrers error", t, func() {
|
||||
buff := bytes.NewBufferString("")
|
||||
searchConfig := getMockSearchConfig(buff, mockService{
|
||||
getReferrersFn: func(ctx context.Context, config searchConfig, username string, password string,
|
||||
getReferrersFn: func(ctx context.Context, config SearchConfig, username string, password string,
|
||||
repo string, digest string) (referrersResult, error,
|
||||
) {
|
||||
return referrersResult{}, zerr.ErrInjected
|
||||
|
@ -607,17 +607,17 @@ func TestSearchRepos(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func getMockSearchConfig(buff *bytes.Buffer, mockService mockService) searchConfig {
|
||||
return searchConfig{
|
||||
resultWriter: buff,
|
||||
user: "",
|
||||
searchService: mockService,
|
||||
servURL: "http://127.0.0.1:8000",
|
||||
outputFormat: "",
|
||||
verifyTLS: false,
|
||||
fixedFlag: false,
|
||||
verbose: false,
|
||||
debug: false,
|
||||
func getMockSearchConfig(buff *bytes.Buffer, mockService mockService) SearchConfig {
|
||||
return SearchConfig{
|
||||
ResultWriter: buff,
|
||||
User: "",
|
||||
SearchService: mockService,
|
||||
ServURL: "http://127.0.0.1:8000",
|
||||
OutputFormat: "",
|
||||
VerifyTLS: false,
|
||||
FixedFlag: false,
|
||||
Verbose: false,
|
||||
Debug: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -744,19 +744,19 @@ func TestUtils(t *testing.T) {
|
|||
|
||||
Convey("CheckExtEndPointQuery", t, func() {
|
||||
// invalid url
|
||||
err := CheckExtEndPointQuery(searchConfig{
|
||||
user: "",
|
||||
servURL: "bad-url",
|
||||
err := CheckExtEndPointQuery(SearchConfig{
|
||||
User: "",
|
||||
ServURL: "bad-url",
|
||||
})
|
||||
So(err, ShouldNotBeNil)
|
||||
|
||||
// good url but no connection
|
||||
err = CheckExtEndPointQuery(searchConfig{
|
||||
user: "",
|
||||
servURL: "http://127.0.0.1:5000",
|
||||
verifyTLS: false,
|
||||
debug: false,
|
||||
resultWriter: io.Discard,
|
||||
err = CheckExtEndPointQuery(SearchConfig{
|
||||
User: "",
|
||||
ServURL: "http://127.0.0.1:5000",
|
||||
VerifyTLS: false,
|
||||
Debug: false,
|
||||
ResultWriter: io.Discard,
|
||||
})
|
||||
So(err, ShouldNotBeNil)
|
||||
})
|
||||
|
|
|
@ -32,49 +32,49 @@ const (
|
|||
)
|
||||
|
||||
type SearchService interface { //nolint:interfacebloat
|
||||
getImagesGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
getImagesGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
imageName string) (*common.ImageListResponse, error)
|
||||
getImagesForDigestGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
getImagesForDigestGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
digest string) (*common.ImagesForDigest, error)
|
||||
getCveByImageGQL(ctx context.Context, config searchConfig, username, password,
|
||||
getCveByImageGQL(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName string, searchedCVE string) (*cveResult, error)
|
||||
getTagsForCVEGQL(ctx context.Context, config searchConfig, username, password, repo,
|
||||
getTagsForCVEGQL(ctx context.Context, config SearchConfig, username, password, repo,
|
||||
cveID string) (*common.ImagesForCve, error)
|
||||
getFixedTagsForCVEGQL(ctx context.Context, config searchConfig, username, password, imageName,
|
||||
getFixedTagsForCVEGQL(ctx context.Context, config SearchConfig, username, password, imageName,
|
||||
cveID string) (*common.ImageListWithCVEFixedResponse, error)
|
||||
getDerivedImageListGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
getDerivedImageListGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
derivedImage string) (*common.DerivedImageListResponse, error)
|
||||
getBaseImageListGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
getBaseImageListGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
baseImage string) (*common.BaseImageListResponse, error)
|
||||
getReferrersGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
getReferrersGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
repo, digest string) (*common.ReferrersResp, error)
|
||||
globalSearchGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
globalSearchGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
query string) (*common.GlobalSearch, error)
|
||||
|
||||
getAllImages(ctx context.Context, config searchConfig, username, password string,
|
||||
getAllImages(ctx context.Context, config SearchConfig, username, password string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup)
|
||||
getImagesByDigest(ctx context.Context, config searchConfig, username, password, digest string,
|
||||
getImagesByDigest(ctx context.Context, config SearchConfig, username, password, digest string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup)
|
||||
getRepos(ctx context.Context, config searchConfig, username, password string,
|
||||
getRepos(ctx context.Context, config SearchConfig, username, password string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup)
|
||||
getImageByName(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
getImageByName(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
channel chan stringResult, wtgrp *sync.WaitGroup)
|
||||
getReferrers(ctx context.Context, config searchConfig, username, password string, repo, digest string,
|
||||
getReferrers(ctx context.Context, config SearchConfig, username, password string, repo, digest string,
|
||||
) (referrersResult, error)
|
||||
}
|
||||
|
||||
type searchConfig struct {
|
||||
searchService SearchService
|
||||
servURL string
|
||||
user string
|
||||
outputFormat string
|
||||
sortBy string
|
||||
verifyTLS bool
|
||||
fixedFlag bool
|
||||
verbose bool
|
||||
debug bool
|
||||
resultWriter io.Writer
|
||||
spinner spinnerState
|
||||
type SearchConfig struct {
|
||||
SearchService SearchService
|
||||
ServURL string
|
||||
User string
|
||||
OutputFormat string
|
||||
SortBy string
|
||||
VerifyTLS bool
|
||||
FixedFlag bool
|
||||
Verbose bool
|
||||
Debug bool
|
||||
ResultWriter io.Writer
|
||||
Spinner spinnerState
|
||||
}
|
||||
|
||||
type searchService struct{}
|
||||
|
@ -83,7 +83,7 @@ func NewSearchService() SearchService {
|
|||
return searchService{}
|
||||
}
|
||||
|
||||
func (service searchService) getDerivedImageListGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getDerivedImageListGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
derivedImage string,
|
||||
) (*common.DerivedImageListResponse, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -107,7 +107,7 @@ func (service searchService) getDerivedImageListGQL(ctx context.Context, config
|
|||
IsSigned
|
||||
}
|
||||
}
|
||||
}`, derivedImage, Flag2SortCriteria(config.sortBy))
|
||||
}`, derivedImage, Flag2SortCriteria(config.SortBy))
|
||||
|
||||
result := &common.DerivedImageListResponse{}
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -119,7 +119,7 @@ func (service searchService) getDerivedImageListGQL(ctx context.Context, config
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getReferrersGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getReferrersGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
repo, digest string,
|
||||
) (*common.ReferrersResp, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -146,7 +146,7 @@ func (service searchService) getReferrersGQL(ctx context.Context, config searchC
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) globalSearchGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) globalSearchGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
query string,
|
||||
) (*common.GlobalSearch, error) {
|
||||
GQLQuery := fmt.Sprintf(`
|
||||
|
@ -179,7 +179,7 @@ func (service searchService) globalSearchGQL(ctx context.Context, config searchC
|
|||
StarCount
|
||||
}
|
||||
}
|
||||
}`, query, Flag2SortCriteria(config.sortBy))
|
||||
}`, query, Flag2SortCriteria(config.SortBy))
|
||||
|
||||
result := &common.GlobalSearchResultResp{}
|
||||
|
||||
|
@ -191,7 +191,7 @@ func (service searchService) globalSearchGQL(ctx context.Context, config searchC
|
|||
return &result.GlobalSearch, nil
|
||||
}
|
||||
|
||||
func (service searchService) getBaseImageListGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getBaseImageListGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
baseImage string,
|
||||
) (*common.BaseImageListResponse, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -215,7 +215,7 @@ func (service searchService) getBaseImageListGQL(ctx context.Context, config sea
|
|||
IsSigned
|
||||
}
|
||||
}
|
||||
}`, baseImage, Flag2SortCriteria(config.sortBy))
|
||||
}`, baseImage, Flag2SortCriteria(config.SortBy))
|
||||
|
||||
result := &common.BaseImageListResponse{}
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -227,7 +227,7 @@ func (service searchService) getBaseImageListGQL(ctx context.Context, config sea
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getImagesGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getImagesGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
imageName string,
|
||||
) (*common.ImageListResponse, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -251,7 +251,7 @@ func (service searchService) getImagesGQL(ctx context.Context, config searchConf
|
|||
IsSigned
|
||||
}
|
||||
}
|
||||
}`, imageName, Flag2SortCriteria(config.sortBy))
|
||||
}`, imageName, Flag2SortCriteria(config.SortBy))
|
||||
result := &common.ImageListResponse{}
|
||||
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -263,7 +263,7 @@ func (service searchService) getImagesGQL(ctx context.Context, config searchConf
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getImagesForDigestGQL(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getImagesForDigestGQL(ctx context.Context, config SearchConfig, username, password string,
|
||||
digest string,
|
||||
) (*common.ImagesForDigest, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -287,7 +287,7 @@ func (service searchService) getImagesForDigestGQL(ctx context.Context, config s
|
|||
IsSigned
|
||||
}
|
||||
}
|
||||
}`, digest, Flag2SortCriteria(config.sortBy))
|
||||
}`, digest, Flag2SortCriteria(config.SortBy))
|
||||
result := &common.ImagesForDigest{}
|
||||
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -299,7 +299,7 @@ func (service searchService) getImagesForDigestGQL(ctx context.Context, config s
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getCveByImageGQL(ctx context.Context, config searchConfig, username, password,
|
||||
func (service searchService) getCveByImageGQL(ctx context.Context, config SearchConfig, username, password,
|
||||
imageName, searchedCVE string,
|
||||
) (*cveResult, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -310,7 +310,7 @@ func (service searchService) getCveByImageGQL(ctx context.Context, config search
|
|||
PackageList {Name InstalledVersion FixedVersion}
|
||||
}
|
||||
}
|
||||
}`, imageName, searchedCVE, Flag2SortCriteria(config.sortBy))
|
||||
}`, imageName, searchedCVE, Flag2SortCriteria(config.SortBy))
|
||||
result := &cveResult{}
|
||||
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -322,7 +322,7 @@ func (service searchService) getCveByImageGQL(ctx context.Context, config search
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getTagsForCVEGQL(ctx context.Context, config searchConfig,
|
||||
func (service searchService) getTagsForCVEGQL(ctx context.Context, config SearchConfig,
|
||||
username, password, repo, cveID string,
|
||||
) (*common.ImagesForCve, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -347,7 +347,7 @@ func (service searchService) getTagsForCVEGQL(ctx context.Context, config search
|
|||
}
|
||||
}
|
||||
}`,
|
||||
cveID, Flag2SortCriteria(config.sortBy))
|
||||
cveID, Flag2SortCriteria(config.SortBy))
|
||||
result := &common.ImagesForCve{}
|
||||
|
||||
err := service.makeGraphQLQuery(ctx, config, username, password, query, result)
|
||||
|
@ -371,7 +371,7 @@ func (service searchService) getTagsForCVEGQL(ctx context.Context, config search
|
|||
return filteredResults, nil
|
||||
}
|
||||
|
||||
func (service searchService) getFixedTagsForCVEGQL(ctx context.Context, config searchConfig,
|
||||
func (service searchService) getFixedTagsForCVEGQL(ctx context.Context, config SearchConfig,
|
||||
username, password, imageName, cveID string,
|
||||
) (*common.ImageListWithCVEFixedResponse, error) {
|
||||
query := fmt.Sprintf(`
|
||||
|
@ -409,10 +409,10 @@ func (service searchService) getFixedTagsForCVEGQL(ctx context.Context, config s
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (service searchService) getReferrers(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getReferrers(ctx context.Context, config SearchConfig, username, password string,
|
||||
repo, digest string,
|
||||
) (referrersResult, error) {
|
||||
referrersEndpoint, err := combineServerAndEndpointURL(config.servURL,
|
||||
referrersEndpoint, err := combineServerAndEndpointURL(config.ServURL,
|
||||
fmt.Sprintf("/v2/%s/referrers/%s", repo, digest))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -423,8 +423,8 @@ func (service searchService) getReferrers(ctx context.Context, config searchConf
|
|||
}
|
||||
|
||||
referrerResp := &ispec.Index{}
|
||||
_, err = makeGETRequest(ctx, referrersEndpoint, username, password, config.verifyTLS,
|
||||
config.debug, &referrerResp, config.resultWriter)
|
||||
_, err = makeGETRequest(ctx, referrersEndpoint, username, password, config.VerifyTLS,
|
||||
config.Debug, &referrerResp, config.ResultWriter)
|
||||
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -447,7 +447,7 @@ func (service searchService) getReferrers(ctx context.Context, config searchConf
|
|||
return referrersList, nil
|
||||
}
|
||||
|
||||
func (service searchService) getImageByName(ctx context.Context, config searchConfig,
|
||||
func (service searchService) getImageByName(ctx context.Context, config SearchConfig,
|
||||
username, password, imageName string, rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
@ -466,7 +466,7 @@ func (service searchService) getImageByName(ctx context.Context, config searchCo
|
|||
localWg.Wait()
|
||||
}
|
||||
|
||||
func (service searchService) getAllImages(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getAllImages(ctx context.Context, config SearchConfig, username, password string,
|
||||
rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
@ -474,7 +474,7 @@ func (service searchService) getAllImages(ctx context.Context, config searchConf
|
|||
|
||||
catalog := &catalogResponse{}
|
||||
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("%s%s",
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(config.ServURL, fmt.Sprintf("%s%s",
|
||||
constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -485,8 +485,8 @@ func (service searchService) getAllImages(ctx context.Context, config searchConf
|
|||
return
|
||||
}
|
||||
|
||||
_, err = makeGETRequest(ctx, catalogEndPoint, username, password, config.verifyTLS,
|
||||
config.debug, catalog, config.resultWriter)
|
||||
_, err = makeGETRequest(ctx, catalogEndPoint, username, password, config.VerifyTLS,
|
||||
config.Debug, catalog, config.ResultWriter)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -513,14 +513,14 @@ func (service searchService) getAllImages(ctx context.Context, config searchConf
|
|||
localWg.Wait()
|
||||
}
|
||||
|
||||
func getImage(ctx context.Context, config searchConfig, username, password, imageName string,
|
||||
func getImage(ctx context.Context, config SearchConfig, username, password, imageName string,
|
||||
rch chan stringResult, wtgrp *sync.WaitGroup, pool *requestsPool,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
||||
repo, imageTag := common.GetImageDirAndTag(imageName)
|
||||
|
||||
tagListEndpoint, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("/v2/%s/tags/list", repo))
|
||||
tagListEndpoint, err := combineServerAndEndpointURL(config.ServURL, fmt.Sprintf("/v2/%s/tags/list", repo))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -531,8 +531,8 @@ func getImage(ctx context.Context, config searchConfig, username, password, imag
|
|||
}
|
||||
|
||||
tagList := &tagListResp{}
|
||||
_, err = makeGETRequest(ctx, tagListEndpoint, username, password, config.verifyTLS,
|
||||
config.debug, &tagList, config.resultWriter)
|
||||
_, err = makeGETRequest(ctx, tagListEndpoint, username, password, config.VerifyTLS,
|
||||
config.Debug, &tagList, config.ResultWriter)
|
||||
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -567,7 +567,7 @@ func getImage(ctx context.Context, config searchConfig, username, password, imag
|
|||
}
|
||||
}
|
||||
|
||||
func (service searchService) getImagesByDigest(ctx context.Context, config searchConfig, username,
|
||||
func (service searchService) getImagesByDigest(ctx context.Context, config SearchConfig, username,
|
||||
password string, digest string, rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
@ -652,16 +652,16 @@ func isContextDone(ctx context.Context) bool {
|
|||
// Query using GQL, the query string is passed as a parameter
|
||||
// errors are returned in the stringResult channel, the unmarshalled payload is in resultPtr.
|
||||
func (service searchService) makeGraphQLQuery(ctx context.Context,
|
||||
config searchConfig, username, password, query string,
|
||||
config SearchConfig, username, password, query string,
|
||||
resultPtr interface{},
|
||||
) error {
|
||||
endPoint, err := combineServerAndEndpointURL(config.servURL, constants.FullSearchPrefix)
|
||||
endPoint, err := combineServerAndEndpointURL(config.ServURL, constants.FullSearchPrefix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = makeGraphQLRequest(ctx, endPoint, query, username, password, config.verifyTLS,
|
||||
config.debug, resultPtr, config.resultWriter)
|
||||
err = makeGraphQLRequest(ctx, endPoint, query, username, password, config.VerifyTLS,
|
||||
config.Debug, resultPtr, config.ResultWriter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -697,12 +697,12 @@ func checkResultGraphQLQuery(ctx context.Context, err error, resultErrors []comm
|
|||
return nil
|
||||
}
|
||||
|
||||
func addManifestCallToPool(ctx context.Context, config searchConfig, pool *requestsPool,
|
||||
func addManifestCallToPool(ctx context.Context, config SearchConfig, pool *requestsPool,
|
||||
username, password, imageName, tagName string, rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
||||
manifestEndpoint, err := combineServerAndEndpointURL(config.servURL,
|
||||
manifestEndpoint, err := combineServerAndEndpointURL(config.ServURL,
|
||||
fmt.Sprintf("/v2/%s/manifests/%s", imageName, tagName))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -1304,7 +1304,7 @@ func getRepoTableWriter(writer io.Writer) *tablewriter.Table {
|
|||
return table
|
||||
}
|
||||
|
||||
func (service searchService) getRepos(ctx context.Context, config searchConfig, username, password string,
|
||||
func (service searchService) getRepos(ctx context.Context, config SearchConfig, username, password string,
|
||||
rch chan stringResult, wtgrp *sync.WaitGroup,
|
||||
) {
|
||||
defer wtgrp.Done()
|
||||
|
@ -1312,7 +1312,7 @@ func (service searchService) getRepos(ctx context.Context, config searchConfig,
|
|||
|
||||
catalog := &catalogResponse{}
|
||||
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("%s%s",
|
||||
catalogEndPoint, err := combineServerAndEndpointURL(config.ServURL, fmt.Sprintf("%s%s",
|
||||
constants.RoutePrefix, constants.ExtCatalogPrefix))
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
|
@ -1323,8 +1323,8 @@ func (service searchService) getRepos(ctx context.Context, config searchConfig,
|
|||
return
|
||||
}
|
||||
|
||||
_, err = makeGETRequest(ctx, catalogEndPoint, username, password, config.verifyTLS,
|
||||
config.debug, catalog, config.resultWriter)
|
||||
_, err = makeGETRequest(ctx, catalogEndPoint, username, password, config.VerifyTLS,
|
||||
config.Debug, catalog, config.ResultWriter)
|
||||
if err != nil {
|
||||
if isContextDone(ctx) {
|
||||
return
|
||||
|
@ -1334,15 +1334,15 @@ func (service searchService) getRepos(ctx context.Context, config searchConfig,
|
|||
return
|
||||
}
|
||||
|
||||
fmt.Fprintln(config.resultWriter, "\nREPOSITORY NAME")
|
||||
fmt.Fprintln(config.ResultWriter, "\nREPOSITORY NAME")
|
||||
|
||||
if config.sortBy == SortByAlphabeticAsc {
|
||||
if config.SortBy == SortByAlphabeticAsc {
|
||||
for i := 0; i < len(catalog.Repositories); i++ {
|
||||
fmt.Fprintln(config.resultWriter, catalog.Repositories[i])
|
||||
fmt.Fprintln(config.ResultWriter, catalog.Repositories[i])
|
||||
}
|
||||
} else {
|
||||
for i := len(catalog.Repositories) - 1; i >= 0; i-- {
|
||||
fmt.Fprintln(config.resultWriter, catalog.Repositories[i])
|
||||
fmt.Fprintln(config.ResultWriter, catalog.Repositories[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,31 +30,31 @@ func ref[T any](input T) *T {
|
|||
return &ref
|
||||
}
|
||||
|
||||
func fetchImageDigest(repo, ref, username, password string, config searchConfig) (string, error) {
|
||||
url, err := combineServerAndEndpointURL(config.servURL, fmt.Sprintf("/v2/%s/manifests/%s", repo, ref))
|
||||
func fetchImageDigest(repo, ref, username, password string, config SearchConfig) (string, error) {
|
||||
url, err := combineServerAndEndpointURL(config.ServURL, fmt.Sprintf("/v2/%s/manifests/%s", repo, ref))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
res, err := makeHEADRequest(context.Background(), url, username, password, config.verifyTLS, false)
|
||||
res, err := makeHEADRequest(context.Background(), url, username, password, config.VerifyTLS, false)
|
||||
|
||||
digestStr := res.Get(constants.DistContentDigestKey)
|
||||
|
||||
return digestStr, err
|
||||
}
|
||||
|
||||
func collectResults(config searchConfig, wg *sync.WaitGroup, imageErr chan stringResult,
|
||||
func collectResults(config SearchConfig, wg *sync.WaitGroup, imageErr chan stringResult,
|
||||
cancel context.CancelFunc, printHeader printHeader, errCh chan error,
|
||||
) {
|
||||
var foundResult bool
|
||||
|
||||
defer wg.Done()
|
||||
config.spinner.startSpinner()
|
||||
config.Spinner.startSpinner()
|
||||
|
||||
for {
|
||||
select {
|
||||
case result, ok := <-imageErr:
|
||||
config.spinner.stopSpinner()
|
||||
config.Spinner.stopSpinner()
|
||||
|
||||
if !ok {
|
||||
cancel()
|
||||
|
@ -69,18 +69,18 @@ func collectResults(config searchConfig, wg *sync.WaitGroup, imageErr chan strin
|
|||
return
|
||||
}
|
||||
|
||||
if !foundResult && (config.outputFormat == defaultOutputFormat || config.outputFormat == "") {
|
||||
if !foundResult && (config.OutputFormat == defaultOutputFormat || config.OutputFormat == "") {
|
||||
var builder strings.Builder
|
||||
|
||||
printHeader(&builder, config.verbose, 0, 0, 0)
|
||||
fmt.Fprint(config.resultWriter, builder.String())
|
||||
printHeader(&builder, config.Verbose, 0, 0, 0)
|
||||
fmt.Fprint(config.ResultWriter, builder.String())
|
||||
}
|
||||
|
||||
foundResult = true
|
||||
|
||||
fmt.Fprint(config.resultWriter, result.StrValue)
|
||||
fmt.Fprint(config.ResultWriter, result.StrValue)
|
||||
case <-time.After(waitTimeout):
|
||||
config.spinner.stopSpinner()
|
||||
config.Spinner.stopSpinner()
|
||||
cancel()
|
||||
|
||||
errCh <- zerr.ErrCLITimeout
|
||||
|
@ -193,8 +193,8 @@ func printCVETableHeader(writer io.Writer) {
|
|||
table.Render()
|
||||
}
|
||||
|
||||
func printReferrersTableHeader(config searchConfig, writer io.Writer, maxArtifactTypeLen int) {
|
||||
if config.outputFormat != "" && config.outputFormat != defaultOutputFormat {
|
||||
func printReferrersTableHeader(config SearchConfig, writer io.Writer, maxArtifactTypeLen int) {
|
||||
if config.OutputFormat != "" && config.OutputFormat != defaultOutputFormat {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -269,18 +269,18 @@ func printRepoTableHeader(writer io.Writer, repoMaxLen, maxTimeLen int, verbose
|
|||
table.Render()
|
||||
}
|
||||
|
||||
func printReferrersResult(config searchConfig, referrersList referrersResult, maxArtifactTypeLen int) error {
|
||||
out, err := referrersList.string(config.outputFormat, maxArtifactTypeLen)
|
||||
func printReferrersResult(config SearchConfig, referrersList referrersResult, maxArtifactTypeLen int) error {
|
||||
out, err := referrersList.string(config.OutputFormat, maxArtifactTypeLen)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(config.resultWriter, out)
|
||||
fmt.Fprint(config.ResultWriter, out)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printImageResult(config searchConfig, imageList []imageStruct) error {
|
||||
func printImageResult(config SearchConfig, imageList []imageStruct) error {
|
||||
var builder strings.Builder
|
||||
maxImgNameLen := 0
|
||||
maxTagLen := 0
|
||||
|
@ -305,29 +305,29 @@ func printImageResult(config searchConfig, imageList []imageStruct) error {
|
|||
}
|
||||
}
|
||||
|
||||
if config.outputFormat == defaultOutputFormat || config.outputFormat == "" {
|
||||
printImageTableHeader(&builder, config.verbose, maxImgNameLen, maxTagLen, maxPlatformLen)
|
||||
if config.OutputFormat == defaultOutputFormat || config.OutputFormat == "" {
|
||||
printImageTableHeader(&builder, config.Verbose, maxImgNameLen, maxTagLen, maxPlatformLen)
|
||||
}
|
||||
|
||||
fmt.Fprint(config.resultWriter, builder.String())
|
||||
fmt.Fprint(config.ResultWriter, builder.String())
|
||||
}
|
||||
|
||||
for i := range imageList {
|
||||
img := imageList[i]
|
||||
verbose := config.verbose
|
||||
verbose := config.Verbose
|
||||
|
||||
out, err := img.string(config.outputFormat, maxImgNameLen, maxTagLen, maxPlatformLen, verbose)
|
||||
out, err := img.string(config.OutputFormat, maxImgNameLen, maxTagLen, maxPlatformLen, verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(config.resultWriter, out)
|
||||
fmt.Fprint(config.ResultWriter, out)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func printRepoResults(config searchConfig, repoList []repoStruct) error {
|
||||
func printRepoResults(config SearchConfig, repoList []repoStruct) error {
|
||||
maxRepoNameLen := 0
|
||||
maxTimeLen := 0
|
||||
|
||||
|
@ -341,31 +341,31 @@ func printRepoResults(config searchConfig, repoList []repoStruct) error {
|
|||
}
|
||||
}
|
||||
|
||||
if len(repoList) > 0 && (config.outputFormat == defaultOutputFormat || config.outputFormat == "") {
|
||||
printRepoTableHeader(config.resultWriter, maxRepoNameLen, maxTimeLen, config.verbose)
|
||||
if len(repoList) > 0 && (config.OutputFormat == defaultOutputFormat || config.OutputFormat == "") {
|
||||
printRepoTableHeader(config.ResultWriter, maxRepoNameLen, maxTimeLen, config.Verbose)
|
||||
}
|
||||
|
||||
for _, repo := range repoList {
|
||||
out, err := repo.string(config.outputFormat, maxRepoNameLen, maxTimeLen, config.verbose)
|
||||
out, err := repo.string(config.OutputFormat, maxRepoNameLen, maxTimeLen, config.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(config.resultWriter, out)
|
||||
fmt.Fprint(config.ResultWriter, out)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetSearchConfigFromFlags(cmd *cobra.Command, searchService SearchService) (searchConfig, error) {
|
||||
func GetSearchConfigFromFlags(cmd *cobra.Command, searchService SearchService) (SearchConfig, error) {
|
||||
serverURL, err := GetServerURLFromFlags(cmd)
|
||||
if err != nil {
|
||||
return searchConfig{}, err
|
||||
return SearchConfig{}, err
|
||||
}
|
||||
|
||||
isSpinner, verifyTLS, err := GetCliConfigOptions(cmd)
|
||||
if err != nil {
|
||||
return searchConfig{}, err
|
||||
return SearchConfig{}, err
|
||||
}
|
||||
|
||||
flags := cmd.Flags()
|
||||
|
@ -379,18 +379,18 @@ func GetSearchConfigFromFlags(cmd *cobra.Command, searchService SearchService) (
|
|||
spin := spinner.New(spinner.CharSets[39], spinnerDuration, spinner.WithWriter(cmd.ErrOrStderr()))
|
||||
spin.Prefix = prefix
|
||||
|
||||
return searchConfig{
|
||||
searchService: searchService,
|
||||
servURL: serverURL,
|
||||
user: user,
|
||||
outputFormat: outputFormat,
|
||||
verifyTLS: verifyTLS,
|
||||
fixedFlag: fixed,
|
||||
verbose: verbose,
|
||||
debug: debug,
|
||||
sortBy: sortBy,
|
||||
spinner: spinnerState{spin, isSpinner},
|
||||
resultWriter: cmd.OutOrStdout(),
|
||||
return SearchConfig{
|
||||
SearchService: searchService,
|
||||
ServURL: serverURL,
|
||||
User: user,
|
||||
OutputFormat: outputFormat,
|
||||
VerifyTLS: verifyTLS,
|
||||
FixedFlag: fixed,
|
||||
Verbose: verbose,
|
||||
Debug: debug,
|
||||
SortBy: sortBy,
|
||||
Spinner: spinnerState{spin, isSpinner},
|
||||
ResultWriter: cmd.OutOrStdout(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -20,19 +20,19 @@ import (
|
|||
test "zotregistry.io/zot/pkg/test/common"
|
||||
)
|
||||
|
||||
func getDefaultSearchConf(baseURL string) searchConfig {
|
||||
func getDefaultSearchConf(baseURL string) SearchConfig {
|
||||
verifyTLS := false
|
||||
debug := false
|
||||
verbose := true
|
||||
outputFormat := "text"
|
||||
|
||||
return searchConfig{
|
||||
servURL: baseURL,
|
||||
resultWriter: io.Discard,
|
||||
verifyTLS: verifyTLS,
|
||||
debug: debug,
|
||||
verbose: verbose,
|
||||
outputFormat: outputFormat,
|
||||
return SearchConfig{
|
||||
ServURL: baseURL,
|
||||
ResultWriter: io.Discard,
|
||||
VerifyTLS: verifyTLS,
|
||||
Debug: debug,
|
||||
Verbose: verbose,
|
||||
OutputFormat: outputFormat,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue