2020-10-14 16:47:20 -05:00
|
|
|
// +build extended
|
|
|
|
|
2020-06-16 20:52:40 -05:00
|
|
|
package cli //nolint:testpackage
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
2020-07-14 12:11:01 -05:00
|
|
|
"path"
|
2020-06-16 20:52:40 -05:00
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"gopkg.in/resty.v1"
|
|
|
|
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
zotErrors "github.com/anuvu/zot/errors"
|
|
|
|
"github.com/anuvu/zot/pkg/api"
|
|
|
|
"github.com/anuvu/zot/pkg/compliance/v1_0_0"
|
2021-05-26 12:22:31 -05:00
|
|
|
"github.com/anuvu/zot/pkg/extensions"
|
2020-06-16 20:52:40 -05:00
|
|
|
godigest "github.com/opencontainers/go-digest"
|
|
|
|
ispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestSearchImageCmd(t *testing.T) {
|
|
|
|
Convey("Test image help", t, func() {
|
|
|
|
args := []string{"--help"}
|
|
|
|
configPath := makeConfigFile("")
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(buff.String(), ShouldContainSubstring, "Usage")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
Convey("with the shorthand", func() {
|
|
|
|
args[0] = "-h"
|
|
|
|
configPath := makeConfigFile("")
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(buff.String(), ShouldContainSubstring, "Usage")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
Convey("Test image no url", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyIdRandom"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
2020-07-06 17:44:32 -05:00
|
|
|
So(err, ShouldEqual, zotErrors.ErrNoURLProvided)
|
2020-06-16 20:52:40 -05:00
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test image no params", t, func() {
|
|
|
|
args := []string{"imagetest", "--url", "someUrl"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test image invalid url", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "--url", "invalidUrl"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
So(err, ShouldEqual, zotErrors.ErrInvalidURL)
|
|
|
|
So(buff.String(), ShouldContainSubstring, "invalid URL format")
|
|
|
|
})
|
|
|
|
Convey("Test image invalid url port", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "--url", "http://localhost:99999"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
So(buff.String(), ShouldContainSubstring, "invalid port")
|
|
|
|
|
|
|
|
Convey("without flags", func() {
|
|
|
|
args := []string{"imagetest", "--url", "http://localhost:99999"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err = cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
So(buff.String(), ShouldContainSubstring, "invalid port")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
Convey("Test image unreachable", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "--url", "http://localhost:9999"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test image url from config", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST SIZE dummyImageName tag DigestsA 123kB")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test image by name", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "--url", "someUrlImage"}
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
imageCmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
imageCmd.SetOut(buff)
|
|
|
|
imageCmd.SetErr(ioutil.Discard)
|
|
|
|
imageCmd.SetArgs(args)
|
|
|
|
err := imageCmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST SIZE dummyImageName tag DigestsA 123kB")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
Convey("using shorthand", func() {
|
|
|
|
args := []string{"imagetest", "-n", "dummyImageName", "--url", "someUrlImage"}
|
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
imageCmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
imageCmd.SetOut(buff)
|
|
|
|
imageCmd.SetErr(ioutil.Discard)
|
|
|
|
imageCmd.SetArgs(args)
|
|
|
|
err := imageCmd.Execute()
|
|
|
|
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST SIZE dummyImageName tag DigestsA 123kB")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOutputFormat(t *testing.T) {
|
|
|
|
Convey("Test text", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "-o", "text"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, "IMAGE NAME TAG DIGEST SIZE dummyImageName tag DigestsA 123kB")
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test json", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "-o", "json"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, `{ "name": "dummyImageName", "tags": [ { "name":`+
|
2021-05-28 11:27:17 -05:00
|
|
|
` "tag", "size": 123445, "digest": "DigestsAreReallyLong", "configDigest": "", "layerDigests": null } ] }`)
|
2020-06-16 20:52:40 -05:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test yaml", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "-o", "yaml"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
So(strings.TrimSpace(str), ShouldEqual, `name: dummyImageName tags: -`+
|
2021-05-28 11:27:17 -05:00
|
|
|
` name: tag size: 123445 digest: DigestsAreReallyLong configdigest: "" layers: []`)
|
2020-06-16 20:52:40 -05:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
|
|
|
|
Convey("Test yml", func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "-o", "yml"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(ioutil.Discard)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
2021-05-28 11:27:17 -05:00
|
|
|
So(strings.TrimSpace(str), ShouldEqual, `name: dummyImageName tags: -`+
|
|
|
|
` name: tag size: 123445 digest: DigestsAreReallyLong configdigest: "" layers: []`)
|
2020-06-16 20:52:40 -05:00
|
|
|
So(err, ShouldBeNil)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
Convey("Test invalid", t, func() {
|
|
|
|
args := []string{"imagetest", "--name", "dummyImageName", "-o", "random"}
|
|
|
|
|
|
|
|
configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`)
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(mockService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err := cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
So(buff.String(), ShouldContainSubstring, "invalid output format")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestServerResponse(t *testing.T) {
|
|
|
|
Convey("Test from real server", t, func() {
|
|
|
|
port := "8080"
|
|
|
|
url := "http://127.0.0.1:8080"
|
|
|
|
config := api.NewConfig()
|
|
|
|
config.HTTP.Port = port
|
2021-05-26 12:22:31 -05:00
|
|
|
config.Extensions = &extensions.ExtensionConfig{
|
|
|
|
Search: &extensions.SearchConfig{},
|
|
|
|
}
|
2020-06-16 20:52:40 -05:00
|
|
|
c := api.NewController(config)
|
|
|
|
dir, err := ioutil.TempDir("", "oci-repo-test")
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(dir)
|
|
|
|
|
|
|
|
c.Config.Storage.RootDirectory = dir
|
|
|
|
go func(controller *api.Controller) {
|
|
|
|
// this blocks
|
|
|
|
if err := controller.Run(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}(c)
|
|
|
|
// wait till ready
|
|
|
|
for {
|
|
|
|
_, err := resty.R().Get(url)
|
|
|
|
if err == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
}
|
|
|
|
defer func(controller *api.Controller) {
|
|
|
|
ctx := context.Background()
|
|
|
|
_ = controller.Server.Shutdown(ctx)
|
|
|
|
}(c)
|
|
|
|
|
|
|
|
uploadManifest(url)
|
|
|
|
|
|
|
|
Convey("Test all images config url", func() {
|
|
|
|
args := []string{"imagetest"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
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, "IMAGE NAME TAG DIGEST SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b 15B")
|
|
|
|
})
|
|
|
|
|
2021-05-28 11:27:17 -05:00
|
|
|
Convey("Test all images verbose", func() {
|
|
|
|
args := []string{"imagetest", "--verbose"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := NewImageCommand(new(searchService))
|
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err = cmd.Execute()
|
|
|
|
So(err, 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):
|
|
|
|
// IMAGE NAME TAG DIGEST CONFIG LAYERS SIZE
|
|
|
|
// repo7 test:2.0 a0ca253b b8781e88 15B
|
|
|
|
// b8781e88 15B
|
|
|
|
// repo7 test:1.0 a0ca253b b8781e88 15B
|
|
|
|
// b8781e88 15B
|
|
|
|
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST CONFIG LAYERS SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b b8781e88 15B b8781e88 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b b8781e88 15B b8781e88 15B")
|
|
|
|
})
|
|
|
|
|
2020-06-16 20:52:40 -05:00
|
|
|
Convey("Test image by name config url", func() {
|
|
|
|
args := []string{"imagetest", "--name", "repo7"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
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, "IMAGE NAME TAG DIGEST SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b 15B")
|
|
|
|
|
|
|
|
Convey("with shorthand", func() {
|
|
|
|
args := []string{"imagetest", "-n", "repo7"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
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, "IMAGE NAME TAG DIGEST SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b 15B")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
Convey("Test image by digest", func() {
|
|
|
|
args := []string{"imagetest", "--digest", "a0ca253b"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := NewImageCommand(new(searchService))
|
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err = cmd.Execute()
|
|
|
|
So(err, 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):
|
|
|
|
// IMAGE NAME TAG DIGEST SIZE
|
|
|
|
// repo7 test:2.0 a0ca253b 15B
|
|
|
|
// repo7 test:1.0 a0ca253b 15B
|
|
|
|
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b 15B")
|
|
|
|
Convey("with shorthand", func() {
|
|
|
|
args := []string{"imagetest", "-d", "a0ca253b"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
|
|
|
cmd := NewImageCommand(new(searchService))
|
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err = cmd.Execute()
|
|
|
|
So(err, ShouldBeNil)
|
|
|
|
space := regexp.MustCompile(`\s+`)
|
|
|
|
str := space.ReplaceAllString(buff.String(), " ")
|
|
|
|
actual := strings.TrimSpace(str)
|
|
|
|
So(actual, ShouldContainSubstring, "IMAGE NAME TAG DIGEST SIZE")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:2.0 a0ca253b 15B")
|
|
|
|
So(actual, ShouldContainSubstring, "repo7 test:1.0 a0ca253b 15B")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-06-16 20:52:40 -05:00
|
|
|
Convey("Test image by name invalid name", func() {
|
|
|
|
args := []string{"imagetest", "--name", "repo777"}
|
|
|
|
configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url))
|
|
|
|
defer os.Remove(configPath)
|
2020-07-14 12:11:01 -05:00
|
|
|
cmd := NewImageCommand(new(searchService))
|
2020-06-16 20:52:40 -05:00
|
|
|
buff := bytes.NewBufferString("")
|
|
|
|
cmd.SetOut(buff)
|
|
|
|
cmd.SetErr(buff)
|
|
|
|
cmd.SetArgs(args)
|
|
|
|
err = cmd.Execute()
|
|
|
|
So(err, ShouldNotBeNil)
|
|
|
|
actual := buff.String()
|
|
|
|
So(actual, ShouldContainSubstring, "unknown")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func uploadManifest(url string) {
|
|
|
|
// create a blob/layer
|
|
|
|
resp, _ := resty.R().Post(url + "/v2/repo7/blobs/uploads/")
|
|
|
|
loc := v1_0_0.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 a manifest
|
|
|
|
m := ispec.Manifest{
|
|
|
|
Config: ispec.Descriptor{
|
|
|
|
Digest: digest,
|
|
|
|
Size: int64(len(content)),
|
|
|
|
},
|
|
|
|
Layers: []ispec.Descriptor{
|
|
|
|
{
|
|
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
|
|
Digest: digest,
|
|
|
|
Size: int64(len(content)),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
m.SchemaVersion = 2
|
|
|
|
content, _ = json.Marshal(m)
|
|
|
|
_, _ = 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
|
|
|
|
m = ispec.Manifest{
|
|
|
|
Config: ispec.Descriptor{
|
|
|
|
Digest: digest,
|
|
|
|
Size: int64(len(content)),
|
|
|
|
},
|
|
|
|
Layers: []ispec.Descriptor{
|
|
|
|
{
|
|
|
|
MediaType: "application/vnd.oci.image.layer.v1.tar",
|
|
|
|
Digest: digest,
|
|
|
|
Size: int64(len(content)),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
m.SchemaVersion = 2
|
|
|
|
content, _ = json.Marshal(m)
|
|
|
|
_, _ = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json").
|
|
|
|
SetBody(content).Put(url + "/v2/repo7/manifests/test:2.0")
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockService struct{}
|
|
|
|
|
2020-07-17 14:42:22 -05:00
|
|
|
func (service mockService) getAllImages(ctx context.Context, config searchConfig, username, password string,
|
2020-07-06 17:44:32 -05:00
|
|
|
channel chan stringResult, wg *sync.WaitGroup) {
|
2020-06-16 20:52:40 -05:00
|
|
|
defer wg.Done()
|
2020-07-06 17:44:32 -05:00
|
|
|
defer close(channel)
|
2020-06-16 20:52:40 -05:00
|
|
|
|
|
|
|
image := &imageStruct{}
|
|
|
|
image.Name = "randomimageName"
|
|
|
|
image.Tags = []tags{
|
|
|
|
{
|
|
|
|
Name: "tag",
|
|
|
|
Digest: "DigestsAreReallyLong",
|
|
|
|
Size: 123445,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-07-17 14:42:22 -05:00
|
|
|
str, err := image.string(*config.outputFormat)
|
2020-06-16 20:52:40 -05:00
|
|
|
if err != nil {
|
2020-07-06 17:44:32 -05:00
|
|
|
channel <- stringResult{"", err}
|
2020-06-16 20:52:40 -05:00
|
|
|
return
|
|
|
|
}
|
2020-07-06 17:44:32 -05:00
|
|
|
channel <- stringResult{str, nil}
|
2020-06-16 20:52:40 -05:00
|
|
|
}
|
|
|
|
|
2020-07-17 14:42:22 -05:00
|
|
|
func (service mockService) getImageByName(ctx context.Context, config searchConfig,
|
2020-07-06 17:44:32 -05:00
|
|
|
username, password, imageName string, channel chan stringResult, wg *sync.WaitGroup) {
|
2020-06-16 20:52:40 -05:00
|
|
|
defer wg.Done()
|
2020-07-06 17:44:32 -05:00
|
|
|
defer close(channel)
|
2020-06-16 20:52:40 -05:00
|
|
|
|
|
|
|
image := &imageStruct{}
|
|
|
|
image.Name = imageName
|
|
|
|
image.Tags = []tags{
|
|
|
|
{
|
|
|
|
Name: "tag",
|
|
|
|
Digest: "DigestsAreReallyLong",
|
|
|
|
Size: 123445,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2020-07-17 14:42:22 -05:00
|
|
|
str, err := image.string(*config.outputFormat)
|
2020-06-16 20:52:40 -05:00
|
|
|
if err != nil {
|
2020-07-06 17:44:32 -05:00
|
|
|
channel <- stringResult{"", err}
|
2020-06-16 20:52:40 -05:00
|
|
|
return
|
|
|
|
}
|
2020-07-06 17:44:32 -05:00
|
|
|
channel <- stringResult{str, nil}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (service mockService) getCveByImage(ctx context.Context, config searchConfig, username, password,
|
|
|
|
imageName string, c chan stringResult, wg *sync.WaitGroup) {
|
|
|
|
defer wg.Done()
|
|
|
|
defer close(c)
|
|
|
|
|
|
|
|
cveRes := &cveResult{}
|
|
|
|
cveRes.Data = cveData{
|
|
|
|
CVEListForImage: cveListForImage{
|
|
|
|
Tag: imageName,
|
|
|
|
CVEList: []cve{
|
|
|
|
{
|
|
|
|
ID: "dummyCVEID",
|
|
|
|
Description: "Description of the CVE",
|
|
|
|
Title: "Title of that CVE",
|
|
|
|
Severity: "HIGH",
|
|
|
|
PackageList: []packageList{
|
|
|
|
{
|
|
|
|
Name: "packagename",
|
|
|
|
FixedVersion: "fixedver",
|
|
|
|
InstalledVersion: "installedver",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
str, err := cveRes.string(*config.outputFormat)
|
|
|
|
if err != nil {
|
|
|
|
c <- stringResult{"", err}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
c <- stringResult{str, nil}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (service mockService) getImagesByCveID(ctx context.Context, config searchConfig, username, password, cveID string,
|
|
|
|
c chan stringResult, wg *sync.WaitGroup) {
|
|
|
|
service.getImageByName(ctx, config, username, password, "anImage", c, wg)
|
|
|
|
}
|
|
|
|
|
2021-05-26 12:22:31 -05:00
|
|
|
func (service mockService) getImagesByDigest(ctx context.Context, config searchConfig, username,
|
|
|
|
password, digest string, c chan stringResult, wg *sync.WaitGroup) {
|
|
|
|
service.getImageByName(ctx, config, username, password, "anImage", c, wg)
|
|
|
|
}
|
|
|
|
|
2020-07-06 17:44:32 -05:00
|
|
|
func (service mockService) getImageByNameAndCVEID(ctx context.Context, config searchConfig, username,
|
|
|
|
password, imageName, cveID string, c chan stringResult, wg *sync.WaitGroup) {
|
|
|
|
service.getImageByName(ctx, config, username, password, imageName, c, wg)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (service mockService) getFixedTagsForCVE(ctx context.Context, config searchConfig,
|
|
|
|
username, password, imageName, cveID string, c chan stringResult, wg *sync.WaitGroup) {
|
|
|
|
service.getImageByName(ctx, config, username, password, imageName, c, wg)
|
2020-06-16 20:52:40 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func makeConfigFile(content string) string {
|
2020-07-14 12:11:01 -05:00
|
|
|
os.Setenv("HOME", os.TempDir())
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
|
2020-06-16 20:52:40 -05:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
configPath := path.Join(home + "/.zot")
|
2020-06-16 20:52:40 -05:00
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
if err := ioutil.WriteFile(configPath, []byte(content), 0600); err != nil {
|
2020-06-16 20:52:40 -05:00
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2020-07-14 12:11:01 -05:00
|
|
|
return configPath
|
2020-06-16 20:52:40 -05:00
|
|
|
}
|