0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2024-12-16 21:56:37 -05:00
zot/pkg/cli/client/search_cmd_internal_test.go
Andrei Aaron ba6f347d8d
refactor(pkg/test): split logic in pkg/test/common.go into multiple packages (#1861)
Which could be imported independently. See more details:
1. "zotregistry.io/zot/pkg/test/common" - currently used as
   tcommon "zotregistry.io/zot/pkg/test/common" - inside pkg/test
   test "zotregistry.io/zot/pkg/test/common" - in tests
   . "zotregistry.io/zot/pkg/test/common" - in tests
Decouple zb from code in test/pkg in order to keep the size small.

2. "zotregistry.io/zot/pkg/test/image-utils" - curently used as
   . "zotregistry.io/zot/pkg/test/image-utils"

3. "zotregistry.io/zot/pkg/test/deprecated" -  curently used as
   "zotregistry.io/zot/pkg/test/deprecated"
This one will bre replaced gradually by image-utils in the future.

4. "zotregistry.io/zot/pkg/test/signature" - (cosign + notation) use as
   "zotregistry.io/zot/pkg/test/signature"

5. "zotregistry.io/zot/pkg/test/auth" - (bearer + oidc)  curently used as
   authutils "zotregistry.io/zot/pkg/test/auth"

 6. "zotregistry.io/zot/pkg/test/oci-utils" -  curently used as
   ociutils "zotregistry.io/zot/pkg/test/oci-utils"

Some unused functions were removed, some were replaced, and in
a few cases specific funtions were moved to the files they were used in.

Added an interface for the StoreController, this reduces the number of imports
of the entire image store, decreasing binary size for tests.
If the zb code was still coupled with pkg/test, this would have reflected in zb size.

Signed-off-by: Andrei Aaron <aaaron@luxoft.com>
2023-09-27 11:34:48 -07:00

934 lines
26 KiB
Go

//go:build search
// +build search
package client
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"
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)
conf := config.New()
conf.HTTP.Port = port
defaultVal := true
conf.Extensions = &extconf.ExtensionConfig{
Search: &extconf.SearchConfig{
BaseConfig: extconf.BaseConfig{Enable: &defaultVal},
},
}
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("commands without gql", t, func() {
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
Convey("query", func() {
args := []string{"query", "repo/al", "--config", "searchtest"}
cmd := NewSearchCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring, "repo 8c25cb36 false 100B")
So(actual, ShouldContainSubstring, "repo 100B 2010-01-01 01:01:01 +0000 UTC 0 0")
})
Convey("query command errors", func() {
// no url
args := []string{"repo/al", "--config", "searchtest"}
cmd := NewSearchQueryCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("subject", func() {
err := UploadImage(CreateRandomImage(), baseURL, "repo", "tag")
So(err, ShouldBeNil)
args := []string{"subject", "repo:tag", "--config", "searchtest"}
cmd := NewSearchCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring, "ArtifactType 100 B Digest")
})
Convey("subject command errors", func() {
// no url
args := []string{"repo:tag", "--config", "searchtest"}
cmd := NewSearchSubjectCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
})
}
func TestSearchCommandREST(t *testing.T) {
port := test.GetFreePort()
baseURL := test.GetBaseURL(port)
conf := config.New()
conf.HTTP.Port = port
ctlr := api.NewController(conf)
ctlr.Config.Storage.RootDirectory = t.TempDir()
cm := test.NewControllerManager(ctlr)
cm.StartAndWait(conf.HTTP.Port)
defer cm.StopServer()
Convey("commands without gql", t, func() {
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"searchtest","url":"%s","showspinner":false}]}`,
baseURL))
defer os.Remove(configPath)
Convey("query", func() {
args := []string{"query", "repo/al", "--config", "searchtest"}
cmd := NewSearchCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err := cmd.Execute()
So(err, ShouldNotBeNil)
})
Convey("subject", func() {
err := UploadImage(CreateRandomImage(), baseURL, "repo", "tag")
So(err, ShouldBeNil)
args := []string{"subject", "repo:tag", "--config", "searchtest"}
cmd := NewSearchCommand(mockService{})
buff := bytes.NewBufferString("")
cmd.SetOut(buff)
cmd.SetErr(buff)
cmd.SetArgs(args)
err = cmd.Execute()
So(err, ShouldBeNil)
space := regexp.MustCompile(`\s+`)
str := space.ReplaceAllString(buff.String(), " ")
actual := strings.TrimSpace(str)
So(actual, ShouldContainSubstring,
"art.type 100 B sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a")
})
})
}
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"))
})
}