mirror of
https://github.com/project-zot/zot.git
synced 2024-12-30 22:34:13 -05:00
f618b1d4ef
* ci(deps): upgrade golangci-lint
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
* build(deps): removed disabled linters
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
* build(deps): go run github.com/daixiang0/gci@latest write .
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): go run golang.org/x/tools/cmd/goimports@latest -l -w .
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): go run github.com/bombsimon/wsl/v4/cmd...@latest -strict-append -test=true -fix ./...
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): go run github.com/catenacyber/perfsprint@latest -fix ./...
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): replace gomnd by mnd
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): make gqlgen
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build: Revert "build(deps): go run github.com/daixiang0/gci@latest write ."
This reverts commit 5bf8c42e1f
.
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): go run github.com/daixiang0/gci@latest write -s 'standard' -s default -s 'prefix(zotregistry.dev/zot)' .
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* build(deps): make gqlgen
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: wsl issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: check-log issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: gci issues
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
* fix: tests
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
---------
Signed-off-by: Jan-Otto Kröpke <mail@jkroepke.de>
Signed-off-by: Jan-Otto Kröpke <joe@cloudeteer.de>
1376 lines
48 KiB
Go
1376 lines
48 KiB
Go
//go:build search
|
|
// +build search
|
|
|
|
package client_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"path"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
godigest "github.com/opencontainers/go-digest"
|
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
"github.com/sigstore/cosign/v2/cmd/cosign/cli/generate"
|
|
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
|
|
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
"gopkg.in/resty.v1"
|
|
|
|
"zotregistry.dev/zot/pkg/api"
|
|
"zotregistry.dev/zot/pkg/api/config"
|
|
"zotregistry.dev/zot/pkg/cli/client"
|
|
extconf "zotregistry.dev/zot/pkg/extensions/config"
|
|
zlog "zotregistry.dev/zot/pkg/log"
|
|
test "zotregistry.dev/zot/pkg/test/common"
|
|
. "zotregistry.dev/zot/pkg/test/image-utils"
|
|
ociutils "zotregistry.dev/zot/pkg/test/oci-utils"
|
|
"zotregistry.dev/zot/pkg/test/signature"
|
|
)
|
|
|
|
//nolint:dupl
|
|
func TestSignature(t *testing.T) {
|
|
space := regexp.MustCompile(`\s+`)
|
|
repoName := "repo7"
|
|
|
|
Convey("Test with cosign signature(tag)", t, func() {
|
|
currentWorkingDir, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
|
|
defer func() { _ = os.Chdir(currentWorkingDir) }()
|
|
|
|
currentDir := t.TempDir()
|
|
err = os.Chdir(currentDir)
|
|
So(err, ShouldBeNil)
|
|
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = currentDir
|
|
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
image := CreateDefaultImage()
|
|
err = UploadImage(image, url, repoName, "1.0")
|
|
So(err, ShouldBeNil)
|
|
|
|
// generate a keypair
|
|
if _, err := os.Stat(path.Join(currentDir, "cosign.key")); err != nil {
|
|
os.Setenv("COSIGN_PASSWORD", "")
|
|
err = generate.GenerateKeyPairCmd(context.TODO(), "", "cosign", nil)
|
|
So(err, ShouldBeNil)
|
|
}
|
|
|
|
_, err = os.Stat(path.Join(currentDir, "cosign.key"))
|
|
So(err, ShouldBeNil)
|
|
|
|
// sign the image
|
|
err = sign.SignCmd(&options.RootOptions{Verbose: true, Timeout: 1 * time.Minute},
|
|
options.KeyOpts{KeyRef: path.Join(currentDir, "cosign.key"), PassFunc: generate.GetPass},
|
|
options.SignOptions{
|
|
Registry: options.RegistryOptions{AllowInsecure: true},
|
|
AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=test:1.0"}},
|
|
Upload: true,
|
|
},
|
|
[]string{fmt.Sprintf("localhost:%s/%s@%s", port, "repo7", image.DigestStr())})
|
|
So(err, ShouldBeNil)
|
|
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
|
|
err = client.SearchAllImagesGQL(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 1.0 linux/amd64 db573b01 true 854B")
|
|
|
|
t.Log("Test getting all images using rest calls to get catalog and individual manifests")
|
|
|
|
buff = &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err = client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 1.0 linux/amd64 db573b01 true 854B")
|
|
})
|
|
|
|
Convey("Test with cosign signature(withReferrers)", t, func() {
|
|
currentWorkingDir, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
|
|
defer func() { _ = os.Chdir(currentWorkingDir) }()
|
|
|
|
currentDir := t.TempDir()
|
|
err = os.Chdir(currentDir)
|
|
So(err, ShouldBeNil)
|
|
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = currentDir
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignImageUsingCosign("repo7:0.0.1", port, true)
|
|
So(err, ShouldBeNil)
|
|
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err = client.SearchAllImagesGQL(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")
|
|
|
|
t.Log("Test getting all images using rest calls to get catalog and individual manifests")
|
|
buff = &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err = client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")
|
|
})
|
|
|
|
Convey("Test with notation signature", t, func() {
|
|
currentWorkingDir, err := os.Getwd()
|
|
So(err, ShouldBeNil)
|
|
|
|
defer func() { _ = os.Chdir(currentWorkingDir) }()
|
|
|
|
currentDir := t.TempDir()
|
|
err = os.Chdir(currentDir)
|
|
So(err, ShouldBeNil)
|
|
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = currentDir
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1")
|
|
So(err, ShouldBeNil)
|
|
|
|
err = signature.SignImageUsingNotary("repo7:0.0.1", port, true)
|
|
So(err, ShouldBeNil)
|
|
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err = client.SearchAllImagesGQL(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")
|
|
|
|
t.Log("Test getting all images using rest calls to get catalog and individual manifests")
|
|
buff = &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err = client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
actual = strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 0.0.1 linux/amd64 db573b01 true 854B")
|
|
})
|
|
}
|
|
|
|
//nolint:dupl
|
|
func TestDerivedImageList(t *testing.T) {
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
|
|
cm := test.NewControllerManager(ctlr)
|
|
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
defer cm.StopServer()
|
|
|
|
err := uploadManifestDerivedBase(url)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
|
|
t.Logf("rootDir: %s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
Convey("Test from real server", t, func() {
|
|
Convey("Test derived images list working", func() {
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchDerivedImageListGQL(searchConfig, "repo7:test:2.0")
|
|
So(err, ShouldBeNil)
|
|
|
|
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 9d9461ed false 860B")
|
|
})
|
|
|
|
Convey("Test derived images list fails", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchDerivedImageListGQL(searchConfig, "repo7:test:missing")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("Test derived images list cannot print", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
searchConfig.OutputFormat = "random"
|
|
err := client.SearchDerivedImageListGQL(searchConfig, "repo7:test:2.0")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
})
|
|
}
|
|
|
|
//nolint:dupl
|
|
func TestBaseImageList(t *testing.T) {
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
defer cm.StopServer()
|
|
|
|
err := uploadManifestDerivedBase(url)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
|
|
t.Logf("rootDir: %s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
Convey("Test from real server", t, func() {
|
|
Convey("Test base images list working", func() {
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchBaseImageListGQL(searchConfig, "repo7:test:1.0")
|
|
So(err, ShouldBeNil)
|
|
actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " "))
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 214e4bed false 530B")
|
|
})
|
|
|
|
Convey("Test base images list fail", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchBaseImageListGQL(searchConfig, "repo7:test:missing")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
|
|
Convey("Test base images list cannot print", func() {
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.OutputFormat = "random"
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchBaseImageListGQL(searchConfig, "repo7:test:missing")
|
|
So(err, ShouldNotBeNil)
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestOutputFormatGQL(t *testing.T) {
|
|
Convey("Test from real server", t, func() {
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
err := uploadManifest(url)
|
|
So(err, ShouldBeNil)
|
|
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
|
|
Convey("Test json", func() {
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
args := []string{"name", "repo7", "--config", "imagetest", "-f", "json"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
expectedStr := `{"repoName":"repo7","tag":"test:1.0",` +
|
|
`"digest":"sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06",` +
|
|
`"mediaType":"application/vnd.oci.image.manifest.v1+json",` +
|
|
`"manifests":[{"digest":"sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06",` +
|
|
`"configDigest":"sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e",` +
|
|
`"lastUpdated":"2023-01-01T12:00:00Z","size":"528","platform":{"os":"linux","arch":"amd64",` +
|
|
`"variant":""},"isSigned":false,"downloadCount":0,"layers":[{"size":"15","digest":` +
|
|
`"sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6","score":0}],` +
|
|
`"history":null,"vulnerabilities":{"maxSeverity":"","unknownCount":0,"lowCount":0,"mediumCount":0,` +
|
|
`"highCount":0,"criticalCount":0,"count":0},` +
|
|
`"referrers":null,"artifactType":"","signatureInfo":null}],` +
|
|
`"size":"528","downloadCount":0,"lastUpdated":"2023-01-01T12:00:00Z","description":"","isSigned":false,` +
|
|
`"licenses":"","labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",` +
|
|
`"vulnerabilities":{"maxSeverity":"","unknownCount":0,"lowCount":0,"mediumCount":0,` +
|
|
`"highCount":0,"criticalCount":0,"count":0},"referrers":null,"signatureInfo":null}` + "\n" +
|
|
`{"repoName":"repo7","tag":"test:2.0",` +
|
|
`"digest":"sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06",` +
|
|
`"mediaType":"application/vnd.oci.image.manifest.v1+json",` +
|
|
`"manifests":[{"digest":"sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06",` +
|
|
`"configDigest":"sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e",` +
|
|
`"lastUpdated":"2023-01-01T12:00:00Z","size":"528","platform":{"os":"linux","arch":"amd64",` +
|
|
`"variant":""},"isSigned":false,"downloadCount":0,"layers":[{"size":"15","digest":` +
|
|
`"sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6","score":0}],` +
|
|
`"history":null,"vulnerabilities":{"maxSeverity":"","unknownCount":0,"lowCount":0,"mediumCount":0,` +
|
|
`"highCount":0,"criticalCount":0,"count":0},` +
|
|
`"referrers":null,"artifactType":"","signatureInfo":null}],` +
|
|
`"size":"528","downloadCount":0,"lastUpdated":"2023-01-01T12:00:00Z","description":"","isSigned":false,` +
|
|
`"licenses":"","labels":"","title":"","source":"","documentation":"","authors":"","vendor":"",` +
|
|
`"vulnerabilities":{"maxSeverity":"","unknownCount":0,"lowCount":0,"mediumCount":0,` +
|
|
`"highCount":0,"criticalCount":0,"count":0},"referrers":null,"signatureInfo":null}` + "\n"
|
|
// Output is supposed to be in json lines format, keep all spaces as is for verification
|
|
So(buff.String(), ShouldEqual, expectedStr)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("Test yaml", func() {
|
|
args := []string{"name", "repo7", "--config", "imagetest", "-f", "yaml"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
expectedStr := `--- reponame: repo7 tag: test:1.0 ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`configdigest: sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e ` +
|
|
`lastupdated: 2023-01-01T12:00:00Z size: "528" platform: os: linux arch: amd64 variant: "" ` +
|
|
`issigned: false downloadcount: 0 layers: - size: "15" ` +
|
|
`digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` +
|
|
`history: [] vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] artifacttype: "" signatureinfo: [] ` +
|
|
`size: "528" downloadcount: 0 lastupdated: 2023-01-01T12:00:00Z description: "" ` +
|
|
`issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` +
|
|
`authors: "" vendor: "" vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] signatureinfo: [] ` +
|
|
`--- reponame: repo7 tag: test:2.0 ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`configdigest: sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e ` +
|
|
`lastupdated: 2023-01-01T12:00:00Z size: "528" platform: os: linux arch: amd64 variant: "" ` +
|
|
`issigned: false downloadcount: 0 layers: - size: "15" ` +
|
|
`digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` +
|
|
`history: [] vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] artifacttype: "" signatureinfo: [] ` +
|
|
`size: "528" downloadcount: 0 lastupdated: 2023-01-01T12:00:00Z description: "" ` +
|
|
`issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` +
|
|
`authors: "" vendor: "" vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] signatureinfo: []`
|
|
So(strings.TrimSpace(str), ShouldEqual, expectedStr)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("Test yml", func() {
|
|
args := []string{"name", "repo7", "--config", "imagetest", "-f", "yml"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
expectedStr := `--- reponame: repo7 tag: test:1.0 ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`configdigest: sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e ` +
|
|
`lastupdated: 2023-01-01T12:00:00Z size: "528" platform: os: linux arch: amd64 variant: "" ` +
|
|
`issigned: false downloadcount: 0 layers: - size: "15" ` +
|
|
`digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` +
|
|
`history: [] vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] artifacttype: "" signatureinfo: [] ` +
|
|
`size: "528" downloadcount: 0 lastupdated: 2023-01-01T12:00:00Z description: "" ` +
|
|
`issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` +
|
|
`authors: "" vendor: "" vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] signatureinfo: [] ` +
|
|
`--- reponame: repo7 tag: test:2.0 ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`mediatype: application/vnd.oci.image.manifest.v1+json manifests: - ` +
|
|
`digest: sha256:51e18f508fd7125b0831ff9a22ba74cd79f0b934e77661ff72cfb54896951a06 ` +
|
|
`configdigest: sha256:d14faead7d60053bad0d62e5ceb0031df28037d8c636d7911179b2f874ee004e ` +
|
|
`lastupdated: 2023-01-01T12:00:00Z size: "528" platform: os: linux arch: amd64 variant: "" ` +
|
|
`issigned: false downloadcount: 0 layers: - size: "15" ` +
|
|
`digest: sha256:b8781e8844f5b7bf6f2f8fa343de18ec471c3b278027355bc34c120585ff04f6 score: 0 ` +
|
|
`history: [] vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] artifacttype: "" signatureinfo: [] ` +
|
|
`size: "528" downloadcount: 0 lastupdated: 2023-01-01T12:00:00Z description: "" ` +
|
|
`issigned: false licenses: "" labels: "" title: "" source: "" documentation: "" ` +
|
|
`authors: "" vendor: "" vulnerabilities: maxseverity: "" ` +
|
|
`unknowncount: 0 lowcount: 0 mediumcount: 0 highcount: 0 criticalcount: 0 count: 0 ` +
|
|
`referrers: [] signatureinfo: []`
|
|
So(strings.TrimSpace(str), ShouldEqual, expectedStr)
|
|
So(err, ShouldBeNil)
|
|
})
|
|
|
|
Convey("Test invalid", func() {
|
|
args := []string{"name", "repo7", "--config", "imagetest", "-f", "random"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldNotBeNil)
|
|
So(buff.String(), ShouldContainSubstring, "invalid cli output format")
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestServerResponseGQL(t *testing.T) {
|
|
Convey("Test from real server", t, func() {
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
err := uploadManifest(url)
|
|
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
So(err, ShouldBeNil)
|
|
|
|
Convey("Test all images config url", func() {
|
|
t.Logf("%s", ctlr.Config.Storage.RootDirectory)
|
|
args := []string{"list", "--config", "imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(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 := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
Convey("Test all images invalid output format", func() {
|
|
args := []string{"list", "--config", "imagetest", "-f", "random"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldNotBeNil)
|
|
So(buff.String(), ShouldContainSubstring, "invalid cli output format")
|
|
})
|
|
})
|
|
|
|
Convey("Test all images verbose", func() {
|
|
args := []string{"list", "--config", "imagetest", "--verbose"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
|
// repo7 test:2.0 linux/amd64 51e18f50 d14faead false 528B
|
|
// b8781e88 15B
|
|
// repo7 test:1.0 linux/amd64 51e18f50 d14faead false 528B
|
|
// b8781e88 15B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 d14faead false 528B b8781e88 15B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 d14faead false 528B b8781e88 15B")
|
|
})
|
|
|
|
Convey("Test all images with debug flag", func() {
|
|
args := []string{"list", "--config", "imagetest", "--debug"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
actual := strings.TrimSpace(str)
|
|
So(actual, ShouldContainSubstring, "GET")
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
})
|
|
|
|
Convey("Test image by name config url", func() {
|
|
args := []string{"name", "repo7", "--config", "imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
actual := strings.TrimSpace(str)
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
|
|
Convey("invalid output format", func() {
|
|
args := []string{"name", "repo7", "--config", "imagetest", "-f", "random"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldNotBeNil)
|
|
So(buff.String(), ShouldContainSubstring, "invalid cli output format")
|
|
})
|
|
})
|
|
|
|
Convey("Test image by digest", func() {
|
|
args := []string{"digest", "51e18f50", "--config", "imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST SIZE
|
|
// repo7 test:2.0 a0ca253b 15B
|
|
// repo7 test:1.0 a0ca253b 15B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
|
|
Convey("nonexistent digest", func() {
|
|
args := []string{"digest", "d1g35t", "--config", "imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
So(len(buff.String()), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("invalid output format", func() {
|
|
args := []string{"digest", "51e18f50", "--config", "imagetest", "-f", "random"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldNotBeNil)
|
|
So(buff.String(), ShouldContainSubstring, "invalid cli output format")
|
|
})
|
|
})
|
|
|
|
Convey("Test image by name nonexistent name", func() {
|
|
args := []string{"name", "repo777", "--config", "imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewImageCommand(client.NewSearchService())
|
|
buff := bytes.NewBufferString("")
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err := cmd.Execute()
|
|
So(err, ShouldBeNil)
|
|
So(len(buff.String()), ShouldEqual, 0)
|
|
})
|
|
|
|
Convey("Test list repos error", func() {
|
|
args := []string{"list", "--config", "config-test"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"config-test",
|
|
"url":"%s","showspinner":false}]}`, url))
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := client.NewRepoCommand(client.NewSearchService())
|
|
buff := &bytes.Buffer{}
|
|
cmd.SetOut(buff)
|
|
cmd.SetErr(buff)
|
|
cmd.SetArgs(args)
|
|
err = cmd.Execute()
|
|
space := regexp.MustCompile(`\s+`)
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
|
|
So(actual, ShouldContainSubstring, "REPOSITORY NAME")
|
|
So(actual, ShouldContainSubstring, "repo7")
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestServerResponse(t *testing.T) {
|
|
port := test.GetFreePort()
|
|
url := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
defer cm.StopServer()
|
|
|
|
err := uploadManifest(url)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
Convey("Test from real server", t, func() {
|
|
searchConfig := getTestSearchConfig(url, client.NewSearchService())
|
|
|
|
Convey("Test all images", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
})
|
|
|
|
Convey("Test all images verbose", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
searchConfig.Verbose = true
|
|
|
|
defer func() { searchConfig.Verbose = false }()
|
|
|
|
err := client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
|
// repo7 test:2.0 linux/amd64 51e18f50 d14faead false 528B
|
|
// b8781e88 15B
|
|
// repo7 test:1.0 linux/amd64 51e18f50 d14faead false 528B
|
|
// b8781e88 15B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 d14faead false 528B b8781e88 15B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 d14faead false 528B b8781e88 15B")
|
|
})
|
|
|
|
Convey("Test image by name", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchImageByName(searchConfig, "repo7")
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
})
|
|
|
|
Convey("Test image by digest", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchImagesByDigest(searchConfig, "51e18f50")
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST SIZE
|
|
// repo7 test:2.0 linux/amd64 51e18f50 528B
|
|
// repo7 test:1.0 linux/amd64 51e18f50 528B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B")
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B")
|
|
|
|
Convey("nonexistent digest", func() {
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchImagesByDigest(searchConfig, "d1g35t")
|
|
So(err, ShouldBeNil)
|
|
|
|
So(len(buff.String()), ShouldEqual, 0)
|
|
})
|
|
})
|
|
|
|
Convey("Test image by name nonexistent name", func() {
|
|
err := client.SearchImageByName(searchConfig, "repo777")
|
|
So(err, ShouldNotBeNil)
|
|
|
|
So(err.Error(), ShouldContainSubstring, "no repository found")
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestServerResponseGQLWithoutPermissions(t *testing.T) {
|
|
Convey("Test accessing a blobs folder without having permissions fails fast", t, func() {
|
|
port := test.GetFreePort()
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
|
|
dir := t.TempDir()
|
|
|
|
srcStorageCtlr := ociutils.GetDefaultStoreController(dir, zlog.NewLogger("debug", ""))
|
|
err := WriteImageToFileSystem(CreateDefaultImage(), "zot-test", "0.0.1", srcStorageCtlr)
|
|
So(err, ShouldBeNil)
|
|
|
|
err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o000)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
defer func() {
|
|
err = os.Chmod(path.Join(dir, "zot-test", "blobs"), 0o777)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}()
|
|
|
|
conf.Storage.RootDirectory = dir
|
|
defaultVal := true
|
|
searchConfig := &extconf.SearchConfig{
|
|
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
|
|
}
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: searchConfig,
|
|
}
|
|
|
|
ctlr := api.NewController(conf)
|
|
if err := ctlr.Init(); err != nil {
|
|
So(err, ShouldNotBeNil)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestDisplayIndex(t *testing.T) {
|
|
Convey("Init Basic Server, No GQL", t, func() {
|
|
port := test.GetFreePort()
|
|
baseURL := test.GetBaseURL(port)
|
|
conf := config.New()
|
|
conf.HTTP.Port = port
|
|
|
|
Convey("No GQL", func() {
|
|
defaultVal := false
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
defer cm.StopServer()
|
|
|
|
runDisplayIndexTests(baseURL)
|
|
})
|
|
|
|
Convey("With GQL", func() {
|
|
defaultVal := true
|
|
conf.Extensions = &extconf.ExtensionConfig{
|
|
Search: &extconf.SearchConfig{BaseConfig: extconf.BaseConfig{Enable: &defaultVal}},
|
|
}
|
|
ctlr := api.NewController(conf)
|
|
ctlr.Config.Storage.RootDirectory = t.TempDir()
|
|
cm := test.NewControllerManager(ctlr)
|
|
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
defer cm.StopServer()
|
|
|
|
runDisplayIndexTests(baseURL)
|
|
})
|
|
})
|
|
}
|
|
|
|
func runDisplayIndexTests(baseURL string) {
|
|
space := regexp.MustCompile(`\s+`)
|
|
searchConfig := getTestSearchConfig(baseURL, client.NewSearchService())
|
|
|
|
Convey("Test Image Index", func() {
|
|
uploadTestMultiarch(baseURL)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
err := client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE
|
|
// repo multi-arch * 4780eafe false 1.5kB
|
|
// linux/amd64 02e0ac42 false 644B
|
|
// windows/arm64/v6 5e09b7f9 false 444B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE")
|
|
So(actual, ShouldContainSubstring, "repo multi-arch * 4780eafe false 1.5kB ")
|
|
So(actual, ShouldContainSubstring, "linux/amd64 02e0ac42 false 644B ")
|
|
So(actual, ShouldContainSubstring, "windows/arm64/v6 5e09b7f9 false 506B")
|
|
})
|
|
|
|
Convey("Test Image Index Verbose", func() {
|
|
uploadTestMultiarch(baseURL)
|
|
|
|
buff := &bytes.Buffer{}
|
|
searchConfig.ResultWriter = buff
|
|
searchConfig.Verbose = true
|
|
err := client.SearchAllImages(searchConfig)
|
|
So(err, ShouldBeNil)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
actual := strings.TrimSpace(str)
|
|
// Actual cli output should be something similar to (order of images may differ):
|
|
// REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE
|
|
// repo multi-arch * 4780eafe false 1.5kB
|
|
// linux/amd64 02e0ac42 58cc9abe false 644B
|
|
// cbb5b121 4B
|
|
// a00291e8 4B
|
|
// windows/arm64/v6 5e09b7f9 5132a1cd false 506B
|
|
// 7d08ce29 4B
|
|
So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST CONFIG SIGNED LAYERS SIZE")
|
|
So(actual, ShouldContainSubstring, "repo multi-arch * 4780eafe false 1.5kB")
|
|
So(actual, ShouldContainSubstring, "linux/amd64 02e0ac42 58cc9abe false 644B")
|
|
So(actual, ShouldContainSubstring, "cbb5b121 4B")
|
|
So(actual, ShouldContainSubstring, "a00291e8 4B")
|
|
So(actual, ShouldContainSubstring, "windows/arm64/v6 5e09b7f9 5132a1cd false 506B")
|
|
So(actual, ShouldContainSubstring, "7d08ce29 4B")
|
|
})
|
|
}
|
|
|
|
func TestImagesSortFlag(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, "a-repo", "tag1", storeController)
|
|
if err != nil {
|
|
t.FailNow()
|
|
}
|
|
|
|
err = WriteImageToFileSystem(image2, "b-repo", "tag2", storeController)
|
|
if err != nil {
|
|
t.FailNow()
|
|
}
|
|
|
|
cm := test.NewControllerManager(ctlr)
|
|
cm.StartAndWait(conf.HTTP.Port)
|
|
|
|
defer cm.StopServer()
|
|
|
|
Convey("Sorting", t, func() {
|
|
args := []string{"list", "--sort-by", "alpha-asc", "--url", baseURL}
|
|
cmd := client.NewImageCommand(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-repo"), ShouldBeLessThan, strings.Index(str, "b-repo"))
|
|
|
|
args = []string{"list", "--sort-by", "alpha-dsc", "--url", baseURL}
|
|
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-repo"))
|
|
|
|
args = []string{"list", "--sort-by", "update-time", "--url", baseURL}
|
|
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-repo"))
|
|
})
|
|
}
|
|
|
|
func uploadTestMultiarch(baseURL string) {
|
|
// ------- Define Image1
|
|
layer11 := []byte{11, 12, 13, 14}
|
|
layer12 := []byte{16, 17, 18, 19}
|
|
|
|
image1 := CreateImageWith().
|
|
LayerBlobs([][]byte{
|
|
layer11,
|
|
layer12,
|
|
}).
|
|
ImageConfig(
|
|
ispec.Image{
|
|
Platform: ispec.Platform{OS: "linux", Architecture: "amd64"},
|
|
},
|
|
).Build()
|
|
|
|
// ------ Define Image2
|
|
layer21 := []byte{21, 22, 23, 24}
|
|
|
|
image2 := CreateImageWith().
|
|
LayerBlobs([][]byte{
|
|
layer21,
|
|
}).
|
|
ImageConfig(
|
|
ispec.Image{
|
|
Platform: ispec.Platform{OS: "windows", Architecture: "arm64", Variant: "v6"},
|
|
},
|
|
).Build()
|
|
|
|
// ------- Upload The multiarch image
|
|
|
|
multiarch := CreateMultiarchWith().Images([]Image{image1, image2}).Build()
|
|
|
|
err := UploadMultiarchImage(multiarch, baseURL, "repo", "multi-arch")
|
|
So(err, ShouldBeNil)
|
|
}
|
|
|
|
func uploadManifest(url string) error {
|
|
// create and upload a blob/layer
|
|
resp, _ := resty.R().Post(url + "/v2/repo7/blobs/uploads/")
|
|
loc := test.Location(url, resp)
|
|
|
|
content := []byte("this is a blob5")
|
|
digest := godigest.FromBytes(content)
|
|
_, _ = resty.R().SetQueryParam("digest", digest.String()).
|
|
SetHeader("Content-Type", "application/octet-stream").SetBody(content).Put(loc)
|
|
|
|
// create config
|
|
createdTime := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
config := ispec.Image{
|
|
Created: &createdTime,
|
|
Platform: ispec.Platform{
|
|
Architecture: "amd64",
|
|
OS: "linux",
|
|
},
|
|
RootFS: ispec.RootFS{
|
|
Type: "layers",
|
|
DiffIDs: []godigest.Digest{},
|
|
},
|
|
Author: "some author",
|
|
}
|
|
|
|
cblob, err := json.MarshalIndent(&config, "", "\t")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cdigest := godigest.FromBytes(cblob)
|
|
|
|
// upload image config blob
|
|
resp, _ = resty.R().Post(url + "/v2/repo7/blobs/uploads/")
|
|
loc = test.Location(url, resp)
|
|
|
|
_, _ = resty.R().
|
|
SetContentLength(true).
|
|
SetHeader("Content-Length", strconv.Itoa(len(cblob))).
|
|
SetHeader("Content-Type", "application/octet-stream").
|
|
SetQueryParam("digest", cdigest.String()).
|
|
SetBody(cblob).
|
|
Put(loc)
|
|
|
|
// create a manifest
|
|
manifest := ispec.Manifest{
|
|
Config: ispec.Descriptor{
|
|
MediaType: "application/vnd.oci.image.config.v1+json",
|
|
Digest: cdigest,
|
|
Size: int64(len(cblob)),
|
|
},
|
|
Layers: []ispec.Descriptor{
|
|
{
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest,
|
|
Size: int64(len(content)),
|
|
},
|
|
},
|
|
}
|
|
manifest.SchemaVersion = 2
|
|
|
|
content, err = json.Marshal(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, _ = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
|
|
SetBody(content).Put(url + "/v2/repo7/manifests/test:1.0")
|
|
|
|
content = []byte("this is a blob5")
|
|
digest = godigest.FromBytes(content)
|
|
// create a manifest with same blob but a different tag
|
|
manifest = ispec.Manifest{
|
|
Config: ispec.Descriptor{
|
|
MediaType: "application/vnd.oci.image.config.v1+json",
|
|
Digest: cdigest,
|
|
Size: int64(len(cblob)),
|
|
},
|
|
Layers: []ispec.Descriptor{
|
|
{
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest,
|
|
Size: int64(len(content)),
|
|
},
|
|
},
|
|
}
|
|
manifest.SchemaVersion = 2
|
|
|
|
content, err = json.Marshal(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
|
|
SetBody(content).Put(url + "/v2/repo7/manifests/test:2.0")
|
|
|
|
return nil
|
|
}
|
|
|
|
func uploadManifestDerivedBase(url string) error {
|
|
// create a blob/layer
|
|
_, _ = resty.R().Post(url + "/v2/repo7/blobs/uploads/")
|
|
|
|
content1 := []byte("this is a blob5.0")
|
|
content2 := []byte("this is a blob5.1")
|
|
content3 := []byte("this is a blob5.2")
|
|
digest1 := godigest.FromBytes(content1)
|
|
digest2 := godigest.FromBytes(content2)
|
|
digest3 := godigest.FromBytes(content3)
|
|
_, _ = resty.R().SetQueryParam("digest", digest1.String()).
|
|
SetHeader("Content-Type", "application/octet-stream").SetBody(content1).Post(url + "/v2/repo7/blobs/uploads/")
|
|
_, _ = resty.R().SetQueryParam("digest", digest2.String()).
|
|
SetHeader("Content-Type", "application/octet-stream").SetBody(content2).Post(url + "/v2/repo7/blobs/uploads/")
|
|
_, _ = resty.R().SetQueryParam("digest", digest3.String()).
|
|
SetHeader("Content-Type", "application/octet-stream").SetBody(content3).Post(url + "/v2/repo7/blobs/uploads/")
|
|
|
|
// create config
|
|
createdTime := time.Date(2023, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
config := ispec.Image{
|
|
Created: &createdTime,
|
|
Platform: ispec.Platform{
|
|
Architecture: "amd64",
|
|
OS: "linux",
|
|
},
|
|
RootFS: ispec.RootFS{
|
|
Type: "layers",
|
|
DiffIDs: []godigest.Digest{},
|
|
},
|
|
Author: "some author",
|
|
}
|
|
|
|
cblob, err := json.MarshalIndent(&config, "", "\t")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cdigest := godigest.FromBytes(cblob)
|
|
|
|
// upload image config blob
|
|
resp, _ := resty.R().Post(url + "/v2/repo7/blobs/uploads/")
|
|
loc := test.Location(url, resp)
|
|
|
|
_, _ = resty.R().
|
|
SetContentLength(true).
|
|
SetHeader("Content-Length", strconv.Itoa(len(cblob))).
|
|
SetHeader("Content-Type", "application/octet-stream").
|
|
SetQueryParam("digest", cdigest.String()).
|
|
SetBody(cblob).
|
|
Put(loc)
|
|
|
|
// create a manifest
|
|
manifest := ispec.Manifest{
|
|
Config: ispec.Descriptor{
|
|
MediaType: "application/vnd.oci.image.config.v1+json",
|
|
Digest: cdigest,
|
|
Size: int64(len(cblob)),
|
|
},
|
|
Layers: []ispec.Descriptor{
|
|
{
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest1,
|
|
Size: int64(len(content1)),
|
|
}, {
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest2,
|
|
Size: int64(len(content2)),
|
|
}, {
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest3,
|
|
Size: int64(len(content3)),
|
|
},
|
|
},
|
|
}
|
|
manifest.SchemaVersion = 2
|
|
|
|
content, err := json.Marshal(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, _ = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
|
|
SetBody(content).Put(url + "/v2/repo7/manifests/test:1.0")
|
|
|
|
content1 = []byte("this is a blob5.0")
|
|
digest1 = godigest.FromBytes(content1)
|
|
// create a manifest with one common layer blob
|
|
manifest = ispec.Manifest{
|
|
Config: ispec.Descriptor{
|
|
MediaType: "application/vnd.oci.image.config.v1+json",
|
|
Digest: cdigest,
|
|
Size: int64(len(cblob)),
|
|
},
|
|
Layers: []ispec.Descriptor{
|
|
{
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
Digest: digest1,
|
|
Size: int64(len(content1)),
|
|
},
|
|
},
|
|
}
|
|
manifest.SchemaVersion = 2
|
|
|
|
content, err = json.Marshal(manifest)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, _ = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
|
|
SetBody(content).Put(url + "/v2/repo7/manifests/test:2.0")
|
|
|
|
return nil
|
|
}
|
|
|
|
func getTestSearchConfig(url string, searchService client.SearchService) client.SearchConfig {
|
|
var (
|
|
user string
|
|
outputFormat string
|
|
verbose bool
|
|
debug bool
|
|
verifyTLS bool
|
|
)
|
|
|
|
return client.SearchConfig{
|
|
SearchService: searchService,
|
|
SortBy: "alpha-asc",
|
|
ServURL: url,
|
|
User: user,
|
|
OutputFormat: outputFormat,
|
|
Verbose: verbose,
|
|
Debug: debug,
|
|
VerifyTLS: verifyTLS,
|
|
ResultWriter: nil,
|
|
}
|
|
}
|